diff --git a/camera/Android.mk b/camera/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..7286f9295660020337fcdee13416ce6d4212f52c --- /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 0000000000000000000000000000000000000000..b81fe86232370543468eec50c778776c0882eccf --- /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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace android { + +// client singleton for camera service binder interface +Mutex Camera::mLock; +sp Camera::mCameraService; +sp Camera::mDeathNotifier; + +// establish binder interface to camera service +const sp& Camera::getCameraService() +{ + Mutex::Autolock _l(mLock); + if (mCameraService.get() == 0) { + sp sm = defaultServiceManager(); + sp 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(binder); + } + ALOGE_IF(mCameraService==0, "no CameraService!?"); + return mCameraService; +} + +// --------------------------------------------------------------------------- + +Camera::Camera() +{ + init(); +} + +// construct a camera client from an existing camera remote +sp Camera::create(const sp& camera) +{ + ALOGV("create"); + if (camera == 0) { + ALOGE("camera remote is a NULL pointer"); + return 0; + } + + sp 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& cs = getCameraService(); + if (cs == 0) return 0; + return cs->getNumberOfCameras(); +} + +status_t Camera::getCameraInfo(int cameraId, + struct CameraInfo* cameraInfo) { + const sp& cs = getCameraService(); + if (cs == 0) return UNKNOWN_ERROR; + return cs->getCameraInfo(cameraId, cameraInfo); +} + +sp Camera::connect(int cameraId, bool force, bool keep) +{ + ALOGV("connect"); + sp c = new Camera(); + const sp& 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 c = mCamera; + if (c == 0) return NO_INIT; + return c->connect(this); +} + +sp Camera::remote() +{ + return mCamera; +} + +status_t Camera::lock() +{ + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->lock(); +} + +status_t Camera::unlock() +{ + sp 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) +{ + ALOGV("setPreviewDisplay(%p)", surface.get()); + sp 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& surfaceTexture) +{ + ALOGV("setPreviewTexture(%p)", surfaceTexture.get()); + sp 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 c = mCamera; + if (c == 0) return NO_INIT; + return c->startPreview(); +} + +status_t Camera::storeMetaDataInBuffers(bool enabled) +{ + ALOGV("storeMetaDataInBuffers: %s", + enabled? "true": "false"); + sp 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 c = mCamera; + if (c == 0) return NO_INIT; + return c->startRecording(); +} + +// stop preview mode +void Camera::stopPreview() +{ + ALOGV("stopPreview"); + sp c = mCamera; + if (c == 0) return; + c->stopPreview(); +} + +// stop recording mode +void Camera::stopRecording() +{ + ALOGV("stopRecording"); + { + Mutex::Autolock _l(mLock); + mRecordingProxyListener.clear(); + } + sp c = mCamera; + if (c == 0) return; + c->stopRecording(); +} + +// release a recording frame +void Camera::releaseRecordingFrame(const sp& mem) +{ + ALOGV("releaseRecordingFrame"); + sp c = mCamera; + if (c == 0) return; + c->releaseRecordingFrame(mem); +} + +// get preview state +bool Camera::previewEnabled() +{ + ALOGV("previewEnabled"); + sp c = mCamera; + if (c == 0) return false; + return c->previewEnabled(); +} + +// get recording state +bool Camera::recordingEnabled() +{ + ALOGV("recordingEnabled"); + sp c = mCamera; + if (c == 0) return false; + return c->recordingEnabled(); +} + +status_t Camera::autoFocus() +{ + ALOGV("autoFocus"); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->autoFocus(); +} + +status_t Camera::cancelAutoFocus() +{ + ALOGV("cancelAutoFocus"); + sp 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 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 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 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 c = mCamera; + if (c == 0) return NO_INIT; + return c->sendCommand(cmd, arg1, arg2); +} + +void Camera::setListener(const sp& listener) +{ + Mutex::Autolock _l(mLock); + mListener = listener; +} + +void Camera::setRecordingProxyListener(const sp& listener) +{ + Mutex::Autolock _l(mLock); + mRecordingProxyListener = listener; +} + +void Camera::setPreviewCallbackFlags(int flag) +{ + ALOGV("setPreviewCallbackFlags"); + sp 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 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& dataPtr, + camera_frame_metadata_t *metadata) +{ + sp 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& 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 proxylistener; + { + Mutex::Autolock _l(mLock); + proxylistener = mRecordingProxyListener; + } + if (proxylistener != NULL) { + proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr); + return; + } + + sp 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& who) { + ALOGW("ICamera died"); + notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); +} + +void Camera::DeathNotifier::binderDied(const wp& who) { + ALOGV("binderDied"); + Mutex::Autolock _l(Camera::mLock); + Camera::mCameraService.clear(); + ALOGW("Camera server died!"); +} + +sp Camera::getRecordingProxy() { + ALOGV("getProxy"); + return new RecordingProxy(this); +} + +status_t Camera::RecordingProxy::startRecording(const sp& 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& mem) +{ + ALOGV("RecordingProxy::releaseRecordingFrame"); + mCamera->releaseRecordingFrame(mem); +} + +Camera::RecordingProxy::RecordingProxy(const sp& camera) +{ + mCamera = camera; +} + +}; // namespace android diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..059a8a5fa5e4f0ef3e19fedc0f5df44be3f99f5a --- /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 + +#include +#include +#include + +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 ¶ms) +{ + 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 &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 &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 &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 &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& 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 0000000000000000000000000000000000000000..8d8408c815d2d1c0ccbc2f73a93fd5f03ac3406e --- /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 +#include +#include +#include +#include +#include +#include + +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 +{ +public: + BpCamera(const sp& impl) + : BpInterface(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) + { + 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& surfaceTexture) + { + ALOGV("setPreviewTexture"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + sp 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& 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& 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::readFromParcel(data); + reply->writeInt32(setPreviewDisplay(surface)); + return NO_ERROR; + } break; + case SET_PREVIEW_TEXTURE: { + ALOGV("SET_PREVIEW_TEXTURE"); + CHECK_INTERFACE(ICamera, data, reply); + sp st = interface_cast(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 mem = interface_cast(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 cameraClient = interface_cast(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 0000000000000000000000000000000000000000..205c8ba1f123df1ffcf8d23442ce58ce6cf544a4 --- /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 +#include +#include +#include + +namespace android { + +enum { + NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, + DATA_CALLBACK, + DATA_CALLBACK_TIMESTAMP, +}; + +class BpCameraClient: public BpInterface +{ +public: + BpCameraClient(const sp& impl) + : BpInterface(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& 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& 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 imageData = interface_cast(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 imageData = interface_cast(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 0000000000000000000000000000000000000000..7223b6d32c3277e23f69c434707d07661dcfeb95 --- /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 +#include +#include +#include +#include +#include + +namespace android { + +enum { + START_RECORDING = IBinder::FIRST_CALL_TRANSACTION, + STOP_RECORDING, + RELEASE_RECORDING_FRAME, +}; + + +class BpCameraRecordingProxy: public BpInterface +{ +public: + BpCameraRecordingProxy(const sp& impl) + : BpInterface(impl) + { + } + + status_t startRecording(const sp& 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& 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 listener = + interface_cast(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 mem = interface_cast(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 0000000000000000000000000000000000000000..cb17f190e48036bc8751e314b8f4d633a0572df3 --- /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 +#include +#include +#include + +namespace android { + +enum { + DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION, +}; + +class BpCameraRecordingProxyListener: public BpInterface +{ +public: + BpCameraRecordingProxyListener(const sp& impl) + : BpInterface(impl) + { + } + + void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& 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 imageData = interface_cast(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 0000000000000000000000000000000000000000..c74298a84bb97e0f1d9dc67a1720399692cef980 --- /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 +#include + +#include +#include +#include + +#include + +namespace android { + +class BpCameraService: public BpInterface +{ +public: + BpCameraService(const sp& impl) + : BpInterface(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 connect(const sp& 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(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 cameraClient = interface_cast(data.readStrongBinder()); + const int cameraId = data.readInt32(); + const int force = data.readInt32(); + const int keep = data.readInt32(); + sp 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 0000000000000000000000000000000000000000..52a92932b35ccbb1401ba07ab09e88304f4103c3 --- /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 0000000000000000000000000000000000000000..0cfeb3edd84e7a0bbc529af9efa3446e39737d8b --- /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 + +#include "SimplePlayer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +SimplePlayer::SimplePlayer() + : mState(UNINITIALIZED), + mDoMoreStuffGeneration(0), + mStartTimeRealUs(-1ll) { +} + +SimplePlayer::~SimplePlayer() { +} + +// static +status_t PostAndAwaitResponse( + const sp &msg, sp *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 msg = new AMessage(kWhatSetDataSource, id()); + msg->setString("path", path); + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::setSurface(const sp &surfaceTexture) { + sp msg = new AMessage(kWhatSetSurface, id()); + + sp surfaceTextureClient; + if (surfaceTexture != NULL) { + surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); + } + + msg->setObject( + "native-window", new NativeWindowWrapper(surfaceTextureClient)); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::prepare() { + sp msg = new AMessage(kWhatPrepare, id()); + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::start() { + sp msg = new AMessage(kWhatStart, id()); + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::stop() { + sp msg = new AMessage(kWhatStop, id()); + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::reset() { + sp msg = new AMessage(kWhatReset, id()); + sp response; + return PostAndAwaitResponse(msg, &response); +} + +void SimplePlayer::onMessageReceived(const sp &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 response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatSetSurface: + { + status_t err; + if (mState != UNPREPARED) { + err = INVALID_OPERATION; + } else { + sp obj; + CHECK(msg->findObject("native-window", &obj)); + + mNativeWindow = static_cast(obj.get()); + + err = OK; + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp 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 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 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 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 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 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 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 &srcBuffer = state->mCSD.itemAt(j); + + size_t index; + err = state->mCodec->dequeueInputBuffer(&index, -1ll); + CHECK_EQ(err, (status_t)OK); + + const sp &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 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 &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 &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 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 &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 0000000000000000000000000000000000000000..2548252304c29a1ae521a011b851ad5496d5bf50 --- /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 +#include +#include + +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 &surfaceTexture); + status_t prepare(); + status_t start(); + status_t stop(); + status_t reset(); + +protected: + virtual ~SimplePlayer(); + + virtual void onMessageReceived(const sp &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 mCodec; + Vector > mCSD; + Vector > mBuffers[2]; + + List mAvailInputBufferIndices; + List mAvailOutputBufferInfos; + + sp mAudioTrack; + uint32_t mNumFramesWritten; + }; + + State mState; + AString mPath; + sp mNativeWindow; + + sp mExtractor; + sp mCodecLooper; + KeyedVector 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 &buffer); + + DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer); +}; + +} // namespace android diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14b43061c1d8d43af1809f7b30cda96f397c197a --- /dev/null +++ b/cmds/stagefright/SineSource.cpp @@ -0,0 +1,102 @@ +#include "SineSource.h" + +#include + +#include +#include +#include +#include + +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 SineSource::getFormat() { + sp 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 0000000000000000000000000000000000000000..76ab669fbfc66ff39a78482b1fe0b1b01b51548d --- /dev/null +++ b/cmds/stagefright/SineSource.h @@ -0,0 +1,39 @@ +#ifndef SINE_SOURCE_H_ + +#define SINE_SOURCE_H_ + +#include + +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 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 0000000000000000000000000000000000000000..a0eb66e2b9bcd504f0d93de5f131e7dcbbcc2378 --- /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 0000000000000000000000000000000000000000..ed7d6cb052011d9581c6b3cdd1afd18917dea304 --- /dev/null +++ b/cmds/stagefright/audioloop.cpp @@ -0,0 +1,101 @@ +#include "SineSource.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 source = new SineSource(kSampleRate, kNumChannels); +#else + sp source = new AudioSource( + AUDIO_SOURCE_DEFAULT, + kSampleRate, + audio_channel_in_mask_from_count(kNumChannels)); +#endif + + sp 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 encoder = OMXCodec::Create( + client.interface(), + meta, true /* createEncoder */, + source); + +#if 1 + sp writer = new AMRWriter("/sdcard/out.amr"); + writer->addSource(encoder); + writer->start(); + sleep(10); + writer->stop(); +#else + sp 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 0000000000000000000000000000000000000000..cf2909ed76f7ee08ca897ee98a39ddfd080d5b42 --- /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 + +#include "SimplePlayer.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 mCodec; + Vector > mCSD; + size_t mCSDIndex; + Vector > mInBuffers; + Vector > mOutBuffers; + bool mSignalledInputEOS; + bool mSawOutputEOS; + int64_t mNumBuffersDecoded; + int64_t mNumBytesDecoded; + bool mIsAudio; +}; + +} // namespace android + +static int decode( + const android::sp &looper, + const char *path, + bool useAudio, + bool useVideo, + const android::sp &surface, + bool decryptInputBuffers) { + using namespace android; + + static int64_t kTimeout = 500ll; + + sp extractor = new NuMediaExtractor; + if (extractor->setDataSource(path) != OK) { + fprintf(stderr, "unable to instantiate extractor.\n"); + return 1; + } + + KeyedVector stateByTrack; + + bool haveAudio = false; + bool haveVideo = false; + for (size_t i = 0; i < extractor->countTracks(); ++i) { + sp 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 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 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 &srcBuffer = + state->mCSD.itemAt(state->mCSDIndex++); + + const sp &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 &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 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 looper = new ALooper; + looper->start(); + + sp composerClient; + sp control; + sp 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 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 0000000000000000000000000000000000000000..7e859c3d586e349d8b007dcc5e88c62977335a1f --- /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 +#include +#include + +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 0000000000000000000000000000000000000000..ce86cf297197c277b3dd6c269cc9138fc2d11055 --- /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 0000000000000000000000000000000000000000..45c3f7b7aabe91d76038d6345fb1bccf0fd05ced --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 getFormat() { + sp 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 createSource(const char *filename) { + sp source; + + sp extractor = + MediaExtractor::Create(new FileSource(filename)); + if (extractor == NULL) { + return NULL; + } + + size_t num_tracks = extractor->countTracks(); + + sp 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 \n", argv[0]); + fprintf(stderr, " : 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 source = createSource(argv[1]); + + if (source == NULL) { + fprintf(stderr, "Unable to find a suitable video track.\n"); + return 1; + } + + sp meta = source->getFormat(); + + sp 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 decoder = new DummySource(width, height, colorFormat); +#endif + + sp 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 encoder = + OMXCodec::Create( + client.interface(), enc_meta, true /* createEncoder */, decoder); + +#if 1 + sp 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 audioSource = new SineSource(kSampleRate, kNumChannels); + +#if 0 + sp audioSink; + AudioPlayer *player = new AudioPlayer(audioSink); + player->setSource(audioSource); + player->start(); + + sleep(10); + + player->stop(); +#endif + + sp 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 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 0000000000000000000000000000000000000000..3bd1fe22f663e579d45243f2dad490a009b5731f --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 getFormat() { + sp 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 source = + new DummySource(width, height, nFrames, frameRateFps, colorFormat); + + sp 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 encoder = + OMXCodec::Create( + client.interface(), enc_meta, true /* createEncoder */, source); + + sp 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 0000000000000000000000000000000000000000..3bbfbdca33b40dcf5881a57af84ca504cf4fb72a --- /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 + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "include/ESDS.h" + +using namespace android; + +struct Controller : public AHandler { + Controller(const char *uri, bool decodeAudio, + const sp &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 &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::CreateFromURI(mURI.c_str()); + + sp extractor = + MediaExtractor::Create(dataSource); + + for (size_t i = 0; i < extractor->countTracks(); ++i) { + sp 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 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 mDecodeLooper; + + AString mURI; + bool mDecodeAudio; + sp mSurface; + bool mRenderToSurface; + sp mCodec; + sp mSource; + bool mIsVorbis; + + Vector > 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 makeFormat(const sp &meta) { + CHECK(mCSD.isEmpty()); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp 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 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 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 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 &msg) { + sp reply; + CHECK(msg->findMessage("reply", &reply)); + + if (mSource == NULL || mSeekState == SEEK_FLUSHING) { + reply->setInt32("err", ERROR_END_OF_STREAM); + reply->post(); + return; + } + + sp 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 &msg) { + sp buffer; + CHECK(msg->findBuffer("buffer", &buffer)); + + mTotalBytesReceived += buffer->size(); + + sp 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 looper = new ALooper; + looper->setName("sf2"); + + sp composerClient; + sp control; + sp 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 = + 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 0000000000000000000000000000000000000000..d70c86223a359260c91021dd837b10482c965b7e --- /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 + +#include + +#include +#include +#include + +#include "jpeg.h" +#include "SineSource.h" + +#include +#include +#include +#include +#include "include/LiveSession.h" +#include "include/NuCachedSource2.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +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 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 *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& 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 &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 &source) { + sp meta = source->getFormat(); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp 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, ×tampUs)); + + 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 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 &source); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + +private: + enum StreamType { + AVC, + MPEG4, + H263, + OTHER, + }; + + sp mSource; + StreamType mStreamType; + bool mSawFirstIDRFrame; + + DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource); +}; + +DetectSyncSource::DetectSyncSource(const sp &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 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 > &sources, bool syncInfoPresent) { +#if 0 + sp writer = + new MPEG4Writer(gWriteMP4Filename.string()); +#else + sp writer = + new MPEG2TSWriter(gWriteMP4Filename.string()); +#endif + + // at most one minute. + writer->setMaxFileDuration(60000000ll); + + for (size_t i = 0; i < sources.size(); ++i) { + sp source = sources.editItemAt(i); + + CHECK_EQ(writer->addSource( + syncInfoPresent ? source : new DetectSyncSource(source)), + (status_t)OK); + } + + sp 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 &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 looper; + sp 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 sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = + interface_cast(binder); + + CHECK(service.get() != NULL); + + sp 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 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 sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = + interface_cast(binder); + + CHECK(service.get() != NULL); + + sp 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 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 sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = interface_cast(binder); + + CHECK(service.get() != NULL); + + sp omx = service->getOMX(); + CHECK(omx.get() != NULL); + + List list; + omx->listNodes(&list); + + for (List::iterator it = list.begin(); + it != list.end(); ++it) { + printf("%s\t Roles: ", (*it).mName.string()); + for (List::iterator itRoles = (*it).mRoles.begin() ; + itRoles != (*it).mRoles.end() ; ++itRoles) { + printf("%s\t", (*itRoles).string()); + } + printf("\n"); + } + } + + sp composerClient; + sp 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 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::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 > mediaSources; + sp 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 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 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 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 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 0000000000000000000000000000000000000000..efa14455cadee431941995783748cd9b90fb3f87 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace android; + +struct MyStreamSource : public BnStreamSource { + // Object assumes ownership of fd. + MyStreamSource(int fd); + + virtual void setListener(const sp &listener); + virtual void setBuffers(const Vector > &buffers); + + virtual void onBufferAvailable(size_t index); + +protected: + virtual ~MyStreamSource(); + +private: + int mFd; + off64_t mFileSize; + uint64_t mNumPacketsSent; + + sp mListener; + Vector > 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 &listener) { + mListener = listener; +} + +void MyStreamSource::setBuffers(const Vector > &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 extra = new AMessage; + extra->setInt32(IStreamListener::kKeyFormatChange, 0); + + mListener->issueCommand( + IStreamListener::DISCONTINUITY, false /* synchronous */, extra); + + mNumPacketsSent = 0; + } +#endif + + sp 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 &listener); + virtual void setBuffers(const Vector > &buffers); + + virtual void onBufferAvailable(size_t index); + +protected: + virtual ~MyConvertingStreamSource(); + +private: + Mutex mLock; + Condition mCondition; + + sp mListener; + Vector > mBuffers; + + sp mWriter; + + ssize_t mCurrentBufferIndex; + size_t mCurrentBufferOffset; + + List 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::CreateFromURI(filename); + CHECK(dataSource != NULL); + + sp extractor = MediaExtractor::Create(dataSource); + CHECK(extractor != NULL); + + mWriter = new MPEG2TSWriter( + this, &MyConvertingStreamSource::WriteDataWrapper); + + for (size_t i = 0; i < extractor->countTracks(); ++i) { + const sp &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 &listener) { + mListener = listener; +} + +void MyConvertingStreamSource::setBuffers( + const Vector > &buffers) { + mBuffers = buffers; +} + +ssize_t MyConvertingStreamSource::WriteDataWrapper( + void *me, const void *data, size_t size) { + return static_cast(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 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 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 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 = control->getSurface(); + CHECK(surface != NULL); + + sp sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = interface_cast(binder); + + CHECK(service.get() != NULL); + + sp client = new MyClient; + + sp 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 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 0000000000000000000000000000000000000000..f1136c916615d44ce1b2c392afd2d7f48faf0eaa --- /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 0000000000000000000000000000000000000000..4a4d798ca43f7420f0a1e18aa234c2e43e365af2 --- /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 + +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 0000000000000000000000000000000000000000..5d035f5b08aa4240e57f14e23a63adf89dea071a --- /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 + +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 0000000000000000000000000000000000000000..1c345a2a2d6110ce9ad31f7dc2d042be4fcf74b7 --- /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 0000000000000000000000000000000000000000..ddcab334e82e82c69c52014f2d30873454e962b1 --- /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 + +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 0000000000000000000000000000000000000000..27a5a2d51e2f848da5a2591747b7414285a33a72 --- /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 +#include + +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 0000000000000000000000000000000000000000..a64685904b66c253f7f1f2be4adbb86e6b2490f3 --- /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 + +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 0000000000000000000000000000000000000000..8ec7311f7ea1371fbf2fb305b40e7ce6713e743b --- /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 + +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 0000000000000000000000000000000000000000..2a4b8c8a4ab9b615b64f4d9fd5354725ddc357a2 --- /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 + +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 0000000000000000000000000000000000000000..3aecb3d35c80628c5df7ee2e22d8db0417ae705d --- /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 +#include + +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 0000000000000000000000000000000000000000..5400bdd45cb849ec57ec401344dca5482937df5c --- /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 +#include + +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 0000000000000000000000000000000000000000..43f64f22e3193afcbfe331915a1a4355f2f9e1b5 --- /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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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& 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(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(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 drmServiceListener + = interface_cast (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(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 0000000000000000000000000000000000000000..6eeea406036a0239fb594618b1b9e909c7a2f620 --- /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 +#include +#include +#include +#include +#include +#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 0000000000000000000000000000000000000000..fd17e98d307a2d41929b5b638964e8992ab7994c --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 0000000000000000000000000000000000000000..fd417cb9d8007a8c7cddf59e768ab1274b18352d --- /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 0000000000000000000000000000000000000000..999295acb734512e91832a2c28583336556bee5b --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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& 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 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 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 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 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 plugInPathList = mPlugInManager.getPlugInIdList(); + int size = plugInPathList.size(); + int validPlugins = 0; + + if (0 < size) { + Vector 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 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 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 serviceListener = mServiceListeners.valueFor(uniqueId); + serviceListener->notify(event); + } + } +} + diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ba02037977bfa093fcc4d463fe34c43a0d69006 --- /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 + +#include +#include + +#include +#include +#include +#include +#include +#include "DrmManagerService.h" +#include "DrmManager.h" + +using namespace android; + +static Vector 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& 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& 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 0000000000000000000000000000000000000000..434d561154b3a698cf9e7439dee4a13bc045b8cb --- /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 +#include +#include +#include + +#include + +using namespace android; + +int main(int argc, char** argv) +{ + sp proc(ProcessState::self()); + sp 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 0000000000000000000000000000000000000000..c534402e32974b9389b90ba4f0f2d26e8b77999a --- /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 0000000000000000000000000000000000000000..8768c0834f608bbbe175821c70959899ab25e00a --- /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 +#include +#include + +#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& 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, int action, bool reserve) { + return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve); +} + +status_t DrmManagerClient::setPlaybackStatus( + sp &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 DrmManagerClient::openDecryptSession( + int fd, off64_t offset, off64_t length, const char* mime) { + + return mDrmManagerClientImpl->openDecryptSession( + mUniqueId, fd, offset, length, mime); +} + +sp DrmManagerClient::openDecryptSession( + const char* uri, const char* mime) { + + return mDrmManagerClientImpl->openDecryptSession( + mUniqueId, uri, mime); +} + +status_t DrmManagerClient::closeDecryptSession(sp &decryptHandle) { + return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle); +} + +status_t DrmManagerClient::initializeDecryptUnit( + sp &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { + return mDrmManagerClientImpl->initializeDecryptUnit( + mUniqueId, decryptHandle, decryptUnitId, headerInfo); +} + +status_t DrmManagerClient::decrypt( + sp &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, int decryptUnitId) { + return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, + decryptHandle, decryptUnitId); +} + +ssize_t DrmManagerClient::pread( + sp &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 0000000000000000000000000000000000000000..fb0439ebf6fec92f5fbb7dec3269cb1a76c02164 --- /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 + +#include +#include +#include + +#include "DrmManagerClientImpl.h" + +using namespace android; + +#define INVALID_VALUE -1 + +Mutex DrmManagerClientImpl::sMutex; +sp DrmManagerClientImpl::sDrmManagerService; +sp 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& DrmManagerClientImpl::getDrmManagerService() { + Mutex::Autolock lock(sMutex); + if (NULL == sDrmManagerService.get()) { + sp sm = defaultServiceManager(); + sp 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(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& 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, + 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, + 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 DrmManagerClientImpl::openDecryptSession( + int uniqueId, int fd, off64_t offset, + off64_t length, const char* mime) { + + return getDrmManagerService()->openDecryptSession( + uniqueId, fd, offset, length, mime); +} + +sp 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) { + 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, + 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, + 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, 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, + 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 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& 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 0000000000000000000000000000000000000000..c9167d4708f2374c376679ac69b72adfe2f49521 --- /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 +#include +#include +#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& 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 mUniqueIdVector; + static const String8 EMPTY_STRING; + + int mDecryptSessionId; + int mConvertId; + Mutex mLock; + Mutex mListenerLock; + Mutex mDecryptLock; + Mutex mConvertLock; + TPlugInManager mPlugInManager; + KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap; + KeyedVector< int, IDrmEngine*> mConvertSessionMap; + KeyedVector< int, sp > 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 0000000000000000000000000000000000000000..2aa493f4ebe17fb17811767751cc11d877d87816 --- /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 +#include +#include + +#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& 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, 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, 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 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 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); + + /** + * 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, + 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, 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, 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, + 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 mOnInfoListener; + + class DeathNotifier: public IBinder::DeathRecipient { + public: + DeathNotifier() {} + virtual ~DeathNotifier(); + virtual void binderDied(const wp& who); + }; + +private: + static Mutex sMutex; + static sp sDeathNotifier; + static sp sDrmManagerService; + static const sp& 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 0000000000000000000000000000000000000000..1a8c2ae5c994f41c9f2e3d7bb85c3c2fc397972c --- /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 +#include +#include +#include +#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& 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& 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 0000000000000000000000000000000000000000..a7d21c5a61813ddca8ec3c72541fb9103f72d64a --- /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 +#include +#include +#include +#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& 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 +{ +public: + BpDrmManagerService(const sp& impl) + : BpInterface(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& 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 +{ +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 0000000000000000000000000000000000000000..7f7109f29b88ac91b9072d440fbf32bcf19e7c6f --- /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 +#include +#include + +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 +{ +public: + BpDrmServiceListener(const sp& impl) + : BpInterface(impl) {} + + virtual status_t notify(const DrmInfoEvent& event); +}; + +/** + * This is the Binder implementation class for DRM service listener. + */ +class BnDrmServiceListener: public BnInterface +{ +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 0000000000000000000000000000000000000000..7bb143fe20952266bdebdfcc62c6615072ff9032 --- /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 +#include +#include + +#include +#include +#include + +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 +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 PlugInMap; + PlugInMap m_plugInMap; + + typedef Vector 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 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 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 getPlugInPathList(const String8& rsDirPath) { + Vector 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 0000000000000000000000000000000000000000..529b3424571bf310b82ffd63493d922a64c44d48 --- /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 +#include + +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 0000000000000000000000000000000000000000..9ee79618c203737d83fea3965f36fa14be6d82d0 --- /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 0000000000000000000000000000000000000000..9ee79618c203737d83fea3965f36fa14be6d82d0 --- /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 0000000000000000000000000000000000000000..08f6e6d2ad5c296805109ab157e80dded52c9ca9 --- /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 +#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 0000000000000000000000000000000000000000..dcf59775700bd535baf12bec6c8600ba44770132 --- /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 + +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 0000000000000000000000000000000000000000..15dda80cf7b9a237bfca96f6d7f8009e5788b622 --- /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 0000000000000000000000000000000000000000..4d12a61a6e6e2ee952620473062f40dffab5ccbf --- /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 + +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 0000000000000000000000000000000000000000..e5638942c23466dda54879438f6bf4cd6f27a851 --- /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 +#include + +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 +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 & operator=(const SessionMap & objectCopy) { + Mutex::Autolock lock(mLock); + + destroyMap(); + map = objectCopy.map; + return *this; + } + +private: + KeyedVector 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 0000000000000000000000000000000000000000..576ed15990be8f54296d7bfdb1c43b50786f4a9c --- /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 +#include + +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 0000000000000000000000000000000000000000..9ee79618c203737d83fea3965f36fa14be6d82d0 --- /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 0000000000000000000000000000000000000000..e359dbd81fcebc2acbbe7df34708fd69bf58416f --- /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 0000000000000000000000000000000000000000..c0e408e3bac0480d6c42c05abdd0a582ef1d1f6d --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 convertSessionMap; +SessionMap 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 0000000000000000000000000000000000000000..4b1b40ebd2b6c95555b8b6921499b0d78a29ead6 --- /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 +#include +#include +#include +#include "drm_framework_common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 0000000000000000000000000000000000000000..9ee79618c203737d83fea3965f36fa14be6d82d0 --- /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 0000000000000000000000000000000000000000..6c5d3cf9bcd96d4f4c1b624e296daa6035b8910a --- /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 0000000000000000000000000000000000000000..92bda8ffadb1d676b3ddad148abab7b3da010410 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 0000000000000000000000000000000000000000..f36f6ea98e5a74ecdf946e5f9a8ee12c70204ce7 --- /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 0000000000000000000000000000000000000000..00bb788fa2cf21242ae398d4d00935750498d5d4 --- /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 0000000000000000000000000000000000000000..299116deb469061ab7d47bdf0f369f2cf7ba679c --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 0000000000000000000000000000000000000000..e20c0c382c26f38edf763c6f1cecce3960daea4e --- /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 + +/** + * 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 0000000000000000000000000000000000000000..b625edf10a94439b576a0c0e76ff79bd186f21e8 --- /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 0000000000000000000000000000000000000000..365bdece02ac9dd06c688ed26ebf498094c6b222 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 0000000000000000000000000000000000000000..fc64050eb5ca90bc135074fd9dedc59edc6c83c9 --- /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 + +/** + * 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 0000000000000000000000000000000000000000..8f95cd218a8a6e8f99ddd9251faed40efe66cc34 --- /dev/null +++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html @@ -0,0 +1,1039 @@ + + + + + +Forward Lock Converter and Decoder + + + + + + + + +
+
+ +
+ +

1      Introduction

+ +

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.

+ +

Our general strategy is to convert such OMA DRM Message +(‘.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.

+ +

2      +Overview

+ +

The Forward Lock Converter converts OMA DRM Message +files to the internal file format. The Forward Lock Decoder 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.

+ +

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.

+ +

+ +

Figure 1. Block diagram illustrating the dependencies between the executable modules.

+ +
+
+ +

3      +Use Cases

+ +

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.

+ +

3.1    +Converter

+ +

Through the converter API, conversion can be performed in one +of two ways:

+ +

1.      Push-mode +conversion 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.

+ +

2.      Pull-mode +conversion 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.

+ +

Internally, pull-mode conversion is implemented in terms +of the API for push-mode conversion.

+ +

3.1.1    Convert Data +(Push-Mode Conversion)

+ +

Push-mode conversion is performed as follows (see also Figure 2):

+ +

1.      FwdLockConv_OpenSession +initializes the output parameter and returns a session ID 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.

+ +

2.      FwdLockConv_ConvertData +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.

+ +

3.      FwdLockConv_CloseSession +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.

+ +

Every time a file is being converted, the converter calls FwdLockGlue_GetRandomNumber +to generate a new, unique session key. No two converted files look alike, even +if the original files are the same.

+ +

Note: The random bytes cannot come from any bare-minimum +implementation of the C-library rand +function—they must be cryptographically secure. Otherwise, security will be +compromised.

+ +

The session key is encrypted and stored within the +converted file. Key encryption is performed using FwdLockGlue_GetEncryptedKeyLength and FwdLockGlue_EncryptKey. +These two functions, together with the corresponding decryption function (FwdLockGlue_DecryptKey), +are the integration points where an OEM manufacturer may implement their own +key-encryption scheme.

+ +

Note: 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.

+ +
+ +

Note: In the open-source implementation of the libfwdlock-common +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.

+ +
+ +

+ +

Figure 2. Converter UC: Convert Data.

+ +
+
+ +

3.1.2    Convert File +(Pull-Mode Conversion)

+ +

Pull-mode conversion is performed by calling FwdLockFile_ConvertFile +with the filename, unless there is need for a specialized read function, in +which case FwdLockFile_ConvertOpenFile +should be used directly instead. See Figure 3.

+ +

Internally, FwdLockFile_ConvertFile +calls FwdLockFile_ConvertOpenFile. +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.

+ +

+ +

Figure 3. Converter UC: Convert File.

+ +
+
+ +

3.2    +Decoder

+ +

The decoder API allows the client to do the following:

+ +

1.      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.

+ +

2.      Get +the MIME type of the embedded content (the “original” MIME type before DRM protection +was applied); see section 3.2.2.

+ +

3.      Decode +the file by random access, i.e., read and seek through it in an arbitrary +manner; see section 3.2.3.

+ +

All subsequent operations on a file first require it to be +opened. Opening a file returns a file descriptor—a handle to be used in +these subsequent operations.

+ +

If the filename is known, an internal Forward Lock file +can be opened using FwdLockFile_open. +If only the file descriptor of an already open file is available, a decoding +session can instead be initialized using FwdLockFile_attach.

+ +

Internally, FwdLockFile_open calls FwdLockFile_attach. For efficiency +reasons, FwdLockFile_attach +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.

+ +

When a file is being attached, the session key stored in +the file during conversion is decrypted using FwdLockGlue_GetEncryptedKeyLength and FwdLockGlue_DecryptKey, +in order to set up for decoding and integrity checking.

+ +

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.

+ +

Symmetrical to FwdLockFile_open and FwdLockFile_attach, there are also functions +for closing a file or detaching from it:

+ +

1.      If +it was opened with FwdLockFile_open +it should be closed with FwdLockFile_close.

+ +

2.      If +it was attached with FwdLockFile_attach +it should be detached with FwdLockFile_detach.

+ +
+
+ +

3.2.1    Check Integrity

+ +

There are three methods for checking the integrity of an +internal Forward Lock file, in whole or in part (see also Figure 4):

+ +

1.      FwdLockFile_CheckDataIntegrity, +which checks the integrity of the encrypted content data.

+ +

2.      FwdLockFile_CheckHeaderIntegrity, +which checks the integrity of the file header, including the content type and +other fields not currently supported but reserved for future use.

+ +

3.      FwdLockFile_CheckIntegrity, +which internally calls first FwdLockFile_CheckHeaderIntegrity +and then FwdLockFile_CheckDataIntegrity.

+ +

FwdLockFile_CheckHeaderIntegrity is +generally much faster than FwdLockFile_CheckDataIntegrity, +whose running time is directly proportional to the size of the file.

+ +

+ +

Figure 4. Decoder UC: Check Integrity.

+ +
+
+ +

3.2.2    Get Content Type

+ +

FwdLockFile_GetContentType 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.

+ +

+ +

Figure 5. Decoder UC: Get Content Type.

+ +
+
+ +

3.2.3    Decode File

+ +

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 lseek does) can be made in any order; this is what we +call random access. See Figure 6.

+ +

The Forward Lock Decoder versions of the read, lseek, and close functions +have the exact same signatures as their POSIX counterparts. So, for example, +the call FwdLockFile_lseek(fd, +0, SEEK_END) returns the size of the embedded content data, i.e., the +size of the original file before DRM protection.

+ +

Moreover, FwdLockFile_open +is like regular POSIX open +except it takes only the filename as a parameter—access is always read-only.

+ +

+ +

Figure 6. Decoder UC: Decode File.

+ +
+
+ +

4      +Definition of the Internal Forward Lock File Format

+ +

The inner structure of an internal +Forward Lock file is defined in Table 1 below.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Offset [bytes]

+
+

Size [bytes]

+
+

Description

+
+

0

+
+

4

+
+

The file signature (so-called + magic number): a four-character code consisting of the letters + F-W-L-K.

+
+

4

+
+

1

+
+

Version number (0 for the + first version).

+
+

5

+
+

1

+
+

Indicates the subformat:

+

0x00 Forward Lock

+

0x01 Combined Delivery

+
+

6

+
+

1

+
+

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.

+

0x00 No usage + restrictions

+

0x01 Ringtone usage + prohibited

+

0x02 Screen usage + prohibited

+

0x80 Bound to SIM

+

(Any number of these may be + OR-ed together.)

+
+

7

+
+

1

+
+

Length of the MIME content + type (k).

+
+

8

+
+

k

+
+

The MIME content type + (ASCII-encoded without null-character termination).

+
+

8+k

+
+

l = 0 or 16

+
+

If the subformat is + Combined Delivery, this field contains the auto-generated content ID (16 bytes). + If not, this field is zero-size.

+
+

8+k+l

+
+

m = 0 or 9

+
+

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.

+
+

8+k+l+m

+
+

n ≥ 16

+
+

The encrypted session key, the + first sixteen bytes of which are also used as the CTR-mode nonce (similar + to the CBC-mode initialization vector).

+
+

8+k+l+m+n

+
+

20

+
+

Data signature—the SHA-1 + HMAC of the encrypted content data.

+
+

28+k+l+m+n

+
+

20

+
+

Header signature—the SHA-1 + HMAC of all the fields above, including the encrypted session key and data + signature.

+
+

48+k+l+m+n

+
+

<to the end of the + file>

+
+

The content data encrypted + using 128-bit AES in CTR mode.

+
+ +

Table 1. Definition of the fields of an internal Forward Lock file.

+ +

As of now, neither Combined Delivery nor usage +restrictions (including SIM binding) are supported. These fields are reserved +for future use.

+ +

4.1    +Key Derivation

+ +

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.

+ +

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.

+ +

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 nonce +for the CTR-mode encryption of the content data.

+ +

4.2    +Calculation of the Counters

+ +

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:

+ +

1.      The +nonce is interpreted as a 128-bit unsigned integer in little-endian format.

+ +

2.      The +zero-based block sequence number (also a little-endian unsigned integer) is +added modulo 2128 to the nonce to produce the counter for a given +block.

+ +

5      +Unit Test Cases

+ +

Unit test cases for the converter and decoder come in two +varieties:

+ +

1.      Black-box +test cases aim to verify that you get sensible results from malformed or +“tricky” input data.

+ +

2.      White-box +test cases aim to maximize code coverage using knowledge of code internals.

+ +

The black-box test cases are dependent on a specifically +designed set of input files found in the forward-lock/internal-format/test/res +directory in the repository. For ‘tests’ variants of the software, these input +files will be automatically installed in the file system image during build.

+ +

Run the test cases from the ADB shell command line as +follows:

+ +

# +gtest_fwdlock

+ +

If all black-box but no white-box test cases fail, the +input files probably can’t be found in the working directory.

+ +

6      +References

+ +

[1]           +Dworkin, +Morris: “Recommendation for Block Cipher Modes of Operation—Methods and +Techniques,” NIST Special Publication 800-38A, December 2001.

+ +
+ + + + 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 0000000000000000000000000000000000000000..ee94513a0fa788c9a68e579737c26f80f8c5e614 Binary files /dev/null and b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif 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 0000000000000000000000000000000000000000..8c12f460a77880ae5b194a308ecd3c7fdc52fc43 Binary files /dev/null and b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif 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 0000000000000000000000000000000000000000..9e019cab97ac6772a4d4d29c85c6ffb8026b8626 Binary files /dev/null and b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif 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 0000000000000000000000000000000000000000..cae1d0156bb9444703812ff1f81533fe5a11d31f Binary files /dev/null and b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif 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 0000000000000000000000000000000000000000..0d87be96ad3b166772f3411043a3e3dfcfab0420 Binary files /dev/null and b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif 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 0000000000000000000000000000000000000000..9445b6ba2d9cc534e42ea1f1b28097ec62b3e437 Binary files /dev/null and b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif differ diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..d0d1439bb945d80d2af50ba139e9c2dc4319685d --- /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 0000000000000000000000000000000000000000..f941f7007dc8f58e13f0892bf1d2b043c39240c0 --- /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 + +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 0000000000000000000000000000000000000000..a3eac3e0da7243f3f06fe64762065f8300ab9af6 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 0000000000000000000000000000000000000000..3fedea0f6b67ea75c3698aa69b65b0934200d4aa --- /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 +#include +#include +#include +#include +#include + +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& dataPtr, + camera_frame_metadata_t *metadata) = 0; + virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr) = 0; +}; + +class Camera : public BnCameraClient, public IBinder::DeathRecipient +{ +public: + // construct a camera client from an existing remote + static sp create(const sp& camera); + static int32_t getNumberOfCameras(); + static status_t getCameraInfo(int cameraId, + struct CameraInfo* cameraInfo); + static sp 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); + + // pass the buffered ISurfaceTexture to the camera service + status_t setPreviewTexture(const sp& 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& 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& listener); + void setRecordingProxyListener(const sp& listener); + void setPreviewCallbackFlags(int preview_callback_flag); + + sp getRecordingProxy(); + + // ICameraClient interface + virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); + virtual void dataCallback(int32_t msgType, const sp& dataPtr, + camera_frame_metadata_t *metadata); + virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr); + + sp remote(); + + class RecordingProxy : public BnCameraRecordingProxy + { + public: + RecordingProxy(const sp& camera); + + // ICameraRecordingProxy interface + virtual status_t startRecording(const sp& listener); + virtual void stopRecording(); + virtual void releaseRecordingFrame(const sp& mem); + + private: + sp mCamera; + }; + +private: + Camera(); + Camera(const Camera&); + Camera& operator=(const Camera); + virtual void binderDied(const wp& who); + + class DeathNotifier: public IBinder::DeathRecipient + { + public: + DeathNotifier() { + } + + virtual void binderDied(const wp& who); + }; + + static sp mDeathNotifier; + + // helper function to obtain camera service handle + static const sp& getCameraService(); + + sp mCamera; + status_t mStatus; + + sp mListener; + sp mRecordingProxyListener; + + friend class DeathNotifier; + + static Mutex mLock; + static sp mCameraService; +}; + +}; // namespace android + +#endif diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h new file mode 100644 index 0000000000000000000000000000000000000000..3d188379fede7808aa24a6a1709a669922a04038 --- /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 +#include +#include +#include +#include +#include + +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& 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) = 0; + + // pass the buffered ISurfaceTexture to the camera service + virtual status_t setPreviewTexture( + const sp& 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& 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 +{ +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 0000000000000000000000000000000000000000..b30aa7a7a13e430fc2327d3b7528df5cfac363b3 --- /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 +#include +#include +#include +#include +#include + +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& data, + camera_frame_metadata_t *metadata) = 0; + virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& data) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnCameraClient: public BnInterface +{ +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 0000000000000000000000000000000000000000..2aac28465c3b83fc6fbfdf1905260b98ad891247 --- /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 +#include + +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& listener) = 0; + virtual void stopRecording() = 0; + virtual void releaseRecordingFrame(const sp& mem) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnCameraRecordingProxy: public BnInterface +{ +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 0000000000000000000000000000000000000000..b6c062442fd6a3bf887b001acee86b5a3ae5a4b7 --- /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 +#include +#include +#include + +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& data) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnCameraRecordingProxyListener: public BnInterface +{ +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 0000000000000000000000000000000000000000..97e3169875d2d5fcf5bb44296b5c0e4eca24e296 --- /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 +#include +#include + +#include +#include + +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 connect(const sp& cameraClient, + int cameraId, bool force, bool keep) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnCameraService: public BnInterface +{ +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 0000000000000000000000000000000000000000..d7073f1337d9157bef1303f90b97dae562f3caf7 --- /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 +#include + +#include +#include + +namespace android { + +class ICommonClockListener : public IInterface { + public: + DECLARE_META_INTERFACE(CommonClockListener); + + virtual void onTimelineChanged(uint64_t timelineID) = 0; +}; + +class BnCommonClockListener : public BnInterface { + 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& listener) = 0; + virtual status_t unregisterListener( + const sp& listener) = 0; + + // Simple helper to make it easier to connect to the CommonClock service. + static inline sp getInstance() { + sp binder = defaultServiceManager()->checkService( + ICommonClock::kServiceName); + sp clk = interface_cast(binder); + return clk; + } +}; + +class BnCommonClock : public BnInterface { + 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 0000000000000000000000000000000000000000..497b666de6f8946df7e4e17be346083f713a0b61 --- /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 +#include + +#include +#include + +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 getInstance() { + sp binder = defaultServiceManager()->checkService( + ICommonTimeConfig::kServiceName); + sp clk = interface_cast(binder); + return clk; + } +}; + +class BnCommonTimeConfig : public BnInterface { + 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 0000000000000000000000000000000000000000..8c4d5c063d528e3ab7ad34665ee68f8ab9ee2b5b --- /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 +#include +#include + +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 common_clock_; + static sp 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 0000000000000000000000000000000000000000..384c3dec011c760536f948c74d422a65b7140353 --- /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 + +#include +#include +#include + +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 0000000000000000000000000000000000000000..a9ec94252f20805ef67a344835331b36347656c4 --- /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 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 DrmConstraintsMap; + DrmConstraintsMap mConstraintMap; +}; + +}; + +#endif /* __DRM_CONSTRAINTS_H__ */ + diff --git a/include/drm/DrmConvertedStatus.h b/include/drm/DrmConvertedStatus.h new file mode 100644 index 0000000000000000000000000000000000000000..679e48df99905568ffc0c2a65472e2eb45a68c81 --- /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 0000000000000000000000000000000000000000..7b4854187a5755dedc67f2b6fd7b03e1fdef6c31 --- /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)), 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)), 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 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 mAttributes; +}; + +}; + +#endif /* __DRM_INFO_H__ */ + diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h new file mode 100644 index 0000000000000000000000000000000000000000..dfca228b902c5233b94859c6f47ff75e7a57a757 --- /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 0000000000000000000000000000000000000000..3e48ecc8599f9ab8fdd6b05f75c18052f66ac4c4 --- /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)), 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)), 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 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 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 0000000000000000000000000000000000000000..88c0f40df0f120e53bcdb124fb32bd9329a7fd9a --- /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 0000000000000000000000000000000000000000..c47bbfbfdce61e7a90cd243d8f7bc10768d79823 --- /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 +#include +#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 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 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); + + /** + * 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, 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, 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, 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, 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, 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, + 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& 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 mDrmManagerClientImpl; +}; + +}; + +#endif /* __DRM_MANAGER_CLIENT_H__ */ + diff --git a/include/drm/DrmMetadata.h b/include/drm/DrmMetadata.h new file mode 100644 index 0000000000000000000000000000000000000000..2c7538af55765de683052258ea55f197604ac143 --- /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 DrmMetadataMap; + DrmMetadataMap mMetadataMap; +}; + +}; + +#endif /* __DRM_METADATA_H__ */ + diff --git a/include/drm/DrmRights.h b/include/drm/DrmRights.h new file mode 100644 index 0000000000000000000000000000000000000000..11f8f78bc56eefa4c4e37b8f3183263c26f5c952 --- /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 0000000000000000000000000000000000000000..bf12b0b37e9dc3bce73bd896e93e1535a1bce8ee --- /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 mMimeTypeVector; + Vector 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 0000000000000000000000000000000000000000..637409ca00696c71a335fee88f87a0c3ab55b699 --- /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 +#include +#include +#include +#include + +#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 copyControlVector; + + /** + * Defines a vector for any extra data the DRM plugin wants to send + * to the native code + */ + KeyedVector 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 0000000000000000000000000000000000000000..02dfc1bb97b40ac8316605ddf4f2a90b0ed0d2a7 --- /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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +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& 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 mIEffect; // IEffect binder interface + sp mIEffectClient; // IEffectClient implementation + sp 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 0000000000000000000000000000000000000000..79d5d82ddb8acdb6de3d02a9f5b5c4a20611d863 --- /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 +#include +#include + +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 mParameters; +}; + +}; // namespace android + +#endif /*ANDROID_AUDIOPARAMETER_H_*/ diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h new file mode 100644 index 0000000000000000000000000000000000000000..5bfb65b926aae2476d0e7e25ac17fc431e8cd1fc --- /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 +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +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& 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 mAudioRecord; + sp mCblkMemory; + sp 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 0000000000000000000000000000000000000000..cc0a594d164d1841723e5eeb224c5009e90efe1f --- /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 +#include +#include + +#include +#include + +/* XXX: Should be include by all the users instead */ +#include + +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& 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& get_audio_policy_service(); + + // ---------------------------------------------------------------------------- + +private: + + class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient + { + public: + AudioFlingerClient() { + } + + // DeathRecipient + virtual void binderDied(const wp& 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& who); + }; + + static sp gAudioFlingerClient; + static sp gAudioPolicyServiceClient; + friend class AudioFlingerClient; + friend class AudioPolicyServiceClient; + + static Mutex gLock; + static sp 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 gAudioPolicyService; + + // mapping between stream types and outputs + static DefaultKeyedVector gStreamOutputMap; + // list of output descriptors containing cached parameters + // (sampling rate, framecount, channel count...) + static DefaultKeyedVector gOutputs; +}; + +}; // namespace android + +#endif /*ANDROID_AUDIOSYSTEM_H_*/ diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..7d5d772ff94176078fa88f96b7decc66265b7b73 --- /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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +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& 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& 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& 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 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& 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& 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& 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 mAudioTrack; + sp mCblkMemory; + sp 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 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* 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& 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 0000000000000000000000000000000000000000..65c26f4794be69baa020cb794382c1bf14cf9b1e --- /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 +#include +#include +#include + +#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 0000000000000000000000000000000000000000..8239b0e48192aba39a80d67ccbcbe397469c4271 --- /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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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& sharedBuffer, + audio_io_handle_t output, + int *sessionId, + status_t *status) = 0; + + virtual sp 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& 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 createEffect(pid_t pid, + effect_descriptor_t *pDesc, + const sp& 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 +{ +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 0000000000000000000000000000000000000000..75a997169a0230e54316232ef35ca4af19d3a86d --- /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 +#include +#include +#include + +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 +{ +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 0000000000000000000000000000000000000000..04c927aec3bd9a408d6d080976062a95989f2319 --- /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 +#include +#include + +#include +#include +#include +#include + +#include + +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 +{ +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 0000000000000000000000000000000000000000..089be3b12890d75d2a01ede264f687efa21288c1 --- /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 +#include + +#include +#include +#include +#include + + +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 getCblk() const = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnAudioRecord : public BnInterface +{ +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 0000000000000000000000000000000000000000..577b09527e59ce565ac9ca383a6ecc26e2c1c0de --- /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 +#include + +#include +#include +#include +#include +#include + +namespace android { + +// ---------------------------------------------------------------------------- + +class IAudioTrack : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioTrack); + + /* Get this track's control block */ + virtual sp 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* buffer) = 0; + + /* Queue a buffer obtained via allocateTimedBuffer for playback at the given + timestamp */ + virtual status_t queueTimedBuffer(const sp& 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 +{ +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 0000000000000000000000000000000000000000..916abe031d118e3e3886556f9d8497035d985a9e --- /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 +#include + +#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 { + 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 0000000000000000000000000000000000000000..ff04869e06be2d6281c8f0d1a5b6ff9224632c66 --- /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 +#include +#include +#include + +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 getCblk() const = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnEffect: public BnInterface +{ +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 0000000000000000000000000000000000000000..2f78c98f172c3d8d647d245e091dc83b8bf7486c --- /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 +#include +#include +#include + +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 +{ +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 0000000000000000000000000000000000000000..bb3d0d845aae73004049fc55f9fbeabdd2260e2f --- /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 +#include +#include + +namespace android { + +class IMediaDeathNotifier: virtual public RefBase +{ +public: + IMediaDeathNotifier() { addObitRecipient(this); } + virtual ~IMediaDeathNotifier() { removeObitRecipient(this); } + + virtual void died() = 0; + static const sp& getMediaPlayerService(); + +private: + IMediaDeathNotifier &operator=(const IMediaDeathNotifier &); + IMediaDeathNotifier(const IMediaDeathNotifier &); + + static void addObitRecipient(const wp& recipient); + static void removeObitRecipient(const wp& recipient); + + class DeathNotifier: public IBinder::DeathRecipient + { + public: + DeathNotifier() {} + virtual ~DeathNotifier(); + + virtual void binderDied(const wp& who); + }; + + friend class DeathNotifier; + + static Mutex sServiceLock; + static sp sMediaPlayerService; + static sp sDeathNotifier; + static SortedVector< wp > sObitRecipients; +}; + +}; // namespace android + +#endif // ANDROID_IMEDIADEATHNOTIFIER_H diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h new file mode 100644 index 0000000000000000000000000000000000000000..6dbb2d75bce0e2ce8b92bd7ed3b07b7e5c86cebb --- /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 +#include +#include +#include +#include + +namespace android { + +class IMediaMetadataRetriever: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaMetadataRetriever); + virtual void disconnect() = 0; + + virtual status_t setDataSource( + const char *srcUrl, + const KeyedVector *headers = NULL) = 0; + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual sp getFrameAtTime(int64_t timeUs, int option) = 0; + virtual sp extractAlbumArt() = 0; + virtual const char* extractMetadata(int keyCode) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaMetadataRetriever: public BnInterface +{ +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 0000000000000000000000000000000000000000..00facc5a6d752b8e49dde5250ab79ad14d3f03f8 --- /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 +#include +#include +#include +#include + +// 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* headers) = 0; + virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setDataSource(const sp& source) = 0; + virtual status_t setVideoSurfaceTexture( + const sp& 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& 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 +{ +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 0000000000000000000000000000000000000000..8f1843ea3dff93d057ab3cef671f969d3779c72f --- /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 +#include +#include + +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 +{ +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 0000000000000000000000000000000000000000..76c45a0270c6178854ead03c152854f5bb608f28 --- /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 // for status_t +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace android { + +struct ICrypto; +class IMediaRecorder; +class IOMX; +struct IStreamSource; + +class IMediaPlayerService: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaPlayerService); + + virtual sp createMediaRecorder(pid_t pid) = 0; + virtual sp createMetadataRetriever(pid_t pid) = 0; + virtual sp create(pid_t pid, const sp& client, int audioSessionId = 0) = 0; + + virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0; + virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0; + virtual sp getOMX() = 0; + virtual sp 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 +{ +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 0000000000000000000000000000000000000000..ec84e2574aed4f52370ef1dadc392b2b6bc9a3fb --- /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 + +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& camera, + const sp& proxy) = 0; + virtual status_t setPreviewSurface(const sp& 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& 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 querySurfaceMediaSource() = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaRecorder: public BnInterface +{ +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 0000000000000000000000000000000000000000..e7d0229576bafdbb91e572fd5de0a3b6d00a530a --- /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 +#include +#include + +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 +{ +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 0000000000000000000000000000000000000000..be1b2fc5316166630c20eb9f046834b47c7e4de6 --- /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 +#include +#include +#include + +#include +#include + +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 mRoles; + }; + virtual status_t listNodes(List *list) = 0; + + virtual status_t allocateNode( + const char *name, const sp &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 ¶ms, + buffer_id *buffer) = 0; + + virtual status_t useGraphicBuffer( + node_id node, OMX_U32 port_index, + const sp &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 ¶ms, + 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 { +public: + virtual status_t onTransact( + uint32_t code, const Parcel &data, Parcel *reply, + uint32_t flags = 0); +}; + +class BnOMXObserver : public BnInterface { +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 0000000000000000000000000000000000000000..19646b0c9d06d8b755160c16839c57356bc8cb78 --- /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 + +namespace android { + +struct AMessage; +struct IMemory; +struct IStreamListener; + +struct IStreamSource : public IInterface { + DECLARE_META_INTERFACE(StreamSource); + + virtual void setListener(const sp &listener) = 0; + virtual void setBuffers(const Vector > &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 &msg = NULL) = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct BnStreamSource : public BnInterface { + virtual status_t onTransact( + uint32_t code, const Parcel &data, Parcel *reply, + uint32_t flags = 0); +}; + +struct BnStreamListener : public BnInterface { + 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 0000000000000000000000000000000000000000..0616bf039b0f9d6d1c585517f629c32fa3ae8084 --- /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 + +#include +#include +#include + + +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 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 0000000000000000000000000000000000000000..ecc3b650d88176a1ff21660a4f05316dba837c78 --- /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 +#include +#include + +namespace android { + +// Abstract base class +class MediaMetadataRetrieverBase : public RefBase +{ +public: + MediaMetadataRetrieverBase() {} + virtual ~MediaMetadataRetrieverBase() {} + + virtual status_t setDataSource( + const char *url, + const KeyedVector *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 0000000000000000000000000000000000000000..d4aa233940b3895cc3e66269f4afbdbed5dae458 --- /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 +#include +#include +#include +#include + +#include +#include +#include + +// 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 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 *headers = NULL) = 0; + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + + virtual status_t setDataSource(const sp &source) { + return INVALID_OPERATION; + } + + // pass the buffered ISurfaceTexture to the media player service + virtual status_t setVideoSurfaceTexture( + const sp& 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 &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) { mAudioSink = audioSink; } +protected: + sp 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 0000000000000000000000000000000000000000..9fc962c10dda7328fc6165264686eb6b9ba6c3cd --- /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 +#include + +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 getOutputFileFormats() const; + + /** + * Returns the video encoders supported. + */ + Vector 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 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 getVideoDecoders() const; + + /** + * Returns the audio decoders supported. + */ + Vector getAudioDecoders() const; + + /** + * Returns the number of image encoding quality levels supported. + */ + Vector 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 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& 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& 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 mCamcorderProfiles; + Vector mAudioEncoders; + Vector mVideoEncoders; + Vector mAudioDecoders; + Vector mVideoDecoders; + Vector mEncoderOutputFileFormats; + Vector mImageEncodingQualityLevels; + KeyedVector 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 mCameraIds; + VideoEditorCap* mVideoEditorCap; + Vector mVideoEditorExportProfiles; +}; + +}; // namespace android + +#endif // ANDROID_MEDIAPROFILES_H diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h new file mode 100644 index 0000000000000000000000000000000000000000..ef799f5cff26b2f4b21032b94d6ddb94b20533d6 --- /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 + +#include + +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& camera, + const sp& proxy) = 0; + virtual status_t setPreviewSurface(const sp& 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& 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& args) const = 0; + virtual sp 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 0000000000000000000000000000000000000000..d2618aaefa50c2fc9f5e71b3fc2ce9acf4ae280b --- /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 0000000000000000000000000000000000000000..07567ebbc1581dd49c4ee6d299d1c536de957f90 --- /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 +#include +#include +#include + +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 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 0000000000000000000000000000000000000000..df0c97ebed3b9a9628e7d1c330e098d613729dbc --- /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 +#include +#include +#include +#include + +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 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 0000000000000000000000000000000000000000..60fa15b39594039743668b0302176bbb94453554 --- /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 +#include +#include + +/** + * 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 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 0000000000000000000000000000000000000000..534afce498f056023c24199d708fc645fc2e89f5 --- /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 // for status_t +#include +#include +#include + +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 *headers = NULL); + + status_t setDataSource(int fd, int64_t offset, int64_t length); + sp getFrameAtTime(int64_t timeUs, int option); + sp extractAlbumArt(); + const char* extractMetadata(int keyCode); + +private: + static const sp& getService(); + + class DeathNotifier: public IBinder::DeathRecipient + { + public: + DeathNotifier() {} + virtual ~DeathNotifier(); + virtual void binderDied(const wp& who); + }; + + static sp sDeathNotifier; + static Mutex sServiceLock; + static sp sService; + + Mutex mLock; + sp mRetriever; + +}; + +}; // namespace android + +#endif // MEDIAMETADATARETRIEVER_H diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h new file mode 100644 index 0000000000000000000000000000000000000000..a68ab4e8edbda0241fd78b779a88d7208d922c62 --- /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 + +#include +#include +#include +#include +#include + +#include +#include + +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 *headers); + + status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setDataSource(const sp &source); + status_t setVideoSurfaceTexture( + const sp& surfaceTexture); + status_t setListener(const sp& 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 decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat); + static sp 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& 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& player); + status_t reset_l(); + status_t doSetRetransmitEndpoint(const sp& player); + + sp mPlayer; + thread_id_t mLockThreadId; + Mutex mLock; + Mutex mNotifyLock; + Condition mSignal; + sp 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 0000000000000000000000000000000000000000..30db64246a3486c7648554ff90430cd13c61c6c7 --- /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 +#include +#include +#include +#include +#include + +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& camera, const sp& proxy); + status_t setPreviewSurface(const sp& 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& 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 querySurfaceMediaSourceFromMediaServer(); + +private: + void doCleanUp(); + status_t doReset(); + + sp mMediaRecorder; + sp mListener; + + // Reference toISurfaceTexture + // for encoding GL Frames. That is useful only when the + // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER + sp 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 0000000000000000000000000000000000000000..a73403b026cddfc8a2f2c9639a9d8289574c79ac --- /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 +#include +#include +#include +#include + +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 0000000000000000000000000000000000000000..49397ee261b98c3d235f7d9a3cc50b957d124cdd --- /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 +#include + +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 &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 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 0000000000000000000000000000000000000000..7d7af63f7685c500a5a090218608a038c9611a44 --- /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 +#include +#include +#include +#include + +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 &msg); + void initiateSetup(const sp &msg); + void signalFlush(); + void signalResume(); + void initiateShutdown(bool keepComponentAllocated = false); + + void initiateAllocateComponent(const sp &msg); + void initiateConfigureComponent(const sp &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 mData; + sp mGraphicBuffer; + }; + + sp mNotify; + + sp mUninitializedState; + sp mLoadedState; + sp mLoadedToIdleState; + sp mIdleToExecutingState; + sp mExecutingState; + sp mOutputPortSettingsChangedState; + sp mExecutingToIdleState; + sp mIdleToLoadedState; + sp mFlushingState; + + AString mComponentName; + uint32_t mFlags; + uint32_t mQuirks; + sp mOMX; + IOMX::node_id mNode; + sp mDealer[2]; + + sp mNativeWindow; + + Vector mBuffers[2]; + bool mPortEOS[2]; + status_t mInputEOSResult; + + List > 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 &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 &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 &msg); + status_t setupH263EncoderParameters(const sp &msg); + status_t setupAVCEncoderParameters(const sp &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 &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 0000000000000000000000000000000000000000..392f968834377297830eccec7afc90fd49639906 --- /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 + +#include +#include + +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 &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 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 0000000000000000000000000000000000000000..70c47aeb7b9aea9faf0854c6fb34db165fe1e36e --- /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 +#include +#include +#include + +namespace android { + +class MediaSource; +class AudioTrack; +class AwesomePlayer; + +class AudioPlayer : public TimeSource { +public: + enum { + REACHED_EOS, + SEEK_COMPLETE + }; + + AudioPlayer(const sp &audioSink, + AwesomePlayer *audioObserver = NULL); + + virtual ~AudioPlayer(); + + // Caller retains ownership of "source". + void setSource(const sp &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 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 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 0000000000000000000000000000000000000000..f5466e80ba6aee5b35f6503a17f0c3614c21880b --- /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 +#include +#include +#include +#include + +#include + +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 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 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 0000000000000000000000000000000000000000..5a35358d46755c85f46cb24d846b22f68df27c20 --- /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 +#include +#include +#include +#include +#include +#include + +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 &camera, + const sp &proxy, + int32_t cameraId, + Size videoSize, + int32_t frameRate, + const sp& 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 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& source); + virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType, + const sp &data); + + private: + sp mSource; + }; + + // isBinderAlive needs linkToDeath to work. + class DeathNotifier: public IBinder::DeathRecipient { + public: + DeathNotifier() {} + virtual void binderDied(const wp& 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 mCamera; + sp mCameraRecordingProxy; + sp mDeathNotifier; + sp mSurface; + sp 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& camera, const sp& proxy, + int32_t cameraId, + Size videoSize, int32_t frameRate, + const sp& surface, + bool storeMetaDataInVideoBuffers); + + virtual void startCameraRecording(); + virtual void releaseRecordingFrame(const sp& 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 &data) {} + + virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType, + const sp &data); + +private: + friend class CameraSourceListener; + + Mutex mLock; + Condition mFrameAvailableCondition; + Condition mFrameCompleteCondition; + List > mFramesReceived; + List > mFramesBeingEncoded; + List mFrameTimes; + + int64_t mFirstFrameTimeUs; + int32_t mNumFramesDropped; + int32_t mNumGlitches; + int64_t mGlitchDurationThresholdUs; + bool mCollectStats; + bool mIsMetaDataStoredInVideoBuffers; + + void releaseQueuedFrames(); + void releaseOneRecordingFrame(const sp& frame); + + + status_t init(const sp& camera, const sp& proxy, + int32_t cameraId, Size videoSize, int32_t frameRate, + bool storeMetaDataInVideoBuffers); + + status_t initWithCameraAccess( + const sp& camera, const sp& proxy, + int32_t cameraId, Size videoSize, int32_t frameRate, + bool storeMetaDataInVideoBuffers); + + status_t isCameraAvailable(const sp& camera, + const sp& 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 0000000000000000000000000000000000000000..0936da2f3efcd10da7f2462c89d3a4e8b897c477 --- /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 + +#include +#include + +namespace android { + +class ICamera; +class IMemory; +class Camera; + +class CameraSourceTimeLapse : public CameraSource { +public: + static CameraSourceTimeLapse *CreateFromCamera( + const sp &camera, + const sp &proxy, + int32_t cameraId, + Size videoSize, + int32_t videoFrameRate, + const sp& 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 &camera, + const sp &proxy, + int32_t cameraId, + Size videoSize, + int32_t videoFrameRate, + const sp& 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 &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 createIMemoryCopy(const sp &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 0000000000000000000000000000000000000000..85ba9206835c229f7204b2443c1898c6ced6171e --- /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 + +#include +#include + +#include + +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 0000000000000000000000000000000000000000..00d583e531fd4c0ab49c580a3ca6f4e30f6b0dab --- /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 + +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +struct AMessage; +class String8; + +class DataSource : public RefBase { +public: + enum Flags { + kWantsPrefetching = 1, + kStreamedFromLocalHost = 2, + kIsCachingDataSource = 4, + kIsHTTPBasedSource = 8, + }; + + static sp CreateFromURI( + const char *uri, + const KeyedVector *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 *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 &source, String8 *mimeType, + float *confidence, sp *meta); + + static void RegisterSniffer(SnifferFunc func); + static void RegisterDefaultSniffers(); + + // for DRM + virtual sp DrmInitialization(const char *mime = NULL) { + return NULL; + } + virtual void getDrmInfo(sp &handle, DrmManagerClient **client) {}; + + virtual String8 getUri() { + return String8(); + } + + virtual String8 getMIMEType() const; + +protected: + virtual ~DataSource() {} + +private: + static Mutex gSnifferMutex; + static List 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 0000000000000000000000000000000000000000..d994cb3fa7217eee22305531809e8e0b576538a8 --- /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 + +#include +#include +#include +#include + +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 DrmInitialization(const char *mime); + + virtual void getDrmInfo(sp &handle, DrmManagerClient **client); + +protected: + virtual ~FileSource(); + +private: + int mFd; + int64_t mOffset; + int64_t mLength; + Mutex mLock; + + /*for DRM*/ + sp 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 0000000000000000000000000000000000000000..1b7e91b8661efedc290447f748704c398bc803a4 --- /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 + +namespace android { + +class DataSource; +class MediaBufferGroup; + +struct JPEGSource : public MediaSource { + JPEGSource(const sp &source); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~JPEGSource(); + +private: + sp 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 0000000000000000000000000000000000000000..a7c9ecf7c504412a02f0c621a4de81af4e447a01 --- /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 +#include +#include +#include + +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 &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& args); + + void onMessageReceived(const sp &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 mLooper; + sp > mReflector; + + bool mStarted; + + Vector > 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 &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 0000000000000000000000000000000000000000..0409b30746f51ad5aec124671dcbbe749a923e31 --- /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 + +#include +#include +#include + +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 &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& 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 mTracks; + + List 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 mSamples; // Sample data + + // Convenient constructor + Chunk(): mTrack(NULL), mTimeStampUs(0) {} + + Chunk(Track *track, int64_t timeUs, List samples) + : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { + } + + }; + struct ChunkInfo { + Track *mTrack; // Owner + List 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 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 0000000000000000000000000000000000000000..3d79596f3f4670a93da247d78ce98d1410d64e70 --- /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 + +#include +#include + +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); + + MediaBuffer(const sp &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() const; + + sp 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 mGraphicBuffer; + sp mBuffer; + + bool mOwnsData; + + sp 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 0000000000000000000000000000000000000000..04882926bc2bde769bc780c5b2d2006f05f7db3f --- /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 +#include +#include + +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 0000000000000000000000000000000000000000..0fc88e12110ef6e570a005d9cd5c7cbc7a330cf0 --- /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 +#include +#include + +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 CreateByType( + const sp &looper, const char *mime, bool encoder); + + static sp CreateByComponentName( + const sp &looper, const char *name); + + status_t configure( + const sp &format, + const sp &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 *format) const; + + status_t getInputBuffers(Vector > *buffers) const; + status_t getOutputBuffers(Vector > *buffers) const; + +protected: + virtual ~MediaCodec(); + virtual void onMessageReceived(const sp &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 mData; + sp mEncryptedData; + sp mNotify; + bool mOwnedByClient; + }; + + State mState; + sp mLooper; + sp mCodecLooper; + sp mCodec; + uint32_t mReplyID; + uint32_t mFlags; + sp mNativeWindow; + SoftwareRenderer *mSoftRenderer; + sp mOutputFormat; + + List mAvailPortBuffers[2]; + Vector mPortBuffers[2]; + + int32_t mDequeueInputTimeoutGeneration; + uint32_t mDequeueInputReplyID; + + int32_t mDequeueOutputTimeoutGeneration; + uint32_t mDequeueOutputReplyID; + + sp mCrypto; + + MediaCodec(const sp &looper); + + static status_t PostAndAwaitResponse( + const sp &msg, sp *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 &msg); + status_t onQueueInputBuffer(const sp &msg); + status_t onReleaseOutputBuffer(const sp &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 0000000000000000000000000000000000000000..14dc1b8da1767128deb3abed684ec34ca9033735 --- /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 +#include + +#include +#include +#include +#include + +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 mCodecInfos; + KeyedVector mCodecQuirks; + KeyedVector 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 0000000000000000000000000000000000000000..457d5d72e98cc00c03eb58e0e9629161dadef60a --- /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 0000000000000000000000000000000000000000..dd3bf2876999b6beb4776507252e709b00d24e29 --- /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 + +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 0000000000000000000000000000000000000000..94090eef26a3f19fb4008f0e26db2e95a75d07b8 --- /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 + +namespace android { + +class DataSource; +class MediaSource; +class MetaData; + +class MediaExtractor : public RefBase { +public: + static sp Create( + const sp &source, const char *mime = NULL); + + virtual size_t countTracks() = 0; + virtual sp getTrack(size_t index) = 0; + + enum GetTrackMetaDataFlags { + kIncludeExtensiveMetaData = 1 + }; + virtual sp getTrackMetaData( + size_t index, uint32_t flags = 0) = 0; + + // Return container specific meta-data. The default implementation + // returns an empty metadata object. + virtual sp 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 0000000000000000000000000000000000000000..3818e63ff4e9f651bbc8d5c28d69d2459a262368 --- /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 + +#include +#include +#include + +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 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 &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 0000000000000000000000000000000000000000..5cc8dcffe0d14b2c876589ed72e5361eadcb4597 --- /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 +#include + +namespace android { + +struct MediaSource; +struct MetaData; + +struct MediaWriter : public RefBase { + MediaWriter() + : mMaxFileSizeLimitBytes(0), + mMaxFileDurationLimitUs(0) { + } + + virtual status_t addSource(const sp &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& listener) { + mListener = listener; + } + + virtual status_t dump(int fd, const Vector& args) { + return OK; + } + +protected: + virtual ~MediaWriter() {} + int64_t mMaxFileSizeLimitBytes; + int64_t mMaxFileDurationLimitUs; + sp 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 0000000000000000000000000000000000000000..639446ead94a99990ba62adc3c56cf063dcc8484 --- /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 + +#include + +#include +#include +#include + +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 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 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 0000000000000000000000000000000000000000..97cc0cebda3e00f2d5d8c3ff6f8b97a10e95f953 --- /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 + +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) : + mSurfaceTextureClient(surfaceTextureClient) { } + + sp getNativeWindow() const { + return mSurfaceTextureClient; + } + + sp getSurfaceTextureClient() const { + return mSurfaceTextureClient; + } + +private: + const sp 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 0000000000000000000000000000000000000000..07c7be562bbb95d7149be835c53c83bce7fb6a61 --- /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 +#include +#include +#include + +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 *format) const; + + status_t selectTrack(size_t index); + + status_t seekTo(int64_t timeUs); + + status_t advance(); + status_t readSampleData(const sp &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 mSource; + size_t mTrackIndex; + status_t mFinalResult; + MediaBuffer *mSample; + int64_t mSampleTimeUs; + uint32_t mSampleFlags; + + uint32_t mTrackFlags; // bitmask of "TrackFlags" + }; + + sp mImpl; + + Vector 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 0000000000000000000000000000000000000000..2f14d06e8cf62b91ab1aec205004cee78b302eca --- /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 + +namespace android { + +class OMXClient { +public: + OMXClient(); + + status_t connect(); + void disconnect(); + + sp interface() { + return mOMX; + } + +private: + sp 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 0000000000000000000000000000000000000000..7d51deea9435638babe5da00edc4d2a42ed498e2 --- /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 +#include +#include +#include +#include + +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 Create( + const sp &omx, + const sp &meta, bool createEncoder, + const sp &source, + const char *matchComponentName = NULL, + uint32_t flags = 0, + const sp &nativeWindow = NULL); + + static void setComponentRole( + const sp &omx, IOMX::node_id node, bool isEncoder, + const char *mime); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + + virtual sp 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 *matchingCodecs, + Vector *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 mMem; + size_t mSize; + void *mData; + MediaBuffer *mMediaBuffer; + }; + + struct CodecSpecificData { + size_t mSize; + uint8_t mData[1]; + }; + + sp 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 mOutputFormat; + sp mSource; + Vector mCodecSpecificData; + size_t mCodecSpecificDataIndex; + + sp mDealer[2]; + + State mState; + Vector 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 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 mFilledBuffers; + Condition mBufferFilled; + + // Used to record the decoding time for an output picture from + // a video encoder. + List mDecodingTimeList; + + OMXCodec(const sp &omx, IOMX::node_id node, + uint32_t quirks, uint32_t flags, + bool isEncoder, const char *mime, const char *componentName, + const sp &source, + const sp &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& meta); + + status_t setupBitRate(int32_t bitRate); + status_t setupErrorCorrectionParameters(); + status_t setupH263EncoderParameters(const sp& meta); + status_t setupMPEG4EncoderParameters(const sp& meta); + status_t setupAVCEncoderParameters(const sp& meta); + status_t findTargetColorFormat( + const sp& 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& 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 &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 &inputFormat); + status_t initNativeWindow(); + + void initNativeWindowCrop(); + + void dumpPortStatus(OMX_U32 portIndex); + + status_t configureCodec(const sp &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 mProfileLevels; + Vector 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 &omx, + const char *mimeType, bool queryDecoders, bool hwCodecOnly, + Vector *results); + +status_t QueryCodecs( + const sp &omx, + const char *mimeType, bool queryDecoders, + Vector *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 0000000000000000000000000000000000000000..5c7cd47bf061656a10c90c03148a452cf023a4bd --- /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 + +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 0000000000000000000000000000000000000000..6510a597e9a44bc76c6246e059efe1b2354854cf --- /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 + +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 0000000000000000000000000000000000000000..936b0572c46bcc1bce6bde94c978049202a1e742 --- /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 + +#include +#include +#include +#include + +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 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* 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& listener); + + // getCurrentBuffer returns the buffer associated with the current image. + sp 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 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 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 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 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 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 0000000000000000000000000000000000000000..443673de46922c358fc4d1d0782d549e46d330a6 --- /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 + +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 0000000000000000000000000000000000000000..498b525c7bd92d6f7de0c5c5fdbc74e893531f03 --- /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 + +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 0000000000000000000000000000000000000000..439918cd5971dab0b496224a2b767738edae8cd5 --- /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 +#include + +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 &videoSource, + int32_t width, int32_t height); + + // MediaSource interface + virtual status_t start(MetaData *params = NULL); + + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + + virtual status_t pause(); + +private: + // Reference to the real video source. + sp 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 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 0000000000000000000000000000000000000000..ff70923f040a70ba502060a99f233de56afdd038 --- /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 + +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 0000000000000000000000000000000000000000..4e98618948a68b3e02e4397c9bff03f49bfb8263 --- /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 +#include + +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 0000000000000000000000000000000000000000..5f3a678a727adfc3919afb95d381ad14cd5353e8 --- /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 + +#include +#include +#include +#include +#include + +namespace android { + +struct AAtomizer { + static const char *Atomize(const char *name); + +private: + static AAtomizer gAtomizer; + + Mutex mLock; + Vector > 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 0000000000000000000000000000000000000000..9eceea3fdca7a167ac2f007a278cd0962697f995 --- /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 0000000000000000000000000000000000000000..5510b12aee8cceefa91d84edce167682b1fd4eda --- /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 + +#include +#include + +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 0000000000000000000000000000000000000000..28f0aed4f76391e38443bfd38d06c175c4e9f661 --- /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 +#include + +#include +#include + +namespace android { + +struct AMessage; + +struct ABuffer : public RefBase { + ABuffer(size_t capacity); + ABuffer(void *data, size_t capacity); + + void setFarewellMessage(const sp 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 meta(); + +protected: + virtual ~ABuffer(); + +private: + sp mFarewell; + sp 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 0000000000000000000000000000000000000000..450dcfe8bedf17e23c0901c28d3097c53b3f4cd4 --- /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 + +#include +#include +#include + +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 \ + 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 0000000000000000000000000000000000000000..b008b54a80e6be69af6ac00431cae624edea9dcd --- /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 +#include + +namespace android { + +struct AMessage; + +struct AHandler : public RefBase { + AHandler() + : mID(0) { + } + + ALooper::handler_id id() const { + return mID; + } + + sp looper(); + +protected: + virtual void onMessageReceived(const sp &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 0000000000000000000000000000000000000000..9d201b56a2b5aad1cdeab0326512f4ba4be2efe9 --- /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 + +namespace android { + +template +struct AHandlerReflector : public AHandler { + AHandlerReflector(T *target) + : mTarget(target) { + } + +protected: + virtual void onMessageReceived(const sp &msg) { + sp target = mTarget.promote(); + if (target != NULL) { + target->onMessageReceived(msg); + } + } + +private: + wp mTarget; + + AHandlerReflector(const AHandlerReflector &); + AHandlerReflector &operator=(const AHandlerReflector &); +}; + +} // 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 0000000000000000000000000000000000000000..d2e6b28df556f35edb3a7ed61e0a2c39d45ef914 --- /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 + +namespace android { + +struct AState : public RefBase { + AState(const sp &parentState = NULL); + + sp parentState(); + +protected: + virtual ~AState(); + + virtual void stateEntered(); + virtual void stateExited(); + + virtual bool onMessageReceived(const sp &msg) = 0; + +private: + friend struct AHierarchicalStateMachine; + + sp mParentState; + + DISALLOW_EVIL_CONSTRUCTORS(AState); +}; + +struct AHierarchicalStateMachine : public AHandler { + AHierarchicalStateMachine(); + +protected: + virtual ~AHierarchicalStateMachine(); + + virtual void onMessageReceived(const sp &msg); + + // Only to be called in response to a message. + void changeState(const sp &state); + +private: + sp 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 0000000000000000000000000000000000000000..70e0c5e6b39267d042b35c5758805d68d114afa8 --- /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 +#include +#include +#include +#include +#include +#include + +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 &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 mMessage; + }; + + Mutex mLock; + Condition mQueueChangedCondition; + + AString mName; + + List mEventQueue; + + struct LooperThread; + sp mThread; + bool mRunningLocally; + + void post(const sp &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 0000000000000000000000000000000000000000..2e5fd73b52c08bce5b9473ba65f5d585ca5e4fc5 --- /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 +#include + +namespace android { + +struct ALooperRoster { + ALooperRoster(); + + ALooper::handler_id registerHandler( + const sp looper, const sp &handler); + + void unregisterHandler(ALooper::handler_id handlerID); + + status_t postMessage(const sp &msg, int64_t delayUs = 0); + void deliverMessage(const sp &msg); + + status_t postAndAwaitResponse( + const sp &msg, sp *response); + + void postReply(uint32_t replyID, const sp &reply); + + sp findLooper(ALooper::handler_id handlerID); + +private: + struct HandlerInfo { + wp mLooper; + wp mHandler; + }; + + Mutex mLock; + KeyedVector mHandlers; + ALooper::handler_id mNextHandlerID; + uint32_t mNextReplyID; + Condition mRepliesCondition; + + KeyedVector > mReplies; + + status_t postMessage_l(const sp &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 0000000000000000000000000000000000000000..e5416e4fc9d7842299ca35d879801352f78d69ab --- /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 +#include +#include +#include + +namespace android { + +struct ABuffer; +struct AString; +struct Parcel; + +struct AMessage : public RefBase { + AMessage(uint32_t what = 0, ALooper::handler_id target = 0); + + static sp 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 &obj); + void setBuffer(const char *name, const sp &buffer); + void setMessage(const char *name, const sp &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 *obj) const; + bool findBuffer(const char *name, sp *buffer) const; + bool findMessage(const char *name, sp *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 *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 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 &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 0000000000000000000000000000000000000000..0f8f1e159d3c272154cf43c09425b3e7cbf6b878 --- /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 + +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 0000000000000000000000000000000000000000..e340b8940117a564fab6369ec96efd54bb2cd934 --- /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 + +namespace android { + +struct ABuffer; +struct AString; + +sp 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 0000000000000000000000000000000000000000..f6083a93a5707f1fa5244f1af04dbf4aac718219 --- /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 + +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 0000000000000000000000000000000000000000..b9752df5a7e6c153c8bbaadca89bec31173518da --- /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 // for DISALLOW_* macro +#include // for status_t +#include +#include + +namespace android { + +class ALooper; +class MediaPlayerBase; +class MediaSource; +class Parcel; +class TimedTextPlayer; +class TimedTextSource; + +class TimedTextDriver { +public: + TimedTextDriver(const wp &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& 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 mLooper; + sp mPlayer; + wp mListener; + + // Variables to be guarded by mLock. + State mState; + int32_t mCurrentTrackIndex; + Vector > 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 0000000000000000000000000000000000000000..ee4149270ae295ecb5eff051d112c44e78ea47cc --- /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 0000000000000000000000000000000000000000..abcf41df0c6976c9c53c13d27672666202b41f6d --- /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 0000000000000000000000000000000000000000..a3a99a49820e958cd0f51b9437d9b99915afe47e --- /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 +#include + +#include + +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 0000000000000000000000000000000000000000..af2db9379f31da9d6767dbb79620695ab368f312 --- /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 +#include + +#include + +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 0000000000000000000000000000000000000000..0ecc34819bd6cad5e02292a783b1a5bcfd40fd6f --- /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 +#include +#include +#include + +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 0000000000000000000000000000000000000000..526f17b44a5c9ed9279df9109897c3c199f5cf99 --- /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 0000000000000000000000000000000000000000..28b43acff16a48f289c484628d57518a03509f4a --- /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 + +#include +#include + +#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 +{ + public: + BpCommonClock(const sp& impl) + : BpInterface(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(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(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& 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& 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(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(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 listener = + interface_cast(data.readStrongBinder()); + status_t status = registerListener(listener); + reply->writeInt32(status); + return OK; + } break; + + case UNREGISTER_LISTENER: { + CHECK_INTERFACE(ICommonClock, data, reply); + sp listener = + interface_cast(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 +{ + public: + BpCommonClockListener(const sp& impl) + : BpInterface(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 0000000000000000000000000000000000000000..8eb37cb8064ac3068383a21257e2644902498a78 --- /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 + +#include +#include + +#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 +{ + public: + BpCommonTimeConfig(const sp& impl) + : BpInterface(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(reply.readInt32()); + } + } + + return status; + } + + virtual status_t setMasterElectionPriority(uint8_t priority) { + Parcel data, reply; + data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor()); + data.writeInt32(static_cast(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(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(priority)); + } + return OK; + } break; + + case SET_MASTER_ELECTION_PRIORITY: { + CHECK_INTERFACE(ICommonTimeConfig, data, reply); + uint8_t priority = static_cast(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(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 0000000000000000000000000000000000000000..8d8556cb7f54ddfe56601b31ff0c54d934d41ca1 --- /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 + +#include +#include +#include + +namespace android { + +Mutex CCHelper::lock_; +sp CCHelper::common_clock_; +sp 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 0000000000000000000000000000000000000000..a7c61fc76aa5eec1c01033e67e80faf2916d0ccf --- /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 + +#include +#include + +#include +#include +#include +#include +#include + +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(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 0000000000000000000000000000000000000000..65391711b0bde808b6de81d1857601a451bc055d --- /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 +#include + +#include + +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(addr); + p->writeInt32(AF_INET); + p->writeInt32(ntohl(s->sin_addr.s_addr)); + p->writeInt32(static_cast(ntohs(s->sin_port))); + } break; + + case AF_INET6: { + const struct sockaddr_in6* s = + reinterpret_cast(addr); + const int32_t* a = + reinterpret_cast(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(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(addr); + s->sin_addr.s_addr = htonl(p->readInt32()); + s->sin_port = htons(static_cast(p->readInt32())); + } break; + + case AF_INET6: { + struct sockaddr_in6* s = + reinterpret_cast(addr); + int32_t* a = reinterpret_cast(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(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 0000000000000000000000000000000000000000..ce79d0d74cecf143fc625715b2ffafd75bad6ec0 --- /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 + +#include +#include + +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 0000000000000000000000000000000000000000..6c927bae3c07a70fb8a30bb0db970629bf850666 --- /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 0000000000000000000000000000000000000000..bebba54e9b9e96ad3af506b0a97a695507cbb344 --- /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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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(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(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(decoded_sample->data()); + uint32_t decoded_amt = decoded_sample->range_length(); + decoded_data += decoded_sample->range_offset(); + + sp 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(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& 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(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 0000000000000000000000000000000000000000..4d57e49f514fb211a29f2b250893b1dbec9fd8d4 --- /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 + +#include +#include +#include +#include +#include + +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& 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 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 format_; + int32_t format_channels_; // channel count, not channel mask + int32_t format_sample_rate_; + + sp decoder_; + OMXClient& omx_; + Mutex init_lock_; + + sp 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 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 0000000000000000000000000000000000000000..9dd79fd2dd8365592659fac75784574b451f341d --- /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 +#include +#include + +#include "aah_rx_player.h" + +namespace android { + +const uint32_t AAH_RXPlayer::kRTPRingBufferSize = 1 << 10; + +sp createAAH_RXPlayer() { + sp 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 *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) { + return OK; +} + +status_t AAH_RXPlayer::setVideoSurfaceTexture( + const sp& 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 sm = defaultServiceManager(); + sp 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(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 0000000000000000000000000000000000000000..ba5617eb7daedd2b2a8148041ad9f04f0f305766 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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* + headers); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSurface(const sp& surface); + virtual status_t setVideoSurfaceTexture(const sp& + 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 substream_meta_; + + MediaBuffer* buffer_in_progress_; + uint32_t expected_buffer_size_; + uint32_t buffer_filled_; + + Vector aux_data_in_progress_; + uint32_t aux_data_expected_size_; + + sp decoder_; + + static int64_t kAboutToUnderflowThreshold; + + DISALLOW_EVIL_CONSTRUCTORS(Substream); + }; + + typedef DefaultKeyedVector< uint32_t, sp > 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 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 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 0000000000000000000000000000000000000000..d6b31fd4a455cbd53b76484238792b03bc74c08c --- /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 + +#include +#include +#include +#include +#include + +#include + +#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(U16_AT(data)); +} + +static inline int32_t fetchInt32(uint8_t* data) { + return static_cast(U32_AT(data)); +} + +static inline int64_t fetchInt64(uint8_t* data) { + return static_cast(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(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(&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(res)); + goto bailout; + } + + // Fetch the data. + from_len = sizeof(from); + res = recvfrom(sock_fd_, pb->data_, pb->length_, 0, + reinterpret_cast(&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(res), + static_cast(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(amt)); + goto drop_packet; + } + + // Check to see if this is the special case of a NAK packet. + nak_magic = ntohl(*(reinterpret_cast(data))); + if (nak_magic == kRetransNAKMagic) { + // Looks like a NAK packet; make sure its long enough. + + if (amt < static_cast(sizeof(RetransRequest))) { + ALOGV("Dropping packet, too short to contain NAK payload" + " (%u bytes)", static_cast(amt)); + goto drop_packet; + } + + SeqNoGap gap; + RetransRequest* rtr = reinterpret_cast(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; + 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(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(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( + 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 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 substreams_to_remove; + for (size_t i = 0; i < substreams_.size(); ++i) { + sp 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(&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(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 0000000000000000000000000000000000000000..779405e02d2e4496201d6f2bb25ea4380f991189 --- /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 + +#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(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( + 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(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 0000000000000000000000000000000000000000..18b0e2b290ebd4ea5a3cd7391b08cf85fcbef804 --- /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 + +#include +#include +#include +#include +#include +#include + +#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(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 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(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(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(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 0000000000000000000000000000000000000000..4cd6e4715b57b699a6e1dec05a5e8a8c91fdba36 --- /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 + +#include +#include + +#include + +#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( + 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( + 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(buf) = htons(val); + buf += 2; +} + +void TRTPPacket::writeU32(uint8_t*& buf, uint32_t val) { + *reinterpret_cast(buf) = htonl(val); + buf += 4; +} + +void TRTPPacket::writeU64(uint8_t*& buf, uint64_t val) { + buf[0] = static_cast(val >> 56); + buf[1] = static_cast(val >> 48); + buf[2] = static_cast(val >> 40); + buf[3] = static_cast(val >> 32); + buf[4] = static_cast(val >> 24); + buf[5] = static_cast(val >> 16); + buf[6] = static_cast(val >> 8); + buf[7] = static_cast(val); + buf += 8; +} + +void TRTPPacket::writeTRTPHeader(uint8_t*& buf, + bool isFirstFragment, + int totalPacketLen) { + // RTP header + writeU8(buf, + ((mVersion & 0x03) << 6) | + (static_cast(mPadding) << 5) | + (static_cast(mExtension) << 4) | + (mCsrcCount & 0x0F)); + writeU8(buf, + (static_cast(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(hasAux) << 4) | + (static_cast(mRandomAccessPoint) << 3) | + (static_cast(mDropable) << 2) | + (static_cast(mDiscontinuity) << 1) | + (static_cast(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 0000000000000000000000000000000000000000..7f78ea0b11cb2072647b77a5bf4abadb7c3700c5 --- /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 +#include +#include +#include + +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 0000000000000000000000000000000000000000..974805b306d758ad757f4e53f642516e6694d53e --- /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 + +#define __STDC_FORMAT_MACROS +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 createAAH_TXPlayer() { + sp ret = new AAH_TXPlayer(); + return ret; +} + +template 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 *headers) { + Mutex::Autolock autoLock(mLock); + return setDataSource_l(url, headers); +} + +status_t AAH_TXPlayer::setDataSource_l( + const char *url, + const KeyedVector *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 = new FileSource(dup(fd), offset, length); + + status_t err = dataSource->initCheck(); + + if (err != OK) { + return err; + } + + mFileSource = dataSource; + + sp extractor = MediaExtractor::Create(dataSource); + + if (extractor == NULL) { + return UNKNOWN_ERROR; + } + + return setDataSource_l(extractor); +} + +status_t AAH_TXPlayer::setVideoSurface(const sp& surface) { + return OK; +} + +status_t AAH_TXPlayer::setVideoSurfaceTexture( + const sp& 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; + + 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 extractor = MediaExtractor::Create(dataSource); + + if (extractor == NULL) { + return UNKNOWN_ERROR; + } + + return setDataSource_l(extractor); +} + +status_t AAH_TXPlayer::setDataSource_l(const sp &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 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 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((sample_rate >> 24) & 0xFF); + tmp[1] = static_cast((sample_rate >> 16) & 0xFF); + tmp[2] = static_cast((sample_rate >> 8) & 0xFF); + tmp[3] = static_cast((sample_rate ) & 0xFF); + tmp[4] = static_cast((channel_count >> 24) & 0xFF); + tmp[5] = static_cast((channel_count >> 16) & 0xFF); + tmp[6] = static_cast((channel_count >> 8) & 0xFF); + tmp[7] = static_cast((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 packet = new TRTPControlPacket(); + packet->setClockTransform(mCurrentClockTransform); + packet->setCommandID(TRTPControlPacket::kCommandNop); + queuePacketToSender_l(packet); +} + +void AAH_TXPlayer::sendEOS_l() { + sp 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(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 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(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((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(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 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& packet) { + if (mAAH_Sender == NULL) { + return; + } + + sp 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 0000000000000000000000000000000000000000..2e4b1f7ec504252aa2dc727a7b4481e0e4b0c9ba --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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* + headers); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSurface(const sp& surface); + virtual status_t setVideoSurfaceTexture(const sp& + 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 *headers); + status_t setDataSource_l(const sp& 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& packet); + + Mutex mLock; + + TimedEventQueue mQueue; + bool mQueueStarted; + + sp mBufferingEvent; + bool mBufferingEventPending; + + uint32_t mFlags; + uint32_t mExtractorFlags; + + String8 mUri; + KeyedVector mUriHeaders; + + sp mFileSource; + + sp mAsyncPrepareEvent; + Condition mPreparedCondition; + status_t mPrepareResult; + + bool mIsSeeking; + int64_t mSeekTimeUs; + + sp mPumpAudioEvent; + bool mPumpAudioEventPending; + + sp mConnectingDataSource; + sp mCachedSource; + + sp mAudioSource; + TRTPAudioPacket::TRTPAudioCodecType mAudioCodec; + sp mAudioFormat; + uint8_t* mAudioCodecData; + size_t mAudioCodecDataSize; + + int64_t mDurationUs; + int64_t mBitrate; + + sp 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 0000000000000000000000000000000000000000..08e32d26b00ae027a45d58f5b13cce4856354ed1 --- /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 + +#include +#include +#include +#include +#include + +#include +#include + +#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::sInstance; +uint32_t AAH_TXSender::sNextEpoch; +bool AAH_TXSender::sNextEpochValid = false; + +AAH_TXSender::AAH_TXSender() : mSocket(-1) { + mLastSentPacketTime = systemTime(); +} + +sp AAH_TXSender::GetInstance() { + Mutex::Autolock autoLock(sLock); + + sp 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(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(&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 trimMessage = new AMessage(kWhatTrimRetryBuffers, + handlerID()); + trimMessage->post(kRetryTrimIntervalUs); + + sp 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& 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& msg) { + sp obj; + CHECK(msg->findObject(kSendPacketTRTPPacket, &obj)); + sp packet = static_cast(obj.get()); + + uint32_t ipAddr; + CHECK(msg->findInt32(kSendPacketIPAddr, + reinterpret_cast(&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& 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 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 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 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 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 +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(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(startSeq - retryFirstSeq); + } else { + startIndex = -1; + } + + int endIndex; + if (withinIntervalWithRollover(endSeq, retryFirstSeq, retryLastSeq)) { + endIndex = static_cast(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& 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 +CircularBuffer::CircularBuffer(size_t capacity) + : mCapacity(capacity) + , mHead(0) + , mTail(0) + , mFillCount(0) { + mBuffer = new T[capacity]; +} + +template +CircularBuffer::~CircularBuffer() { + delete [] mBuffer; +} + +template +void CircularBuffer::push_back(const T& item) { + if (this->isFull()) { + this->pop_front(); + } + mBuffer[mHead] = item; + mHead = (mHead + 1) % mCapacity; + mFillCount++; +} + +template +void CircularBuffer::pop_front() { + CHECK(!isEmpty()); + mBuffer[mTail] = T(); + mTail = (mTail + 1) % mCapacity; + mFillCount--; +} + +template +size_t CircularBuffer::size() const { + return mFillCount; +} + +template +bool CircularBuffer::isFull() const { + return (mFillCount == mCapacity); +} + +template +bool CircularBuffer::isEmpty() const { + return (mFillCount == 0); +} + +template +const T& CircularBuffer::itemAt(size_t index) const { + CHECK(index < mFillCount); + return mBuffer[(mTail + index) % mCapacity]; +} + +template +const T& CircularBuffer::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 0000000000000000000000000000000000000000..74206c49b28bdf9a367747004942d21aea18c85a --- /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 +#include +#include +#include + +#include "aah_tx_packet.h" +#include "pipe_event.h" + +namespace android { + +template 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 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 sInstance; + static uint32_t sNextEpoch; + static bool sNextEpochValid; + + static uint32_t getNextEpoch(); + + typedef CircularBuffer > 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; + void onMessageReceived(const sp& msg); + void onSendPacket(const sp& msg); + void doSendPacket_l(const sp& packet, + const Endpoint& endpoint); + void trimRetryBuffers(); + void sendHeartbeats(); + bool shouldSendHeartbeats_l(); + + sp mLooper; + sp > mReflector; + + int mSocket; + nsecs_t mLastSentPacketTime; + + DefaultKeyedVector 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 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 0000000000000000000000000000000000000000..b8e696080ca9b21a890107515696ae2430a88ff7 --- /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 + +#include +#include +#include +#include + +#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 0000000000000000000000000000000000000000..e53b0fdb74c0e9a24f2508927c12d464cf456d85 --- /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 + +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 0000000000000000000000000000000000000000..ce25bc804c6e699f88f40367782a1f6a2106266d --- /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 { +# { +# 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 { +# { +# library +# 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 { +# { +# { +# { +# param { +# int|short|float|bool|string +# [ int|short|float|bool|string ] +# ... +# } +# value { +# int|short|float|bool|string +# [ int|short|float|bool|string ] +# ... +# } +# } +# { } +# ... +# } +# ... +# } +# ... +# } + +# +# 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 0000000000000000000000000000000000000000..95ca6fd11c9da7c2d4da25ee1aebaaeed0de5ef2 --- /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 0000000000000000000000000000000000000000..a325172a9c72da6dcfee9d7f7a1baca2990d461e --- /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 +#include +#include +#include +#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 0000000000000000000000000000000000000000..4176b5adead2a8a24b56b2c8bea2cd23819294da --- /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 +#include +#include + +/*------------------------------------ + * 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 0000000000000000000000000000000000000000..6e69151a4087c1b5697fa3b89a125edc2c878111 --- /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 0000000000000000000000000000000000000000..59cd9e3c3bf1ca3bc20f4193cf732e9fa705092c --- /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 +#include +#include + +#include +#include +#include + +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 0000000000000000000000000000000000000000..c1d4319798d5d71265ae0a7aa4972fa62e051ad5 --- /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 +#include +#include +#include + +#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 0000000000000000000000000000000000000000..f49267e527842454bd4909a43e7cbfa85bea2271 --- /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 0000000000000000000000000000000000000000..228977d0e99f6d579b4f8056a8d599ced2e98a72 --- /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 0000000000000000000000000000000000000000..94a7869b6737448cf1eb6534567d2d14a6c2c8cf --- /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 0000000000000000000000000000000000000000..ab2a832d5b37c0f52c9110ff924424ac51cea20f --- /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 0000000000000000000000000000000000000000..3b3c07c739ba04858e1320f9ee5b34361d5370a7 --- /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; iRegion[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 0000000000000000000000000000000000000000..8339d3c52cf82414f6fd476549eac5ff01fee063 --- /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 0000000000000000000000000000000000000000..69d79d2e49956c5f7e44e0c2018a97d39fbae8a5 --- /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 0000000000000000000000000000000000000000..f5d229eb15b4c24821db87bd55dd2e93093e3e78 --- /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 0000000000000000000000000000000000000000..476e6a0b34815a52a15e35e08830bef28fb3e999 --- /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 0000000000000000000000000000000000000000..1ff2a2cf7bc8d150d62384437af5167754f8196d --- /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 0000000000000000000000000000000000000000..07b7f0e128befb277c7abd79967e0f2b578448c6 --- /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 0000000000000000000000000000000000000000..6cbee7d1fdd0258824dd5ccb9bf6ec7f380b6a55 --- /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 0000000000000000000000000000000000000000..f578db93aea244d15c0a744676ea6fdbbf417117 --- /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 0000000000000000000000000000000000000000..72564d4cfc49f34961f001c9cb5a061228e8bea9 --- /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; iEQNB_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; iNewParams.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 0000000000000000000000000000000000000000..20370b7ea236ee48d639fadf646ce3eafc4393b2 --- /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; iMaxBlockSize) & 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; iRegion[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; iRegion[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 0000000000000000000000000000000000000000..2d1cf427f20022f189bae67e7144c353efdf157c --- /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 0000000000000000000000000000000000000000..794271bd5605b657daed6a2e540148febdbd0d68 --- /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 0000000000000000000000000000000000000000..e14f9091109cdf3d8ac220e7cb2807b97c1ced68 --- /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 0000000000000000000000000000000000000000..a7601ffb2d21cb5e261264ff8a0e6bdea275b42c --- /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 0000000000000000000000000000000000000000..2080d6494374db098d78ac536f6c72116cb47063 --- /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 0000000000000000000000000000000000000000..7ac7fbd2e4e8ee28c60f9801f84b69f5ec5480ad --- /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 0000000000000000000000000000000000000000..4cb8aa2cd066c4c1513ef3f9a6f3cb87b166e7b2 --- /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 0000000000000000000000000000000000000000..229701a77fc38481b9d64427796e3e3dba81ad3e --- /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 0000000000000000000000000000000000000000..c6954f220fda2d00ef358f9176c0276e1ca5ae33 --- /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 0000000000000000000000000000000000000000..ceccd7b540cce90e91a0e0c8769bb91039c8989f --- /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 0000000000000000000000000000000000000000..97d13a50f647dbe030d5d87d2553127c0668da78 --- /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 0000000000000000000000000000000000000000..81e288cf4ddec934efee548daf777833e87793a9 --- /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 0000000000000000000000000000000000000000..81655dd90732b42366d2db8302aa8291790a2d7e --- /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 0000000000000000000000000000000000000000..89deb0deacb18c5eebe3139c1360a1d1f1bf05a1 --- /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 0000000000000000000000000000000000000000..3d62704756917dd34d558f4f4b0a99ebd0bc80d8 --- /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 0000000000000000000000000000000000000000..2b791bdd6832ed5bdf0625e4bf695907d84e7237 --- /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 0000000000000000000000000000000000000000..920b5152e481a10e7ce8823ed73b9a05c4c0be05 --- /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> 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 0000000000000000000000000000000000000000..9128b8210ecd41bcdb5a0ff2c118f848e77ce5f8 --- /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 0000000000000000000000000000000000000000..6978fe78f0384d69d0bb46fac5d9be02e58d8376 --- /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 0000000000000000000000000000000000000000..69d357eda47c0f5e7ad66e87474497428da0260a --- /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 0000000000000000000000000000000000000000..f4c5757d3bfb1fe337a6a48dacf581761daee2a4 --- /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 0000000000000000000000000000000000000000..88914ad9113b3b062833f90c925bd45c50d1b892 --- /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 0000000000000000000000000000000000000000..980539cc51d4d16841454f15877495ac61041a2a --- /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 0000000000000000000000000000000000000000..ba1a42f41ece2d4f7d34e2d0b74dfb384901caeb --- /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 0000000000000000000000000000000000000000..e833218815323b98d0323d1252a63ed446aae276 --- /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 0000000000000000000000000000000000000000..9cca6271bd3563d2c365955c116480afaf4a8a18 --- /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 0000000000000000000000000000000000000000..b09c1aad50be878c0bca93409bded936872ad8ae --- /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 0000000000000000000000000000000000000000..93679124ece3894d1d8a95fa178fbfff96b3a440 --- /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 0000000000000000000000000000000000000000..5cc1ce2b59a1e65e22285a5426371790245f3b34 --- /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 0000000000000000000000000000000000000000..f2f8c6b9228a5f6d5da671f82cd72a3a4994a9c6 --- /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 0000000000000000000000000000000000000000..baf0c1a5147f74ed5f365a845f080673e9ce1b44 --- /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 0000000000000000000000000000000000000000..909c69922ecc293cc9946b796b6b0daf6e8ac2da --- /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 0000000000000000000000000000000000000000..92f6caf3782193ee51301255f6953df8bd4ebf99 --- /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 0000000000000000000000000000000000000000..aea10f08eeda353c73fbe64a4ac5b3bc5a149982 --- /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 0000000000000000000000000000000000000000..1d6be4e1df451444ba275ad8f12001550b14c901 --- /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 0000000000000000000000000000000000000000..972e7048d0bcf44692552e1375a8790c36f46ee7 --- /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 0000000000000000000000000000000000000000..e056373cc585b07af1f521835fe0a85c316374ad --- /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 0000000000000000000000000000000000000000..0a8ac3530ff4a4fabd5733370b5916ce1a8edcfe --- /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 0000000000000000000000000000000000000000..7d42cede04a0b99efed0fc200398ffd05ef9ec3a --- /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 0000000000000000000000000000000000000000..4a0cce44d702a41f93be55e62c5728a6bd00609c --- /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 0000000000000000000000000000000000000000..052e2a03da524b04a3f4b1ccc4b1016d6453f3c8 --- /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 0000000000000000000000000000000000000000..8c741e1ae6eb89ef5b8c0779265b2b96ee942d30 --- /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 0000000000000000000000000000000000000000..4f0cf67e4724cfafdd146f5d789cae68db933e29 --- /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 0000000000000000000000000000000000000000..4591ee0ad7cff080e79ec174a1887e006c2198e8 --- /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 0000000000000000000000000000000000000000..fd8212e418c92e49c9df18af861bd0094bc2c4a1 --- /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 0000000000000000000000000000000000000000..1709f713d5565fac9abeb4021edc370b1977dea5 --- /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 0000000000000000000000000000000000000000..747af6a57dc55e2990ffac34f937397b7e8ee7ac --- /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 0000000000000000000000000000000000000000..06a21c311fb6b5b375ad7e794ae88bd680614733 --- /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 0000000000000000000000000000000000000000..20404ad7ce1a49a8efc5bfa37ec342bb943bece3 --- /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 0000000000000000000000000000000000000000..bf69e35ac9d98513528b3676a51e4dc44e2186a2 --- /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 0000000000000000000000000000000000000000..3471f05754542c06f42e59d6f635d503451b9fab --- /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 0000000000000000000000000000000000000000..709c304c5e6feb16e167c96febd5367ac7327199 --- /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 0000000000000000000000000000000000000000..49fa184a9840fce5eb03e8cdd1d65a8700ec88a6 --- /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 0000000000000000000000000000000000000000..468a88dc90e0ac39f057e841f80c3180ef390036 --- /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 0000000000000000000000000000000000000000..89a4e68c9683cfcef379e9acd057bcd3c7c1f890 --- /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 0000000000000000000000000000000000000000..2e20d79a96eb37c94a38f35623b6d00d5e1c75fd --- /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 0000000000000000000000000000000000000000..7e3182d5fe3c3627f3310b3aad95d6f3191b2853 --- /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> 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 0000000000000000000000000000000000000000..809cddc46e81cff0f07c4ccbe62695aba8066818 --- /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= 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 0000000000000000000000000000000000000000..de77361895deb25bfe776e00d8a8e4e230e459fe --- /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 0000000000000000000000000000000000000000..96252cc35a8bf9f5354b7d2b46f610f141d6ef98 --- /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 0000000000000000000000000000000000000000..516ca8349886b6bdb1c7e1627027e0b2dc204bcb --- /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 0000000000000000000000000000000000000000..0f1d5bc40b2aa197658f0c463516d946ce4e61d8 --- /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 0000000000000000000000000000000000000000..136e4f6d2dcad0442e76fafdf9bca95a9447a3dc --- /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 0000000000000000000000000000000000000000..94ad48caabf11fa357955c1a4554e67e42b6919c --- /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 0000000000000000000000000000000000000000..8388050a0dd923b76df9586d942e0000b90c0951 --- /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 0000000000000000000000000000000000000000..a19c32c7904f1f3c6a010e0ecf804096a547cc71 --- /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 0000000000000000000000000000000000000000..46407437a741d941a4e1fbeb8994ceb18de18b61 --- /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 0000000000000000000000000000000000000000..4d32df1dcdb5d242c956be11da1f6a0b4b064d62 --- /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 0000000000000000000000000000000000000000..7975e8bc0ee477e5181adc3bb6d9b24f2a2e95e3 --- /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 0000000000000000000000000000000000000000..b758ee71654f955618f61ec7cc4b1acaa3f38831 --- /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 0000000000000000000000000000000000000000..8bb292ffc7b723d40b5af8a3e36f9cdb91793601 --- /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 0000000000000000000000000000000000000000..481df84e20c7c7cca44e87d892b377e42bade78b --- /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 0000000000000000000000000000000000000000..9f09e4d3d75da422b79a2cd6e9f0b5189831663c --- /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 0000000000000000000000000000000000000000..8c9980d921e13c06f9c9eb5c154e0d67c7432185 --- /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 0000000000000000000000000000000000000000..9b938bd42dc832e3762388587641d75cec91dc36 --- /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 0000000000000000000000000000000000000000..3d39b93cec11bc60a37dfde81d5028a8ea72ee73 --- /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 0000000000000000000000000000000000000000..2daf74a2d965f02d491ad409e76074149065d1b1 --- /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 0000000000000000000000000000000000000000..caa09513e45aa69227932750441f312d404512de --- /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) + 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 0000000000000000000000000000000000000000..09ec427ed4ea4b420863d4ec7aff5979e2731eed --- /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) + CurrentL = TargetL; + } + else + { + CurrentL -= DeltaL; /* Q31 + Q31 into Q31*/ + if (CurrentL < TargetL) + CurrentL = TargetL; + } + + 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) + CurrentL = TargetL; + } + else + { + CurrentL -= DeltaL; /* Q31 + Q31 into Q31*/ + if (CurrentL < TargetL) + CurrentL = TargetL; + } + + 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 0000000000000000000000000000000000000000..f1a9ca3abb5fa3709f11b72187a28cb1062c288f --- /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) + 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 0000000000000000000000000000000000000000..0052dd76c00fc25cff0ce87a2d90677bbefab02c --- /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 0000000000000000000000000000000000000000..f443c8f7c398c2d0ea97503a2f0c0af95d69b113 --- /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 0000000000000000000000000000000000000000..c8dcad702bf9f0637fb2d8342ab09df069e20562 --- /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 0000000000000000000000000000000000000000..7240705980e4bca551eca5feed9e009b12503420 --- /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 0000000000000000000000000000000000000000..980c78385e15fb011656ba36a7542bb951916692 --- /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 0000000000000000000000000000000000000000..b5ae264b566dfee4711b0a24c71642770deb90f2 --- /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 0000000000000000000000000000000000000000..dc2f8e9e2c4f40c2c2177bf38c83343d154c53af --- /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 0000000000000000000000000000000000000000..449e7b1fc62d5df549e0253438f527cac3aa33a0 --- /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 0000000000000000000000000000000000000000..294e05c09c8d513f345a3b1c0789b1a865dc3e09 --- /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 0000000000000000000000000000000000000000..5efa501a1085fbd8da906bb65a13a024641fb0c9 --- /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 0000000000000000000000000000000000000000..4c1c8b27d4f0d75f51b8d470d48523f14191e028 --- /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 0000000000000000000000000000000000000000..8d5304e7bc03d332b38b0eafd19c7d79b6636251 --- /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 0000000000000000000000000000000000000000..6d8fe4605757a62835f8ae574d99bd1d7bcf8992 --- /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 0000000000000000000000000000000000000000..86ec951e172168a5d8b07f375c9c49c25fdf6cb2 --- /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 0000000000000000000000000000000000000000..f3b9b3c00b37b0c282cf90f7b0f71cf5e1b51665 --- /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 0000000000000000000000000000000000000000..6846d49eb6993f3ab6f522ed163f0fdb5dfd3882 --- /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 0000000000000000000000000000000000000000..809d904efaff3e14b147c90139bd2983c9d49b0b --- /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 0000000000000000000000000000000000000000..a6d7db295e3c044b7778d5cf6f7251d829945153 --- /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<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 0000000000000000000000000000000000000000..a935cfe70fa965f5aff0b0c3082ffb04d454f618 --- /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 0000000000000000000000000000000000000000..480944f844d26560ab3b9d46869bbe50a90f1604 --- /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 0000000000000000000000000000000000000000..f88ca0ea4d9d5fdcf2dd0d05fd9404ef57546ba2 --- /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 0000000000000000000000000000000000000000..2f1e5914da77c7d140df0f57d09d9ebd1b1ed1b7 --- /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 0000000000000000000000000000000000000000..26297e72093f8208c8ef881e914a058e87334645 --- /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 0000000000000000000000000000000000000000..ef04ae81dd10598d4b4a3afa3d450c6f5fa07c0d --- /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 0000000000000000000000000000000000000000..f28f366be07651d047e3337c16d6434042553aef --- /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 0000000000000000000000000000000000000000..73c26ed1bacc8cc28e8da98555ea6bc6378a86d3 --- /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 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 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 0000000000000000000000000000000000000000..ca88b04a8f2c046de39e7541815e4ce946c07cea --- /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 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 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 0000000000000000000000000000000000000000..2e0a099089ffd606a89dd4766667543756421701 --- /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 0000000000000000000000000000000000000000..607073c48a0b03b296a14e6a0950e72a476c8644 --- /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 0000000000000000000000000000000000000000..ead798de7b87695922f97f6611910f5b80d6aa8f --- /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 0000000000000000000000000000000000000000..c09ec0f6056d2727aa21bce423a699214dde52fa --- /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 0000000000000000000000000000000000000000..a5dc50fd6d33c99a79a874e061c8923480035d7f --- /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 0000000000000000000000000000000000000000..73343cda921c642dcdf593ecea70ecbdbe0c1c3e --- /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> 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 0000000000000000000000000000000000000000..c8c1527707655e1738e617630c12a0527b862ca5 --- /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 0000000000000000000000000000000000000000..67a570b1cf00324c7f0265925700379fe4f744f5 --- /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 0000000000000000000000000000000000000000..1d6142c96c148b1cad0e6f024807d7314293e271 --- /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 0000000000000000000000000000000000000000..c5f9c7cf766338bd7cc77ba6063754b7de13ae02 --- /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 0000000000000000000000000000000000000000..b9f64e6957435e0e4af2fe15bd4bbde40c29a280 --- /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 0000000000000000000000000000000000000000..e2050e04fd9a96088fd4b0fc3df9f8902192ac91 --- /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 0000000000000000000000000000000000000000..8363270fcbe812c564424b69e839ecaab5106d02 --- /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 0000000000000000000000000000000000000000..fbd132e6555d2c85af37f8240df64a924f8094b5 --- /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) != 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 0000000000000000000000000000000000000000..ac0343fdcfae3f247986710e4903495b062d282d --- /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 0000000000000000000000000000000000000000..4092560180f2b876f035c1524a592a8ad12fa90f --- /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 0000000000000000000000000000000000000000..db6aabe50c7a4e8d26627280c361d148e29bb123 --- /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 0000000000000000000000000000000000000000..fddedb9947d68e4b13a97f20874324ac773d4832 --- /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 0000000000000000000000000000000000000000..87d7145cf5cace303fbd20e710bd6b3ed0997caa --- /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 0000000000000000000000000000000000000000..10e7d74d25d100d0884ffcbfad48ff8efa455aaf --- /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; iNBands; 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; iParams.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 0000000000000000000000000000000000000000..e83e51572041263fa6f3fe4ace981509aedaddc2 --- /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 0000000000000000000000000000000000000000..9df980ccfd264c2d437c6c692f4b3c470ee15d55 --- /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 0000000000000000000000000000000000000000..ac3c740908dd83b6e32944b1de87c5107b69a001 --- /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; iNBands; 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 0000000000000000000000000000000000000000..8e2e0e89456cae130bcdc1e5f57128df39498333 --- /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 0000000000000000000000000000000000000000..28e336958401a5cca19a63c866f062a029522444 --- /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 0000000000000000000000000000000000000000..ac2ef9dfb4a9aa2f41c396704080f4e1662f92af --- /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; iDelay_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; iNewParams.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; iRoomSizeInms * 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 0000000000000000000000000000000000000000..6bb1e88a2a9e49e5fc1e3397c7421f76a9215d8c --- /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 0000000000000000000000000000000000000000..7cee26d1f0a79f90638bf3af7b062e5823efb4d7 --- /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 0000000000000000000000000000000000000000..ffa51384b2e92e538d414d3b2562d9069454b5d6 --- /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 0000000000000000000000000000000000000000..20124327a8fcbd2e907cbfa158b0347e901050a6 --- /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 0000000000000000000000000000000000000000..fbfa4378cd1b2873c316a28c4d2cf3b3c410751b --- /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 0000000000000000000000000000000000000000..5c7a8a0d999ab65018c9d67fde99b24a0b71c9dc --- /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 0000000000000000000000000000000000000000..f5895a716e946aafccba716d551d74ab93a05acd --- /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 0000000000000000000000000000000000000000..5a6d43d7a688f2bae5955ae67213c9abd640698c --- /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 0000000000000000000000000000000000000000..5f993bde2a76d5718974a7b80a41f1c57bf7232f --- /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 0000000000000000000000000000000000000000..a675cb25070e171f3e2c27b933830fb8b9a77ef4 --- /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 0000000000000000000000000000000000000000..cd5f69cd996258dadfc5e5726de4422fdad7393e --- /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 0000000000000000000000000000000000000000..27a4bc3e60bdb3fc194a8ee86812cd899c5639de --- /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 0000000000000000000000000000000000000000..0984b10f3ab1cb6220f22486c7a81a667aea8749 --- /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 0000000000000000000000000000000000000000..1d8bedd7e22eb2d800a003071a3a308ec462bd09 --- /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 0000000000000000000000000000000000000000..9e29f68e423756941199a719fd8d93f0a20c4ade --- /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_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 0000000000000000000000000000000000000000..836bfd74cf30246912d3769aaff5d6b86abf40e7 --- /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 0000000000000000000000000000000000000000..50e0a802ef13832f95167530ce840502e741c336 --- /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 0000000000000000000000000000000000000000..67197c13e62c6006fe5ab9f824c9efa1ffe1f87d --- /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 0000000000000000000000000000000000000000..21a5d8d413f0afa45258cb0b87ad08d857e1b181 --- /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 0000000000000000000000000000000000000000..0d62274b10d7f680dc8c82ba3c77904d22244d31 --- /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 0000000000000000000000000000000000000000..3e48c7eb1e14e5352f718cde15b99b3cd41d5477 --- /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 0000000000000000000000000000000000000000..d1ef70aea5d724bab9485be0409e339ec9f16b2d --- /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 0000000000000000000000000000000000000000..ce6d4105a4a7a79580191b801206919249ed7a16 --- /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 0000000000000000000000000000000000000000..25b0d86295558a6387d29005e8ca4281a032e372 --- /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 0000000000000000000000000000000000000000..cf96f5b2d5d4fa858835d019fff9d3f192a3c7f5 --- /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 0000000000000000000000000000000000000000..1d55281994b33d79c91efd31ce234adf44925503 --- /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 0000000000000000000000000000000000000000..1904e467b38e8d4018dbdaf3d5ad2637326a3ff3 --- /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 0000000000000000000000000000000000000000..f3adb8d8451f103b3fee8595fbe43b52519e37f1 --- /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 0000000000000000000000000000000000000000..5d9946181843ba9fdc8d143a34ad59cf19385515 --- /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 0000000000000000000000000000000000000000..ee257b8ba233efb95c6a6d68e74f925dde0e8838 --- /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 0000000000000000000000000000000000000000..6e026ff77682313dc5cdf94c22ace22af24c8c3a --- /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 0000000000000000000000000000000000000000..b9b8b05115e01c2a5ffd2b43e53d0b245be2d45e --- /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 0000000000000000000000000000000000000000..15bc407ee562b45418c462cd4809bf305e6587b9 --- /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 0000000000000000000000000000000000000000..974de21d02adf4f539644d87d3919a678b80faf2 --- /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 0000000000000000000000000000000000000000..3f6c4c8824864b6dab88b83085e1cbd4a004dbaa --- /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 0000000000000000000000000000000000000000..4313424a1426a8b0198f2c56510c5f6692741a4a --- /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 0000000000000000000000000000000000000000..40dffd403ac2f13dc30d9a9590b9def9177ef915 --- /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 +#include +#include +#include +#include +#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; ipBundledContext = 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; ipBundledContext->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; iconfig.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; ipBundledContext->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; ipBundledContext->hInstance, + ¶ms); + + 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; ipBundledContext->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; iinputCfg.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 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; ipBundledContext->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 0000000000000000000000000000000000000000..5634ca138eb5cd51ff69fd0419e1ff1fb343851c --- /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 +#include +#include +#include +#include + +#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 0000000000000000000000000000000000000000..9599dcc6f567e7db20e19cad0c97302dcdb50fc8 --- /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 +#include +#include +#include +#include +#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; iInFrames32[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; ihInstance, + &MemTab, + LVM_NULL); + + LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "Reverb_free") + + for (int i=0; iinputCfg.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; ihInstance = 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, + ¶ms); + + 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 0000000000000000000000000000000000000000..7c15b1884022315e7eade20fcaf329e48ea6b354 --- /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 +#include + +#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 0000000000000000000000000000000000000000..c13b9d4141f516d8dafe493568e503c478e8891a --- /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 0000000000000000000000000000000000000000..1d76f625578e5b7347192a2cf4a8e31088f048fb --- /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 +#include +#define LOG_TAG "PreProcessing" +//#define LOG_NDEBUG 0 +#include +#include +#include +#include +#include +#include +#include +#include +#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(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(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(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(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(effect->engine); + ALOGV("AgcEnable agc %p", agc); + agc->Enable(true); +} + +void AgcDisable(preproc_effect_t *effect) +{ + ALOGV("AgcDisable"); + webrtc::GainControl *agc = static_cast(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(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(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(effect->engine); + ALOGV("AecEnable aec %p", aec); + aec->Enable(true); +} + +void AecDisable(preproc_effect_t *effect) +{ + ALOGV("AecDisable"); + webrtc::EchoControlMobile *aec = static_cast(effect->engine); + aec->Enable(false); +} + +int AecSetDevice(preproc_effect_t *effect, uint32_t device) +{ + ALOGV("AecSetDevice %08x", device); + webrtc::EchoControlMobile *aec = static_cast(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(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(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(effect->engine); + ALOGV("NsEnable ns %p", ns); + ns->Enable(true); +} + +void NsDisable(preproc_effect_t *effect) +{ + ALOGV("NsDisable"); + webrtc::NoiseSuppression *ns = static_cast(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<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<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<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<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 0000000000000000000000000000000000000000..2954908806aec46236d301f9d276511c15e7496a --- /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 0000000000000000000000000000000000000000..16dd1c506ad16d738d910198697911e47dd7b96f --- /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 +#include +#include + +#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(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< maxDelta) { + mCoefs[i] += maxDelta; + } else if (diff < -maxDelta) { + mCoefs[i] -= maxDelta; + } else { + mCoefs[i] = coefs[i]; + mCoefDirtyBits ^= (1< 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 0000000000000000000000000000000000000000..2b0e2d64aa420606c12b716836cbd9c0c05d809b --- /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 0000000000000000000000000000000000000000..6b569221d8d9c5168e321e5ca9abebe41137aebe --- /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 + +#include + +#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(hi-lo) * frac; + return lo + static_cast (delta >> 32); +} + +} diff --git a/media/libeffects/testlibs/AudioCoefInterpolator.h b/media/libeffects/testlibs/AudioCoefInterpolator.h new file mode 100644 index 0000000000000000000000000000000000000000..13e569714758e4193171d09d00c4434d4bf863eb --- /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 0000000000000000000000000000000000000000..e8080dcfb4d9ae371e622381f7dba23697cfa2e0 --- /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 +#include +#include + +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 0000000000000000000000000000000000000000..4f3a30877c53d4e7ffc8b2b3b59131237c738077 --- /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 +#include +#include +#include + +#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(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 0000000000000000000000000000000000000000..40284627f53627b457e3484cde065da1a460b817 --- /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 0000000000000000000000000000000000000000..41f1810e4eacefae44676e4c0294683fb9a7cfd3 --- /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 + + +#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 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 (pIn), + reinterpret_cast (pOut), + numSamplesIter); + } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { + mpProcessor->process( + reinterpret_cast (pIn), + mBuffer, numSamplesIter); + MixOutput(pOut, numSamplesIter); + } else { + assert(false); + } + pIn = reinterpret_cast (pIn) + + nSamplesChannels; + pOut = reinterpret_cast (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(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(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(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 0000000000000000000000000000000000000000..ebba139c341cdb2561421721f7def4e7d3fe5502 --- /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 0000000000000000000000000000000000000000..b57deb46dea12cc1ef27bfb6db4172977c84ea7c --- /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 0000000000000000000000000000000000000000..99323acd6b498b2f0f0bf034c5825fe628b2054b --- /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 +#include +#include + +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( + (static_cast(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(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((static_cast(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16); + if (CC_UNLIKELY(halfBW >= (16 << 15))) { + high = mNiquistFreq; + } else { + high = static_cast((static_cast(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 0000000000000000000000000000000000000000..d0f49c9e1ba905dd681b5c4b58ea3d09f1336936 --- /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 0000000000000000000000000000000000000000..374c6e11d0436a6034b73bfb5d72f6d63c7e0003 --- /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 0000000000000000000000000000000000000000..e031287fc7c2f96ecb2f64979a0ae2d8d68eb7db --- /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 +#include +#include + +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( + (static_cast(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(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 0000000000000000000000000000000000000000..f72d7935404b2ad662037e0d1389ebfc682ffe01 --- /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 0000000000000000000000000000000000000000..35a4a61794cd3e59e9b31de410ed82fb9c8eb05f --- /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 +#include +#include +#include +#include +#include "AudioEqualizer.h" +#include "AudioBiquadFilter.h" +#include "AudioFormatAdapter.h" +#include + + +// 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 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 0000000000000000000000000000000000000000..835171200ee430a0d34cddc57a10c24ce2ce81eb --- /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 +#include +#include +#include +#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 0000000000000000000000000000000000000000..1fb14a7be47e88d2e25a46457d2dfc6cd94da22e --- /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 +#include + + +/*------------------------------------ + * 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 0000000000000000000000000000000000000000..41ec66252b6fbfea4bcbe0ae32eb5bd217f7b76f --- /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 +#include + +#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 0000000000000000000000000000000000000000..2a44399e3f77988c3379244da7d0b28a823755ad --- /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 + +#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) */ \ + (((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) */ \ + (((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) */ \ + (((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) */ \ + (((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 */ \ + (int32_t)( \ + ( \ + ((int32_t)(audio)) * ((int32_t)(coef)) \ + ) \ + >> NUM_PHASE_FRAC_BITS \ + ) \ + /* lint +704 */ + +/* 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) */ \ + (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) */ \ + (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) */ \ + (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) */ \ + (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 */ \ + (int32_t)( \ + ( \ + ((int32_t)(dents)) * ((int32_t)(coef)) \ + ) \ + >> NUM_DENTS_FRAC_BITS \ + ) \ + /* lint +e704 */ + + +/* 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) */ \ + (int32_t) ( \ + ( \ + ((int32_t)(audio)) * ((int32_t)(drive)) \ + ) \ + >> NUM_DRIVE_COEF_FRAC_BITS \ + ) + +#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ + (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 0000000000000000000000000000000000000000..76b5110b7e5da6cb30750c5f1eede4891fabb76e --- /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 0000000000000000000000000000000000000000..bdb1a1cd969c1e668445f29155fd24a4a49381e8 --- /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 +#include +#include +#include +#include +#include +#include + + +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 0000000000000000000000000000000000000000..c8e1dc76664708fcb20d970faf6b84c3dcef8a8b --- /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 0000000000000000000000000000000000000000..34451caf96db8043ea0df20724b1925819327c9d --- /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 +#include +#include + +#include +#include + +#include +#include + + + +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; + sp 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& 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(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, ¶m->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& 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& 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& 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& 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 0000000000000000000000000000000000000000..abc7b3f9f3a42fcefecdd5a23a44f9cc76a28967 --- /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 + +#include + +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 0000000000000000000000000000000000000000..70ec593fe3d07387f1b5166257fb576d0c112770 --- /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 +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 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 audioRecord = mAudioRecord; + sp 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 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& audioFlinger = AudioSystem::get_audio_flinger(); + if (audioFlinger == 0) { + return NO_INIT; + } + + sp 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 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(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(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 audioRecord = mAudioRecord; + sp 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& 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 audioRecord = mAudioRecord; + sp 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 0000000000000000000000000000000000000000..33c7d03d93e04959ea89c4333dbbf9f6703124c8 --- /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 +#include +#include +#include +#include + +#include + +// ---------------------------------------------------------------------------- + +namespace android { + +// client singleton for AudioFlinger binder interface +Mutex AudioSystem::gLock; +sp AudioSystem::gAudioFlinger; +sp AudioSystem::gAudioFlingerClient; +audio_error_callback AudioSystem::gAudioErrorCallback = NULL; +// Cached values + +DefaultKeyedVector AudioSystem::gStreamOutputMap(0); +DefaultKeyedVector 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& AudioSystem::get_audio_flinger() +{ + Mutex::Autolock _l(gLock); + if (gAudioFlinger == 0) { + sp sm = defaultServiceManager(); + sp 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(binder); + gAudioFlinger->registerClient(gAudioFlingerClient); + } + ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); + + return gAudioFlinger; +} + +status_t AudioSystem::muteMicrophone(bool state) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setMicMute(state); +} + +status_t AudioSystem::isMicrophoneMuted(bool* state) { + const sp& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& af = AudioSystem::get_audio_flinger(); + if (af == 0) return 0; + return af->newAudioSessionId(); +} + +void AudioSystem::acquireAudioSessionId(int audioSession) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af != 0) { + af->acquireAudioSessionId(audioSession); + } +} + +void AudioSystem::releaseAudioSessionId(int audioSession) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af != 0) { + af->releaseAudioSessionId(audioSession); + } +} + +// --------------------------------------------------------------------------- + +void AudioSystem::AudioFlingerClient::binderDied(const wp& 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 AudioSystem::gAudioPolicyService; +sp AudioSystem::gAudioPolicyServiceClient; + + +// establish binder interface to AudioFlinger service +const sp& AudioSystem::get_audio_policy_service() +{ + gLock.lock(); + if (gAudioPolicyService == 0) { + sp sm = defaultServiceManager(); + sp 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(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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 0000000000000000000000000000000000000000..bafde3ab14b07635dcf5b60f1e968e8cce99efbc --- /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 +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +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& 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& 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& AudioTrack::sharedBuffer() +{ + return mSharedBuffer; +} + +// ------------------------------------------------------------------------- + +void AudioTrack::start() +{ + sp 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 audioTrack = mAudioTrack; + sp 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 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& sharedBuffer, + audio_io_handle_t output) +{ + status_t status; + const sp& 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 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 cblk = track->getCblk(); + if (cblk == 0) { + ALOGE("Could not get control block"); + return NO_INIT; + } + mAudioTrack = track; + mCblkMemory = cblk; + mCblk = static_cast(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 audioTrack = mAudioTrack; + sp 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* 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& 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& 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 audioTrack = mAudioTrack; + sp 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& 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 0000000000000000000000000000000000000000..ce10c8ecf3fdece92651b717234a3bf752378c01 --- /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 + +#include +#include + +#include + +#include + +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 +{ +public: + BpAudioFlinger(const sp& impl) + : BpInterface(impl) + { + } + + virtual sp 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& sharedBuffer, + audio_io_handle_t output, + int *sessionId, + status_t *status) + { + Parcel data, reply; + sp 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(reply.readStrongBinder()); + } + if (status) { + *status = lStatus; + } + return track; + } + + virtual sp 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 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(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& 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 createEffect(pid_t pid, + effect_descriptor_t *pDesc, + const sp& client, + int32_t priority, + audio_io_handle_t output, + int sessionId, + status_t *status, + int *id, + int *enabled) + { + Parcel data, reply; + sp 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(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 buffer = interface_cast(data.readStrongBinder()); + audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); + int sessionId = data.readInt32(); + status_t status; + sp 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 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 client = interface_cast(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 client = interface_cast(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 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 0000000000000000000000000000000000000000..4178b2938faa0a4202fffa0e98e9d1399eb6d4d8 --- /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 + +#include +#include + +#include + +#include +#include + +namespace android { + +enum { + IO_CONFIG_CHANGED = IBinder::FIRST_CALL_TRANSACTION +}; + +class BpAudioFlingerClient : public BpInterface +{ +public: + BpAudioFlingerClient(const sp& impl) + : BpInterface(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 0000000000000000000000000000000000000000..5040bd9bd95b65e6cc974944731a5c738ab4fab4 --- /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 + +#include +#include + +#include + +#include + +#include + +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 +{ +public: + BpAudioPolicyService(const sp& impl) + : BpInterface(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 (device)); + data.writeInt32(static_cast (state)); + data.writeCString(device_address); + remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply); + return static_cast (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 (device)); + data.writeCString(device_address); + remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply); + return static_cast (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 (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 (usage)); + data.writeInt32(static_cast (config)); + remote()->transact(SET_FORCE_USE, data, &reply); + return static_cast (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 (usage)); + remote()->transact(GET_FORCE_USE, data, &reply); + return static_cast (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 (stream)); + data.writeInt32(samplingRate); + data.writeInt32(static_cast (format)); + data.writeInt32(channels); + data.writeInt32(static_cast (flags)); + remote()->transact(GET_OUTPUT, data, &reply); + return static_cast (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 (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 (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 (format)); + data.writeInt32(channels); + data.writeInt32(static_cast (acoustics)); + data.writeInt32(audioSession); + remote()->transact(GET_INPUT, data, &reply); + return static_cast (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 (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 (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 (stream)); + data.writeInt32(indexMin); + data.writeInt32(indexMax); + remote()->transact(INIT_STREAM_VOLUME, data, &reply); + return static_cast (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 (stream)); + data.writeInt32(index); + data.writeInt32(static_cast (device)); + remote()->transact(SET_STREAM_VOLUME, data, &reply); + return static_cast (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 (stream)); + data.writeInt32(static_cast (device)); + + remote()->transact(GET_STREAM_VOLUME, data, &reply); + int lIndex = reply.readInt32(); + if (index) *index = lIndex; + return static_cast (reply.readInt32()); + } + + virtual uint32_t getStrategyForStream(audio_stream_type_t stream) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(static_cast (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 (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 (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 (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 (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 (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 (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 (data.readInt32()); + audio_policy_dev_state_t state = + static_cast (data.readInt32()); + const char *device_address = data.readCString(); + reply->writeInt32(static_cast (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 (data.readInt32()); + const char *device_address = data.readCString(); + reply->writeInt32(static_cast (getDeviceConnectionState(device, + device_address))); + return NO_ERROR; + } break; + + case SET_PHONE_STATE: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + reply->writeInt32(static_cast (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 (data.readInt32()); + audio_policy_forced_cfg_t config = + static_cast (data.readInt32()); + reply->writeInt32(static_cast (setForceUse(usage, config))); + return NO_ERROR; + } break; + + case GET_FORCE_USE: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_policy_force_use_t usage = static_cast (data.readInt32()); + reply->writeInt32(static_cast (getForceUse(usage))); + return NO_ERROR; + } break; + + case GET_OUTPUT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_stream_type_t stream = + static_cast (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 (data.readInt32()); + + audio_io_handle_t output = getOutput(stream, + samplingRate, + format, + channels, + flags); + reply->writeInt32(static_cast (output)); + return NO_ERROR; + } break; + + case START_OUTPUT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_io_handle_t output = static_cast (data.readInt32()); + uint32_t stream = data.readInt32(); + int session = data.readInt32(); + reply->writeInt32(static_cast (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 (data.readInt32()); + uint32_t stream = data.readInt32(); + int session = data.readInt32(); + reply->writeInt32(static_cast (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 (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 (data.readInt32()); + int audioSession = data.readInt32(); + audio_io_handle_t input = getInput(inputSource, + samplingRate, + format, + channels, + acoustics, + audioSession); + reply->writeInt32(static_cast (input)); + return NO_ERROR; + } break; + + case START_INPUT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_io_handle_t input = static_cast (data.readInt32()); + reply->writeInt32(static_cast (startInput(input))); + return NO_ERROR; + } break; + + case STOP_INPUT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_io_handle_t input = static_cast (data.readInt32()); + reply->writeInt32(static_cast (stopInput(input))); + return NO_ERROR; + } break; + + case RELEASE_INPUT: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_io_handle_t input = static_cast (data.readInt32()); + releaseInput(input); + return NO_ERROR; + } break; + + case INIT_STREAM_VOLUME: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_stream_type_t stream = + static_cast (data.readInt32()); + int indexMin = data.readInt32(); + int indexMax = data.readInt32(); + reply->writeInt32(static_cast (initStreamVolume(stream, indexMin,indexMax))); + return NO_ERROR; + } break; + + case SET_STREAM_VOLUME: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_stream_type_t stream = + static_cast (data.readInt32()); + int index = data.readInt32(); + audio_devices_t device = static_cast (data.readInt32()); + reply->writeInt32(static_cast (setStreamVolumeIndex(stream, + index, + device))); + return NO_ERROR; + } break; + + case GET_STREAM_VOLUME: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_stream_type_t stream = + static_cast (data.readInt32()); + audio_devices_t device = static_cast (data.readInt32()); + int index; + status_t status = getStreamVolumeIndex(stream, &index, device); + reply->writeInt32(index); + reply->writeInt32(static_cast (status)); + return NO_ERROR; + } break; + + case GET_STRATEGY_FOR_STREAM: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_stream_type_t stream = + static_cast (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 (data.readInt32()); + reply->writeInt32(static_cast (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 (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 (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 (unregisterEffect(id))); + return NO_ERROR; + } break; + + case SET_EFFECT_ENABLED: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + int id = data.readInt32(); + bool enabled = static_cast (data.readInt32()); + reply->writeInt32(static_cast (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 0000000000000000000000000000000000000000..377b9a870627664e6a193120204827bdc1a1d7d8 --- /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 + +#include +#include + +#include + +#include + +namespace android { + +enum { + GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, + START, + STOP +}; + +class BpAudioRecord : public BpInterface +{ +public: + BpAudioRecord(const sp& impl) + : BpInterface(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 getCblk() const + { + Parcel data, reply; + sp cblk; + data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_CBLK, data, &reply); + if (status == NO_ERROR) { + cblk = interface_cast(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 0000000000000000000000000000000000000000..09f31a73fb48d9d81f17cab909f551989a367b7e --- /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 + +#include +#include + +#include + +#include + +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 +{ +public: + BpAudioTrack(const sp& impl) + : BpInterface(impl) + { + } + + virtual sp getCblk() const + { + Parcel data, reply; + sp cblk; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_CBLK, data, &reply); + if (status == NO_ERROR) { + cblk = interface_cast(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* 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(reply.readStrongBinder()); + } + } + return status; + } + + virtual status_t queueTimedBuffer(const sp& 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 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 buffer = interface_cast( + 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 0000000000000000000000000000000000000000..827d7af243394f12cf51c0851d825b1b233c349b --- /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 + +#include +#include +#include + +namespace android { + +enum { + INITIALIZE = IBinder::FIRST_CALL_TRANSACTION, + TERMINATE, + SET_ENTITLEMENT_KEY, + SET_ECM, + DECRYPT_VIDEO, + DECRYPT_AUDIO, +}; + +struct BpCrypto : public BpInterface { + BpCrypto(const sp &impl) + : BpInterface(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 0000000000000000000000000000000000000000..a303a8fcd820d105c44efcf13106a095ac2b0ef6 --- /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 +#include +#include +#include +#include + +namespace android { + +enum { + ENABLE = IBinder::FIRST_CALL_TRANSACTION, + DISABLE, + COMMAND, + DISCONNECT, + GET_CBLK +}; + +class BpEffect: public BpInterface +{ +public: + BpEffect(const sp& impl) + : BpInterface(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 getCblk() const + { + Parcel data, reply; + sp cblk; + data.writeInterfaceToken(IEffect::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_CBLK, data, &reply); + if (status == NO_ERROR) { + cblk = interface_cast(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 0000000000000000000000000000000000000000..aef4371d2912dfddfa1c50b3814b11370bff126c --- /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 +#include +#include +#include + +namespace android { + +enum { + CONTROL_STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION, + ENABLE_STATUS_CHANGED, + COMMAND_EXECUTED +}; + +class BpEffectClient: public BpInterface +{ +public: + BpEffectClient(const sp& impl) + : BpInterface(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 0000000000000000000000000000000000000000..9199db6d8922adff3aae63fa012b215464f1c8d6 --- /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 + +#include +#include +#include + +namespace android { + +// client singleton for binder interface to services +Mutex IMediaDeathNotifier::sServiceLock; +sp IMediaDeathNotifier::sMediaPlayerService; +sp IMediaDeathNotifier::sDeathNotifier; +SortedVector< wp > IMediaDeathNotifier::sObitRecipients; + +// establish binder interface to MediaPlayerService +/*static*/const sp& +IMediaDeathNotifier::getMediaPlayerService() +{ + ALOGV("getMediaPlayerService"); + Mutex::Autolock _l(sServiceLock); + if (sMediaPlayerService == 0) { + sp sm = defaultServiceManager(); + sp 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(binder); + } + ALOGE_IF(sMediaPlayerService == 0, "no media player service!?"); + return sMediaPlayerService; +} + +/*static*/ void +IMediaDeathNotifier::addObitRecipient(const wp& recipient) +{ + ALOGV("addObitRecipient"); + Mutex::Autolock _l(sServiceLock); + sObitRecipients.add(recipient); +} + +/*static*/ void +IMediaDeathNotifier::removeObitRecipient(const wp& recipient) +{ + ALOGV("removeObitRecipient"); + Mutex::Autolock _l(sServiceLock); + sObitRecipients.remove(recipient); +} + +void +IMediaDeathNotifier::DeathNotifier::binderDied(const wp& who) { + ALOGW("media server died"); + + // Need to do this with the lock held + SortedVector< wp > 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 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 0000000000000000000000000000000000000000..7e6d54bdf07f50c2d19fd03f6d98824976367687 --- /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 +#include +#include +#include +#include + +// 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 +#include + +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 +{ +public: + BpMediaMetadataRetriever(const sp& impl) + : BpInterface(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 *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 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(reply.readStrongBinder()); + } + + sp 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(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 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 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 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 0000000000000000000000000000000000000000..0bb237db252cde5da67a9e4864d114907de4339d --- /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 +#include +#include + +#include + +#include +#include + +#include +#include + +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 +{ +public: + BpMediaPlayer(const sp& impl) + : BpInterface(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* 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 &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& surfaceTexture) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + sp 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(&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& player) { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + sp 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 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 source = + interface_cast(data.readStrongBinder()); + reply->writeInt32(setDataSource(source)); + return NO_ERROR; + } + case SET_VIDEO_SURFACETEXTURE: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + sp surfaceTexture = + interface_cast(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(data.readInt32()); + bool apply_filter = static_cast(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(&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(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 0000000000000000000000000000000000000000..a670c9640be367a6ca22907f6bb165f435d1f3dd --- /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 +#include +#include + +#include + +namespace android { + +enum { + NOTIFY = IBinder::FIRST_CALL_TRANSACTION, +}; + +class BpMediaPlayerClient: public BpInterface +{ +public: + BpMediaPlayerClient(const sp& impl) + : BpInterface(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(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(&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 0000000000000000000000000000000000000000..912061738bfe84cd70e6a1fa922074e925f7269c --- /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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include // 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 +{ +public: + BpMediaPlayerService(const sp& impl) + : BpInterface(impl) + { + } + + virtual sp createMetadataRetriever(pid_t pid) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(pid); + remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp create( + pid_t pid, const sp& 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(reply.readStrongBinder()); + } + + virtual sp createMediaRecorder(pid_t pid) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(pid); + remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp 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(reply.readStrongBinder()); + } + + virtual sp 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(reply.readStrongBinder()); + } + + virtual sp getOMX() { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + remote()->transact(GET_OMX, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp makeCrypto() { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + remote()->transact(MAKE_CRYPTO, data, &reply); + return interface_cast(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 client = + interface_cast(data.readStrongBinder()); + int audioSessionId = data.readInt32(); + sp 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 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 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 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 retriever = createMetadataRetriever(pid); + reply->writeStrongBinder(retriever->asBinder()); + return NO_ERROR; + } break; + case GET_OMX: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp omx = getOMX(); + reply->writeStrongBinder(omx->asBinder()); + return NO_ERROR; + } break; + case MAKE_CRYPTO: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp 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 0000000000000000000000000000000000000000..a710fd77ba5c941a388915aaf8181f3632bc529d --- /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 +#include +#include +#include +#include +#include +#include +#include + + +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 +{ +public: + BpMediaRecorder(const sp& impl) + : BpInterface(impl) + { + } + + status_t setCamera(const sp& camera, const sp& 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 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(reply.readStrongBinder()); + } + + status_t setPreviewSurface(const sp& 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& 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 listener = + interface_cast(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::readFromParcel(data); + reply->writeInt32(setPreviewSurface(surface)); + return NO_ERROR; + } break; + case SET_CAMERA: { + ALOGV("SET_CAMERA"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + sp camera = interface_cast(data.readStrongBinder()); + sp proxy = + interface_cast(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 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 0000000000000000000000000000000000000000..e7907e345c878621f95a095771a102d08f1e4dc2 --- /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 +#include +#include + +#include + +namespace android { + +enum { + NOTIFY = IBinder::FIRST_CALL_TRANSACTION, +}; + +class BpMediaRecorderClient: public BpInterface +{ +public: + BpMediaRecorderClient(const sp& impl) + : BpInterface(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 0000000000000000000000000000000000000000..48e427abe9b31be58bb687a6c90c89b596cb05ac --- /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 + +#include +#include +#include +#include + +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 { +public: + BpOMX(const sp &impl) + : BpInterface(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 *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 &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(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 ¶ms, + 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, 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 ¶ms, + 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(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 list; + listNodes(&list); + + reply->writeInt32(list.size()); + for (List::iterator it = list.begin(); + it != list.end(); ++it) { + ComponentInfo &cur = *it; + + reply->writeString8(cur.mName); + reply->writeInt32(cur.mRoles.size()); + for (List::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 observer = + interface_cast(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(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(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 params = + interface_cast(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 = 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 params = + interface_cast(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 { +public: + BpOMXObserver(const sp &impl) + : BpInterface(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 0000000000000000000000000000000000000000..078be9446c88e2fe0ecea9495e2c78f5030bb65f --- /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 + +#include +#include + +#include +#include + +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 { + BpStreamSource(const sp &impl) + : BpInterface(impl) { + } + + virtual void setListener(const sp &listener) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(SET_LISTENER, data, &reply); + } + + virtual void setBuffers(const Vector > &buffers) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeInt32(static_cast(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(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(data.readStrongBinder())); + break; + } + + case SET_BUFFERS: + { + CHECK_INTERFACE(IStreamSource, data, reply); + size_t n = static_cast(data.readInt32()); + Vector > buffers; + for (size_t i = 0; i < n; ++i) { + sp mem = + interface_cast(data.readStrongBinder()); + + buffers.push(mem); + } + setBuffers(buffers); + break; + } + + case ON_BUFFER_AVAILABLE: + { + CHECK_INTERFACE(IStreamSource, data, reply); + onBufferAvailable(static_cast(data.readInt32())); + break; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } + + return OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +struct BpStreamListener : public BpInterface { + BpStreamListener(const sp &impl) + : BpInterface(impl) { + } + + virtual void queueBuffer(size_t index, size_t size) { + Parcel data, reply; + data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); + data.writeInt32(static_cast(index)); + data.writeInt32(static_cast(size)); + + remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual void issueCommand( + Command cmd, bool synchronous, const sp &msg) { + Parcel data, reply; + data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); + data.writeInt32(static_cast(cmd)); + data.writeInt32(static_cast(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(data.readInt32()); + size_t size = static_cast(data.readInt32()); + + queueBuffer(index, size); + break; + } + + case ISSUE_COMMAND: + { + CHECK_INTERFACE(IStreamListener, data, reply); + Command cmd = static_cast(data.readInt32()); + + bool synchronous = static_cast(data.readInt32()); + + sp 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 0000000000000000000000000000000000000000..52aee49fcbbcb0314dab0d862174c4d02deeb185 --- /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 +#include + +#include + + +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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c224f066a7807cc0f1a8c38201895a9b8a07c375 --- /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 +#include +#include +#include +#include +#include +#include +#include + +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(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(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(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(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(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(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(format); +} + +static bool isCameraIdFound(int cameraId, const Vector& 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& 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(fileFormat); + profile->mQuality = static_cast(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& 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 MediaProfiles::getOutputFileFormats() const +{ + return mEncoderOutputFileFormats; // copy out +} + +Vector MediaProfiles::getVideoEncoders() const +{ + Vector 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 MediaProfiles::getAudioEncoders() const +{ + Vector 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 MediaProfiles::getVideoDecoders() const +{ + Vector decoders; + for (size_t i = 0; i < mVideoDecoders.size(); ++i) { + decoders.add(mVideoDecoders[i]->mCodec); + } + return decoders; // copy out +} + +Vector MediaProfiles::getAudioDecoders() const +{ + Vector 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 MediaProfiles::getImageEncodingQualityLevels(int cameraId) const +{ + Vector 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 0000000000000000000000000000000000000000..28b5aa7b8c39a313fba5caf18fb95459541ab426 --- /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 +#include + +#include + +#include +#include + +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 0000000000000000000000000000000000000000..e1e334836cd5ae62364f46fd49a57657a55329a1 --- /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 + +#include + +#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 0000000000000000000000000000000000000000..6a108aeca1072fd570b30fa05d2d57eea6e5f695 --- /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 + +#include +#include +#include + +/* + * 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(ptr); + ptr += sizeof(size_t); + + e->dups = *reinterpret_cast(ptr); + ptr += sizeof(size_t); + + e->backtrace = reinterpret_cast(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 0000000000000000000000000000000000000000..ef8a9ed3d45ab3f3b1351d769209e72550743419 --- /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 + +#include +#include +#include +#include +#include + +// 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 0000000000000000000000000000000000000000..c5b1efa7aac764ae6d8da63476a2d5cec02a6a5d --- /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 0000000000000000000000000000000000000000..306c57d3d95b31ac80888658384be79fc28ce275 --- /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 + +//#define USE_SHARED_MEM_BUFFER + +// XXX needed for timing latency +#include + +#include +#include + +#include + +#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::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::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 = 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 = new Sample(++mNextSampleID, fd, offset, length); + mSamples.add(sample->sampleID(), sample); + doLoad(sample); + return sample->sampleID(); +} + +void SoundPool::doLoad(sp& 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; + 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::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::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 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(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, 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; + 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((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(info); + } + + if (mToggle != toggle) { + ALOGV("process wrong toggle %p channel %d", this, mChannelID); + if (b != NULL) { + b->size = 0; + } + return; + } + + sp 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, 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 0000000000000000000000000000000000000000..002b04558d488cd59eb32927e051805d5b601078 --- /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 +#include +#include +#include +#include + +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(mData->pointer()); } + status_t doLoad(); + void startLoad() { mState = LOADING; } + sp getIMemory() { return mData; } + + // hack + void init(int numChannels, int sampleRate, audio_format_t format, size_t size, sp 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 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, int channelID, float leftVolume, + float rightVolume, int priority, int loop, float rate); + sp 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 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, 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); + sp 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 mChannels; + List mRestart; + List mStop; + DefaultKeyedVector< int, sp > 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 0000000000000000000000000000000000000000..ba3b482935dd6d600fab7ace3ecbe0eac476dcc2 --- /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 = 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 0000000000000000000000000000000000000000..d3883886379c12d52020f5d2b5c6e941c6f37290 --- /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 +#include +#include + +#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 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 0000000000000000000000000000000000000000..717d316f2d7d5f4402227de940e3ce8affa605a0 --- /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 + +#include +#include +#include +#include +#include +#include +#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(info); + ToneGenerator *lpToneGen = static_cast(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 0000000000000000000000000000000000000000..bcd6ae4901e73896ad0be648d3b58bc5dc6bb37f --- /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 + +#include +#include +#include + +#include + +#include +#include + +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 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 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 0000000000000000000000000000000000000000..be5c3b24873ddce4081df172b63501ae34348aa9 --- /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 0000000000000000000000000000000000000000..9675db3c1da57a0b02e6fc78b62d6e0d17e2340d --- /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 + +// 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 0000000000000000000000000000000000000000..b0241aab3f1bfadb7ab8393e762af3ad742129b2 --- /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 +#include +#include +#include +#include +#include + +namespace android { + +// client singleton for binder interface to service +Mutex MediaMetadataRetriever::sServiceLock; +sp MediaMetadataRetriever::sService; +sp MediaMetadataRetriever::sDeathNotifier; + +const sp& MediaMetadataRetriever::getService() +{ + Mutex::Autolock lock(sServiceLock); + if (sService == 0) { + sp sm = defaultServiceManager(); + sp 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(binder); + } + ALOGE_IF(sService == 0, "no MediaPlayerService!?"); + return sService; +} + +MediaMetadataRetriever::MediaMetadataRetriever() +{ + ALOGV("constructor"); + const sp& service(getService()); + if (service == 0) { + ALOGE("failed to obtain MediaMetadataRetrieverService"); + return; + } + sp 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 retriever; + { + Mutex::Autolock _l(mLock); + retriever = mRetriever; + mRetriever.clear(); + } + if (retriever != 0) { + retriever->disconnect(); + } +} + +status_t MediaMetadataRetriever::setDataSource( + const char *srcUrl, const KeyedVector *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 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 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& 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 0000000000000000000000000000000000000000..b52a37de174f50dd46f757df1454ce95ac86a623 --- /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 + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +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 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& listener) +{ + ALOGV("setListener"); + Mutex::Autolock _l(mLock); + mListener = listener; + return NO_ERROR; +} + + +status_t MediaPlayer::attachNewPlayer(const sp& player) +{ + status_t err = UNKNOWN_ERROR; + sp 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 *headers) +{ + ALOGV("setDataSource(%s)", url); + status_t err = BAD_VALUE; + if (url != NULL) { + const sp& service(getMediaPlayerService()); + if (service != 0) { + sp 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& service(getMediaPlayerService()); + if (service != 0) { + sp 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 &source) +{ + ALOGV("setDataSource"); + status_t err = UNKNOWN_ERROR; + const sp& service(getMediaPlayerService()); + if (service != 0) { + sp 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& 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& 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 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 MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) +{ + ALOGV("decode(%s)", url); + sp p; + const sp& 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 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 p; + const sp& 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& 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 0000000000000000000000000000000000000000..9541015699b135836d770a5b465f1054ab2c2e0c --- /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 +#include +#include +#include +#include +#include +#include // for MEDIA_ERROR_SERVER_DIED +#include + +namespace android { + +status_t MediaRecorder::setCamera(const sp& camera, const sp& 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) +{ + 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 object to hook up to ANativeWindow. +sp 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& 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& 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 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 0000000000000000000000000000000000000000..065a90f38ebffc47db166d382cb01db93fb2497d --- /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 0000000000000000000000000000000000000000..675c563126f9bbb205ee43fb9e748be19bcc4e37 --- /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 0000000000000000000000000000000000000000..e02035f5ae720cece0e81da8625dd8df3f6d6dd0 --- /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 + +#include "Crypto.h" + +#include + +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 0000000000000000000000000000000000000000..985549621bbc84d0b16f5dd734056f4926bf72b2 --- /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 +#include + +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 0000000000000000000000000000000000000000..123d07ff8755ca87a5c053694f6c1e635059a3e3 --- /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 + +#include +#include +#include +#include +#include + +#include + +#include +#include // for property_get + +#include + +#include + +#include +#include +#include +#include +#include +#include // for status_t +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "MediaRecorderClient.h" +#include "MediaPlayerService.h" +#include "MetadataRetrieverClient.h" + +#include "MidiFile.h" +#include "TestPlayerStub.h" +#include "StagefrightPlayer.h" +#include "nuplayer/NuPlayerDriver.h" + +#include + +#include "Crypto.h" + +namespace android { +sp createAAH_TXPlayer(); +sp 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(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 MediaPlayerService::createMediaRecorder(pid_t pid) +{ + sp recorder = new MediaRecorderClient(this, pid); + wp 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 client) +{ + Mutex::Autolock lock(mLock); + mMediaRecorderClients.remove(client); + ALOGV("Delete media recorder client"); +} + +sp MediaPlayerService::createMetadataRetriever(pid_t pid) +{ + sp retriever = new MetadataRetrieverClient(pid); + ALOGV("Create new media retriever from pid %d", pid); + return retriever; +} + +sp MediaPlayerService::create(pid_t pid, const sp& client, + int audioSessionId) +{ + int32_t connId = android_atomic_inc(&mNextConnId); + + sp 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 w = c; + { + Mutex::Autolock lock(mLock); + mClients.add(w); + } + return c; +} + +sp MediaPlayerService::getOMX() { + Mutex::Autolock autoLock(mLock); + + if (mOMX.get() == NULL) { + mOMX = new OMX; + } + + return mOMX; +} + +sp MediaPlayerService::makeCrypto() { + Mutex::Autolock autoLock(mLock); + + if (mCrypto == NULL) { + mCrypto = new Crypto; + } + + return mCrypto; +} + +status_t MediaPlayerService::AudioCache::dump(int fd, const Vector& 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& 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& 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& 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 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 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) +{ + Mutex::Autolock lock(mLock); + mClients.remove(client); +} + +MediaPlayerService::Client::Client( + const sp& service, pid_t pid, + int32_t connId, const sp& 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(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 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 &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 createPlayer(player_type playerType, void* cookie, + notify_callback_f notifyFunc) +{ + sp 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 MediaPlayerService::Client::createPlayer(player_type playerType) +{ + // determine if we have the right player type + sp 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 MediaPlayerService::Client::setDataSource_pre( + player_type playerType) +{ + ALOGV("player type = %d", playerType); + + // create the right type of player + sp p = createPlayer(playerType); + if (p == NULL) { + return p; + } + + if (!p->hardwareOutput()) { + mAudioOutput = new AudioOutput(mAudioSessionId); + static_cast(p.get())->setAudioSink(mAudioOutput); + } + + return p; +} + +void MediaPlayerService::Client::setDataSource_post( + const sp& 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 *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 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 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 &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 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& surfaceTexture) +{ + ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get()); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + + sp binder(surfaceTexture == NULL ? NULL : + surfaceTexture->asBinder()); + if (mConnectedWindowBinder == binder) { + return OK; + } + + sp 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 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 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 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 p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + p->setLooping(mLoop); + return p->start(); +} + +status_t MediaPlayerService::Client::stop() +{ + ALOGV("[%d] stop", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->stop(); +} + +status_t MediaPlayerService::Client::pause() +{ + ALOGV("[%d] pause", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->pause(); +} + +status_t MediaPlayerService::Client::isPlaying(bool* state) +{ + *state = false; + sp 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 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 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& player) { + ALOGV("setNextPlayer"); + Mutex::Autolock l(mLock); + sp c = static_cast(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 p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->seekTo(msec); +} + +status_t MediaPlayerService::Client::reset() +{ + ALOGV("[%d] reset", mConnId); + mRetransmitEndpointValid = false; + sp 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 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 p = getPlayer(); + { + Mutex::Autolock l(mLock); + if (p != 0 && p->hardwareOutput()) { + MediaPlayerHWInterface* hwp = + reinterpret_cast(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 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 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 = ", mConnId); + } + + sp 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(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(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 MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) +{ + ALOGV("decode(%s)", url); + sp mem; + sp 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 cache = new AudioCache(url); + player = android::createPlayer(playerType, cache.get(), cache->notify); + if (player == NULL) goto Exit; + if (player->hardwareOutput()) goto Exit; + + static_cast(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 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 mem; + sp player; + + player_type playerType = getPlayerType(fd, offset, length); + ALOGV("player type = %d", playerType); + + // create the right type of player + sp 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(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& 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 &sink, + MediaPlayerBase::AudioSink::AudioCallback cb, + void *cookie); + +protected: + virtual ~CallbackThread(); + + virtual bool threadLoop(); + +private: + wp mSink; + MediaPlayerBase::AudioSink::AudioCallback mCallback; + void *mCookie; + void *mBuffer; + size_t mBufferSize; + + CallbackThread(const CallbackThread &); + CallbackThread &operator=(const CallbackThread &); +}; + +CallbackThread::CallbackThread( + const wp &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 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(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(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 0000000000000000000000000000000000000000..b08dd6cf3f7ba07251c27961e5783701e40b6fd6 --- /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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +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& args) const; + + static bool isOnEmulator(); + static int getMinBufferCount(); + void setNextOutput(const sp& 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 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 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& args) const; + + private: + AudioCache(); + + Mutex mLock; + Condition mSignal; + sp mHeap; + float mMsecsPerFrame; + uint16_t mChannelCount; + audio_format_t mFormat; + ssize_t mFrameCount; + uint32_t mSampleRate; + uint32_t mSize; + int mError; + bool mCommandComplete; + + sp mCallbackThread; + }; // AudioCache + +public: + static void instantiate(); + + // IMediaPlayerService interface + virtual sp createMediaRecorder(pid_t pid); + void removeMediaRecorderClient(wp client); + virtual sp createMetadataRetriever(pid_t pid); + + virtual sp create(pid_t pid, const sp& client, int audioSessionId); + + virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat); + virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat); + virtual sp getOMX(); + virtual sp makeCrypto(); + + virtual status_t dump(int fd, const Vector& args); + + void removeClient(wp 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 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& 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& player); + + sp createPlayer(player_type playerType); + + virtual status_t setDataSource( + const char *url, + const KeyedVector *headers); + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + + virtual status_t setDataSource(const sp &source); + + sp setDataSource_pre(player_type playerType); + void setDataSource_post(const sp& 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 &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& args) const; + + int getAudioSessionId() { return mAudioSessionId; } + + private: + friend class MediaPlayerService; + Client( const sp& service, + pid_t pid, + int32_t connId, + const sp& client, + int audioSessionId, + uid_t uid); + Client(); + virtual ~Client(); + + void deletePlayer(); + + sp 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 mPlayer; + sp mService; + sp mClient; + sp mAudioOutput; + pid_t mPid; + status_t mStatus; + bool mLoop; + int32_t mConnId; + int mAudioSessionId; + uid_t mUID; + sp mConnectedWindow; + sp mConnectedWindowBinder; + struct sockaddr_in mRetransmitEndpoint; + bool mRetransmitEndpointValid; + sp 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 > mClients; + SortedVector< wp > mMediaRecorderClients; + int32_t mNextConnId; + sp mOMX; + sp mCrypto; +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_MEDIAPLAYERSERVICE_H diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..beda945331535f132c7f3b3f7d1cd0df18fbd7d0 --- /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 + +#include +#include +#include +#include +#include +#include +#include // for property_get +#include +#include +#include +#include +#include + +#include + +#include + +#include "MediaRecorderClient.h" +#include "MediaPlayerService.h" + +#include "StagefrightRecorder.h" +#include + +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 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& camera, + const sp& 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) +{ + 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 client(this); + mMediaPlayerService->removeMediaRecorderClient(client); + } + return NO_ERROR; +} + +MediaRecorderClient::MediaRecorderClient(const sp& 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& 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& 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 0000000000000000000000000000000000000000..c9ccf22ed944fa24f3d9d3a9311cf50bb9efd519 --- /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 + +namespace android { + +class MediaRecorderBase; +class MediaPlayerService; +class ICameraRecordingProxy; +class ISurfaceTexture; + +class MediaRecorderClient : public BnMediaRecorder +{ +public: + virtual status_t setCamera(const sp& camera, + const sp& proxy); + virtual status_t setPreviewSurface(const sp& 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& 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& args) const; + virtual sp querySurfaceMediaSource(); + +private: + friend class MediaPlayerService; // for accessing private constructor + + MediaRecorderClient( + const sp& service, + pid_t pid); + virtual ~MediaRecorderClient(); + + pid_t mPid; + Mutex mLock; + MediaRecorderBase *mRecorder; + sp mMediaPlayerService; +}; + +}; // namespace android + +#endif // ANDROID_MEDIARECORDERCLIENT_H diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..776d28832cdaf652b6da887cbbd87cf65cac0873 --- /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 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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& 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 createRetriever(player_type playerType) +{ + sp 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 *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 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 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 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 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(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 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 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(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 0000000000000000000000000000000000000000..f08f9331db6af70fad213e54482b851d6bec8abe --- /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 +#include +#include +#include +#include +#include + +#include + + +namespace android { + +class IMediaPlayerService; +class MemoryDealer; + +class MetadataRetrieverClient : public BnMediaMetadataRetriever +{ +public: + MetadataRetrieverClient(const sp& 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 *headers); + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual sp getFrameAtTime(int64_t timeUs, int option); + virtual sp extractAlbumArt(); + virtual const char* extractMetadata(int keyCode); + + virtual status_t dump(int fd, const Vector& args) const; + +private: + friend class MediaPlayerService; + + explicit MetadataRetrieverClient(pid_t pid); + virtual ~MetadataRetrieverClient(); + + mutable Mutex mLock; + sp mRetriever; + pid_t mPid; + + // Keep the shared memory copy of album art and capture frame (for thumbnail) + sp mAlbumArt; + sp mThumbnail; +}; + +}; // namespace android + +#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H + diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8db5b9b8eb77746d31c2ba48c3a893da856f9a51 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 *) { + 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 0000000000000000000000000000000000000000..f6f8f7b3ef9fa8be3aa40c0ab890c42461ab575d --- /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 +#include + +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 *headers); + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSurfaceTexture( + const sp& 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 mThread; +}; + +}; // namespace android + +#endif // ANDROID_MIDIFILE_H diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp new file mode 100644 index 0000000000000000000000000000000000000000..465209f008494f4359fa9e433dcabf2a97ce5902 --- /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 + +#include "MidiMetadataRetriever.h" +#include + +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 *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 0000000000000000000000000000000000000000..4cee42da1274b4985c4d49e6e7722b568d822212 --- /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 +#include +#include + +#include "MidiFile.h" + +namespace android { + +class MidiMetadataRetriever : public MediaMetadataRetrieverInterface { +public: + MidiMetadataRetriever() {} + ~MidiMetadataRetriever() {} + + virtual status_t setDataSource( + const char *url, const KeyedVector *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 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 0000000000000000000000000000000000000000..619c14908962a5cc20e089721fe999ca95081349 --- /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 + +#include "StagefrightPlayer.h" + +#include "AwesomePlayer.h" + +#include +#include + +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 *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 &source) { + return mPlayer->setDataSource(source); +} + +status_t StagefrightPlayer::setVideoSurfaceTexture( + const sp &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) { + 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 &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 0000000000000000000000000000000000000000..e89e18ab2b636017e0f282b8407bfbe0b0eafb95 --- /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 + +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 *headers); + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + + virtual status_t setDataSource(const sp &source); + + virtual status_t setVideoSurfaceTexture( + const sp &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); + 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 &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 0000000000000000000000000000000000000000..ca796572c86d473e70fcee7ca58531618883354d --- /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 + +#include "StagefrightRecorder.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "ARTPWriter.h" + +namespace android { + +// To collect the encoder usage for the battery app +static void addBatteryData(uint32_t params) { + sp binder = + defaultServiceManager()->getService(String16("media.player")); + sp service = interface_cast(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 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 &camera, + const sp &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) { + 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(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(), °rees)) { + 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 ¶ms) { + 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 &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 StagefrightRecorder::createAudioSource() { + sp audioSource = + new AudioSource( + mAudioSource, + mSampleRate, + mAudioChannels); + + status_t err = audioSource->initCheck(); + + if (err != OK) { + ALOGE("audio source is not initialized"); + return NULL; + } + + sp 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 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 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 source; + + if (mAudioSource != AUDIO_SOURCE_CNT) { + source = createAudioSource(); + } else { + + sp 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 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; + status_t err = setupMediaSource(&mediaSource); + if (err != OK) { + return err; + } + + sp 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) { + if (mVideoSource == VIDEO_SOURCE_DEFAULT + || mVideoSource == VIDEO_SOURCE_CAMERA) { + sp 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) { + 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 cameraSource, + int32_t videoBitRate, + sp *source) { + source->clear(); + + sp 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 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 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& 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 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->clear(); + *totalBitRate = 0; + status_t err = OK; + sp writer = new MPEG4Writer(outputFd); + + if (mVideoSource < VIDEO_SOURCE_LIST_END) { + + sp mediaSource; + err = setupMediaSource(&mediaSource); + if (err != OK) { + return err; + } + + sp 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(writer.get())-> + setInterleaveDuration(mInterleaveDurationUs); + } + if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) { + reinterpret_cast(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(writer.get())-> + setStartTimeOffsetMs(mStartTimeOffsetMs); + } + + writer->setListener(mListener); + *mediaWriter = writer; + return OK; +} + +void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate, + sp *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 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& 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 0000000000000000000000000000000000000000..ec5ce7ee58ad01d3aec9dad260612f1ff74eb9e1 --- /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 +#include +#include + +#include + +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& camera, const sp& proxy); + virtual status_t setPreviewSurface(const sp& 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& 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& args) const; + // Querying a SurfaceMediaSourcer + virtual sp querySurfaceMediaSource() const; + +private: + sp mCamera; + sp mCameraProxy; + sp mPreviewSurface; + sp mListener; + sp mWriter; + int mOutputFd; + sp 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 mCameraSourceTimeLapse; + + + String8 mParams; + + bool mIsMetaDataStoredInVideoBuffers; + MediaProfiles *mEncoderProfiles; + + bool mStarted; + // Needed when GLFrames are encoded. + // An pointer + // will be sent to the client side using which the + // frame buffers will be queued and dequeued + sp mSurfaceMediaSource; + + status_t setupMPEG4Recording( + int outputFd, + int32_t videoWidth, int32_t videoHeight, + int32_t videoBitRate, + int32_t *totalBitRate, + sp *mediaWriter); + void setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate, + sp *meta); + status_t startMPEG4Recording(); + status_t startAMRRecording(); + status_t startAACRecording(); + status_t startRawAudioRecording(); + status_t startRTPRecording(); + status_t startMPEG2TSRecording(); + sp 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); + status_t setupCameraSource(sp *cameraSource); + // setup the surfacemediasource for the encoder + status_t setupSurfaceMediaSource(); + + status_t setupAudioEncoder(const sp& writer); + status_t setupVideoEncoder( + sp cameraSource, + int32_t videoBitRate, + sp *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 0000000000000000000000000000000000000000..5d9728af253d85bc30f0879f1cda477d014def0c --- /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 // for dlopen/dlclose +#include +#include +#include +#include // 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:?url= +// +// 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 *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(dlsym(mHandle, + "newPlayer")); + err = ::dlerror(); + if (err || mNewPlayer == NULL) { + // if err is NULL the string is inserted in the logs => + // mNewPlayer was NULL. + ALOGE("dlsym for newPlayer failed %s", err); + resetInternal(); + return UNKNOWN_ERROR; + } + + mDeletePlayer = reinterpret_cast(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 0000000000000000000000000000000000000000..91ffa7dc43fe818be4bbcfdee529764271e7e371 --- /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 +#include + +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:?url= +// +// 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 *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& 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 0000000000000000000000000000000000000000..73336efc4afe76dfdf8c62909ec458b2079204a9 --- /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 0000000000000000000000000000000000000000..99569c9fd2a9ecd8d7867aed8c9443d2fd0299d8 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +NuPlayer::GenericSource::GenericSource( + const char *url, + const KeyedVector *headers, + bool uidValid, + uid_t uid) + : mDurationUs(0ll), + mAudioIsVorbis(false) { + DataSource::RegisterDefaultSniffers(); + + sp 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 = new FileSource(dup(fd), offset, length); + + initFromDataSource(dataSource); +} + +void NuPlayer::GenericSource::initFromDataSource( + const sp &dataSource) { + sp extractor = MediaExtractor::Create(dataSource); + + CHECK(extractor != NULL); + + for (size_t i = 0; i < extractor->countTracks(); ++i) { + sp meta = extractor->getTrackMetaData(i); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp 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 NuPlayer::GenericSource::getFormat(bool audio) { + sp source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; + + if (source == NULL) { + return NULL; + } + + return source->getFormat(); +} + +status_t NuPlayer::GenericSource::dequeueAccessUnit( + bool audio, sp *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 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 0000000000000000000000000000000000000000..aaa5876c3542a062d00d79cfe07906266e83b3aa --- /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 *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 getFormat(bool audio); + virtual status_t dequeueAccessUnit(bool audio, sp *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 mSource; + sp mPackets; + }; + + Track mAudioTrack; + Track mVideoTrack; + + int64_t mDurationUs; + bool mAudioIsVorbis; + + void initFromDataSource(const sp &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 0000000000000000000000000000000000000000..22b88471c07d949c18d38be40eef1460b8c98c73 --- /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 + +#include "HTTPLiveSource.h" + +#include "ATSParser.h" +#include "AnotherPacketSource.h" +#include "LiveDataSource.h" +#include "LiveSession.h" + +#include +#include +#include +#include +#include + +namespace android { + +NuPlayer::HTTPLiveSource::HTTPLiveSource( + const char *url, + const KeyedVector *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 NuPlayer::HTTPLiveSource::getFormat(bool audio) { + ATSParser::SourceType type = + audio ? ATSParser::AUDIO : ATSParser::VIDEO; + + sp source = + static_cast(mTSParser->getSource(type).get()); + + if (source == NULL) { + return NULL; + } + + return source->getFormat(); +} + +status_t NuPlayer::HTTPLiveSource::feedMoreTSData() { + if (mFinalResult != OK) { + return mFinalResult; + } + + sp source = + static_cast(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 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 *accessUnit) { + ATSParser::SourceType type = + audio ? ATSParser::AUDIO : ATSParser::VIDEO; + + sp source = + static_cast(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 0000000000000000000000000000000000000000..f22af5bee607a1255dd577f10db81451086aa562 --- /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 *headers, + bool uidValid = false, + uid_t uid = 0); + + virtual void start(); + + virtual status_t feedMoreTSData(); + + virtual sp getFormat(bool audio); + virtual status_t dequeueAccessUnit(bool audio, sp *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 mExtraHeaders; + bool mUIDValid; + uid_t mUID; + uint32_t mFlags; + status_t mFinalResult; + off64_t mOffset; + sp mLiveLooper; + sp mLiveSession; + sp 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 0000000000000000000000000000000000000000..544d501fb3ea0f39fc54349b709482c3030f17af --- /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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 &driver) { + mDriver = driver; +} + +void NuPlayer::setDataSource(const sp &source) { + sp 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 *headers) { + sp msg = new AMessage(kWhatSetDataSource, id()); + + sp 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 msg = new AMessage(kWhatSetDataSource, id()); + + sp source = new GenericSource(fd, offset, length); + msg->setObject("source", source); + msg->post(); +} + +void NuPlayer::setVideoSurfaceTexture(const sp &surfaceTexture) { + sp msg = new AMessage(kWhatSetVideoNativeWindow, id()); + sp surfaceTextureClient(surfaceTexture != NULL ? + new SurfaceTextureClient(surfaceTexture) : NULL); + msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient)); + msg->post(); +} + +void NuPlayer::setAudioSink(const sp &sink) { + sp 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 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 &msg) { + switch (msg->what()) { + case kWhatSetDataSource: + { + ALOGV("kWhatSetDataSource"); + + CHECK(mSource == NULL); + + sp obj; + CHECK(msg->findObject("source", &obj)); + + mSource = static_cast(obj.get()); + break; + } + + case kWhatSetVideoNativeWindow: + { + ALOGV("kWhatSetVideoNativeWindow"); + + sp obj; + CHECK(msg->findObject("native-window", &obj)); + + mNativeWindow = static_cast(obj.get()); + break; + } + + case kWhatSetAudioSink: + { + ALOGV("kWhatSetAudioSink"); + + sp obj; + CHECK(msg->findObject("sink", &obj)); + + mAudioSink = static_cast(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 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 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 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 driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyResetComplete(); + } + } +} + +void NuPlayer::postScanSources() { + if (mScanSourcesPending) { + return; + } + + sp msg = new AMessage(kWhatScanSources, id()); + msg->setInt32("generation", mScanSourcesGeneration); + msg->post(); + + mScanSourcesPending = true; +} + +status_t NuPlayer::instantiateDecoder(bool audio, sp *decoder) { + if (*decoder != NULL) { + return OK; + } + + sp 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 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 driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyDuration(durationUs); + } + } + + return OK; +} + +status_t NuPlayer::feedDecoderInputData(bool audio, const sp &msg) { + sp reply; + CHECK(msg->findMessage("reply", &reply)); + + if ((audio && IsFlushingState(mFlushingAudio)) + || (!audio && IsFlushingState(mFlushingVideo))) { + reply->setInt32("err", INFO_DISCONTINUITY); + reply->post(); + return OK; + } + + sp 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 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 &msg) { + // ALOGV("renderBuffer %s", audio ? "audio" : "video"); + + sp 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 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 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 0000000000000000000000000000000000000000..25766e0038873ae5c5973a9b65511d04f1ea26df --- /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 +#include +#include + +namespace android { + +struct ACodec; +struct MetaData; +struct NuPlayerDriver; + +struct NuPlayer : public AHandler { + NuPlayer(); + + void setUID(uid_t uid); + + void setDriver(const wp &driver); + + void setDataSource(const sp &source); + + void setDataSource( + const char *url, const KeyedVector *headers); + + void setDataSource(int fd, int64_t offset, int64_t length); + + void setVideoSurfaceTexture(const sp &surfaceTexture); + void setAudioSink(const sp &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 &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 mDriver; + bool mUIDValid; + uid_t mUID; + sp mSource; + sp mNativeWindow; + sp mAudioSink; + sp mVideoDecoder; + bool mVideoIsAVC; + sp mAudioDecoder; + sp 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); + + status_t feedDecoderInputData(bool audio, const sp &msg); + void renderBuffer(bool audio, const sp &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 0000000000000000000000000000000000000000..5733229ccef9316add116b37589301def1663179 --- /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 + +#include "NuPlayerDecoder.h" + +#include "ESDS.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +NuPlayer::Decoder::Decoder( + const sp ¬ify, + const sp &nativeWindow) + : mNotify(notify), + mNativeWindow(nativeWindow) { +} + +NuPlayer::Decoder::~Decoder() { +} + +void NuPlayer::Decoder::configure(const sp &meta) { + CHECK(mCodec == NULL); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp notifyMsg = + new AMessage(kWhatCodecNotify, id()); + + sp 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 &msg) { + switch (msg->what()) { + case kWhatCodecNotify: + { + int32_t what; + CHECK(msg->findInt32("what", &what)); + + if (what == ACodec::kWhatFillThisBuffer) { + onFillThisBuffer(msg); + } else { + sp notify = mNotify->dup(); + notify->setMessage("codec-request", msg); + notify->post(); + } + break; + } + + default: + TRESPASS(); + break; + } +} + +sp NuPlayer::Decoder::makeFormat(const sp &meta) { + CHECK(mCSD.isEmpty()); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp 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 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 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 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 &msg) { + sp reply; + CHECK(msg->findMessage("reply", &reply)); + +#if 0 + sp outBuffer; + CHECK(msg->findBuffer("buffer", &outBuffer)); +#else + sp outBuffer; +#endif + + if (mCSDIndex < mCSD.size()) { + outBuffer = mCSD.editItemAt(mCSDIndex++); + outBuffer->meta()->setInt64("timeUs", 0); + + reply->setBuffer("buffer", outBuffer); + reply->post(); + return; + } + + sp 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 0000000000000000000000000000000000000000..3ab1fcf1765ed101b9ee64280531de824e34e553 --- /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 + +namespace android { + +struct ABuffer; + +struct NuPlayer::Decoder : public AHandler { + Decoder(const sp ¬ify, + const sp &nativeWindow = NULL); + + void configure(const sp &meta); + + void signalFlush(); + void signalResume(); + void initiateShutdown(); + +protected: + virtual ~Decoder(); + + virtual void onMessageReceived(const sp &msg); + +private: + enum { + kWhatCodecNotify = 'cdcN', + }; + + sp mNotify; + sp mNativeWindow; + + sp mCodec; + sp mCodecLooper; + + Vector > mCSD; + size_t mCSDIndex; + + sp makeFormat(const sp &meta); + + void onFillThisBuffer(const sp &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 0000000000000000000000000000000000000000..253bc2fad5849a42b7ec643b4f3c39c3e2d7f610 --- /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 + +#include "NuPlayerDriver.h" + +#include "NuPlayer.h" + +#include +#include + +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 *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 &source) { + CHECK_EQ((int)mState, (int)UNINITIALIZED); + + mPlayer->setDataSource(source); + + mState = STOPPED; + + return OK; +} + +status_t NuPlayerDriver::setVideoSurfaceTexture( + const sp &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) { + 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 &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 0000000000000000000000000000000000000000..4a0026ca90ad47bc05384ae88762f490e957d341 --- /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 + +#include + +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 *headers); + + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + + virtual status_t setDataSource(const sp &source); + + virtual status_t setVideoSurfaceTexture( + const sp &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); + 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 &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 mLooper; + sp 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 0000000000000000000000000000000000000000..ecbc4287dd02dd5f428a83826a46faa6d289808c --- /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 + +#include "NuPlayerRenderer.h" + +#include +#include +#include + +namespace android { + +// static +const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll; + +NuPlayer::Renderer::Renderer( + const sp &sink, + const sp ¬ify) + : 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 &buffer, + const sp ¬ifyConsumed) { + sp msg = new AMessage(kWhatQueueBuffer, id()); + msg->setInt32("audio", static_cast(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 msg = new AMessage(kWhatQueueEOS, id()); + msg->setInt32("audio", static_cast(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 msg = new AMessage(kWhatFlush, id()); + msg->setInt32("audio", static_cast(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 &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 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 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 notify = mNotify->dup(); + notify->setInt32("what", kWhatEOS); + notify->setInt32("audio", static_cast(audio)); + notify->setInt32("finalResult", finalResult); + notify->post(); +} + +void NuPlayer::Renderer::onQueueBuffer(const sp &msg) { + int32_t audio; + CHECK(msg->findInt32("audio", &audio)); + + if (audio) { + mHasAudio = true; + } else { + mHasVideo = true; + } + + if (dropBufferWhileFlushing(audio, msg)) { + return; + } + + sp buffer; + CHECK(msg->findBuffer("buffer", &buffer)); + + sp notifyConsumed; + CHECK(msg->findMessage("notifyConsumed", ¬ifyConsumed)); + + 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 firstAudioBuffer = (*mAudioQueue.begin()).mBuffer; + sp 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 &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 &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 *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 notify = mNotify->dup(); + notify->setInt32("what", kWhatFlushComplete); + notify->setInt32("audio", static_cast(audio)); + notify->post(); +} + +bool NuPlayer::Renderer::dropBufferWhileFlushing( + bool audio, const sp &msg) { + bool flushing = false; + + { + Mutex::Autolock autoLock(mFlushLock); + if (audio) { + flushing = mFlushingAudio; + } else { + flushing = mFlushingVideo; + } + } + + if (!flushing) { + return false; + } + + sp notifyConsumed; + if (msg->findMessage("notifyConsumed", ¬ifyConsumed)) { + 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 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 0000000000000000000000000000000000000000..268628bd8c61e8078ea068633458f248c2625e4d --- /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 &sink, + const sp ¬ify); + + void queueBuffer( + bool audio, + const sp &buffer, + const sp ¬ifyConsumed); + + 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 &msg); + +private: + enum { + kWhatDrainAudioQueue = 'draA', + kWhatDrainVideoQueue = 'draV', + kWhatQueueBuffer = 'queB', + kWhatQueueEOS = 'qEOS', + kWhatFlush = 'flus', + kWhatAudioSinkChanged = 'auSC', + kWhatPause = 'paus', + kWhatResume = 'resm', + }; + + struct QueueEntry { + sp mBuffer; + sp mNotifyConsumed; + size_t mOffset; + status_t mFinalResult; + }; + + static const int64_t kMinPositionUpdateDelayUs; + + sp mAudioSink; + sp mNotify; + List mAudioQueue; + List 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 &msg); + void onQueueEOS(const sp &msg); + void onFlush(const sp &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 *queue); + bool dropBufferWhileFlushing(bool audio, const sp &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 0000000000000000000000000000000000000000..531b29f8b464a7a503c20ea165aaa3f45fd36ed3 --- /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 getFormat(bool audio) = 0; + + virtual status_t dequeueAccessUnit( + bool audio, sp *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 0000000000000000000000000000000000000000..885ebe4f47af7a1386d9449f654603a196ffeb39 --- /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 + +#include "NuPlayerStreamListener.h" + +#include +#include +#include +#include + +namespace android { + +NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener( + const sp &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 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 &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 *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 0000000000000000000000000000000000000000..1874d808a4e37cf374418e04ecba147cd68817da --- /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 + +namespace android { + +struct MemoryDealer; + +struct NuPlayer::NuPlayerStreamListener : public BnStreamListener { + NuPlayerStreamListener( + const sp &source, + ALooper::handler_id targetID); + + virtual void queueBuffer(size_t index, size_t size); + + virtual void issueCommand( + Command cmd, bool synchronous, const sp &extra); + + void start(); + ssize_t read(void *data, size_t size, sp *extra); + +private: + enum { + kNumBuffers = 8, + kBufferSize = 188 * 10 + }; + + struct QueueEntry { + bool mIsCommand; + + size_t mIndex; + size_t mSize; + size_t mOffset; + + Command mCommand; + sp mExtra; + }; + + Mutex mLock; + + sp mSource; + ALooper::handler_id mTargetID; + sp mMemoryDealer; + Vector > mBuffers; + List 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 0000000000000000000000000000000000000000..4c65b6564df514865f45e8777c0bc1ec47969381 --- /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 + +#include "RTSPSource.h" + +#include "AnotherPacketSource.h" +#include "MyHandler.h" + +#include + +namespace android { + +NuPlayer::RTSPSource::RTSPSource( + const char *url, + const KeyedVector *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(this); + mLooper->registerHandler(mReflector); + } + + CHECK(mHandler == NULL); + + sp 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 msg = new AMessage(kWhatDisconnect, mReflector->id()); + + sp dummy; + msg->postAndAwaitResponse(&dummy); +} + +status_t NuPlayer::RTSPSource::feedMoreTSData() { + return mFinalResult; +} + +sp NuPlayer::RTSPSource::getFormat(bool audio) { + sp source = getSource(audio); + + if (source == NULL) { + return NULL; + } + + return source->getFormat(); +} + +status_t NuPlayer::RTSPSource::dequeueAccessUnit( + bool audio, sp *accessUnit) { + sp 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 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 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 &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 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 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 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 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 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 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 &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 0000000000000000000000000000000000000000..59d06ada866262c4ceb37242c3d2c67e71ca4634 --- /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 + +namespace android { + +struct ALooper; +struct AnotherPacketSource; +struct MyHandler; + +struct NuPlayer::RTSPSource : public NuPlayer::Source { + RTSPSource( + const char *url, + const KeyedVector *headers, + bool uidValid = false, + uid_t uid = 0); + + virtual void start(); + virtual void stop(); + + virtual status_t feedMoreTSData(); + + virtual sp getFormat(bool audio); + virtual status_t dequeueAccessUnit(bool audio, sp *accessUnit); + + virtual status_t getDuration(int64_t *durationUs); + virtual status_t seekTo(int64_t seekTimeUs); + virtual bool isSeekable(); + + void onMessageReceived(const sp &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 mSource; + + int32_t mTimeScale; + uint32_t mRTPTime; + int64_t mNormalPlaytimeUs; + bool mNPTMappingValid; + }; + + AString mURL; + KeyedVector mExtraHeaders; + bool mUIDValid; + uid_t mUID; + uint32_t mFlags; + State mState; + status_t mFinalResult; + uint32_t mDisconnectReplyID; + + sp mLooper; + sp > mReflector; + sp mHandler; + + Vector mTracks; + sp mAudioTrack; + sp mVideoTrack; + + int32_t mSeekGeneration; + + sp getSource(bool audio); + + void onConnected(); + void onDisconnected(const sp &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 0000000000000000000000000000000000000000..7c9bc5e0a09668afce813cf6d8e30ee80573d7bb --- /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 + +#include "StreamingSource.h" + +#include "ATSParser.h" +#include "AnotherPacketSource.h" +#include "NuPlayerStreamListener.h" + +#include +#include +#include +#include +#include + +namespace android { + +NuPlayer::StreamingSource::StreamingSource(const sp &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 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 NuPlayer::StreamingSource::getFormat(bool audio) { + ATSParser::SourceType type = + audio ? ATSParser::AUDIO : ATSParser::VIDEO; + + sp source = + static_cast(mTSParser->getSource(type).get()); + + if (source == NULL) { + return NULL; + } + + return source->getFormat(); +} + +status_t NuPlayer::StreamingSource::dequeueAccessUnit( + bool audio, sp *accessUnit) { + ATSParser::SourceType type = + audio ? ATSParser::AUDIO : ATSParser::VIDEO; + + sp source = + static_cast(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 0000000000000000000000000000000000000000..ca00ef91d2d970052ea74e2359da87a00db7453f --- /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 &source); + + virtual void start(); + + virtual status_t feedMoreTSData(); + + virtual sp getFormat(bool audio); + virtual status_t dequeueAccessUnit(bool audio, sp *accessUnit); + +protected: + virtual ~StreamingSource(); + +private: + sp mSource; + status_t mFinalResult; + sp mStreamListener; + sp 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 0000000000000000000000000000000000000000..4d1072fb5d2844168be5fbbd1d1a6cbdf225f0bc --- /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 + +#include "include/AACExtractor.h" +#include "include/avc_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class AACSource : public MediaSource { +public: + AACSource(const sp &source, + const sp &meta, + const Vector &offset_vector, + int64_t frame_duration_us); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~AACSource(); + +private: + static const size_t kMaxFrameSize; + sp mDataSource; + sp mMeta; + + off64_t mOffset; + int64_t mCurrentTimeUs; + bool mStarted; + MediaBufferGroup *mGroup; + + Vector 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 &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 &source, const sp &_meta) + : mDataSource(source), + mInitCheck(NO_INIT), + mFrameDurationUs(0) { + sp meta = _meta; + + if (meta == NULL) { + String8 mimeType; + float confidence; + sp _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 AACExtractor::getMetaData() { + sp 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 AACExtractor::getTrack(size_t index) { + if (mInitCheck != OK || index != 0) { + return NULL; + } + + return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs); +} + +sp 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 &source, const sp &meta, + const Vector &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 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 &source, String8 *mimeType, float *confidence, + sp *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 0000000000000000000000000000000000000000..9cdb46360c5a77009a48cfef9e210c168395088d --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &source) { + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mSource != NULL) { + ALOGE("AAC files only support a single track of audio."); + return UNKNOWN_ERROR; + } + + sp 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(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, ×tampUs)); + 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 0000000000000000000000000000000000000000..db2bedad568c0d807600e92edf9a7437322575f5 --- /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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace android { + +template +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 &msg) { + mNotify = msg; + } + + // from IOMXObserver + virtual void onMessage(const omx_message &omx_msg) { + sp 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 mNotify; + + DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct ACodec::BaseState : public AState { + BaseState(ACodec *codec, const sp &parentState = NULL); + +protected: + enum PortMode { + KEEP_BUFFERS, + RESUBMIT_BUFFERS, + FREE_BUFFERS, + }; + + ACodec *mCodec; + + virtual PortMode getPortMode(OMX_U32 portIndex); + + virtual bool onMessageReceived(const sp &msg); + + virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); + + virtual void onOutputBufferDrained(const sp &msg); + virtual void onInputBufferFilled(const sp &msg); + + void postFillThisBuffer(BufferInfo *info); + +private: + bool onOMXMessage(const sp &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 &msg); + virtual void stateEntered(); + +private: + void onSetup(const sp &msg); + bool onAllocateComponent(const sp &msg); + + DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct ACodec::LoadedState : public ACodec::BaseState { + LoadedState(ACodec *codec); + +protected: + virtual bool onMessageReceived(const sp &msg); + virtual void stateEntered(); + +private: + friend struct ACodec::UninitializedState; + + bool onConfigureComponent(const sp &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 &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 &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 &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 &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 &msg); + virtual void stateEntered(); + + virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); + + virtual void onOutputBufferDrained(const sp &msg); + virtual void onInputBufferFilled(const sp &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 &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 &msg); + virtual void stateEntered(); + + virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); + + virtual void onOutputBufferDrained(const sp &msg); + virtual void onInputBufferFilled(const sp &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 &msg) { + mNotify = msg; +} + +void ACodec::initiateSetup(const sp &msg) { + msg->setWhat(kWhatSetup); + msg->setTarget(id()); + msg->post(); +} + +void ACodec::initiateAllocateComponent(const sp &msg) { + msg->setWhat(kWhatAllocateComponent); + msg->setTarget(id()); + msg->post(); +} + +void ACodec::initiateConfigureComponent(const sp &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 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 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 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(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 &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 &msg) { + int32_t tmp; + if (!msg->findInt32("color-format", &tmp)) { + return INVALID_OPERATION; + } + + OMX_COLOR_FORMATTYPE colorFormat = + static_cast(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 &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(profile); + mpeg4type.eLevel = static_cast(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 &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(profile); + h263type.eLevel = static_cast(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 &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(profile); + h264type.eLevel = static_cast(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(¶ms); + params.nPortIndex = kPortIndexOutput; + + for (params.nProfileIndex = 0;; ++params.nProfileIndex) { + status_t err = mOMX->getParameter( + mNode, + OMX_IndexParamVideoProfileLevelQuerySupported, + ¶ms, + sizeof(params)); + + if (err != OK) { + return err; + } + + int32_t supportedProfile = static_cast(params.eProfile); + int32_t supportedLevel = static_cast(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 &msg) { + bool wasEmptyBefore = mDeferredQueue.empty(); + mDeferredQueue.push_back(msg); +} + +void ACodec::processDeferredMessages() { + List > queue = mDeferredQueue; + mDeferredQueue.clear(); + + List >::iterator it = queue.begin(); + while (it != queue.end()) { + onMessageReceived(*it++); + } +} + +void ACodec::sendFormatChange() { + sp 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(¶ms); + params.nPortIndex = kPortIndexOutput; + + CHECK_EQ(mOMX->getParameter( + mNode, OMX_IndexParamAudioPcm, + ¶ms, 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 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 &parentState) + : AState(parentState), + mCodec(codec) { +} + +ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { + return KEEP_BUFFERS; +} + +bool ACodec::BaseState::onMessageReceived(const sp &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 &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(event), + static_cast(data1), + static_cast(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 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 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 &msg) { + IOMX::buffer_id bufferID; + CHECK(msg->findPointer("buffer-id", &bufferID)); + + sp 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 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 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 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 &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 &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 notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatShutdownCompleted); + notify->post(); + + handled = true; + break; + } + + case ACodec::kWhatFlush: + { + sp 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 &msg) { + if (onAllocateComponent(msg) + && mCodec->mLoadedState->onConfigureComponent(msg)) { + mCodec->mLoadedState->onStart(); + } +} + +bool ACodec::UninitializedState::onAllocateComponent(const sp &msg) { + ALOGV("onAllocateComponent"); + + CHECK(mCodec->mNode == NULL); + + OMXClient client; + CHECK_EQ(client.connect(), (status_t)OK); + + sp omx = client.interface(); + + Vector matchingCodecs; + Vector 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 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 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 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 notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatShutdownCompleted); + notify->post(); +} + +bool ACodec::LoadedState::onMessageReceived(const sp &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 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 &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 obj; + if (msg->findObject("native-window", &obj) + && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { + sp nativeWindow( + static_cast(obj.get())); + CHECK(nativeWindow != NULL); + mCodec->mNativeWindow = nativeWindow->getNativeWindow(); + } + CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); + + { + sp 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 &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 &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 &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 &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 &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 &msg) { + BaseState::onInputBufferFilled(msg); + + changeStateIfWeOwnAllBuffers(); +} + +void ACodec::ExecutingToIdleState::onOutputBufferDrained( + const sp &msg) { + BaseState::onOutputBufferDrained(msg); + + changeStateIfWeOwnAllBuffers(); +} + +//////////////////////////////////////////////////////////////////////////////// + +ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) + : BaseState(codec) { +} + +bool ACodec::IdleToLoadedState::onMessageReceived(const sp &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 &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 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 &msg) { + BaseState::onOutputBufferDrained(msg); + + changeStateIfWeOwnAllBuffers(); +} + +void ACodec::FlushingState::onInputBufferFilled(const sp &msg) { + BaseState::onInputBufferFilled(msg); + + changeStateIfWeOwnAllBuffers(); +} + +void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { + if (mFlushComplete[kPortIndexInput] + && mFlushComplete[kPortIndexOutput] + && mCodec->allYourBuffersAreBelongToUs()) { + sp 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 0000000000000000000000000000000000000000..03dcbf90ff43c12463d6f6c16467c336f49acd4c --- /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 + +#include "include/AMRExtractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class AMRSource : public MediaSource { +public: + AMRSource(const sp &source, + const sp &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 getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~AMRSource(); + +private: + sp mDataSource; + sp 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 &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 &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 AMRExtractor::getMetaData() { + sp 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 AMRExtractor::getTrack(size_t index) { + if (mInitCheck != OK || index != 0) { + return NULL; + } + + return new AMRSource(mDataSource, mMeta, mIsWide, + mOffsetTable, mOffsetTableLength); +} + +sp AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) { + if (mInitCheck != OK || index != 0) { + return NULL; + } + + return mMeta; +} + +//////////////////////////////////////////////////////////////////////////////// + +AMRSource::AMRSource( + const sp &source, const sp &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 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 &source, String8 *mimeType, float *confidence, + sp *) { + 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 0000000000000000000000000000000000000000..ca856409ba70d478c182f8e17d6a8002f764e3e8 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &source) { + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mSource != NULL) { + // AMR files only support a single track of audio. + return UNKNOWN_ERROR; + } + + sp 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(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, ×tampUs)); + 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 0000000000000000000000000000000000000000..5a6211e1a6174e38c69b7065725b1827ae6484be --- /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 + +#include "include/avc_utils.h" +#include "include/AVIExtractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +struct AVIExtractor::AVISource : public MediaSource { + AVISource(const sp &extractor, size_t trackIndex); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + +protected: + virtual ~AVISource(); + +private: + sp mExtractor; + size_t mTrackIndex; + const AVIExtractor::Track &mTrack; + MediaBufferGroup *mBufferGroup; + size_t mSampleIndex; + + sp 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 mBuffer; + + bool resync(); + + DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter); +}; + +//////////////////////////////////////////////////////////////////////////////// + +AVIExtractor::AVISource::AVISource( + const sp &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 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 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) + : mDataSource(dataSource) { + mInitCheck = parseHeaders(); + + if (mInitCheck != OK) { + mTracks.clear(); + } +} + +AVIExtractor::~AVIExtractor() { +} + +size_t AVIExtractor::countTracks() { + return mTracks.size(); +} + +sp AVIExtractor::getTrack(size_t index) { + return index < mTracks.size() ? new AVISource(this, index) : NULL; +} + +sp AVIExtractor::getTrackMetaData( + size_t index, uint32_t flags) { + return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL; +} + +sp AVIExtractor::getMetaData() { + sp 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 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 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 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 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 MakeMPEG4VideoCodecSpecificData(const sp &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 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 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 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 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 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 &source, String8 *mimeType, float *confidence, + sp *) { + 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 0000000000000000000000000000000000000000..8948abbe5e8e999a8a70084091cd9d1ecf2dfa7b --- /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 0000000000000000000000000000000000000000..0f816e7cc8b78e70f443d7152ba9a8b7734cc595 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/AwesomePlayer.h" + +namespace android { + +AudioPlayer::AudioPlayer( + const sp &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 &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 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 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(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 0000000000000000000000000000000000000000..0f1d8419d50fc8d03675731ff7ac46b23949b9c8 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include + +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::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 AudioSource::getFormat() { + Mutex::Autolock autoLock(mLock); + if (mInitCheck != OK) { + return 0; + } + + sp 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 0000000000000000000000000000000000000000..f96a4df7cb5af2f84afe7e2bcc3b3bad296daeb3 --- /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 + +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#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 &nativeWindow, const sp &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 &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 = buffer->meta_data(); + metaData->setInt32(kKeyRendered, 1); + } + +protected: + virtual ~AwesomeNativeWindowRenderer() {} + +private: + sp 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 binder = + defaultServiceManager()->getService(String16("media.player")); + sp service = interface_cast(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 &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 *headers) { + Mutex::Autolock autoLock(mLock); + return setDataSource_l(uri, headers); +} + +status_t AwesomePlayer::setDataSource_l( + const char *uri, const KeyedVector *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 = 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 &source) { + return INVALID_OPERATION; +} + +status_t AwesomePlayer::setDataSource_l( + const sp &dataSource) { + sp 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->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 &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 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 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 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 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 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 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 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 &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 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 &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 &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 source) { + CHECK(source != NULL); + + mAudioTrack = source; +} + +void AwesomePlayer::addTextSource(const sp& source) { + Mutex::Autolock autoLock(mTimedTextLock); + CHECK(source != NULL); + + if (mTextDriver == NULL) { + mTextDriver = new TimedTextDriver(mListener); + } + + mTextDriver->addInBandTextSource(source); +} + +status_t AwesomePlayer::initAudioDecoder() { + sp 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 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; + + 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 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 extractor; + + if (isWidevineStreaming) { + String8 mimeType; + float confidence; + sp 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(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 &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 0000000000000000000000000000000000000000..fd3f89267d073d39b044ab5a7577bea18cf8396f --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL; + +struct CameraSourceListener : public CameraListener { + CameraSourceListener(const sp &source); + + virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); + virtual void postData(int32_t msgType, const sp &dataPtr, + camera_frame_metadata_t *metadata); + + virtual void postDataTimestamp( + nsecs_t timestamp, int32_t msgType, const sp& dataPtr); + +protected: + virtual ~CameraSourceListener(); + +private: + wp mSource; + + CameraSourceListener(const CameraSourceListener &); + CameraSourceListener &operator=(const CameraSourceListener &); +}; + +CameraSourceListener::CameraSourceListener(const sp &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 &dataPtr, + camera_frame_metadata_t *metadata) { + ALOGV("postData(%d, ptr:%p, size:%d)", + msgType, dataPtr->pointer(), dataPtr->size()); + + sp source = mSource.promote(); + if (source.get() != NULL) { + source->dataCallback(msgType, dataPtr); + } +} + +void CameraSourceListener::postDataTimestamp( + nsecs_t timestamp, int32_t msgType, const sp& dataPtr) { + + sp 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 camera; + return new CameraSource(camera, NULL, 0, size, -1, NULL, false); +} + +// static +CameraSource *CameraSource::CreateFromCamera( + const sp& camera, + const sp& proxy, + int32_t cameraId, + Size videoSize, + int32_t frameRate, + const sp& surface, + bool storeMetaDataInVideoBuffers) { + + CameraSource *source = new CameraSource(camera, proxy, cameraId, + videoSize, frameRate, surface, + storeMetaDataInVideoBuffers); + return source; +} + +CameraSource::CameraSource( + const sp& camera, + const sp& proxy, + int32_t cameraId, + Size videoSize, + int32_t frameRate, + const sp& 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& camera, const sp& 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& 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& 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 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 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& camera, + const sp& 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& camera, + const sp& 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(¶ms, + 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& 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 >::iterator it; + while (!mFramesReceived.empty()) { + it = mFramesReceived.begin(); + releaseRecordingFrame(*it); + mFramesReceived.erase(it); + ++mNumFramesDropped; + } +} + +sp CameraSource::getFormat() { + return mMeta; +} + +void CameraSource::releaseOneRecordingFrame(const sp& frame) { + releaseRecordingFrame(frame); +} + +void CameraSource::signalBufferReturned(MediaBuffer *buffer) { + ALOGV("signalBufferReturned: %p", buffer->data()); + Mutex::Autolock autoLock(mLock); + for (List >::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 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 &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& source) { + mSource = source; +} + +void CameraSource::ProxyListener::dataCallbackTimestamp( + nsecs_t timestamp, int32_t msgType, const sp& dataPtr) { + mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr); +} + +void CameraSource::DeathNotifier::binderDied(const wp& 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 0000000000000000000000000000000000000000..26ce7ae9a88f4e2788920fb26062594d88ec86bd --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +// static +CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera( + const sp &camera, + const sp &proxy, + int32_t cameraId, + Size videoSize, + int32_t videoFrameRate, + const sp& 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& camera, + const sp& proxy, + int32_t cameraId, + Size videoSize, + int32_t videoFrameRate, + const sp& 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 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 CameraSourceTimeLapse::createIMemoryCopy( + const sp &source_data) { + + ALOGV("createIMemoryCopy"); + size_t source_size = source_data->size(); + void* source_pointer = source_data->pointer(); + + sp newMemoryHeap = new MemoryHeapBase(source_size); + sp 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 &data) { + ALOGV("dataCallbackTimestamp"); + mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs); + CameraSource::dataCallbackTimestamp(timestampUs, msgType, data); +} + +} // namespace android diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..524c3aad099ee344bf89ccbce9f4c15dacdd2fee --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace android { + +class DRMSource : public MediaSource { +public: + DRMSource(const sp &mediaSource, + const sp &decryptHandle, + DrmManagerClient *managerClient, + int32_t trackId, DrmBuffer *ipmpBox); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp getFormat(); + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~DRMSource(); + +private: + sp mOriginalMediaSource; + sp 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, + const sp &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 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 &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 DRMExtractor::getTrack(size_t index) { + sp 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 DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) { + return mOriginalExtractor->getTrackMetaData(index, flags); +} + +sp DRMExtractor::getMetaData() { + return mOriginalExtractor->getMetaData(); +} + +bool SniffDRM( + const sp &source, String8 *mimeType, float *confidence, + sp *) { + sp 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 0000000000000000000000000000000000000000..d0a78808830123c98d97114561304a18d686ad71 --- /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 +#include +#include +#include +#include + +#include + +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::gSniffers; + +bool DataSource::sniff( + String8 *mimeType, float *confidence, sp *meta) { + *mimeType = ""; + *confidence = 0.0f; + meta->clear(); + + Mutex::Autolock autoLock(gSnifferMutex); + for (List::iterator it = gSniffers.begin(); + it != gSniffers.end(); ++it) { + String8 newMimeType; + float newConfidence; + sp 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::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::CreateFromURI( + const char *uri, const KeyedVector *headers) { + sp source; + if (!strncasecmp("file://", uri, 7)) { + source = new FileSource(uri + 7); + } else if (!strncasecmp("http://", uri, 7) + || !strncasecmp("https://", uri, 8)) { + sp 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 0000000000000000000000000000000000000000..4a0c35c6784148ec29e91aa3fa863855df39c941 --- /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 + +#include "include/ESDS.h" + +#include + +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 0000000000000000000000000000000000000000..668d7f7d9efe46fa9ba707de7f3e48763ce865df --- /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 + +#include "include/FLACExtractor.h" +// Vorbis comments +#include "include/OggExtractor.h" +// libFLAC parser +#include "FLAC/stream_decoder.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class FLACParser; + +class FLACSource : public MediaSource { + +public: + FLACSource( + const sp &dataSource, + const sp &trackMetadata); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~FLACSource(); + +private: + sp mDataSource; + sp mTrackMetadata; + sp 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, + // If metadata pointers aren't provided, we don't fill them + const sp &fileMetadata = 0, + const sp &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 mDataSource; + sp mFileMetadata; + sp 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, + const sp &fileMetadata, + const sp &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, + const sp &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 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) + : mDataSource(dataSource), + mInitCheck(false) +{ + ALOGV("FLACExtractor::FLACExtractor"); + mInitCheck = init(); +} + +FLACExtractor::~FLACExtractor() +{ + ALOGV("~FLACExtractor::FLACExtractor"); +} + +size_t FLACExtractor::countTracks() +{ + return mInitCheck == OK ? 1 : 0; +} + +sp FLACExtractor::getTrack(size_t index) +{ + if (mInitCheck != OK || index > 0) { + return NULL; + } + return new FLACSource(mDataSource, mTrackMetadata); +} + +sp 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 FLACExtractor::getMetaData() +{ + return mFileMetadata; +} + +// Sniffer + +bool SniffFLAC( + const sp &source, String8 *mimeType, float *confidence, + sp *) +{ + // 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 0000000000000000000000000000000000000000..73c8d033d150441bfb7ddae68cea47615f1a1681 --- /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 +#include +#include +#include +#include +#include +#include + +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 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 &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 0000000000000000000000000000000000000000..d7eea3f0f418732ce705be87ff170b4b430c8df4 --- /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 + +#include "include/HTTPBase.h" + +#if CHROMIUM_AVAILABLE +#include "include/ChromiumHTTPDataSource.h" +#endif + +#include +#include + +#include +#include + +namespace android { + +HTTPBase::HTTPBase() + : mNumBandwidthHistoryItems(0), + mTotalTransferTimeUs(0), + mTotalTransferBytes(0), + mPrevBandwidthMeasureTimeUs(0), + mPrevEstimatedBandWidthKbps(0), + mBandWidthCollectFreqMs(5000), + mUIDValid(false), + mUID(0) { +} + +// static +sp 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 0000000000000000000000000000000000000000..bafa4b219e476da21525243c38d3b1762f2f9f5a --- /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 + +#include +#include +#include +#include +#include +#include +#include + +#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 &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 JPEGSource::getFormat() { + sp 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 0000000000000000000000000000000000000000..6abaf23ba31059ead5d3c234b12aa84f3024ce84 --- /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 + +#include "include/MP3Extractor.h" + +#include "include/avc_utils.h" +#include "include/ID3.h" +#include "include/VBRISeeker.h" +#include "include/XINGSeeker.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &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 &meta, const sp &source, + off64_t first_frame_pos, uint32_t fixed_header, + const sp &seeker); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~MP3Source(); + +private: + sp mMeta; + sp mDataSource; + off64_t mFirstFramePos; + uint32_t mFixedHeader; + off64_t mCurrentPos; + int64_t mCurrentTimeUs; + bool mStarted; + sp mSeeker; + MediaBufferGroup *mGroup; + + int64_t mBasisTimeUs; + int64_t mSamplesRead; + + MP3Source(const MP3Source &); + MP3Source &operator=(const MP3Source &); +}; + +MP3Extractor::MP3Extractor( + const sp &source, const sp &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 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 MP3Extractor::getTrack(size_t index) { + if (mInitCheck != OK || index != 0) { + return NULL; + } + + return new MP3Source( + mMeta, mDataSource, mFirstFramePos, mFixedHeader, + mSeeker); +} + +sp MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) { + if (mInitCheck != OK || index != 0) { + return NULL; + } + + return mMeta; +} + +//////////////////////////////////////////////////////////////////////////////// + +MP3Source::MP3Source( + const sp &meta, const sp &source, + off64_t first_frame_pos, uint32_t fixed_header, + const sp &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 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 MP3Extractor::getMetaData() { + sp 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 &source, String8 *mimeType, + float *confidence, sp *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 0000000000000000000000000000000000000000..f7023762829138ccf0ce41c05bee83838860d2d6 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/ESDS.h" + +namespace android { + +struct MPEG2TSWriter::SourceInfo : public AHandler { + SourceInfo(const sp &source); + + void start(const sp ¬ify); + void stop(); + + unsigned streamType() const; + unsigned incrementContinuityCounter(); + + void readMore(); + + enum { + kNotifyStartFailed, + kNotifyBuffer, + kNotifyReachedEOS, + }; + + sp lastAccessUnit(); + int64_t lastAccessUnitTimeUs(); + void setLastAccessUnit(const sp &accessUnit); + + void setEOSReceived(); + bool eosReceived() const; + +protected: + virtual void onMessageReceived(const sp &msg); + + virtual ~SourceInfo(); + +private: + enum { + kWhatStart = 'strt', + kWhatRead = 'read', + }; + + sp mSource; + sp mLooper; + sp mNotify; + + sp mAACCodecSpecificData; + + sp mAACBuffer; + + sp 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 &source) + : mSource(source), + mLooper(new ALooper), + mEOSReceived(false), + mStreamType(0), + mContinuityCounter(0) { + mLooper->setName("MPEG2TSWriter source"); + + sp 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 ¬ify) { + 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 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 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 notify = mNotify->dup(); + notify->setInt32("what", kNotifyBuffer); + notify->setBuffer("buffer", out); + notify->setInt32("oob", true); + notify->post(); +} + +void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) { + sp notify = mNotify->dup(); + notify->setInt32("what", kNotifyBuffer); + + sp 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 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 &msg) { + switch (msg->what()) { + case kWhatStart: + { + status_t err = mSource->start(); + if (err != OK) { + sp 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 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 MPEG2TSWriter::SourceInfo::lastAccessUnit() { + return mLastAccessUnit; +} + +void MPEG2TSWriter::SourceInfo::setLastAccessUnit( + const sp &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(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 &source) { + CHECK(!mStarted); + + sp 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 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 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 &args) { + return OK; +} + +void MPEG2TSWriter::onMessageReceived(const sp &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 source = mSources.editItemAt(sourceIndex); + source->setEOSReceived(); + + sp buffer = source->lastAccessUnit(); + source->setLastAccessUnit(NULL); + + if (buffer != NULL) { + writeTS(); + writeAccessUnit(sourceIndex, buffer); + } + + ++mNumSourcesDone; + } else if (what == SourceInfo::kNotifyBuffer) { + sp 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 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 &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 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 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 &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 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 0000000000000000000000000000000000000000..9385b8aff33d40b17718d2810bcca3e21b7ae85e --- /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 + +#include "include/MPEG4Extractor.h" +#include "include/SampleTable.h" +#include "include/ESDS.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class MPEG4Source : public MediaSource { +public: + // Caller retains ownership of both "dataSource" and "sampleTable". + MPEG4Source(const sp &format, + const sp &dataSource, + int32_t timeScale, + const sp &sampleTable); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~MPEG4Source(); + +private: + Mutex mLock; + + sp mFormat; + sp mDataSource; + int32_t mTimescale; + sp 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 &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 mSource; + off64_t mCachedOffset; + size_t mCachedSize; + uint8_t *mCache; + + void clearCache(); + + MPEG4DataSource(const MPEG4DataSource &); + MPEG4DataSource &operator=(const MPEG4DataSource &); +}; + +MPEG4DataSource::MPEG4DataSource(const sp &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 &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 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 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, 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 *path, uint32_t chunkType) + : mPath(path) { + mPath->push(chunkType); + } + + ~PathAdder() { + mPath->pop(); + } + +private: + Vector *mPath; + + PathAdder(const PathAdder &); + PathAdder &operator=(const PathAdder &); +}; + +static bool underMetaDataPath(const Vector &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 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, ×cale, 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 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 &format, + const sp &dataSource, + int32_t timeScale, + const sp &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 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 &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 &source, String8 *mimeType, float *confidence, + sp *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 &source, String8 *mimeType, float *confidence, + sp *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 0000000000000000000000000000000000000000..7ebbe1d3ce8534ba5fc81203c8d8f20eaa866fdd --- /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 + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 &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& args) const; + +private: + enum { + kMaxCttsOffsetTimeUs = 1000000LL, // 1 second + }; + + MPEG4Writer *mOwner; + sp mMeta; + sp 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 mSampleSizes; + bool mSamplesHaveSameSize; + + List mChunkSamples; + + size_t mNumStcoTableEntries; + List 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 mStscTableEntries; + + size_t mNumStssTableEntries; + List 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 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 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 mSeqParamSets; + List 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& 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::iterator it = mTracks.begin(); + delete *it; + (*it) = NULL; + mTracks.erase(it); + } + mTracks.clear(); +} + +status_t MPEG4Writer::dump( + int fd, const Vector& 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::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + (*it)->dump(fd, args); + } + return OK; +} + +status_t MPEG4Writer::Track::dump( + int fd, const Vector& 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 &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::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + status_t err = (*it)->start(params); + + if (err != OK) { + for (List::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::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::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(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::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::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::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(mEstimatedMoovBoxSize); + for (List::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::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { + return true; + } + } + return false; +} + +bool MPEG4Writer::reachedEOS() { + bool allDone = true; + for (List::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 &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(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::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::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::iterator it = mChunkInfos.begin(); + it != mChunkInfos.end(); ++it) { + if (!it->mChunks.empty()) { + List::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::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::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 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(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, ¶mSetLen); + } 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, ¶mSetLen); + } 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::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::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& 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 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, ×tampUs)); + +//////////////////////////////////////////////////////////////////////////////// + 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::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::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::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::iterator it = mSampleSizes.begin(); + mOwner->writeInt32(*it); // default sample size + } else { + mOwner->writeInt32(0); + } + mOwner->writeInt32(mNumSamples); + if (!mSamplesHaveSameSize) { + for (List::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::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::iterator it = mChunkOffsets.begin(); + it != mChunkOffsets.end(); ++it) { + if (use32BitOffset) { + mOwner->writeInt32(static_cast(*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 0000000000000000000000000000000000000000..11b80bf42429baed71658a0f9b54e764bb6eb4e4 --- /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 + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +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) + : 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 &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 MediaBuffer::graphicBuffer() const { + return mGraphicBuffer; +} + +sp 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 0000000000000000000000000000000000000000..80aae51c86b24520e6866f0e0e1d4ccdc46f4c8a --- /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 + +#include +#include +#include + +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 0000000000000000000000000000000000000000..42b5c7ee40ce739aa1b47578f45487b6b48eee08 --- /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 + +#include + +#include "include/SoftwareRenderer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +// static +sp MediaCodec::CreateByType( + const sp &looper, const char *mime, bool encoder) { + sp codec = new MediaCodec(looper); + if (codec->init(mime, true /* nameIsType */, encoder) != OK) { + return NULL; + } + + return codec; +} + +// static +sp MediaCodec::CreateByComponentName( + const sp &looper, const char *name) { + sp codec = new MediaCodec(looper); + if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) { + return NULL; + } + + return codec; +} + +MediaCodec::MediaCodec(const sp &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 &msg, sp *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 msg = new AMessage(kWhatInit, id()); + msg->setString("name", name); + msg->setInt32("nameIsType", nameIsType); + + if (nameIsType) { + msg->setInt32("encoder", encoder); + } + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::configure( + const sp &format, + const sp &nativeWindow, + uint32_t flags) { + sp 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 response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::start() { + sp msg = new AMessage(kWhatStart, id()); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::stop() { + sp msg = new AMessage(kWhatStop, id()); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::release() { + sp msg = new AMessage(kWhatRelease, id()); + + sp 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 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 response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { + sp msg = new AMessage(kWhatDequeueInputBuffer, id()); + msg->setInt64("timeoutUs", timeoutUs); + + sp 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 msg = new AMessage(kWhatDequeueOutputBuffer, id()); + msg->setInt64("timeoutUs", timeoutUs); + + sp 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 msg = new AMessage(kWhatReleaseOutputBuffer, id()); + msg->setSize("index", index); + msg->setInt32("render", true); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::releaseOutputBuffer(size_t index) { + sp msg = new AMessage(kWhatReleaseOutputBuffer, id()); + msg->setSize("index", index); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::getOutputFormat(sp *format) const { + sp msg = new AMessage(kWhatGetOutputFormat, id()); + + sp response; + status_t err; + if ((err = PostAndAwaitResponse(msg, &response)) != OK) { + return err; + } + + CHECK(response->findMessage("format", format)); + + return OK; +} + +status_t MediaCodec::getInputBuffers(Vector > *buffers) const { + sp msg = new AMessage(kWhatGetBuffers, id()); + msg->setInt32("portIndex", kPortIndexInput); + msg->setPointer("buffers", buffers); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::getOutputBuffers(Vector > *buffers) const { + sp msg = new AMessage(kWhatGetBuffers, id()); + msg->setInt32("portIndex", kPortIndexOutput); + msg->setPointer("buffers", buffers); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::flush() { + sp msg = new AMessage(kWhatFlush, id()); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + +//////////////////////////////////////////////////////////////////////////////// + +void MediaCodec::cancelPendingDequeueOperations() { + if (mFlags & kFlagDequeueInputPending) { + sp response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + response->postReply(mDequeueInputReplyID); + + ++mDequeueInputTimeoutGeneration; + mDequeueInputReplyID = 0; + mFlags &= ~kFlagDequeueInputPending; + } + + if (mFlags & kFlagDequeueOutputPending) { + sp 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 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 response = new AMessage; + response->setSize("index", index); + response->postReply(replyID); + + return true; +} + +bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) { + sp 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 &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 &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 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 *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 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 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 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 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 response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + mReplyID = replyID; + setState(CONFIGURING); + + sp obj; + if (!msg->findObject("native-window", &obj)) { + obj.clear(); + } + + sp 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 sm = defaultServiceManager(); + + sp binder = + sm->getService(String16("media.player")); + + sp service = + interface_cast(binder); + + CHECK(service != NULL); + + mCrypto = service->makeCrypto(); + + status_t err = mCrypto->initialize(); + + if (err == OK) { + sp emm; + if (format->findBuffer("emm", &emm)) { + err = mCrypto->setEntitlementKey( + emm->data(), emm->size()); + } + } + + if (err == OK) { + sp 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 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 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 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 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 response = new AMessage; + response->setInt32("err", -EAGAIN); + response->postReply(replyID); + break; + } + + mFlags |= kFlagDequeueInputPending; + mDequeueInputReplyID = replyID; + + if (timeoutUs > 0ll) { + sp 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 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 response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + status_t err = onQueueInputBuffer(msg); + + sp 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 response = new AMessage; + response->setInt32("err", -EAGAIN); + response->postReply(replyID); + break; + } + + mFlags |= kFlagDequeueOutputPending; + mDequeueOutputReplyID = replyID; + + if (timeoutUs > 0ll) { + sp 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 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 response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + status_t err = onReleaseOutputBuffer(msg); + + sp 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 response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + int32_t portIndex; + CHECK(msg->findInt32("portIndex", &portIndex)); + + Vector > *dstBuffers; + CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); + + dstBuffers->clear(); + const Vector &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 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 response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + sp 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 *buffers = &mPortBuffers[portIndex]; + + for (size_t i = 0; i < buffers->size(); ++i) { + BufferInfo *info = &buffers->editItemAt(i); + + if (info->mNotify != NULL) { + sp 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 &msg) { + CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); + + void *bufferID; + CHECK(msg->findPointer("buffer-id", &bufferID)); + + Vector *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 &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 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 &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 *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 0000000000000000000000000000000000000000..6b64e21c6cd67e8930e9b951e631c99d4f952f5c --- /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 + +#include + +#include +#include +#include + +#include + +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(me)->startElementHandler(name, attrs); +} + +// static +void MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) { + static_cast(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 0000000000000000000000000000000000000000..2740d6b5893425a26a40e1f3e59aaf1252c7a31e --- /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 + +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 0000000000000000000000000000000000000000..2171492624d006b575a8e677088461a799dc676e --- /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 + +#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 +#include +#include +#include +#include +#include + +namespace android { + +sp MediaExtractor::getMetaData() { + return new MetaData; +} + +uint32_t MediaExtractor::flags() const { + return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK; +} + +// static +sp MediaExtractor::Create( + const sp &source, const char *mime) { + sp 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 0000000000000000000000000000000000000000..fd0e79c34f0ef4362fec0c8fea940aefaefa7f83 --- /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 + +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 0000000000000000000000000000000000000000..755594a76299e753b3f2dff9a72eb34246484f48 --- /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 + +#include +#include + +#include +#include + +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 0000000000000000000000000000000000000000..0957426b7950d102cab8dccc73c7bc245f25e846 --- /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 + +#include "include/NuCachedSource2.h" +#include "include/HTTPBase.h" + +#include +#include +#include +#include + +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 mActivePages; + List mFreePages; + + void freePages(List *list); + + DISALLOW_EVIL_CONSTRUCTORS(PageCache); +}; + +PageCache::PageCache(size_t pageSize) + : mPageSize(pageSize), + mTotalSize(0) { +} + +PageCache::~PageCache() { + freePages(&mActivePages); + freePages(&mFreePages); +} + +void PageCache::freePages(List *list) { + List::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::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::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::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 &source, + const char *cacheConfig, + bool disconnectAtHighwatermark) + : mSource(source), + mReflector(new AHandlerReflector(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(mSource.get()); + return source->getEstimatedBandwidthKbps(kbps); + } + return ERROR_UNSUPPORTED; +} + +status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) { + if (mSource->flags() & kIsHTTPBasedSource) { + HTTPBase *source = static_cast(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 &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(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 &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 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 NuCachedSource2::DrmInitialization(const char* mime) { + return mSource->DrmInitialization(mime); +} + +void NuCachedSource2::getDrmInfo(sp &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 *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 0000000000000000000000000000000000000000..224ec3378a883f70498970575717a44936645952 --- /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 + +#include + +#include "include/ESDS.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::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 *format) const { + *format = NULL; + + if (mImpl == NULL) { + return -EINVAL; + } + + if (index >= mImpl->countTracks()) { + return -ERANGE; + } + + sp meta = mImpl->getTrackMetaData(index); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp 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 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 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 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 emm = new ABuffer(size); + memcpy(emm->data(), data, size); + + msg->setBuffer("emm", emm); + } + + if (meta->findData(kKeyECM, &type, &data, &size)) { + sp 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 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 &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 0000000000000000000000000000000000000000..7cdb793b594e998941ce264d30d2f8f86eb23fac --- /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 + +#include +#include +#include +#include +#include + +#include "include/OMX.h" + +namespace android { + +struct MuxOMX : public IOMX { + MuxOMX(const sp &remoteOMX); + virtual ~MuxOMX(); + + virtual IBinder *onAsBinder() { return NULL; } + + virtual bool livesLocally(node_id node, pid_t pid); + + virtual status_t listNodes(List *list); + + virtual status_t allocateNode( + const char *name, const sp &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 ¶ms, + buffer_id *buffer); + + virtual status_t useGraphicBuffer( + node_id node, OMX_U32 port_index, + const sp &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 ¶ms, + 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 mRemoteOMX; + sp mLocalOMX; + + KeyedVector mIsLocalNode; + + bool isLocalNode(node_id node) const; + bool isLocalNode_l(node_id node) const; + const sp &getOMX(node_id node) const; + const sp &getOMX_l(node_id node) const; + + static bool IsSoftwareComponent(const char *name); + + DISALLOW_EVIL_CONSTRUCTORS(MuxOMX); +}; + +MuxOMX::MuxOMX(const sp &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 &MuxOMX::getOMX(node_id node) const { + return isLocalNode(node) ? mLocalOMX : mRemoteOMX; +} + +const sp &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 *list) { + Mutex::Autolock autoLock(mLock); + + if (mLocalOMX == NULL) { + mLocalOMX = new OMX; + } + + return mLocalOMX->listNodes(list); +} + +status_t MuxOMX::allocateNode( + const char *name, const sp &observer, + node_id *node) { + Mutex::Autolock autoLock(mLock); + + sp 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 ¶ms, + 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, 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 ¶ms, + 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 sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = interface_cast(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 0000000000000000000000000000000000000000..9769f21ba6106a94cc07eefad3265ed91bda09a4 --- /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 + +#include "include/AACEncoder.h" +#include "include/AVCEncoder.h" +#include "include/M4vH263Encoder.h" + +#include "include/ESDS.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 Make##name(const sp &source, const sp &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 InstantiateSoftwareEncoder( + const char *name, const sp &source, + const sp &meta) { + struct FactoryInfo { + const char *name; + sp (*CreateFunc)(const sp &, const sp &); + }; + + 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 &target) { + mTarget = target; + } + + // from IOMXObserver + virtual void onMessage(const omx_message &msg) { + sp codec = mTarget.promote(); + + if (codec.get() != NULL) { + Mutex::Autolock autoLock(codec->mLock); + codec->on_message(msg); + codec.clear(); + } + } + +protected: + virtual ~OMXCodecObserver() {} + +private: + wp mTarget; + + OMXCodecObserver(const OMXCodecObserver &); + OMXCodecObserver &operator=(const OMXCodecObserver &); +}; + +template +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 *matchingCodecs, + Vector *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 OMXCodec::Create( + const sp &omx, + const sp &meta, bool createEncoder, + const sp &source, + const char *matchComponentName, + uint32_t flags, + const sp &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 matchingCodecs; + Vector matchingCodecQuirks; + findMatchingCodecs( + mime, createEncoder, matchComponentName, flags, + &matchingCodecs, &matchingCodecQuirks); + + if (matchingCodecs.isEmpty()) { + return NULL; + } + + sp 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 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 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 &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& 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(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& 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& 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(¶m); + param.nPortIndex = kPortIndexOutput; + for (param.nProfileIndex = 0;; ++param.nProfileIndex) { + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoProfileLevelQuerySupported, + ¶m, sizeof(param)); + + if (err != OK) break; + + int32_t supportedProfile = static_cast(param.eProfile); + int32_t supportedLevel = static_cast(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& 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(profileLevel.mProfile); + h263type.eLevel = static_cast(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& 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(profileLevel.mProfile); + mpeg4type.eLevel = static_cast(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& 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(profileLevel.mProfile); + h264type.eLevel = static_cast(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 &omx, IOMX::node_id node, + uint32_t quirks, uint32_t flags, + bool isEncoder, + const char *mime, + const char *componentName, + const sp &source, + const sp &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 &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 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 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 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 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(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 *buffers = &mPortBuffers[kPortIndexOutput]; + BufferInfo *bufInfo = 0; + for (size_t i = 0; i < buffers->size(); i++) { + sp 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 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::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 *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 *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 &from, const sp &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 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 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 &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 *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 *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 = 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 *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 *buffers = &mPortBuffers[kPortIndexInput]; + for (size_t i = 0; i < buffers->size(); ++i) { + if (!drainAnyInputBuffer() + || (mFlags & kOnlySubmitOneInputBufferAtOneTime)) { + break; + } + } + } else { + Vector *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 *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 *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 = 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 *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 *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 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 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 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 *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 = 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(¶ms); + params.nPortIndex = portIndex; + + err = mOMX->getParameter( + mNode, OMX_IndexParamAudioPcm, ¶ms, 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 &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(¶ms); + params.nPortIndex = kPortIndexOutput; + + err = mOMX->getParameter( + mNode, OMX_IndexParamAudioPcm, ¶ms, 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 &omx, + const char *mime, bool queryDecoders, bool hwCodecOnly, + Vector *results) { + Vector 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 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(¶m); + + param.nPortIndex = queryDecoders ? 0 : 1; + + for (param.nProfileIndex = 0;; ++param.nProfileIndex) { + err = omx->getParameter( + node, OMX_IndexParamVideoProfileLevelQuerySupported, + ¶m, 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 &omx, + const char *mimeType, bool queryDecoders, + Vector *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 0000000000000000000000000000000000000000..5e79e788816d24150a0d212e8e51a68b87c85959 --- /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 + +#include "include/OggExtractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + #include + + 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 &extractor); + + virtual sp 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 mExtractor; + bool mStarted; + + OggSource(const OggSource &); + OggSource &operator=(const OggSource &); +}; + +struct MyVorbisExtractor { + MyVorbisExtractor(const sp &source); + virtual ~MyVorbisExtractor(); + + sp 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 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 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 mMeta; + sp mFileMeta; + + Vector 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 &fileMeta, const void *data, size_t size); + +//////////////////////////////////////////////////////////////////////////////// + +OggSource::OggSource(const sp &extractor) + : mExtractor(extractor), + mStarted(false) { +} + +OggSource::~OggSource() { + if (mStarted) { + stop(); + } +} + +sp 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 &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 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 &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 &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 &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 OggExtractor::getTrack(size_t index) { + if (index >= 1) { + return NULL; + } + + return new OggSource(this); +} + +sp OggExtractor::getTrackMetaData( + size_t index, uint32_t flags) { + if (index >= 1) { + return NULL; + } + + return mImpl->getFormat(); +} + +sp OggExtractor::getMetaData() { + return mImpl->getFileMetaData(); +} + +bool SniffOgg( + const sp &source, String8 *mimeType, float *confidence, + sp *) { + 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 0000000000000000000000000000000000000000..eae721b5fb78ac72b5b741532b46e0ce0165e92e --- /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 + +#include "include/SampleIterator.h" + +#include + +#include +#include +#include + +#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 0000000000000000000000000000000000000000..d9858d76464d6bc5432c95bf7a86ceaf8cfdbe21 --- /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 + +#include "include/SampleTable.h" +#include "include/SampleIterator.h" + +#include + +#include +#include +#include + +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 &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 0000000000000000000000000000000000000000..6d331b0d0946d317cd5dd979be995c7756eac548 --- /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 + +#include +#include +#include + +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 0000000000000000000000000000000000000000..bd7a2269023e3e8379bebf8c88519b1c58138281 --- /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 + +#include + +#include +#include + +// Sonivox includes +#include + +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 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 mRetriever(new MediaMetadataRetriever); + if (mRetriever->setDataSource(fd, 0, size) == OK) { + sp mem = mRetriever->extractAlbumArt(); + + if (mem != NULL) { + MediaAlbumArt *art = static_cast(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 0000000000000000000000000000000000000000..35f9c1f7aae81953003767f5ffd3d861ab2e5917 --- /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 + +#include "include/StagefrightMetadataRetriever.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +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 *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 &trackMeta, + const sp &source, + uint32_t flags, + int64_t frameTimeUs, + int seekMode) { + sp 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(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 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 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 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 trackMeta = mExtractor->getTrackMetaData( + i, MediaExtractor::kIncludeExtensiveMetaData); + + sp 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 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 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 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 0000000000000000000000000000000000000000..7481e2e467a6dc72db74e2004fae7136b3f5db35 --- /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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +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 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* 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& 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( + 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 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& 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 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 SurfaceMediaSource::getFormat() +{ + ALOGV("getFormat"); + Mutex::Autolock autoLock(mMutex); + sp 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 0000000000000000000000000000000000000000..b1fcafdafc5033ef9e7c911c0afdb6ecde75d6fc --- /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 + +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 &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 0000000000000000000000000000000000000000..d987fbf1c7317bac469ae0487399c5b8b22985a4 --- /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 +#include + +#include + +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 0000000000000000000000000000000000000000..9df15eb214a0e63c9e591531bcc4c6f5c5be6274 --- /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 + +//#define LOG_NDEBUG 0 +#define LOG_TAG "TimedEventQueue" +#include +#include + +#include "include/TimedEventQueue.h" + +#include +#include + +#include + +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) { + // 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) { + return postTimedEvent(event, INT64_MAX); +} + +TimedEventQueue::event_id TimedEventQueue::postEventWithDelay( + const sp &event, int64_t delay_us) { + CHECK(delay_us >= 0); + return postTimedEvent(event, getRealTimeUs() + delay_us); +} + +TimedEventQueue::event_id TimedEventQueue::postTimedEvent( + const sp &event, int64_t realtime_us) { + Mutex::Autolock autoLock(mLock); + + event->setEventID(mNextEventID++); + + List::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 &event) { + TimedEventQueue::event_id *id = + static_cast(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), + void *cookie, + bool stopAfterFirstMatch) { + Mutex::Autolock autoLock(mLock); + + List::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(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; + + { + 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::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::removeEventFromQueue_l( + event_id id) { + for (List::iterator it = mQueue.begin(); + it != mQueue.end(); ++it) { + if ((*it).event->eventID() == id) { + sp 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 0000000000000000000000000000000000000000..c563ce64b0a1ee859bece0ebee5e8f10ce45ea06 --- /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 + +#include + +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 0000000000000000000000000000000000000000..bcba87413cb22296b4446c6197ed53c19ec739b5 --- /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 + +#include "include/VBRISeeker.h" + +#include "include/avc_utils.h" +#include "include/MP3Extractor.h" + +#include +#include +#include + +namespace android { + +static uint32_t U24_AT(const uint8_t *ptr) { + return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; +} + +// static +sp VBRISeeker::CreateFromSource( + const sp &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 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 0000000000000000000000000000000000000000..90a42c9ae5ef34e97de9d73941e0fe34515bfe5f --- /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 +#include +#include +#include +#include +#include +#include "OMX_Video.h" + +namespace android { + +VideoSourceDownSampler::VideoSourceDownSampler(const sp &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 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 0000000000000000000000000000000000000000..c35a77af2b5e9f05827ec06bff5a487ca6dfc040 --- /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 + +#include "include/WAVExtractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, + const sp &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 getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~WAVSource(); + +private: + static const size_t kMaxFrameSize; + + sp mDataSource; + sp 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 &source) + : mDataSource(source), + mValidFormat(false), + mChannelMask(CHANNEL_MASK_USE_CHANNEL_ORDER) { + mInitCheck = init(); +} + +WAVExtractor::~WAVExtractor() { +} + +sp WAVExtractor::getMetaData() { + sp 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 WAVExtractor::getTrack(size_t index) { + if (mInitCheck != OK || index > 0) { + return NULL; + } + + return new WAVSource( + mDataSource, mTrackMeta, + mWaveFormat, mBitsPerSample, mDataOffset, mDataSize); +} + +sp 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, + const sp &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 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 &source, String8 *mimeType, float *confidence, + sp *) { + 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 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 0000000000000000000000000000000000000000..dac8106a6858edb16802bc06d4ae251b64947f4d --- /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 + +#include "include/WVMExtractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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 &source) + : mDataSource(source) +{ + Mutex::Autolock autoLock(gWVMutex); + + if (!getVendorLibHandle()) { + return; + } + + typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp); + 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 WVMExtractor::getTrack(size_t index) { + if (mImpl == NULL) { + return NULL; + } + return mImpl->getTrack(index); +} + +sp WVMExtractor::getTrackMetaData(size_t index, uint32_t flags) { + if (mImpl == NULL) { + return NULL; + } + return mImpl->getTrackMetaData(index, flags); +} + +sp 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 &source, String8 *mimeType, float *confidence, + sp *) { + + Mutex::Autolock autoLock(gWVMutex); + + if (!WVMExtractor::getVendorLibHandle()) { + return false; + } + + typedef WVMLoadableExtractor *(*SnifferFunc)(const sp&); + 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 0000000000000000000000000000000000000000..9c91134922e7042de9f15fdfa170dc9b236c368d --- /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 + +#include "include/XINGSeeker.h" +#include "include/avc_utils.h" + +#include +#include + +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::CreateFromSource( + const sp &source, off64_t first_frame_pos) { + sp 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 0000000000000000000000000000000000000000..65c1848af53ef9a2486006ba73af5d268f058dcd --- /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 + +#include "include/avc_utils.h" + +#include +#include +#include +#include +#include + +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 &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 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 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 MakeAVCCodecSpecificData(const sp &accessUnit) { + const uint8_t *data = accessUnit->data(); + size_t size = accessUnit->size(); + + sp seqParamSet = FindNAL(data, size, 7, NULL); + if (seqParamSet == NULL) { + return NULL; + } + + int32_t width, height; + FindAVCDimensions(seqParamSet, &width, &height); + + size_t stopOffset; + sp 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 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 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 &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 &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 MakeAACCodecSpecificData( + unsigned profile, unsigned sampling_freq_index, + unsigned channel_configuration) { + sp 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 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 0000000000000000000000000000000000000000..d595686adeac071d3b0961ce12500f1d8374ebd8 --- /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 0000000000000000000000000000000000000000..76f7946229e9f824a4ffe41791f277f37830c7de --- /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 + +#include "include/ChromiumHTTPDataSource.h" + +#include +#include + +#include "support.h" + +#include // 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 *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 *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 @%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 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 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 &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 0000000000000000000000000000000000000000..ecf3fa1954edc420aa66aed63b50a6f15238de0c --- /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 +#include + + +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 0000000000000000000000000000000000000000..f15014ee400e5ed10a927b3b6a4a1d4b87295116 --- /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 + +#include + +#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 +#include +#include +#include + +namespace android { + +static Mutex gNetworkThreadLock; +static base::Thread *gNetworkThread = NULL; +static scoped_refptr gReqContext; +static scoped_ptr 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& 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 *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 *headers, + off64_t offset) { + me->onInitiateConnection(url, headers, offset); +} + +void SfDelegate::onInitiateConnection( + const GURL &url, + const KeyedVector *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 0000000000000000000000000000000000000000..d2c5bc00f32b75b65900f3f38ab3432791fb6c53 --- /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 + +#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 +#include + +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& 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 *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 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 *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 *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 0000000000000000000000000000000000000000..2e431205aa6d7f8512da485ac3f6820d26ac7394 --- /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 0000000000000000000000000000000000000000..fd6de79f612734a4144e2d2c3741f73aff7606fe --- /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 0000000000000000000000000000000000000000..90f96c62440a7a1874c319f85f1a9b6c1d626cd9 --- /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 + +#include "SoftAAC.h" + +#include "pvmp4audiodecoder_api.h" + +#include +#include + +namespace android { + +template +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("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("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 &inQueue = getPortQueue(0); + List &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(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 0000000000000000000000000000000000000000..da0b8ed817dadce84f124112b20a2f6c989cdab9 --- /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 0000000000000000000000000000000000000000..ce7cb1242bc95f6335b5a21e4f9e0815c13959be --- /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 + +#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 0000000000000000000000000000000000000000..2786dcccf2ac07106dfc74d7f49bd46086673cc1 --- /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 0000000000000000000000000000000000000000..815456c53d3906bdd38398ecd2a5c5c5c8a19c6e --- /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 0000000000000000000000000000000000000000..ab36c6af165128b6d313d27930eea6319ce9687e --- /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 0000000000000000000000000000000000000000..ed7fb7a9d22c9c024ec0e643bd015580ca20364d --- /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 0000000000000000000000000000000000000000..96ecd2748e00ca4ac3f8cd17e666dea05b6b5a2b --- /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 0000000000000000000000000000000000000000..85fb85198b37067cca94b0ffd0d103b6d33089ea --- /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 0000000000000000000000000000000000000000..2669f877582f3058094b4af65d0a803757a5b713 --- /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 0000000000000000000000000000000000000000..34f4f607cf9a841054c18915615e038325cac1aa --- /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 0000000000000000000000000000000000000000..1b5d252839fc45e111638a052f4be365476f8f20 --- /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 0000000000000000000000000000000000000000..031216a2aad866c5e3bc43f80b131eb827f0c978 --- /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 0000000000000000000000000000000000000000..e75c79e3300daceae7d945a7d61b6c1d063bb6c7 --- /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 0000000000000000000000000000000000000000..ee32398844a1abce62e35c50d982dd1b6748e08f --- /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 0000000000000000000000000000000000000000..0f0dae2a18ebedadf5427e0c0e5c44b9a391585e --- /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 0000000000000000000000000000000000000000..40475029c55bb8fbe9a92ac53e738e259974bbfe --- /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 0000000000000000000000000000000000000000..5ec3f6924918e81eb8cb77c7242b27caac92a928 --- /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 0000000000000000000000000000000000000000..c93848e6f3b12002955a90d4e6a9bd241c941585 --- /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 0000000000000000000000000000000000000000..4fb35351e9615f7ecdc1d4255446867da6594c50 --- /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), "ient); + } + else + { + tmp_q1 = nL_man[aux1] >> (-tmp_q1); + pv_div(tmp_q1, tmp_q1 + 0x3FFFFFFF, "ient); + } + + /* + * 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, "ient); + /* + * 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), "ient); + } + else + { + tmp_q2 = nL_man[aux1] >> (-tmp_q2); + pv_div(nrg_ref_man[c], tmp_q2 + 0x3FFFFFFF, "ient); + 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, "ient); + + /* + * 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, "ient); + /* + * 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, "ient); + /* + * 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, "ient); + + 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], "ient); + 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, "ient); + 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 0000000000000000000000000000000000000000..2a6ae5775e7ff67f2f7c5fa531e9c022c013748e --- /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 0000000000000000000000000000000000000000..e557aa1f4c08b940986dad7b175783020ad4004a --- /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 0000000000000000000000000000000000000000..28bd6deb5d189d5302a2d4398128cec7f00ec189 --- /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 0000000000000000000000000000000000000000..325b5cd839cf0a33af29ba5f5a195da53365beb0 --- /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 0000000000000000000000000000000000000000..17f3b87f65b1d8eb585126e1b841be2ad53a1b23 --- /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 0000000000000000000000000000000000000000..9293d4795e0c2e07408ce22e08e712a07ebd6553 --- /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 0000000000000000000000000000000000000000..75bd4ba2babccec66de6177220e166e373bbaaf2 --- /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 0000000000000000000000000000000000000000..6f8fcb291b0041b87998da47a3596b9fd73cc6f1 --- /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 0000000000000000000000000000000000000000..a21a814a0cc674ae5797fdcbaae957318a00bb2d --- /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 0000000000000000000000000000000000000000..3d5e82be38b4cd793eec44f896ae61ba046822d1 --- /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 0000000000000000000000000000000000000000..0d1561b5575352f2fbdd7aab71ff9b0072f9d880 --- /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 0000000000000000000000000000000000000000..41cd18785fe3564f08e83ffd5d2202e2993c84a1 --- /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 0000000000000000000000000000000000000000..a9c3551cf1db536e4bd1f24db6716baf72cf223c --- /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 0000000000000000000000000000000000000000..5298b191a00aab98da1bfcc18ceb86b25a4bccf6 --- /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 0000000000000000000000000000000000000000..ffa980d2f77fa4d0a329a84afc70dbd9234cdb38 --- /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 0000000000000000000000000000000000000000..7fdaaf74d437fa65f673a27616484338841e031e --- /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 0000000000000000000000000000000000000000..41c9259afee3d041ff824cd650133b807a30a0e5 --- /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<=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 0000000000000000000000000000000000000000..bce73ba4bd6a60eea1a5e86a24c43f7dda02e9c1 --- /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 0000000000000000000000000000000000000000..5edecf161b820f4e8ecd09306da4a48300317b35 --- /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<=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 0000000000000000000000000000000000000000..c2bf1d20ae37a5b229eac67cdc5d51682ba9bd3f --- /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 0000000000000000000000000000000000000000..eaf82802ce0d1124a85bb64faad85a7e2c107770 --- /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<=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 0000000000000000000000000000000000000000..2738e80897995eebcf5ec653ac34a8ff536c8cc8 --- /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 0000000000000000000000000000000000000000..08b541598f032fe44f984100c7d136488c7a706b --- /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 0000000000000000000000000000000000000000..bf6ad1500f00c971f8d815e81eb9e5fc6988870f --- /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 0000000000000000000000000000000000000000..68244bb079f1147776c98947b44e4ead9342ec2f --- /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 0000000000000000000000000000000000000000..5f8464372e95182ad40ac22e12885368688278b0 --- /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 0000000000000000000000000000000000000000..5d0e6281842a4ade66f9cbd9d5aac25ada140742 --- /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 0000000000000000000000000000000000000000..788b5e9337d5d2c04120a4da6e00642cbfc4260a --- /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 0000000000000000000000000000000000000000..57b32816448d4e26aad93fbebc63bf502d606437 --- /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 0000000000000000000000000000000000000000..010b6f8a54dce6cfd5f328e8db488173e4313359 --- /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 0000000000000000000000000000000000000000..10064065d1916c440228ee9f33c772daf97da500 --- /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 0000000000000000000000000000000000000000..b5fdc0870a2b7ee790f38d8b049b436ba8cc3b5e --- /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 0000000000000000000000000000000000000000..a460d138b297a19840505f7424e38b33abd6e95f --- /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 0000000000000000000000000000000000000000..1b021ffb581b7873c2cb4024155b07d26f8e08b2 --- /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 0000000000000000000000000000000000000000..b6c8a900a87d3ebadd73cd708c9820f86da3e4db --- /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 0000000000000000000000000000000000000000..5b2a43fdbfd6e272db420896a555fa9f48a3d9dd --- /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 0000000000000000000000000000000000000000..16e43a484938c3d0ea35adf99f803ea77f69a3e2 --- /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 0000000000000000000000000000000000000000..d9f866994e2e7a2476dad4fb7e0c5b1b9964180e --- /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 0000000000000000000000000000000000000000..eff00dd2b891462f73d25f5a061ed95c8ffda9c0 --- /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 0000000000000000000000000000000000000000..83ccccecef5d9d0c8a3a2d1477223afe5da72e80 --- /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 0000000000000000000000000000000000000000..157d47119e7e678345164549bb88148224406bba --- /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 0000000000000000000000000000000000000000..c4b933eb8d682f0e0045f9346219231f7413eeec --- /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 0000000000000000000000000000000000000000..3eca43899229892f72d91fa5bb7ca61385e554e5 --- /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 0000000000000000000000000000000000000000..778c88cb350790c81f4acaa7a534037dd91e74d3 --- /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< 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 0000000000000000000000000000000000000000..a846b9f8abd25110c217cfb0112fb9836418d364 --- /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 0000000000000000000000000000000000000000..571cc9856763e290b7113ffe9315538675a10e69 --- /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 0000000000000000000000000000000000000000..2fcfe378976c92971b856de748bd44065213efa3 --- /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 0000000000000000000000000000000000000000..8e7acb311535873b082e24789e84328ef56b052e --- /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 0000000000000000000000000000000000000000..c517e7e666597afc86624cebfa53e9ceb9f3bdfb --- /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 0000000000000000000000000000000000000000..4a8a0d6a83f76fb94c0920ce66ff6296daabc9e7 --- /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 0000000000000000000000000000000000000000..2476b875abe475a8690234f0e3b83943923a2ffa --- /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; jusedBits < + (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 0000000000000000000000000000000000000000..d147bc5b438784a7efcfc3a006f31a288056a47e --- /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 0000000000000000000000000000000000000000..b85c7df8d79069b359a49ffaecba5d06e6f07521 --- /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 0000000000000000000000000000000000000000..5978906474f6f09470ac919e4ec7d17edb695a66 --- /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 0000000000000000000000000000000000000000..964f7666665cc83c9a33ba39c7cf146aeb6078c8 --- /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 0000000000000000000000000000000000000000..3d1e1f1e122a66b7940f9674b8ae60dda626a6e7 --- /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 0000000000000000000000000000000000000000..230cef5e7445170d703c8c9292e159c5ce35cb1f --- /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 0000000000000000000000000000000000000000..dc58976626e12943525df78c69fb41cf9c295c2e --- /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 0000000000000000000000000000000000000000..6869c54c6aac70e19b93a55f1c04ea87512441da --- /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 0000000000000000000000000000000000000000..f4ab2f798916e4ffcecd31b464af7a7d9c375e21 --- /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 0000000000000000000000000000000000000000..8ab108f926ab495f4c3dba542595054dabfaf1f2 --- /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 0000000000000000000000000000000000000000..5bcbe5347d23b6c4728be3f18344af3ef1715ad1 --- /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 0000000000000000000000000000000000000000..64397cf7d58b26c2c238d161a2e4511bb7240ea6 --- /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 0000000000000000000000000000000000000000..04cbf493dd873208cc94a3ef155147e28eeb1077 --- /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 0000000000000000000000000000000000000000..72862e78377fb09bbc386d67e20512933ffe152e --- /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 0000000000000000000000000000000000000000..08ccc4ace8d01bd9edaa86f0671ba9e6dbc398ff --- /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 0000000000000000000000000000000000000000..17b5490f2ed4c8a5a88bbcff24e36dd5742f6e7a --- /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 0000000000000000000000000000000000000000..8a1e74bca6e87e45f03f3106ae4ae0936f424cda --- /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 0000000000000000000000000000000000000000..8bc341168f17e3f51765ef1bf698af561dd07113 --- /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 0000000000000000000000000000000000000000..3ac27563cd84e69998f757f2734e44e05db846c8 --- /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 0000000000000000000000000000000000000000..13afa05a6e3cdb12eee4bb6fc5efb11c8c0d2aaf --- /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 0000000000000000000000000000000000000000..092f3978701c84615e2945d6f5c8a91272a45e6c --- /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 0000000000000000000000000000000000000000..b7cfcf59cc21716c8464b9ea152ba6a18b91710e --- /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 0000000000000000000000000000000000000000..d64087f9ba756406e4608e8e876690c62f71dd05 --- /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 0000000000000000000000000000000000000000..3563f71eb4d48456ea4cb26013925b586c3964ae --- /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 0000000000000000000000000000000000000000..0534c139b832407a2e46d2dbb6472e66d29d5d57 --- /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 0000000000000000000000000000000000000000..82f140bdf795f65778e3b93495da7866b48eff2c --- /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 0000000000000000000000000000000000000000..65c00ea0142ed831c295612c9112678ee146d15f --- /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 0000000000000000000000000000000000000000..7c77da51ab765ca11b02d6819b07b2e714e86c06 --- /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 0000000000000000000000000000000000000000..17204ccb948a1acac7c473cfb42c902b9eb4c082 --- /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_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 0000000000000000000000000000000000000000..b94ef8e39d2ed30efc921ca91723546e729f3758 --- /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 0000000000000000000000000000000000000000..6bddd573694736c13db7ba2611d9c162111f565e --- /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 0000000000000000000000000000000000000000..646ba46620eb664b06685b76a9ef3131af0b2183 --- /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 0000000000000000000000000000000000000000..f9c24f4cf8eb4fccfd453326d91290fa891b1b71 --- /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 0000000000000000000000000000000000000000..267f534118fc1d643a599e83b1c69689e05f1e0f --- /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 0000000000000000000000000000000000000000..b6ec365c1dcd2b629daebb5c083e8d7afaf95b27 --- /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 0000000000000000000000000000000000000000..8094b1aba185312f598195e5aabb908370b99ffd --- /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 0000000000000000000000000000000000000000..38ddc0b08dff05373f8ea1168fa1823b6128e646 --- /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 0000000000000000000000000000000000000000..10fa16018f64a4f69c4823641d87217b0ffd5299 --- /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 0000000000000000000000000000000000000000..e32c61d568d95ed1bf081564100dbd7cea227941 --- /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 0000000000000000000000000000000000000000..341a3d4de145d3cc84c813be69f0afded5bdc190 --- /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 0000000000000000000000000000000000000000..445d2f2930ee9c76f475af99b15c29c395158a48 --- /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 0000000000000000000000000000000000000000..e0b021baef8bcf3062d5379edef138a0000fa78c --- /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<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 0000000000000000000000000000000000000000..731484f0750588075e964a6b9bc1c58e3a398577 --- /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 0000000000000000000000000000000000000000..e854be51316104896171688a2faf1ecf44329976 --- /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 0000000000000000000000000000000000000000..3c4fc4c066a9868bf4920f1debf06fe8b74cf609 --- /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<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; iusedBits += 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 0000000000000000000000000000000000000000..3ba976ac9b8e561c47d7e0c9f6f9b6d3e986922e --- /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 0000000000000000000000000000000000000000..0f909cdab2c6bd1d3c20d8e6919ca5bb36fc8b1b --- /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 0000000000000000000000000000000000000000..8d76744358844a45bfa42ae8804d25aa4df78581 --- /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 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 0000000000000000000000000000000000000000..2fd34f14c76567b308f27c678f6c674a6c971fd9 --- /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 0000000000000000000000000000000000000000..a35fed04d85d4bfb72bb0ad6b70b829fbdd5e90f --- /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 0000000000000000000000000000000000000000..d097af1f90d6fe89ee15ace66dbf1f7ad84cd0e1 --- /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 0000000000000000000000000000000000000000..30f38fa2ce118b17f923bd1fad05675bbdfe2d56 --- /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< 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 0000000000000000000000000000000000000000..890a6fb95fb3133a233fec1e24f5157e37206359 --- /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 0000000000000000000000000000000000000000..e5a9c59e8010f3a7fca76717fa524098fdcb007d --- /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 0000000000000000000000000000000000000000..030ae23f144ef2061c78eb1496f003060f70abc7 --- /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 0000000000000000000000000000000000000000..b18c12d5a391cd66bb186788341ba895abb89f91 --- /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 0000000000000000000000000000000000000000..8b644dc8ee5c889e5024ff9c340b359caf6a75cc --- /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 0000000000000000000000000000000000000000..324fe9ee490d15c0bb448054b59256b30fcd49a6 --- /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<=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 0000000000000000000000000000000000000000..afade0789b7099d0f75a2185fbaece9a5cedac26 --- /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 0000000000000000000000000000000000000000..ac9773b58a78863f3d40a647ff026411ea14df15 --- /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<=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 0000000000000000000000000000000000000000..12c685a8fa06e875794dfde7e63afed11a4bf486 --- /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 0000000000000000000000000000000000000000..8f040cef96c562de559bd0df62ff16648ddbfc35 --- /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<=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 0000000000000000000000000000000000000000..ad7eaae18ba0670b55d779c5df91e886afd2a191 --- /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 0000000000000000000000000000000000000000..ad67f2095febd70202369cf66cf76a85c894e5f6 --- /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 0000000000000000000000000000000000000000..583775030cfb0a0be925f6262e5e7af62ab0d9a5 --- /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 0000000000000000000000000000000000000000..7bdcdcd47ae3a8d3cf513caa6853b2f5d5b5c2f2 --- /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 - 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 0000000000000000000000000000000000000000..fc47dd39f357b2a2a7bc792f0a83462bc82b63c6 --- /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 0000000000000000000000000000000000000000..844fa0e80e37165880c79ab16b81663303f19a2f --- /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 0000000000000000000000000000000000000000..106298a1fe4ed926c642b8c0fdef7c4cadd6b454 --- /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 0000000000000000000000000000000000000000..823da07567d95e8e94f952afa94af626c3d1a739 --- /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 0000000000000000000000000000000000000000..84a7ec862cbb767a70d88aa668ae84847a559f73 --- /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> 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> 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 0000000000000000000000000000000000000000..8b958674fd70a3dc1241f5384ee3c0d1016f650d --- /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 0000000000000000000000000000000000000000..5b4f1c57c871746d44d827fc3b330284a6339ea6 --- /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 0000000000000000000000000000000000000000..97ed7307a32188b53a17191bf8fe0528c7bf0bd7 --- /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 0000000000000000000000000000000000000000..aee47d6f8504ca4ca0b3b817f11b9796f09333d8 --- /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 0000000000000000000000000000000000000000..dadc3d0cfaaaf5cee2dd39587fc1f5e862bd3b7b --- /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 0000000000000000000000000000000000000000..69e4c466fedf1ca80fc74c174a1adde155fbb691 --- /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 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 0000000000000000000000000000000000000000..014934be67c574643c28f704855f8608cd7815a5 --- /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 0000000000000000000000000000000000000000..c361db161c09b3e9d9909463d1c7f323f2c0d3f6 --- /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 = ¤t_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 = ¤t_frame[0]; + + pQ_format_start = &q_format[0]; + + num_sfb = sfb_per_win[0]; + + FOR (wnd=0; wnd 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 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 = ¤t_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 = ¤t_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; wndweight_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 0000000000000000000000000000000000000000..c655270116d6c667b6ed51f46aa590b1a4038f11 --- /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 0000000000000000000000000000000000000000..e52a1e852ca771b577cd70a1ce1994ce371af149 --- /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 0000000000000000000000000000000000000000..d76ac756d8a41d83fdff6734bb7e99e75b6dc5d4 --- /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 0000000000000000000000000000000000000000..df371e8485633527da5cb01f8b2d3652b7f93124 --- /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 0000000000000000000000000000000000000000..b8d5a8078ca78ad4e7eb6246fb28e27f2cf51c3c --- /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 0000000000000000000000000000000000000000..709cbf20e2f0c040d17d4f2c282405b6e41dd044 --- /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 0000000000000000000000000000000000000000..19f82e320917fdcfdb586a701100ec4ea0ef252f --- /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 0000000000000000000000000000000000000000..5b3e1c995f370badf12adc4ea6800c389f166e4c --- /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 0000000000000000000000000000000000000000..6081c46d341945ecb1acce82e1d4e5717faf1522 --- /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 0000000000000000000000000000000000000000..563c2807960eb5843f5528c5f1a2c9b8172be706 --- /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 0000000000000000000000000000000000000000..fbbec7886ab04447795a998487041254e3826c95 --- /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 0000000000000000000000000000000000000000..1f25516273bee21b8caedcadfc278b9e958257c8 --- /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 0000000000000000000000000000000000000000..a00e6e20b99ada3d596146fcf920cd8ee9bbeeff --- /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 0000000000000000000000000000000000000000..4cfe720dbe9ed6b926327599ebe265dd027bd0ce --- /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 0000000000000000000000000000000000000000..c892a8cbf1af3b6bb0118d52d60de00559110967 --- /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 0000000000000000000000000000000000000000..f2d50c10a6a30ec245c96d76b669ec4fa65f2935 --- /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 0000000000000000000000000000000000000000..7b6f79fe6196d12c8a5c14b77fa91cc01668d0d2 --- /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 0000000000000000000000000000000000000000..2446de2b11271ada6fb1f40fb1224167719a7882 --- /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 0000000000000000000000000000000000000000..c44b13c76fc44e2dd2928a01a86a67782872e67a --- /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 0000000000000000000000000000000000000000..48432f896ce13440556c992c71d71e17b830f084 --- /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 0000000000000000000000000000000000000000..0358acb9a5af18da988e971a48be5fd7551c4588 --- /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 0000000000000000000000000000000000000000..81761a6c797510d25273c4c712dd9e4c84215b52 --- /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 0000000000000000000000000000000000000000..b4e987663e403787e5cd5e45b5e20cb7378d809b --- /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<=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 0000000000000000000000000000000000000000..ab15651f8ee28056a2ac921321c9c250cd64d290 --- /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<=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 0000000000000000000000000000000000000000..d5f152f424dec78120f1b772aeb3561bb951c4a0 --- /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 0000000000000000000000000000000000000000..77fd8a7179d368a18a194cd1e7e1dd79c1edad2d --- /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 0000000000000000000000000000000000000000..231d9c3fb5a0dd520f0dfdd5cf2d465da69dc550 --- /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 0000000000000000000000000000000000000000..c7ed60b91859f9ba4d923643027d40e74a6995d0 --- /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; envnoEnv; 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 0000000000000000000000000000000000000000..5212bf8d00bbe71d24b32e23b7935aae36d1f1ed --- /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 0000000000000000000000000000000000000000..03a53df9aee0b3704085581b98dff3428d274908 --- /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<=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 0000000000000000000000000000000000000000..19cda79b0fe215a1b95a90e72f2ce2d7143e1daf --- /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 0000000000000000000000000000000000000000..d5b2ad4b686d05a72f3e9a2c979fb1d6f59b07cc --- /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 0000000000000000000000000000000000000000..241da34cf963ae333e19689e11545ead340d7de6 --- /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 0000000000000000000000000000000000000000..a672d94c763498c00ba90ac1c8d4805e77250b24 --- /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 0000000000000000000000000000000000000000..6776d6e7fb327b9f0068063f07ce1b0643c9dfee --- /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 0000000000000000000000000000000000000000..c2a025aa9600e5b9a487dcec51fcd29433070e8d --- /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 0000000000000000000000000000000000000000..7669be3b227961b2e473bc10eb7adaf66c904c1a --- /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<=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 0000000000000000000000000000000000000000..6c3482e2601298605fa72306df953e26cf22dcf3 --- /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 0000000000000000000000000000000000000000..933b07e16a0f6bad16a25816f1b6ce6f16a285a6 --- /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 0000000000000000000000000000000000000000..0140a1f79c02687672b392013d1a708c498d2c5a --- /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 0000000000000000000000000000000000000000..4ff238538c5d26eefc83325afea7392acc4a409f --- /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 0000000000000000000000000000000000000000..fbc0d80c7c955cdf6654fe4a7e24bd3315a33345 --- /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 0000000000000000000000000000000000000000..4fbd016507e6bc67855dab8c612c0738d05b5b4a --- /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 0000000000000000000000000000000000000000..d7242dda51a5568b89504a6359b74cf309b3fa7b --- /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 0000000000000000000000000000000000000000..7027b5cba2c620c1312caf19066b95e4546fe539 --- /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<=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 0000000000000000000000000000000000000000..6c307813bce7ec28115611f352d12477b0201521 --- /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 0000000000000000000000000000000000000000..a0e8c38631a7f293d72295b2c7bda42517566d6b --- /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<=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 0000000000000000000000000000000000000000..80a73a82980c9fa0d6ce2131e087ca15c7857e6e --- /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 0000000000000000000000000000000000000000..c49eb3d834809b3036bbe52025051c9844fbecc6 --- /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 0000000000000000000000000000000000000000..e2fec5315104f431528fa473dab4b2a452395b5e --- /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 0000000000000000000000000000000000000000..813b55da8901a7ef06b25b917ecf87c8abd3f8da --- /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 0000000000000000000000000000000000000000..58b025a3b704d425b96eb8142f08d915e89caeeb --- /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 0000000000000000000000000000000000000000..87b264d2831a84bf89905b0bc1bf904f8773e0de --- /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 0000000000000000000000000000000000000000..8181dd0352aa7a745386ec45f22758e6528bb3b9 --- /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 0000000000000000000000000000000000000000..dee66bc758c3c37b9e0d5d2148355798ecb82629 --- /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 + +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 0000000000000000000000000000000000000000..86d2487923ade363f0af3a966de540440a487665 --- /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 0000000000000000000000000000000000000000..2dfa8a0c081842d0f1c98864cd5cdd19aaf189dd --- /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 0000000000000000000000000000000000000000..69cbe9185ac00d3a6244d6da64720f34394c4bd8 --- /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<=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 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 0000000000000000000000000000000000000000..dce080e395f7963afe6f5f9ed37b391484d4fe0d --- /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 0000000000000000000000000000000000000000..8dfca23f5fc192530c48ff28176e7db16aff7e81 --- /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<=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 0000000000000000000000000000000000000000..04bfe93617b0b07c3ea03b19699207d1e65efbcc --- /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 0000000000000000000000000000000000000000..54319b1220c016e902c24fa9b24de91a2bbb942c --- /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<=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 0000000000000000000000000000000000000000..145013a642f9446180981b1e37e32b67dfd1c1fc --- /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 0000000000000000000000000000000000000000..065fa38002bb58d3fd0eaf3a3e998b601d6321d7 --- /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<=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 0000000000000000000000000000000000000000..45d6f52f8863a2f12fc5b63c55191530a7389fb1 --- /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 0000000000000000000000000000000000000000..7806f886219692ea7c9a5068732843bd1f74955e --- /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 0000000000000000000000000000000000000000..9208fa83da6a6e8c9daac7b2e9fb46d106dddb43 --- /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 0000000000000000000000000000000000000000..7a279dc6f43c6c17f060fc8e8e783b2267e5809f --- /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 . 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 0000000000000000000000000000000000000000..7cdecd04515be9f23223bd6cbf801a6c7f4d3497 --- /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 0000000000000000000000000000000000000000..146ba0ffbd568d8aeb4692bd816bdc8b447febe4 --- /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 0000000000000000000000000000000000000000..c10423b18d01ca9c7e48689c8f8e485827119ad6 --- /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 0000000000000000000000000000000000000000..d183d842e414585e87836540343eaac6d5b1dde8 --- /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 0000000000000000000000000000000000000000..52669669c3e76218f4fe6b0dea70eb414dc0d425 --- /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 0000000000000000000000000000000000000000..63a9d53d5ceed24d7fd31e10420aefd52c4c9767 --- /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 0000000000000000000000000000000000000000..1164129a9a97d2c38b28df88d54d333020c07c32 --- /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 0000000000000000000000000000000000000000..c8968cb8c8fb1645ef7fd1d405739ec46145d585 --- /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 0000000000000000000000000000000000000000..7fd49d348adf98acce2e95dd8fc059649d0490e1 --- /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< 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 0000000000000000000000000000000000000000..69250e75e5869827e2f3cffc54e24f1124c1182c --- /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 0000000000000000000000000000000000000000..40b2f137af5bc2ca83bc7131280073583bd6a9af --- /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<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 0000000000000000000000000000000000000000..90061195c87945f74601635a8ccab011cf5192fb --- /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 0000000000000000000000000000000000000000..7f456d5e212abf5486c42fcc9a4681af0d389b59 --- /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 0000000000000000000000000000000000000000..554fc2d00f691f3140155d07ee2b22ee2bf91d79 --- /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 0000000000000000000000000000000000000000..e58e5fc31efc9a8d8adfc3b1d2c14f57fbfd65ac --- /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<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 0000000000000000000000000000000000000000..7d7d746688c829700bf5f1eed82ffa14730faccd --- /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 0000000000000000000000000000000000000000..609463aeac1dbdefeac0c74bd49118db7783769a --- /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 0000000000000000000000000000000000000000..83dcc319a96698459dd3c3362b4ed781ba654c1f --- /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 0000000000000000000000000000000000000000..9b710037a64f3dc2a8dc4ee09b436defc3a99bc9 --- /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 0000000000000000000000000000000000000000..f7a36022dda410bef22b0ba8cf6465fba9a9597c --- /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 0000000000000000000000000000000000000000..d0ffb0b54733d1d3347f49d566a9b0c5eca66162 --- /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<=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, "ient); + + 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, "ient); + 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 0000000000000000000000000000000000000000..2ce99ec5b180292a37a9c6befa7326eb5e0ace74 --- /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 0000000000000000000000000000000000000000..c8b81b22ecc625f8ff8e486efd9a92a1220252e2 --- /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 0000000000000000000000000000000000000000..68785379d70affc4f5b953ba7853ce52506e4126 --- /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 0000000000000000000000000000000000000000..9db32214642b636929959a26a1beccd5faf2eed6 --- /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 0000000000000000000000000000000000000000..3df05310e01fa147b01c9a30e2aba035d027c513 --- /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 0000000000000000000000000000000000000000..d54a699b8c9a0387ee6f7cbd005da6539a84e89c --- /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 0000000000000000000000000000000000000000..3bb4398e5d153a4ce8d96e5e9c7bd76c80fa137b --- /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 0000000000000000000000000000000000000000..9e6b1be558f50609daa8314ad4c7fc457e9192b1 --- /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 0000000000000000000000000000000000000000..9472ffc71028f08022b411ed2005d1c2a163593f --- /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<=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 0000000000000000000000000000000000000000..7a539447d8d89b6b7528f0959464e98f5762952c --- /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 0000000000000000000000000000000000000000..8519b175ac36f9d405dbc648122b5420334f35e7 --- /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 0000000000000000000000000000000000000000..ba7c1f37c0c16ad290a747522a62e9318651fbe8 --- /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 0000000000000000000000000000000000000000..771bb32dc7ea1b431bc2adbab56f3a97d73b9f28 --- /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 0000000000000000000000000000000000000000..19c04a9843d12019a326b47ac05b2b8a2b398be8 --- /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 0000000000000000000000000000000000000000..290fd18477a78b2acdb36a3a68726b1d5a710043 --- /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 0000000000000000000000000000000000000000..bfbdb6767ec3eeecbd88da8fe99a24481d7d97c7 --- /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 0000000000000000000000000000000000000000..c2b007ab73c0644cf94f043bb42c73dc4696868b --- /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 0000000000000000000000000000000000000000..2f49aea9c8ee9bfdbb617a7c148fd135a005bd95 --- /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 0000000000000000000000000000000000000000..2ed76dda2a91340095e04c961726274c2a0077e7 --- /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 0000000000000000000000000000000000000000..60e806d59a8b5b8d71d4964cd6cb874eb639d464 --- /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 0000000000000000000000000000000000000000..7fce46bcb79c81d2baa9044353a2d71b3097a1ed --- /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<=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 0000000000000000000000000000000000000000..b9498305fe652609b0ded5815e020ddd0ee60b6c --- /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 0000000000000000000000000000000000000000..92b22f771f81ce347a31c9f3bcacc4ceb36bd90e --- /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 0000000000000000000000000000000000000000..bbca3b9a9d8953078407d33250d40e76ac221996 --- /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 0000000000000000000000000000000000000000..fc3d38fa784639111d8097d66e0da72a4a9f904c --- /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 0000000000000000000000000000000000000000..88283c694222c293cf9d1356ee213093c0dc3155 --- /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 0000000000000000000000000000000000000000..2126e47cdd3cf927b48149661ad8e82f18e445b8 --- /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 *) °reeAlias[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, "ient); + + 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, "ient); + /* + * 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, "ient); + + 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, "ient); + overflow_flag = (quotient.shift_factor < -2) ? 1 : 0; + temp1r = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */ + pv_div(temp1i, ac.det, "ient); + 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, "ient); + overflow_flag = (quotient.shift_factor < -2) ? 1 : 0; + temp0r = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */ + pv_div(temp0i, ac.r11r, "ient); + 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 0000000000000000000000000000000000000000..0e9c928341b0534139e293292160027c45229edf --- /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 0000000000000000000000000000000000000000..60072ddf229748c8944695822b1b1f3b06986343 --- /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 0000000000000000000000000000000000000000..51285c5e5e9cd8160c45c43b2a048b693a0e388d --- /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 0000000000000000000000000000000000000000..657d03215da1d6f88e955bac63aaeec05ac30739 --- /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 0000000000000000000000000000000000000000..b6f99f8d34793d1bd4353bf2988e0ba3037fb4a1 --- /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 0000000000000000000000000000000000000000..3d7ad8c7102a4ee55a7547669848be6f719d69b3 --- /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 0000000000000000000000000000000000000000..3b587dcc0342e8e8266f5e891cd8aebd5d7f1370 --- /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 0000000000000000000000000000000000000000..e92abb1f1ec40306ad8eeafa5ba0ee2fdad78b1b --- /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 0000000000000000000000000000000000000000..b7a266aeeb67e70dde2e9998b34c1891da5d0b65 --- /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 0000000000000000000000000000000000000000..42789aeee02005ffc5f6cbae557fd409d84306ac --- /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 0000000000000000000000000000000000000000..7bfb2725a702d1f4014f8f7a5f85bfc5f4ef4c7f --- /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 0000000000000000000000000000000000000000..8d861580154e86fde1180d28d9f90fe80c553cd5 --- /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 0000000000000000000000000000000000000000..e61abda763928fe29a32a21c3d21dd804a73b909 --- /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 0000000000000000000000000000000000000000..ba514f438e8f871eb1039177f208e7679a82b308 --- /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 0000000000000000000000000000000000000000..36adb0449d28986b8523b1889c84d871fadcee10 --- /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 0000000000000000000000000000000000000000..833ace303d01571a51e9137967776ff23d6d597e --- /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<=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 0000000000000000000000000000000000000000..586214c8c5d4d1f4bdb86cfdb83003e29b6a2aa9 --- /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 0000000000000000000000000000000000000000..868819a5c8fd5d2428884471f0e8ada68a2e4a9e --- /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 0000000000000000000000000000000000000000..8d17ffaf59d65a9e5445072df2b6f8652c069b95 --- /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 0000000000000000000000000000000000000000..2220fce1b71ba03cbd9beaeeac4ee707c5b11450 --- /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 0000000000000000000000000000000000000000..74cf5b984f1ec1e5b4a9f4f5a8bdab08b6978009 --- /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 0000000000000000000000000000000000000000..487496f7b2053ea09f83f660ffbf0c48eb3f1bc5 --- /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<=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 0000000000000000000000000000000000000000..211358662082a4dc8f219f3a962a4cc95ea351cb --- /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 0000000000000000000000000000000000000000..810a34ab75c52a858a13658e0ec6eadd8241860c --- /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 0000000000000000000000000000000000000000..0ff94a56226384077f00074036ee6524c9bafefc --- /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 0000000000000000000000000000000000000000..18bd5d9fa78e857e3f3cc665371518dbff813721 --- /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<=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 0000000000000000000000000000000000000000..4acf3aaf52e668211c83665bfed00bab317c79ff --- /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 0000000000000000000000000000000000000000..5a119410a8ab5a94328f894e4c0da48897fa6c6c --- /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 0000000000000000000000000000000000000000..8043b3b57925d346be46fe4773b3332c06e63664 --- /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 0000000000000000000000000000000000000000..f2d3a3e26f0a2c7f4203ad27b401067fb28f9685 --- /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 0000000000000000000000000000000000000000..0cc17077ff6f0dee43e438addc84863b5d926372 --- /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 0000000000000000000000000000000000000000..5feb8039dd69409033d174423fedc3e0a0165386 --- /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 0000000000000000000000000000000000000000..a4658e3ecdf376d3e6a25ee28c4951e7d0060107 --- /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 0000000000000000000000000000000000000000..3e27c70ad4b911e7bb28fec5f78d35993e6095a1 --- /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 0000000000000000000000000000000000000000..c1418e3b4ac3e222cf1b47cb88cce5125c1cb8b3 --- /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 0000000000000000000000000000000000000000..042c488bae1f2cef08f69b01b77579f440078c58 --- /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 0000000000000000000000000000000000000000..db31a6381120a63ba88c052ed7559e5f22da814f --- /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; i0; 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 0000000000000000000000000000000000000000..2538b4d49b580cae49c41a328e166a05ae5e0a17 --- /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 0000000000000000000000000000000000000000..366cce50feb91cbd2f33413df9359c074efd3d37 --- /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= 0) ? iqfac : iqfac_m) ); + } + + lpc[0] = 1; + for (m=1; m<=order; m++) + { + + b[0] = lpc[0]; + for (i=1; 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 0000000000000000000000000000000000000000..a6bac6c155332bccc98928d82784737510c95ab8 --- /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 0000000000000000000000000000000000000000..631f8874df1a25369f5110189bbfc4aef9fafa61 --- /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 0000000000000000000000000000000000000000..1b57fc131790bdb79f49ae42680132d8abf7e140 --- /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 0000000000000000000000000000000000000000..6ccc023854dc336d138cec4f4a5b8722216bd68f --- /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=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>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 0000000000000000000000000000000000000000..b1b44f0b41028f2aab53dc233e39dc7579568c00 --- /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; wndthis_bk][SHORT_WINDOW_m_1] + + FOR( i=0, j=SHORT_WINDOW; ithis_bk][SHORT_WINDOW_m_1]; + + FOR ( i=0; iprev_bk][0]; + + FOR ( i=0; ithis_bk][LONG_WINDOW_m_1]; + + FOR ( i=0; 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; wnd0; 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++<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 0000000000000000000000000000000000000000..9180994bcbca71c881dab5c83b80105844468d9d --- /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 0000000000000000000000000000000000000000..a308c4ad4cc83a0ee589aec5f22b632e01913048 --- /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 0000000000000000000000000000000000000000..f9361997cbdf3e4558500d9d290339341bbb12ae --- /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 0000000000000000000000000000000000000000..aa04225e107a4f63df705979c06c0bf622591c47 --- /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 0000000000000000000000000000000000000000..0085a6365641940bb3117536586b51498b7939e8 --- /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 0000000000000000000000000000000000000000..8b5007eb141f4eb566112613ec5b9c682704c609 --- /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 + +#include "AACEncoder.h" +#include "voAAC.h" +#include "cmnMemory.h" + +#include +#include +#include +#include +#include + +namespace android { + +AACEncoder::AACEncoder(const sp &source, const sp &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(¶ms, 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, ¶ms)) { + 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 AACEncoder::getFormat() { + sp 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 0000000000000000000000000000000000000000..b47cb1e91236ffe9f116b6d4885ce8e8c6afa10e --- /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 0000000000000000000000000000000000000000..2f31de4aed728f910f0569e95cf00fa8b876f898 --- /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 +#include +#include +#include +#include +#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 -of -sr -ch -br -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 0000000000000000000000000000000000000000..ba3f4d235bacfbf930b6d5c14b9b45e32d7a310e --- /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 0000000000000000000000000000000000000000..c6724c260d56b11384c6b0e2889ee847effaa606 --- /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 + +#include "SoftAACEncoder.h" + +#include "voAAC.h" +#include "cmnMemory.h" + +#include +#include + +namespace android { + +template +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("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("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(¶ms, 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, ¶ms)) { + 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 &inQueue = getPortQueue(0); + List &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 0000000000000000000000000000000000000000..d148eb7630f22ed27b67ff0242b86617cd93960f --- /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 0000000000000000000000000000000000000000..5cd7e5f4a4573966ecd730c4cd1ce8ad4278538a --- /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 0000000000000000000000000000000000000000..d43bbd99eb50d3c2ae5cc560585142330658a25d --- /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 0000000000000000000000000000000000000000..982f4fd44e6d5680e6da56b77c709d5960b1fc3f --- /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 0000000000000000000000000000000000000000..6e5844faad340fac6cc2e8284e80637aed0f18b2 --- /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<> 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 0000000000000000000000000000000000000000..b1f8225e463163ece30ca3772373476eed85cc0d --- /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 0000000000000000000000000000000000000000..605923733e0fbee7a5c26d1f6e344160bae583ec --- /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 0000000000000000000000000000000000000000..874d0f7fc267bf8b0536dab24e366089c54ecbbd Binary files /dev/null and b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf 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 0000000000000000000000000000000000000000..8e206b7fb056537b716ff95ad47bc369365a61e8 --- /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 0000000000000000000000000000000000000000..bb75b6dc479638a5d003a1d00f2e79c165fe4c11 --- /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 0000000000000000000000000000000000000000..0f4bb5e6ccd99b1031987262f78a96a9d46ba0f0 --- /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 0000000000000000000000000000000000000000..30132d854c1d76d9e7967d8c4321955aadfb86af --- /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 0000000000000000000000000000000000000000..65453c0a3415d10b5cdde78744467c1f70514bb4 --- /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 0000000000000000000000000000000000000000..266a219447ab4618eaf95341bb6dc84a1ae79c06 --- /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 0000000000000000000000000000000000000000..7c79f07ec50a3d7c6b3537ce2379ba1245940a8d --- /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 0000000000000000000000000000000000000000..6a58aebe939029a1abfe50ce6b51fbbc5fa01934 --- /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 0000000000000000000000000000000000000000..a4d3e8fd44c6c8937e2ef590026c64057254c3f0 --- /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 0000000000000000000000000000000000000000..c361feb89c02ae1c300fc2cf9f2c45093d877c12 --- /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 0000000000000000000000000000000000000000..b0b4c26f8aea71d29fd4ba4106284be371b4f5d6 --- /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 0000000000000000000000000000000000000000..d3a8a6714e1702af831f26b4297da1055f7ef3b6 --- /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 0000000000000000000000000000000000000000..4c1b2cbab81fa4af373037d200fce19ed9a6d477 --- /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 0000000000000000000000000000000000000000..a42e6a9cd742249161f996e12e28019e699eb345 --- /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 0000000000000000000000000000000000000000..116d5a8c4bc3bf1df17aef59af76dbb297c6c903 --- /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 0000000000000000000000000000000000000000..30bbf45019af9ae60a675d5f97e71d1954b792e9 --- /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 0000000000000000000000000000000000000000..3c03dea449bd76ccb6af83d15ef8daf9cc336097 --- /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 0000000000000000000000000000000000000000..e719ba72a1ecb917da8c33be50a5f8f64684f584 --- /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 0000000000000000000000000000000000000000..f6981fafff9511026b0ed89af8183de17ec27225 --- /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 0000000000000000000000000000000000000000..19fb9b2e1eea7d30cff73d7cafe4000dfa1fd522 --- /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 0000000000000000000000000000000000000000..3ea6a84d46ec132d6ddd58ded8ac092cc96c0229 --- /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 0000000000000000000000000000000000000000..2ccac60b37bfd6f077cccb955fde5c91c3a76096 --- /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 0000000000000000000000000000000000000000..109922df03677cd1c47c28f99ce6ef61b8cdfe0d --- /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 0000000000000000000000000000000000000000..8f8397304da453e2a1675103413ec049b7c52fb4 --- /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 0000000000000000000000000000000000000000..1cafef69c1bfad3282096b9dad8211438b584deb --- /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 0000000000000000000000000000000000000000..997eba5b828b41768201fbd4fcf2a31910ed5180 --- /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 0000000000000000000000000000000000000000..0c96fc750242732041260b1a8e37ff2451f25225 --- /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 0000000000000000000000000000000000000000..9cddc1d54b8f386800839b39a70e9a01d9e167ef --- /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 0000000000000000000000000000000000000000..40cfaee792ac4fd3bd1897fe706c00658d0875c8 --- /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 0000000000000000000000000000000000000000..02df24de529850f1adf62dd6206543245a446ed1 --- /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 0000000000000000000000000000000000000000..0aa33c3531a90a139ff13e4599bdd416eb6d5944 --- /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 0000000000000000000000000000000000000000..311cef5e1da067d6cfbf1cde7e02053487b75e0e --- /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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..127322d2ad1aeadbfca0c3f978c196a0a215546e --- /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 0000000000000000000000000000000000000000..ad2f29a55a1f2b68e6c51b6a3f72eda2831fafc7 --- /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 0000000000000000000000000000000000000000..cecbc8f10be64d6fece3f7a16998496a1f7babdd --- /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 0000000000000000000000000000000000000000..07b33b7ff8a4b6c0dc8949e229e1f04abccebab4 --- /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 + + +#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; chsfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) + pthrExp = &(thrExp[ch][sfbGrp]); + psfbThre = psyOutChan->sfbThreshold + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; 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; chsfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; 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; sfbOffssfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; 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; chwindowSequence != SHORT_WINDOW) { + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *psfbSpreadEn = *psfbSpreadEn >> 1; /* 0.5 */ + ++psfbSpreadEn; + } + } + } + else { + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3); /* 0.63 */ + ++psfbSpreadEn; + } + } + } + } + + /* increase minSnr for local peaks, decrease it for valleys */ + if (ahParam->modifyMinSnr) { + for(ch=0; chwindowSequence != 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; sfbmaxSfbPerGroup; 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<> 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; sfbsfbCnt; 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<= 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; chsfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + Word16 *pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; 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; sfbsfbPerGroup; 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; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; 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; chsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + psfbEn = psyOutChan->sfbEnergy + sfbGrp; + psfbThr = psyOutChan->sfbThreshold + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; 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; chpeChannelData[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; sfbmaxSfbPerGroup; 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; chpeChannelData[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; sfbmaxSfbPerGroup; 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<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; sfbpeChannelData; + PSY_OUT_CHANNEL* psyOutCh = psyOutChannel; + for (ch=0; chsfbMinSnr[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; sfbsfbCnt; 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; chstartSfbL; + else + startSfb[ch] = ahParam->startSfbS; + } + + avgEn = 0; + minEn = MAX_32; + ahCnt = 0; + for (ch=0; chsfbCnt; 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=startSfb[ch] && sfbsfbCnt) { + /* 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 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 0000000000000000000000000000000000000000..e7051975f8f44b5f46746e2b660a432da41bb396 --- /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 0000000000000000000000000000000000000000..b30e8cb8147aaf27e2c2b9be882335945ab27406 --- /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 0000000000000000000000000000000000000000..da21d5faf0c209affd471aadee183efc8f72bf5b --- /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 0000000000000000000000000000000000000000..4ca4f31108cfe07237f581bf069b58936c4af488 --- /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 0000000000000000000000000000000000000000..b59b967ad9fad571f84e4d4584fdee179f0edc8a --- /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 0000000000000000000000000000000000000000..4789f6d1d67d35bebca1f13ae9a66ba05522c35b --- /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 0000000000000000000000000000000000000000..7f6b8813456ed7fe7a1203ae5b7d156eb59b6df8 --- /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 0000000000000000000000000000000000000000..03fa6a987f6cafbf09b2c3c0a568c70fc2e45078 --- /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 0000000000000000000000000000000000000000..431bc30c931202b537556f9b470b2a9bda440297 --- /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 0000000000000000000000000000000000000000..e4034b8a4efd7db444f7d8e0fa971188c0b6d989 --- /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> 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 0000000000000000000000000000000000000000..9fe511cd975193c526b2228213791376578996c2 --- /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;i0) + (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;i0) + (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;i0) + (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;i0) + (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;i0) + (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;i0) + (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;i0) + (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= 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 0000000000000000000000000000000000000000..0ce93d395444ea8c53243223c2c9421829dd1b4d --- /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 0000000000000000000000000000000000000000..fcc12ddfcc169259276e822feefb18386da559db --- /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; inoOfSections; i++) { + psectioninfo = &(sectionData->sectionInfo[i]); + /* + huffencode spectral data for this section + */ + for(sfb=psectioninfo->sfbStart; + sfbsfbStart+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;inoOfSections;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;inoOfSections;i++){ + psectioninfo = &(sectionData->sectionInfo[i]); + if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){ + for (j=psectioninfo->sfbStart; + jsfbStart+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 3 || + tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) { + coefBits = 4; + break; + } + } + } + else { + coefBits = 2; + for(k=0; 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; kfirstScf], 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;iqcElement.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 0000000000000000000000000000000000000000..47fd15e716396175c74a78c3993cc3837ad95f0a --- /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; igroupLen[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; igroupLen[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; wwindowNrg[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; waccWindowNrg); + 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> 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; igroupLen[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; igroupLen[i] = 0; + blockSwitchingControlRight->groupLen[i] = 0; + } + } + else { + + if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; + for (i=0; igroupLen[i] = blockSwitchingControlLeft->groupLen[i]; + } + } + else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; + for (i=0; igroupLen[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 0000000000000000000000000000000000000000..f6552ed424c45c99dd710e0f1fdee0eb35b1960f --- /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 0000000000000000000000000000000000000000..77691884da2a61e5917ab0a9ab9467473fb1cc2e --- /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 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; icodeBook != 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].sfbCntnoOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + + if (sectionData->maxSfbPerGroup == 0) + return; + + /* + loop trough groups + */ + for (grpNdx=0; grpNdxsfbCnt; 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; imaxSfbPerGroup; 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; inoOfSections; 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; inoOfSections; 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 0000000000000000000000000000000000000000..7861e1cdcc59ce8d05f2e9ba07e598f063778a0e --- /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=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; jsfbShort[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; jsfbShort[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; jsfbShort[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; jsfbShort[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;imaxSfbPerGroup = 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; jsfbMinSnr; + for(j=0;jgroupingMask = 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 0000000000000000000000000000000000000000..480dc288b922135291f9dd357f0d2416fc30477f --- /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; chpeChannelData[ch]; + for(sfbGrp=0;sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; 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; chpeChannelData[ch]; + const Word32 *sfbEnergy = psyOutChan->sfbEnergy; + const Word32 *sfbThreshold = psyOutChan->sfbThreshold; + + pe = 0; + constPart = 0; + nActiveLines = 0; + + for(sfbGrp=0; sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; 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 0000000000000000000000000000000000000000..bb266dcde79d240b6a170ce6edf3e2cdeecf351a --- /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 +#else +#include +#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 0000000000000000000000000000000000000000..2e34f14b964f298a9ec505b503cbc4ede6837e3c --- /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> 8) + 1); + + temp = pnms - pnlr; + if( temp > 0 ){ + + msMask[idx] = 1; + msMaskTrueSomewhere = 1; + + for (j=sfbOffset[idx]; 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 0000000000000000000000000000000000000000..1406e11b0ec6cdac643df3751c063b1e3f1927ae --- /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 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 0000000000000000000000000000000000000000..dd40f9b24fbb834ba6d8b83eb66ef6fb88c31060 --- /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; i0) + 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 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> 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 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 0000000000000000000000000000000000000000..4e9218c81a39f4647e27b2cd182cf5f6bfea7070 --- /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; ipsyData[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; nchpsyData[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; chChannelIndex[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 0) { + Word32 *Spectrum = psyData[ch].mdctSpectrum; + for(line=0; line> scaleDiff; + Spectrum++; + } + } + psyData[ch].mdctScale = maxScale; + } + + for (ch=0; chsfbCnt-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; chsfbCnt, + 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;chsfbCnt, + 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; imdctSpectrum, + 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; isfbEnergySum.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; imdctSpectrum+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; wsfbOffset, + 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 0000000000000000000000000000000000000000..48ff30087d43b298b6124ac3e4d4ad7fa43736f3 --- /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; iqcChannel[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; iqcChannel[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;sfbOffsbitResTot = 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 0000000000000000000000000000000000000000..0d0f550402e66d07ae1ef7ed9620fda21c18fdb0 --- /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<> (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> 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 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> (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> 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> 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> 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; sfbOffssfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; 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> 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;jsfbCnt;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 scfAct)) { + sfb = sfb + 1; + } + stopSfb = sfb; + + possibleRegionFound = 0; + + if (startSfb < sfbCnt) { + possibleRegionFound = 1; + for (sfb=startSfb; sfbmdctSpectrum + + 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 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; isfbCnt; 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;isfbCnt;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; isfbCnt; 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; isfbCnt; 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; isfbCnt; i++) { + + if (scf[i] == MIN_16) { + scf[i] = lastSf; + /* set band explicitely to zero */ + for (j=psyOutChan->sfbOffsets[i]; jsfbOffsets[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; isfbCnt; i++) { + scf[i] = 0; + for (j=psyOutChan->sfbOffsets[i]; jsfbOffsets[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=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 0000000000000000000000000000000000000000..c2bd8bde61c438e08bba17f6f3ebae5d0e22974b --- /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; sfbOfftnsActive[i]!=0) { + tnsPresent = 1; + } + } + + if (tnsPresent) { + /* there is data to be written*/ + /*count += 1; */ + for (i=0; itnsActive[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; korder[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; korder[i]; k++) { + + if ((ptcoef[k] > 1) || (ptcoef[k] < -2)) { + coefBits = 3; + break; + } + } + } + for (k=0; korder[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 0000000000000000000000000000000000000000..455a864cbb5ac493f75734f7ef919203728cfd62 --- /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 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; itnsActive[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= 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=lpcStartLine; i--){ + pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1; + } + /* filter up */ + for (i=(lpcStartLine + 1); i> 1; + } + + /* weight and normalize */ + for (i=lpcStartLine; i= 0) + { + for (i=lpcStartLine; i> maxShift; + } + } + else + { + maxShift = -maxShift; + for (i=lpcStartLine; i> 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> scf)); + } + corr[i] = accu; + } +} +#endif + +/***************************************************************************** +* +* function name: AutoToParcor +* description: conversion autocorrelation to reflection coefficients +* returns: prediction gain +* input: input values, no. of output values (=order), +* ptr. to workbuffer (required size: 2*order) +* output: 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 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> 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> 2); + } + } +} diff --git a/media/libstagefright/codecs/aacenc/src/transform.c b/media/libstagefright/codecs/aacenc/src/transform.c new file mode 100644 index 0000000000000000000000000000000000000000..a02336f3f03039d394e80700b612015ac1e7b62e --- /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> 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> 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> 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> 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> 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> 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> 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 0000000000000000000000000000000000000000..2e431205aa6d7f8512da485ac3f6820d26ac7394 --- /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 0000000000000000000000000000000000000000..30ce29cd9d54f5df28429e4815b1718902ad1e79 --- /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 0000000000000000000000000000000000000000..e92eaf42594dec608d534e9047c5dcc0f581502c --- /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 0000000000000000000000000000000000000000..43daeca9154179e6e8acb42faa0c4c582512cccd --- /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 0000000000000000000000000000000000000000..7c24ca944053e1dfdff00c9d2ddd560b427e6fa7 --- /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 0000000000000000000000000000000000000000..f6c80e2bda00c37e24103aa65b97db77da2bd115 --- /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 0000000000000000000000000000000000000000..48f0bcb3259b3554bffcff9af818f61fc8fd6ae1 --- /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 0000000000000000000000000000000000000000..c939356f20b01bebced4aaeb9e6c58d738865a9a --- /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 0000000000000000000000000000000000000000..35638e3756589b4a241998524fd2f6c14cbc23a5 --- /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 0000000000000000000000000000000000000000..363d14846dff49956514f430d3f0de74b529f4b0 --- /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 0000000000000000000000000000000000000000..a170750fc69f0d5657843ca3fc72d5845c3501ab --- /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 0000000000000000000000000000000000000000..bfcb4cf85a29c1433ff0a0e8d2b4aa38d6c21408 --- /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 0000000000000000000000000000000000000000..6a11bb428275afddcb23698bedbcaab849614d19 --- /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 0000000000000000000000000000000000000000..934efbe3ba41d4b3250f72ef55c2550c897082d4 --- /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 0000000000000000000000000000000000000000..b648eb7d94f023b1a526ec6a7fb80a3e971605dc --- /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 0000000000000000000000000000000000000000..6877a1bb9bac85dd661af975e48b433a4acf3517 --- /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 0000000000000000000000000000000000000000..b539ebb927636d9ad1561f631579981ae368965c --- /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 0000000000000000000000000000000000000000..70868f4eb12c97fdf7ddd4e490624c5623a3af33 --- /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 0000000000000000000000000000000000000000..fec072be4ebc6790f88bd2d1ba14b29bbd990979 --- /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 0000000000000000000000000000000000000000..0e5ca9a401e36c5bc028ef1c6d2e2bfca61f24fd --- /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 0000000000000000000000000000000000000000..28b726bfe411cfe156e17c53a8ae5a9a3f6f80da --- /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 0000000000000000000000000000000000000000..e8421db1e8979af7a0b2095c75ccdc989f202f62 --- /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 0000000000000000000000000000000000000000..c29b9e11c4e1203557e197c0c4a80f79162034c4 --- /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 0000000000000000000000000000000000000000..34a623f7a7d33772a35af286a96ba0ce6fec2835 --- /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 0000000000000000000000000000000000000000..ed7460d95e0f329b39fd44e0d3ce3db2e5e29544 --- /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 0000000000000000000000000000000000000000..1d0c6c10e1144cb402beb480ea55f7713573eed5 --- /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 0000000000000000000000000000000000000000..3ebd929944b5a5c896a6190a23d8a2d11416b83f --- /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 0000000000000000000000000000000000000000..b82603c716d3c983be701332f9f2b1ab52d9290f --- /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 0000000000000000000000000000000000000000..1c4ede24e688ddd4f239f7b3a96c8c5a1571ad6c --- /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 0000000000000000000000000000000000000000..4abcbbde750ed6faa6d9173bf1ed38ba129ea671 --- /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 + +/*---------------------------------------------------------------------------- +; MACROS +; 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 0000000000000000000000000000000000000000..e95e6cad66959206aeee59f24f49ee323bf84b97 --- /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 0000000000000000000000000000000000000000..4e02ae6988f599eba60f85246151c97466ebf9a3 --- /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 0000000000000000000000000000000000000000..91ab3e4424af795df7cf54f6785b57c811cf51f8 --- /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 0000000000000000000000000000000000000000..db57b8248c37995f6287e15e3912de64d148a0e1 --- /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 0000000000000000000000000000000000000000..136b914acc1bd524be2645356502f5cfbb08294b --- /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 0000000000000000000000000000000000000000..3585a3c64c8821331a27751eb4e3e58a57f5adca --- /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 0000000000000000000000000000000000000000..02a4bb737f38a62e00609ce13abf1bec73e81a33 --- /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 0000000000000000000000000000000000000000..e58bc5f1b85d44097ad05be0bea04b5efe24e633 --- /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 0000000000000000000000000000000000000000..09fabfd53e0f5d9375c8f14f6c817e33d563f4f4 --- /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 0000000000000000000000000000000000000000..fdbe3514b13fe56707245225f2a59c6673ddc4c0 --- /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 0000000000000000000000000000000000000000..b4af3aadd5dca559504a9a013a75b687f5b409a8 --- /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 0000000000000000000000000000000000000000..3bafb00d797311e96620eec88f5f35323832a91d --- /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 0000000000000000000000000000000000000000..061df60fc397ecf76dfdd349df1c527900c1c5a6 --- /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 0000000000000000000000000000000000000000..11e14a80dd8164ac51f9912660adcf33db052ad0 --- /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 0000000000000000000000000000000000000000..7b9fdb1ebff97b1667793fc42b00056ae26e7fda --- /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 0000000000000000000000000000000000000000..ef22073deb0c070c5d3ff78ff9ddd0a8b19c62c3 --- /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 0000000000000000000000000000000000000000..1a1661faaf95f82529de1209b5cff58f8c40d09a --- /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 0000000000000000000000000000000000000000..97d753837aa58d23691ae4333090b84da8a9c151 --- /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 0000000000000000000000000000000000000000..e589b2fc0a2a33694420b66b446b6d34d7d67705 --- /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 0000000000000000000000000000000000000000..46b4e4d8b8b63117367b6e0cbc354ddc5736d353 --- /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 0000000000000000000000000000000000000000..d9a1f80a6995d7525ae98e47e1c89311eea9815f --- /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 0000000000000000000000000000000000000000..26a4b34156ff200675a1cf84009eeff64eedd648 --- /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 0000000000000000000000000000000000000000..ae8150765cea587289901c8676e0a066779d7d73 --- /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 0000000000000000000000000000000000000000..186b4d3c7b4ba8f65709992bc80d89e820073908 --- /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 0000000000000000000000000000000000000000..01b3317bf3b504710c005668dc8c11c211df39ae --- /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 0000000000000000000000000000000000000000..9e9ebe1d80264150a82e5506b434e88f129c5e85 --- /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 0000000000000000000000000000000000000000..75f86cb67a017b9b2289b955b3bf4b433422e79c --- /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 0000000000000000000000000000000000000000..03f36b2e85077737bbe271c34c6e6285fa3a0214 --- /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 0000000000000000000000000000000000000000..7eaa7411eb4d0455d4c2e385fb2e1ed79872319c --- /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 0000000000000000000000000000000000000000..6927eba057213f4d8eddeeb742849e87baa80e25 --- /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 0000000000000000000000000000000000000000..d7a185778d46f84121356489d2659904b1ef13ab --- /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 0000000000000000000000000000000000000000..e5738c17187c470d64fa9ceb696d9ef843a554b8 --- /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 0000000000000000000000000000000000000000..f67569e8da78bb973e0ab39737e5433abe8b8f6d --- /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 0000000000000000000000000000000000000000..533b1059d92d52de467b886571557107e6ce4040 --- /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 0000000000000000000000000000000000000000..2e37a9f6e6958db0c751773ce2a682264460b9f1 --- /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 0000000000000000000000000000000000000000..ec3fcfbb5640f7ecb35733c1919aeaac33dfaa07 --- /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 0000000000000000000000000000000000000000..6c277da98d7bca45422e0769177707012a9051de --- /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 0000000000000000000000000000000000000000..9b944ebafca9aa6c52e9b03d12e3f7a3b0b8da87 --- /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 0000000000000000000000000000000000000000..a2bfed2e1253203b25b38e8dff30b4d061f04170 --- /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 0000000000000000000000000000000000000000..b697524781e5b6505fd34b47f8c86bdfb096b570 --- /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 +#include + +#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 0000000000000000000000000000000000000000..431272a96eb98f086336431eacb6c35cca418b85 --- /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 0000000000000000000000000000000000000000..2e43d10c09dd927e2b8f2259ed8474ae8eee05de --- /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 0000000000000000000000000000000000000000..245b5f44b72c8422b94f62f19e2ac60dad4a7a48 --- /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 0000000000000000000000000000000000000000..6c0d766d012d713644573c6d8de283080a429505 --- /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 0000000000000000000000000000000000000000..65b35ee7920144128f3c8f431b97645d66e32651 --- /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 0000000000000000000000000000000000000000..a7691e76cfcb24e42c20ce9103215e7e796838f6 --- /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 0000000000000000000000000000000000000000..620cd0ba104d2eebc24eb2d818bff3f7fcab75ae --- /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 0000000000000000000000000000000000000000..f4d00411d0ac1f8d0eb7d3e92651f4a919458ac7 --- /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 0000000000000000000000000000000000000000..fcc8df698a2d15763b3722ce74e41a53d08595b7 --- /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 0000000000000000000000000000000000000000..3129e271c336b184129d4a64914c027db75e6c40 --- /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 0000000000000000000000000000000000000000..debd223cdbaf1405182a0d4b576a1b9802fcc827 --- /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 0000000000000000000000000000000000000000..84ca8d94be949da4cbf90a64d7e7bc1c213a9217 --- /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 0000000000000000000000000000000000000000..e961c0485264368aef6250a29871351935e5d4ed --- /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 0000000000000000000000000000000000000000..c4f9e2c840e3aa59eb2884bc18d14f7a57f3ff4e --- /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 0000000000000000000000000000000000000000..a6a2ee5fba92e22757a807979a2e9c52b8a44421 --- /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 0000000000000000000000000000000000000000..18dc4568cf406bc3cc324a30477b4325df6be415 --- /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 0000000000000000000000000000000000000000..7fff112ae238c5b59ceda3b8b36ad01595d98a7a --- /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 0000000000000000000000000000000000000000..ee4d73235edc66b901659b4814003b4727538ca4 --- /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 0000000000000000000000000000000000000000..b9ee89f230101107198fe001ecff6be10894d3c4 --- /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 0000000000000000000000000000000000000000..c144ea0249ef9c4152713eb26904b8f6d446cf5e --- /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 0000000000000000000000000000000000000000..3197b3a18ea92f497d853b31685b09c966f868ee --- /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 0000000000000000000000000000000000000000..0358c8566b630753ec48f38510171607fcbbbdcc --- /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 0000000000000000000000000000000000000000..42233afbd3b41960b535e101bb4a0796d5d77cc9 --- /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 0000000000000000000000000000000000000000..8bcccc80eefc5feaf4db6efacca960c4982cb329 --- /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 0000000000000000000000000000000000000000..ccbed44faaefb56ee8f01392d9f153a8893e6d1b --- /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 0000000000000000000000000000000000000000..d488ca5338f3bd82eea8dff2b202c397a6a35d8e --- /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 0000000000000000000000000000000000000000..4135f30ea73f2640f41208380137255f4b63f137 --- /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 0000000000000000000000000000000000000000..4ee04a561dec3aa211c43fd1fd1f75e41f18864c --- /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 0000000000000000000000000000000000000000..e284bbcbc7f3c3c5ae404d44d468b74533d794ce --- /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 0000000000000000000000000000000000000000..1d6f7b1308938d669f0f7ee8c455598190537ab0 --- /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 0000000000000000000000000000000000000000..b61bac4d9fc7c5b19c39b4058fdb5920420a48a3 --- /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 0000000000000000000000000000000000000000..20de9d63ff9751c371c4507a22ff0bac0c810b94 --- /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 0000000000000000000000000000000000000000..75890b21f11452cc85f3d35b5976929db45f57d1 --- /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 + +#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 0000000000000000000000000000000000000000..143e37c38eb142ffa46cc6fe4a9fb52fbf20e175 --- /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 0000000000000000000000000000000000000000..f3bed7e9ca4fcdc95969d23836084a5d03853847 --- /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 0000000000000000000000000000000000000000..e538f9f9dcec70f969720e2f426bf9e2c31bd302 --- /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 0000000000000000000000000000000000000000..dbb9a6e5e8a8ca28d6d8caa57f1fa5e5742c0656 --- /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 0000000000000000000000000000000000000000..a7cd6fbea66fcdd5d2d5ecac2f0d69839b299676 --- /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 0000000000000000000000000000000000000000..3650f3cb6ebcc6b95dfd2f4c4d296a63466d22b2 --- /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 = * 2^27*2^exp_code + // frac_en = ener_code / 2^16 + // = * 2^11*2^exp_code + // = *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 = * 2^27*2^exp_code + frac_en = ener_code / 2^16 + = * 2^11*2^exp_code + = *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 0000000000000000000000000000000000000000..be76241c226d6e2212b5e0e9d9d75cfa327c0990 --- /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 0000000000000000000000000000000000000000..c4b2dbc138ab70bf20648f2afbebb3d65ddff529 --- /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 0000000000000000000000000000000000000000..48566cca56c2555517abf9747a22befd66b1f791 --- /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 0000000000000000000000000000000000000000..806474d816194ed61e883b32258b850d4a0a6a07 --- /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 0000000000000000000000000000000000000000..83f4d0c583f8144dd33ecc612991ab9676896d76 --- /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 0000000000000000000000000000000000000000..13c3b24053b4e27d011d4d7effdd495a9c1e4de9 --- /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 0000000000000000000000000000000000000000..fd1c90dd5f3680e3ac826e2306766fcaa10eb3c1 --- /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 0000000000000000000000000000000000000000..e705ed1d8b17883da48155dd9491b6d20213a564 --- /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 0000000000000000000000000000000000000000..5064fdb938038fefddb38fc8653b857a685e8eab --- /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 0000000000000000000000000000000000000000..f609a73a9030a7e6cc00a9b5f75dd564560c59d6 --- /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 0000000000000000000000000000000000000000..0ada42310547db25025e08fa63b43d7d6b125c34 --- /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 0000000000000000000000000000000000000000..feda874987361e01a3f5feb0dd3e0fc43cda03c8 --- /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 0000000000000000000000000000000000000000..9b9b099efc10e4b7648bfad5234073509d90001d --- /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 0000000000000000000000000000000000000000..6b511f767db9051615a80fde4df37879fab73257 --- /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 0000000000000000000000000000000000000000..0e3f772a44c3fdf8af712b10054623e284edae58 --- /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 +#include + +#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 0000000000000000000000000000000000000000..6b7b4710eb612306b8df7e02c3b646e1f015a0c4 --- /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 0000000000000000000000000000000000000000..39d6edacf6f496264ac00e3259c4b604579623f4 --- /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 0000000000000000000000000000000000000000..ddeeba4282a5a629fcce1d8907b2b00b721416e4 --- /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 0000000000000000000000000000000000000000..0a32dd7a092aaaa031522a32436a5657a98a98f9 --- /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 0000000000000000000000000000000000000000..0777e684d91d3db4969fafa1423392f72fc86e23 --- /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 0000000000000000000000000000000000000000..be58d2b36161357b89b797ba92c152a6bbe2f008 --- /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 0000000000000000000000000000000000000000..132fed65b32a655c3442eeeb348f7027b23bb0b5 --- /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 0000000000000000000000000000000000000000..8cdcdb82e925bf2e0fd0274dd064a02a727ca79b --- /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 0000000000000000000000000000000000000000..c4a016d557b9bf1c37ffcd2295d7aefe17e222a9 --- /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 0000000000000000000000000000000000000000..d568b780a0f065cca304a18152cbe7a795d292ec --- /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 0000000000000000000000000000000000000000..a8686f8339c62175b585606a3b6914a7889c91b8 --- /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 0000000000000000000000000000000000000000..902ea0f5bbc5dfba844ea73ad497480bfd075023 --- /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 0000000000000000000000000000000000000000..9163623e55379d9caf23f93d7f3910f4866cfb10 --- /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 0000000000000000000000000000000000000000..5d96baad40a1d96339066371e09612cc083922e0 --- /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 + +#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 0000000000000000000000000000000000000000..2b30bf40b25e71fab767476a76b5d3a184537539 --- /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 + +#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 0000000000000000000000000000000000000000..56c13e73b7bd48f332fc062ea0c204c98687f955 --- /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 0000000000000000000000000000000000000000..2f9e40ee6be37734e459b97d260eed3a7b4876ce --- /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 0000000000000000000000000000000000000000..caa81cbf972fb9d7b4ccd454151184349ea40120 --- /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 0000000000000000000000000000000000000000..2d913b8063f9ffbbf448c9bd3984bf3f2cbe82f9 --- /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 0000000000000000000000000000000000000000..b1e47115eced5b3557ac8d08fc162f63dc3f87f2 --- /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 0000000000000000000000000000000000000000..b25d3bee04f501e84d4ba0a793cc083d17fcb53d --- /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 0000000000000000000000000000000000000000..71d17020b14ad36fec41ea9bfc5e4de529599631 --- /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 0000000000000000000000000000000000000000..be23b254bd9b6ceadc58c8a1f6fcd61f66e31297 --- /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 0000000000000000000000000000000000000000..775dc690794f9385fb6bf0bdb607ef75dfe6249c --- /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 0000000000000000000000000000000000000000..6656f9339c5e69a73d3131b8c6344bc8e5bee588 --- /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 0000000000000000000000000000000000000000..8f74aa65bcd78a201a6310c366c5081c2d7bd2cd --- /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 0000000000000000000000000000000000000000..5a84b63e6c933c9304d23f366378baa9480d8293 --- /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 0000000000000000000000000000000000000000..d9361280f634bb66ff526d9be7973d4a1f1a2fcf --- /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 0000000000000000000000000000000000000000..bcdc6962f728c53fa3a504964758ab69d8fcb47f --- /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 + +#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 0000000000000000000000000000000000000000..a6e113146e6e86a12cbc5a67488e0e90e2f9b93a --- /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 +#include + +#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 0000000000000000000000000000000000000000..2e2efc4a57b07b427481a9629a053129f5fb522e --- /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 0000000000000000000000000000000000000000..d8fc8cce9ccfda09f24e81314bf4f7582302d51a --- /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 0000000000000000000000000000000000000000..b81306dfb686fda9199dc5626d07306d27b58b91 --- /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 0000000000000000000000000000000000000000..796caa4185b1f42210cc5a94e640f3204ce10795 --- /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 + +#include "SoftAMR.h" + +#include "gsmamr_dec.h" +#include "pvamrwbdecoder.h" + +#include + +namespace android { + +template +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("audio/amr") + : const_cast("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("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 &inQueue = getPortQueue(0); + List &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(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(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(&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 0000000000000000000000000000000000000000..9a596e527f161b31274fbf31a8ce36f185b87104 --- /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 0000000000000000000000000000000000000000..7b943209f36e4ff316382b2f2c64c8985cf5a29f --- /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 0000000000000000000000000000000000000000..fb7cff37b7e38e8689b4287cbdfb4b632a91686c --- /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 0000000000000000000000000000000000000000..4028e1e28e31d534128d8dfc6102098c3dedd2db --- /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 0000000000000000000000000000000000000000..4c66d54a7b010b22da588591a1f16cfaf99bf04e --- /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 0000000000000000000000000000000000000000..b6e32495dad36ba6355c8e71deaf168bf4cd9635 --- /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 0000000000000000000000000000000000000000..873d7afa06823df64aeafae6b163f9ffee0b69e4 --- /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 0000000000000000000000000000000000000000..db951b939058696f2598a040bd71a04f77f9dba9 --- /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 0000000000000000000000000000000000000000..e62e483a116c1d288ba7656f7b938b5b9eaececd --- /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<>= 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 0000000000000000000000000000000000000000..743237c9ad84092e6c3c16562976238d88c57251 --- /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 0000000000000000000000000000000000000000..e732007bbb6a9b25a17bf80e71586af1117f2635 --- /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 + +#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(<pGainHist[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(<pGainHist[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 0000000000000000000000000000000000000000..41349d9b6e6af78cf7bfedbe80e9c7ca9063e7be --- /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 0000000000000000000000000000000000000000..91d3982c3ff239ab2851f2337aee6ff7da227aa0 --- /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 + +#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 0000000000000000000000000000000000000000..0b53753736da99538aeb143912159711ddb32b71 --- /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 0000000000000000000000000000000000000000..899daba63f3d97c06c23203b635d72b76fecbb2a --- /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 0000000000000000000000000000000000000000..51f1f42b5b6e2f94184516f54b33a9b2bd1c8b03 --- /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 0000000000000000000000000000000000000000..e1e544fb13d27743e5ba74be1987fcb5db59de0f --- /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 0000000000000000000000000000000000000000..aaf2e084c0382975ddcd752674146abdca8c7c18 --- /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 0000000000000000000000000000000000000000..2c36706a184dcdf36bb4316fac4f21fd5eb8cc1d --- /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 0000000000000000000000000000000000000000..38076d807ff1ef90b40d87c8211cb72369285220 --- /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 0000000000000000000000000000000000000000..d1912cf15b6e8995b8cb91ba1e9d0deb543e1f3e --- /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 0000000000000000000000000000000000000000..1e2e0cd94d0bd6976141c1bd99952beff9967321 --- /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 0000000000000000000000000000000000000000..ece82c06dd55f41c9e3adf5aa3df4a1a79cda03e --- /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 0000000000000000000000000000000000000000..5dc43f3947a1024aae177d40c0582e147599bb93 --- /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 0000000000000000000000000000000000000000..917c47f204d601f3b3ba1be6fcecbefc04988aae --- /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 0000000000000000000000000000000000000000..162685ff4800a226107be330d50b65f5b6b2cb80 --- /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 0000000000000000000000000000000000000000..b6c62f821135500372cb42e3715cf9d5f23b71a9 --- /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 0000000000000000000000000000000000000000..99446db7c9127fcd535ed2a1c71b7c6d5326826a --- /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 0000000000000000000000000000000000000000..138193f888e60c988b14f10e24f3ae8bbfa6f71d --- /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 0000000000000000000000000000000000000000..7b31d041c9f206bf2c8cad79f5397a9c380184af --- /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 0000000000000000000000000000000000000000..08b690dfde15feed6104bbeaac4a73731eb4c9be --- /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 0000000000000000000000000000000000000000..be1547506484f380f5d44c8948b725901bb24ed3 --- /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 + +#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 0000000000000000000000000000000000000000..b04137d0a9a3c664c7211b949de3622de9cf2e21 --- /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 0000000000000000000000000000000000000000..ceab48d5d3a83df85aaaa840310614f2d3f9eb0d --- /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 0000000000000000000000000000000000000000..b9c6a8d9ded7ec1f03710c12fdb9b727adb6167b --- /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 0000000000000000000000000000000000000000..fffbbfd82420679f3cb40e38a3c02ce92a67e188 --- /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 0000000000000000000000000000000000000000..70baaba23e80ea75738c0bc8b2d5685fd9c8f6a3 --- /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 0000000000000000000000000000000000000000..e758b92d73b30887ac3b87638bcb462ffab4dd57 --- /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 0000000000000000000000000000000000000000..7dc7a8df987434b82a205d8e6efe4ae3ac4057c8 --- /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 0000000000000000000000000000000000000000..7322bc8daf5887fc2025dd2acbed2685cdccffe9 --- /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 0000000000000000000000000000000000000000..9d04373068a5608bad773c63a95743a47105e230 --- /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 + +#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 0000000000000000000000000000000000000000..2b5a614adb1b6b6e1db6f7355d91ff1012966ec5 --- /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 0000000000000000000000000000000000000000..e73db62ba6d18c7d7d24ad56167e83360da90332 --- /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 0000000000000000000000000000000000000000..e05a0af8c489fa4f67638fe9879b8e0e09f42ddd --- /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 0000000000000000000000000000000000000000..f18054b3cb39682493779ee998f3050a4bb6df6b --- /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 0000000000000000000000000000000000000000..11c632e4e4f903067d0287ce7fa1f22c3d3bc3a1 --- /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 0000000000000000000000000000000000000000..a9fdb1c484da6a3b8abad275a52f0fd8ff67fcfb --- /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 0000000000000000000000000000000000000000..733c8b80f69eb6df2ca5d457187df86226ac6443 --- /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 0000000000000000000000000000000000000000..490565db436c8abb3ce993b41186b483e74e7155 --- /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 0000000000000000000000000000000000000000..c5aefe4b1d84dd90c8b17c06e91c137f27e9624c --- /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 0000000000000000000000000000000000000000..9b65c7ae3b066cefd3d579c597ea16f6c650541d --- /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, + + 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 0000000000000000000000000000000000000000..b289c08314939d18384b2597bd296557b537b4d6 --- /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 0000000000000000000000000000000000000000..da5445b94951eaaf4ec3edb8c493c471b656e242 --- /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; igainMem[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 0000000000000000000000000000000000000000..58e2e4fb688fdffeebe75cef4a1b84baa194e08d --- /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 0000000000000000000000000000000000000000..ce31793ecc6fa95ccaa80d6597d47b4a4f4328a1 --- /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 0000000000000000000000000000000000000000..85e58887d356dff580b8bbeb28a75964a764211f --- /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 0000000000000000000000000000000000000000..9864325b4decd3d22efa2ca10d5a6b4c58890e60 --- /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 0000000000000000000000000000000000000000..20bab7195e8cd049b170470750a5a925636bf168 --- /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 0000000000000000000000000000000000000000..0336990fa1cf51ce0a3572cfac546b01771a3f42 --- /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 + +#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 0000000000000000000000000000000000000000..29c0d84ee82778dc0f5ddb0f052dd63f8d70638e --- /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 0000000000000000000000000000000000000000..95b0b473ef136536027630d1848d650c3631c32f --- /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 0000000000000000000000000000000000000000..1a08efa3a60004a1e8aae1b7f99d0edab9242a94 --- /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 0000000000000000000000000000000000000000..2989b7452edf24d17f86137b31bf53ccd49f2895 --- /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 + +#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 0000000000000000000000000000000000000000..3150feb4049ea3d0e546210704434d215d25ae7d --- /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 0000000000000000000000000000000000000000..4dfbb67a605f900370dd529a6898041ef5c656aa --- /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 0000000000000000000000000000000000000000..28246ae161229c23a8ccccdce5459bf3cf39b9ee --- /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 0000000000000000000000000000000000000000..07f8b4f8b93dead02cbd7403cefae35198611c12 --- /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 + +#include "SoftAMRNBEncoder.h" + +#include "gsmamr_enc.h" + +#include +#include + +namespace android { + +static const int32_t kSampleRate = 8000; + +template +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("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("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 &inQueue = getPortQueue(0); + List &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 0000000000000000000000000000000000000000..50178c4129761fb4b66f059165a4b4680163387c --- /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 0000000000000000000000000000000000000000..d07c846d8135bcf59f26067774404eb6fda74f7b --- /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 0000000000000000000000000000000000000000..1e85db1be97cafee4678883c42ad32086721dc47 --- /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 0000000000000000000000000000000000000000..0d3acac42dc309ba8fc81acc1f882913468d5e1b --- /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 0000000000000000000000000000000000000000..6045d6e73e51533d860f3254d8a3b83b6b62713e --- /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 0000000000000000000000000000000000000000..d95995c2ccb4e8ae441a49d8f25c339c3e9e3499 --- /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 + +#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 0000000000000000000000000000000000000000..be45cbb94eb4db16f668f7dd242b2ef40d1d5545 --- /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 0000000000000000000000000000000000000000..87fa9b8be5204b62b88a6dc2053fb64bbd486d29 --- /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 0000000000000000000000000000000000000000..f963ae1fd18445b5fe44656e4dbe2b41e765ce9e --- /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 0000000000000000000000000000000000000000..a33cdf749307d51846f667f8400af75be3157812 --- /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 0000000000000000000000000000000000000000..203e1d9c9eca72c9f29bee02e5aa861a5d8258ad --- /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 0000000000000000000000000000000000000000..58ab2fa0e8045f835f08ec03dab463c751533e87 --- /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 0000000000000000000000000000000000000000..15e2f1afa17b0a547ef2960554a2b21736e87d4c --- /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 0000000000000000000000000000000000000000..d52b43b8b92269aa8d82f95671649f2ab97ad15d --- /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 0000000000000000000000000000000000000000..4dc66a9f03f59dfb1b3c8448b0e094737388c861 --- /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 0000000000000000000000000000000000000000..07c2efd77cb99ab219ebe8143d3efd279d67ce99 --- /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 0000000000000000000000000000000000000000..03225ceb59a1ec5a48da8f24bf748fcd70a553ed --- /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 0000000000000000000000000000000000000000..db786a6197ec2e67b7d1310b992749222f71d876 --- /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] = , 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 0000000000000000000000000000000000000000..d4a694bb48026f7aa8b5c9a2c13cdb642ae4bdea --- /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] = , 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 0000000000000000000000000000000000000000..6cf6867fd041729fc622c10617af9454bf5632fb --- /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] = LP residual energy + frac_en[1]*2^exp_en[1] = LTP residual energy + frac_en[2]*2^exp_en[2] = LTP/CB innovation dot product + frac_en[3]*2^exp_en[3] = 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 + 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, <pg_exp, <pg_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 */ + /* */ + + 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, <pg_exp, <pg_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 + 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 = / (0 if <= 0) + + Product and 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 + // 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 + + 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* + + 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* + + 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 + + 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 = / 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 */ + /* 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 */ + s1 = L_mac(s1, tmp, tmp, pOverflow); + + /* Compute scalar product -2* */ + s2 = L_mac(s2, xn[i], tmp, pOverflow); + + /* Compute scalar product 2* */ + 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 */ + 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 = / 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 = + +------------------------------------------------------------------------------ + 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 + 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) = * 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 */ + 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) = * 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 0000000000000000000000000000000000000000..052f5b48e4d21aafb7c5c21d2e34f4275faab430 --- /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] = // LP residual energy + * frac_en[1]*2^exp_en[1] = // LTP residual energy + * frac_en[2]*2^exp_en[2] = // LTP/CB innovation dot product + * frac_en[3]*2^exp_en[3] = // 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 = / (0 if <= 0) + * + * Product and 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 */ + /* 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 = + */ + 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 0000000000000000000000000000000000000000..a02b891e616694a0e3c1aa659986699fcaa1e447 --- /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 0000000000000000000000000000000000000000..46d149ba9e28fc7ffd773fc5dc8e0b36d501d84e --- /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 0000000000000000000000000000000000000000..4a0532707118fe47d8d010cb43e684899403961c --- /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 + +#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 0000000000000000000000000000000000000000..3e9b587cd51fccfd4ddaccc611e4ce2217e632bc --- /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 0000000000000000000000000000000000000000..84681319db513a56cb40d7f1880cadc1f9a8cc0b --- /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 +#include + +#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 0000000000000000000000000000000000000000..7360c0a9cca48ef8a7e4adb29618b3e8696e3187 --- /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 0000000000000000000000000000000000000000..e9ce7ba5f6e35a645e0e044b916db5e3f115fbe3 --- /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 0000000000000000000000000000000000000000..1f2b503f37330986e846fbc5f1716363f819c37e --- /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 0000000000000000000000000000000000000000..e46d99f1bfde8945692fdbf72398e7224c3f45bf --- /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 0000000000000000000000000000000000000000..59b9d685f8f33269629dad11a15179e167d4ef34 --- /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 0000000000000000000000000000000000000000..beb2aec671bedace44b853f6f5f19a3bfd1a119b --- /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 0000000000000000000000000000000000000000..66ada72a3c17f1986d0f961b42c672c0247af786 --- /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 0000000000000000000000000000000000000000..da606402ba92cd605189073605da77ab9275c83f --- /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 0000000000000000000000000000000000000000..f2b482cb433d4b559e161846dc746a00716f50ed --- /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 0000000000000000000000000000000000000000..b3ed02d213acf025abb81a9aeb8ed6fcf2edc87e --- /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 0000000000000000000000000000000000000000..276e590763ac723cfeeda907470cae65c32a00f8 --- /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 +#include + +#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 0000000000000000000000000000000000000000..5bb168d7d4ebb18169840c2c06d786b9c58e537c --- /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 0000000000000000000000000000000000000000..a1fc0080bada245977f1535d8715ecec2fef5692 --- /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 0000000000000000000000000000000000000000..949cd979f241f3bbbd735f397b318497922c887c --- /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 0000000000000000000000000000000000000000..2c7863ecc8df79e5fe7e643ef3c8c9eb92a6bbeb --- /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 0000000000000000000000000000000000000000..04383218eb1169fdcee8eddb39419a970cbf42a1 --- /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 0000000000000000000000000000000000000000..4551fd7febf841ad7e44f4ad97b1b335c4bd6592 --- /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 0000000000000000000000000000000000000000..01b8627da36d4490095330d5d30a81943398d104 --- /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 0000000000000000000000000000000000000000..d85bcc983833b93ada4c9f0754033d8ba187eae5 --- /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 0000000000000000000000000000000000000000..9da3fb89f7613aae31bf232500dfe10409605773 --- /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 0000000000000000000000000000000000000000..a018fcfcb8b7dddb75f123aedae49476c9670be8 --- /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 0000000000000000000000000000000000000000..712a7fdfaf71e8bdffe06a52c84b288e2ef1ab1e --- /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 + +#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 0000000000000000000000000000000000000000..2ea508ba9ee4bc5d88f03cac9ab9d6d921572e20 --- /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 0000000000000000000000000000000000000000..f937cb78d0b367117754bac94fb6c80dff6758c8 --- /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 = / + + 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 + + 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 + + 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 */ + 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 */ + + 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 0000000000000000000000000000000000000000..c62cba66a53316d3f8bd9d612e81b6cfef1e4620 --- /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 0000000000000000000000000000000000000000..f6235ad38ff81652252268e7bca9d49a22b6fc1e --- /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 = / + + 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 + + // 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 + + 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 */ + + /* 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 */ + + 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 0000000000000000000000000000000000000000..6ea06ea4ad2cf4a9c6430d57b9fdcecbe5590abb --- /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 0000000000000000000000000000000000000000..e44e4bc9d292b7d9d8d4998f1f9b9f083514242a --- /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 +#include + +#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 + 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 */ + /* 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 0000000000000000000000000000000000000000..a5c7f4ead8cc8f87ddda89dfc3fe9d30a003b3bb --- /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 */ + /* 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 0000000000000000000000000000000000000000..67c7aa3fbc2aa65556c06bb5634a0f53afa772db --- /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 0000000000000000000000000000000000000000..d0865944d89192df6ced4a788ae805c858cc2a08 --- /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] = , 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 0000000000000000000000000000000000000000..b6689240cd9eebd370a54103a8171f833c5d67d9 --- /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 0000000000000000000000000000000000000000..87766a92f09b7197147081806d76005cffae7722 --- /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 0000000000000000000000000000000000000000..f35a5c57daf8bede66100318c68509aa5668fe3d --- /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 0000000000000000000000000000000000000000..c8d7b1393297f23e884a62865f0891b317cf0cd8 --- /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 0000000000000000000000000000000000000000..21ade697b1219b5181736491e9fccafb1720b986 --- /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 0000000000000000000000000000000000000000..64be4dd4571c6a39d6bbd152fdf8128ca8b9aa27 --- /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 0000000000000000000000000000000000000000..6add29926d8e1cfc5c82ad9fa962ee1957540a8e --- /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 0000000000000000000000000000000000000000..588abbbb8663af05442289674086f1c14e9d80a7 --- /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 0000000000000000000000000000000000000000..0b2d2a14225d4100ab1f12ce89bf7c2cc5eef125 --- /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 0000000000000000000000000000000000000000..4928ac4403d4eb36e061746a32d522fff63a8094 --- /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 0000000000000000000000000000000000000000..b0f5b3a142baa929e58e808c70fba7813c931d06 --- /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 0000000000000000000000000000000000000000..c210932ee433dc2f21db0543eba5f8fe54844550 --- /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 0000000000000000000000000000000000000000..001897bcb250241938a305491915bf4971d5e63a --- /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 +#include + +#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 0000000000000000000000000000000000000000..65ba481866a1de269ba54cc7749a3aafaa46d6ee --- /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 0000000000000000000000000000000000000000..3c1a4bc13b0f7d61de4b47d34be6c2a69ea6e58f --- /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 + +#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 0000000000000000000000000000000000000000..705a1d407b537bfd11f11cdb6d15770b11cd02bc --- /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 0000000000000000000000000000000000000000..7d034e084f523ad170b6956bc3af95777eb2477f --- /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 0000000000000000000000000000000000000000..f8c1481f9dca7a5f774f1b16cfd8cff0e8fb4861 --- /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 0000000000000000000000000000000000000000..68d7345c14b7d452dd77204dea8b15e762d7c797 --- /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 + +#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(), (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() + 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] = , 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 0000000000000000000000000000000000000000..5a846fa624f631542ba5d2dbf284fbe0e328652e --- /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 + +#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] = /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 0000000000000000000000000000000000000000..5e87cc9dd5e60c885f1bc4abf698393181c9e411 --- /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 0000000000000000000000000000000000000000..d3a2ec0d6e10ba42513e61948e40401bb399a806 --- /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 + +#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(), (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() + 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] = , 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() + 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() */ + 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(), (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() + 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() */ + 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 , + 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 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 0000000000000000000000000000000000000000..df7f3077c4334a14f303fa5ddbb3a99f781b9097 --- /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 0000000000000000000000000000000000000000..02544cf0021a037e7b64b4169981b198d6ca40dc --- /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 0000000000000000000000000000000000000000..6b47bfe62d0d769e2c2acc87299d5144df774f7c --- /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 0000000000000000000000000000000000000000..fdc2440915d9f3ad9df9ab9355aba8e0f7c78017 --- /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 + +#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 0000000000000000000000000000000000000000..abe676ffdbf48dc0d3295c280fbd8c548d2631db --- /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 0000000000000000000000000000000000000000..9088f7df24e8518a4eeb42753ced92bf3e0ae73c --- /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 0000000000000000000000000000000000000000..8ad11a88dfdbb9129670dd5a577d29395556583c --- /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 0000000000000000000000000000000000000000..c58b6879f4cbad57f4257131f480f397096e6020 --- /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 0000000000000000000000000000000000000000..621143de1aaee7a34103bb4afbc25985b826442a --- /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 0000000000000000000000000000000000000000..c1aff6b5b3779a77aa63199ea99797328fc44a06 --- /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 0000000000000000000000000000000000000000..233ccb0bddead312ac614fc77a180e1d42189874 --- /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 0000000000000000000000000000000000000000..f8da5898aebb04500e902eca8697eb7f4442b3cb --- /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 * + * t[1] = -2*gp * + * t[2] = gc^2 * + * t[3] = -2*gc * + * t[4] = 2*gp*gc * + * + + // 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 * + * t[1] = -2*gp * + * t[2] = gc^2 * + * t[3] = -2*gc * + * t[4] = 2*gp*gc * + * + */ + + /* 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 0000000000000000000000000000000000000000..3f1f03f02f467638dd161e12a5db930e82318c53 --- /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 0000000000000000000000000000000000000000..d09fbe3458f650f2cf699ca3e7ef7ba90bfa5a48 --- /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 * + * t[1] = -2*gp * + * t[2] = gc^2 * + * t[3] = -2*gc * + * t[4] = 2*gp*gc * + * + */ + + /* 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] = // LP residual energy + frac_en[1]*2^exp_en[1] = // LTP residual energy + frac_en[2]*2^exp_en[2] = // LTP/CB innovation dot product + frac_en[3]*2^exp_en[3] = // 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, <pg, 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 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 0000000000000000000000000000000000000000..b739dad5b014cc3906568c762de907a76a994984 --- /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 0000000000000000000000000000000000000000..740abcb800e20002cf89d845ab58207994fbbd2f --- /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 * + * t[1] = -2*gp * + * t[2] = gc^2 * + * t[3] = -2*gc * + * t[4] = 2*gp*gc * + * + */ + + /* 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 0000000000000000000000000000000000000000..352b611447d3ed6ef3cafc6bf10c6298f3324cdc --- /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 + +#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 0000000000000000000000000000000000000000..7591f5f859774df10bb709bd9a7700c2c48efb5e --- /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 0000000000000000000000000000000000000000..d626de37e5a49dc8a41f47c5d39ad1f4ea69cfb9 --- /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 0000000000000000000000000000000000000000..7b0185a24e5a3ce2962ddd8a33838a04f3277caf --- /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 0000000000000000000000000000000000000000..3e744f6b0ddcf181ce6dca328e95a5b98f238fe2 --- /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 + +#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 0000000000000000000000000000000000000000..c3cb1cf5d845a3f96904086eaa6b2e2cef504ee9 --- /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 0000000000000000000000000000000000000000..77ae9ded8772486f736cdc996299b96ab3982390 --- /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 + +#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 0000000000000000000000000000000000000000..8eb2a9b6456aab7a6517116799c1869a21a026e3 --- /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 0000000000000000000000000000000000000000..71d645a99c88784a719f96523cd6024ba3bdfa90 --- /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 + +#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 0000000000000000000000000000000000000000..77d35fcfa9fced5bc1dc63544ab8049c21810cea --- /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 0000000000000000000000000000000000000000..b9574aa793330f7f245b8a43fe55d86789fb8b9a --- /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< 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 0000000000000000000000000000000000000000..edc43e4a187cf47cabe66add765f2ed4257ed8d5 --- /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 0000000000000000000000000000000000000000..455a51028a2cba7f15e1993882f85b67f720f668 --- /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 + +#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 0000000000000000000000000000000000000000..fb06e6447eae6f4c1535655257c7d80b6d205ef6 --- /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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..c9e1c25c8901ebe64e3e743bce0c4413c0d8d33d --- /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 0000000000000000000000000000000000000000..eca5ae0077254f96dd58e8ff12e6b3fb7a7b41a2 --- /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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..2e53d13bb7c890778be31e6a01a72c9e146397a9 --- /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 0000000000000000000000000000000000000000..97c7402c65756cda3e6a3a094c51c5ef5cd0bbc1 --- /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 0000000000000000000000000000000000000000..740bc16f26ca9108ee4ed227953f4448749e2550 --- /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 0000000000000000000000000000000000000000..4868822fbf1bfea5a14dcf7185a76598fdc8b97b --- /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 0000000000000000000000000000000000000000..44fdc09c9665ffda3533a5d06a45f6cd0547e5de --- /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) & 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 0000000000000000000000000000000000000000..8cae5599c462c1f7f80cfb83a6db5bdf500a519d --- /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 0000000000000000000000000000000000000000..b80555b6bb9150e49168d6df14b05edf8c9703e9 --- /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 0000000000000000000000000000000000000000..a81f0895c0191a95a75edc7e7ae6a8c326ddeed4 --- /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 0000000000000000000000000000000000000000..7c798ccc2a5a27011bd81357d81b0513f82c4a48 --- /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 0000000000000000000000000000000000000000..251a3ce4aafd6033c13d276997ec6884a83f424f --- /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 0000000000000000000000000000000000000000..b325e8fc1f642928c80e48105cbac2d5fe624f0d --- /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 0000000000000000000000000000000000000000..48e43dba2ac11c86d76d3560b21241f82e963b15 --- /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 0000000000000000000000000000000000000000..65034545189652b3c0cd4267197a339feaac20f4 --- /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 0000000000000000000000000000000000000000..c70c163866e2031cfcab42010cb373abd817d8a3 --- /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 0000000000000000000000000000000000000000..f032a085e52bede45d0e49ead311ea6728d17e1c --- /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 0000000000000000000000000000000000000000..3ccebdbf23b346084ebc215186dabb1c29c867f8 --- /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 0000000000000000000000000000000000000000..72d353a899a252d89b87aca48acdab85029c8863 --- /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 0000000000000000000000000000000000000000..40093f5c81b2e38f25ab1316e5e4bf25ef2eaa1f --- /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 0000000000000000000000000000000000000000..05527334d7e5b9a24757bcf52ae4cfb1a9b88793 --- /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 0000000000000000000000000000000000000000..c699808f95d44281ab456cdee49dc5d04e243222 --- /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 0000000000000000000000000000000000000000..ec1d6e0854d0c54779f61c92ed25012d84cdb90c --- /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 0000000000000000000000000000000000000000..b922de547f54b18a07cc1c52c6e180166fbe4173 --- /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 0000000000000000000000000000000000000000..e1966c6c4425affb914d7da7a176e9cf8053850b --- /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 0000000000000000000000000000000000000000..3be1d9c5602beb3133b41b9c3fe804cd336bfaa6 --- /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 0000000000000000000000000000000000000000..2c1059fbeffb983af59054780621d06ab0978fdf --- /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 0000000000000000000000000000000000000000..0325311810199bdcbde6c98d378ca70334f683a1 --- /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 0000000000000000000000000000000000000000..e4c80ef76ec77458dc5993654e0c03e357820c44 --- /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 0000000000000000000000000000000000000000..806851ea42e851fbe3e221fb9c7340ba8bce264a --- /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 0000000000000000000000000000000000000000..7b08a4060e35887e61ce7a216040a8fca518f9e0 --- /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 0000000000000000000000000000000000000000..4bfcf9c8e75f88cef00765910f9d635d0c0b6d82 --- /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 0000000000000000000000000000000000000000..d5a7984dafc47a82af8f58648ac991179713c9c9 --- /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 0000000000000000000000000000000000000000..3eb5cda83eb161abfd4bdbb948c496e5e2d40d6b --- /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 0000000000000000000000000000000000000000..1ebcb86bf41acdbd1f844b09585953aeacffb0da --- /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 + +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 0000000000000000000000000000000000000000..d1ec790984b43e7324f58743321ac86296245d82 --- /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 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 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 0000000000000000000000000000000000000000..8951e5cc8fb387895c37edf214ead97fe47fd656 --- /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 0000000000000000000000000000000000000000..b8cfefac8b7e0b0463172b70fabbdb993087c88f --- /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 0000000000000000000000000000000000000000..c40bc10f2ea5a19ed61d201721900b2940bfd9ea --- /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 0000000000000000000000000000000000000000..59671155652a7d7feaa51f4d060bb8ee98436e58 --- /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 0000000000000000000000000000000000000000..df239d2ce8281be6f626fabd1030295790f4cc5f --- /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 0000000000000000000000000000000000000000..c800a2e554ba74510d3860c0b2bdef9000b00871 --- /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 0000000000000000000000000000000000000000..7fd680dbaf392b5ce378e4fc84c5260d65784ac2 --- /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 0000000000000000000000000000000000000000..741b584f90754ae1b98ff2c002d7ae2257d4079e --- /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 0000000000000000000000000000000000000000..ecf1bf35bcf23388153e292ad2e5d586f2f7826d --- /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 0000000000000000000000000000000000000000..e348916217502fb3213cd1155bd7e34a9a4f86a0 --- /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 + + +#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 0000000000000000000000000000000000000000..92c235f0e8230207d85e95d16685df22628ecdfc --- /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 0000000000000000000000000000000000000000..0ac52b341f08d46e17c935c0fa39c767b8fe6ac6 --- /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 0000000000000000000000000000000000000000..07e342bce669dc5362740d61438918ffcd7f8a3d --- /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 0000000000000000000000000000000000000000..4e9f67eacf0d0e70671d79277428a21168f4d987 --- /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 0000000000000000000000000000000000000000..e5630e8dcce39434df0fc1e5e4003b3fdf2c5b9d --- /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 0000000000000000000000000000000000000000..0d465c66feb45c4dcfecd32aaee74b7783777af3 --- /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 0000000000000000000000000000000000000000..61f8c068503deb28faaf0c7259bfd8eb8766f565 --- /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 0000000000000000000000000000000000000000..d57522ec1990a349ed252aba323f92243e7b1c92 --- /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 0000000000000000000000000000000000000000..b2b02b1e40c54aebe4fc291ea7896990e95f8161 --- /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 0000000000000000000000000000000000000000..c3aa887b513ce8d8db5fa68c95ca3947394f33ce --- /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 0000000000000000000000000000000000000000..4bfc3c5bbea6d19c41f1d1fe0290303a7de1e5b5 --- /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 0000000000000000000000000000000000000000..6153c67d3298567abb78a12406d9806e44e06ef4 --- /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 0000000000000000000000000000000000000000..e1af6d4293b83fb5fa55104ba58f625078e1f134 --- /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 0000000000000000000000000000000000000000..63d2e00b5d196522ddde11e0fccfa513d87c7c17 --- /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 0000000000000000000000000000000000000000..d3c3041a0d0d7505569f0d74634303656e56db3d --- /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 0000000000000000000000000000000000000000..4ff5f10949b01f1eed87e88a5bfaa1a678be7115 --- /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 +#endif + +#include +#include +#include +#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 0000000000000000000000000000000000000000..85ddcebb4655ff8180be6af7026c24321368b06d --- /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 0000000000000000000000000000000000000000..9ccb49c6b8b8da3a897e97a053612ee0c48c42b9 --- /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 + +#include "SoftAMRWBEncoder.h" + +#include "cmnMemory.h" + +#include +#include + +namespace android { + +static const int32_t kSampleRate = 16000; + +template +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("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("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 &inQueue = getPortQueue(0); + List &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 0000000000000000000000000000000000000000..d0c1dabf93138ea8f411177d724d65123595bbce --- /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 0000000000000000000000000000000000000000..5bade44f92bb77a49e526bc047c8bcd56f61f5ee Binary files /dev/null and b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf differ diff --git a/media/libstagefright/codecs/amrwbenc/inc/acelp.h b/media/libstagefright/codecs/amrwbenc/inc/acelp.h new file mode 100644 index 0000000000000000000000000000000000000000..5a1e53646456b9da70a75d5b177d26bcf78268b6 --- /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 */ +/* 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 0000000000000000000000000000000000000000..f42a27cf8b69a8510ccaa1fb40e75e82a0a6d7ee --- /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 +#include +#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 0000000000000000000000000000000000000000..e8806841f35fac3f50a558bb1e9c1f6a7c52fe6f --- /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 +#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 0000000000000000000000000000000000000000..5395d2dce545cba544812dbc5f8142b50d6a5d49 --- /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 0000000000000000000000000000000000000000..53ca55efd325d2581cf33b61accf970a01d4294e --- /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 0000000000000000000000000000000000000000..0bdda674837fd22de3fcdb7a4831ee6c554179d5 --- /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 0000000000000000000000000000000000000000..658d28deb3cf0f7696758605c5582fd0182d623b --- /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 0000000000000000000000000000000000000000..560a9973de5683f00daa328b63b5e10a2402322a --- /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 0000000000000000000000000000000000000000..e399fb8455973376d872496e74f0b1fd8451c7f0 --- /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 0000000000000000000000000000000000000000..865eea0ac5706daf73b460e333d5a847d072e383 --- /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 0000000000000000000000000000000000000000..9c73357f2c828239d58baf8ae9cc35924079a651 --- /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 0000000000000000000000000000000000000000..b065eb4df437159df9551ef38a2396ca57f06d3a --- /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 0000000000000000000000000000000000000000..85fa73c8edb1fbc43183c25abf57dcc7d6bba25e --- /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 0000000000000000000000000000000000000000..3a6f9638566d8e5fa34db5e74b48bf04e5c0a505 --- /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 0000000000000000000000000000000000000000..7b6196b272ef5f3ed56f7170e5e9c579aaf53e7f --- /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 0000000000000000000000000000000000000000..442786a16b19d182fae81f83de5ac3404851b2ce --- /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 0000000000000000000000000000000000000000..7b485eae99dd993cfe5ef00525f4dab4bc9456b7 --- /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 +#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 0000000000000000000000000000000000000000..7a0f564ce8a40a9ad09f2ac29e069e0b241f9dda --- /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 0000000000000000000000000000000000000000..4a13f166fa564c6330aa3038f994d23d41b0a915 --- /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 0000000000000000000000000000000000000000..d74ec8ea8a2ad02d8658581997dabd2094ccf235 --- /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 0000000000000000000000000000000000000000..bc36489d80ef9784943b09e5e1af83fef0318fe1 --- /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 0000000000000000000000000000000000000000..b5d52802cf0e41e8b08c237a6399708b102420a4 --- /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 0000000000000000000000000000000000000000..43c47e96efbcbdc4aaf55617fe95ab6371cf4341 --- /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 0000000000000000000000000000000000000000..b6b4e817b5b235f453f6eb8e7b8e2bfa5a3fa351 --- /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 0000000000000000000000000000000000000000..4c1d0f07c230c7e6d05dcbd4dfedfeedc99a29a0 --- /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 0000000000000000000000000000000000000000..f08a678c73b54771732b9ce52ebb68bbff9d4631 --- /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 0000000000000000000000000000000000000000..0062584adb5bf6b3d8611e771d80e01d2d00fd8b --- /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 +#include + + + +/* +******************************************************************************** +* 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 0000000000000000000000000000000000000000..6822f4898e12f08e6f8ebc73d9c5a405547562d8 --- /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 0000000000000000000000000000000000000000..04fd3186918c7d7cd207a27c2af08fc03fa50249 --- /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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..282db9218df11daa5e436f9221a583ead957dfff --- /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 0000000000000000000000000000000000000000..4aa317e63defd253aa47c0eb2a5bd182ba02f3e4 --- /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 0000000000000000000000000000000000000000..856ada86340b4bfb1d55c988d958749fa9443385 --- /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 0000000000000000000000000000000000000000..49bdc2b4bcf9aaf3b7d7c6b1d2a04eb944fed63c --- /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 0000000000000000000000000000000000000000..3f4930cba76c5ade49b8c261c537d00b1ab21fd0 --- /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 0000000000000000000000000000000000000000..71bb532dd74d2a771b3f4e130029d70b166ac7ce --- /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 0000000000000000000000000000000000000000..2d4c7cc9bbe963f91aa58c627890e0593812c04c --- /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 0000000000000000000000000000000000000000..e0b338d547f486fab6f3e71b225c4f535df761f3 --- /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 0000000000000000000000000000000000000000..5ff096488cb932cfbc07f920f9858f3bfd19d2dd --- /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 0000000000000000000000000000000000000000..b300224513d47184dc662259f40b4d0bb9a52299 --- /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 0000000000000000000000000000000000000000..0c287a4d6286a163174562794202ab777a444d9a --- /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 0000000000000000000000000000000000000000..1d5893f3d360fa0993effb53f1679883afb583a1 --- /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 0000000000000000000000000000000000000000..8230944d42173240329b07b8db10c14b1dbde5ef --- /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 0000000000000000000000000000000000000000..14ba8289f4caeb32c2747754efc59335fe359500 --- /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 0000000000000000000000000000000000000000..4263cd4d1817303c2f6807247e8ba547c89c5144 --- /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 0000000000000000000000000000000000000000..e786dde79d68e57ed228a772bbc3f42bada486a0 --- /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 0000000000000000000000000000000000000000..8efa9fbba4edccf8c50c871d8028493bc9b3232b --- /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 0000000000000000000000000000000000000000..8904289b55accb7187e5b3ffd02238c9eab314d1 --- /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 0000000000000000000000000000000000000000..6b782cb40b8198cf8e92141088935dcdb93f2f8e --- /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 0000000000000000000000000000000000000000..394fa8301e0733fb8ed642743a8512ab83fbad23 --- /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 0000000000000000000000000000000000000000..e45daace8b2ea39e0ad76a78d05b50639d2aab18 --- /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 0000000000000000000000000000000000000000..5731bdb357282fb8deccd30c088d7f8612bf75ca --- /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 0000000000000000000000000000000000000000..8c477caf4d8b07e705033fdf18e3348fff78f172 --- /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<> 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 0000000000000000000000000000000000000000..43db27a88ec99469c468b140491a7982b5198406 --- /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> 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 0000000000000000000000000000000000000000..e78dc1f26fcdeac0633799ac9363b3099454e6c6 --- /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 +#include +#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 0000000000000000000000000000000000000000..18698e223e906aae7e004a2389c967834bf01032 --- /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 0000000000000000000000000000000000000000..1ecc11f536f1ca9889ab1492c19909478d57890d --- /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 0000000000000000000000000000000000000000..acba532a507f67b13c4cd52d7820f8cd77d62d2b --- /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 0000000000000000000000000000000000000000..d9245ed60ca805e098c04a0ba3f9acf0cee3a55e --- /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 0000000000000000000000000000000000000000..3b88514ac51b1e624004e47d3dabac0892d462f1 --- /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 0000000000000000000000000000000000000000..0c49d6be0b9dbc13c62343530a22303420178e70 --- /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 0000000000000000000000000000000000000000..2cfaced0f14838507181a13a1fc0ed309fe5519e --- /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 +#include +#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 0000000000000000000000000000000000000000..d681f2e34dc2857c2954580a8630d6eeae3b77aa --- /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 */ +#ifdef ASM_OPT /* asm optimization branch */ + /* Compute scalar product */ + 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 */ + 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 0000000000000000000000000000000000000000..800b3f99161320f3bd6349e06588c65f675cdaaa --- /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 0000000000000000000000000000000000000000..565040fbd2c6d94c29f780dd6ffce93000afbe7f --- /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 0000000000000000000000000000000000000000..a6f970168a89519af094c18fad20ea83ffb86d56 --- /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 0000000000000000000000000000000000000000..c1c7b83b4af9b9379e1ee53a8fcc7df7e7c657e3 --- /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 0000000000000000000000000000000000000000..8e66eb0c82fb7c41fe821930330cad6e8de4db0b --- /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 0000000000000000000000000000000000000000..bc1ec49e2e5bbb7bf7bcdab3dc513e47cd979283 --- /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 0000000000000000000000000000000000000000..1119bc707863d37b6edf84769efda68b471cd049 --- /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 0000000000000000000000000000000000000000..30a8bbdcc42413eccf0abeab046a3e57267d7078 --- /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 0000000000000000000000000000000000000000..b4ba408c31758021bcb67be5498002b3ff06c333 --- /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 0000000000000000000000000000000000000000..49c622c26bda0cc7df46c6f3a4cf307559b99a8b --- /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 0000000000000000000000000000000000000000..4b2f8ed9006356a6a67a3f874fcf61cf51742a21 --- /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 0000000000000000000000000000000000000000..0f655416c86625e532f78318d7aa2977bf2f5b77 --- /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 0000000000000000000000000000000000000000..1d5d07641e776e541f5108f8378f26a1a9b17517 --- /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 0000000000000000000000000000000000000000..7affbb20d81f440ebf0f18477bb35fc44ccfb099 --- /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 | +| | +| 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 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 0000000000000000000000000000000000000000..3b7853f198542673f385777accc80329bfe73153 --- /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 +#else +#include +#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 0000000000000000000000000000000000000000..27cad76f308dddb9ebcb4425b736a7309472a195 --- /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 0000000000000000000000000000000000000000..b8174b91b4ead7c143c0b4bf75d2fd890113efaf --- /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 0000000000000000000000000000000000000000..6f55b8f734630241026e0de72bd44bfa7f7cade9 --- /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 0000000000000000000000000000000000000000..0d66c3158c5f668e348688392520189cc80c0a5c --- /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<> 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 0000000000000000000000000000000000000000..8404cf9d4d5c618813721b8da634863f1e659820 --- /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 0000000000000000000000000000000000000000..c867bf7598bca94b24b6fba515dc7f7012eff258 --- /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 0000000000000000000000000000000000000000..e8ca043ec5ed7d8acacfe641b53d8e4221817d80 --- /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 */ + /* 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 and 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 */ +#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* */ +#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* */ +#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 0000000000000000000000000000000000000000..80a0b738bbddfa6142f9c17bd7339920621ea7b4 --- /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 +#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<> 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<> 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< 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 0000000000000000000000000000000000000000..b89686357ab9b72c434a199257bd9aceee734222 --- /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 0000000000000000000000000000000000000000..b0c04b521d2778d9db65ff183b1ceabbf9f6c8d3 --- /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 0000000000000000000000000000000000000000..418cc064b2f3a04291c2d5263f97de76543797bc --- /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 0000000000000000000000000000000000000000..780f0090b152a8cbcdd63f8c7db0806106e0a41f --- /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 0000000000000000000000000000000000000000..1bda05a0f8ff6ae8475a3fcd55654d981509d381 --- /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 0000000000000000000000000000000000000000..96779fd3774e7f31767137943af6276d6af6948f --- /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 0000000000000000000000000000000000000000..76ab1b1cf57b7274751ee049c6ccc3cce75f4c62 --- /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 0000000000000000000000000000000000000000..ea9da5238710cb11d6c93af2fe1c546e8febea53 --- /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 +#include +#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 0000000000000000000000000000000000000000..d8900446e552853223495ec213f8d7cd408c233e --- /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 0000000000000000000000000000000000000000..13dd2aa06f12c39c1d001c15639e12e4365e5571 --- /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 +#include +#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 0000000000000000000000000000000000000000..a02b48d1d071b93d6cc722f37fa5b996b2e42b67 --- /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 0000000000000000000000000000000000000000..2e431205aa6d7f8512da485ac3f6820d26ac7394 --- /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 0000000000000000000000000000000000000000..22dee15cf6231c6b7ada80edb0f2771c979a2ab8 --- /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 0000000000000000000000000000000000000000..ec8b6de9f338085b348b23d59cf6deeb8a8b9a32 --- /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 + +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 0000000000000000000000000000000000000000..3331689054481f91157c4ff2873f991d9b08d0de --- /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 0000000000000000000000000000000000000000..465e604a86e952f5b29d789869dc812df2e966f6 --- /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 0000000000000000000000000000000000000000..cbbf0c6715537dddb347ae0940c7140670ac56b7 --- /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 + +#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 0000000000000000000000000000000000000000..5ed4c825989955227b48540c224bbf3dd21e7234 --- /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 + +#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 0000000000000000000000000000000000000000..2c4c7da47881aadb72802416c25958384951d16a --- /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 0000000000000000000000000000000000000000..d66eba3045ab118f19a0ff4f0939f8c919fddcb3 --- /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 + +#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 0000000000000000000000000000000000000000..414b8f7bc480373e954c62824d1745ada415cdc9 --- /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 + +#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 0000000000000000000000000000000000000000..4ddc7ddf1c4fa231a8cb096b502f1e82dc251078 --- /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 0000000000000000000000000000000000000000..7533f07736c9715049872dbac828b8dc14a5c0d3 --- /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 + +#include "AVCEncoder.h" + +#include "avcenc_api.h" +#include "avcenc_int.h" +#include "OMX_Video.h" + +#include +#include +#include +#include +#include +#include + +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(malloc(size)); +} + +static void FreeWrapper(void *userData, int32_t ptr) { + free(reinterpret_cast(ptr)); +} + +static int32_t DpbAllocWrapper(void *userData, + unsigned int sizeInMbs, unsigned int numBuffers) { + AVCEncoder *encoder = static_cast(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(userData); + CHECK(encoder != NULL); + return encoder->bindOutputBuffer(index, yuv); +} + +static void UnbindFrameWrapper(void *userData, int32_t index) { + AVCEncoder *encoder = static_cast(userData); + CHECK(encoder != NULL); + return encoder->unbindOutputBuffer(index); +} + +AVCEncoder::AVCEncoder( + const sp& source, + const sp& 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& 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 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 0000000000000000000000000000000000000000..54cc9b12d6dca7500abf6fe0f223435f332ff58e --- /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 0000000000000000000000000000000000000000..d39885db3989f414339b761a93dbbc9b0789e59f --- /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 0000000000000000000000000000000000000000..6841ec33c77d1604a7e1de2054842b2e7e85e48c --- /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 + +/** + 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 0000000000000000000000000000000000000000..3fe08a10c85b297df3c8ff8c4583040490e58475 --- /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) +#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 0000000000000000000000000000000000000000..17e28ef8d394967310c4e52064c0a92355915cbc --- /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 0000000000000000000000000000000000000000..75ab51433ce54158ad1fadf960ddffda1ce46b04 --- /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 0000000000000000000000000000000000000000..01e26a60b602ef6bc0a3af943f1f0db61ced602e --- /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 0000000000000000000000000000000000000000..38a2a15e0f788c27ba3154ff5d728ec0ebf5903b --- /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 0000000000000000000000000000000000000000..9acff9eb651719e76456180855e61aded949fd78 --- /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 0000000000000000000000000000000000000000..c258b574ef64524b712f9c872177827dc53e5a3c --- /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 0000000000000000000000000000000000000000..17e5985afbe089b314e67eb5262d11128bc456c0 --- /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 0000000000000000000000000000000000000000..ac62d782c83d4da5767548f064c39cc3e94af35f --- /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 0000000000000000000000000000000000000000..f650ef9f5fe7c07f1f64ea9a0ed32e72a64a0f69 --- /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 0000000000000000000000000000000000000000..15b55fb82a54635a34a6d7772072ff6ecee75fc5 --- /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 + +/* 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 0000000000000000000000000000000000000000..42eb91004746f0b688080cf282cc60db4d3c8c77 --- /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 0000000000000000000000000000000000000000..ae7acd238175edd68b5b32529ceca71cff814921 --- /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 0000000000000000000000000000000000000000..faf21989ff62f6779026c41db4f5b42eab647efc --- /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 0000000000000000000000000000000000000000..3a2164778f4f04ff112c9967ecbe3b5cac45814d --- /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 0000000000000000000000000000000000000000..f39794f155e6609477a177f3787fa26be74ec18f --- /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 0000000000000000000000000000000000000000..d5d4a4283ac6882c76c2b2fa10ac1cf31e448e5a --- /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 0000000000000000000000000000000000000000..f6d066e1f7116c41bc4809979a747e51edd1af80 --- /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 0000000000000000000000000000000000000000..222e709b301b0d222eaa087d1639250141bb1264 --- /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<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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..af8795ab570b4cca744185ea98f70d35ddb88a6e --- /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 0000000000000000000000000000000000000000..187f25cc1f2110e8272380a5254fcd4efecf28fd --- /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 0000000000000000000000000000000000000000..aa52bd98f0709b432fb3b0f075dd2d4299987d06 --- /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 +#include + +//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 0000000000000000000000000000000000000000..0308dfa92dbebc98b76d77660e13b8213e3519cb --- /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 + +//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 0000000000000000000000000000000000000000..9ecb14246949687cbde577e6e57d41f82b041036 --- /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, /*! */ + 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 0000000000000000000000000000000000000000..d8628eeae018e105cfc1fa85e2029d8113438462 --- /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, /*!
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 0000000000000000000000000000000000000000..320a2f82f87fd584f2b0a96a4eac894aa3449c05 --- /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 0000000000000000000000000000000000000000..8dfb634d51b64bd2902d8fed9f26ecfdbd9e5ba1 --- /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 0000000000000000000000000000000000000000..5f659ab051107c98545fa21c220c433c3641c5b2 --- /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; /*! + +#include "SoftG711.h" + +#include +#include + +namespace android { + +template +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( + 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("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 &inQueue = getPortQueue(0); + List &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(outHeader->pBuffer), + inputptr, inHeader->nFilledLen); + } else { + DecodeALaw( + reinterpret_cast(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 0000000000000000000000000000000000000000..bff0c68cb1dd83469b51334b370b51bf778af47f --- /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 0000000000000000000000000000000000000000..2e431205aa6d7f8512da485ac3f6820d26ac7394 --- /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 0000000000000000000000000000000000000000..8c245d10df27ff120ee17b7a4d0e80a6659fd317 --- /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 0000000000000000000000000000000000000000..a34a0caef68e218b9f256496569efbb3fe04bd2d --- /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 + +#include "SoftMPEG4.h" + +#include +#include +#include +#include + +#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 +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(MEDIA_MIMETYPE_VIDEO_MPEG4) + : const_cast(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(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 &inQueue = getPortQueue(0); + List &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::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, ×tamp, &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::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 0000000000000000000000000000000000000000..dff08a71b44ad4a7d968da8af2c6bbeefc67fe35 --- /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 0000000000000000000000000000000000000000..ec6871f3a6f84941896dfa318c16f839e4515414 --- /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 +#include +#include // 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 0000000000000000000000000000000000000000..24a50ceaddf15eebe1245275cf37ccb349f7f683 --- /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 0000000000000000000000000000000000000000..48da0dcbe5416fd9e527026f6b039022e6410dc8 --- /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 0000000000000000000000000000000000000000..e2761eb31e1ea535397f8e4b370f739aa3623c2d --- /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 0000000000000000000000000000000000000000..37250f3a6984a1448a0b814b965bfae4d11b5ef9 --- /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 0000000000000000000000000000000000000000..d52fa873271a5c4b8c564eb34d14c79a1ba1fd95 --- /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 0000000000000000000000000000000000000000..a75483a3dd730460ee1cc3a5accd33319ffa645a --- /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 0000000000000000000000000000000000000000..85889d3aed457ccb5827b7f6216872d1e591ba10 --- /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 0000000000000000000000000000000000000000..6593b48d88adac9c2bf4bf86c650b9394fabafe6 --- /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 0000000000000000000000000000000000000000..795cf71dceec1c4bc0a19ff2c2d963a82b15ee27 --- /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) + { + 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) + { + 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 0000000000000000000000000000000000000000..64992330438f44d70e1a13c2d6ec16b7cab84b0b --- /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 0000000000000000000000000000000000000000..e9ead016a413f799887ab6931027f8517e67aa21 --- /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 0000000000000000000000000000000000000000..00db04b8276c1319815e351e67f2e0a286a34b85 --- /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 0000000000000000000000000000000000000000..2a8bf1e3e2edc15354a8fd638f70713e9b15b6d6 --- /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 0000000000000000000000000000000000000000..c19c23a193e6022840d67910104e9ee9f07a3d26 --- /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 0000000000000000000000000000000000000000..ce779b06b2340804f5ec42cef75c92debfa70682 --- /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 0000000000000000000000000000000000000000..b5574b43d16027cb4ff54076c9aad812ce4d5898 --- /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 0000000000000000000000000000000000000000..a357ea6859a9cafc2b10fa71c31ae2c9b338f72e --- /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 0000000000000000000000000000000000000000..e23f23d1d78df15a5a893f7e89f8960943a4424d --- /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 0000000000000000000000000000000000000000..9cd9022e6665fe24d6d58899c7b056a0f075f4bd --- /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 0000000000000000000000000000000000000000..2e932a4e9b9a6b25b4103d0c1554371e5786aaae --- /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 0000000000000000000000000000000000000000..8edb6547b4840fb64743c9adcdc53975a59f81d2 --- /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 0000000000000000000000000000000000000000..f35ce4f58361a198c7d00c92062c04d27d467cee --- /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 0000000000000000000000000000000000000000..2d59c737a1bc8e27e22a54986b88fa4116442a22 --- /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 0000000000000000000000000000000000000000..fbc7be1aa130bfa15ff2ec51467b314192d01a04 --- /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 0000000000000000000000000000000000000000..25a31b79ac62024fda02747fdbaad4826bedf601 --- /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 0000000000000000000000000000000000000000..c45bb5fac261d78814877f3513e49683bfa862b1 --- /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 0000000000000000000000000000000000000000..0c12f201aea7e0e16880ef545fe367e001b5f784 --- /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 0000000000000000000000000000000000000000..9cd4edc359ad9df9d1c10a11304a703fbda54c5d --- /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 0000000000000000000000000000000000000000..3388d89db924cc8da098bfa89d2699ff18f405ba --- /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:(xUB) 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 0000000000000000000000000000000000000000..d6754a779525b9a3d340abbcb1ce4cde4e721b37 --- /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 0000000000000000000000000000000000000000..48414d7b32a93caa5515c8f4821b95ddc3a7013f --- /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 0000000000000000000000000000000000000000..b36050c5af0add8b75787f648cba2fafe3e0ecc6 --- /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 0000000000000000000000000000000000000000..091fdaf5a771c4c1c9c31bf3c8ab37d281111b19 --- /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 0000000000000000000000000000000000000000..3abc6be0ff5cda3e1466cf13722cf72c0cb7348a --- /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 0000000000000000000000000000000000000000..7c202223d4f18c547385decaceda8445ee4eaf6e --- /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 0000000000000000000000000000000000000000..b3a1ebddb14a8a3986a40a35dd9492f906cc6580 --- /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 0000000000000000000000000000000000000000..844bd14050bdadca6bdf578365e569dabebb7da9 --- /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 +#include +/* ======================================================================== */ +/* 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 0000000000000000000000000000000000000000..26abbaea12b5268fec765a5021ccb5eb75c84930 --- /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 0000000000000000000000000000000000000000..a1f95aa754abf76d563d33fd8782c6d743cebe04 --- /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 0000000000000000000000000000000000000000..404cc8bb4852174edf02ce897f781c6415dad411 --- /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 , +* 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 +* +* +* +* 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 0000000000000000000000000000000000000000..f7192b1c0f781ff415146a99667c8f35e2ffa908 --- /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 , +* 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 +* +* +* +* 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 0000000000000000000000000000000000000000..a8046062f822328c4d81c894d709f14a768e9b7d --- /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 0000000000000000000000000000000000000000..db13a485217853846037c5cf0abe04d63cbc07b9 --- /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 0000000000000000000000000000000000000000..704992fb1ba09d5342bab1ff9f770b0fbe12e830 --- /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 0000000000000000000000000000000000000000..b3c350f607398e255ace714a912e1ddb4e1ea288 --- /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 0000000000000000000000000000000000000000..4690a18ed97d072d6d5f7bf2800da1bd30580e78 --- /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 0000000000000000000000000000000000000000..33dbb14d0c26c4ea42f3813a573a6faa912ec8d8 --- /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 0000000000000000000000000000000000000000..2b7c93854a3da3e0c4d694fce1768cbd16db8871 --- /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 0000000000000000000000000000000000000000..20b0f8da2d908b24b75749fc212395a45655e936 --- /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 + +#include "M4vH263Encoder.h" + +#include "mp4enc_api.h" +#include "OMX_Video.h" + +#include +#include +#include +#include +#include +#include + +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& source, + const sp& 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& 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 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 0000000000000000000000000000000000000000..18e54dc47df91d8f12d90c7e81c3449af0f17830 --- /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 0000000000000000000000000000000000000000..a54fd8b5af61a369ca62ea4e3572e807a0de5578 --- /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 + +#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 0000000000000000000000000000000000000000..5c4c4abc7ff247ab040b90a2b2a016a3d97cf4e1 --- /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 + +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)<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 0000000000000000000000000000000000000000..0bce257628eec34a503756875b27865c96686e45 --- /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 0000000000000000000000000000000000000000..e725680e62b9b07a5145755e73036266c0c9b70b --- /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 0000000000000000000000000000000000000000..16c8e79d3c70c886ec9239fe822e20a10559f5bc --- /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 0000000000000000000000000000000000000000..fa50eeb5a3d6aa503a14f28a235b08a8d842d0e0 --- /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 0000000000000000000000000000000000000000..3dceb66705c1f0408550d7c9f9e961cb7c6e8392 --- /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 0000000000000000000000000000000000000000..f795bd9c2ace4fded50fed69e15ca52b0df45054 --- /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 0000000000000000000000000000000000000000..6fd41c3c592a2bbcbdbc294b54aab4811947c245 --- /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 0000000000000000000000000000000000000000..686a66d4c91c583fed99728aff73b2aed4a049f2 --- /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 0000000000000000000000000000000000000000..21d74276f488bff1ebb19cf42e4298e461d1b4df --- /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 0000000000000000000000000000000000000000..466ce4794bf9f5f83ab22e018b957fe1a7fed8b7 --- /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 + +/* ======================================================================== */ +/* 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 0000000000000000000000000000000000000000..79d0ebf8c26b14877d25eb2fe3a82ed23c54495a --- /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 0000000000000000000000000000000000000000..319c76f0cd6bca46edacaaf0364f896406945e13 --- /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 0000000000000000000000000000000000000000..c9e18d521532ffe27b05ae5d66d49d3fc13163c8 --- /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 +#include + +#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 0000000000000000000000000000000000000000..6dab31a29ed50f53652f886f376b09de8e679f34 --- /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 0000000000000000000000000000000000000000..b81d278633108182f47cc24a7a799913a7b0d630 --- /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 0000000000000000000000000000000000000000..997b78d2291a7f3746191243773f1e21048cb2c9 --- /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 0000000000000000000000000000000000000000..0d5a3e8a21c0b412b5d852fcfb9cb1629fba3250 --- /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 // for uint8_t, etc +#include +#include + +// 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 0000000000000000000000000000000000000000..946e3d099ec5b16706d9f5e82c2cfba19ff0f0bc --- /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 0000000000000000000000000000000000000000..8293576b1a006ebb3966a60f9500b36d675d8aa5 --- /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 0000000000000000000000000000000000000000..3bc94212bc4081c5a75f4d11fdc303836fd2f595 --- /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 0000000000000000000000000000000000000000..53149c1991558266517c1e71c74d6b1a7523a8b6 --- /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; nT */ +/* 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 0000000000000000000000000000000000000000..ad29549dad3d5d48f79645531bc5b82290ef32c8 --- /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 0000000000000000000000000000000000000000..8d18f4588ed61a1cc21beac5d909df9c175c7048 --- /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 0000000000000000000000000000000000000000..f05697cba7e4bdc5d72b1f6d9e70729449e01695 --- /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 /* 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 0000000000000000000000000000000000000000..d55778f61da664905bb7fe6a1d4096f3497b9d77 --- /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 0000000000000000000000000000000000000000..ba77dfd97213dabe0bcffeaa21ea1b2ea41538f2 --- /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 0000000000000000000000000000000000000000..4c7b929c60f3196669e517ed16abf2f22698fc14 --- /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 0000000000000000000000000000000000000000..79d62e4c3d3d8f45fe2a40e28f1e648633cd7e48 --- /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 0000000000000000000000000000000000000000..7ea5dc448791249cbfae90e026ceb3911647ac37 --- /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 0000000000000000000000000000000000000000..3721b6bdb94ad12486c450f4a6892b2ed0714f6f --- /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 0000000000000000000000000000000000000000..a2f49342046ab036f602f596cab59429032d7706 --- /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 0000000000000000000000000000000000000000..47076c33dc257e20bb79d8caa251b4b3a0cc8b5b --- /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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..ed51aa5aa8bb5b57fd6097538b07722e44b1d20d --- /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 0000000000000000000000000000000000000000..92009eeb76ff3d246521b86f923ccf91c9f7334c --- /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 + +#include "SoftMP3.h" + +#include +#include + +#include "include/pvmp3decoder_api.h" + +namespace android { + +template +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(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("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 &inQueue = getPortQueue(0); + List &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(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 0000000000000000000000000000000000000000..3a05466475f4d39c915864bcda380209dc0cde76 --- /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 0000000000000000000000000000000000000000..e287433dd7d921396f6eb5510dbf516f7facb928 --- /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 0000000000000000000000000000000000000000..2d94384fbd76a0242d5c347092bd162f34676b02 --- /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 + +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 0000000000000000000000000000000000000000..1568e7c1ddb4e19efc32708fdf8826e809cac734 --- /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 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /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 0000000000000000000000000000000000000000..f83732bb61d5fdb7443daf0e6989acc1b2a478ab --- /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 0000000000000000000000000000000000000000..3a6dd4fffd246f825610edff07295ac9ffec0472 --- /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 0000000000000000000000000000000000000000..618c50e25334c9ed08b824e5eb094f150d350319 --- /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 0000000000000000000000000000000000000000..9401d8c9b77fcd192e541af1d57cdb6216b736e9 --- /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 0000000000000000000000000000000000000000..96230c5378e031fe643c04c0c4a1f3ac895da1a6 --- /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 0000000000000000000000000000000000000000..5be75d4881ab37aa487b51bf28905094685fa188 --- /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 0000000000000000000000000000000000000000..abec5992f2bae4bf9983ee1264ef8af3f3218051 --- /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 0000000000000000000000000000000000000000..4f457372c118e7486369a4906622f48f23d60a2b --- /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 0000000000000000000000000000000000000000..f957267e2bc6bdb3fdf01d1688d15c2f3f37ecaa --- /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 0000000000000000000000000000000000000000..46e802231976bd492149da7d6f95f29e2a96e274 --- /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 + +#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 0000000000000000000000000000000000000000..31102ea0bbbf46ebfe5d7f0f1a3e15cd3b98c35a --- /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 0000000000000000000000000000000000000000..f14e2de717ce695266343165f0f57e33bf9e2c49 --- /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 0000000000000000000000000000000000000000..76a8229aa820bb967062fcdc179172270abce9fe --- /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 0000000000000000000000000000000000000000..71fbd208604ba6c5d77448d5a903b732c8263e3b --- /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 0000000000000000000000000000000000000000..ba438206d8ef74efc7d99845dd946ae82d291772 --- /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 0000000000000000000000000000000000000000..271e6b740dd59b74f87b48b898c33fe48f93fb39 --- /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 0000000000000000000000000000000000000000..32c76c66d96226a9bdd95218f274e9c1db07ebe5 --- /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 0000000000000000000000000000000000000000..2292d5f6aadbea8163d69a443c58a742b27ca017 --- /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 0000000000000000000000000000000000000000..20d0d8291fd899662382d47049d7c1441e43fd97 --- /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 0000000000000000000000000000000000000000..b7c277adfb88f0e8ac7266d91760d717cdcc599e --- /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 0000000000000000000000000000000000000000..a71efc4b4fd8c9fbfc5ff22a246890c5ce88244d --- /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 0000000000000000000000000000000000000000..e8bf76ed353e89272701c3db380cff06e2c9a997 --- /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 0000000000000000000000000000000000000000..4c5fb0300c7c281bcc1ded3c8db6073e91fcb829 --- /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 0000000000000000000000000000000000000000..ce3ec64a64336a1fec3a212a493408b91245d1aa --- /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 0000000000000000000000000000000000000000..6cf8e3edc0ac3f370c4b6c84c8d396332bc1697a --- /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 0000000000000000000000000000000000000000..d443b7ccfee74dd2bdcc9737e4bdad0aa51b3af7 --- /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 0000000000000000000000000000000000000000..2c2e89e4e79172def2696cec29f203bc06ba8fbc --- /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 0000000000000000000000000000000000000000..6e45a18a83da2e91fbb5236240b7e8663f306735 --- /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 0000000000000000000000000000000000000000..941ca6d839bf4693d8b101d944ba1e5cd064fb0b --- /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 0000000000000000000000000000000000000000..69e1987778b0382d5bc8c53371b8950b3d4f32c8 --- /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 0000000000000000000000000000000000000000..9393eb11875262760fc586abfe591c8e5f379636 --- /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 0000000000000000000000000000000000000000..f4a4efb15b099c276e702bed88afa37f1513de20 --- /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 0000000000000000000000000000000000000000..bbf134fbfbb2ef3992054b752a460273ae538f71 --- /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 0000000000000000000000000000000000000000..26bc25cd2d071b5f32ace79a6380748c1a3faba3 --- /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; chnum_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;grbitrate_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 0000000000000000000000000000000000000000..f6d4a3505c5a98a7e09c5884cc13354005b65efa --- /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 0000000000000000000000000000000000000000..423a7b12830d8a5d69eafdadf6ed117a9b38a7f9 --- /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 0000000000000000000000000000000000000000..8e9eaa8a5986b16f63c59dbc614a4958e9d430e9 --- /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 0000000000000000000000000000000000000000..f1a3ff8c052aa7484d85efde542ae9509f9c5a36 --- /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 0000000000000000000000000000000000000000..d4f262bf49a364d70877abeba3d3d1ce06cff575 --- /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 0000000000000000000000000000000000000000..7eaa860731ada84e3f63fa2d818d7cafbda548fd --- /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 0000000000000000000000000000000000000000..2d6ccd8e5d7a11b51c01a0ce6972806f93f65e0d --- /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 0000000000000000000000000000000000000000..8ff79538b5db56a1300d6883ce500dfca4bbfefe --- /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 0000000000000000000000000000000000000000..b058b007c81944576f3bc68c569d347821d5640f --- /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 0000000000000000000000000000000000000000..5d58cd2c227aee057ad19ecf87b666014a24b96b --- /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 0000000000000000000000000000000000000000..ff815dc62271b4248f4469a7d34aafb381a12dfd --- /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 0000000000000000000000000000000000000000..11961d1e1d7fa56dd346c512d40f635a734bc6ce --- /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 0000000000000000000000000000000000000000..ea42e498eb0289484597520c22c21086a33d6f75 --- /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 0000000000000000000000000000000000000000..09a735bf2740aa36f63795f5f2b4e93ed7c3ef95 --- /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 0000000000000000000000000000000000000000..e497aee228c1d73641095bc9d7ba86085ee860aa --- /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 0000000000000000000000000000000000000000..6a72aadf0f4f19a156f36947b3248c14ac161bb2 --- /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<=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 0000000000000000000000000000000000000000..6ba53d7d1168b7f3411cd146a7f8537e3abdead4 --- /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 0000000000000000000000000000000000000000..ee42dc50a64df330cefd2d148841d7b65a2b8a30 --- /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 0000000000000000000000000000000000000000..630ed6104811ffa73d1e96c61c24c8f1aac0e6be --- /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 0000000000000000000000000000000000000000..e4d29d66c06cc1554185b4e5d1106e80451c4650 --- /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 0000000000000000000000000000000000000000..46d16b3a305dedf3136e7a138281c915fc64b2b7 --- /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 0000000000000000000000000000000000000000..c79062c4c8ec835096ebfee47d914410c6ac2018 --- /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 0000000000000000000000000000000000000000..7db0c53020a72666d6ff564d3f0927f8d696b323 --- /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 0000000000000000000000000000000000000000..e579bbd8dcd64fa3ec2cf1dcdad32c2214c9a503 --- /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 0000000000000000000000000000000000000000..54717712bfd86904c000af7a96f9a944405fa589 --- /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 0000000000000000000000000000000000000000..33c8e6194504d5cc11ce36f17823be17ae05d908 --- /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 0000000000000000000000000000000000000000..166cffd812f8cca00f472aaa798a0800c98b6913 --- /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 0000000000000000000000000000000000000000..83804370771273c6ff564bc182f32f876feb47c8 --- /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 0000000000000000000000000000000000000000..b9eccad0e833c01fc34460062ad90b5c6d844277 --- /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 0000000000000000000000000000000000000000..286c6363e2c27a4cb2f3b6171f582edf11e0f93e --- /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 0000000000000000000000000000000000000000..52489517d862dcfc9372129b6fcff734310139c3 --- /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 0000000000000000000000000000000000000000..82faafd2b0e2fa83a096f870eb6e95e020d48c13 --- /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 0000000000000000000000000000000000000000..8097cee69b524e9277afd2a910fa0ba743fe3be5 --- /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 0000000000000000000000000000000000000000..d69a46dbd8c1f16898828b98679092e8c6a0877a --- /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 0000000000000000000000000000000000000000..bfaf1a12a99d99f21461bc19203c33c821936105 --- /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 0000000000000000000000000000000000000000..90e524a96234ac85ad0646d8f3af07c6c5e69c73 --- /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 0000000000000000000000000000000000000000..b54c5bf7867be47906910cc61c91d11280a09169 --- /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 0000000000000000000000000000000000000000..874943df9c0b4c93019e7b1c93145f300199d03f --- /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 0000000000000000000000000000000000000000..b905b9a6fd47c4d40af5522311eb65b4eed4dde2 --- /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 0000000000000000000000000000000000000000..6eb8835f82ccaa55dde0a0f621a6bcad65631773 --- /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 0000000000000000000000000000000000000000..611e08fbe584b181990a9d5970be8dd9bcfcb3d6 --- /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 0000000000000000000000000000000000000000..2e431205aa6d7f8512da485ac3f6820d26ac7394 --- /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 0000000000000000000000000000000000000000..2997228fbe211a3d465a553afdbf4646a96fd795 --- /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 0000000000000000000000000000000000000000..bf9ab3a68025884ac568a46c38a01781da3fd140 --- /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 + +#include "SoftVPX.h" + +#include +#include + +#include "vpx/vpx_decoder.h" +#include "vpx/vpx_codec.h" +#include "vpx/vp8dx.h" + +namespace android { + +template +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(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(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 &inQueue = getPortQueue(0); + List &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 0000000000000000000000000000000000000000..3e814a2f4a4cc26340feb15de99976f281dce988 --- /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 0000000000000000000000000000000000000000..43c20f01ba19e3c79e344ef5e4fe01c5758affa3 --- /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 0000000000000000000000000000000000000000..6c3f834aec34d35c6ea3f1f6e9def9f4566f2e60 --- /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 + +#include "SoftAVC.h" + +#include +#include +#include +#include + + +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 +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 &outQueue = getPortQueue(kOutputPortIndex); + List &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(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(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 &inQueue = getPortQueue(kInputPortIndex); + List &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 &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 &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 0000000000000000000000000000000000000000..879b0149d78d7cae8208520f893b3c8756e73f6b --- /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 + +#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 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 0000000000000000000000000000000000000000..fe112bc35ae0fd4194e8543a812745cab4f43220 --- /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 0000000000000000000000000000000000000000..63d56539dc134bbbaa7c95f822363aac7898f7a4 --- /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 0000000000000000000000000000000000000000..5ce70cada2b7633395e39710ef28c16bfdabe4eb --- /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 0000000000000000000000000000000000000000..9b2238bab5c47b5820fc403eee6f3bdf14f55f28 --- /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 0000000000000000000000000000000000000000..2ed86a466390016f8c431bd255030e4fec86aa71 --- /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 +#include +#include +#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 + * + * 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 + +#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 0000000000000000000000000000000000000000..abb98fcc1af794edbcae5e19425beeeab8ecbe79 --- /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 0000000000000000000000000000000000000000..4f9bc3bee8b79fd63e8958e60d35e17211d60229 --- /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 0000000000000000000000000000000000000000..d5db32ff4d3565709a6ab59599bc30f29b998e7b --- /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 0000000000000000000000000000000000000000..03f713774db4acb55c2b45523cc718a529dc1621 --- /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 0000000000000000000000000000000000000000..b5da9dce4e2471f189a8267552b124f47ec6d4a3 --- /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 0000000000000000000000000000000000000000..13e5b2b647ced1b40492fcf7b44a4d97d08014aa --- /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 0000000000000000000000000000000000000000..2df1fc88cb806eac5dde57ee5132c58dd1f59616 --- /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 0000000000000000000000000000000000000000..f629f72b25db0da7e01d1f917bfed611ae517d7a --- /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 0000000000000000000000000000000000000000..8b295a6feee35b4c7cca52b5ef61b36bb41e0c63 --- /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 + +#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 0000000000000000000000000000000000000000..8d24b650a83d186c977d28d6a603b076be556d2c --- /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 0000000000000000000000000000000000000000..1ae7005fbe7ca0893bbd8cf4de4b1322b7548a51 --- /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, '; +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 0000000000000000000000000000000000000000..0f1623f250d7f7d2e40caffbe24ce1611a9d6119 --- /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 0000000000000000000000000000000000000000..e572a896754dd46c166e31ae827eab526d62a645 --- /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 + * + * 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< 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 0000000000000000000000000000000000000000..9ef9319d3056336525f7c5d4adcd77a4bfb9e1f3 --- /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 0000000000000000000000000000000000000000..9e4679cdb317eb3ead9d7651975c739e42980d08 --- /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 0000000000000000000000000000000000000000..3241db26ce03444b79fc6351a9af03c1331cd1f3 --- /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 0000000000000000000000000000000000000000..7fa7716740b9122ae10b1c8f5f1e5ed2c8aac4c9 --- /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 0000000000000000000000000000000000000000..7f0a9b809746267c1fa34acfde0a317f6558ad99 --- /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 0000000000000000000000000000000000000000..7b3cc7289554a10744eacffc0d0af5ef39d61e8c --- /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 0000000000000000000000000000000000000000..be974d52bd5fd66d468762e147fe6c45a450e8ba --- /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 0000000000000000000000000000000000000000..2663a70a4b51c5ee4603757bf8fb2239db102522 --- /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 0000000000000000000000000000000000000000..993873c858c496033172fd975763ce97d865347d --- /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 0000000000000000000000000000000000000000..02b4b0838395d1c6879095d6d74199466150273a --- /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 0000000000000000000000000000000000000000..4340f2aaeb2abd9daeafd79bc57b556385912988 --- /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 0000000000000000000000000000000000000000..b2cd9d1c89559885ffbb6f12af790e5b284a3971 --- /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_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 0000000000000000000000000000000000000000..17fe51839d7b80dbe441bac777f8e38a210bc80e --- /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<= (3<>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 0000000000000000000000000000000000000000..ac448a0179ee87393c4ce9ee43d2dc5ad5f6615b --- /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 0000000000000000000000000000000000000000..b16f188b8c0b0b6456a358325d45856ab385cba3 --- /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 0000000000000000000000000000000000000000..82b954237deae7d2a001df74d9228eae3408691c --- /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 0000000000000000000000000000000000000000..bc0b6ecb6568b07ba13fb9b6b22947c001aa6368 --- /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 0000000000000000000000000000000000000000..66cfe5ef9266ad6d8d41885bf5c783233859033f --- /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 0000000000000000000000000000000000000000..851ff6abbdc020ff42f84ccdf10b1048270d9c92 --- /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 0000000000000000000000000000000000000000..2f48e13d52b17aca5d6ac41390dc5b0be8c33c82 --- /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 0000000000000000000000000000000000000000..6690ced7ba58df21935ea3912c818a19ce06e673 --- /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 0000000000000000000000000000000000000000..007cd0de8b60938eb531e4e8f76a6863fae126ce --- /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 0000000000000000000000000000000000000000..b1ad17c6fd3f170390ccfbf62675eab5c50a29d7 --- /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 0000000000000000000000000000000000000000..f962f70cd9ac1f8193f91ce964ebb6c7a440e596 --- /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 0000000000000000000000000000000000000000..241d18837a889ec8b3f0158a2cb0209b893aab8b --- /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 0000000000000000000000000000000000000000..ad16d9cb09070f115a145d0c5247cddac9973528 --- /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 buffer by zero + ;//----------------------------------------------------------------------- + + MOV Value, #0 ;// Initialize the zero value + MOV Value2, #0 ;// Initialize the zero value + LDRB Flag, [pSrc], #1 ;// Preload before + + 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 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 at offset + 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 0000000000000000000000000000000000000000..c2e6b6012ad1dd426638d653438ea4c6e20eb9e3 --- /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 0000000000000000000000000000000000000000..6023862268299dddff46d23bdb6b48d2714cfd78 --- /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 0000000000000000000000000000000000000000..a19f277707f8753143e1d394ef67ba83091eb4d8 --- /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 0000000000000000000000000000000000000000..99bb4ce8514001616120a893c9105c82853502c1 --- /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 0000000000000000000000000000000000000000..2b7148686a3e331c8bb4e7c2969dc6d0cd25b54b --- /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 (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]< (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]<>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 0000000000000000000000000000000000000000..00c8354cfc0dc6c3d81f3ef5a4e1c958a2bc2ed6 --- /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|>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 0000000000000000000000000000000000000000..1b840805c7b136712584e84fb13b82d2be3e38be --- /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|= 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 0000000000000000000000000000000000000000..34fedd85b6c63e6fed24c6dad5bceb5c9fb62d6c --- /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 0000000000000000000000000000000000000000..1557208158041988ad756d2f3a892f4c14df68b0 --- /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 0000000000000000000000000000000000000000..a90f4604967f1e528f48c145abb47672a619cb93 --- /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 0000000000000000000000000000000000000000..53597a85be9a410081dd8754ffc3dccae092c14b --- /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 buffer by zero + ;//----------------------------------------------------------------------- + + MOV Value, #0 ;// Initialize the zero value + MOV Value2, #0 ;// Initialize the zero value + LDRB Flag, [pSrc], #1 ;// Preload before + 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 at offset + 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 0000000000000000000000000000000000000000..73caec2ccac6ad4dbdd004322747705119cc9237 --- /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] + + ;//---------------------------------------------------------------------- + ;// + ;// 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 0000000000000000000000000000000000000000..22115d3326a79780bcafec476099d2c1dd324457 --- /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 0000000000000000000000000000000000000000..d5f865cd8771dff4abd717d04de93bf666e265e9 --- /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 0000000000000000000000000000000000000000..7801e578b93a177550da288a37da5ea8fbb7df26 --- /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 0000000000000000000000000000000000000000..9e309006d364dfe49c3c3fca2222c9b99b54ec76 --- /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 0000000000000000000000000000000000000000..ba4d05849b819ab5df51852c210217f27e011d41 --- /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 0000000000000000000000000000000000000000..25cf8db6a399ad1d160d103ea956644c4a26d5da --- /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 0000000000000000000000000000000000000000..3f92d85eed993774012d9f5b6467d41187ac7f3d --- /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 0000000000000000000000000000000000000000..ed17f9b4de9faee50f73a0bac593cb27b2992c54 --- /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 0000000000000000000000000000000000000000..b63d295166c3d7e5726f651b1a0e36a447264b8d --- /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 0000000000000000000000000000000000000000..c609a60e37bddaf0450053d52282a9a9d1df40d4 --- /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 0000000000000000000000000000000000000000..a1861da9cf947eee509a7e727471e4733eb1760f --- /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 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 High diffMVdy-=Range + STRH diffMVdx,[pDstMVCurMB,temp1] + + CMP BlkCount,Count + M_LDR pSrcMVLeftMB,ppSrcMVLeftMB + M_LDR pSrcMVUpperMB,ppSrcMVUpperMB + + BLT Loop ;// If BlkCount> 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_" macros for specified + ;// predictType. Each + ;// M_MCRECONBLOCK_ $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 0000000000000000000000000000000000000000..213444a3fb34fcf8d381a2e2a265d3c8f9b242b5 --- /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==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=>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 0000000000000000000000000000000000000000..c9591cb19fcbf95721f4be0e8f6d9b020c0745b1 --- /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 0000000000000000000000000000000000000000..6328e01463666ec718c45aa4db0cdcb004503d32 --- /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 0000000000000000000000000000000000000000..5d9368140505b5ca7168766b15bdd1b7f518b722 --- /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 0000000000000000000000000000000000000000..cc2d70a16cc3222079e930ddaac4036f29c2d566 --- /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 0000000000000000000000000000000000000000..8310f6794da8533be10f35ce1310cd8c1d34aa53 --- /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 0000000000000000000000000000000000000000..64c19586c6f0942969b87fa9dc813ecbdf38fb40 --- /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 +#include +#include +#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 + * + * 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 + +#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 0000000000000000000000000000000000000000..c738f72d8125c03c57d13e6250d1ba034f89abb5 --- /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 0000000000000000000000000000000000000000..b6990340065e77144e5bdf2654c6f93a25fef56f --- /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 0000000000000000000000000000000000000000..e0cfdaad84fef69509894c210518bbd696dbcb98 --- /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 0000000000000000000000000000000000000000..0baa0870640564ec8dffa061a2e7f11ad53235e7 --- /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 0000000000000000000000000000000000000000..51118fdb37d5cfcff9f0c917da93efafe8e8745c --- /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 0000000000000000000000000000000000000000..41b3e1e3be4ea9fada1d8b61fc8627d4fa96eee9 --- /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 0000000000000000000000000000000000000000..0956bd16bf439be19f82195d780e6618fe6e7267 --- /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 0000000000000000000000000000000000000000..7a68d14f4d01ae73e2262a843c9024815a3b4e33 --- /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 0000000000000000000000000000000000000000..8b295a6feee35b4c7cca52b5ef61b36bb41e0c63 --- /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 + +#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 0000000000000000000000000000000000000000..48703d1c0f171dfcc4aa1e1524a4d8dcd3fefb52 --- /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 0000000000000000000000000000000000000000..649e74c21f7d1df804409afb8c8342123d9ba957 --- /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, '; +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 0000000000000000000000000000000000000000..8db8eeba144134ad8ec85d3e23a8f765111b108d --- /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 0000000000000000000000000000000000000000..e572a896754dd46c166e31ae827eab526d62a645 --- /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 + * + * 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< 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 0000000000000000000000000000000000000000..9ef9319d3056336525f7c5d4adcd77a4bfb9e1f3 --- /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 0000000000000000000000000000000000000000..3f5e279c62bf646a0785240518d02555f6f9c4da --- /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 0000000000000000000000000000000000000000..09f88c3ab071555f41e52034a1c2c44060819d59 --- /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 0000000000000000000000000000000000000000..35b510b07c0b5ac8deb7960fd3ec57f0d91e26aa --- /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 0000000000000000000000000000000000000000..32a0166d7f25475fc9ba572609a051aaefc642c1 --- /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 0000000000000000000000000000000000000000..7b3cc7289554a10744eacffc0d0af5ef39d61e8c --- /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 0000000000000000000000000000000000000000..89f3040fac6e4aff283a10ea87fd10d81f127c17 --- /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 0000000000000000000000000000000000000000..296d59dd429fd1a4317efe6b979c1484ccf72544 --- /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 0000000000000000000000000000000000000000..db9e5ef6ef279ffcc568ee554246df206aa78c13 --- /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 0000000000000000000000000000000000000000..5c5b7d8166b957b2306c6fa03f4676f7ba4294db --- /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 0000000000000000000000000000000000000000..547a2d9869b87412c947b2656dca24f69d374fa8 --- /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 0000000000000000000000000000000000000000..4f0892d63c2cc9fbb3536de834273ba529cecb56 --- /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_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 0000000000000000000000000000000000000000..137495d16939bf05882a1bd9edd4fb81bbed2590 --- /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<= (3<> 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 0000000000000000000000000000000000000000..0afe4fd73af73f3d77294daf1349feac88a25917 --- /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>2)+2) + ;// aq>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 0000000000000000000000000000000000000000..10a89e959270bf0ba21809654cb840f57052c106 --- /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 0000000000000000000000000000000000000000..27616004f5f245e17e5a56addaed17108d303fdb --- /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 0000000000000000000000000000000000000000..6e912d7681c49802dbe30a0cc502840b67fa13ed --- /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 0000000000000000000000000000000000000000..d2758912ddbfa6c2ddf2795c7e1665a304c2a2c0 --- /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 0000000000000000000000000000000000000000..4e5a39d2c5dfe4a0e5c864006c1575bae1961b51 --- /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 0000000000000000000000000000000000000000..d1684cb42ac573ce7da64b2e3f63db33cece3191 --- /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 0000000000000000000000000000000000000000..7bc091f06bd3b46fed34825838702e365960b975 --- /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 0000000000000000000000000000000000000000..babe8adeab803bc77729cce88b169b9a33b52433 --- /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 0000000000000000000000000000000000000000..89c90aa87764d086990cf1f95f6df3ab26f84169 --- /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 0000000000000000000000000000000000000000..0f0ec7854364095deee457f653cc133318d35875 --- /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 0000000000000000000000000000000000000000..7e2642babd5b35a6465cd67569140d14783e4e62 --- /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 0000000000000000000000000000000000000000..ee9c339652f53fafd90fb722b96f620f62af7f5d --- /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 0000000000000000000000000000000000000000..4c52e2221976ee129f6ef1edf9faa55bcdbd3916 --- /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 buffer by zero + ;//----------------------------------------------------------------------- + + MOV Value, #0 ;// Initialize the zero value + MOV Value2, #0 ;// Initialize the zero value + LDRB Flag, [pSrc], #1 ;// Preload before + + 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 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 at offset + 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 0000000000000000000000000000000000000000..40d4d5ef7f6a3c7cc1d8e52fa6f6bb043f221f49 --- /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 0000000000000000000000000000000000000000..619365fcfd14e3cf0f4b2acf4a0c3c8a06682376 --- /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 0000000000000000000000000000000000000000..4e871bfcdd839d2733663a1ad24c9a7dbb37a9e3 --- /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 0000000000000000000000000000000000000000..b29e57663f295e36d166c14be632ed52c2e2de62 --- /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 0000000000000000000000000000000000000000..485a48854bda162a7c362c06686ae797cf8b9ccc --- /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 0000000000000000000000000000000000000000..4606197919bb4a8d94de7ac696ff1675ee6ded92 --- /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 0000000000000000000000000000000000000000..18e6c1d25e01d26172c068a7414160ed6eff7e14 --- /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 0000000000000000000000000000000000000000..0c3f4f28810e9b4e65368f83dfb93deaeb679d1b --- /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 0000000000000000000000000000000000000000..e6fbb34225800bd48ddba80bbcc005e220d73e98 --- /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 0000000000000000000000000000000000000000..3ce41bea49183c16df54e35f22995e6777e7670f --- /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 0000000000000000000000000000000000000000..942ebc6d03d5f468ccafb2cde2b65d1fb76da6cc --- /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 0000000000000000000000000000000000000000..3a607058adb936f9d477f23f95c47681b2f642be --- /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 0000000000000000000000000000000000000000..e9c0eee49b62fe4797c303bb37df568cc57b9b9a --- /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 0000000000000000000000000000000000000000..39eb8a40d100ebaed6505d039ba46f6457ace542 --- /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 0000000000000000000000000000000000000000..e3943397c9a0702149343a18f3103f8033d5db36 --- /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 buffer by zero + ;//----------------------------------------------------------------------- + + VST1 dZero,[pDst] ;// pDst[0] = pDst[1] = pDst[2] = pDst[3] = 0 + LDRB Flag, [pSrc], #1 ;// Preload before + + +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 at offset + 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 0000000000000000000000000000000000000000..25299595344e1ad73ad75e5d3da25ec21a83cf08 --- /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 + + ;//---------------------------------------------------------------------- + ;// + ;// 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 0000000000000000000000000000000000000000..aca2df4879f906b628746cd393f0007a02ebcd3a --- /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 0000000000000000000000000000000000000000..b9ee2214ba16e70ec7c5941eac2c8e6f73da0057 --- /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 0000000000000000000000000000000000000000..47f3d44287ffd0f9660c22a45934e3e2f7c9476d --- /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 0000000000000000000000000000000000000000..e68bd8ef3353c36d026400a5c32b2252342d315e --- /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 0000000000000000000000000000000000000000..44eb4286c5e6c8fce44519399fe91f3bae5f13f0 --- /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 0000000000000000000000000000000000000000..37bc69b60a00462eb0d0b7d78fea8606eb02a1bc --- /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 0000000000000000000000000000000000000000..fe92201ac57be0db0a6af5185fb78dec8ada2284 --- /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 0000000000000000000000000000000000000000..544abe82a28bdbc1a114cbd1412374b14a28c7a6 --- /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 0000000000000000000000000000000000000000..a330972f43bb73c4256d6236a8435584efab5efb --- /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 0000000000000000000000000000000000000000..991c33f9a180a53cd3dacdbdfc269ccbfd56384f --- /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 0000000000000000000000000000000000000000..40e141baef2277e40f33cfc775af0320ea643628 --- /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 0000000000000000000000000000000000000000..955846f3f778da706a4c94a62d2d02e22b053028 --- /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 0000000000000000000000000000000000000000..66520da3adf5a43cf2ba2cc461f148dcdb863e94 --- /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 0000000000000000000000000000000000000000..f5d6d1f11a43b12e5dfe9b9aa53e5c8cd7144c07 --- /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 0000000000000000000000000000000000000000..c24d717cb6b195b23db9b4a13980964dc4014713 --- /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 0000000000000000000000000000000000000000..c552f8dcfbcf9e8b4938b534211f27b84eabb9d3 --- /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 0000000000000000000000000000000000000000..ba6105934e3942a0c4c07628904c147294ca4304 --- /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 0000000000000000000000000000000000000000..be21ee724c7979ccbcc7348d475ed57e0811d092 --- /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 0000000000000000000000000000000000000000..79ba538d2be2a873d9a7fa9c74b4d88622c2250a --- /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 0000000000000000000000000000000000000000..dcdddbeaf9517eda307936da424150ccd9b85729 --- /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 0000000000000000000000000000000000000000..97558994d4c9d54b26db3b306c334b61815dc76a --- /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 0000000000000000000000000000000000000000..66cc32ea2a00ebf6cbe7c519d069c8ac29362b7a --- /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 0000000000000000000000000000000000000000..76c3d7d1ecc199fde1dda9ee286be02b64ca5e49 --- /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 0000000000000000000000000000000000000000..0d49e4bde023fc0cb9241d67a081cca88da8f217 --- /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 0000000000000000000000000000000000000000..53268f6190047fb331a11ba25b3c285158b7631a --- /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 0000000000000000000000000000000000000000..aa6d7ef839e715d542647dacf68ea29ac3c0ae0b --- /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 0000000000000000000000000000000000000000..28a89cb3f03384cf3ee82e57e9f1a029ff5bff32 --- /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 0000000000000000000000000000000000000000..a3a071539580efc16e8d0f16d9f6bc17cfe2ab1e --- /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 0000000000000000000000000000000000000000..74b55054e76a2dec4698bd05498b410fe1a78264 --- /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 0000000000000000000000000000000000000000..e95203af4027e82f3d9dfb931b250ffe001be86d --- /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 0000000000000000000000000000000000000000..95fe6d237b8b312e0ef5dad6c40e9db7a5620544 --- /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 0000000000000000000000000000000000000000..e4a7f331e6cbb1996b0680cf3ff1460693d93ea1 --- /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 0000000000000000000000000000000000000000..38af9758691e1a4e1b23ce60722389d655c0eca3 --- /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 0000000000000000000000000000000000000000..6948f8062aae6e0a200e51bdbe54a752f570ee30 --- /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 0000000000000000000000000000000000000000..44f246052ce80c0b2f2ce1082b8e6d272520f8bf --- /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 0000000000000000000000000000000000000000..21fa7153f65c26e7ef82e9dd8d19d4446e1efeae --- /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 0000000000000000000000000000000000000000..796ad6eab2b7ba691e302db71f1a2678f76b7f42 --- /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 0000000000000000000000000000000000000000..b28657c308a15f64ac399ef50f436f85eff09d08 --- /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 0000000000000000000000000000000000000000..cc16f5a230b6be2fdcbdb39c597a001fac7f148c --- /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 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 High diffMVdy-=Range + STRH diffMVdx,[pDstMVCurMB,temp1] + + CMP BlkCount,Count + M_LDR pSrcMVLeftMB,ppSrcMVLeftMB + M_LDR pSrcMVUpperMB,ppSrcMVUpperMB + + BLT Loop ;// If BlkCount31, +; * 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 0000000000000000000000000000000000000000..bd0ad1fefd4b958110d9bdb175c7f21492bcb633 --- /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 0000000000000000000000000000000000000000..e00591fc18efdb4561f07b879d1de4175bd584c2 --- /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 0000000000000000000000000000000000000000..5d9368140505b5ca7168766b15bdd1b7f518b722 --- /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 0000000000000000000000000000000000000000..7801f3ddb6da365816edb874bccb5d936cc939de --- /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 0000000000000000000000000000000000000000..8e01b1e31dc02d27bf82d459d84e6ef609713035 --- /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 0000000000000000000000000000000000000000..2ed86a466390016f8c431bd255030e4fec86aa71 --- /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 +#include +#include +#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 + * + * 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 + +#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 0000000000000000000000000000000000000000..4f9bc3bee8b79fd63e8958e60d35e17211d60229 --- /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 0000000000000000000000000000000000000000..e99a4506cff3f7411119f3b897bba519b23d5bad --- /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 0000000000000000000000000000000000000000..f629f72b25db0da7e01d1f917bfed611ae517d7a --- /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 0000000000000000000000000000000000000000..8b295a6feee35b4c7cca52b5ef61b36bb41e0c63 --- /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 + +#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 0000000000000000000000000000000000000000..f0b43e01e5413ad940e5624e9f0ae82ab8fd5ee1 --- /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, '; +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 0000000000000000000000000000000000000000..66f34ac368e2f349402a36e2a4ca859c51e52176 --- /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 0000000000000000000000000000000000000000..e572a896754dd46c166e31ae827eab526d62a645 --- /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 + * + * 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< 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 0000000000000000000000000000000000000000..9ef9319d3056336525f7c5d4adcd77a4bfb9e1f3 --- /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 0000000000000000000000000000000000000000..7fa7716740b9122ae10b1c8f5f1e5ed2c8aac4c9 --- /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 0000000000000000000000000000000000000000..7b3cc7289554a10744eacffc0d0af5ef39d61e8c --- /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 0000000000000000000000000000000000000000..1e5107786a9d97f408de2cbc6a63745710dbf817 --- /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 0000000000000000000000000000000000000000..d41ac9a050bcc96ae4b7c60525ef005213f2c583 --- /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 0000000000000000000000000000000000000000..6d1447e19be909656b3c93aab56823eddf67ca0b --- /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 0000000000000000000000000000000000000000..17b1326c68b039f7dc9a51c060abc47d0097b3f3 --- /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 0000000000000000000000000000000000000000..e559adf11e1c90c00d3189554e3c8a02004029e0 --- /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 0000000000000000000000000000000000000000..c4731aadb8064cc47ead62c216381f4bea6aaab3 --- /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 0000000000000000000000000000000000000000..48570242227b1a94f52d7afa3aaa7a812fe21d47 --- /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 0000000000000000000000000000000000000000..a4f9dde674f57c79d2912630e63c02d18f06e584 --- /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 0000000000000000000000000000000000000000..9536df75bb0ce81055bb262e1114e6cd94b60648 --- /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 0000000000000000000000000000000000000000..af045829ab87493c9ee5de3a638dc2f19578fe4a --- /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 0000000000000000000000000000000000000000..0f0cedb806f762dbf972fb1ef69892d143c92c82 --- /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 0000000000000000000000000000000000000000..1421d9940964b6e54c5b9cc9bc5026ce19145c72 --- /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 0000000000000000000000000000000000000000..8d18a8f4f750d654300872b00b7ce3c929403f4a --- /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 0000000000000000000000000000000000000000..f4e36ad6cf985ea8a27d391d076da2f12df45387 --- /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 0000000000000000000000000000000000000000..e4bedc26b9dc5dd54dae726c4e8e26d9800f425a --- /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 0000000000000000000000000000000000000000..f4fb1d9fae48a2a09fd597b0e478488561b166a0 --- /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>1) - (p1<<1))>>1; + delta = armClip(-tC0, tC0, delta); + pQ0[-2*Step] = (OMX_U8)(p1 + delta); + } + + if (ChromaFlag==0 && aq>1) - (q1<<1))>>1; + delta = armClip(-tC0, tC0, delta); + pQ0[ 1*Step] = (OMX_U8)(q1 + delta); + } + } + else /* bS==4 */ + { + if (ChromaFlag==0 && ap>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>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 0000000000000000000000000000000000000000..7616add02dfd6ffafd28835823b3d9ed024ec294 --- /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=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 0000000000000000000000000000000000000000..d9c2541e5eaaef5a4658459b4c6cb1f5a980454c --- /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 0000000000000000000000000000000000000000..93d54c3db124d7cc4a1e46356556497c680686d7 --- /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 0000000000000000000000000000000000000000..8732f4fb62b1da93e987253b6bdd6c05d4d7f5af --- /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 0000000000000000000000000000000000000000..89c00798aa072fc95d9b0a857205018a08d5b011 --- /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 0000000000000000000000000000000000000000..f7ecfc5e9684a9d3600a41896e130b2505b5d153 --- /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 0000000000000000000000000000000000000000..1507d2319b4958c4a1cf2ce8a1cbc32dec6a0e81 --- /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 0000000000000000000000000000000000000000..89978dd5c3e85a43b5efaadc116ced31230a6b72 --- /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 0000000000000000000000000000000000000000..b713073d16a1f2a07f0651c059f4041814849e18 --- /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 0000000000000000000000000000000000000000..f0b5bb0c9023d4eba46a144701bcfe27889fc8a6 --- /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 0000000000000000000000000000000000000000..a41e04bddca5c88fef5817e785acff966e6a5b08 --- /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 0000000000000000000000000000000000000000..f9f756a6f27bd58709ad5f70b0ac1b1cadbd8f0b --- /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 0000000000000000000000000000000000000000..dda49f67d404a75dc923e769b631c18853b9cd7b --- /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 0000000000000000000000000000000000000000..3c0dcbd1baafc1f848e78b87939176779faf6943 --- /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 0000000000000000000000000000000000000000..ac0d5235970642e0f413476feda8e7698e78ace5 --- /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 0000000000000000000000000000000000000000..c490e104e4129763bfd6c3618950fe3d3554df7f --- /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 0000000000000000000000000000000000000000..f7764e1485bda92a50006ebefe5dbb9b8c4d5046 --- /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 0000000000000000000000000000000000000000..513ee25167f99d44ba11363b661347dfbeef364d --- /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 0000000000000000000000000000000000000000..a07b1bb0706e6e16155a6e4d250b5d69600b30a5 --- /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 0000000000000000000000000000000000000000..1f3a64648f1dd3456265b4e23c6317d4ca03db40 --- /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 0000000000000000000000000000000000000000..830ddc7a6123e4b33fde7f02678f3f61cd87da08 --- /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 0000000000000000000000000000000000000000..7e83d1e311286a5bb4a203f52e79942f57d4d939 --- /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 0000000000000000000000000000000000000000..ed5a158dffa6e7a91817b4d806e1710dc549920c --- /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 0000000000000000000000000000000000000000..75edee215452ac0f26f210a7915786527f7bade8 --- /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 0000000000000000000000000000000000000000..10b25925d87f407e9427bd09e26ccf8ad17b4f99 --- /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 0000000000000000000000000000000000000000..30a37da1f81ea21e8bc80d5737b67de1803f4160 --- /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 0000000000000000000000000000000000000000..8733427e366a96b5d7e3ecfe24b4ec1979124f66 --- /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 0000000000000000000000000000000000000000..81c59d6eab2b9585a069da40a050ae0a06a38029 --- /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 0000000000000000000000000000000000000000..8824de2f8c86768a3f10e23dd2708119e06b7404 --- /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 0000000000000000000000000000000000000000..ef0befac2d71676b4f095cb1bc1512ee51f066c0 --- /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 0000000000000000000000000000000000000000..3560ff84cf7a4601d478a96af1ff72094ab369a1 --- /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 0000000000000000000000000000000000000000..d233735014a35a4c57b4a7db2e40de91767a97c5 --- /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 0000000000000000000000000000000000000000..92ba0319b25aa802bd256d0dafbc23acb570e8a6 --- /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 0000000000000000000000000000000000000000..a3b1200fbc371c47d82f8646d227f4aa3b2a069f --- /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 0000000000000000000000000000000000000000..3303997b953ba2f05d8337d5eefe1cd8eb9acbcc --- /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 0000000000000000000000000000000000000000..8c3a5c3126a1287f0e4cb9dbe8ec3b60ac831e56 --- /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 0000000000000000000000000000000000000000..58ecc886adbb88770a7f9090474b74a3f3bd3357 --- /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 0000000000000000000000000000000000000000..33dbf3f886782e4005347cc161cfe1399c0a4d07 --- /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 0000000000000000000000000000000000000000..d6ca7833f0a629d744a3ac9271cd7bb1ee35bdea --- /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 0000000000000000000000000000000000000000..c90cb4cdea8404e4f05f564566461e9b3e35572f --- /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 0000000000000000000000000000000000000000..3fa8212778d5249f4d26a75cd407ee19cb1974a7 --- /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 0000000000000000000000000000000000000000..c8114ee55f9e13fcfc7e28ae59a50c678a11d3c7 --- /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 0000000000000000000000000000000000000000..4b330ba3e0ce5b1d8c676dcabe94ff83e9e4cdfd --- /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 0000000000000000000000000000000000000000..c9e9c246df82736223ccd367f997e5639bb54fe8 --- /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 0000000000000000000000000000000000000000..927c454831ff6baa39b2928e3fb995447f00a222 --- /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 0000000000000000000000000000000000000000..a91ae660ef180d6ab128343e9213d0de4dc8eb4a --- /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 0000000000000000000000000000000000000000..23a5662e20957354784bf33aca9b5a84f76b9d59 --- /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 0000000000000000000000000000000000000000..9ad0e813f84da21949a207a9288d72b6f6a1b5dc --- /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 0000000000000000000000000000000000000000..16c8be1b08722f062391ffdc2d56ea13021cb68b --- /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 0000000000000000000000000000000000000000..b5544dd0caaad77581fb9b743b9967fe4d251c84 --- /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 0000000000000000000000000000000000000000..2ccf7f0597c535fb57127218f01be254a17cbfe9 --- /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 0000000000000000000000000000000000000000..3255b61beacff199a8bc0c8e4e86ee0367e1b2a5 --- /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 0000000000000000000000000000000000000000..92ecc0573d5acc977eff446ad903a717ef58dc44 --- /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 0000000000000000000000000000000000000000..c75ed8910ecdc5c9d437a6bb5b23ba5efb677886 --- /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 0000000000000000000000000000000000000000..b6a396a665cdf1541fcf8a383aaed23905375182 --- /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 0000000000000000000000000000000000000000..1b69a337b7034dd4e45d6f11476f20f36c58bdc2 --- /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 0000000000000000000000000000000000000000..77fe358bf2c3c37351afe1a2487d150350cc3a60 --- /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 0000000000000000000000000000000000000000..94e8639a909a788162e147c93fc12551ebbbfb33 --- /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 0000000000000000000000000000000000000000..3b8845e07467b9ba7603d02f694cc38db72b75ea --- /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 0000000000000000000000000000000000000000..a6f713e7a4d237ec9339f8b2a6a9c314f5ec7b31 --- /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 0000000000000000000000000000000000000000..a2572e07f291c3c4e2e6bf707771afcf1184adba --- /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 0000000000000000000000000000000000000000..cd6b56d22f796ce45444292578a07e56e8c9a51b --- /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 0000000000000000000000000000000000000000..93c950402ed77cb5742a8d07e85c747bca231a42 --- /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 0000000000000000000000000000000000000000..1712c3a47b5dfd7cb9bdf5d8d99899fee925a356 --- /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 0000000000000000000000000000000000000000..953f597c1b2a168bd35d9b16e0df3f625268cf77 --- /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 0000000000000000000000000000000000000000..cd7e9e41887dfa45384ccbca5ed6aa6528da89bd --- /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 0000000000000000000000000000000000000000..ca9efec70bb70004b169141c5e09a12612ff83c4 --- /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 0000000000000000000000000000000000000000..a9cd0089029dbfb8a312b0ebc338f6ab3a09a096 --- /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 0000000000000000000000000000000000000000..a247c690ef95717b79e2156eb160f86148810986 --- /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 0000000000000000000000000000000000000000..dcd3ce1f5f08579d61dc1dc4663f9f8edb120ca3 --- /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 0000000000000000000000000000000000000000..6996e6da612339ae50c31ef768ea6632abb2fd63 --- /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 0000000000000000000000000000000000000000..e714ef1313bd3bba6fc80c513cc1e1c9b4c2f3ce --- /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 0000000000000000000000000000000000000000..607e64cbff5787e5d8e83770f950a3fab268a296 --- /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 0000000000000000000000000000000000000000..a077ac86b80bb33fec2316af27cf2a0925fbad42 --- /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 +#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 0000000000000000000000000000000000000000..51f7babbd629dd779a69c14f69f2469e55ce254c --- /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 0000000000000000000000000000000000000000..a0b237673f0b72711be02f0c6a13ab24dbb53730 --- /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 0000000000000000000000000000000000000000..7e159b7a7e02f2c079847033eccc1abeb3a63675 --- /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 0000000000000000000000000000000000000000..88a8d0452383b1aaf18201f2008fe151ae72fdab --- /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 0000000000000000000000000000000000000000..96593d1d3e54bc372c0aabce4761bb5fea1061b6 --- /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 0000000000000000000000000000000000000000..95e00d79e119179099920b6ec554e7482c07f579 --- /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 0000000000000000000000000000000000000000..def2b6d35172bd5ff93b7987a7488a25fa3bf991 --- /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 0000000000000000000000000000000000000000..b6c73ea4abe163c9279361faf0f700bd4421a836 --- /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 0000000000000000000000000000000000000000..d047942cb5a1686f5702528cbd88da8a0ac100ec --- /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 0000000000000000000000000000000000000000..c57acd2fdfc01654da2fe330b792b9e585d8262a --- /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 0000000000000000000000000000000000000000..a0cff481c5882dc32f91b60c84fdfe24ae7733c7 --- /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 0000000000000000000000000000000000000000..1886d92f115f98b8fbd334ff6a97a11ea98d99ec --- /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 +#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 0000000000000000000000000000000000000000..7b3faeeb4973cd08ce0d1e6d2d07cf6591064454 --- /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 0000000000000000000000000000000000000000..a8e51da6d2785e58021b3a82293e1e3ddd681d54 --- /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 0000000000000000000000000000000000000000..419e71a6a339e672a31e078a4910df2fad02f180 --- /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 0000000000000000000000000000000000000000..95490505296978abaf07c3808494a659766730b9 --- /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 0000000000000000000000000000000000000000..1613f477743f282b8b8b65289947a37bca08c877 --- /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 0000000000000000000000000000000000000000..5964f732a2abb9b8bc823313bd743dd7758ea376 --- /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 0000000000000000000000000000000000000000..a10da68779e34116a4161e5e0ca293f050a67a86 --- /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 0000000000000000000000000000000000000000..6e0de5c62f0a96339b93c6fcbf916cc653d5d355 --- /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 0000000000000000000000000000000000000000..a946d7b905c448a3890acd43e5ca072e9c6e7a36 --- /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 0000000000000000000000000000000000000000..6e0c59b1053c94f9540e6ed0c17cedfe487fa609 --- /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 0000000000000000000000000000000000000000..dd444f91b6eebdb9052d509a0e57bf746edcd020 --- /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 0000000000000000000000000000000000000000..5d9368140505b5ca7168766b15bdd1b7f518b722 --- /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 0000000000000000000000000000000000000000..dcf2ef6fffab3fff75b92ff27468f5764f0729f4 --- /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 +#include +#include + +/*------------------------------------------------------------------------------ + 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 0000000000000000000000000000000000000000..aadc75f5519f5969386d76f62b67e1c56474702b --- /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 +#include +#include + +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 0000000000000000000000000000000000000000..2bb4c4de6a3673c0994a930d50fa1916413dc057 --- /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 +#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 +#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 0000000000000000000000000000000000000000..42170d3272be8440fa5170945856d4c67683a95d --- /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 +#include +#include + +#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 0000000000000000000000000000000000000000..634a4846b9d4f8e58d5da4d7e99bd9e43cdfd316 --- /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 0000000000000000000000000000000000000000..7420ad3cf6403853826e91a51df16fb22d46106c --- /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 0000000000000000000000000000000000000000..af9df1bb5db7e384ad904f5a43d5b4703ff179df --- /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 0000000000000000000000000000000000000000..93968b6721b9a17e99b20cca495e900eeb33c4c2 --- /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 0000000000000000000000000000000000000000..de243d47a60f35889649e0289c4b498fb93a7286 --- /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 0000000000000000000000000000000000000000..1c79b39e9e02f377f4dae6a621d14e3dc8fe8204 --- /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 0000000000000000000000000000000000000000..a81aed77b04a008022dbeffeb48d72de09b65203 --- /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 0000000000000000000000000000000000000000..244fc6ff7fcc19f396100cb0b35dd8ae43df2827 --- /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 0000000000000000000000000000000000000000..5266c85600e3257e80b4dbcd2dca485275ef6101 --- /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 0000000000000000000000000000000000000000..1b8d88c0858afe11357ff090a358a01d7c369e5f --- /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 0000000000000000000000000000000000000000..db1165426ed5b538d9912530c4598ec645426b2c --- /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 0000000000000000000000000000000000000000..c7bd73e1bc928ce08c995d87a3b56c1056766dcf --- /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 0000000000000000000000000000000000000000..5bfac9229a8743d5ff4d980dd44e5612898ac602 --- /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 0000000000000000000000000000000000000000..21335b835a10968517bdf531c860c445c35c9be6 --- /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 0000000000000000000000000000000000000000..38a078132ea07b5f2b6e568e8c92bf41ba50d697 --- /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 0000000000000000000000000000000000000000..f39f5c497367c694aa5d9fa4d4c92a820dec8b0e --- /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 0000000000000000000000000000000000000000..c8a940e0f3847668c487c496d7d21272a1557689 --- /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 0000000000000000000000000000000000000000..05253d0d4ae184b41bbf8999ee10e7c43dc75221 --- /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 0000000000000000000000000000000000000000..6955b9a463cd9066a252bf55a50ce04e28598d6d --- /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 0000000000000000000000000000000000000000..b3f3191a114a219d44a64125a14765981c7ba7d8 --- /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 0000000000000000000000000000000000000000..495d560181299376e17c80bb5d70ec888bc7c3cb --- /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 0000000000000000000000000000000000000000..db77f8c6723fc200b8b814dde8e1c6318a593f98 --- /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 0000000000000000000000000000000000000000..36aec76e9a679bf82beac3e1ae25fef3a606844c --- /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 0000000000000000000000000000000000000000..91d78bd466c2cacd4ad1b4c39e818eec1133f1c5 --- /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 0000000000000000000000000000000000000000..80353d392f7fc15620960d88c8073b8e8ccff3e7 --- /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 0000000000000000000000000000000000000000..2baba5add14a533874f2b1e2bc25fd7b6d409fd0 --- /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 0000000000000000000000000000000000000000..493fb9e472173b9ac37662c9de0ab43dc2bb60d9 --- /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 0000000000000000000000000000000000000000..3134670c8c628936eb07c263915765b5001bfdc1 --- /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 0000000000000000000000000000000000000000..99b74a0a7d0a4bb94441d81ef9b544733f3a4951 --- /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 0000000000000000000000000000000000000000..f8c1f76da98ed6ce5f2e04752fec939fe039e013 --- /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 0000000000000000000000000000000000000000..2571ddaf9c9db3b90fce334221d2fe47cf07b413 --- /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 0000000000000000000000000000000000000000..a816871b0f23ffbd354fd23b08d0c1addaa6795a --- /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 0000000000000000000000000000000000000000..83365231c00c05ab735464479a09f4e38d573fd4 --- /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 0000000000000000000000000000000000000000..9517d0ae3eb075257a1182d63aedd44cce3428d6 --- /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 0000000000000000000000000000000000000000..0e25084dd8407de73dd8bf6ffab63a5b1fc419cd --- /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 0000000000000000000000000000000000000000..7b928709be14e9c131de1a75d37cfdc8277eb1ef --- /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 0000000000000000000000000000000000000000..ed7c18ca8dbdc394d2349143984f9090d48ad14e --- /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 0000000000000000000000000000000000000000..2a81c4a2c26bf8e62998b0af052a73234daadb34 --- /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 0000000000000000000000000000000000000000..94dee259eae4de330d984efb382b27af8bad95bc --- /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 0000000000000000000000000000000000000000..15eabfb63e8314d975c71810265b27d4be42373f --- /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 0000000000000000000000000000000000000000..4652bd56347d7f5f39bd1535158b73304cfb90b0 --- /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 0000000000000000000000000000000000000000..2b3e7f0018c6bf819d67814ab89b9f1ef1670481 --- /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 0000000000000000000000000000000000000000..32bc3403741ca0e15e7b010e2d0d06c6cb5451dd --- /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 0000000000000000000000000000000000000000..e44c43a7cc58ad319ee79e4d5e5f162aa2bd2074 --- /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 0000000000000000000000000000000000000000..38957bf73c6c4d365d15798fc7403b71686caa0b --- /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 0000000000000000000000000000000000000000..ce5eeff76e7a05c811c7d9359f3c60b7c1a9a9a2 --- /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 0000000000000000000000000000000000000000..fce0ad19ef06d4d1a9ac3298160656a962eb14e1 --- /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 0000000000000000000000000000000000000000..fb23352d2b2abb47deac63850d7ff11aa4848437 --- /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 0000000000000000000000000000000000000000..19741eb3161fa56da0440afe35a73391a59d54ff --- /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 0000000000000000000000000000000000000000..e04dea4b4ea957b220db681040ed09f13453b4cb --- /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 0000000000000000000000000000000000000000..63286380221752110a1b0c1445869b133ad34124 --- /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 0000000000000000000000000000000000000000..c94877623ddfe8addd4680b6f245d75178f1f083 --- /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 0000000000000000000000000000000000000000..5a1a140fbfa32d3e0a1f5c0bbfd577526484be1d --- /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 0000000000000000000000000000000000000000..0756c4734fb61c54f2eee71bedb4940d3f9843d9 --- /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 0000000000000000000000000000000000000000..efe543a63797cc3e363332de693b09961dabdeea --- /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 0000000000000000000000000000000000000000..751051a14ffd8a3a27beea1c7e311e38b7c971e5 --- /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 0000000000000000000000000000000000000000..e18df94976709fd6de3978421f4a79e529183b8a --- /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 0000000000000000000000000000000000000000..c288d4b7dd8702d1462633eb930cc02fe6958a52 --- /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 0000000000000000000000000000000000000000..f23d49ec7a5530c8a668a4dd70ea42d27fc07814 --- /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 0000000000000000000000000000000000000000..7cbb534155cc2b5cd8b7be8dcf9be49af211fe1d --- /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 0000000000000000000000000000000000000000..4bcb6f2cee0943070a54ec12d40f0fd8c42e4170 --- /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 0000000000000000000000000000000000000000..a7c6f64df4a6586dd74d6b5b4794b86dbb5c33ea --- /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<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 0000000000000000000000000000000000000000..198898a87b5aa5f0b2645f924557dbf147fc9e85 --- /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 0000000000000000000000000000000000000000..3234754b30536a0f5658b2a258f16d7ed6f07a07 --- /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 0000000000000000000000000000000000000000..ba3b2da7726e3d0221079eee139e96f7c74306b9 --- /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 0000000000000000000000000000000000000000..20d10836a6d298ed3e6c72068c47ebd062dd8739 --- /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 0000000000000000000000000000000000000000..4404b6683415b53bd47121343ccc0450d1ee9206 --- /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 0000000000000000000000000000000000000000..4eb6dd09013f60fc37803a5a708eb71aa3ec63f9 --- /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 0000000000000000000000000000000000000000..4f41a23e46636d7b2dd357b0943f6637896e0ef8 --- /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 0000000000000000000000000000000000000000..53b2fd8e53df029f09fa9cfab2ac017881ca9ac6 --- /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 0000000000000000000000000000000000000000..cb3adda7ee456a5f6b8738b431e0da3a9b6310c0 --- /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 +#endif + +#include "H264SwDecApi.h" + +#if defined(_RANGE_CHECK) || defined(_DEBUG_PRINT) || defined(_ERROR_PRINT) +#include +#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 0000000000000000000000000000000000000000..060f35e3102ac65745e36dae8ed0bb85f8882f59 --- /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 0000000000000000000000000000000000000000..4c16773ca7d91b2576104e4cda165c10af00c79f --- /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 0000000000000000000000000000000000000000..4a9335ad71440e3f746244529368676a48b4e252 --- /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 0000000000000000000000000000000000000000..05d52a45a996a91a0b9300a028913d073d182163 --- /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 0000000000000000000000000000000000000000..2e431205aa6d7f8512da485ac3f6820d26ac7394 --- /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 0000000000000000000000000000000000000000..fca70b7b78d67f6f14543066b781da2a55f02811 --- /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 0000000000000000000000000000000000000000..ac88107544b6d36a70e1e78d31e9327e51c9b3b5 --- /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 + +#include "SoftVorbis.h" + +#include +#include + +extern "C" { + #include + + 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 +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(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("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 &inQueue = getPortQueue(0); + List &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 0000000000000000000000000000000000000000..e252f5553f5427247e2a6e62f7aa690e30867352 --- /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 0000000000000000000000000000000000000000..59a64ba25aafae247c246bc1dc0f627c509c8edd --- /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 0000000000000000000000000000000000000000..597167f91e2cfd454615c6182905d3023226ecc1 --- /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 + +#include +#include +#include + +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(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 0000000000000000000000000000000000000000..059d6b9866beda2b5a21a5a367d9cb7026abcb53 --- /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 + +#include "../include/SoftwareRenderer.h" + +#include +#include +#include +#include +#include + +namespace android { + +SoftwareRenderer::SoftwareRenderer( + const sp &nativeWindow, const sp &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 0000000000000000000000000000000000000000..b7b9e9f950fc0a5d2dab5956f9b4c3be74ab7586 --- /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 + +#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()); + } +} + +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 &entry = mAtoms.editItemAt(index); + List::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 0000000000000000000000000000000000000000..5499c32bbaba3cc2848a9aed6d61fafc1e49604b --- /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 + +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 0000000000000000000000000000000000000000..6173db4b012fa45b4eab534be64a1cf9d5229368 --- /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 msg) { + mFarewell = msg; +} + +sp 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 0000000000000000000000000000000000000000..bd5f7e940a2c2427e5f2add149e84431ad5a014a --- /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 + +#include + +#include + +namespace android { + +sp 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 0000000000000000000000000000000000000000..40c5a3c0500ddfc70a7703a3611317e4ca0ab439 --- /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 + +#include +#include +#include + +namespace android { + +AState::AState(const sp &parentState) + : mParentState(parentState) { +} + +AState::~AState() { +} + +sp AState::parentState() { + return mParentState; +} + +void AState::stateEntered() { +} + +void AState::stateExited() { +} + +//////////////////////////////////////////////////////////////////////////////// + +AHierarchicalStateMachine::AHierarchicalStateMachine() { +} + +AHierarchicalStateMachine::~AHierarchicalStateMachine() { +} + +void AHierarchicalStateMachine::onMessageReceived(const sp &msg) { + sp save = mState; + + sp 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 &state) { + if (state == mState) { + // Quick exit for the easy case. + return; + } + + Vector > A; + sp cur = mState; + for (;;) { + A.push(cur); + if (cur == NULL) { + break; + } + cur = cur->parentState(); + } + + Vector > 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 0000000000000000000000000000000000000000..a5b316d7899f96071ad72924719e74a7cf47f2b3 --- /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 + +#include + +#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 &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 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 &msg, int64_t delayUs) { + Mutex::Autolock autoLock(mLock); + + int64_t whenUs; + if (delayUs > 0) { + whenUs = GetNowUs() + delayUs; + } else { + whenUs = GetNowUs(); + } + + List::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 0000000000000000000000000000000000000000..dff931d496e702fee47e4d315ee46d568ac1fab3 --- /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 + +#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 looper, const sp &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 handler = info.mHandler.promote(); + + if (handler != NULL) { + handler->setID(0); + } + + mHandlers.removeItemsAt(index); +} + +status_t ALooperRoster::postMessage( + const sp &msg, int64_t delayUs) { + Mutex::Autolock autoLock(mLock); + return postMessage_l(msg, delayUs); +} + +status_t ALooperRoster::postMessage_l( + const sp &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 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 &msg) { + sp 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 ALooperRoster::findLooper(ALooper::handler_id handlerID) { + Mutex::Autolock autoLock(mLock); + + ssize_t index = mHandlers.indexOfKey(handlerID); + + if (index < 0) { + return NULL; + } + + sp looper = mHandlers.valueAt(index).mLooper.promote(); + + if (looper == NULL) { + mHandlers.removeItemsAt(index); + return NULL; + } + + return looper; +} + +status_t ALooperRoster::postAndAwaitResponse( + const sp &msg, sp *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 &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 0000000000000000000000000000000000000000..8b01ac65236a9ade1607cce8d0bddaef5655b527 --- /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 + +#include "AAtomizer.h" +#include "ABuffer.h" +#include "ADebug.h" +#include "ALooperRoster.h" +#include "AString.h" + +#include + +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 &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 &obj) { + setObjectInternal(name, obj, kTypeObject); +} + +void AMessage::setBuffer(const char *name, const sp &buffer) { + setObjectInternal(name, sp(buffer), kTypeBuffer); +} + +void AMessage::setMessage(const char *name, const sp &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 *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 *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 *obj) const { + const Item *item = findItem(name, kTypeMessage); + if (item) { + *obj = static_cast(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 *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(tmp); + + return true; +} + +sp AMessage::dup() const { + sp 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 copy = + static_cast(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( + 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::FromParcel(const Parcel &parcel) { + int32_t what = parcel.readInt32(); + sp msg = new AMessage(what); + + msg->mNumItems = static_cast(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(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(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 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(mWhat)); + parcel->writeInt32(static_cast(mNumItems)); + + for (size_t i = 0; i < mNumItems; ++i) { + const Item &item = mItems[i]; + + parcel->writeCString(item.mName); + parcel->writeInt32(static_cast(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(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(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 0000000000000000000000000000000000000000..dee786d95983a4022da334c72d761fe1b59ca317 --- /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 +#include +#include +#include +#include + +#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 0000000000000000000000000000000000000000..d5025a13ed8672cca300e4d1cfce6a133a8a3a20 --- /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 0000000000000000000000000000000000000000..d5fb4e014468296833da5a0ea4621c5373f7753d --- /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 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 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 0000000000000000000000000000000000000000..16c1ca517c3197c03f22cde0633001e71e819ca3 --- /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 + +#include "hexdump.h" + +#include "ADebug.h" +#include "AString.h" + +#include +#include +#include + +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 0000000000000000000000000000000000000000..90cb448574dd92431125db59c3bba86d80e63f0a --- /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 0000000000000000000000000000000000000000..7560642a72f56cc924d6c1b191da4779cbdeeae2 --- /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 + +#include "LiveDataSource.h" + +#include +#include + +#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 >::iterator it = mBufferQueue.begin(); + it != mBufferQueue.end(); ++it) { + sp 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 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 &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 0000000000000000000000000000000000000000..b7be6371a64549bf3540bb78f3257a22a8c6108c --- /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 +#include +#include +#include + +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 &buffer); + void queueEOS(status_t finalResult); + void reset(); + + size_t countQueuedBuffers(); + +protected: + virtual ~LiveDataSource(); + +private: + Mutex mLock; + Condition mCondition; + + off64_t mOffset; + List > 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 0000000000000000000000000000000000000000..0cddd2e7e4eebe95bc33dba2deaf259131f2a7a0 --- /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 + +#include "include/LiveSession.h" + +#include "LiveDataSource.h" + +#include "include/M3UParser.h" +#include "include/HTTPBase.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 LiveSession::getDataSource() { + return mDataSource; +} + +void LiveSession::connect( + const char *url, const KeyedVector *headers) { + sp msg = new AMessage(kWhatConnect, id()); + msg->setString("url", url); + + if (headers != NULL) { + msg->setPointer( + "headers", + new KeyedVector(*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 msg = new AMessage(kWhatSeek, id()); + msg->setInt64("timeUs", timeUs); + msg->post(); + + while (!mSeekDone) { + mCondition.wait(mLock); + } +} + +void LiveSession::onMessageReceived(const sp &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 &msg) { + AString url; + CHECK(msg->findString("url", &url)); + + KeyedVector *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 "); + } + + mMasterURL = url; + + bool dummy; + sp 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 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 *out, + int64_t range_offset, int64_t range_length) { + *out = NULL; + + sp 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 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 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 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 LiveSession::fetchPlaylist(const char *url, bool *unchanged) { + *unchanged = false; + + sp 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 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 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 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 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 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 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 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 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 &buffer) { + sp 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 key; + if (index >= 0) { + key = mAESKeyForURI.valueAt(index); + } else { + key = new ABuffer(16); + + sp 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 msg = new AMessage(kWhatMonitorQueue, id()); + msg->setInt32("generation", ++mMonitorQueueGeneration); + msg->post(delayUs); +} + +void LiveSession::onSeek(const sp &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 0000000000000000000000000000000000000000..7d3cf05433765277dbbb368cc58c4f6c739f8355 --- /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 + +#include "include/M3UParser.h" + +#include +#include +#include + +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 M3UParser::meta() { + return mMeta; +} + +size_t M3UParser::size() { + return mItems.size(); +} + +bool M3UParser::itemAt(size_t index, AString *uri, sp *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 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 *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 *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 *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 *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 0000000000000000000000000000000000000000..ff35d4a775218bd7cda80c1abb6299372a7aa2bc --- /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 0000000000000000000000000000000000000000..ca140545e0c58db967f677b4bc65576e1d9a1956 --- /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 + +#include "../include/ID3.h" + +#include +#include +#include +#include +#include + +namespace android { + +static const size_t kMaxMetadataSize = 3 * 1024 * 1024; + +ID3::ID3(const sp &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 &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 &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 0000000000000000000000000000000000000000..bc4572cc214d2a30f4e877118bb532de7bad1545 --- /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 + +#include +#include + +#include +#include +#include + +#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 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 0000000000000000000000000000000000000000..3d5fc6072d0101eafd7796488ad86e0e47100ff8 --- /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 +#include + +struct VO_AUDIO_CODECAPI; +struct VO_MEM_OPERATOR; + +namespace android { + +struct MediaBufferGroup; + +class AACEncoder: public MediaSource { + public: + AACEncoder(const sp &source, const sp &meta); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + virtual sp getFormat(); + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + + + protected: + virtual ~AACEncoder(); + + private: + sp mSource; + sp 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 0000000000000000000000000000000000000000..e98ca82c9d248acb223375b0feeb960b5031e9f6 --- /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 + +#include + +namespace android { + +struct AMessage; +class String8; + +class AACExtractor : public MediaExtractor { +public: + AACExtractor(const sp &source, const sp &meta); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~AACExtractor(); + +private: + sp mDataSource; + sp mMeta; + status_t mInitCheck; + + Vector mOffsetVector; + int64_t mFrameDurationUs; + + AACExtractor(const AACExtractor &); + AACExtractor &operator=(const AACExtractor &); +}; + +bool SniffAAC( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..4a1c827453e1f824e0cc18669d12e5e33a323a3f --- /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 +#include + +namespace android { + +struct AMessage; +class String8; +#define OFFSET_TABLE_LEN 300 + +class AMRExtractor : public MediaExtractor { +public: + AMRExtractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~AMRExtractor(); + +private: + sp mDataSource; + sp 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 &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..83e1f970e2a263af395706a2e185794486807dfc --- /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 +#include +#include + +struct tagAVCHandle; +struct tagAVCEncParam; + +namespace android { + +struct MediaBuffer; +struct MediaBufferGroup; + +struct AVCEncoder : public MediaSource, + public MediaBufferObserver { + AVCEncoder(const sp &source, + const sp& meta); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + + virtual sp 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 mSource; + sp mFormat; + sp 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 mOutputBuffers; + + + status_t initCheck(const sp& 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 0000000000000000000000000000000000000000..ff5dcb53ee0ce5eaa51dd88a2f96ced5ec4baf26 --- /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 +#include +#include +#include + +namespace android { + +struct AVIExtractor : public MediaExtractor { + AVIExtractor(const sp &dataSource); + + virtual size_t countTracks(); + + virtual sp getTrack(size_t index); + + virtual sp getTrackMetaData( + size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~AVIExtractor(); + +private: + struct AVISource; + struct MP3Splitter; + + struct SampleInfo { + uint32_t mOffset; + bool mIsKey; + }; + + struct Track { + sp mMeta; + Vector 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 mDataSource; + status_t mInitCheck; + Vector 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 &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..06e946887f18df2eb16d7be160d49bc57853acef --- /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 +#include +#include +#include +#include +#include + +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 &listener); + void setUID(uid_t uid); + + status_t setDataSource( + const char *uri, + const KeyedVector *headers = NULL); + + status_t setDataSource(int fd, int64_t offset, int64_t length); + + status_t setDataSource(const sp &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 &surfaceTexture); + void setAudioSink(const sp &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 &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 mListener; + bool mUIDValid; + uid_t mUID; + + sp mNativeWindow; + sp mAudioSink; + + SystemTimeSource mSystemTimeSource; + TimeSource *mTimeSource; + + String8 mUri; + KeyedVector mUriHeaders; + + sp mFileSource; + + sp mVideoTrack; + sp mVideoSource; + sp mVideoRenderer; + bool mVideoRendererIsPreview; + + sp mAudioTrack; + sp 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 mVideoEvent; + bool mVideoEventPending; + sp mStreamDoneEvent; + bool mStreamDoneEventPending; + sp mBufferingEvent; + bool mBufferingEventPending; + sp mCheckAudioStatusEvent; + bool mAudioStatusEventPending; + sp mVideoLagEvent; + bool mVideoLagEventPending; + + sp 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 mConnectingDataSource; + sp mCachedSource; + + DrmManagerClient *mDrmManagerClient; + sp mDecryptHandle; + + int64_t mLastVideoTimeUs; + TimedTextDriver *mTextDriver; + mutable Mutex mTimedTextLock; + + sp mWVMExtractor; + + status_t setDataSource_l( + const char *uri, + const KeyedVector *headers = NULL); + + status_t setDataSource_l(const sp &dataSource); + status_t setDataSource_l(const sp &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 source); + status_t initAudioDecoder(); + + void setVideoSource(sp source); + status_t initVideoDecoder(uint32_t flags = 0); + + void addTextSource(const sp& 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 &native); + + bool isStreamingHTTP() const; + void sendCacheStats(); + void checkDrmStatus(const sp& 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 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 0000000000000000000000000000000000000000..82e08fd1ba1e324e1cee9340b8a2c814e4f49afd --- /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 +#include + +#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 *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 DrmInitialization(const char *mime); + + virtual void getDrmInfo(sp &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 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 mDecryptHandle; + DrmManagerClient *mDrmManagerClient; + + void disconnect_l(); + + status_t connect_l( + const char *uri, + const KeyedVector *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 0000000000000000000000000000000000000000..b4e4afb13afd646b33621cfc17ee314db29bf080 --- /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 +#include + +namespace android { + +struct AMessage; +class DataSource; +class SampleTable; +class String8; +class DecryptHandle; + +class DRMExtractor : public MediaExtractor { +public: + DRMExtractor(const sp &source, const char *mime); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + virtual sp getMetaData(); + +protected: + virtual ~DRMExtractor(); + +private: + sp mDataSource; + + sp mOriginalExtractor; + sp mDecryptHandle; + DrmManagerClient* mDrmManagerClient; + + DRMExtractor(const DRMExtractor &); + DRMExtractor &operator=(const DRMExtractor &); +}; + +bool SniffDRM( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..d223c0640d78ced099aaa45becd2987a34c9afdc --- /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 + +#include +#include +#include + +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 0000000000000000000000000000000000000000..3a799516ec34a65ea1f81d85c5ae7a000702e610 --- /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 + +#include + +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 0000000000000000000000000000000000000000..ded91c27e54762e7f1166cf8d66373c5af9cbda5 --- /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 +#include +#include + +namespace android { + +class FLACParser; + +class FLACExtractor : public MediaExtractor { + +public: + // Extractor assumes ownership of source + FLACExtractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~FLACExtractor(); + +private: + sp mDataSource; + sp mParser; + status_t mInitCheck; + sp mFileMetadata; + + // There is only one track + sp mTrackMetadata; + + status_t init(); + + FLACExtractor(const FLACExtractor &); + FLACExtractor &operator=(const FLACExtractor &); + +}; + +bool SniffFLAC(const sp &source, String8 *mimeType, + float *confidence, sp *); + +} // 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 0000000000000000000000000000000000000000..b8e10f7542fae1b20f335eabe8e8888d1bb257cb --- /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 +#include +#include +#include + +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 *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 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 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 0000000000000000000000000000000000000000..87140084e6e45666f6aa756b05f9de1943831d01 --- /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 + +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 &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 &source); + bool parseV2(const sp &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 0000000000000000000000000000000000000000..3a11612f2628c1652c09316e437ee1f63093aab3 --- /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 + +#include + +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 getDataSource(); + + void connect( + const char *url, + const KeyedVector *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 &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 mDataSource; + + sp mHTTPDataSource; + + AString mMasterURL; + KeyedVector mExtraHeaders; + + Vector mBandwidthItems; + + KeyedVector > mAESKeyForURI; + + ssize_t mPrevBandwidthIndex; + int64_t mLastPlaylistFetchTimeUs; + sp 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 &msg); + void onDisconnect(); + void onDownloadNext(); + void onMonitorQueue(); + void onSeek(const sp &msg); + + status_t fetchFile( + const char *url, sp *out, + int64_t range_offset = 0, int64_t range_length = -1); + + sp fetchPlaylist(const char *url, bool *unchanged); + size_t getBandwidthIndex(); + + status_t decryptBuffer( + size_t playlistIndex, const sp &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 0000000000000000000000000000000000000000..e30d6fdb8f81f311769a1b690d52e8341299115c --- /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 +#include +#include +#include + +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 meta(); + + size_t size(); + bool itemAt(size_t index, AString *uri, sp *meta = NULL); + +protected: + virtual ~M3UParser(); + +private: + struct Item { + AString mURI; + sp mMeta; + }; + + status_t mInitCheck; + + AString mBaseURI; + bool mIsExtM3U; + bool mIsVariantPlaylist; + bool mIsComplete; + + sp mMeta; + Vector mItems; + + status_t parse(const void *data, size_t size); + + static status_t parseMetaData( + const AString &line, sp *meta, const char *key); + + static status_t parseMetaDataDuration( + const AString &line, sp *meta, const char *key); + + static status_t parseStreamInf( + const AString &line, sp *meta); + + static status_t parseCipherInfo( + const AString &line, sp *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 0000000000000000000000000000000000000000..dbe9fd0fc3fce34c7f64b60f3cb5b5953f4b68a0 --- /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 +#include + +struct tagvideoEncControls; +struct tagvideoEncOptions; + +namespace android { + +struct MediaBuffer; +struct MediaBufferGroup; + +struct M4vH263Encoder : public MediaSource, + public MediaBufferObserver { + M4vH263Encoder(const sp &source, + const sp& meta); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + + virtual void signalBufferReturned(MediaBuffer *buffer); + +protected: + virtual ~M4vH263Encoder(); + +private: + sp mSource; + sp mFormat; + sp 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& 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 0000000000000000000000000000000000000000..c83d9e80b39742a692a91f8004908887313a827b --- /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 +#include + +namespace android { + +struct AMessage; +class DataSource; +struct MP3Seeker; +class String8; + +class MP3Extractor : public MediaExtractor { +public: + // Extractor assumes ownership of "source". + MP3Extractor(const sp &source, const sp &meta); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + +private: + status_t mInitCheck; + + sp mDataSource; + off64_t mFirstFramePos; + sp mMeta; + uint32_t mFixedHeader; + sp mSeeker; + + MP3Extractor(const MP3Extractor &); + MP3Extractor &operator=(const MP3Extractor &); +}; + +bool SniffMP3( + const sp &source, String8 *mimeType, float *confidence, + sp *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 0000000000000000000000000000000000000000..599542e27bb8c064f8784c2cd08eac548f075ede --- /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 +#include + +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 0000000000000000000000000000000000000000..fb76564c608ce0f59e1756ab7a68a588c0b9b366 --- /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 +#include +#include +#include + +namespace android { + +struct ABuffer; +struct AMessage; +struct Track; +struct String8; + +struct MPEG2PSExtractor : public MediaExtractor { + MPEG2PSExtractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + + virtual uint32_t flags() const; + +protected: + virtual ~MPEG2PSExtractor(); + +private: + struct Track; + struct WrappedTrack; + + mutable Mutex mLock; + sp mDataSource; + + off64_t mOffset; + status_t mFinalResult; + sp mBuffer; + KeyedVector > mTracks; + bool mScanning; + + bool mProgramStreamMapValid; + KeyedVector mStreamTypeByESID; + + status_t feedMore(); + + status_t dequeueChunk(); + ssize_t dequeuePack(); + ssize_t dequeueSystemHeader(); + ssize_t dequeuePES(); + + DISALLOW_EVIL_CONSTRUCTORS(MPEG2PSExtractor); +}; + +bool SniffMPEG2PS( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..fe74a423e645d9e688a8db2e25c3d9ab33e08cdb --- /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 +#include +#include +#include + +namespace android { + +struct AMessage; +struct AnotherPacketSource; +struct ATSParser; +struct DataSource; +struct MPEG2TSSource; +struct String8; +struct LiveSession; + +struct MPEG2TSExtractor : public MediaExtractor { + MPEG2TSExtractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + + virtual uint32_t flags() const; + + void setLiveSession(const sp &liveSession); + void seekTo(int64_t seekTimeUs); + +private: + friend struct MPEG2TSSource; + + mutable Mutex mLock; + + sp mDataSource; + sp mLiveSession; + + sp mParser; + + Vector > mSourceImpls; + + off64_t mOffset; + + void init(); + status_t feedMore(); + + DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSExtractor); +}; + +bool SniffMPEG2TS( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..5c549e0879e16619d961aa8985fc1dd69fb8532a --- /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 +#include +#include + +namespace android { + +struct AMessage; +class DataSource; +class SampleTable; +class String8; + +class MPEG4Extractor : public MediaExtractor { +public: + // Extractor assumes ownership of "source". + MPEG4Extractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + + // for DRM + virtual char* getDrmTrackInfo(size_t trackID, int *len); + +protected: + virtual ~MPEG4Extractor(); + +private: + struct Track { + Track *next; + sp meta; + uint32_t timescale; + sp sampleTable; + bool includes_expensive_metadata; + bool skipTrack; + }; + + sp mDataSource; + status_t mInitCheck; + bool mHasVideo; + + Track *mFirstTrack, *mLastTrack; + + sp mFileMetaData; + + Vector 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 &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..c27a29b7662476a69ea9cadbc0419663172d9525 --- /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 +#include +#include + +namespace android { + +struct ALooper; +struct PageCache; + +struct NuCachedSource2 : public DataSource { + NuCachedSource2( + const sp &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 DrmInitialization(const char* mime); + virtual void getDrmInfo(sp &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 *headers, + String8 *cacheConfig, + bool *disconnectAtHighwatermark); + +protected: + virtual ~NuCachedSource2(); + +private: + friend struct AHandlerReflector; + + 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 mSource; + sp > mReflector; + sp mLooper; + + Mutex mSerializer; + Mutex mLock; + Condition mCondition; + + PageCache *mCache; + off64_t mCacheOffset; + status_t mFinalStatus; + off64_t mLastAccessPos; + sp 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 &msg); + void onFetch(); + void onRead(const sp &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 0000000000000000000000000000000000000000..2c87b34e42a833674661c05ef10c362bb1175426 --- /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 +#include +#include + +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 *list); + + virtual status_t allocateNode( + const char *name, const sp &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 ¶ms, + buffer_id *buffer); + + virtual status_t useGraphicBuffer( + node_id node, OMX_U32 port_index, + const sp &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 ¶ms, + 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 &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, OMXNodeInstance *> mLiveNodes; + KeyedVector mNodeIDToInstance; + KeyedVector > mDispatchers; + + node_id makeNodeID(OMXNodeInstance *instance); + OMXNodeInstance *findInstance(node_id node); + sp 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 0000000000000000000000000000000000000000..47ca5797f3d35162c8b08b50d4dc32861426e6d2 --- /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 +#include + +namespace android { + +class IOMXObserver; +struct OMXMaster; + +struct OMXNodeInstance { + OMXNodeInstance( + OMX *owner, const sp &observer); + + void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle); + + OMX *owner(); + sp 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 ¶ms, + OMX::buffer_id *buffer); + + status_t useGraphicBuffer( + OMX_U32 portIndex, const sp &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 ¶ms, + 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 mObserver; + bool mDying; + + struct ActiveBuffer { + OMX_U32 mPortIndex; + OMX::buffer_id mID; + }; + Vector 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, + 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 0000000000000000000000000000000000000000..e97c8cdef486413668cccf2e38c16e5f1d281728 --- /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 +#include + +namespace android { + +struct AMessage; +class DataSource; +class String8; + +struct MyVorbisExtractor; +struct OggSource; + +struct OggExtractor : public MediaExtractor { + OggExtractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~OggExtractor(); + +private: + friend struct OggSource; + + sp mDataSource; + status_t mInitCheck; + + MyVorbisExtractor *mImpl; + + OggExtractor(const OggExtractor &); + OggExtractor &operator=(const OggExtractor &); +}; + +bool SniffOgg( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +void parseVorbisComment( + const sp &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 0000000000000000000000000000000000000000..b5a043c626ed197bbadcf1c077a0e58866c62a73 --- /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 + +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 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 0000000000000000000000000000000000000000..847dff70bfa4ff067fbfdbf899f1ac91a9870500 --- /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 +#include + +#include +#include +#include + +namespace android { + +class DataSource; +struct SampleIterator; + +class SampleTable : public RefBase { +public: + SampleTable(const sp &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 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 0000000000000000000000000000000000000000..50cd275d0e7b4e804dd75edd4766d94ba18d959b --- /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 +#include +#include +#include + +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 &msg); + +protected: + struct BufferInfo { + OMX_BUFFERHEADERTYPE *mHeader; + bool mOwnedByUs; + }; + + struct PortInfo { + OMX_PARAM_PORTDEFINITIONTYPE mDef; + Vector mBuffers; + List 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 &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 mLooper; + sp > mHandler; + + OMX_STATETYPE mState; + OMX_STATETYPE mTargetState; + + Vector 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 0000000000000000000000000000000000000000..a808611c2ec69d9a1f0747edd8231d2d059c3b20 --- /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 +#include +#include + +#include + +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 0000000000000000000000000000000000000000..7ab004239069730f30a48a110c781ef6c4b805c8 --- /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 +#include +#include + +namespace android { + +struct MetaData; + +class SoftwareRenderer { +public: + SoftwareRenderer( + const sp &nativeWindow, const sp &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 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 0000000000000000000000000000000000000000..b02ed0e5bf9389d8c2705f21dd47b9ac08729cb3 --- /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 + +#include +#include + +namespace android { + +struct DataSource; +class MediaExtractor; + +struct StagefrightMetadataRetriever : public MediaMetadataRetrieverInterface { + StagefrightMetadataRetriever(); + virtual ~StagefrightMetadataRetriever(); + + virtual status_t setDataSource( + const char *url, + const KeyedVector *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 mSource; + sp mExtractor; + + bool mParsedMetaData; + KeyedVector 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 0000000000000000000000000000000000000000..7fe7c0676c558106c485d2efd370cd3448a1ec7d --- /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 +#include + +namespace android { + +struct ThrottledSource : public DataSource { + ThrottledSource( + const sp &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 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 0000000000000000000000000000000000000000..11f844c6d3f2915006ff1e74d1cbbba9a63e4015 --- /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 + +#include +#include +#include + +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_id postEventToBack(const sp &event); + + // It is an error to post an event with a negative delay. + event_id postEventWithDelay(const sp &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, 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), + void *cookie, + bool stopAfterFirstMatch = false); + + static int64_t getRealTimeUs(); + +private: + struct QueueItem { + sp 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 mQueue; + Mutex mLock; + Condition mQueueNotEmptyCondition; + Condition mQueueHeadChangedCondition; + event_id mNextEventID; + + bool mRunning; + bool mStopped; + + static void *ThreadWrapper(void *me); + void threadEntry(); + + sp 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 0000000000000000000000000000000000000000..1a2bf9f8aaa598ceabe29dd393847838dcf71a5c --- /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 + +namespace android { + +struct DataSource; + +struct VBRISeeker : public MP3Seeker { + static sp CreateFromSource( + const sp &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 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 0000000000000000000000000000000000000000..c567ccdce112adfab9071d2e61570d4e05faf70e --- /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 +#include + +namespace android { + +struct AMessage; +class DataSource; +class String8; + +class WAVExtractor : public MediaExtractor { +public: + // Extractor assumes ownership of "source". + WAVExtractor(const sp &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~WAVExtractor(); + +private: + sp 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 mTrackMeta; + + status_t init(); + + WAVExtractor(const WAVExtractor &); + WAVExtractor &operator=(const WAVExtractor &); +}; + +bool SniffWAV( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..3c3ca892259a7c1e7fa0a0b956b292cb16b49a66 --- /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 +#include + +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 &source); + + virtual size_t countTracks(); + virtual sp getTrack(size_t index); + virtual sp getTrackMetaData(size_t index, uint32_t flags); + virtual sp 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 mDataSource; + sp mImpl; + + WVMExtractor(const WVMExtractor &); + WVMExtractor &operator=(const WVMExtractor &); +}; + +bool SniffWVM( + const sp &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..c4085768b04e4d96181dc7e69fb7f078c0d35993 --- /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 CreateFromSource( + const sp &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 0000000000000000000000000000000000000000..e4188224d23f92a975a6a4eec8b7185de3e4d340 --- /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 +#include + +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 &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 MakeAVCCodecSpecificData(const sp &accessUnit); + +bool IsIDR(const sp &accessUnit); +bool IsAVCReferenceFrame(const sp &accessUnit); + +const char *AVCProfileToString(uint8_t profile); + +sp 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 0000000000000000000000000000000000000000..2cccb4f9e722bceb0cfcaf0d6b574fb2bb7aeb39 --- /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 0000000000000000000000000000000000000000..a0db719f70d27d5162462d9bf2239da83c8e70c2 --- /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 + +#include "MatroskaExtractor.h" + +#include "mkvparser.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +struct DataSourceReader : public mkvparser::IMkvReader { + DataSourceReader(const sp &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 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 &extractor, size_t index); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + +protected: + virtual ~MatroskaSource(); + +private: + enum Type { + AVC, + AAC, + OTHER + }; + + sp mExtractor; + size_t mTrackIndex; + Type mType; + bool mIsAudio; + BlockIterator mBlockIter; + size_t mNALSizeLen; // for type AVC + + List mPendingFrames; + + status_t advance(); + + status_t readBlock(); + void clearPendingFrames(); + + MatroskaSource(const MatroskaSource &); + MatroskaSource &operator=(const MatroskaSource &); +}; + +MatroskaSource::MatroskaSource( + const sp &extractor, size_t index) + : mExtractor(extractor), + mTrackIndex(index), + mType(OTHER), + mIsAudio(false), + mBlockIter(mExtractor.get(), + mExtractor->mTracks.itemAt(index).mTrackNum), + mNALSizeLen(0) { + sp 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 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 &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 MatroskaExtractor::getTrack(size_t index) { + if (index >= mTracks.size()) { + return NULL; + } + + return new MatroskaSource(this, index); +} + +sp 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 &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 &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 meta = new MetaData; + + switch (track->GetType()) { + case VIDEO_TRACK: + { + const mkvparser::VideoTrack *vtrack = + static_cast(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(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 MatroskaExtractor::getMetaData() { + sp 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 &source, String8 *mimeType, float *confidence, + sp *) { + 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 0000000000000000000000000000000000000000..1294b4fe415aa9c7defca321074c6c65e03308a4 --- /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 +#include +#include + +namespace mkvparser { +struct Segment; +}; + +namespace android { + +struct AMessage; +class String8; + +struct DataSourceReader; +struct MatroskaSource; + +struct MatroskaExtractor : public MediaExtractor { + MatroskaExtractor(const sp &source); + + virtual size_t countTracks(); + + virtual sp getTrack(size_t index); + + virtual sp getTrackMetaData( + size_t index, uint32_t flags); + + virtual sp getMetaData(); + + virtual uint32_t flags() const; + +protected: + virtual ~MatroskaExtractor(); + +private: + friend struct MatroskaSource; + friend struct BlockIterator; + + struct TrackInfo { + unsigned long mTrackNum; + sp mMeta; + }; + + Mutex mLock; + Vector mTracks; + + sp 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 &source, String8 *mimeType, float *confidence, + sp *); + +} // 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 0000000000000000000000000000000000000000..3f4de1fd30dc9591df194dde6707d4543009ab5c --- /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 + +#include "ATSParser.h" + +#include "AnotherPacketSource.h" +#include "ESQueue.h" +#include "include/avc_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &extra); + + void signalEOS(status_t finalResult); + + sp 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 > 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 &extra); + + void signalEOS(status_t finalResult); + + sp getSource(SourceType type); + +protected: + virtual ~Stream(); + +private: + Program *mProgram; + unsigned mElementaryPID; + unsigned mStreamType; + + sp mBuffer; + sp 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 &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 &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 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 = 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 s1 = mStreams.editValueAt(0); + sp 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 = new Stream(this, info.mPID, info.mType); + mStreams.add(info.mPID, stream); + } + } + + return OK; +} + +sp ATSParser::Program::getSource(SourceType type) { + size_t index = (type == AUDIO) ? 0 : 0; + + for (size_t i = 0; i < mStreams.size(); ++i) { + sp 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 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 &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 accessUnit; + while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) { + if (mSource == NULL) { + sp 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 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 &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 = 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 ATSParser::getSource(SourceType type) { + int which = -1; // any + + for (size_t i = 0; i < mPrograms.size(); ++i) { + const sp &program = mPrograms.editItemAt(i); + + if (which >= 0 && (int)program->number() != which) { + continue; + } + + sp 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 0000000000000000000000000000000000000000..c8038d1835bef2f325388ea6e3c8e19157665971 --- /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 + +#include +#include +#include +#include + +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 &extra); + + void signalEOS(status_t finalResult); + + enum SourceType { + VIDEO, + AUDIO + }; + sp 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 > 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 0000000000000000000000000000000000000000..eaa139d1ed6eab259db0a9a017d2aba1d38024dd --- /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 0000000000000000000000000000000000000000..e1ac53ce7481f5aa37239a472f1b9865c57ce994 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +AnotherPacketSource::AnotherPacketSource(const sp &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 &meta) { + CHECK(mFormat == NULL); + mFormat = meta; +} + +AnotherPacketSource::~AnotherPacketSource() { +} + +status_t AnotherPacketSource::start(MetaData *params) { + return OK; +} + +status_t AnotherPacketSource::stop() { + return OK; +} + +sp AnotherPacketSource::getFormat() { + return mFormat; +} + +status_t AnotherPacketSource::dequeueAccessUnit(sp *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 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 &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 &extra) { + Mutex::Autolock autoLock(mLock); + + // Leave only discontinuities in the queue. + List >::iterator it = mBuffers.begin(); + while (it != mBuffers.end()) { + sp oldBuffer = *it; + + int32_t oldDiscontinuityType; + if (!oldBuffer->meta()->findInt32( + "discontinuity", &oldDiscontinuityType)) { + it = mBuffers.erase(it); + continue; + } + + ++it; + } + + mEOSResult = OK; + + sp buffer = new ABuffer(0); + buffer->meta()->setInt32("discontinuity", static_cast(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 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 0000000000000000000000000000000000000000..c99f7f247f91b243b93c87b2a255bb988c10c429 --- /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 +#include +#include +#include + +#include "ATSParser.h" + +namespace android { + +struct ABuffer; + +struct AnotherPacketSource : public MediaSource { + AnotherPacketSource(const sp &meta); + + void setFormat(const sp &meta); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp 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 &buffer); + + void queueDiscontinuity( + ATSParser::DiscontinuityType type, const sp &extra); + + void signalEOS(status_t result); + + status_t dequeueAccessUnit(sp *buffer); + +protected: + virtual ~AnotherPacketSource(); + +private: + Mutex mLock; + Condition mCondition; + + bool mIsAudio; + sp mFormat; + List > 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 0000000000000000000000000000000000000000..7fd99a8032437667a010146edd9f89a52a6b2b3f --- /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 + +#include "ESQueue.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/avc_utils.h" + +namespace android { + +ElementaryStreamQueue::ElementaryStreamQueue(Mode mode) + : mMode(mode) { +} + +sp 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 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 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 ElementaryStreamQueue::dequeueAccessUnitAAC() { + Vector ranges; + Vector frameOffsets; + Vector 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 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 ElementaryStreamQueue::dequeueAccessUnitH264() { + const uint8_t *data = mBuffer->data(); + size_t size = mBuffer->size(); + + Vector 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 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 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 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 MakeMPEGVideoESDS(const sp &csd) { + sp 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 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 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 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 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 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 csd = new ABuffer(offset); + memcpy(csd->data(), data, offset); + + // hexdump(csd->data(), csd->size()); + + sp 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 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 0000000000000000000000000000000000000000..4035ed3ad187813326b9ac0cc94a7c398128b56d --- /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 +#include +#include +#include + +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 dequeueAccessUnit(); + + sp getFormat(); + +private: + struct RangeInfo { + int64_t mTimestampUs; + size_t mLength; + }; + + Mode mMode; + + sp mBuffer; + List mRangeInfos; + + sp mFormat; + + sp dequeueAccessUnitH264(); + sp dequeueAccessUnitAAC(); + sp dequeueAccessUnitMPEGAudio(); + sp dequeueAccessUnitMPEGVideo(); + sp 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 0000000000000000000000000000000000000000..dd714c9933aa259ff86fb18a86ba46d7c8cf4255 --- /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 + +#include "include/MPEG2PSExtractor.h" + +#include "AnotherPacketSource.h" +#include "ESQueue.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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 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 &extractor, const sp &track); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + +protected: + virtual ~WrappedTrack(); + +private: + sp mExtractor; + sp mTrack; + + DISALLOW_EVIL_CONSTRUCTORS(WrappedTrack); +}; + +//////////////////////////////////////////////////////////////////////////////// + +MPEG2PSExtractor::MPEG2PSExtractor(const sp &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 MPEG2PSExtractor::getTrack(size_t index) { + if (index >= mTracks.size()) { + return NULL; + } + + return new WrappedTrack(this, mTracks.valueAt(index)); +} + +sp MPEG2PSExtractor::getTrackMetaData(size_t index, uint32_t flags) { + if (index >= mTracks.size()) { + return NULL; + } + + return mTracks.valueAt(index)->getFormat(); +} + +sp MPEG2PSExtractor::getMetaData() { + sp 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 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 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 accessUnit; + while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) { + if (mSource == NULL) { + sp 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 &extractor, const sp &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 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 &source, String8 *mimeType, float *confidence, + sp *) { + 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 0000000000000000000000000000000000000000..e1589b44c8879241964d68f7555473cea953f1ab --- /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 + +#include "include/MPEG2TSExtractor.h" +#include "include/LiveSession.h" +#include "include/NuCachedSource2.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "AnotherPacketSource.h" +#include "ATSParser.h" + +namespace android { + +static const size_t kTSPacketSize = 188; + +struct MPEG2TSSource : public MediaSource { + MPEG2TSSource( + const sp &extractor, + const sp &impl, + bool seekable); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +private: + sp mExtractor; + sp 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 &extractor, + const sp &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 MPEG2TSSource::getFormat() { + sp 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 &source) + : mDataSource(source), + mParser(new ATSParser), + mOffset(0) { + init(); +} + +size_t MPEG2TSExtractor::countTracks() { + return mSourceImpls.size(); +} + +sp MPEG2TSExtractor::getTrack(size_t index) { + if (index >= mSourceImpls.size()) { + return NULL; + } + + bool seekable = true; + if (mSourceImpls.size() > 1) { + CHECK_EQ(mSourceImpls.size(), 2u); + + sp 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 MPEG2TSExtractor::getTrackMetaData( + size_t index, uint32_t flags) { + return index < mSourceImpls.size() + ? mSourceImpls.editItemAt(index)->getFormat() : NULL; +} + +sp MPEG2TSExtractor::getMetaData() { + sp 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 impl = + (AnotherPacketSource *)mParser->getSource( + ATSParser::VIDEO).get(); + + if (impl != NULL) { + haveVideo = true; + mSourceImpls.push(impl); + } + } + + if (!haveAudio) { + sp 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) { + 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 &source, String8 *mimeType, float *confidence, + sp *) { + 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 0000000000000000000000000000000000000000..d20ecb6ec8cd5f427ef775d870859e46a22ee171 --- /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 0000000000000000000000000000000000000000..f11fcd20b9f7f38d6d6862e37137fc4b7f3db406 --- /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 + +#include + +#include "../include/OMX.h" + +#include "../include/OMXNodeInstance.h" + +#include +#include +#include + +#include "OMXMaster.h" + +#include + +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 mQueue; + + sp 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 &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 *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 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 &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 ¶ms, + 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, 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 ¶ms, + 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::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 0000000000000000000000000000000000000000..6b6d0ab9eef9fe11132f6dd75581cc2202442270 --- /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 + +#include "OMXMaster.h" + +#include "SoftOMXPlugin.h" + +#include + +#include + +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::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 *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 0000000000000000000000000000000000000000..6069741742b144e6eada4d0d02d2c312c345d799 --- /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 + +#include +#include +#include +#include + +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 *roles); + +private: + Mutex mLock; + List mPlugins; + KeyedVector mPluginByComponentName; + KeyedVector 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 0000000000000000000000000000000000000000..bff3def81ff3a75ca1326652f19db607ad0d29d0 --- /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 + +#include "../include/OMXNodeInstance.h" +#include "OMXMaster.h" + +#include + +#include +#include +#include +#include + +namespace android { + +struct BufferMeta { + BufferMeta(const sp &mem, bool is_backup = false) + : mMem(mem), + mIsBackup(is_backup) { + } + + BufferMeta(size_t size) + : mSize(size), + mIsBackup(false) { + } + + BufferMeta(const sp &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 mGraphicBuffer; + sp 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 &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 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(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(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(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.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, ¶ms); + + 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.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, ¶ms); + + 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.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(¶ms, 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, ¶ms)) != 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 ¶ms, + 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(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, + 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( + reinterpret_cast(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, + 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.google.android.index.useAndroidNativeBuffer2"), + &index) == OMX_ErrorNone) { + return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); + } + + OMX_ERRORTYPE err = OMX_GetExtensionIndex( + mHandle, + const_cast("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, ¶ms); + + 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 ¶ms, + 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(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(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(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( + msg.u.extended_buffer_data.buffer); + + BufferMeta *buffer_meta = + static_cast(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(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(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(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 0000000000000000000000000000000000000000..c79e01f6ddf90ce7c2825563a792455a1d344543 --- /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 + +#include "include/SimpleSoftOMXComponent.h" + +#include +#include +#include + +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(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 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 msg = new AMessage(kWhatEmptyThisBuffer, mHandler->id()); + msg->setPointer("header", buffer); + msg->post(); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE SimpleSoftOMXComponent::fillThisBuffer( + OMX_BUFFERHEADERTYPE *buffer) { + sp 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 &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", ¶m)); + + 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::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 0000000000000000000000000000000000000000..b1c34dc4e49e306f43a233fd0c21d8996d0219e1 --- /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 + +#include "include/SoftOMXComponent.h" + +#include + +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 0000000000000000000000000000000000000000..99ffe7d658149b3852dcbb00f8b4290158242748 --- /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 + +#include "SoftOMXPlugin.h" +#include "include/SoftOMXComponent.h" + +#include +#include + +#include + +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 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 *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 0000000000000000000000000000000000000000..c89cd87aafe18b215384d93cd20a09bdd976032f --- /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 +#include + +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 *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 0000000000000000000000000000000000000000..6aa7470c66287e21231eac3ed6a4b502d1594186 --- /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 0000000000000000000000000000000000000000..fab1771004beeb3389d1187a0737bb76ded9c658 --- /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 + +#include "OMXHarness.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 sm = defaultServiceManager(); + sp binder = sm->getService(String16("media.player")); + sp service = interface_cast(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 *inputBuffers, + Vector *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 *inputBuffers, + Vector *outputBuffers, + omx_message *msg, int64_t timeoutUs) { + int64_t finishBy = getNowUs() + timeoutUs; + + for (;;) { + Mutex::Autolock autoLock(mLock); + List::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 &dealer, + IOMX::node_id node, OMX_U32 portIndex, + Vector *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, + ¶ms, sizeof(params)); +} + +struct NodeReaper { + NodeReaper(const sp &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 mHarness; + IOMX::node_id mNode; + + NodeReaper(const NodeReaper &); + NodeReaper &operator=(const NodeReaper &); +}; + +static sp CreateExtractorFromURI(const char *uri) { + sp source = DataSource::CreateFromURI(uri); + + if (source == NULL) { + return NULL; + } + + return MediaExtractor::Create(source); +} + +static sp MakeSource( + const char *uri, + const char *mimeType) { + sp extractor = CreateExtractorFromURI(uri); + + if (extractor == NULL) { + return NULL; + } + + for (size_t i = 0; i < extractor->countTracks(); ++i) { + sp 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 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 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 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 CreateSourceForMime(const char *mime) { + const char *url = GetURLForMime(mime); + CHECK(url != NULL); + + sp extractor = CreateExtractorFromURI(url); + + if (extractor == NULL) { + return NULL; + } + + for (size_t i = 0; i < extractor->countTracks(); ++i) { + sp 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 source = CreateSourceForMime(mime); + + sp seekSource = CreateSourceForMime(mime); + if (source == NULL || seekSource == NULL) { + return UNKNOWN_ERROR; + } + + CHECK_EQ(seekSource->start(), (status_t)OK); + + sp 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 componentInfos; + status_t err = mOMX->listNodes(&componentInfos); + EXPECT_SUCCESS(err, "listNodes"); + + for (List::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::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 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 0000000000000000000000000000000000000000..bb8fd0c93f85e8056dbb2d364444ec486ffed482 --- /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 +#include +#include +#include + +#include + +namespace android { + +class MemoryDealer; + +struct Harness : public BnOMXObserver { + enum BufferFlags { + kBufferBusy = 1 + }; + struct Buffer { + IOMX::buffer_id mID; + sp 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 *inputBuffers, + Vector *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 &dealer, + IOMX::node_id node, OMX_U32 portIndex, + Vector *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 mOMX; + List mMessageQueue; + Condition mMessageAddedCondition; + + status_t initOMX(); + + bool handleBufferMessage( + const omx_message &msg, + Vector *inputBuffers, + Vector *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 0000000000000000000000000000000000000000..fb8abc580c17a451e5e25e9ddd9656b07c7cc27f --- /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 + +#include "AAMRAssembler.h" + +#include "ARTPSource.h" + +#include +#include +#include +#include +#include + +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 ¬ify, bool isWide, const AString ¶ms) + : 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 &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 &source) { + List > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List >::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 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 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 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 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 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 0000000000000000000000000000000000000000..d55e10923b2632745e5de3dc64335f2b28a60e68 --- /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 + +#include + +namespace android { + +struct AMessage; +struct AString; + +struct AAMRAssembler : public ARTPAssembler { + AAMRAssembler( + const sp ¬ify, bool isWide, + const AString ¶ms); + +protected: + virtual ~AAMRAssembler(); + + virtual AssemblyStatus assembleMore(const sp &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + bool mIsWide; + + sp mNotifyMsg; + bool mNextExpectedSeqNoValid; + uint32_t mNextExpectedSeqNo; + + AssemblyStatus addPacket(const sp &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 0000000000000000000000000000000000000000..7ea132e54cf48c15ae43eacea4e670791de741ce --- /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 + +#include "AAVCAssembler.h" + +#include "ARTPSource.h" + +#include +#include +#include +#include + +#include + +namespace android { + +// static +AAVCAssembler::AAVCAssembler(const sp ¬ify) + : mNotifyMsg(notify), + mAccessUnitRTPTime(0), + mNextExpectedSeqNoValid(false), + mNextExpectedSeqNo(0), + mAccessUnitDamaged(false) { +} + +AAVCAssembler::~AAVCAssembler() { +} + +ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit( + const sp &source) { + List > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List >::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 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 &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 &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 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 > *queue) { + CHECK(!queue->empty()); + + sp 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 >::iterator it = ++queue->begin(); + while (it != queue->end()) { + ALOGV("sequence length %d", totalCount); + + const sp &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 unit = new ABuffer(totalSize); + CopyTimes(unit, *queue->begin()); + + unit->data()[0] = (nri << 5) | nalType; + + size_t offset = 1; + List >::iterator it = queue->begin(); + for (size_t i = 0; i < totalCount; ++i) { + const sp &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 >::iterator it = mNALUnits.begin(); + it != mNALUnits.end(); ++it) { + totalSize += 4 + (*it)->size(); + } + + sp accessUnit = new ABuffer(totalSize); + size_t offset = 0; + for (List >::iterator it = mNALUnits.begin(); + it != mNALUnits.end(); ++it) { + memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4); + offset += 4; + + sp 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 msg = mNotifyMsg->dup(); + msg->setBuffer("access-unit", accessUnit); + msg->post(); +} + +ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore( + const sp &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 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 0000000000000000000000000000000000000000..bf389ec329e56a104e60812188ded0608165fb2b --- /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 +#include + +namespace android { + +struct ABuffer; +struct AMessage; + +struct AAVCAssembler : public ARTPAssembler { + AAVCAssembler(const sp ¬ify); + +protected: + virtual ~AAVCAssembler(); + + virtual AssemblyStatus assembleMore(const sp &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + sp mNotifyMsg; + + uint32_t mAccessUnitRTPTime; + bool mNextExpectedSeqNoValid; + uint32_t mNextExpectedSeqNo; + bool mAccessUnitDamaged; + List > mNALUnits; + + AssemblyStatus addNALUnit(const sp &source); + void addSingleNALUnit(const sp &buffer); + AssemblyStatus addFragmentedNALUnit(List > *queue); + bool addSingleTimeAggregationPacket(const sp &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 0000000000000000000000000000000000000000..ded70fa174391348832430238993f82e7c349724 --- /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 +#include +#include +#include +#include + +namespace android { + +AH263Assembler::AH263Assembler(const sp ¬ify) + : mNotifyMsg(notify), + mAccessUnitRTPTime(0), + mNextExpectedSeqNoValid(false), + mNextExpectedSeqNo(0), + mAccessUnitDamaged(false) { +} + +AH263Assembler::~AH263Assembler() { +} + +ARTPAssembler::AssemblyStatus AH263Assembler::assembleMore( + const sp &source) { + AssemblyStatus status = addPacket(source); + if (status == MALFORMED_PACKET) { + mAccessUnitDamaged = true; + } + return status; +} + +ARTPAssembler::AssemblyStatus AH263Assembler::addPacket( + const sp &source) { + List > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List >::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 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 >::iterator it = mPackets.begin(); + while (it != mPackets.end()) { + const sp &unit = *it; + + totalSize += unit->size(); + ++it; + } + + sp accessUnit = new ABuffer(totalSize); + size_t offset = 0; + it = mPackets.begin(); + while (it != mPackets.end()) { + const sp &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 msg = mNotifyMsg->dup(); + msg->setBuffer("access-unit", accessUnit); + msg->post(); +} + +void AH263Assembler::packetLost() { + CHECK(mNextExpectedSeqNoValid); + ++mNextExpectedSeqNo; + + mAccessUnitDamaged = true; +} + +void AH263Assembler::onByeReceived() { + sp 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 0000000000000000000000000000000000000000..2b6c6253005b936fc5255a756bbb17952b92a41a --- /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 + +#include + +namespace android { + +struct AMessage; + +struct AH263Assembler : public ARTPAssembler { + AH263Assembler(const sp ¬ify); + +protected: + virtual ~AH263Assembler(); + + virtual AssemblyStatus assembleMore(const sp &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + sp mNotifyMsg; + uint32_t mAccessUnitRTPTime; + bool mNextExpectedSeqNoValid; + uint32_t mNextExpectedSeqNo; + bool mAccessUnitDamaged; + List > mPackets; + + AssemblyStatus addPacket(const sp &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 0000000000000000000000000000000000000000..24c2f30209ef53e87f8932bf4dd1d90d8b6903e2 --- /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 +#include +#include +#include +#include +#include + +#include + +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 decodeHex(const AString &s) { + if ((s.size() % 2) != 0) { + return NULL; + } + + size_t outLen = s.size() / 2; + sp 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 *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 AMPEG4AudioAssembler::removeLATMFraming(const sp &buffer) { + CHECK(!mMuxConfigPresent); // XXX to be implemented + + sp 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 ¬ify, const AString ¶ms) + : 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 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 &source) { + AssemblyStatus status = addPacket(source); + if (status == MALFORMED_PACKET) { + mAccessUnitDamaged = true; + } + return status; +} + +ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket( + const sp &source) { + List > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List >::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 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 >::iterator it = mPackets.begin(); + while (it != mPackets.end()) { + const sp &unit = *it; + + totalSize += unit->size(); + ++it; + } + + sp accessUnit = new ABuffer(totalSize); + size_t offset = 0; + it = mPackets.begin(); + while (it != mPackets.end()) { + const sp &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 msg = mNotifyMsg->dup(); + msg->setBuffer("access-unit", accessUnit); + msg->post(); +} + +void AMPEG4AudioAssembler::packetLost() { + CHECK(mNextExpectedSeqNoValid); + ++mNextExpectedSeqNo; + + mAccessUnitDamaged = true; +} + +void AMPEG4AudioAssembler::onByeReceived() { + sp 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 0000000000000000000000000000000000000000..1361cd2db7010874a9d79a4fc0d4ad70c4612602 --- /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 + +#include + +namespace android { + +struct AMessage; +struct AString; + +struct AMPEG4AudioAssembler : public ARTPAssembler { + AMPEG4AudioAssembler( + const sp ¬ify, const AString ¶ms); + +protected: + virtual ~AMPEG4AudioAssembler(); + + virtual AssemblyStatus assembleMore(const sp &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + sp 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 > mPackets; + + AssemblyStatus addPacket(const sp &source); + void submitAccessUnit(); + + sp removeLATMFraming(const sp &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 0000000000000000000000000000000000000000..687d72bbda564bfe81d394de522222f915f66d34 --- /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 + +#include "AMPEG4ElementaryAssembler.h" + +#include "ARTPSource.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +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 ¬ify, const AString &desc, const AString ¶ms) + : 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 &source) { + List > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List >::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 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 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::iterator it = headers.begin(); + it != headers.end(); ++it) { + const AUHeader &header = *it; + + CHECK_LE(offset + header.mSize, buffer->size()); + + sp 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 >::iterator it = mPackets.begin(); + it != mPackets.end(); ++it) { + totalSize += (*it)->size(); + } + + sp accessUnit = new ABuffer(totalSize); + size_t offset = 0; + for (List >::iterator it = mPackets.begin(); + it != mPackets.end(); ++it) { + sp 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 msg = mNotifyMsg->dup(); + msg->setBuffer("access-unit", accessUnit); + msg->post(); +} + +ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore( + const sp &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 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 0000000000000000000000000000000000000000..794bbcc6c4e69151f337bfdf63f3a07883c25a72 --- /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 + +#include +#include + +namespace android { + +struct ABuffer; +struct AMessage; + +struct AMPEG4ElementaryAssembler : public ARTPAssembler { + AMPEG4ElementaryAssembler( + const sp ¬ify, const AString &desc, + const AString ¶ms); + +protected: + virtual ~AMPEG4ElementaryAssembler(); + + virtual AssemblyStatus assembleMore(const sp &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + sp 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 > mPackets; + + AssemblyStatus addPacket(const sp &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 0000000000000000000000000000000000000000..6cf1301934aba549464cdbea32037aad554731fd --- /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 + +#include "APacketSource.h" + +#include "ARawAudioAssembler.h" +#include "ASessionDescription.h" + +#include "avc_utils.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 decodeHex(const AString &s) { + if ((s.size() % 2) != 0) { + return NULL; + } + + size_t outLen = s.size() / 2; + sp 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 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 profileLevelID = decodeHex(val); + CHECK(profileLevelID != NULL); + CHECK_EQ(profileLevelID->size(), 3u); + + Vector > 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 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 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 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 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 MakeAACCodecSpecificData(const char *params) { + AString val; + CHECK(GetAttribute(params, "config", &val)); + + sp 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 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 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 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 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 &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 MakeMPEG4VideoCodecSpecificData( + const char *params, int32_t *width, int32_t *height) { + *width = 0; + *height = 0; + + AString val; + CHECK(GetAttribute(params, "config", &val)); + + sp 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 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 &sessionDesc, size_t index) + : mInitCheck(NO_INIT), + mFormat(new MetaData) { + unsigned long PT; + AString desc; + AString params; + sessionDesc->getFormatType(index, &PT, &desc, ¶ms); + + 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 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 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 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 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 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 0000000000000000000000000000000000000000..530e53761700639c313203357ecafb8af7d4c313 --- /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 +#include +#include + +namespace android { + +struct ASessionDescription; + +struct APacketSource : public RefBase { + APacketSource(const sp &sessionDesc, size_t index); + + status_t initCheck() const; + + virtual sp getFormat(); + +protected: + virtual ~APacketSource(); + +private: + status_t mInitCheck; + + sp 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 0000000000000000000000000000000000000000..a897c10da4a1768934a86ef9baac5d938d9127aa --- /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 +#include +#include + +#include + +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 &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 &to, const sp &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 0000000000000000000000000000000000000000..70ea186673667f1711ec17a776e620c41c510fc2 --- /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 +#include + +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 &source); + virtual void onByeReceived() = 0; + +protected: + virtual AssemblyStatus assembleMore(const sp &source) = 0; + virtual void packetLost() = 0; + + static void CopyTimes(const sp &to, const sp &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 0000000000000000000000000000000000000000..44988a34733fadc3391e0ba42978d725f090adff --- /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 + +#include "ARTPConnection.h" + +#include "ARTPSource.h" +#include "ASessionDescription.h" + +#include +#include +#include +#include +#include + +#include +#include + +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 mSessionDesc; + size_t mIndex; + sp mNotifyMsg; + KeyedVector > 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 &sessionDesc, + size_t index, + const sp ¬ify, + bool injected) { + sp 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 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 &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 &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 obj; + CHECK(msg->findObject("session-desc", &obj)); + info->mSessionDesc = static_cast(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 &msg) { + int32_t rtpSocket, rtcpSocket; + CHECK(msg->findInt32("rtp-socket", &rtpSocket)); + CHECK(msg->findInt32("rtcp-socket", &rtcpSocket)); + + List::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 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::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::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 buffer = new ABuffer(kMaxUDPSize); + List::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 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 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 &buffer) { + if (s->mNumRTPPacketsReceived++ == 0) { + sp 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 source = findSource(s, srcId); + + uint32_t rtpTime = u32at(&data[4]); + + sp 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 &buffer) { + if (s->mNumRTCPPacketsReceived++ == 0) { + sp 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 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 source = findSource(s, id); + + source->timeUpdate(rtpTime, ntpTime); + + return 0; +} + +sp ARTPConnection::findSource(StreamInfo *info, uint32_t srcId) { + sp 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 &buffer) { + sp msg = new AMessage(kWhatInjectPacket, id()); + msg->setInt32("index", index); + msg->setBuffer("buffer", buffer); + msg->post(); +} + +void ARTPConnection::onInjectPacket(const sp &msg) { + int32_t index; + CHECK(msg->findInt32("index", &index)); + + sp buffer; + CHECK(msg->findBuffer("buffer", &buffer)); + + List::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 0000000000000000000000000000000000000000..edbcc35d28404e88cd6bc1cc458062ac2bcbd40e --- /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 +#include + +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 &sessionDesc, size_t index, + const sp ¬ify, + bool injected); + + void removeStream(int rtpSocket, int rtcpSocket); + + void injectPacket(int index, const sp &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 &msg); + +private: + enum { + kWhatAddStream, + kWhatRemoveStream, + kWhatPollStreams, + kWhatInjectPacket, + }; + + static const int64_t kSelectTimeoutUs; + + uint32_t mFlags; + + struct StreamInfo; + List mStreams; + + bool mPollEventPending; + int64_t mLastReceiverReportTimeUs; + + void onAddStream(const sp &msg); + void onRemoveStream(const sp &msg); + void onPollStreams(); + void onInjectPacket(const sp &msg); + void onSendReceiverReports(); + + status_t receive(StreamInfo *info, bool receiveRTP); + + status_t parseRTP(StreamInfo *info, const sp &buffer); + status_t parseRTCP(StreamInfo *info, const sp &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 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 0000000000000000000000000000000000000000..ba4e33c813db51eccdc201c76478cef545bfa8b5 --- /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 + +#include "ARTPSession.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "APacketSource.h" +#include "ARTPConnection.h" +#include "ASessionDescription.h" + +namespace android { + +ARTPSession::ARTPSession() + : mInitCheck(NO_INIT) { +} + +status_t ARTPSession::setup(const sp &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 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 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 &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 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 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 0000000000000000000000000000000000000000..9bff74c48d6bb21ebb3c50fbf9361c0ac0e89b67 --- /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 + +namespace android { + +struct APacketSource; +struct ARTPConnection; +struct ASessionDescription; +struct MediaSource; + +struct ARTPSession : public AHandler { + ARTPSession(); + + status_t setup(const sp &desc); + + size_t countTracks(); + sp trackAt(size_t index); + +protected: + virtual void onMessageReceived(const sp &msg); + + virtual ~ARTPSession(); + +private: + enum { + kWhatAccessUnitComplete = 'accu' + }; + + struct TrackInfo { + int mRTPSocket; + int mRTCPSocket; + + sp mPacketSource; + }; + + status_t mInitCheck; + sp mDesc; + sp mRTPConn; + + Vector 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 0000000000000000000000000000000000000000..ed687906df8a17779fc9c710a1c5bf676707e0da --- /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 + +#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 +#include +#include + +namespace android { + +static const uint32_t kSourceID = 0xdeadbeef; + +ARTPSource::ARTPSource( + uint32_t id, + const sp &sessionDesc, size_t index, + const sp ¬ify) + : 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, ¶ms); + + 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 &buffer) { + if (queuePacket(buffer) && mAssembler != NULL) { + mAssembler->onPacketReceived(this); + } +} + +void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) { + mLastNTPTime = ntpTime; + mLastNTPTimeUpdateUs = ALooper::GetNowUs(); + + sp 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 &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 >::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 &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 &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 0000000000000000000000000000000000000000..b70f94e496c8fab6ee7e566952f11892d47aa326 --- /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 + +#include +#include +#include + +namespace android { + +struct ABuffer; +struct AMessage; +struct ARTPAssembler; +struct ASessionDescription; + +struct ARTPSource : public RefBase { + ARTPSource( + uint32_t id, + const sp &sessionDesc, size_t index, + const sp ¬ify); + + void processRTPPacket(const sp &buffer); + void timeUpdate(uint32_t rtpTime, uint64_t ntpTime); + void byeReceived(); + + List > *queue() { return &mQueue; } + + void addReceiverReport(const sp &buffer); + void addFIR(const sp &buffer); + +private: + uint32_t mID; + uint32_t mHighestSeqNumber; + int32_t mNumBuffersReceived; + + List > mQueue; + sp mAssembler; + + uint64_t mLastNTPTime; + int64_t mLastNTPTimeUpdateUs; + + bool mIssueFIRRequests; + int64_t mLastFIRRequestUs; + uint8_t mNextFIRSeqNo; + + sp mNotify; + + bool queuePacket(const sp &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 0000000000000000000000000000000000000000..0d070434aacdd7690e11560d4b6d7bf587124a89 --- /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 + +#include "ARTPWriter.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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 &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 &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 &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 &msg) { + sp 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 &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 &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 &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 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 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 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 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 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 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 0000000000000000000000000000000000000000..fdc8d230fda2afe79f673243fb1b8916dd080007 --- /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 +#include +#include +#include +#include + +#include +#include + +#define LOG_TO_FILES 0 + +namespace android { + +struct ABuffer; +struct MediaBuffer; + +struct ARTPWriter : public MediaWriter { + ARTPWriter(int fd); + + virtual status_t addSource(const sp &source); + virtual bool reachedEOS(); + virtual status_t start(MetaData *params); + virtual status_t stop(); + virtual status_t pause(); + + virtual void onMessageReceived(const sp &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 mSource; + sp mLooper; + sp > 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 &msg); + void onSendSR(const sp &msg); + + void addSR(const sp &buffer); + void addSDES(const sp &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 &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 0000000000000000000000000000000000000000..539a88823cabcece8bbb2f1e68a958535007d437 --- /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 + +#include "ARTSPConnection.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 &reply) { + sp msg = new AMessage(kWhatConnect, id()); + msg->setString("url", url); + msg->setMessage("reply", reply); + msg->post(); +} + +void ARTSPConnection::disconnect(const sp &reply) { + sp msg = new AMessage(kWhatDisconnect, id()); + msg->setMessage("reply", reply); + msg->post(); +} + +void ARTSPConnection::sendRequest( + const char *request, const sp &reply) { + sp msg = new AMessage(kWhatSendRequest, id()); + msg->setString("request", request); + msg->setMessage("reply", reply); + msg->post(); +} + +void ARTSPConnection::observeBinaryData(const sp &reply) { + sp msg = new AMessage(kWhatObserveBinaryData, id()); + msg->setMessage("reply", reply); + msg->post(); +} + +void ARTSPConnection::onMessageReceived(const sp &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 &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 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 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 &msg) { + if (mState == CONNECTED || mState == CONNECTING) { + performDisconnect(); + } + + sp reply; + CHECK(msg->findMessage("reply", &reply)); + + reply->setInt32("result", OK); + + reply->post(); +} + +void ARTSPConnection::onCompleteConnection(const sp &msg) { + sp 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 &msg) { + sp 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 reply = mPendingRequests.valueAt(i); + + reply->setInt32("result", -ECONNABORTED); + reply->post(); + } + + mPendingRequests.clear(); +} + +void ARTSPConnection::postReceiveReponseEvent() { + if (mReceiveResponseEventPending) { + return; + } + + sp 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 ARTSPConnection::receiveBinaryData() { + uint8_t x[3]; + if (receive(x, 3) != OK) { + return NULL; + } + + sp 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 buffer = receiveBinaryData(); + + if (buffer == NULL) { + return false; + } + + if (mObserveBinaryMessage != NULL) { + sp notify = mObserveBinaryMessage->dup(); + notify->setBuffer("buffer", buffer); + notify->post(); + } else { + ALOGW("received binary data, but no one cares."); + } + + return true; + } + + sp 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 reply = mPendingRequests.valueAt(i); + mPendingRequests.removeItemsAt(i); + + AString request; + CHECK(reply->findString("original-request", &request)); + + sp 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 &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 &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 &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 reply = mPendingRequests.valueAt(i); + mPendingRequests.removeItemsAt(i); + + reply->setInt32("result", OK); + reply->setObject("response", response); + reply->post(); + + return true; +} + +bool ARTSPConnection::parseAuthMethod(const sp &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 0000000000000000000000000000000000000000..68f2d59ea80e66cd1a65e8425d38834b0dcfa1c8 --- /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 +#include + +namespace android { + +struct ABuffer; + +struct ARTSPResponse : public RefBase { + unsigned long mStatusCode; + AString mStatusLine; + KeyedVector mHeaders; + sp mContent; +}; + +struct ARTSPConnection : public AHandler { + ARTSPConnection(bool uidValid = false, uid_t uid = 0); + + void connect(const char *url, const sp &reply); + void disconnect(const sp &reply); + + void sendRequest(const char *request, const sp &reply); + + void observeBinaryData(const sp &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 &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 > mPendingRequests; + + sp mObserveBinaryMessage; + + AString mUserAgent; + + void performDisconnect(); + + void onConnect(const sp &msg); + void onDisconnect(const sp &msg); + void onCompleteConnection(const sp &msg); + void onSendRequest(const sp &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 receiveBinaryData(); + bool notifyResponseListener(const sp &response); + + bool parseAuthMethod(const sp &response); + void addAuthentication(AString *request); + + void addUserAgent(AString *request) const; + + status_t findPendingRequest( + const sp &response, ssize_t *index) const; + + bool handleServerRequest(const sp &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 0000000000000000000000000000000000000000..0da5dd250e9b6e25d5d7cb311b1430ee553fe182 --- /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 + +#include "ARawAudioAssembler.h" + +#include "ARTPSource.h" +#include "ASessionDescription.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +ARawAudioAssembler::ARawAudioAssembler( + const sp ¬ify, const char *desc, const AString ¶ms) + : mNotifyMsg(notify), + mNextExpectedSeqNoValid(false), + mNextExpectedSeqNo(0) { +} + +ARawAudioAssembler::~ARawAudioAssembler() { +} + +ARTPAssembler::AssemblyStatus ARawAudioAssembler::assembleMore( + const sp &source) { + return addPacket(source); +} + +ARTPAssembler::AssemblyStatus ARawAudioAssembler::addPacket( + const sp &source) { + List > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List >::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 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 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 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 &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 0000000000000000000000000000000000000000..ed7af080c575b26321cb0e514cafdbee9251343e --- /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 ¬ify, + const char *desc, const AString ¶ms); + + static bool Supports(const char *desc); + + static void MakeFormat( + const char *desc, const sp &format); + +protected: + virtual ~ARawAudioAssembler(); + + virtual AssemblyStatus assembleMore(const sp &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + bool mIsWide; + + sp mNotifyMsg; + bool mNextExpectedSeqNoValid; + uint32_t mNextExpectedSeqNo; + + AssemblyStatus addPacket(const sp &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 0000000000000000000000000000000000000000..a9b33308b1ad26a58c4b07b73df3e2469246df59 --- /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 + +#include "ASessionDescription.h" + +#include +#include + +#include + +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 0000000000000000000000000000000000000000..b4629834b68d78eb880f66e5146f203d15ca20d9 --- /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 + +#include +#include +#include +#include + +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 Attribs; + + bool mIsValid; + Vector mTracks; + Vector 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 0000000000000000000000000000000000000000..e0fe59ba9f75afe1c0c3f327d604448d05da9bc5 --- /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 0000000000000000000000000000000000000000..deee30f1460080ded4d34cce6a976317fbad49b7 --- /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 + +#include "APacketSource.h" +#include "ARTPConnection.h" +#include "ARTSPConnection.h" +#include "ASessionDescription.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 ¬ify, + 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 notify = new AMessage('biny', id()); + mConn->observeBinaryData(notify); + + sp reply = new AMessage('conn', id()); + mConn->connect(mOriginalSessionURL.c_str(), reply); + } + + void disconnect() { + (new AMessage('abor', id()))->post(); + } + + void seek(int64_t timeUs) { + sp msg = new AMessage('seek', id()); + msg->setInt64("time", timeUs); + msg->post(); + } + + static void addRR(const sp &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 &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 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 &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 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 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response = + static_cast(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 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 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response = + static_cast(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 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 reply = new AMessage('play', id()); + mConn->sendRequest(request.c_str(), reply); + } else { + sp 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response = + static_cast(obj.get()); + + if (response->mStatusCode != 200) { + result = UNKNOWN_ERROR; + } else { + parsePlayResponse(response); + + sp timeout = new AMessage('tiou', id()); + timeout->post(kStartupTimeoutUs); + } + } + + if (result != OK) { + sp 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 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 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 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 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 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 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 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 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response = + static_cast(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 msg = mNotify->dup(); + msg->setInt32("what", kWhatSeekDone); + msg->post(); + break; + } + + case 'biny': + { + sp 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 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 msg = new AMessage('aliv', id()); + msg->setInt32("generation", mKeepAliveGeneration); + msg->post((mKeepAliveTimeoutUs * 9) / 10); + } + + void postAccessUnitTimeoutCheck() { + if (mCheckPending) { + return; + } + + mCheckPending = true; + sp check = new AMessage('chek', id()); + check->setInt32("generation", mCheckGeneration); + check->post(kAccessUnitTimeoutUs); + } + + static void SplitString( + const AString &s, const char *separator, List *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 &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 streamInfos; + SplitString(rtpInfo, ",", &streamInfos); + + int n = 1; + for (List::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 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 mPacketSource; + + // Stores packets temporarily while no notion of time + // has been established yet. + List > mPackets; + }; + + sp mNotify; + bool mUIDValid; + uid_t mUID; + sp mNetLooper; + sp mConn; + sp mRTPConn; + sp 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 mTracks; + + void setupTrack(size_t index) { + sp source = + new APacketSource(mSessionDesc, index); + + if (source->initCheck() != OK) { + ALOGW("Unsupported format. Ignoring track #%d.", index); + + sp 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(), ×cale, &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 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 &accessUnit) { + ALOGV("onAccessUnitComplete track %d", trackIndex); + + if (mFirstAccessUnit) { + sp 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 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 &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 &accessUnit) { + sp 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 msg = mNotify->dup(); + msg->setInt32("what", kWhatEOS); + msg->setSize("trackIndex", trackIndex); + msg->setInt32("finalResult", finalResult); + msg->post(); + } + + void postQueueSeekDiscontinuity(size_t trackIndex) { + sp 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 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 0000000000000000000000000000000000000000..009a3b1fb0eac6bc1903e848bcfc0091f08b92ae --- /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 +#include + +#include + +#include +#include +#include + +#ifdef ANDROID +#include "VideoSource.h" + +#include +#include +#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 &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 reply = new AMessage('conn', id()); + mConn->connect(mServerURL.c_str(), reply); + +#ifdef ANDROID + int width = 640; + int height = 480; + + sp source = new VideoSource(width, height); + + sp 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 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 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 &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 &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 obj; + CHECK(msg->findObject("response", &obj)); + sp response; + + if (result == OK) { + response = static_cast(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 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 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response; + + if (result == OK) { + response = static_cast(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 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response; + + if (result == OK) { + response = static_cast(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 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 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 reply = new AMessage('paus', id()); + mConn->sendRequest(request.c_str(), reply); + } + break; + } + + case 'sr ': + { + if (!mConnected) { + break; + } + + sp 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 obj; + CHECK(msg->findObject("response", &obj)); + sp 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 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 obj; + CHECK(msg->findObject("response", &obj)); + sp response; + + if (result == OK) { + response = static_cast(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 mLooper; + sp 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 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 &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 &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 0000000000000000000000000000000000000000..47ea6f162c8dcebd6c9a057e2b01d9983718595e --- /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 + +#include "UDPPusher.h" + +#include +#include +#include +#include + +#include + +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 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 &msg) { + switch (msg->what()) { + case kWhatPush: + { + if (!onPush() && !(ntohs(mRemoteAddr.sin_port) & 1)) { + ALOGI("emulating BYE packet"); + + sp 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 0000000000000000000000000000000000000000..2bde533509b24d968239bc97f362e8899298f3bb --- /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 + +#include +#include + +namespace android { + +struct UDPPusher : public AHandler { + UDPPusher(const char *filename, unsigned port); + + void start(); + +protected: + virtual ~UDPPusher(); + virtual void onMessageReceived(const sp &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 0000000000000000000000000000000000000000..ae0c85b6bb8d1ca8aae7b4970e0ffcd041efc17c --- /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 +#include +#include +#include + +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 getFormat() { + sp 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 0000000000000000000000000000000000000000..d43cd2a4ed4b12535b077c2dca51626cc2941aa6 --- /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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 looper = new ALooper; + + sp rtp_pusher; + sp 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 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 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 source = session->trackAt(0); + + OMXClient client; + CHECK_EQ(client.connect(), (status_t)OK); + + sp 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 0000000000000000000000000000000000000000..656a63004318e72fe3f046a0be10e209a536fa9f --- /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 0000000000000000000000000000000000000000..ac37b2841507dd75084d730aee255da9496790fe --- /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 +#include +#include "DummyRecorder.h" + +#include + +namespace android { + +// static +void *DummyRecorder::threadWrapper(void *pthis) { + ALOGV("ThreadWrapper: %p", pthis); + DummyRecorder *writer = static_cast(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 0000000000000000000000000000000000000000..1cbea1b0dea23caa2a11e045c1ff3af580bfb0d0 --- /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 +#include +#include + + +namespace android { + +class MediaSource; +class MediaBuffer; + +class DummyRecorder { + public: + // The media source from which this will receive frames + sp 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 &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 0000000000000000000000000000000000000000..fe77cf7540a000245d34becdeddfbf344d57f3b6 --- /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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 window = mSurfaceControl->getSurface(); + mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, + window.get(), NULL); + } else { + ALOGV("No actual display. Choosing EGLSurface based on SurfaceMediaSource"); + sp sms = new SurfaceMediaSource( + getSurfaceWidth(), getSurfaceHeight()); + sp stc = new SurfaceTextureClient(sms); + sp 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 mComposerClient; + sp 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 >( mSMS)); + mANW = mSTC; + } + + virtual void TearDown() { + mSMS.clear(); + mSTC.clear(); + mANW.clear(); + } + + const int mYuvTexWidth; + const int mYuvTexHeight; + + sp mSMS; + sp mSTC; + sp 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 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 >( 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& mr); + + const int mYuvTexWidth; + const int mYuvTexHeight; + + sp mSMS; + sp mSTC; + sp 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 SurfaceMediaSourceGLTest::setUpMediaRecorder(int fd, int videoSource, + int outputFormat, int videoEncoder, int width, int height, int fps) { + sp 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& mr) { + sp 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 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 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 mSource; + + SimpleDummyRecorder + (const sp &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 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 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 >( 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 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 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 0000000000000000000000000000000000000000..58ef9e36b309eb10a12ed5beeea280041658ec37 --- /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 0000000000000000000000000000000000000000..f9c1fe093803961c4e71cf7093115abf70196cf7 --- /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 +#include + +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 0000000000000000000000000000000000000000..0144917505e943fb572eae248d18ca83fd95fec7 --- /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 +#include + +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 + KEY_STRUCT_FONT_LIST = 9, // List + KEY_STRUCT_HIGHLIGHT_LIST = 10, // List + KEY_STRUCT_HYPER_TEXT_LIST = 11, // List + KEY_STRUCT_KARAOKE_LIST = 12, // List + KEY_STRUCT_STYLE_LIST = 13, // List