summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk4
-rw-r--r--camera/CameraMetadata.cpp3
-rw-r--r--camera/VendorTagDescriptor.cpp26
-rw-r--r--drm/libdrmframework/Android.mk4
-rw-r--r--drm/libdrmframework/DrmManagerClient.cpp2
-rw-r--r--drm/libdrmframework/DrmManagerClientImpl.cpp17
-rw-r--r--drm/libdrmframework/NoOpDrmManagerClientImpl.cpp152
-rw-r--r--drm/libdrmframework/include/DrmManagerClientImpl.h66
-rw-r--r--drm/libdrmframework/include/NoOpDrmManagerClientImpl.h74
-rw-r--r--include/soundtrigger/ISoundTrigger.h59
-rw-r--r--include/soundtrigger/ISoundTriggerClient.h49
-rw-r--r--include/soundtrigger/ISoundTriggerHwService.h57
-rw-r--r--include/soundtrigger/SoundTrigger.h75
-rw-r--r--include/soundtrigger/SoundTriggerCallback.h40
-rw-r--r--media/libcpustats/Android.mk4
-rw-r--r--media/libcpustats/ThreadCpuUsage.cpp3
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp13
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp20
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp4
-rw-r--r--media/libnbaio/NBLog.cpp2
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp3
-rw-r--r--media/libstagefright/MediaBuffer.cpp5
-rw-r--r--media/libstagefright/codecs/aacdec/Android.mk3
-rw-r--r--media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp372
-rw-r--r--media/libstagefright/codecs/aacdec/DrcPresModeWrap.h62
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.cpp730
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.h27
-rw-r--r--media/libstagefright/codecs/hevcdec/Android.mk4
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s210
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s369
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm366
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s237
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm231
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp4
-rw-r--r--media/mediaserver/Android.mk6
-rw-r--r--media/mediaserver/main_mediaserver.cpp2
-rw-r--r--services/audioflinger/AudioFlinger.cpp10
-rw-r--r--services/audioflinger/AudioResamplerDyn.cpp56
-rw-r--r--services/audioflinger/AudioWatchdog.cpp2
-rw-r--r--services/audioflinger/FastMixer.cpp63
-rw-r--r--services/audioflinger/StateQueue.cpp4
-rw-r--r--services/audioflinger/Threads.cpp73
-rw-r--r--services/audioflinger/tests/Android.mk31
-rwxr-xr-xservices/audioflinger/tests/build_and_run_all_unit_tests.sh22
-rw-r--r--services/audioflinger/tests/resampler_tests.cpp471
-rwxr-xr-xservices/audioflinger/tests/run_all_unit_tests.sh11
-rw-r--r--services/audiopolicy/Android.mk16
-rw-r--r--services/audiopolicy/AudioPolicyFactory.cpp32
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp26
-rw-r--r--services/audiopolicy/AudioPolicyManager.h1
-rw-r--r--services/audiopolicy/AudioPolicyService.cpp28
-rw-r--r--services/audiopolicy/AudioPolicyService.h2
-rw-r--r--services/camera/libcameraservice/utils/CameraTraces.cpp4
-rw-r--r--services/medialog/MediaLogService.cpp4
-rw-r--r--services/soundtrigger/Android.mk41
-rw-r--r--services/soundtrigger/SoundTriggerHwService.cpp570
-rw-r--r--services/soundtrigger/SoundTriggerHwService.h185
-rw-r--r--soundtrigger/Android.mk38
-rw-r--r--soundtrigger/ISoundTrigger.cpp177
-rw-r--r--soundtrigger/ISoundTriggerClient.cpp75
-rw-r--r--soundtrigger/ISoundTriggerHwService.cpp150
-rw-r--r--soundtrigger/SoundTrigger.cpp253
64 files changed, 3825 insertions, 1830 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 20da925..d0890fe 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -55,6 +55,10 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libaudiopolicy
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libaudiopolicy.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libaudiopolicyservice_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libaudiopolicymanager_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libaudiopolicyservice.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libaudiopolicymanager.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libaudiopolicyservice_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libaudiopolicymanager_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 1567cd1..043437f 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -590,7 +590,8 @@ status_t CameraMetadata::writeToParcel(Parcel& data,
const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
- __FUNCTION__, alignment, metadataStart, offset);
+ __FUNCTION__, alignment,
+ reinterpret_cast<const void *>(metadataStart), offset);
copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
// Not too big of a problem since receiving side does hard validation
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index 59dce91..0dda6b6 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -213,7 +213,7 @@ status_t VendorTagDescriptor::createFromParcel(const Parcel* parcel,
return res;
}
if (sectionCount < (maxSectionIndex + 1)) {
- ALOGE("%s: Incorrect number of sections defined, received %d, needs %d.",
+ ALOGE("%s: Incorrect number of sections defined, received %zu, needs %d.",
__FUNCTION__, sectionCount, (maxSectionIndex + 1));
return BAD_VALUE;
}
@@ -222,14 +222,16 @@ status_t VendorTagDescriptor::createFromParcel(const Parcel* parcel,
for (size_t i = 0; i < sectionCount; ++i) {
String8 sectionName = parcel->readString8();
if (sectionName.isEmpty()) {
- ALOGE("%s: parcel section name was NULL for section %d.", __FUNCTION__, i);
+ ALOGE("%s: parcel section name was NULL for section %zu.",
+ __FUNCTION__, i);
return NOT_ENOUGH_DATA;
}
desc->mSections.add(sectionName);
}
}
- LOG_ALWAYS_FATAL_IF(tagCount != allTags.size(), "tagCount must be the same as allTags size");
+ LOG_ALWAYS_FATAL_IF(static_cast<size_t>(tagCount) != allTags.size(),
+ "tagCount must be the same as allTags size");
// Set up reverse mapping
for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
uint32_t tag = allTags[i];
@@ -349,18 +351,18 @@ void VendorTagDescriptor::dump(int fd, int verbosity, int indentation) const {
size_t size = mTagToNameMap.size();
if (size == 0) {
- fdprintf(fd, "%*sDumping configured vendor tag descriptors: None set\n",
+ dprintf(fd, "%*sDumping configured vendor tag descriptors: None set\n",
indentation, "");
return;
}
- fdprintf(fd, "%*sDumping configured vendor tag descriptors: %zu entries\n",
+ dprintf(fd, "%*sDumping configured vendor tag descriptors: %zu entries\n",
indentation, "", size);
for (size_t i = 0; i < size; ++i) {
uint32_t tag = mTagToNameMap.keyAt(i);
if (verbosity < 1) {
- fdprintf(fd, "%*s0x%x\n", indentation + 2, "", tag);
+ dprintf(fd, "%*s0x%x\n", indentation + 2, "", tag);
continue;
}
String8 name = mTagToNameMap.valueAt(i);
@@ -369,7 +371,7 @@ void VendorTagDescriptor::dump(int fd, int verbosity, int indentation) const {
int type = mTagToTypeMap.valueFor(tag);
const char* typeName = (type >= 0 && type < NUM_TYPES) ?
camera_metadata_type_names[type] : "UNKNOWN";
- fdprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2,
+ dprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2,
"", tag, name.string(), type, typeName, sectionName.string());
}
@@ -409,7 +411,7 @@ sp<VendorTagDescriptor> VendorTagDescriptor::getGlobalVendorTagDescriptor() {
extern "C" {
-int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* v) {
+int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* /*v*/) {
Mutex::Autolock al(sLock);
if (sGlobalVendorTagDescriptor == NULL) {
ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
@@ -418,7 +420,7 @@ int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* v) {
return sGlobalVendorTagDescriptor->getTagCount();
}
-void vendor_tag_descriptor_get_all_tags(const vendor_tag_ops_t* v, uint32_t* tagArray) {
+void vendor_tag_descriptor_get_all_tags(const vendor_tag_ops_t* /*v*/, uint32_t* tagArray) {
Mutex::Autolock al(sLock);
if (sGlobalVendorTagDescriptor == NULL) {
ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
@@ -427,7 +429,7 @@ void vendor_tag_descriptor_get_all_tags(const vendor_tag_ops_t* v, uint32_t* tag
sGlobalVendorTagDescriptor->getTagArray(tagArray);
}
-const char* vendor_tag_descriptor_get_section_name(const vendor_tag_ops_t* v, uint32_t tag) {
+const char* vendor_tag_descriptor_get_section_name(const vendor_tag_ops_t* /*v*/, uint32_t tag) {
Mutex::Autolock al(sLock);
if (sGlobalVendorTagDescriptor == NULL) {
ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
@@ -436,7 +438,7 @@ const char* vendor_tag_descriptor_get_section_name(const vendor_tag_ops_t* v, ui
return sGlobalVendorTagDescriptor->getSectionName(tag);
}
-const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* v, uint32_t tag) {
+const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* /*v*/, uint32_t tag) {
Mutex::Autolock al(sLock);
if (sGlobalVendorTagDescriptor == NULL) {
ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
@@ -445,7 +447,7 @@ const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* v, uint32
return sGlobalVendorTagDescriptor->getTagName(tag);
}
-int vendor_tag_descriptor_get_tag_type(const vendor_tag_ops_t* v, uint32_t tag) {
+int vendor_tag_descriptor_get_tag_type(const vendor_tag_ops_t* /*v*/, uint32_t tag) {
Mutex::Autolock al(sLock);
if (sGlobalVendorTagDescriptor == NULL) {
ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 49c4f9b..33f9d3b 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -19,12 +19,14 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
DrmManagerClientImpl.cpp \
- DrmManagerClient.cpp
+ DrmManagerClient.cpp \
+ NoOpDrmManagerClientImpl.cpp
LOCAL_MODULE:= libdrmframework
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libcutils \
liblog \
libbinder \
libdl
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index ea30d01..440dd91 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -29,7 +29,7 @@ DrmManagerClient::DrmManagerClient():
}
DrmManagerClient::~DrmManagerClient() {
- DrmManagerClientImpl::remove(mUniqueId);
+ mDrmManagerClientImpl->remove(mUniqueId);
mDrmManagerClientImpl->removeClient(mUniqueId);
mDrmManagerClientImpl->setOnInfoListener(mUniqueId, NULL);
}
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index ffefd74..2d2c90e 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -21,8 +21,10 @@
#include <utils/String8.h>
#include <utils/Vector.h>
#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
#include "DrmManagerClientImpl.h"
+#include "NoOpDrmManagerClientImpl.h"
using namespace android;
@@ -35,9 +37,12 @@ const String8 DrmManagerClientImpl::EMPTY_STRING("");
DrmManagerClientImpl* DrmManagerClientImpl::create(
int* pUniqueId, bool isNative) {
- *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
-
- return new DrmManagerClientImpl();
+ sp<IDrmManagerService> service = getDrmManagerService();
+ if (service != NULL) {
+ *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
+ return new DrmManagerClientImpl();
+ }
+ return new NoOpDrmManagerClientImpl();
}
void DrmManagerClientImpl::remove(int uniqueId) {
@@ -47,6 +52,12 @@ void DrmManagerClientImpl::remove(int uniqueId) {
const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
Mutex::Autolock lock(sMutex);
if (NULL == sDrmManagerService.get()) {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("drm.service.enabled", value, NULL) == 0) {
+ // Drm is undefined for this device
+ return sDrmManagerService;
+ }
+
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
diff --git a/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp b/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp
new file mode 100644
index 0000000..dab583d
--- /dev/null
+++ b/drm/libdrmframework/NoOpDrmManagerClientImpl.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NoOpDrmManagerClientImpl.h"
+
+namespace android {
+
+void NoOpDrmManagerClientImpl::remove(int uniqueId) {
+}
+
+void NoOpDrmManagerClientImpl::addClient(int uniqueId) {
+}
+
+void NoOpDrmManagerClientImpl::removeClient(int uniqueId) {
+}
+
+status_t NoOpDrmManagerClientImpl::setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ return UNKNOWN_ERROR;
+}
+
+DrmConstraints* NoOpDrmManagerClientImpl::getConstraints(int uniqueId, const String8* path, const int action) {
+ return NULL;
+}
+
+DrmMetadata* NoOpDrmManagerClientImpl::getMetadata(int uniqueId, const String8* path) {
+ return NULL;
+}
+
+bool NoOpDrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ return false;
+}
+
+DrmInfoStatus* NoOpDrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ return NULL;
+}
+
+DrmInfo* NoOpDrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ return NULL;
+}
+
+status_t NoOpDrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ return UNKNOWN_ERROR;
+}
+
+String8 NoOpDrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
+ return String8();
+}
+
+int NoOpDrmManagerClientImpl::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ return -1;
+}
+
+int NoOpDrmManagerClientImpl::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ return -1;
+}
+
+status_t NoOpDrmManagerClientImpl::consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve) {
+ return UNKNOWN_ERROR;
+}
+
+status_t NoOpDrmManagerClientImpl::setPlaybackStatus(
+ int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) {
+ return UNKNOWN_ERROR;
+}
+
+bool NoOpDrmManagerClientImpl::validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ return false;
+}
+
+status_t NoOpDrmManagerClientImpl::removeRights(int uniqueId, const String8& path) {
+ return UNKNOWN_ERROR;
+}
+
+status_t NoOpDrmManagerClientImpl::removeAllRights(int uniqueId) {
+ return UNKNOWN_ERROR;
+}
+
+int NoOpDrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+ return -1;
+}
+
+DrmConvertedStatus* NoOpDrmManagerClientImpl::convertData(int uniqueId, int convertId, const DrmBuffer* inputData) {
+ return NULL;
+}
+
+DrmConvertedStatus* NoOpDrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+ return NULL;
+}
+
+status_t NoOpDrmManagerClientImpl::getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ return UNKNOWN_ERROR;
+}
+
+sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
+ return NULL;
+}
+
+sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(
+ int uniqueId, const char* uri, const char* mime) {
+ return NULL;
+}
+
+sp<DecryptHandle> NoOpDrmManagerClientImpl::openDecryptSession(int uniqueId, const DrmBuffer& buf,
+ const String8& mimeType) {
+ return NULL;
+}
+
+status_t NoOpDrmManagerClientImpl::closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle) {
+ return UNKNOWN_ERROR;
+}
+
+status_t NoOpDrmManagerClientImpl::initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ return UNKNOWN_ERROR;
+}
+
+status_t NoOpDrmManagerClientImpl::decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ return UNKNOWN_ERROR;
+}
+
+status_t NoOpDrmManagerClientImpl::finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
+ return UNKNOWN_ERROR;
+}
+
+ssize_t NoOpDrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) {
+ return -1;
+}
+
+status_t NoOpDrmManagerClientImpl::notify(const DrmInfoEvent& event) {
+ return UNKNOWN_ERROR;
+}
+
+}
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 3400cb1..3858675 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -34,30 +34,30 @@ class DrmInfoEvent;
*
*/
class DrmManagerClientImpl : public BnDrmServiceListener {
-private:
+protected:
DrmManagerClientImpl() { }
public:
static DrmManagerClientImpl* create(int* pUniqueId, bool isNative);
- static void remove(int uniqueId);
-
virtual ~DrmManagerClientImpl() { }
public:
+ virtual void remove(int uniqueId);
+
/**
* Adds the client respective to given unique id.
*
* @param[in] uniqueId Unique identifier for a session
*/
- void addClient(int uniqueId);
+ virtual void addClient(int uniqueId);
/**
* Removes the client respective to given unique id.
*
* @param[in] uniqueId Unique identifier for a session
*/
- void removeClient(int uniqueId);
+ virtual void removeClient(int uniqueId);
/**
* Register a callback to be invoked when the caller required to
@@ -68,7 +68,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t setOnInfoListener(
+ virtual status_t setOnInfoListener(
int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener);
/**
@@ -83,7 +83,7 @@ public:
* @note
* In case of error, return NULL
*/
- DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+ virtual DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
/**
* Get metadata information associated with input content.
@@ -95,7 +95,7 @@ public:
* @note
* In case of error, return NULL
*/
- DrmMetadata* getMetadata(int uniqueId, const String8* path);
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path);
/**
* Check whether the given mimetype or path can be handled
@@ -106,7 +106,7 @@ public:
* @return
* True if DrmManager can handle given path or mime type.
*/
- bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
/**
* Executes given drm information based on its type
@@ -116,7 +116,7 @@ public:
* @return DrmInfoStatus
* instance as a result of processing given input
*/
- DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
/**
* Retrieves necessary information for registration, unregistration or rights
@@ -127,7 +127,7 @@ public:
* @return DrmInfo
* instance as a result of processing given input
*/
- DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
/**
* Save DRM rights to specified rights path
@@ -140,7 +140,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
const String8& rightsPath, const String8& contentPath);
/**
@@ -152,7 +152,7 @@ public:
* @return String8
* Returns mime-type of the original content, such as "video/mpeg"
*/
- String8 getOriginalMimeType(int uniqueId, const String8& path, int fd);
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path, int fd);
/**
* Retrieves the type of the protected object (content, rights, etc..)
@@ -165,7 +165,7 @@ public:
* @return type of the DRM content,
* such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
*/
- int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+ virtual int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
/**
* Check whether the given content has valid rights or not
@@ -176,7 +176,7 @@ public:
* @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);
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action);
/**
* Consumes the rights for a content.
@@ -190,7 +190,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
+ virtual status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
/**
* Informs the DRM engine about the playback actions performed on the DRM files.
@@ -203,7 +203,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t setPlaybackStatus(
+ virtual status_t setPlaybackStatus(
int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
/**
@@ -215,7 +215,7 @@ public:
* @param[in] description Detailed description of the action
* @return true if the action is allowed.
*/
- bool validateAction(
+ virtual bool validateAction(
int uniqueId, const String8& path, int action, const ActionDescription& description);
/**
@@ -226,7 +226,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t removeRights(int uniqueId, const String8& path);
+ virtual status_t removeRights(int uniqueId, const String8& path);
/**
* Removes all the rights information of each plug-in associated with
@@ -236,7 +236,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t removeAllRights(int uniqueId);
+ virtual status_t removeAllRights(int uniqueId);
/**
* This API is for Forward Lock based DRM scheme.
@@ -248,7 +248,7 @@ public:
* @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);
+ virtual int openConvertSession(int uniqueId, const String8& mimeType);
/**
* Accepts and converts the input data which is part of DRM file.
@@ -263,7 +263,7 @@ public:
* 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);
+ virtual DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
/**
* Informs the Drm Agent when there is no more data which need to be converted
@@ -279,7 +279,7 @@ public:
* the application on which offset these signature data
* should be appended.
*/
- DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
/**
* Retrieves all DrmSupportInfo instance that native DRM framework can handle.
@@ -292,7 +292,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+ virtual status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
/**
* Open the decrypt session to decrypt the given protected content
@@ -305,7 +305,7 @@ public:
* @return
* Handle for the decryption session
*/
- sp<DecryptHandle> openDecryptSession(
+ virtual sp<DecryptHandle> openDecryptSession(
int uniqueId, int fd, off64_t offset, off64_t length, const char* mime);
/**
@@ -317,7 +317,7 @@ public:
* @return
* Handle for the decryption session
*/
- sp<DecryptHandle> openDecryptSession(
+ virtual sp<DecryptHandle> openDecryptSession(
int uniqueId, const char* uri, const char* mime);
/**
@@ -329,7 +329,7 @@ public:
* @return
* Handle for the decryption session
*/
- sp<DecryptHandle> openDecryptSession(int uniqueId, const DrmBuffer& buf,
+ virtual sp<DecryptHandle> openDecryptSession(int uniqueId, const DrmBuffer& buf,
const String8& mimeType);
/**
@@ -340,7 +340,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
+ virtual status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
/**
* Initialize decryption for the given unit of the protected content
@@ -352,7 +352,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ virtual status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
int decryptUnitId, const DrmBuffer* headerInfo);
/**
@@ -372,7 +372,7 @@ public:
* DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
* DRM_ERROR_DECRYPT for failure.
*/
- status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ virtual status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
/**
@@ -384,7 +384,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
+ virtual status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
/**
* Reads the specified number of bytes from an open DRM file.
@@ -397,7 +397,7 @@ public:
*
* @return Number of bytes read. Returns -1 for Failure.
*/
- ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ virtual ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
void* buffer, ssize_t numBytes, off64_t offset);
/**
@@ -407,7 +407,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t notify(const DrmInfoEvent& event);
+ virtual status_t notify(const DrmInfoEvent& event);
private:
Mutex mLock;
diff --git a/drm/libdrmframework/include/NoOpDrmManagerClientImpl.h b/drm/libdrmframework/include/NoOpDrmManagerClientImpl.h
new file mode 100644
index 0000000..e8e8f42
--- /dev/null
+++ b/drm/libdrmframework/include/NoOpDrmManagerClientImpl.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NO_OP_DRM_MANAGER_CLIENT_IMPL_H__
+#define __NO_OP_DRM_MANAGER_CLIENT_IMPL_H__
+
+#include "DrmManagerClientImpl.h"
+
+namespace android {
+
+class NoOpDrmManagerClientImpl : public DrmManagerClientImpl {
+public:
+ NoOpDrmManagerClientImpl() { }
+
+ void remove(int uniqueId);
+ void addClient(int uniqueId);
+ void removeClient(int uniqueId);
+ status_t setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener);
+ 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 fd);
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+ status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
+ status_t setPlaybackStatus(
+ int uniqueId, sp<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);
+ sp<DecryptHandle> openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime);
+ sp<DecryptHandle> openDecryptSession(
+ int uniqueId, const char* uri, const char* mime);
+ sp<DecryptHandle> openDecryptSession(int uniqueId, const DrmBuffer& buf,
+ const String8& mimeType);
+ status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
+ status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+ status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+ status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
+ ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+ status_t notify(const DrmInfoEvent& event);
+};
+
+}
+
+#endif // __NO_OP_DRM_MANAGER_CLIENT_IMPL_H
diff --git a/include/soundtrigger/ISoundTrigger.h b/include/soundtrigger/ISoundTrigger.h
new file mode 100644
index 0000000..5fd8eb2
--- /dev/null
+++ b/include/soundtrigger/ISoundTrigger.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_ISOUNDTRIGGER_H
+#define ANDROID_HARDWARE_ISOUNDTRIGGER_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <system/sound_trigger.h>
+
+namespace android {
+
+class ISoundTrigger : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(SoundTrigger);
+
+ virtual void detach() = 0;
+
+ virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
+ sound_model_handle_t *handle) = 0;
+
+ virtual status_t unloadSoundModel(sound_model_handle_t handle) = 0;
+
+ virtual status_t startRecognition(sound_model_handle_t handle,
+ const sp<IMemory>& dataMemory) = 0;
+ virtual status_t stopRecognition(sound_model_handle_t handle) = 0;
+
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSoundTrigger: public BnInterface<ISoundTrigger>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_H
diff --git a/include/soundtrigger/ISoundTriggerClient.h b/include/soundtrigger/ISoundTriggerClient.h
new file mode 100644
index 0000000..7f86d02
--- /dev/null
+++ b/include/soundtrigger/ISoundTriggerClient.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_ISOUNDTRIGGER_CLIENT_H
+#define ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class ISoundTriggerClient : public IInterface
+{
+public:
+
+ DECLARE_META_INTERFACE(SoundTriggerClient);
+
+ virtual void onRecognitionEvent(const sp<IMemory>& eventMemory) = 0;
+
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSoundTriggerClient : public BnInterface<ISoundTriggerClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
diff --git a/include/soundtrigger/ISoundTriggerHwService.h b/include/soundtrigger/ISoundTriggerHwService.h
new file mode 100644
index 0000000..05a764a
--- /dev/null
+++ b/include/soundtrigger/ISoundTriggerHwService.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_ISOUNDTRIGGER_SERVICE_H
+#define ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <system/sound_trigger.h>
+
+namespace android {
+
+class ISoundTrigger;
+class ISoundTriggerClient;
+
+class ISoundTriggerHwService : public IInterface
+{
+public:
+
+ DECLARE_META_INTERFACE(SoundTriggerHwService);
+
+ virtual status_t listModules(struct sound_trigger_module_descriptor *modules,
+ uint32_t *numModules) = 0;
+
+ virtual status_t attach(const sound_trigger_module_handle_t handle,
+ const sp<ISoundTriggerClient>& client,
+ sp<ISoundTrigger>& module) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSoundTriggerHwService: public BnInterface<ISoundTriggerHwService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
new file mode 100644
index 0000000..1f7f286
--- /dev/null
+++ b/include/soundtrigger/SoundTrigger.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_SOUNDTRIGGER_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_H
+
+#include <binder/IBinder.h>
+#include <soundtrigger/SoundTriggerCallback.h>
+#include <soundtrigger/ISoundTrigger.h>
+#include <soundtrigger/ISoundTriggerHwService.h>
+#include <soundtrigger/ISoundTriggerClient.h>
+#include <system/sound_trigger.h>
+
+namespace android {
+
+class MemoryDealer;
+
+class SoundTrigger : public BnSoundTriggerClient,
+ public IBinder::DeathRecipient
+{
+public:
+ static status_t listModules(struct sound_trigger_module_descriptor *modules,
+ uint32_t *numModules);
+ static sp<SoundTrigger> attach(const sound_trigger_module_handle_t module,
+ const sp<SoundTriggerCallback>& callback);
+
+ virtual ~SoundTrigger();
+
+ void detach();
+
+ status_t loadSoundModel(const sp<IMemory>& modelMemory,
+ sound_model_handle_t *handle);
+
+ status_t unloadSoundModel(sound_model_handle_t handle);
+
+ status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory);
+ status_t stopRecognition(sound_model_handle_t handle);
+
+ // BpSoundTriggerClient
+ virtual void onRecognitionEvent(const sp<IMemory>& eventMemory);
+
+ //IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ static status_t stringToGuid(const char *str, sound_trigger_uuid_t *guid);
+ static status_t guidToString(const sound_trigger_uuid_t *guid,
+ char *str, size_t maxLen);
+
+private:
+ SoundTrigger(sound_trigger_module_handle_t module,
+ const sp<SoundTriggerCallback>&);
+ static const sp<ISoundTriggerHwService>& getSoundTriggerHwService();
+
+ Mutex mLock;
+ sp<ISoundTrigger> mISoundTrigger;
+ const sound_trigger_module_handle_t mModule;
+ sp<SoundTriggerCallback> mCallback;
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_SOUNDTRIGGER_H
diff --git a/include/soundtrigger/SoundTriggerCallback.h b/include/soundtrigger/SoundTriggerCallback.h
new file mode 100644
index 0000000..8a5ba02
--- /dev/null
+++ b/include/soundtrigger/SoundTriggerCallback.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_SOUNDTRIGGER_CALLBACK_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
+
+#include <utils/RefBase.h>
+#include <system/sound_trigger.h>
+
+namespace android {
+
+class SoundTriggerCallback : public RefBase
+{
+public:
+
+ SoundTriggerCallback() {}
+ virtual ~SoundTriggerCallback() {}
+
+ virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event) = 0;
+
+ virtual void onServiceDied() = 0;
+
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
diff --git a/media/libcpustats/Android.mk b/media/libcpustats/Android.mk
index b506353..ee283a6 100644
--- a/media/libcpustats/Android.mk
+++ b/media/libcpustats/Android.mk
@@ -1,4 +1,4 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -8,4 +8,6 @@ LOCAL_SRC_FILES := \
LOCAL_MODULE := libcpustats
+LOCAL_CFLAGS := -std=gnu++11 -Werror
+
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libcpustats/ThreadCpuUsage.cpp b/media/libcpustats/ThreadCpuUsage.cpp
index 637402a..cfdcb51 100644
--- a/media/libcpustats/ThreadCpuUsage.cpp
+++ b/media/libcpustats/ThreadCpuUsage.cpp
@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <time.h>
-#include <utils/Debug.h>
#include <utils/Log.h>
#include <cpustats/ThreadCpuUsage.h>
@@ -218,7 +217,7 @@ uint32_t ThreadCpuUsage::getCpukHz(int cpuNum)
#define FREQ_SIZE 64
char freq_path[FREQ_SIZE];
#define FREQ_DIGIT 27
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10);
+ static_assert(MAX_CPU <= 10, "MAX_CPU too large");
#define FREQ_PATH "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq"
strlcpy(freq_path, FREQ_PATH, sizeof(freq_path));
freq_path[FREQ_DIGIT] = cpuNum + '0';
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index a9820e0..194abbb 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -95,7 +95,8 @@ status_t MediaRecorderClient::setPreviewSurface(const sp<IGraphicBufferProducer>
status_t MediaRecorderClient::setVideoSource(int vs)
{
ALOGV("setVideoSource(%d)", vs);
- if (!checkPermission(cameraPermission)) {
+ // Check camera permission for sources other than SURFACE
+ if (vs != VIDEO_SOURCE_SURFACE && !checkPermission(cameraPermission)) {
return PERMISSION_DENIED;
}
Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d8d939a..857e703 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1376,16 +1376,15 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifyPrepareCompleted(err);
- }
-
- int64_t durationUs;
- if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
- sp<NuPlayerDriver> driver = mDriver.promote();
- if (driver != NULL) {
+ // notify duration first, so that it's definitely set when
+ // the app received the "prepare complete" callback.
+ int64_t durationUs;
+ if (mSource->getDuration(&durationUs) == OK) {
driver->notifyDuration(durationUs);
}
+ driver->notifyPrepareCompleted(err);
}
+
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 469c9ca..cfbf282 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -37,6 +37,7 @@ NuPlayer::Decoder::Decoder(
: mNotify(notify),
mNativeWindow(nativeWindow),
mBufferGeneration(0),
+ mPaused(true),
mComponentName("decoder") {
// Every decoder has its own looper because MediaCodec operations
// are blocking, but NuPlayer needs asynchronous operations.
@@ -112,6 +113,7 @@ void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
mOutputBuffers.size());
requestCodecNotification();
+ mPaused = false;
}
void NuPlayer::Decoder::requestCodecNotification() {
@@ -352,6 +354,11 @@ void NuPlayer::Decoder::onFlush() {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatFlushCompleted);
notify->post();
+ mPaused = true;
+}
+
+void NuPlayer::Decoder::onResume() {
+ mPaused = false;
}
void NuPlayer::Decoder::onShutdown() {
@@ -380,6 +387,7 @@ void NuPlayer::Decoder::onShutdown() {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatShutdownCompleted);
notify->post();
+ mPaused = true;
}
void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
@@ -397,7 +405,9 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
case kWhatCodecNotify:
{
if (!isStaleReply(msg)) {
- while (handleAnInputBuffer()) {
+ if (!mPaused) {
+ while (handleAnInputBuffer()) {
+ }
}
while (handleAnOutputBuffer()) {
@@ -430,6 +440,12 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatResume:
+ {
+ onResume();
+ break;
+ }
+
case kWhatShutdown:
{
onShutdown();
@@ -447,7 +463,7 @@ void NuPlayer::Decoder::signalFlush() {
}
void NuPlayer::Decoder::signalResume() {
- // nothing to do
+ (new AMessage(kWhatResume, id()))->post();
}
void NuPlayer::Decoder::initiateShutdown() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 94243fc..2892584 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -87,11 +87,13 @@ private:
void onConfigure(const sp<AMessage> &format);
void onFlush();
+ void onResume();
void onInputBufferFilled(const sp<AMessage> &msg);
void onRenderBuffer(const sp<AMessage> &msg);
void onShutdown();
int32_t mBufferGeneration;
+ bool mPaused;
AString mComponentName;
bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index e4850f0..280b5af 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -284,6 +284,10 @@ status_t NuPlayerDriver::seekTo(int msec) {
case STATE_PREPARED:
{
mStartupSeekTimeUs = seekTimeUs;
+ // pretend that the seek completed. It will actually happen when starting playback.
+ // TODO: actually perform the seek here, so the player is ready to go at the new
+ // location
+ notifySeekComplete();
break;
}
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 4d9a1fa..4d14904 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -438,7 +438,7 @@ void NBLog::Reader::dump(int fd, size_t indent)
void NBLog::Reader::dumpLine(const String8& timestamp, String8& body)
{
if (mFd >= 0) {
- fdprintf(mFd, "%.*s%s %s\n", mIndent, "", timestamp.string(), body.string());
+ dprintf(mFd, "%.*s%s %s\n", mIndent, "", timestamp.string(), body.string());
} else {
ALOGI("%.*s%s %s", mIndent, "", timestamp.string(), body.string());
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index aabe0ec..297f4fc 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2510,8 +2510,9 @@ status_t MPEG4Extractor::verifyTrack(Track *track) {
}
}
- if (!track->sampleTable->isValid()) {
+ if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
// Make sure we have all the metadata we need.
+ ALOGE("stbl atom missing/invalid.");
return ERROR_MALFORMED;
}
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp
index 11b80bf..8af0880 100644
--- a/media/libstagefright/MediaBuffer.cpp
+++ b/media/libstagefright/MediaBuffer.cpp
@@ -27,7 +27,6 @@
#include <media/stagefright/MetaData.h>
#include <ui/GraphicBuffer.h>
-#include <sys/atomics.h>
namespace android {
@@ -92,7 +91,7 @@ void MediaBuffer::release() {
return;
}
- int prevCount = __atomic_dec(&mRefCount);
+ int prevCount = __sync_fetch_and_sub(&mRefCount, 1);
if (prevCount == 1) {
if (mObserver == NULL) {
delete this;
@@ -112,7 +111,7 @@ void MediaBuffer::claim() {
}
void MediaBuffer::add_ref() {
- (void) __atomic_inc(&mRefCount);
+ (void) __sync_fetch_and_add(&mRefCount, 1);
}
void *MediaBuffer::data() const {
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 49ff238..afb00aa 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -3,7 +3,8 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- SoftAAC2.cpp
+ SoftAAC2.cpp \
+ DrcPresModeWrap.cpp
LOCAL_C_INCLUDES := \
frameworks/av/media/libstagefright/include \
diff --git a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
new file mode 100644
index 0000000..129ad65
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "DrcPresModeWrap.h"
+
+#include <assert.h>
+
+#define LOG_TAG "SoftAAC2_DrcWrapper"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+//#define DRC_PRES_MODE_WRAP_DEBUG
+
+#define GPM_ENCODER_TARGET_LEVEL 64
+#define MAX_TARGET_LEVEL 64
+
+CDrcPresModeWrapper::CDrcPresModeWrapper()
+{
+ mDataUpdate = true;
+
+ /* Data from streamInfo. */
+ /* Initialized to the same values as in the aac decoder */
+ mStreamPRL = -1;
+ mStreamDRCPresMode = -1;
+ mStreamNrAACChan = 0;
+ mStreamNrOutChan = 0;
+
+ /* Desired values (set by user). */
+ /* Initialized to the same values as in the aac decoder */
+ mDesTarget = -1;
+ mDesAttFactor = 0;
+ mDesBoostFactor = 0;
+ mDesHeavy = 0;
+
+ mEncoderTarget = -1;
+
+ /* Values from last time. */
+ /* Initialized to the same values as the desired values */
+ mLastTarget = -1;
+ mLastAttFactor = 0;
+ mLastBoostFactor = 0;
+ mLastHeavy = 0;
+}
+
+CDrcPresModeWrapper::~CDrcPresModeWrapper()
+{
+}
+
+void
+CDrcPresModeWrapper::setDecoderHandle(const HANDLE_AACDECODER handle)
+{
+ mHandleDecoder = handle;
+}
+
+void
+CDrcPresModeWrapper::submitStreamData(CStreamInfo* pStreamInfo)
+{
+ assert(pStreamInfo);
+
+ if (mStreamPRL != pStreamInfo->drcProgRefLev) {
+ mStreamPRL = pStreamInfo->drcProgRefLev;
+ mDataUpdate = true;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ ALOGV("DRC presentation mode wrapper: drcProgRefLev is %d\n", mStreamPRL);
+#endif
+ }
+
+ if (mStreamDRCPresMode != pStreamInfo->drcPresMode) {
+ mStreamDRCPresMode = pStreamInfo->drcPresMode;
+ mDataUpdate = true;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ ALOGV("DRC presentation mode wrapper: drcPresMode is %d\n", mStreamDRCPresMode);
+#endif
+ }
+
+ if (mStreamNrAACChan != pStreamInfo->aacNumChannels) {
+ mStreamNrAACChan = pStreamInfo->aacNumChannels;
+ mDataUpdate = true;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ ALOGV("DRC presentation mode wrapper: aacNumChannels is %d\n", mStreamNrAACChan);
+#endif
+ }
+
+ if (mStreamNrOutChan != pStreamInfo->numChannels) {
+ mStreamNrOutChan = pStreamInfo->numChannels;
+ mDataUpdate = true;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ ALOGV("DRC presentation mode wrapper: numChannels is %d\n", mStreamNrOutChan);
+#endif
+ }
+
+
+
+ if (mStreamNrOutChan<mStreamNrAACChan) {
+ mIsDownmix = true;
+ } else {
+ mIsDownmix = false;
+ }
+
+ if (mIsDownmix && (mStreamNrOutChan == 1)) {
+ mIsMonoDownmix = true;
+ } else {
+ mIsMonoDownmix = false;
+ }
+
+ if (mIsDownmix && mStreamNrOutChan == 2){
+ mIsStereoDownmix = true;
+ } else {
+ mIsStereoDownmix = false;
+ }
+
+}
+
+void
+CDrcPresModeWrapper::setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value)
+{
+ switch (param) {
+ case DRC_PRES_MODE_WRAP_DESIRED_TARGET:
+ mDesTarget = value;
+ break;
+ case DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR:
+ mDesAttFactor = value;
+ break;
+ case DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR:
+ mDesBoostFactor = value;
+ break;
+ case DRC_PRES_MODE_WRAP_DESIRED_HEAVY:
+ mDesHeavy = value;
+ break;
+ case DRC_PRES_MODE_WRAP_ENCODER_TARGET:
+ mEncoderTarget = value;
+ break;
+ default:
+ break;
+ }
+ mDataUpdate = true;
+}
+
+void
+CDrcPresModeWrapper::update()
+{
+ // Get Data from Decoder
+ int progRefLevel = mStreamPRL;
+ int drcPresMode = mStreamDRCPresMode;
+
+ // by default, do as desired
+ int newTarget = mDesTarget;
+ int newAttFactor = mDesAttFactor;
+ int newBoostFactor = mDesBoostFactor;
+ int newHeavy = mDesHeavy;
+
+ if (mDataUpdate) {
+ // sanity check
+ if (mDesTarget < MAX_TARGET_LEVEL){
+ mDesTarget = MAX_TARGET_LEVEL; // limit target level to -16 dB or below
+ newTarget = MAX_TARGET_LEVEL;
+ }
+
+ if (mEncoderTarget != -1) {
+ if (mDesTarget<124) { // if target level > -31 dB
+ if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) {
+ // no stereo or mono downmixing, calculated scaling of light DRC
+ /* use as little compression as possible */
+ newAttFactor = 0;
+ newBoostFactor = 0;
+ if (mDesTarget<progRefLevel) { // if target level > PRL
+ if (mEncoderTarget < mDesTarget) { // if mEncoderTarget > target level
+ // mEncoderTarget > target level > PRL
+ int calcFactor;
+ float calcFactor_norm;
+ // 0.0f < calcFactor_norm < 1.0f
+ calcFactor_norm = (float)(mDesTarget - progRefLevel) /
+ (float)(mEncoderTarget - progRefLevel);
+ calcFactor = (int)(calcFactor_norm*127.0f); // 0 <= calcFactor < 127
+ // calcFactor is the lower limit
+ newAttFactor = (calcFactor>newAttFactor) ? calcFactor : newAttFactor;
+ // new AttFactor will be always = calcFactor, as it is set to 0 before.
+ newBoostFactor = newAttFactor;
+ } else {
+ /* target level > mEncoderTarget > PRL */
+ // newTDLimiterEnable = 1;
+ // the time domain limiter must always be active in this case.
+ // It is assumed that the framework activates it by default
+ newAttFactor = 127;
+ newBoostFactor = 127;
+ }
+ } else { // target level <= PRL
+ // no restrictions required
+ // newAttFactor = newAttFactor;
+ }
+ } else { // downmixing
+ // if target level > -23 dB or mono downmix
+ if ( (mDesTarget<92) || mIsMonoDownmix ) {
+ newHeavy = 1;
+ } else {
+ // we perform a downmix, so, we need at least full light DRC
+ newAttFactor = 127;
+ }
+ }
+ } else { // target level <= -31 dB
+ // playback -31 dB: light DRC only needed if we perform downmixing
+ if (mIsDownmix) { // we do downmixing
+ newAttFactor = 127;
+ }
+ }
+ }
+ else { // handle other used encoder target levels
+
+ // Sanity check: DRC presentation mode is only specified for max. 5.1 channels
+ if (mStreamNrAACChan > 6) {
+ drcPresMode = 0;
+ }
+
+ switch (drcPresMode) {
+ case 0:
+ default: // presentation mode not indicated
+ {
+
+ if (mDesTarget<124) { // if target level > -31 dB
+ // no stereo or mono downmixing
+ if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) {
+ if (mDesTarget<progRefLevel) { // if target level > PRL
+ // newTDLimiterEnable = 1;
+ // the time domain limiter must always be active in this case.
+ // It is assumed that the framework activates it by default
+ newAttFactor = 127; // at least, use light compression
+ } else { // target level <= PRL
+ // no restrictions required
+ // newAttFactor = newAttFactor;
+ }
+ } else { // downmixing
+ // newTDLimiterEnable = 1;
+ // the time domain limiter must always be active in this case.
+ // It is assumed that the framework activates it by default
+
+ // if target level > -23 dB or mono downmix
+ if ( (mDesTarget < 92) || mIsMonoDownmix ) {
+ newHeavy = 1;
+ } else{
+ // we perform a downmix, so, we need at least full light DRC
+ newAttFactor = 127;
+ }
+ }
+ } else { // target level <= -31 dB
+ if (mIsDownmix) { // we do downmixing.
+ // newTDLimiterEnable = 1;
+ // the time domain limiter must always be active in this case.
+ // It is assumed that the framework activates it by default
+ newAttFactor = 127;
+ }
+ }
+ }
+ break;
+
+ // Presentation mode 1 and 2 according to ETSI TS 101 154:
+ // Digital Video Broadcasting (DVB); Specification for the use of Video and Audio Coding
+ // in Broadcasting Applications based on the MPEG-2 Transport Stream,
+ // section C.5.4., "Decoding", and Table C.33
+ // ISO DRC -> newHeavy = 0 (Use light compression, MPEG-style)
+ // Compression_value -> newHeavy = 1 (Use heavy compression, DVB-style)
+ // scaling restricted -> newAttFactor = 127
+
+ case 1: // presentation mode 1, Light:-31/Heavy:-23
+ {
+ if (mDesTarget < 124) { // if target level > -31 dB
+ // playback up to -23 dB
+ newHeavy = 1;
+ } else { // target level <= -31 dB
+ // playback -31 dB
+ if (mIsDownmix) { // we do downmixing.
+ newAttFactor = 127;
+ }
+ }
+ }
+ break;
+
+ case 2: // presentation mode 2, Light:-23/Heavy:-23
+ {
+ if (mDesTarget < 124) { // if target level > -31 dB
+ // playback up to -23 dB
+ if (mIsMonoDownmix) { // if mono downmix
+ newHeavy = 1;
+ } else {
+ newHeavy = 0;
+ newAttFactor = 127;
+ }
+ } else { // target level <= -31 dB
+ // playback -31 dB
+ newHeavy = 0;
+ if (mIsDownmix) { // we do downmixing.
+ newAttFactor = 127;
+ }
+ }
+ }
+ break;
+
+ } // switch()
+ } // if (mEncoderTarget == GPM_ENCODER_TARGET_LEVEL)
+
+ // sanity again
+ if (newHeavy == 1) {
+ newBoostFactor=127; // not really needed as the same would be done by the decoder anyway
+ newAttFactor = 127;
+ }
+
+ // update the decoder
+ if (newTarget != mLastTarget) {
+ aacDecoder_SetParam(mHandleDecoder, AAC_DRC_REFERENCE_LEVEL, newTarget);
+ mLastTarget = newTarget;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ if (newTarget != mDesTarget)
+ ALOGV("DRC presentation mode wrapper: forced target level to %d (from %d)\n", newTarget, mDesTarget);
+ else
+ ALOGV("DRC presentation mode wrapper: set target level to %d\n", newTarget);
+#endif
+ }
+
+ if (newAttFactor != mLastAttFactor) {
+ aacDecoder_SetParam(mHandleDecoder, AAC_DRC_ATTENUATION_FACTOR, newAttFactor);
+ mLastAttFactor = newAttFactor;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ if (newAttFactor != mDesAttFactor)
+ ALOGV("DRC presentation mode wrapper: forced attenuation factor to %d (from %d)\n", newAttFactor, mDesAttFactor);
+ else
+ ALOGV("DRC presentation mode wrapper: set attenuation factor to %d\n", newAttFactor);
+#endif
+ }
+
+ if (newBoostFactor != mLastBoostFactor) {
+ aacDecoder_SetParam(mHandleDecoder, AAC_DRC_BOOST_FACTOR, newBoostFactor);
+ mLastBoostFactor = newBoostFactor;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ if (newBoostFactor != mDesBoostFactor)
+ ALOGV("DRC presentation mode wrapper: forced boost factor to %d (from %d)\n",
+ newBoostFactor, mDesBoostFactor);
+ else
+ ALOGV("DRC presentation mode wrapper: set boost factor to %d\n", newBoostFactor);
+#endif
+ }
+
+ if (newHeavy != mLastHeavy) {
+ aacDecoder_SetParam(mHandleDecoder, AAC_DRC_HEAVY_COMPRESSION, newHeavy);
+ mLastHeavy = newHeavy;
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ if (newHeavy != mDesHeavy)
+ ALOGV("DRC presentation mode wrapper: forced heavy compression to %d (from %d)\n",
+ newHeavy, mDesHeavy);
+ else
+ ALOGV("DRC presentation mode wrapper: set heavy compression to %d\n", newHeavy);
+#endif
+ }
+
+#ifdef DRC_PRES_MODE_WRAP_DEBUG
+ ALOGV("DRC config: tgt_lev: %3d, cut: %3d, boost: %3d, heavy: %d\n", newTarget,
+ newAttFactor, newBoostFactor, newHeavy);
+#endif
+ mDataUpdate = false;
+
+ } // if (mDataUpdate)
+}
diff --git a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.h b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.h
new file mode 100644
index 0000000..f0b6cf2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+#include "aacdecoder_lib.h"
+
+typedef enum
+{
+ DRC_PRES_MODE_WRAP_DESIRED_TARGET = 0x0000,
+ DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR = 0x0001,
+ DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR = 0x0002,
+ DRC_PRES_MODE_WRAP_DESIRED_HEAVY = 0x0003,
+ DRC_PRES_MODE_WRAP_ENCODER_TARGET = 0x0004
+} DRC_PRES_MODE_WRAP_PARAM;
+
+
+class CDrcPresModeWrapper {
+public:
+ CDrcPresModeWrapper();
+ ~CDrcPresModeWrapper();
+ void setDecoderHandle(const HANDLE_AACDECODER handle);
+ void setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value);
+ void submitStreamData(CStreamInfo*);
+ void update();
+
+protected:
+ HANDLE_AACDECODER mHandleDecoder;
+ int mDesTarget;
+ int mDesAttFactor;
+ int mDesBoostFactor;
+ int mDesHeavy;
+
+ int mEncoderTarget;
+
+ int mLastTarget;
+ int mLastAttFactor;
+ int mLastBoostFactor;
+ int mLastHeavy;
+
+ SCHAR mStreamPRL;
+ SCHAR mStreamDRCPresMode;
+ INT mStreamNrAACChan;
+ INT mStreamNrOutChan;
+
+ bool mIsDownmix;
+ bool mIsMonoDownmix;
+ bool mIsStereoDownmix;
+
+ bool mDataUpdate;
+};
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 532e36f..64bf2b6 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -25,16 +25,22 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
+#include <math.h>
+
#define FILEREAD_MAX_LAYERS 2
#define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* 64*-0.25dB = -16 dB below full scale for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* switch for heavy compression for mobile conf */
+#define DRC_DEFAULT_MOBILE_ENC_LEVEL -1 /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
#define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */
// names of properties that can be used to override the default DRC settings
#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
#define PROP_DRC_OVERRIDE_CUT "aac_drc_cut"
#define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost"
+#define PROP_DRC_OVERRIDE_HEAVY "aac_drc_heavy"
+#define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
namespace android {
@@ -57,18 +63,19 @@ SoftAAC2::SoftAAC2(
mStreamInfo(NULL),
mIsADTS(false),
mInputBufferCount(0),
+ mOutputBufferCount(0),
mSignalledError(false),
- mSawInputEos(false),
- mSignalledOutputEos(false),
- mAnchorTimeUs(0),
- mNumSamplesOutput(0),
mOutputPortSettingsChange(NONE) {
+ for (unsigned int i = 0; i < kNumDelayBlocksMax; i++) {
+ mAnchorTimeUs[i] = 0;
+ }
initPorts();
CHECK_EQ(initDecoder(), (status_t)OK);
}
SoftAAC2::~SoftAAC2() {
aacDecoder_Close(mAACDecoder);
+ delete mOutputDelayRingBuffer;
}
void SoftAAC2::initPorts() {
@@ -121,36 +128,72 @@ status_t SoftAAC2::initDecoder() {
status = OK;
}
}
- mDecoderHasData = false;
- // for streams that contain metadata, use the mobile profile DRC settings unless overridden
- // by platform properties:
+ mEndOfInput = false;
+ mEndOfOutput = false;
+ mOutputDelayCompensated = 0;
+ mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax;
+ mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize];
+ mOutputDelayRingBufferWritePos = 0;
+ mOutputDelayRingBufferReadPos = 0;
+
+ if (mAACDecoder == NULL) {
+ ALOGE("AAC decoder is null. TODO: Can not call aacDecoder_SetParam in the following code");
+ }
+
+ //aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 0);
+
+ //init DRC wrapper
+ mDrcWrap.setDecoderHandle(mAACDecoder);
+ mDrcWrap.submitStreamData(mStreamInfo);
+
+ // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties
+ // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone)
char value[PROPERTY_VALUE_MAX];
- // * AAC_DRC_REFERENCE_LEVEL
+ // DRC_PRES_MODE_WRAP_DESIRED_TARGET
if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
unsigned refLevel = atoi(value);
- ALOGV("AAC decoder using AAC_DRC_REFERENCE_LEVEL of %d instead of %d",
- refLevel, DRC_DEFAULT_MOBILE_REF_LEVEL);
- aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, refLevel);
+ ALOGV("AAC decoder using desired DRC target reference level of %d instead of %d", refLevel,
+ DRC_DEFAULT_MOBILE_REF_LEVEL);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, refLevel);
} else {
- aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, DRC_DEFAULT_MOBILE_REF_LEVEL);
}
- // * AAC_DRC_ATTENUATION_FACTOR
+ // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
unsigned cut = atoi(value);
- ALOGV("AAC decoder using AAC_DRC_ATTENUATION_FACTOR of %d instead of %d",
- cut, DRC_DEFAULT_MOBILE_DRC_CUT);
- aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, cut);
+ ALOGV("AAC decoder using desired DRC attenuation factor of %d instead of %d", cut,
+ DRC_DEFAULT_MOBILE_DRC_CUT);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, cut);
} else {
- aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
}
- // * AAC_DRC_BOOST_FACTOR (note: no default, using cut)
+ // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
unsigned boost = atoi(value);
- ALOGV("AAC decoder using AAC_DRC_BOOST_FACTOR of %d", boost);
- aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, boost);
+ ALOGV("AAC decoder using desired DRC boost factor of %d instead of %d", boost,
+ DRC_DEFAULT_MOBILE_DRC_BOOST);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, boost);
+ } else {
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
+ }
+ // DRC_PRES_MODE_WRAP_DESIRED_HEAVY
+ if (property_get(PROP_DRC_OVERRIDE_HEAVY, value, NULL)) {
+ unsigned heavy = atoi(value);
+ ALOGV("AAC decoder using desried DRC heavy compression switch of %d instead of %d", heavy,
+ DRC_DEFAULT_MOBILE_DRC_HEAVY);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, heavy);
} else {
- aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
+ }
+ // DRC_PRES_MODE_WRAP_ENCODER_TARGET
+ if (property_get(PROP_DRC_OVERRIDE_ENC_LEVEL, value, NULL)) {
+ unsigned encoderRefLevel = atoi(value);
+ ALOGV("AAC decoder using encoder-side DRC reference level of %d instead of %d",
+ encoderRefLevel, DRC_DEFAULT_MOBILE_ENC_LEVEL);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, encoderRefLevel);
+ } else {
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, DRC_DEFAULT_MOBILE_ENC_LEVEL);
}
return status;
@@ -290,19 +333,101 @@ bool SoftAAC2::isConfigured() const {
return mInputBufferCount > 0;
}
-void SoftAAC2::maybeConfigureDownmix() const {
- if (mStreamInfo->numChannels > 2) {
- char value[PROPERTY_VALUE_MAX];
- if (!(property_get("media.aac_51_output_enabled", value, NULL) &&
- (!strcmp(value, "1") || !strcasecmp(value, "true")))) {
- ALOGI("Downmixing multichannel AAC to stereo");
- aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, 2);
- mStreamInfo->numChannels = 2;
- // By default, the decoder creates a 5.1 channel downmix signal
- // for seven and eight channel input streams. To enable 6.1 and 7.1 channel output
- // use aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1)
+void SoftAAC2::configureDownmix() const {
+ char value[PROPERTY_VALUE_MAX];
+ if (!(property_get("media.aac_51_output_enabled", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true")))) {
+ ALOGI("limiting to stereo output");
+ aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, 2);
+ // By default, the decoder creates a 5.1 channel downmix signal
+ // for seven and eight channel input streams. To enable 6.1 and 7.1 channel output
+ // use aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1)
+ }
+}
+
+bool SoftAAC2::outputDelayRingBufferPutSamples(INT_PCM *samples, int32_t numSamples) {
+ if (mOutputDelayRingBufferWritePos + numSamples <= mOutputDelayRingBufferSize
+ && (mOutputDelayRingBufferReadPos <= mOutputDelayRingBufferWritePos
+ || mOutputDelayRingBufferReadPos > mOutputDelayRingBufferWritePos + numSamples)) {
+ // faster memcopy loop without checks, if the preconditions allow this
+ for (int32_t i = 0; i < numSamples; i++) {
+ mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos++] = samples[i];
+ }
+
+ if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
+ mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
+ }
+ if (mOutputDelayRingBufferWritePos == mOutputDelayRingBufferReadPos) {
+ ALOGE("RING BUFFER OVERFLOW");
+ return false;
+ }
+ } else {
+ ALOGV("slow SoftAAC2::outputDelayRingBufferPutSamples()");
+
+ for (int32_t i = 0; i < numSamples; i++) {
+ mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos] = samples[i];
+ mOutputDelayRingBufferWritePos++;
+ if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
+ mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
+ }
+ if (mOutputDelayRingBufferWritePos == mOutputDelayRingBufferReadPos) {
+ ALOGE("RING BUFFER OVERFLOW");
+ return false;
+ }
}
}
+ return true;
+}
+
+int32_t SoftAAC2::outputDelayRingBufferGetSamples(INT_PCM *samples, int32_t numSamples) {
+ if (mOutputDelayRingBufferReadPos + numSamples <= mOutputDelayRingBufferSize
+ && (mOutputDelayRingBufferWritePos < mOutputDelayRingBufferReadPos
+ || mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferReadPos + numSamples)) {
+ // faster memcopy loop without checks, if the preconditions allow this
+ if (samples != 0) {
+ for (int32_t i = 0; i < numSamples; i++) {
+ samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++];
+ }
+ } else {
+ mOutputDelayRingBufferReadPos += numSamples;
+ }
+ if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
+ mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
+ }
+ } else {
+ ALOGV("slow SoftAAC2::outputDelayRingBufferGetSamples()");
+
+ for (int32_t i = 0; i < numSamples; i++) {
+ if (mOutputDelayRingBufferWritePos == mOutputDelayRingBufferReadPos) {
+ ALOGE("RING BUFFER UNDERRUN");
+ return -1;
+ }
+ if (samples != 0) {
+ samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos];
+ }
+ mOutputDelayRingBufferReadPos++;
+ if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
+ mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
+ }
+ }
+ }
+ return numSamples;
+}
+
+int32_t SoftAAC2::outputDelayRingBufferSamplesAvailable() {
+ int32_t available = mOutputDelayRingBufferWritePos - mOutputDelayRingBufferReadPos;
+ if (available < 0) {
+ available += mOutputDelayRingBufferSize;
+ }
+ if (available < 0) {
+ ALOGE("FATAL RING BUFFER ERROR");
+ return 0;
+ }
+ return available;
+}
+
+int32_t SoftAAC2::outputDelayRingBufferSamplesLeft() {
+ return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable();
}
void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
@@ -318,12 +443,11 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
List<BufferInfo *> &outQueue = getPortQueue(1);
if (portIndex == 0 && mInputBufferCount == 0) {
- ++mInputBufferCount;
- BufferInfo *info = *inQueue.begin();
- OMX_BUFFERHEADERTYPE *header = info->mHeader;
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
- inBuffer[0] = header->pBuffer + header->nOffset;
- inBufferLength[0] = header->nFilledLen;
+ inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
+ inBufferLength[0] = inHeader->nFilledLen;
AAC_DECODER_ERROR decoderErr =
aacDecoder_ConfigRaw(mAACDecoder,
@@ -331,19 +455,25 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
inBufferLength);
if (decoderErr != AAC_DEC_OK) {
+ ALOGW("aacDecoder_ConfigRaw decoderErr = 0x%4.4x", decoderErr);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
return;
}
+ mInputBufferCount++;
+ mOutputBufferCount++; // fake increase of outputBufferCount to keep the counters aligned
+
+ inInfo->mOwnedByUs = false;
inQueue.erase(inQueue.begin());
- info->mOwnedByUs = false;
- notifyEmptyBufferDone(header);
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ configureDownmix();
// Only send out port settings changed event if both sample rate
// and numChannels are valid.
if (mStreamInfo->sampleRate && mStreamInfo->numChannels) {
- maybeConfigureDownmix();
ALOGI("Initially configuring decoder: %d Hz, %d channels",
mStreamInfo->sampleRate,
mStreamInfo->numChannels);
@@ -355,202 +485,304 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
return;
}
- while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
- BufferInfo *inInfo = NULL;
- OMX_BUFFERHEADERTYPE *inHeader = NULL;
+ while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) {
if (!inQueue.empty()) {
- inInfo = *inQueue.begin();
- inHeader = inInfo->mHeader;
- }
+ INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
- BufferInfo *outInfo = *outQueue.begin();
- OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
- outHeader->nFlags = 0;
-
- if (inHeader) {
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
- mSawInputEos = true;
+ mEndOfInput = true;
+ } else {
+ mEndOfInput = false;
}
-
- if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
- mAnchorTimeUs = inHeader->nTimeStamp;
- mNumSamplesOutput = 0;
+ if (inHeader->nOffset == 0) { // TODO: does nOffset != 0 happen?
+ mAnchorTimeUs[mInputBufferCount % kNumDelayBlocksMax] =
+ inHeader->nTimeStamp;
}
- if (mIsADTS && inHeader->nFilledLen) {
- size_t adtsHeaderSize = 0;
- // skip 30 bits, aac_frame_length follows.
- // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ } else {
+ if (mIsADTS) {
+ size_t adtsHeaderSize = 0;
+ // skip 30 bits, aac_frame_length follows.
+ // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
- const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset;
+ const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset;
- bool signalError = false;
- if (inHeader->nFilledLen < 7) {
- ALOGE("Audio data too short to contain even the ADTS header. "
- "Got %d bytes.", inHeader->nFilledLen);
- hexdump(adtsHeader, inHeader->nFilledLen);
- signalError = true;
- } else {
- bool protectionAbsent = (adtsHeader[1] & 1);
-
- unsigned aac_frame_length =
- ((adtsHeader[3] & 3) << 11)
- | (adtsHeader[4] << 3)
- | (adtsHeader[5] >> 5);
-
- if (inHeader->nFilledLen < aac_frame_length) {
- ALOGE("Not enough audio data for the complete frame. "
- "Got %d bytes, frame size according to the ADTS "
- "header is %u bytes.",
- inHeader->nFilledLen, aac_frame_length);
+ bool signalError = false;
+ if (inHeader->nFilledLen < 7) {
+ ALOGE("Audio data too short to contain even the ADTS header. "
+ "Got %d bytes.", inHeader->nFilledLen);
hexdump(adtsHeader, inHeader->nFilledLen);
signalError = true;
} else {
- adtsHeaderSize = (protectionAbsent ? 7 : 9);
+ bool protectionAbsent = (adtsHeader[1] & 1);
+
+ unsigned aac_frame_length =
+ ((adtsHeader[3] & 3) << 11)
+ | (adtsHeader[4] << 3)
+ | (adtsHeader[5] >> 5);
+
+ if (inHeader->nFilledLen < aac_frame_length) {
+ ALOGE("Not enough audio data for the complete frame. "
+ "Got %d bytes, frame size according to the ADTS "
+ "header is %u bytes.",
+ inHeader->nFilledLen, aac_frame_length);
+ hexdump(adtsHeader, inHeader->nFilledLen);
+ signalError = true;
+ } else {
+ adtsHeaderSize = (protectionAbsent ? 7 : 9);
+
+ inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
+ inBufferLength[0] = aac_frame_length - adtsHeaderSize;
+
+ inHeader->nOffset += adtsHeaderSize;
+ inHeader->nFilledLen -= adtsHeaderSize;
+ }
+ }
+
+ if (signalError) {
+ mSignalledError = true;
- inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize;
- inBufferLength[0] = aac_frame_length - adtsHeaderSize;
+ notify(OMX_EventError,
+ OMX_ErrorStreamCorrupt,
+ ERROR_MALFORMED,
+ NULL);
- inHeader->nOffset += adtsHeaderSize;
- inHeader->nFilledLen -= adtsHeaderSize;
+ return;
}
+ } else {
+ inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
+ inBufferLength[0] = inHeader->nFilledLen;
}
- if (signalError) {
- mSignalledError = true;
+ // Fill and decode
+ bytesValid[0] = inBufferLength[0];
+
+ INT prevSampleRate = mStreamInfo->sampleRate;
+ INT prevNumChannels = mStreamInfo->numChannels;
+
+ aacDecoder_Fill(mAACDecoder,
+ inBuffer,
+ inBufferLength,
+ bytesValid);
- notify(OMX_EventError,
- OMX_ErrorStreamCorrupt,
- ERROR_MALFORMED,
- NULL);
+ // run DRC check
+ mDrcWrap.submitStreamData(mStreamInfo);
+ mDrcWrap.update();
+ AAC_DECODER_ERROR decoderErr =
+ aacDecoder_DecodeFrame(mAACDecoder,
+ tmpOutBuffer,
+ 2048 * MAX_CHANNEL_COUNT,
+ 0 /* flags */);
+
+ if (decoderErr != AAC_DEC_OK) {
+ ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
+ }
+
+ if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
+ ALOGE("AAC_DEC_NOT_ENOUGH_BITS should never happen");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
return;
}
- } else {
- inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
- inBufferLength[0] = inHeader->nFilledLen;
- }
- } else {
- inBufferLength[0] = 0;
- }
- // Fill and decode
- INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(
- outHeader->pBuffer + outHeader->nOffset);
-
- bytesValid[0] = inBufferLength[0];
-
- int prevSampleRate = mStreamInfo->sampleRate;
- int prevNumChannels = mStreamInfo->numChannels;
-
- AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS;
- while ((bytesValid[0] > 0 || mSawInputEos) && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
- mDecoderHasData |= (bytesValid[0] > 0);
- aacDecoder_Fill(mAACDecoder,
- inBuffer,
- inBufferLength,
- bytesValid);
-
- decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
- outBuffer,
- outHeader->nAllocLen,
- 0 /* flags */);
- if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
- if (mSawInputEos && bytesValid[0] <= 0) {
- if (mDecoderHasData) {
- // flush out the decoder's delayed data by calling DecodeFrame
- // one more time, with the AACDEC_FLUSH flag set
- decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
- outBuffer,
- outHeader->nAllocLen,
- AACDEC_FLUSH);
- mDecoderHasData = false;
+ if (bytesValid[0] != 0) {
+ ALOGE("bytesValid[0] != 0 should never happen");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
+ size_t numOutBytes =
+ mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
+
+ if (decoderErr == AAC_DEC_OK) {
+ if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
+ mStreamInfo->frameSize * mStreamInfo->numChannels)) {
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
}
- outHeader->nFlags = OMX_BUFFERFLAG_EOS;
- mSignalledOutputEos = true;
- break;
+ UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
+ inHeader->nFilledLen -= inBufferUsedLength;
+ inHeader->nOffset += inBufferUsedLength;
} else {
- ALOGW("Not enough bits, bytesValid %d", bytesValid[0]);
- }
- }
- }
+ ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr);
- size_t numOutBytes =
- mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
+ memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow
- if (inHeader) {
- if (decoderErr == AAC_DEC_OK) {
- UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
- inHeader->nFilledLen -= inBufferUsedLength;
- inHeader->nOffset += inBufferUsedLength;
- } else {
- ALOGW("AAC decoder returned error %d, substituting silence",
- decoderErr);
+ if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
+ mStreamInfo->frameSize * mStreamInfo->numChannels)) {
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
- memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes);
+ // Discard input buffer.
+ inHeader->nFilledLen = 0;
- // Discard input buffer.
- inHeader->nFilledLen = 0;
+ aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
+ // fall through
+ }
- // fall through
+ /*
+ * 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 (mOutputBufferCount > 1) {
+ if (mStreamInfo->sampleRate != prevSampleRate ||
+ mStreamInfo->numChannels != prevNumChannels) {
+ ALOGE("can not reconfigure AAC output");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
+ }
+ if (mInputBufferCount <= 2) { // TODO: <= 1
+ if (mStreamInfo->sampleRate != prevSampleRate ||
+ mStreamInfo->numChannels != prevNumChannels) {
+ ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
+ prevSampleRate, mStreamInfo->sampleRate,
+ prevNumChannels, mStreamInfo->numChannels);
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ mInputBufferCount++;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+ return;
+ }
+ } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
+ ALOGW("Invalid AAC stream");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ mInputBufferCount++;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ } else {
+ ALOGW("inHeader->nFilledLen = %d", inHeader->nFilledLen);
+ }
}
+ }
- if (inHeader->nFilledLen == 0) {
- inInfo->mOwnedByUs = false;
- inQueue.erase(inQueue.begin());
- inInfo = NULL;
- notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
+ int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
+
+ if (!mEndOfInput && mOutputDelayCompensated < outputDelay) {
+ // discard outputDelay at the beginning
+ int32_t toCompensate = outputDelay - mOutputDelayCompensated;
+ int32_t discard = outputDelayRingBufferSamplesAvailable();
+ if (discard > toCompensate) {
+ discard = toCompensate;
}
+ int32_t discarded = outputDelayRingBufferGetSamples(0, discard);
+ mOutputDelayCompensated += discarded;
+ continue;
}
- /*
- * 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 (mInputBufferCount <= 2) {
- if (mStreamInfo->sampleRate != prevSampleRate ||
- mStreamInfo->numChannels != prevNumChannels) {
- maybeConfigureDownmix();
- ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
- prevSampleRate, mStreamInfo->sampleRate,
- prevNumChannels, mStreamInfo->numChannels);
-
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- return;
+ if (mEndOfInput) {
+ while (mOutputDelayCompensated > 0) {
+ // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
+ INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
+
+ // run DRC check
+ mDrcWrap.submitStreamData(mStreamInfo);
+ mDrcWrap.update();
+
+ AAC_DECODER_ERROR decoderErr =
+ aacDecoder_DecodeFrame(mAACDecoder,
+ tmpOutBuffer,
+ 2048 * MAX_CHANNEL_COUNT,
+ AACDEC_FLUSH);
+ if (decoderErr != AAC_DEC_OK) {
+ ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
+ }
+
+ int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
+ if (tmpOutBufferSamples > mOutputDelayCompensated) {
+ tmpOutBufferSamples = mOutputDelayCompensated;
+ }
+ outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
+ mOutputDelayCompensated -= tmpOutBufferSamples;
}
- } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
- ALOGW("Invalid AAC stream");
- mSignalledError = true;
- notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return;
}
- if (decoderErr == AAC_DEC_OK || 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.
- outHeader->nFilledLen = numOutBytes;
+ while (!outQueue.empty()
+ && outputDelayRingBufferSamplesAvailable()
+ >= mStreamInfo->frameSize * mStreamInfo->numChannels) {
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
- outHeader->nTimeStamp =
- mAnchorTimeUs
- + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate;
+ if (outHeader->nOffset != 0) {
+ ALOGE("outHeader->nOffset != 0 is not handled");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
- mNumSamplesOutput += mStreamInfo->frameSize;
+ INT_PCM *outBuffer =
+ reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
+ if (outHeader->nOffset
+ + mStreamInfo->frameSize * mStreamInfo->numChannels * sizeof(int16_t)
+ > outHeader->nAllocLen) {
+ ALOGE("buffer overflow");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+ int32_t ns = outputDelayRingBufferGetSamples(outBuffer,
+ mStreamInfo->frameSize * mStreamInfo->numChannels); // TODO: check for overflow
+ if (ns != mStreamInfo->frameSize * mStreamInfo->numChannels) {
+ ALOGE("not a complete frame of samples available");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
+ outHeader->nFilledLen = mStreamInfo->frameSize * mStreamInfo->numChannels
+ * sizeof(int16_t);
+ if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) {
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ mEndOfOutput = true;
+ } else {
+ outHeader->nFlags = 0;
+ }
+
+ outHeader->nTimeStamp = mAnchorTimeUs[mOutputBufferCount
+ % kNumDelayBlocksMax];
+
+ mOutputBufferCount++;
outInfo->mOwnedByUs = false;
outQueue.erase(outQueue.begin());
outInfo = NULL;
@@ -558,8 +790,48 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
outHeader = NULL;
}
- if (decoderErr == AAC_DEC_OK) {
- ++mInputBufferCount;
+ if (mEndOfInput) {
+ if (outputDelayRingBufferSamplesAvailable() > 0
+ && outputDelayRingBufferSamplesAvailable()
+ < mStreamInfo->frameSize * mStreamInfo->numChannels) {
+ ALOGE("not a complete frame of samples available");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
+ if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) {
+ if (!mEndOfOutput) {
+ // send empty block signaling EOS
+ mEndOfOutput = true;
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (outHeader->nOffset != 0) {
+ ALOGE("outHeader->nOffset != 0 is not handled");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
+ INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer
+ + outHeader->nOffset);
+ int32_t ns = 0;
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outHeader->nTimeStamp = mAnchorTimeUs[mOutputBufferCount
+ % kNumDelayBlocksMax];
+
+ mOutputBufferCount++;
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+ }
+ break; // if outQueue not empty but no more output
+ }
}
}
}
@@ -570,38 +842,66 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) {
// depend on fragments from the last one decoded.
// drain all existing data
drainDecoder();
- // force decoder loop to drop the first decoded buffer by resetting these state variables,
- // but only if initialization has already happened.
- if (mInputBufferCount != 0) {
- mInputBufferCount = 1;
- mStreamInfo->sampleRate = 0;
+ } else {
+ while (outputDelayRingBufferSamplesAvailable() > 0) {
+ int32_t ns = outputDelayRingBufferGetSamples(0,
+ mStreamInfo->frameSize * mStreamInfo->numChannels);
+ if (ns != mStreamInfo->frameSize * mStreamInfo->numChannels) {
+ ALOGE("not a complete frame of samples available");
+ }
+ mOutputBufferCount++;
}
+ mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
}
}
void SoftAAC2::drainDecoder() {
- // a buffer big enough for 6 channels of decoded HE-AAC
- short buf [2048*6];
- aacDecoder_DecodeFrame(mAACDecoder,
- buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
- aacDecoder_DecodeFrame(mAACDecoder,
- buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
- aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mDecoderHasData = false;
+ int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
+
+ // flush decoder until outputDelay is compensated
+ while (mOutputDelayCompensated > 0) {
+ // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
+ INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
+
+ // run DRC check
+ mDrcWrap.submitStreamData(mStreamInfo);
+ mDrcWrap.update();
+
+ AAC_DECODER_ERROR decoderErr =
+ aacDecoder_DecodeFrame(mAACDecoder,
+ tmpOutBuffer,
+ 2048 * MAX_CHANNEL_COUNT,
+ AACDEC_FLUSH);
+ if (decoderErr != AAC_DEC_OK) {
+ ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
+ }
+
+ int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
+ if (tmpOutBufferSamples > mOutputDelayCompensated) {
+ tmpOutBufferSamples = mOutputDelayCompensated;
+ }
+ outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
+
+ mOutputDelayCompensated -= tmpOutBufferSamples;
+ }
}
void SoftAAC2::onReset() {
drainDecoder();
// reset the "configured" state
mInputBufferCount = 0;
- mNumSamplesOutput = 0;
+ mOutputBufferCount = 0;
+ mOutputDelayCompensated = 0;
+ mOutputDelayRingBufferWritePos = 0;
+ mOutputDelayRingBufferReadPos = 0;
+ mEndOfInput = false;
+ mEndOfOutput = false;
+
// To make the codec behave the same before and after a reset, we need to invalidate the
// streaminfo struct. This does that:
- mStreamInfo->sampleRate = 0;
+ mStreamInfo->sampleRate = 0; // TODO: mStreamInfo is read only
mSignalledError = false;
- mSawInputEos = false;
- mSignalledOutputEos = false;
mOutputPortSettingsChange = NONE;
}
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index a7ea1e2..5cde03a 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -20,6 +20,7 @@
#include "SimpleSoftOMXComponent.h"
#include "aacdecoder_lib.h"
+#include "DrcPresModeWrap.h"
namespace android {
@@ -47,18 +48,19 @@ private:
enum {
kNumInputBuffers = 4,
kNumOutputBuffers = 4,
+ kNumDelayBlocksMax = 8,
};
HANDLE_AACDECODER mAACDecoder;
CStreamInfo *mStreamInfo;
bool mIsADTS;
- bool mDecoderHasData;
+ bool mIsFirst;
size_t mInputBufferCount;
+ size_t mOutputBufferCount;
bool mSignalledError;
- bool mSawInputEos;
- bool mSignalledOutputEos;
- int64_t mAnchorTimeUs;
- int64_t mNumSamplesOutput;
+ int64_t mAnchorTimeUs[kNumDelayBlocksMax];
+
+ CDrcPresModeWrapper mDrcWrap;
enum {
NONE,
@@ -69,9 +71,22 @@ private:
void initPorts();
status_t initDecoder();
bool isConfigured() const;
- void maybeConfigureDownmix() const;
+ void configureDownmix() const;
void drainDecoder();
+// delay compensation
+ bool mEndOfInput;
+ bool mEndOfOutput;
+ int32_t mOutputDelayCompensated;
+ int32_t mOutputDelayRingBufferSize;
+ short *mOutputDelayRingBuffer;
+ int32_t mOutputDelayRingBufferWritePos;
+ int32_t mOutputDelayRingBufferReadPos;
+ bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
+ int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
+ int32_t outputDelayRingBufferSamplesAvailable();
+ int32_t outputDelayRingBufferSamplesLeft();
+
DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
};
diff --git a/media/libstagefright/codecs/hevcdec/Android.mk b/media/libstagefright/codecs/hevcdec/Android.mk
index 2fe347b..960602f 100644
--- a/media/libstagefright/codecs/hevcdec/Android.mk
+++ b/media/libstagefright/codecs/hevcdec/Android.mk
@@ -1,3 +1,5 @@
+ifeq ($(if $(wildcard external/libhevc),1,0),1)
+
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -20,3 +22,5 @@ LOCAL_SHARED_LIBRARIES += liblog
include $(BUILD_SHARED_LIBRARY)
+
+endif
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
deleted file mode 100644
index 3a6dd4f..0000000
--- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s
+++ /dev/null
@@ -1,210 +0,0 @@
-; ------------------------------------------------------------------
-; Copyright (C) 1998-2009 PacketVideo
-;
-; Licensed under the Apache License, Version 2.0 (the "License");
-; you may not use this file except in compliance with the License.
-; You may obtain a copy of the License at
-;
-; http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing, software
-; distributed under the License is distributed on an "AS IS" BASIS,
-; WITHOUT WARRANTIES 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_mdct_18_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s
deleted file mode 100644
index 9401d8c..0000000
--- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s
+++ /dev/null
@@ -1,369 +0,0 @@
-; ------------------------------------------------------------------
-; Copyright (C) 1998-2009 PacketVideo
-;
-; Licensed under the Apache License, Version 2.0 (the "License");
-; you may not use this file except in compliance with the License.
-; You may obtain a copy of the License at
-;
-; http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing, software
-; distributed under the License is distributed on an "AS IS" BASIS,
-; WITHOUT WARRANTIES 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_wm.asm b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm
deleted file mode 100644
index 5be75d4..0000000
--- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm
+++ /dev/null
@@ -1,366 +0,0 @@
-; ------------------------------------------------------------------
-; Copyright (C) 1998-2009 PacketVideo
-;
-; Licensed under the Apache License, Version 2.0 (the "License");
-; you may not use this file except in compliance with the License.
-; You may obtain a copy of the License at
-;
-; http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing, software
-; distributed under the License is distributed on an "AS IS" BASIS,
-; WITHOUT WARRANTIES 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
deleted file mode 100644
index abec599..0000000
--- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s
+++ /dev/null
@@ -1,237 +0,0 @@
-; ------------------------------------------------------------------
-; Copyright (C) 1998-2009 PacketVideo
-;
-; Licensed under the Apache License, Version 2.0 (the "License");
-; you may not use this file except in compliance with the License.
-; You may obtain a copy of the License at
-;
-; http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing, software
-; distributed under the License is distributed on an "AS IS" BASIS,
-; WITHOUT WARRANTIES 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_wm.asm b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm
deleted file mode 100644
index f957267..0000000
--- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm
+++ /dev/null
@@ -1,231 +0,0 @@
-; ------------------------------------------------------------------
-; Copyright (C) 1998-2009 PacketVideo
-;
-; Licensed under the Apache License, Version 2.0 (the "License");
-; you may not use this file except in compliance with the License.
-; You may obtain a copy of the License at
-;
-; http://www.apache.org/licenses/LICENSE-2.0
-;
-; Unless required by applicable law or agreed to in writing, software
-; distributed under the License is distributed on an "AS IS" BASIS,
-; WITHOUT WARRANTIES 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/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index d1afd8b..338e899 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -555,7 +555,9 @@ status_t ATSParser::Stream::parse(
}
#endif
- return OK;
+ if (!payload_unit_start_indicator) {
+ return OK;
+ }
}
mExpectedContinuityCounter = (continuity_counter + 1) & 0x0f;
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index 786bf0d..3a280f0 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -25,7 +25,8 @@ LOCAL_SHARED_LIBRARIES := \
libmediaplayerservice \
libutils \
liblog \
- libbinder
+ libbinder \
+ libsoundtriggerservice
LOCAL_STATIC_LIBRARIES := \
libregistermsext
@@ -36,7 +37,8 @@ LOCAL_C_INCLUDES := \
frameworks/av/services/audioflinger \
frameworks/av/services/audiopolicy \
frameworks/av/services/camera/libcameraservice \
- $(call include-path-for, audio-utils)
+ $(call include-path-for, audio-utils) \
+ frameworks/av/services/soundtrigger
LOCAL_MODULE:= mediaserver
LOCAL_32_BIT_ONLY := true
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index a347951..af1c9e6 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -34,6 +34,7 @@
#include "MediaLogService.h"
#include "MediaPlayerService.h"
#include "AudioPolicyService.h"
+#include "SoundTriggerHwService.h"
using namespace android;
@@ -128,6 +129,7 @@ int main(int argc __unused, char** argv)
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
+ SoundTriggerHwService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a4cad4e..527fd65 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -431,7 +431,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
if (mLogMemoryDealer != 0) {
sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
if (binder != 0) {
- fdprintf(fd, "\nmedia.log:\n");
+ dprintf(fd, "\nmedia.log:\n");
Vector<String16> args;
binder->dump(fd, args);
}
@@ -1266,7 +1266,7 @@ AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
: RefBase(),
mAudioFlinger(audioFlinger),
// FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
- mMemoryDealer(new MemoryDealer(4 * 1024*1024, "AudioFlinger::Client")),
+ mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
mPid(pid),
mTimedTrackCount(0)
{
@@ -2609,7 +2609,7 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand
}
} else {
if (fd >= 0) {
- fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno));
+ dprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno));
}
}
char teeTime[16];
@@ -2663,11 +2663,11 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand
write(teeFd, &temp, sizeof(temp));
close(teeFd);
if (fd >= 0) {
- fdprintf(fd, "tee copied to %s\n", teePath);
+ dprintf(fd, "tee copied to %s\n", teePath);
}
} else {
if (fd >= 0) {
- fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno));
+ dprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno));
}
}
}
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index a4446a4..318eb57 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -460,9 +460,15 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
const uint32_t phaseIncrement = mPhaseIncrement;
size_t outputIndex = 0;
size_t outputSampleCount = outFrameCount * 2; // stereo output
- size_t inFrameCount = getInFrameCountRequired(outFrameCount) + (phaseFraction != 0);
- ALOG_ASSERT(0 < inFrameCount && inFrameCount < (1U << 31));
const uint32_t phaseWrapLimit = c.mL << c.mShift;
+ size_t inFrameCount = (phaseIncrement * (uint64_t)outFrameCount + phaseFraction)
+ / phaseWrapLimit;
+ // sanity check that inFrameCount is in signed 32 bit integer range.
+ ALOG_ASSERT(0 <= inFrameCount && inFrameCount < (1U << 31));
+
+ //ALOGV("inFrameCount:%d outFrameCount:%d"
+ // " phaseIncrement:%u phaseFraction:%u phaseWrapLimit:%u",
+ // inFrameCount, outFrameCount, phaseIncrement, phaseFraction, phaseWrapLimit);
// NOTE: be very careful when modifying the code here. register
// pressure is very high and a small change might cause the compiler
@@ -472,10 +478,17 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
// the following logic is a bit convoluted to keep the main processing loop
// as tight as possible with register allocation.
while (outputIndex < outputSampleCount) {
- // buffer is empty, fetch a new one
- while (mBuffer.frameCount == 0) {
+ //ALOGV("LOOP: inFrameCount:%d outputIndex:%d outFrameCount:%d"
+ // " phaseFraction:%u phaseWrapLimit:%u",
+ // inFrameCount, outputIndex, outFrameCount, phaseFraction, phaseWrapLimit);
+
+ // check inputIndex overflow
+ ALOG_ASSERT(inputIndex <= mBuffer.frameCount, "inputIndex%d > frameCount%d",
+ inputIndex, mBuffer.frameCount);
+ // Buffer is empty, fetch a new one if necessary (inFrameCount > 0).
+ // We may not fetch a new buffer if the existing data is sufficient.
+ while (mBuffer.frameCount == 0 && inFrameCount > 0) {
mBuffer.frameCount = inFrameCount;
- ALOG_ASSERT(inFrameCount > 0);
provider->getNextBuffer(&mBuffer,
calculateOutputPTS(outputIndex / 2));
if (mBuffer.raw == NULL) {
@@ -486,9 +499,9 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
mInBuffer.template readAdvance<CHANNELS>(
impulse, c.mHalfNumCoefs,
reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
+ inputIndex++;
phaseFraction -= phaseWrapLimit;
while (phaseFraction >= phaseWrapLimit) {
- inputIndex++;
if (inputIndex >= mBuffer.frameCount) {
inputIndex = 0;
provider->releaseBuffer(&mBuffer);
@@ -497,6 +510,7 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
mInBuffer.template readAdvance<CHANNELS>(
impulse, c.mHalfNumCoefs,
reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
+ inputIndex++;
phaseFraction -= phaseWrapLimit;
}
}
@@ -507,9 +521,6 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
const int halfNumCoefs = c.mHalfNumCoefs;
const TO* const volumeSimd = mVolumeSimd;
- // reread the last input in.
- mInBuffer.template readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
-
// main processing loop
while (CC_LIKELY(outputIndex < outputSampleCount)) {
// caution: fir() is inlined and may be large.
@@ -518,6 +529,10 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
// from the input samples in impulse[-halfNumCoefs+1]... impulse[halfNumCoefs]
// from the polyphase filter of (phaseFraction / phaseWrapLimit) in coefs.
//
+ //ALOGV("LOOP2: inFrameCount:%d outputIndex:%d outFrameCount:%d"
+ // " phaseFraction:%u phaseWrapLimit:%u",
+ // inFrameCount, outputIndex, outFrameCount, phaseFraction, phaseWrapLimit);
+ ALOG_ASSERT(phaseFraction < phaseWrapLimit);
fir<CHANNELS, LOCKED, STRIDE>(
&out[outputIndex],
phaseFraction, phaseWrapLimit,
@@ -527,17 +542,20 @@ void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
phaseFraction += phaseIncrement;
while (phaseFraction >= phaseWrapLimit) {
- inputIndex++;
if (inputIndex >= frameCount) {
goto done; // need a new buffer
}
mInBuffer.template readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+ inputIndex++;
phaseFraction -= phaseWrapLimit;
}
}
done:
- // often arrives here when input buffer runs out
- if (inputIndex >= frameCount) {
+ // We arrive here when we're finished or when the input buffer runs out.
+ // Regardless we need to release the input buffer if we've acquired it.
+ if (inputIndex > 0) { // we've acquired a buffer (alternatively could check frameCount)
+ ALOG_ASSERT(inputIndex == frameCount, "inputIndex(%d) != frameCount(%d)",
+ inputIndex, frameCount); // must have been fully read.
inputIndex = 0;
provider->releaseBuffer(&mBuffer);
ALOG_ASSERT(mBuffer.frameCount == 0);
@@ -545,14 +563,12 @@ done:
}
resample_exit:
- // Release frames to avoid the count being inaccurate for pts timing.
- // TODO: Avoid this extra check by making fetch count exact. This is tricky
- // due to the overfetching mechanism which loads unnecessarily when
- // mBuffer.frameCount == 0.
- if (inputIndex) {
- mBuffer.frameCount = inputIndex;
- provider->releaseBuffer(&mBuffer);
- }
+ // inputIndex must be zero in all three cases:
+ // (1) the buffer never was been acquired; (2) the buffer was
+ // released at "done:"; or (3) getNextBuffer() failed.
+ ALOG_ASSERT(inputIndex == 0, "Releasing: inputindex:%d frameCount:%d phaseFraction:%u",
+ inputIndex, mBuffer.frameCount, phaseFraction);
+ ALOG_ASSERT(mBuffer.frameCount == 0); // there must be no frames in the buffer
mInBuffer.setImpulse(impulse);
mPhaseFraction = phaseFraction;
}
diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/AudioWatchdog.cpp
index 93d185e..877e776 100644
--- a/services/audioflinger/AudioWatchdog.cpp
+++ b/services/audioflinger/AudioWatchdog.cpp
@@ -34,7 +34,7 @@ void AudioWatchdogDump::dump(int fd)
} else {
strcpy(buf, "N/A\n");
}
- fdprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s",
+ dprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s",
mUnderruns, mLogs, buf);
}
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index c9a3f10..c486630 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -26,7 +26,6 @@
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include "Configuration.h"
-#include <sys/atomics.h>
#include <time.h>
#include <utils/Log.h>
#include <utils/Trace.h>
@@ -492,7 +491,7 @@ static int compare_uint32_t(const void *pa, const void *pb)
void FastMixerDumpState::dump(int fd) const
{
if (mCommand == FastMixerState::INITIAL) {
- fdprintf(fd, " FastMixer not initialized\n");
+ dprintf(fd, " FastMixer not initialized\n");
return;
}
#define COMMAND_MAX 32
@@ -526,10 +525,10 @@ void FastMixerDumpState::dump(int fd) const
double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
(mMeasuredWarmupTs.tv_nsec / 1000000.0);
double mixPeriodSec = (double) mFrameCount / (double) mSampleRate;
- fdprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
- " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
- " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
- " mixPeriod=%.2f ms\n",
+ dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
+ " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
+ " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
+ " mixPeriod=%.2f ms\n",
string, mWriteSequence, mFramesWritten,
mNumTracks, mWriteErrors, mUnderruns, mOverruns,
mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
@@ -581,26 +580,26 @@ void FastMixerDumpState::dump(int fd) const
#endif
}
if (n) {
- fdprintf(fd, " Simple moving statistics over last %.1f seconds:\n",
- wall.n() * mixPeriodSec);
- fdprintf(fd, " wall clock time in ms per mix cycle:\n"
- " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
- wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
- wall.stddev()*1e-6);
- fdprintf(fd, " raw CPU load in us per mix cycle:\n"
- " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
- loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
- loadNs.stddev()*1e-3);
+ dprintf(fd, " Simple moving statistics over last %.1f seconds:\n",
+ wall.n() * mixPeriodSec);
+ dprintf(fd, " wall clock time in ms per mix cycle:\n"
+ " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
+ wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
+ wall.stddev()*1e-6);
+ dprintf(fd, " raw CPU load in us per mix cycle:\n"
+ " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
+ loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
+ loadNs.stddev()*1e-3);
} else {
- fdprintf(fd, " No FastMixer statistics available currently\n");
+ dprintf(fd, " No FastMixer statistics available currently\n");
}
#ifdef CPU_FREQUENCY_STATISTICS
- fdprintf(fd, " CPU clock frequency in MHz:\n"
- " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
- kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
- fdprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
- " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
- loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
+ dprintf(fd, " CPU clock frequency in MHz:\n"
+ " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
+ kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
+ dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
+ " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
+ loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
#endif
if (tail != NULL) {
qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
@@ -611,12 +610,12 @@ void FastMixerDumpState::dump(int fd) const
left.sample(tail[i]);
right.sample(tail[n - (i + 1)]);
}
- fdprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n"
- " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
- " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
- left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
- right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
- right.stddev()*1e-6);
+ dprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n"
+ " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
+ " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
+ left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
+ right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
+ right.stddev()*1e-6);
delete[] tail;
}
#endif
@@ -626,9 +625,9 @@ void FastMixerDumpState::dump(int fd) const
// Instead we always display all tracks, with an indication
// of whether we think the track is active.
uint32_t trackMask = mTrackMask;
- fdprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
+ dprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
FastMixerState::kMaxFastTracks, trackMask);
- fdprintf(fd, " Index Active Full Partial Empty Recent Ready\n");
+ dprintf(fd, " Index Active Full Partial Empty Recent Ready\n");
for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
bool isActive = trackMask & 1;
const FastTrackDump *ftDump = &mTracks[i];
@@ -648,7 +647,7 @@ void FastMixerDumpState::dump(int fd) const
mostRecent = "?";
break;
}
- fdprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
+ dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
(underruns.mBitFields.mFull) & UNDERRUN_MASK,
(underruns.mBitFields.mPartial) & UNDERRUN_MASK,
(underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp
index 48399c0..7e01c9f 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/StateQueue.cpp
@@ -28,12 +28,12 @@ namespace android {
#ifdef STATE_QUEUE_DUMP
void StateQueueObserverDump::dump(int fd)
{
- fdprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges);
+ dprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges);
}
void StateQueueMutatorDump::dump(int fd)
{
- fdprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n",
+ dprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n",
mPushDirty, mPushAck, mBlockedSequence);
}
#endif
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d6333be..d08c966 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -574,30 +574,30 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __u
bool locked = AudioFlinger::dumpTryLock(mLock);
if (!locked) {
- fdprintf(fd, "thread %p maybe dead locked\n", this);
+ dprintf(fd, "thread %p maybe dead locked\n", this);
}
- fdprintf(fd, " I/O handle: %d\n", mId);
- fdprintf(fd, " TID: %d\n", getTid());
- fdprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no");
- fdprintf(fd, " Sample rate: %u\n", mSampleRate);
- fdprintf(fd, " HAL frame count: %zu\n", mFrameCount);
- fdprintf(fd, " HAL buffer size: %u bytes\n", mBufferSize);
- fdprintf(fd, " Channel Count: %u\n", mChannelCount);
- fdprintf(fd, " Channel Mask: 0x%08x (%s)\n", mChannelMask,
+ dprintf(fd, " I/O handle: %d\n", mId);
+ dprintf(fd, " TID: %d\n", getTid());
+ dprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no");
+ dprintf(fd, " Sample rate: %u\n", mSampleRate);
+ dprintf(fd, " HAL frame count: %zu\n", mFrameCount);
+ dprintf(fd, " HAL buffer size: %u bytes\n", mBufferSize);
+ dprintf(fd, " Channel Count: %u\n", mChannelCount);
+ dprintf(fd, " Channel Mask: 0x%08x (%s)\n", mChannelMask,
channelMaskToString(mChannelMask, mType != RECORD).string());
- fdprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat));
- fdprintf(fd, " Frame size: %zu\n", mFrameSize);
- fdprintf(fd, " Pending config events:");
+ dprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat));
+ dprintf(fd, " Frame size: %zu\n", mFrameSize);
+ dprintf(fd, " Pending config events:");
size_t numConfig = mConfigEvents.size();
if (numConfig) {
for (size_t i = 0; i < numConfig; i++) {
mConfigEvents[i]->dump(buffer, SIZE);
- fdprintf(fd, "\n %s", buffer);
+ dprintf(fd, "\n %s", buffer);
}
- fdprintf(fd, "\n");
+ dprintf(fd, "\n");
} else {
- fdprintf(fd, " none\n");
+ dprintf(fd, " none\n");
}
if (locked) {
@@ -1260,15 +1260,15 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar
// These values are "raw"; they will wrap around. See prepareTracks_l() for a better way.
FastTrackUnderruns underruns = getFastTrackUnderruns(0);
- fdprintf(fd, " Normal mixer raw underrun counters: partial=%u empty=%u\n",
+ dprintf(fd, " Normal mixer raw underrun counters: partial=%u empty=%u\n",
underruns.mBitFields.mPartial, underruns.mBitFields.mEmpty);
size_t numtracks = mTracks.size();
size_t numactive = mActiveTracks.size();
- fdprintf(fd, " %d Tracks", numtracks);
+ dprintf(fd, " %d Tracks", numtracks);
size_t numactiveseen = 0;
if (numtracks) {
- fdprintf(fd, " of which %d are active\n", numactive);
+ dprintf(fd, " of which %d are active\n", numactive);
Track::appendDumpHeader(result);
for (size_t i = 0; i < numtracks; ++i) {
sp<Track> track = mTracks[i];
@@ -1300,22 +1300,21 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar
}
write(fd, result.string(), result.size());
-
}
void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
{
- fdprintf(fd, "\nOutput thread %p:\n", this);
- fdprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount);
- fdprintf(fd, " Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
- fdprintf(fd, " Total writes: %d\n", mNumWrites);
- fdprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites);
- fdprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no");
- fdprintf(fd, " Suspend count: %d\n", mSuspended);
- fdprintf(fd, " Sink buffer : %p\n", mSinkBuffer);
- fdprintf(fd, " Mixer buffer: %p\n", mMixerBuffer);
- fdprintf(fd, " Effect buffer: %p\n", mEffectBuffer);
- fdprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask);
+ dprintf(fd, "\nOutput thread %p:\n", this);
+ dprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount);
+ dprintf(fd, " Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
+ dprintf(fd, " Total writes: %d\n", mNumWrites);
+ dprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites);
+ dprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no");
+ dprintf(fd, " Suspend count: %d\n", mSuspended);
+ dprintf(fd, " Sink buffer : %p\n", mSinkBuffer);
+ dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer);
+ dprintf(fd, " Effect buffer: %p\n", mEffectBuffer);
+ dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask);
dumpBase(fd, args);
}
@@ -3799,7 +3798,7 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& ar
PlaybackThread::dumpInternals(fd, args);
- fdprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames());
+ dprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames());
// Make a non-atomic copy of fast mixer dump state so it won't change underneath us
const FastMixerDumpState copy(mFastMixerDumpState);
@@ -5717,12 +5716,12 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args)
{
- fdprintf(fd, "\nInput thread %p:\n", this);
+ dprintf(fd, "\nInput thread %p:\n", this);
if (mActiveTracks.size() > 0) {
- fdprintf(fd, " Buffer size: %zu bytes\n", mBufferSize);
+ dprintf(fd, " Buffer size: %zu bytes\n", mBufferSize);
} else {
- fdprintf(fd, " No active record clients\n");
+ dprintf(fd, " No active record clients\n");
}
dprintf(fd, " Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
@@ -5738,9 +5737,9 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args
size_t numtracks = mTracks.size();
size_t numactive = mActiveTracks.size();
size_t numactiveseen = 0;
- fdprintf(fd, " %d Tracks", numtracks);
+ dprintf(fd, " %d Tracks", numtracks);
if (numtracks) {
- fdprintf(fd, " of which %d are active\n", numactive);
+ dprintf(fd, " of which %d are active\n", numactive);
RecordTrack::appendDumpHeader(result);
for (size_t i = 0; i < numtracks ; ++i) {
sp<RecordTrack> track = mTracks[i];
@@ -5754,7 +5753,7 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args
}
}
} else {
- fdprintf(fd, "\n");
+ dprintf(fd, "\n");
}
if (numactiveseen != numactive) {
diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk
new file mode 100644
index 0000000..874f18f
--- /dev/null
+++ b/services/audioflinger/tests/Android.mk
@@ -0,0 +1,31 @@
+# Build the unit tests for audioflinger
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libutils \
+ libcutils \
+ libstlport \
+ libaudioutils \
+ libaudioresampler
+
+LOCAL_STATIC_LIBRARIES := \
+ libgtest \
+ libgtest_main
+
+LOCAL_C_INCLUDES := \
+ bionic \
+ bionic/libstdc++/include \
+ external/gtest/include \
+ external/stlport/stlport \
+ frameworks/av/services/audioflinger
+
+LOCAL_SRC_FILES := \
+ resampler_tests.cpp
+
+LOCAL_MODULE := resampler_tests
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/services/audioflinger/tests/build_and_run_all_unit_tests.sh b/services/audioflinger/tests/build_and_run_all_unit_tests.sh
new file mode 100755
index 0000000..2c453b0
--- /dev/null
+++ b/services/audioflinger/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ echo "Android build environment not set"
+ exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+pushd $ANDROID_BUILD_TOP/frameworks/av/services/audioflinger/
+pwd
+mm
+
+echo "waiting for device"
+adb root && adb wait-for-device remount
+adb push $OUT/system/lib/libaudioresampler.so /system/lib
+adb push $OUT/system/bin/resampler_tests /system/bin
+
+sh $ANDROID_BUILD_TOP/frameworks/av/services/audioflinger/tests/run_all_unit_tests.sh
+
+popd
diff --git a/services/audioflinger/tests/resampler_tests.cpp b/services/audioflinger/tests/resampler_tests.cpp
new file mode 100644
index 0000000..8f9c270
--- /dev/null
+++ b/services/audioflinger/tests/resampler_tests.cpp
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audioflinger_resampler_tests"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <time.h>
+#include <math.h>
+#include <vector>
+#include <utility>
+#include <cutils/log.h>
+#include <gtest/gtest.h>
+#include <media/AudioBufferProvider.h>
+#include "AudioResampler.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+template<typename T, typename U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> // partial specialization
+{
+ static const bool value = true;
+};
+
+template<typename T>
+static inline T convertValue(double val)
+{
+ if (is_same<T, int16_t>::value) {
+ return floor(val * 32767.0 + 0.5);
+ } else if (is_same<T, int32_t>::value) {
+ return floor(val * (1UL<<31) + 0.5);
+ }
+ return val; // assume float or double
+}
+
+/* Creates a type-independent audio buffer provider from
+ * a buffer base address, size, framesize, and input increment array.
+ *
+ * No allocation or deallocation of the provided buffer is done.
+ */
+class TestProvider : public android::AudioBufferProvider {
+public:
+ TestProvider(const void* addr, size_t frames, size_t frameSize,
+ const std::vector<size_t>& inputIncr)
+ : mAddr(addr),
+ mNumFrames(frames),
+ mFrameSize(frameSize),
+ mNextFrame(0), mUnrel(0), mInputIncr(inputIncr), mNextIdx(0)
+ {
+ }
+
+ virtual android::status_t getNextBuffer(Buffer* buffer, int64_t pts __unused = kInvalidPTS )
+ {
+ size_t requestedFrames = buffer->frameCount;
+ if (requestedFrames > mNumFrames - mNextFrame) {
+ buffer->frameCount = mNumFrames - mNextFrame;
+ }
+ if (!mInputIncr.empty()) {
+ size_t provided = mInputIncr[mNextIdx++];
+ ALOGV("getNextBuffer() mValue[%d]=%u not %u",
+ mNextIdx-1, provided, buffer->frameCount);
+ if (provided < buffer->frameCount) {
+ buffer->frameCount = provided;
+ }
+ if (mNextIdx >= mInputIncr.size()) {
+ mNextIdx = 0;
+ }
+ }
+ ALOGV("getNextBuffer() requested %u frames out of %u frames available"
+ " and returned %u frames\n",
+ requestedFrames, mNumFrames - mNextFrame, buffer->frameCount);
+ mUnrel = buffer->frameCount;
+ if (buffer->frameCount > 0) {
+ buffer->raw = (char *)mAddr + mFrameSize * mNextFrame;
+ return android::NO_ERROR;
+ } else {
+ buffer->raw = NULL;
+ return android::NOT_ENOUGH_DATA;
+ }
+ }
+
+ virtual void releaseBuffer(Buffer* buffer)
+ {
+ if (buffer->frameCount > mUnrel) {
+ ALOGE("releaseBuffer() released %u frames but only %u available "
+ "to release\n", buffer->frameCount, mUnrel);
+ mNextFrame += mUnrel;
+ mUnrel = 0;
+ } else {
+
+ ALOGV("releaseBuffer() released %u frames out of %u frames available "
+ "to release\n", buffer->frameCount, mUnrel);
+ mNextFrame += buffer->frameCount;
+ mUnrel -= buffer->frameCount;
+ }
+ buffer->frameCount = 0;
+ buffer->raw = NULL;
+ }
+
+ void reset()
+ {
+ mNextFrame = 0;
+ }
+
+ size_t getNumFrames()
+ {
+ return mNumFrames;
+ }
+
+ void setIncr(const std::vector<size_t> inputIncr)
+ {
+ mNextIdx = 0;
+ mInputIncr = inputIncr;
+ }
+
+protected:
+ const void* mAddr; // base address
+ size_t mNumFrames; // total frames
+ int mFrameSize; // frame size (# channels * bytes per sample)
+ size_t mNextFrame; // index of next frame to provide
+ size_t mUnrel; // number of frames not yet released
+ std::vector<size_t> mInputIncr; // number of frames provided per call
+ size_t mNextIdx; // index of next entry in mInputIncr to use
+};
+
+/* Creates a buffer filled with a sine wave.
+ *
+ * Returns a pair consisting of the sine signal buffer and the number of frames.
+ * The caller must delete[] the buffer when no longer needed (no shared_ptr<>).
+ */
+template<typename T>
+static std::pair<T*, size_t> createSine(size_t channels,
+ double freq, double samplingRate, double time)
+{
+ double tscale = 1. / samplingRate;
+ size_t frames = static_cast<size_t>(samplingRate * time);
+ T* buffer = new T[frames * channels];
+ for (size_t i = 0; i < frames; ++i) {
+ double t = i * tscale;
+ double y = sin(2. * M_PI * freq * t);
+ T yt = convertValue<T>(y);
+
+ for (size_t j = 0; j < channels; ++j) {
+ buffer[i*channels + j] = yt / (j + 1);
+ }
+ }
+ return std::make_pair(buffer, frames);
+}
+
+/* Creates a buffer filled with a chirp signal (a sine wave sweep).
+ *
+ * Returns a pair consisting of the chirp signal buffer and the number of frames.
+ * The caller must delete[] the buffer when no longer needed (no shared_ptr<>).
+ *
+ * When creating the Chirp, note that the frequency is the true sinusoidal
+ * frequency not the sampling rate.
+ *
+ * http://en.wikipedia.org/wiki/Chirp
+ */
+template<typename T>
+static std::pair<T*, size_t> createChirp(size_t channels,
+ double minfreq, double maxfreq, double samplingRate, double time)
+{
+ double tscale = 1. / samplingRate;
+ size_t frames = static_cast<size_t>(samplingRate * time);
+ T *buffer = new T[frames * channels];
+ // note the chirp constant k has a divide-by-two.
+ double k = (maxfreq - minfreq) / (2. * time);
+ for (size_t i = 0; i < frames; ++i) {
+ double t = i * tscale;
+ double y = sin(2. * M_PI * (k * t + minfreq) * t);
+ T yt = convertValue<T>(y);
+
+ for (size_t j = 0; j < channels; ++j) {
+ buffer[i*channels + j] = yt / (j + 1);
+ }
+ }
+ return std::make_pair(buffer, frames);
+}
+
+/* This derived class creates a buffer provider of datatype T,
+ * consisting of an input signal, e.g. from createChirp().
+ * The number of frames can be obtained from the base class
+ * TestProvider::getNumFrames().
+ */
+template <typename T>
+class SignalProvider : public TestProvider {
+public:
+ SignalProvider(const std::pair<T*, size_t>& bufferInfo, size_t channels,
+ const std::vector<size_t>& values)
+ : TestProvider(bufferInfo.first, bufferInfo.second, channels * sizeof(T), values),
+ mManagedPtr(bufferInfo.first)
+ {
+ }
+
+ virtual ~SignalProvider()
+ {
+ delete[] mManagedPtr;
+ }
+
+protected:
+ T* mManagedPtr;
+};
+
+void resample(void *output, size_t outputFrames, const std::vector<size_t> &outputIncr,
+ android::AudioBufferProvider *provider, android::AudioResampler *resampler)
+{
+ for (size_t i = 0, j = 0; i < outputFrames; ) {
+ size_t thisFrames = outputIncr[j++];
+ if (j >= outputIncr.size()) {
+ j = 0;
+ }
+ if (thisFrames == 0 || thisFrames > outputFrames - i) {
+ thisFrames = outputFrames - i;
+ }
+ resampler->resample((int32_t*) output + 2*i, thisFrames, provider);
+ i += thisFrames;
+ }
+}
+
+void buffercmp(const void *reference, const void *test,
+ size_t outputFrameSize, size_t outputFrames)
+{
+ for (size_t i = 0; i < outputFrames; ++i) {
+ int check = memcmp((const char*)reference + i * outputFrameSize,
+ (const char*)test + i * outputFrameSize, outputFrameSize);
+ if (check) {
+ ALOGE("Failure at frame %d", i);
+ ASSERT_EQ(check, 0); /* fails */
+ }
+ }
+}
+
+void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFreq,
+ enum android::AudioResampler::src_quality quality)
+{
+ // create the provider
+ std::vector<size_t> inputIncr;
+ SignalProvider<int16_t> provider(createChirp<int16_t>(channels,
+ 0., outputFreq/2., outputFreq, outputFreq/2000.),
+ channels, inputIncr);
+
+ // calculate the output size
+ size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
+ size_t outputFrameSize = 2 * sizeof(int32_t);
+ size_t outputSize = outputFrameSize * outputFrames;
+ outputSize &= ~7;
+
+ // create the resampler
+ const int volumePrecision = 12; /* typical unity gain */
+ android::AudioResampler* resampler;
+
+ resampler = android::AudioResampler::create(16, channels, outputFreq, quality);
+ resampler->setSampleRate(inputFreq);
+ resampler->setVolume(1 << volumePrecision, 1 << volumePrecision);
+
+ // set up the reference run
+ std::vector<size_t> refIncr;
+ refIncr.push_back(outputFrames);
+ void* reference = malloc(outputSize);
+ resample(reference, outputFrames, refIncr, &provider, resampler);
+
+ provider.reset();
+
+#if 0
+ /* this test will fail - API interface issue: reset() does not clear internal buffers */
+ resampler->reset();
+#else
+ delete resampler;
+ resampler = android::AudioResampler::create(16, channels, outputFreq, quality);
+ resampler->setSampleRate(inputFreq);
+ resampler->setVolume(1 << volumePrecision, 1 << volumePrecision);
+#endif
+
+ // set up the test run
+ std::vector<size_t> outIncr;
+ outIncr.push_back(1);
+ outIncr.push_back(2);
+ outIncr.push_back(3);
+ void* test = malloc(outputSize);
+ resample(test, outputFrames, outIncr, &provider, resampler);
+
+ // check
+ buffercmp(reference, test, outputFrameSize, outputFrames);
+
+ free(reference);
+ free(test);
+ delete resampler;
+}
+
+template <typename T>
+inline double sqr(T v)
+{
+ double dv = static_cast<double>(v);
+ return dv * dv;
+}
+
+template <typename T>
+double signalEnergy(T *start, T *end, unsigned stride)
+{
+ double accum = 0;
+
+ for (T *p = start; p < end; p += stride) {
+ accum += sqr(*p);
+ }
+ unsigned count = (end - start + stride - 1) / stride;
+ return accum / count;
+}
+
+void testStopbandDownconversion(size_t channels,
+ unsigned inputFreq, unsigned outputFreq,
+ unsigned passband, unsigned stopband,
+ enum android::AudioResampler::src_quality quality)
+{
+ // create the provider
+ std::vector<size_t> inputIncr;
+ SignalProvider<int16_t> provider(createChirp<int16_t>(channels,
+ 0., inputFreq/2., inputFreq, inputFreq/2000.),
+ channels, inputIncr);
+
+ // calculate the output size
+ size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
+ size_t outputFrameSize = 2 * sizeof(int32_t);
+ size_t outputSize = outputFrameSize * outputFrames;
+ outputSize &= ~7;
+
+ // create the resampler
+ const int volumePrecision = 12; /* typical unity gain */
+ android::AudioResampler* resampler;
+
+ resampler = android::AudioResampler::create(16, channels, outputFreq, quality);
+ resampler->setSampleRate(inputFreq);
+ resampler->setVolume(1 << volumePrecision, 1 << volumePrecision);
+
+ // set up the reference run
+ std::vector<size_t> refIncr;
+ refIncr.push_back(outputFrames);
+ void* reference = malloc(outputSize);
+ resample(reference, outputFrames, refIncr, &provider, resampler);
+
+ int32_t *out = reinterpret_cast<int32_t *>(reference);
+
+ // check signal energy in passband
+ const unsigned passbandFrame = passband * outputFreq / 1000.;
+ const unsigned stopbandFrame = stopband * outputFreq / 1000.;
+
+ // check each channel separately
+ for (size_t i = 0; i < channels; ++i) {
+ double passbandEnergy = signalEnergy(out, out + passbandFrame * channels, channels);
+ double stopbandEnergy = signalEnergy(out + stopbandFrame * channels,
+ out + outputFrames * channels, channels);
+ double dbAtten = -10. * log10(stopbandEnergy / passbandEnergy);
+ ASSERT_GT(dbAtten, 60.);
+
+#if 0
+ // internal verification
+ printf("if:%d of:%d pbf:%d sbf:%d sbe: %f pbe: %f db: %.2f\n",
+ provider.getNumFrames(), outputFrames,
+ passbandFrame, stopbandFrame, stopbandEnergy, passbandEnergy, dbAtten);
+ for (size_t i = 0; i < 10; ++i) {
+ printf("%d\n", out[i+passbandFrame*channels]);
+ }
+ for (size_t i = 0; i < 10; ++i) {
+ printf("%d\n", out[i+stopbandFrame*channels]);
+ }
+#endif
+ }
+
+ free(reference);
+ delete resampler;
+}
+
+/* Buffer increment test
+ *
+ * We compare a reference output, where we consume and process the entire
+ * buffer at a time, and a test output, where we provide small chunks of input
+ * data and process small chunks of output (which may not be equivalent in size).
+ *
+ * Two subtests - fixed phase (3:2 down) and interpolated phase (147:320 up)
+ */
+TEST(audioflinger_resampler, bufferincrement_fixedphase) {
+ // all of these work
+ static const enum android::AudioResampler::src_quality kQualityArray[] = {
+ android::AudioResampler::LOW_QUALITY,
+ android::AudioResampler::MED_QUALITY,
+ android::AudioResampler::HIGH_QUALITY,
+ android::AudioResampler::VERY_HIGH_QUALITY,
+ android::AudioResampler::DYN_LOW_QUALITY,
+ android::AudioResampler::DYN_MED_QUALITY,
+ android::AudioResampler::DYN_HIGH_QUALITY,
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
+ testBufferIncrement(2, 48000, 32000, kQualityArray[i]);
+ }
+}
+
+TEST(audioflinger_resampler, bufferincrement_interpolatedphase) {
+ // all of these work except low quality
+ static const enum android::AudioResampler::src_quality kQualityArray[] = {
+// android::AudioResampler::LOW_QUALITY,
+ android::AudioResampler::MED_QUALITY,
+ android::AudioResampler::HIGH_QUALITY,
+ android::AudioResampler::VERY_HIGH_QUALITY,
+ android::AudioResampler::DYN_LOW_QUALITY,
+ android::AudioResampler::DYN_MED_QUALITY,
+ android::AudioResampler::DYN_HIGH_QUALITY,
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
+ testBufferIncrement(2, 22050, 48000, kQualityArray[i]);
+ }
+}
+
+/* Simple aliasing test
+ *
+ * This checks stopband response of the chirp signal to make sure frequencies
+ * are properly suppressed. It uses downsampling because the stopband can be
+ * clearly isolated by input frequencies exceeding the output sample rate (nyquist).
+ */
+TEST(audioflinger_resampler, stopbandresponse) {
+ // not all of these may work (old resamplers fail on downsampling)
+ static const enum android::AudioResampler::src_quality kQualityArray[] = {
+ //android::AudioResampler::LOW_QUALITY,
+ //android::AudioResampler::MED_QUALITY,
+ //android::AudioResampler::HIGH_QUALITY,
+ //android::AudioResampler::VERY_HIGH_QUALITY,
+ android::AudioResampler::DYN_LOW_QUALITY,
+ android::AudioResampler::DYN_MED_QUALITY,
+ android::AudioResampler::DYN_HIGH_QUALITY,
+ };
+
+ // in this test we assume a maximum transition band between 12kHz and 20kHz.
+ // there must be at least 60dB relative attenuation between stopband and passband.
+ for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
+ testStopbandDownconversion(2, 48000, 32000, 12000, 20000, kQualityArray[i]);
+ }
+
+ // in this test we assume a maximum transition band between 7kHz and 15kHz.
+ // there must be at least 60dB relative attenuation between stopband and passband.
+ // (the weird ratio triggers interpolative resampling)
+ for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
+ testStopbandDownconversion(2, 48000, 22101, 7000, 15000, kQualityArray[i]);
+ }
+}
diff --git a/services/audioflinger/tests/run_all_unit_tests.sh b/services/audioflinger/tests/run_all_unit_tests.sh
new file mode 100755
index 0000000..ffae6ae
--- /dev/null
+++ b/services/audioflinger/tests/run_all_unit_tests.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ echo "Android build environment not set"
+ exit -1
+fi
+
+echo "waiting for device"
+adb root && adb wait-for-device remount
+
+adb shell /system/bin/resampler_tests
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index a22ad9d..cddc503 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -46,8 +46,8 @@ LOCAL_CFLAGS += -fvisibility=hidden
include $(BUILD_SHARED_LIBRARY)
+
ifneq ($(USE_LEGACY_AUDIO_POLICY), 1)
-ifneq ($(USE_CUSTOM_AUDIO_POLICY), 1)
include $(CLEAR_VARS)
@@ -62,6 +62,20 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_STATIC_LIBRARIES := \
libmedia_helper
+LOCAL_MODULE:= libaudiopolicymanagerdefault
+
+include $(BUILD_SHARED_LIBRARY)
+
+ifneq ($(USE_CUSTOM_AUDIO_POLICY), 1)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AudioPolicyFactory.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudiopolicymanagerdefault
+
LOCAL_MODULE:= libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/AudioPolicyFactory.cpp b/services/audiopolicy/AudioPolicyFactory.cpp
new file mode 100644
index 0000000..2ae7bc1
--- /dev/null
+++ b/services/audiopolicy/AudioPolicyFactory.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioPolicyManager.h"
+
+namespace android {
+
+extern "C" AudioPolicyInterface* createAudioPolicyManager(
+ AudioPolicyClientInterface *clientInterface)
+{
+ return new AudioPolicyManager(clientInterface);
+}
+
+extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
+{
+ delete interface;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 61edac2..d4c9374 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -100,6 +100,7 @@ const StringToEnum sDeviceNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE),
STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF),
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
};
const StringToEnum sFlagNameToEnumTable[] = {
@@ -284,16 +285,8 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
0);
}
- if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET) {
- device = AUDIO_DEVICE_IN_WIRED_HEADSET;
- } else if (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO ||
- device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
- device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
- device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else {
- mpClientInterface->onAudioPortListUpdate();
- return NO_ERROR;
- }
+ mpClientInterface->onAudioPortListUpdate();
+ return NO_ERROR;
} // end if is output device
// handle input devices
@@ -3809,6 +3802,12 @@ audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t input
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+ break;
+ }
+ // FALL THROUGH
+
case AUDIO_SOURCE_VOICE_RECOGNITION:
case AUDIO_SOURCE_HOTWORD:
case AUDIO_SOURCE_VOICE_COMMUNICATION:
@@ -3985,6 +3984,11 @@ const AudioPolicyManager::VolumeCurvePoint
};
const AudioPolicyManager::VolumeCurvePoint
+ AudioPolicyManager::sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT] = {
+ {1, -56.0f}, {20, -34.0f}, {86, -10.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManager::VolumeCurvePoint
AudioPolicyManager::sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT] = {
{1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
};
@@ -4098,6 +4102,8 @@ void AudioPolicyManager::initializeVolumeCurves()
sSpeakerSonificationVolumeCurveDrc;
mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
sSpeakerSonificationVolumeCurveDrc;
+ mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
+ sSpeakerMediaVolumeCurveDrc;
}
}
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index adf1b33..1abeb6a 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -374,6 +374,7 @@ protected:
static const VolumeCurvePoint sDefaultMediaVolumeCurve[AudioPolicyManager::VOLCNT];
// volume curve for media strategy on speakers
static const VolumeCurvePoint sSpeakerMediaVolumeCurve[AudioPolicyManager::VOLCNT];
+ static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT];
// volume curve for sonification strategy on speakers
static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT];
static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[AudioPolicyManager::VOLCNT];
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index a2a0461..93fab11 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -108,7 +108,7 @@ AudioPolicyService::AudioPolicyService()
ALOGI("AudioPolicyService CSTOR in new mode");
mAudioPolicyClient = new AudioPolicyClient(this);
- mAudioPolicyManager = new AudioPolicyManager(mAudioPolicyClient);
+ mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif
// load audio pre processing modules
@@ -145,7 +145,7 @@ AudioPolicyService::~AudioPolicyService()
audio_policy_dev_close(mpAudioPolicyDev);
}
#else
- delete mAudioPolicyManager;
+ destroyAudioPolicyManager(mAudioPolicyManager);
delete mAudioPolicyClient;
#endif
@@ -399,7 +399,8 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.lock();
while (!exitPending())
{
- while (!mAudioCommands.isEmpty()) {
+ sp<AudioPolicyService> svc;
+ while (!mAudioCommands.isEmpty() && !exitPending()) {
nsecs_t curTime = systemTime();
// commands are sorted by increasing time stamp: execute them from index 0 and up
if (mAudioCommands[0]->mTime <= curTime) {
@@ -452,7 +453,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
StopOutputData *data = (StopOutputData *)command->mParam.get();
ALOGV("AudioCommandThread() processing stop output %d",
data->mIO);
- sp<AudioPolicyService> svc = mService.promote();
+ svc = mService.promote();
if (svc == 0) {
break;
}
@@ -464,7 +465,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get();
ALOGV("AudioCommandThread() processing release output %d",
data->mIO);
- sp<AudioPolicyService> svc = mService.promote();
+ svc = mService.promote();
if (svc == 0) {
break;
}
@@ -494,7 +495,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
} break;
case UPDATE_AUDIOPORT_LIST: {
ALOGV("AudioCommandThread() processing update audio port list");
- sp<AudioPolicyService> svc = mService.promote();
+ svc = mService.promote();
if (svc == 0) {
break;
}
@@ -504,7 +505,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
}break;
case UPDATE_AUDIOPATCH_LIST: {
ALOGV("AudioCommandThread() processing update audio patch list");
- sp<AudioPolicyService> svc = mService.promote();
+ svc = mService.promote();
if (svc == 0) {
break;
}
@@ -542,9 +543,16 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
if (mAudioCommands.isEmpty()) {
release_wake_lock(mName.string());
}
- ALOGV("AudioCommandThread() going to sleep");
- mWaitWorkCV.waitRelative(mLock, waitTime);
- ALOGV("AudioCommandThread() waking up");
+ // release mLock before releasing strong reference on the service as
+ // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock.
+ mLock.unlock();
+ svc.clear();
+ mLock.lock();
+ if (!exitPending()) {
+ ALOGV("AudioCommandThread() going to sleep");
+ mWaitWorkCV.waitRelative(mLock, waitTime);
+ ALOGV("AudioCommandThread() waking up");
+ }
}
mLock.unlock();
return false;
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 40f589b..66d9cad 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -539,7 +539,7 @@ private:
sp<AudioCommandThread> mOutputCommandThread; // process stop and release output
struct audio_policy_device *mpAudioPolicyDev;
struct audio_policy *mpAudioPolicy;
- AudioPolicyManager *mAudioPolicyManager;
+ AudioPolicyInterface *mAudioPolicyManager;
AudioPolicyClient *mAudioPolicyClient;
KeyedVector< audio_source_t, InputSourceDesc* > mInputSources;
diff --git a/services/camera/libcameraservice/utils/CameraTraces.cpp b/services/camera/libcameraservice/utils/CameraTraces.cpp
index 346e15f..374dc5e 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.cpp
+++ b/services/camera/libcameraservice/utils/CameraTraces.cpp
@@ -74,10 +74,10 @@ status_t CameraTraces::dump(int fd, const Vector<String16> &args __attribute__((
return BAD_VALUE;
}
- fdprintf(fd, "Camera traces (%zu):\n", pcsList.size());
+ dprintf(fd, "Camera traces (%zu):\n", pcsList.size());
if (pcsList.empty()) {
- fdprintf(fd, " No camera traces collected.\n");
+ dprintf(fd, " No camera traces collected.\n");
}
// Print newest items first
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 0c7fbbd..41dab1f 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -60,7 +60,7 @@ status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused)
static const String16 sDump("android.permission.DUMP");
if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA ||
PermissionCache::checkCallingPermission(sDump))) {
- fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n",
+ dprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
return NO_ERROR;
@@ -74,7 +74,7 @@ status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused)
for (size_t i = 0; i < namedReaders.size(); i++) {
const NamedReader& namedReader = namedReaders[i];
if (fd >= 0) {
- fdprintf(fd, "\n%s:\n", namedReader.name());
+ dprintf(fd, "\n%s:\n", namedReader.name());
} else {
ALOGI("%s:", namedReader.name());
}
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
new file mode 100644
index 0000000..b7ccaab
--- /dev/null
+++ b/services/soundtrigger/Android.mk
@@ -0,0 +1,41 @@
+# Copyright 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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)
+
+
+ifeq ($(SOUND_TRIGGER_USE_STUB_MODULE), 1)
+ LOCAL_CFLAGS += -DSOUND_TRIGGER_USE_STUB_MODULE
+endif
+
+LOCAL_SRC_FILES:= \
+ SoundTriggerHwService.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+ libui \
+ liblog \
+ libutils \
+ libbinder \
+ libcutils \
+ libhardware \
+ libsoundtrigger
+
+#LOCAL_C_INCLUDES += \
+
+
+LOCAL_MODULE:= libsoundtriggerservice
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
new file mode 100644
index 0000000..fa59388
--- /dev/null
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 "SoundTriggerHwService"
+//#define LOG_NDEBUG 0
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <hardware/hardware.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include "SoundTriggerHwService.h"
+#include <system/sound_trigger.h>
+#include <hardware/sound_trigger.h>
+
+namespace android {
+
+#ifdef SOUND_TRIGGER_USE_STUB_MODULE
+#define HW_MODULE_PREFIX "stub"
+#else
+#define HW_MODULE_PREFIX "primary"
+#endif
+
+SoundTriggerHwService::SoundTriggerHwService()
+ : BnSoundTriggerHwService(),
+ mNextUniqueId(1)
+{
+}
+
+void SoundTriggerHwService::onFirstRef()
+{
+ const hw_module_t *mod;
+ int rc;
+ sound_trigger_hw_device *dev;
+
+ rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, &mod);
+ if (rc != 0) {
+ ALOGE("couldn't load sound trigger module %s.%s (%s)",
+ SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+ return;
+ }
+ rc = sound_trigger_hw_device_open(mod, &dev);
+ if (rc != 0) {
+ ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
+ SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+ return;
+ }
+ if (dev->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
+ ALOGE("wrong sound trigger hw device version %04x", dev->common.version);
+ return;
+ }
+
+ sound_trigger_module_descriptor descriptor;
+ rc = dev->get_properties(dev, &descriptor.properties);
+ if (rc != 0) {
+ ALOGE("could not read implementation properties");
+ return;
+ }
+ descriptor.handle =
+ (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
+ ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
+ descriptor.handle);
+
+ sp<ISoundTriggerClient> client;
+ sp<Module> module = new Module(this, dev, descriptor, client);
+ mModules.add(descriptor.handle, module);
+ mCallbackThread = new CallbackThread(this);
+}
+
+SoundTriggerHwService::~SoundTriggerHwService()
+{
+ if (mCallbackThread != 0) {
+ mCallbackThread->exit();
+ }
+ for (size_t i = 0; i < mModules.size(); i++) {
+ sound_trigger_hw_device_close(mModules.valueAt(i)->hwDevice());
+ }
+}
+
+status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
+ uint32_t *numModules)
+{
+ ALOGV("listModules");
+ AutoMutex lock(mServiceLock);
+ if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
+ return BAD_VALUE;
+ }
+ size_t maxModules = *numModules;
+ *numModules = mModules.size();
+ for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
+ modules[i] = mModules.valueAt(i)->descriptor();
+ }
+ return NO_ERROR;
+}
+
+status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
+ const sp<ISoundTriggerClient>& client,
+ sp<ISoundTrigger>& moduleInterface)
+{
+ ALOGV("attach module %d", handle);
+ AutoMutex lock(mServiceLock);
+ moduleInterface.clear();
+ if (client == 0) {
+ return BAD_VALUE;
+ }
+ ssize_t index = mModules.indexOfKey(handle);
+ if (index < 0) {
+ return BAD_VALUE;
+ }
+ sp<Module> module = mModules.valueAt(index);
+
+ module->setClient(client);
+ client->asBinder()->linkToDeath(module);
+ moduleInterface = module;
+
+ return NO_ERROR;
+}
+
+void SoundTriggerHwService::detachModule(sp<Module> module) {
+ AutoMutex lock(mServiceLock);
+ ALOGV("detachModule");
+ module->clearClient();
+}
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 60000;
+
+static bool tryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleep);
+ }
+ return locked;
+}
+
+status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
+ String8 result;
+ if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+ result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
+ write(fd, result.string(), result.size());
+ } else {
+ bool locked = tryLock(mServiceLock);
+ // failed to lock - SoundTriggerHwService is probably deadlocked
+ if (!locked) {
+ result.append("SoundTriggerHwService may be deadlocked\n");
+ write(fd, result.string(), result.size());
+ }
+
+ if (locked) mServiceLock.unlock();
+ }
+ return NO_ERROR;
+}
+
+status_t SoundTriggerHwService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
+}
+
+
+// static
+void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
+ void *cookie)
+{
+ Module *module = (Module *)cookie;
+ if (module == NULL) {
+ return;
+ }
+ module->sendRecognitionEvent(event);
+}
+
+
+void SoundTriggerHwService::sendRecognitionEvent(const sp<RecognitionEvent>& event)
+{
+ mCallbackThread->sendRecognitionEvent(event);
+}
+
+void SoundTriggerHwService::onRecognitionEvent(const sp<RecognitionEvent>& event)
+{
+ ALOGV("onRecognitionEvent");
+ sp<Module> module;
+ {
+ AutoMutex lock(mServiceLock);
+ module = event->mModule.promote();
+ if (module == 0) {
+ return;
+ }
+ }
+ module->onRecognitionEvent(event->mEventMemory);
+}
+
+// static
+void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event __unused,
+ void *cookie)
+{
+ Module *module = (Module *)cookie;
+
+}
+
+#undef LOG_TAG
+#define LOG_TAG "SoundTriggerHwService::CallbackThread"
+
+SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
+ : mService(service)
+{
+}
+
+SoundTriggerHwService::CallbackThread::~CallbackThread()
+{
+ mEventQueue.clear();
+}
+
+void SoundTriggerHwService::CallbackThread::onFirstRef()
+{
+ run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+bool SoundTriggerHwService::CallbackThread::threadLoop()
+{
+ while (!exitPending()) {
+ sp<RecognitionEvent> event;
+ sp<SoundTriggerHwService> service;
+ {
+ Mutex::Autolock _l(mCallbackLock);
+ while (mEventQueue.isEmpty() && !exitPending()) {
+ ALOGV("CallbackThread::threadLoop() sleep");
+ mCallbackCond.wait(mCallbackLock);
+ ALOGV("CallbackThread::threadLoop() wake up");
+ }
+ if (exitPending()) {
+ break;
+ }
+ event = mEventQueue[0];
+ mEventQueue.removeAt(0);
+ service = mService.promote();
+ }
+ if (service != 0) {
+ service->onRecognitionEvent(event);
+ }
+ }
+ return false;
+}
+
+void SoundTriggerHwService::CallbackThread::exit()
+{
+ Mutex::Autolock _l(mCallbackLock);
+ requestExit();
+ mCallbackCond.broadcast();
+}
+
+void SoundTriggerHwService::CallbackThread::sendRecognitionEvent(
+ const sp<SoundTriggerHwService::RecognitionEvent>& event)
+{
+ AutoMutex lock(mCallbackLock);
+ mEventQueue.add(event);
+ mCallbackCond.signal();
+}
+
+SoundTriggerHwService::RecognitionEvent::RecognitionEvent(
+ sp<IMemory> eventMemory,
+ wp<Module> module)
+ : mEventMemory(eventMemory), mModule(module)
+{
+}
+
+SoundTriggerHwService::RecognitionEvent::~RecognitionEvent()
+{
+}
+
+#undef LOG_TAG
+#define LOG_TAG "SoundTriggerHwService::Module"
+
+SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
+ sound_trigger_hw_device* hwDevice,
+ sound_trigger_module_descriptor descriptor,
+ const sp<ISoundTriggerClient>& client)
+ : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
+ mClient(client)
+{
+}
+
+SoundTriggerHwService::Module::~Module() {
+}
+
+void SoundTriggerHwService::Module::detach() {
+ ALOGV("detach()");
+ {
+ AutoMutex lock(mLock);
+ for (size_t i = 0; i < mModels.size(); i++) {
+ sp<Model> model = mModels.valueAt(i);
+ ALOGV("detach() unloading model %d", model->mHandle);
+ if (model->mState == Model::STATE_ACTIVE) {
+ mHwDevice->stop_recognition(mHwDevice, model->mHandle);
+ model->deallocateMemory();
+ }
+ mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
+ }
+ mModels.clear();
+ }
+ if (mClient != 0) {
+ mClient->asBinder()->unlinkToDeath(this);
+ }
+ sp<SoundTriggerHwService> service = mService.promote();
+ if (service == 0) {
+ return;
+ }
+ service->detachModule(this);
+}
+
+status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
+ sound_model_handle_t *handle)
+{
+ ALOGV("loadSoundModel() handle");
+
+ if (modelMemory == 0 || modelMemory->pointer() == NULL) {
+ ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
+ return BAD_VALUE;
+ }
+ struct sound_trigger_sound_model *sound_model =
+ (struct sound_trigger_sound_model *)modelMemory->pointer();
+
+ AutoMutex lock(mLock);
+ status_t status = mHwDevice->load_sound_model(mHwDevice,
+ sound_model,
+ SoundTriggerHwService::soundModelCallback,
+ this,
+ handle);
+ if (status == NO_ERROR) {
+ mModels.replaceValueFor(*handle, new Model(*handle));
+ }
+
+ return status;
+}
+
+status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
+{
+ ALOGV("unloadSoundModel() model handle %d", handle);
+
+ AutoMutex lock(mLock);
+ ssize_t index = mModels.indexOfKey(handle);
+ if (index < 0) {
+ return BAD_VALUE;
+ }
+ sp<Model> model = mModels.valueAt(index);
+ mModels.removeItem(handle);
+ if (model->mState == Model::STATE_ACTIVE) {
+ mHwDevice->stop_recognition(mHwDevice, model->mHandle);
+ model->deallocateMemory();
+ }
+ return mHwDevice->unload_sound_model(mHwDevice, handle);
+}
+
+status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
+ const sp<IMemory>& dataMemory)
+{
+ ALOGV("startRecognition() model handle %d", handle);
+
+ if (dataMemory != 0 && dataMemory->pointer() == NULL) {
+ ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
+ return BAD_VALUE;
+
+ }
+ AutoMutex lock(mLock);
+ sp<Model> model = getModel(handle);
+ if (model == 0) {
+ return BAD_VALUE;
+ }
+
+ if (model->mState == Model::STATE_ACTIVE) {
+ return INVALID_OPERATION;
+ }
+ model->mState = Model::STATE_ACTIVE;
+
+ char *data = NULL;
+ unsigned int data_size = 0;
+ if (dataMemory != 0 && dataMemory->size() != 0) {
+ data_size = (unsigned int)dataMemory->size();
+ data = (char *)dataMemory->pointer();
+ ALOGV("startRecognition() data size %d data %d - %d",
+ data_size, data[0], data[data_size - 1]);
+ }
+
+ //TODO: get capture handle and device from audio policy service
+ audio_io_handle_t capture_handle = 0;
+ return mHwDevice->start_recognition(mHwDevice, handle, capture_handle, AUDIO_DEVICE_NONE,
+ SoundTriggerHwService::recognitionCallback,
+ this,
+ data_size,
+ data);
+}
+
+status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
+{
+ ALOGV("stopRecognition() model handle %d", handle);
+
+ AutoMutex lock(mLock);
+ sp<Model> model = getModel(handle);
+ if (model == 0) {
+ return BAD_VALUE;
+ }
+
+ if (model->mState != Model::STATE_ACTIVE) {
+ return INVALID_OPERATION;
+ }
+ mHwDevice->stop_recognition(mHwDevice, handle);
+ model->deallocateMemory();
+ model->mState = Model::STATE_IDLE;
+ return NO_ERROR;
+}
+
+void SoundTriggerHwService::Module::sendRecognitionEvent(
+ struct sound_trigger_recognition_event *event)
+{
+ sp<SoundTriggerHwService> service;
+ sp<IMemory> eventMemory;
+ ALOGV("sendRecognitionEvent for model %d", event->model);
+ {
+ AutoMutex lock(mLock);
+ sp<Model> model = getModel(event->model);
+ if (model == 0) {
+ return;
+ }
+ if (model->mState != Model::STATE_ACTIVE) {
+ ALOGV("sendRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
+ return;
+ }
+ if (mClient == 0) {
+ return;
+ }
+ service = mService.promote();
+ if (service == 0) {
+ return;
+ }
+
+ //sanitize event
+ switch (event->type) {
+ case SOUND_MODEL_TYPE_KEYPHRASE:
+ ALOGW_IF(event->data_offset !=
+ sizeof(struct sound_trigger_phrase_recognition_event),
+ "sendRecognitionEvent(): invalid data offset %u for keyphrase event type",
+ event->data_offset);
+ event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
+ break;
+ case SOUND_MODEL_TYPE_UNKNOWN:
+ ALOGW_IF(event->data_offset !=
+ sizeof(struct sound_trigger_recognition_event),
+ "sendRecognitionEvent(): invalid data offset %u for unknown event type",
+ event->data_offset);
+ event->data_offset = sizeof(struct sound_trigger_recognition_event);
+ break;
+ default:
+ return;
+ }
+
+ size_t size = event->data_offset + event->data_size;
+ eventMemory = model->allocateMemory(size);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ return;
+ }
+ memcpy(eventMemory->pointer(), event, size);
+ }
+ service->sendRecognitionEvent(new RecognitionEvent(eventMemory, this));
+}
+
+void SoundTriggerHwService::Module::onRecognitionEvent(sp<IMemory> eventMemory)
+{
+ ALOGV("Module::onRecognitionEvent");
+
+ AutoMutex lock(mLock);
+
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ return;
+ }
+ struct sound_trigger_recognition_event *event =
+ (struct sound_trigger_recognition_event *)eventMemory->pointer();
+
+ sp<Model> model = getModel(event->model);
+ if (model == 0) {
+ ALOGI("%s model == 0", __func__);
+ return;
+ }
+ if (model->mState != Model::STATE_ACTIVE) {
+ ALOGV("onRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
+ return;
+ }
+ if (mClient == 0) {
+ ALOGI("%s mClient == 0", __func__);
+ return;
+ }
+ mClient->onRecognitionEvent(eventMemory);
+ model->mState = Model::STATE_IDLE;
+ model->deallocateMemory();
+}
+
+sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
+ sound_model_handle_t handle)
+{
+ sp<Model> model;
+ ssize_t index = mModels.indexOfKey(handle);
+ if (index >= 0) {
+ model = mModels.valueAt(index);
+ }
+ return model;
+}
+
+void SoundTriggerHwService::Module::binderDied(
+ const wp<IBinder> &who __unused) {
+ ALOGW("client binder died for module %d", mDescriptor.handle);
+ detach();
+}
+
+
+SoundTriggerHwService::Model::Model(sound_model_handle_t handle) :
+ mHandle(handle), mState(STATE_IDLE), mInputHandle(AUDIO_IO_HANDLE_NONE),
+ mCaptureSession(AUDIO_SESSION_ALLOCATE),
+ mMemoryDealer(new MemoryDealer(sizeof(struct sound_trigger_recognition_event),
+ "SoundTriggerHwService::Event"))
+{
+
+}
+
+
+sp<IMemory> SoundTriggerHwService::Model::allocateMemory(size_t size)
+{
+ sp<IMemory> memory;
+ if (mMemoryDealer->getMemoryHeap()->getSize() < size) {
+ mMemoryDealer = new MemoryDealer(size, "SoundTriggerHwService::Event");
+ }
+ memory = mMemoryDealer->allocate(size);
+ return memory;
+}
+
+void SoundTriggerHwService::Model::deallocateMemory()
+{
+ mMemoryDealer->deallocate(0);
+}
+
+status_t SoundTriggerHwService::Module::dump(int fd __unused,
+ const Vector<String16>& args __unused) {
+ String8 result;
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
new file mode 100644
index 0000000..377f2a1
--- /dev/null
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -0,0 +1,185 @@
+/*
+ * 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_SOUNDTRIGGER_HAL_SERVICE_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
+
+#include <utils/Vector.h>
+//#include <binder/AppOpsManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/BinderService.h>
+#include <binder/IAppOpsCallback.h>
+#include <soundtrigger/ISoundTriggerHwService.h>
+#include <soundtrigger/ISoundTrigger.h>
+#include <soundtrigger/ISoundTriggerClient.h>
+#include <system/sound_trigger.h>
+#include <hardware/sound_trigger.h>
+
+namespace android {
+
+class MemoryHeapBase;
+
+class SoundTriggerHwService :
+ public BinderService<SoundTriggerHwService>,
+ public BnSoundTriggerHwService
+{
+ friend class BinderService<SoundTriggerHwService>;
+public:
+ class Module;
+
+ static char const* getServiceName() { return "media.sound_trigger_hw"; }
+
+ SoundTriggerHwService();
+ virtual ~SoundTriggerHwService();
+
+ // ISoundTriggerHwService
+ virtual status_t listModules(struct sound_trigger_module_descriptor *modules,
+ uint32_t *numModules);
+
+ virtual status_t attach(const sound_trigger_module_handle_t handle,
+ const sp<ISoundTriggerClient>& client,
+ sp<ISoundTrigger>& module);
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ class Model : public RefBase {
+ public:
+
+ enum {
+ STATE_IDLE,
+ STATE_ACTIVE
+ };
+
+ Model(sound_model_handle_t handle);
+ ~Model() {}
+
+ sp<IMemory> allocateMemory(size_t size);
+ void deallocateMemory();
+
+ sound_model_handle_t mHandle;
+ int mState;
+ audio_io_handle_t mInputHandle;
+ audio_session_t mCaptureSession;
+ sp<MemoryDealer> mMemoryDealer;
+ };
+
+ class Module : public virtual RefBase,
+ public BnSoundTrigger,
+ public IBinder::DeathRecipient {
+ public:
+
+ Module(const sp<SoundTriggerHwService>& service,
+ sound_trigger_hw_device* hwDevice,
+ sound_trigger_module_descriptor descriptor,
+ const sp<ISoundTriggerClient>& client);
+
+ virtual ~Module();
+
+ virtual void detach();
+
+ virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
+ sound_model_handle_t *handle);
+
+ virtual status_t unloadSoundModel(sound_model_handle_t handle);
+
+ virtual status_t startRecognition(sound_model_handle_t handle,
+ const sp<IMemory>& dataMemory);
+ virtual status_t stopRecognition(sound_model_handle_t handle);
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+
+ sound_trigger_hw_device *hwDevice() const { return mHwDevice; }
+ struct sound_trigger_module_descriptor descriptor() { return mDescriptor; }
+ void setClient(sp<ISoundTriggerClient> client) { mClient = client; }
+ void clearClient() { mClient.clear(); }
+ sp<ISoundTriggerClient> client() { return mClient; }
+
+ void sendRecognitionEvent(struct sound_trigger_recognition_event *event);
+ void onRecognitionEvent(sp<IMemory> eventMemory);
+
+ sp<Model> getModel(sound_model_handle_t handle);
+
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder> &who);
+
+ private:
+ Mutex mLock;
+ wp<SoundTriggerHwService> mService;
+ struct sound_trigger_hw_device* mHwDevice;
+ struct sound_trigger_module_descriptor mDescriptor;
+ sp<ISoundTriggerClient> mClient;
+ DefaultKeyedVector< sound_model_handle_t, sp<Model> > mModels;
+ }; // class Module
+
+ class RecognitionEvent : public RefBase {
+ public:
+
+ RecognitionEvent(sp<IMemory> eventMemory, wp<Module> module);
+
+ virtual ~RecognitionEvent();
+
+ sp<IMemory> mEventMemory;
+ wp<Module> mModule;
+ };
+
+ class CallbackThread : public Thread {
+ public:
+
+ CallbackThread(const wp<SoundTriggerHwService>& service);
+
+ virtual ~CallbackThread();
+
+ // Thread virtuals
+ virtual bool threadLoop();
+
+ // RefBase
+ virtual void onFirstRef();
+
+ void exit();
+ void sendRecognitionEvent(const sp<RecognitionEvent>& event);
+
+ private:
+ wp<SoundTriggerHwService> mService;
+ Condition mCallbackCond;
+ Mutex mCallbackLock;
+ Vector< sp<RecognitionEvent> > mEventQueue;
+ };
+
+ void detachModule(sp<Module> module);
+
+ static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie);
+ void sendRecognitionEvent(const sp<RecognitionEvent>& event);
+ void onRecognitionEvent(const sp<RecognitionEvent>& event);
+
+ static void soundModelCallback(struct sound_trigger_model_event *event, void *cookie);
+
+private:
+
+ virtual void onFirstRef();
+
+ Mutex mServiceLock;
+ volatile int32_t mNextUniqueId;
+ DefaultKeyedVector< sound_trigger_module_handle_t, sp<Module> > mModules;
+ sp<CallbackThread> mCallbackThread;
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
diff --git a/soundtrigger/Android.mk b/soundtrigger/Android.mk
new file mode 100644
index 0000000..d91c4c2
--- /dev/null
+++ b/soundtrigger/Android.mk
@@ -0,0 +1,38 @@
+# Copyright 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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:= \
+ SoundTrigger.cpp \
+ ISoundTrigger.cpp \
+ ISoundTriggerClient.cpp \
+ ISoundTriggerHwService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ liblog \
+ libbinder \
+ libhardware
+
+#LOCAL_C_INCLUDES += \
+ system/media/camera/include \
+ system/media/private/camera/include
+
+LOCAL_MODULE:= libsoundtrigger
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
new file mode 100644
index 0000000..42280d1
--- /dev/null
+++ b/soundtrigger/ISoundTrigger.cpp
@@ -0,0 +1,177 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR 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 "ISoundTrigger"
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <binder/IMemory.h>
+#include <soundtrigger/ISoundTrigger.h>
+#include <soundtrigger/ISoundTriggerHwService.h>
+#include <soundtrigger/ISoundTriggerClient.h>
+#include <system/sound_trigger.h>
+
+namespace android {
+
+enum {
+ DETACH = IBinder::FIRST_CALL_TRANSACTION,
+ LOAD_SOUND_MODEL,
+ UNLOAD_SOUND_MODEL,
+ START_RECOGNITION,
+ STOP_RECOGNITION,
+};
+
+class BpSoundTrigger: public BpInterface<ISoundTrigger>
+{
+public:
+ BpSoundTrigger(const sp<IBinder>& impl)
+ : BpInterface<ISoundTrigger>(impl)
+ {
+ }
+
+ void detach()
+ {
+ ALOGV("detach");
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+ remote()->transact(DETACH, data, &reply);
+ }
+
+ status_t loadSoundModel(const sp<IMemory>& modelMemory,
+ sound_model_handle_t *handle)
+ {
+ if (modelMemory == 0 || handle == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+ data.writeStrongBinder(modelMemory->asBinder());
+ status_t status = remote()->transact(LOAD_SOUND_MODEL, data, &reply);
+ if (status != NO_ERROR ||
+ (status = (status_t)reply.readInt32()) != NO_ERROR) {
+ return status;
+ }
+ reply.read(handle, sizeof(sound_model_handle_t));
+ return status;
+ }
+
+ virtual status_t unloadSoundModel(sound_model_handle_t handle)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+ data.write(&handle, sizeof(sound_model_handle_t));
+ status_t status = remote()->transact(UNLOAD_SOUND_MODEL, data, &reply);
+ if (status != NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t startRecognition(sound_model_handle_t handle,
+ const sp<IMemory>& dataMemory)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+ data.write(&handle, sizeof(sound_model_handle_t));
+ if (dataMemory == 0) {
+ data.writeInt32(0);
+ } else {
+ data.writeInt32(dataMemory->size());
+ }
+ data.writeStrongBinder(dataMemory->asBinder());
+ status_t status = remote()->transact(START_RECOGNITION, data, &reply);
+ if (status != NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t stopRecognition(sound_model_handle_t handle)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+ data.write(&handle, sizeof(sound_model_handle_t));
+ status_t status = remote()->transact(STOP_RECOGNITION, data, &reply);
+ if (status != NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(SoundTrigger, "android.hardware.ISoundTrigger");
+
+// ----------------------------------------------------------------------
+
+status_t BnSoundTrigger::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case DETACH: {
+ ALOGV("DETACH");
+ CHECK_INTERFACE(ISoundTrigger, data, reply);
+ detach();
+ return NO_ERROR;
+ } break;
+ case LOAD_SOUND_MODEL: {
+ CHECK_INTERFACE(ISoundTrigger, data, reply);
+ sp<IMemory> modelMemory = interface_cast<IMemory>(
+ data.readStrongBinder());
+ sound_model_handle_t handle;
+ status_t status = loadSoundModel(modelMemory, &handle);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->write(&handle, sizeof(sound_model_handle_t));
+ }
+ return NO_ERROR;
+ }
+ case UNLOAD_SOUND_MODEL: {
+ CHECK_INTERFACE(ISoundTrigger, data, reply);
+ sound_model_handle_t handle;
+ data.read(&handle, sizeof(sound_model_handle_t));
+ status_t status = unloadSoundModel(handle);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+ case START_RECOGNITION: {
+ CHECK_INTERFACE(ISoundTrigger, data, reply);
+ sound_model_handle_t handle;
+ data.read(&handle, sizeof(sound_model_handle_t));
+ sp<IMemory> dataMemory;
+ if (data.readInt32() != 0) {
+ dataMemory = interface_cast<IMemory>(data.readStrongBinder());
+ }
+ status_t status = startRecognition(handle, dataMemory);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+ case STOP_RECOGNITION: {
+ CHECK_INTERFACE(ISoundTrigger, data, reply);
+ sound_model_handle_t handle;
+ data.read(&handle, sizeof(sound_model_handle_t));
+ status_t status = stopRecognition(handle);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/soundtrigger/ISoundTriggerClient.cpp b/soundtrigger/ISoundTriggerClient.cpp
new file mode 100644
index 0000000..1d0c0ec
--- /dev/null
+++ b/soundtrigger/ISoundTriggerClient.cpp
@@ -0,0 +1,75 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <soundtrigger/ISoundTriggerClient.h>
+
+namespace android {
+
+enum {
+ ON_RECOGNITION_EVENT = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpSoundTriggerClient: public BpInterface<ISoundTriggerClient>
+{
+
+public:
+ BpSoundTriggerClient(const sp<IBinder>& impl)
+ : BpInterface<ISoundTriggerClient>(impl)
+ {
+ }
+
+ virtual void onRecognitionEvent(const sp<IMemory>& eventMemory)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
+ data.writeStrongBinder(eventMemory->asBinder());
+ remote()->transact(ON_RECOGNITION_EVENT,
+ data,
+ &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(SoundTriggerClient,
+ "android.hardware.ISoundTriggerClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnSoundTriggerClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case ON_RECOGNITION_EVENT: {
+ CHECK_INTERFACE(ISoundTriggerClient, data, reply);
+ sp<IMemory> eventMemory = interface_cast<IMemory>(
+ data.readStrongBinder());
+ onRecognitionEvent(eventMemory);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
new file mode 100644
index 0000000..c9a0c24
--- /dev/null
+++ b/soundtrigger/ISoundTriggerHwService.cpp
@@ -0,0 +1,150 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR 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 "BpSoundTriggerHwService"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <soundtrigger/ISoundTriggerHwService.h>
+#include <soundtrigger/ISoundTrigger.h>
+#include <soundtrigger/ISoundTriggerClient.h>
+
+namespace android {
+
+enum {
+ LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
+ ATTACH,
+};
+
+class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
+{
+public:
+ BpSoundTriggerHwService(const sp<IBinder>& impl)
+ : BpInterface<ISoundTriggerHwService>(impl)
+ {
+ }
+
+ virtual status_t listModules(struct sound_trigger_module_descriptor *modules,
+ uint32_t *numModules)
+ {
+ if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
+ unsigned int numModulesReq = (modules == NULL) ? 0 : *numModules;
+ data.writeInt32(numModulesReq);
+ status_t status = remote()->transact(LIST_MODULES, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ *numModules = (unsigned int)reply.readInt32();
+ }
+ ALOGV("listModules() status %d got *numModules %d", status, *numModules);
+ if (status == NO_ERROR) {
+ if (numModulesReq > *numModules) {
+ numModulesReq = *numModules;
+ }
+ if (numModulesReq > 0) {
+ reply.read(modules, numModulesReq * sizeof(struct sound_trigger_module_descriptor));
+ }
+ }
+ return status;
+ }
+
+ virtual status_t attach(const sound_trigger_module_handle_t handle,
+ const sp<ISoundTriggerClient>& client,
+ sp<ISoundTrigger>& module)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
+ data.write(&handle, sizeof(sound_trigger_module_handle_t));
+ data.writeStrongBinder(client->asBinder());
+ remote()->transact(ATTACH, data, &reply);
+ status_t status = reply.readInt32();
+ if (reply.readInt32() != 0) {
+ module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
+ }
+ return status;
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
+
+// ----------------------------------------------------------------------
+
+status_t BnSoundTriggerHwService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case LIST_MODULES: {
+ CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
+ unsigned int numModulesReq = data.readInt32();
+ unsigned int numModules = numModulesReq;
+ struct sound_trigger_module_descriptor *modules =
+ (struct sound_trigger_module_descriptor *)calloc(numModulesReq,
+ sizeof(struct sound_trigger_module_descriptor));
+ status_t status = listModules(modules, &numModules);
+ reply->writeInt32(status);
+ reply->writeInt32(numModules);
+ ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
+
+ if (status == NO_ERROR) {
+ if (numModulesReq > numModules) {
+ numModulesReq = numModules;
+ }
+ reply->write(modules,
+ numModulesReq * sizeof(struct sound_trigger_module_descriptor));
+ }
+ free(modules);
+ return NO_ERROR;
+ }
+
+ case ATTACH: {
+ CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
+ sound_trigger_module_handle_t handle;
+ data.read(&handle, sizeof(sound_trigger_module_handle_t));
+ sp<ISoundTriggerClient> client =
+ interface_cast<ISoundTriggerClient>(data.readStrongBinder());
+ sp<ISoundTrigger> module;
+ status_t status = attach(handle, client, module);
+ reply->writeInt32(status);
+ if (module != 0) {
+ reply->writeInt32(1);
+ reply->writeStrongBinder(module->asBinder());
+ } else {
+ reply->writeInt32(0);
+ }
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
new file mode 100644
index 0000000..e43acd0
--- /dev/null
+++ b/soundtrigger/SoundTrigger.cpp
@@ -0,0 +1,253 @@
+/*
+**
+** Copyright (C) 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR 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 "SoundTrigger"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
+
+#include <soundtrigger/SoundTrigger.h>
+#include <soundtrigger/ISoundTrigger.h>
+#include <soundtrigger/ISoundTriggerHwService.h>
+#include <soundtrigger/ISoundTriggerClient.h>
+#include <soundtrigger/SoundTriggerCallback.h>
+
+namespace android {
+
+namespace {
+ sp<ISoundTriggerHwService> gSoundTriggerHwService;
+ const int kSoundTriggerHwServicePollDelay = 500000; // 0.5s
+ const char* kSoundTriggerHwServiceName = "media.sound_trigger_hw";
+ Mutex gLock;
+
+ class DeathNotifier : public IBinder::DeathRecipient
+ {
+ public:
+ DeathNotifier() {
+ }
+
+ virtual void binderDied(const wp<IBinder>& who __unused) {
+ ALOGV("binderDied");
+ Mutex::Autolock _l(gLock);
+ gSoundTriggerHwService.clear();
+ ALOGW("Sound trigger service died!");
+ }
+ };
+
+ sp<DeathNotifier> gDeathNotifier;
+}; // namespace anonymous
+
+const sp<ISoundTriggerHwService>& SoundTrigger::getSoundTriggerHwService()
+{
+ Mutex::Autolock _l(gLock);
+ if (gSoundTriggerHwService.get() == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16(kSoundTriggerHwServiceName));
+ if (binder != 0) {
+ break;
+ }
+ ALOGW("SoundTriggerHwService not published, waiting...");
+ usleep(kSoundTriggerHwServicePollDelay);
+ } while(true);
+ if (gDeathNotifier == NULL) {
+ gDeathNotifier = new DeathNotifier();
+ }
+ binder->linkToDeath(gDeathNotifier);
+ gSoundTriggerHwService = interface_cast<ISoundTriggerHwService>(binder);
+ }
+ ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?");
+ return gSoundTriggerHwService;
+}
+
+// Static methods
+status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modules,
+ uint32_t *numModules)
+{
+ ALOGV("listModules()");
+ const sp<ISoundTriggerHwService>& service = getSoundTriggerHwService();
+ if (service == 0) {
+ return NO_INIT;
+ }
+ return service->listModules(modules, numModules);
+}
+
+sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module,
+ const sp<SoundTriggerCallback>& callback)
+{
+ ALOGV("attach()");
+ sp<SoundTrigger> soundTrigger;
+ const sp<ISoundTriggerHwService>& service = getSoundTriggerHwService();
+ if (service == 0) {
+ return soundTrigger;
+ }
+ soundTrigger = new SoundTrigger(module, callback);
+ status_t status = service->attach(module, soundTrigger, soundTrigger->mISoundTrigger);
+
+ if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
+ soundTrigger->mISoundTrigger->asBinder()->linkToDeath(soundTrigger);
+ } else {
+ ALOGW("Error %d connecting to sound trigger service", status);
+ soundTrigger.clear();
+ }
+ return soundTrigger;
+}
+
+
+// SoundTrigger
+SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module,
+ const sp<SoundTriggerCallback>& callback)
+ : mModule(module), mCallback(callback)
+{
+}
+
+SoundTrigger::~SoundTrigger()
+{
+ if (mISoundTrigger != 0) {
+ mISoundTrigger->detach();
+ }
+}
+
+
+void SoundTrigger::detach() {
+ ALOGV("detach()");
+ Mutex::Autolock _l(mLock);
+ mCallback.clear();
+ if (mISoundTrigger != 0) {
+ mISoundTrigger->detach();
+ mISoundTrigger->asBinder()->unlinkToDeath(this);
+ mISoundTrigger = 0;
+ }
+}
+
+status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
+ sound_model_handle_t *handle)
+{
+ Mutex::Autolock _l(mLock);
+ if (mISoundTrigger == 0) {
+ return NO_INIT;
+ }
+
+ return mISoundTrigger->loadSoundModel(modelMemory, handle);
+}
+
+status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
+{
+ Mutex::Autolock _l(mLock);
+ if (mISoundTrigger == 0) {
+ return NO_INIT;
+ }
+ return mISoundTrigger->unloadSoundModel(handle);
+}
+
+status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
+ const sp<IMemory>& dataMemory)
+{
+ Mutex::Autolock _l(mLock);
+ if (mISoundTrigger == 0) {
+ return NO_INIT;
+ }
+ return mISoundTrigger->startRecognition(handle, dataMemory);
+}
+
+status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
+{
+ Mutex::Autolock _l(mLock);
+ if (mISoundTrigger == 0) {
+ return NO_INIT;
+ }
+ return mISoundTrigger->stopRecognition(handle);
+}
+
+// BpSoundTriggerClient
+void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
+{
+ Mutex::Autolock _l(mLock);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ return;
+ }
+
+ if (mCallback != 0) {
+ mCallback->onRecognitionEvent(
+ (struct sound_trigger_recognition_event *)eventMemory->pointer());
+ }
+}
+
+
+//IBinder::DeathRecipient
+void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
+ Mutex::Autolock _l(mLock);
+ ALOGW("SoundTrigger server binder Died ");
+ mISoundTrigger = 0;
+ if (mCallback != 0) {
+ mCallback->onServiceDied();
+ }
+}
+
+status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_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 SoundTrigger::guidToString(const sound_trigger_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