Merge "C2SoftAvcEnc: add support to use ih264e instead of ive structures"
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..9937b98
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,50 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+// DEPENDING ON IT IN YOUR PROJECT. ***
+package {
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-Unicode-DFS",
+ "legacy_by_exception_only", // by exception only
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
diff --git a/METADATA b/METADATA
index d97975c..aabda36 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,23 @@
+# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+# DEPENDING ON IT IN YOUR PROJECT. ***
third_party {
- license_type: NOTICE
+ # would be NOTICE save for Widevine Master License Agreement in:
+ # drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
+ # drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+ # drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
+ # drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
+ # drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+ # and patent disclaimers in:
+ # media/codec2/components/aac/patent_disclaimer.txt
+ # media/codec2/components/amr_nb_wb/patent_disclaimer.txt
+ # media/codec2/components/mp3/patent_disclaimer.txt
+ # media/codec2/components/mpeg4_h263/patent_disclaimer.txt
+ # media/codecs/amrnb/patent_disclaimer.txt
+ # media/codecs/amrwb/dec/patent_disclaimer.txt
+ # media/codecs/amrwb/enc/patent_disclaimer.txt
+ # media/codecs/m4v_h263/patent_disclaimer.txt
+ # media/codecs/mp3dec/patent_disclaimer.txt
+ # media/libstagefright/codecs/aacenc/patent_disclaimer.txt
+ license_type: BY_EXCEPTION_ONLY
}
diff --git a/OWNERS b/OWNERS
index 8f405e9..7f523a2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,10 @@
+chz@google.com
elaurent@google.com
etalvala@google.com
+hkuang@google.com
lajos@google.com
marcone@google.com
+
+# LON
+olly@google.com
+andrewlewis@google.com
diff --git a/apex/Android.bp b/apex/Android.bp
index 80e751c..dabf4c2 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
apex_defaults {
name: "com.android.media-defaults",
updatable: true,
@@ -31,6 +40,8 @@
"libmpeg2extractor",
"liboggextractor",
"libwavextractor",
+ // JNI
+ "libmediaparser-jni"
],
},
},
@@ -53,6 +64,9 @@
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
min_sdk_version: "29",
+ // Indicates that pre-installed version of this apex can be compressed.
+ // Whether it actually will be compressed is controlled on per-device basis.
+ compressible: true,
}
apex {
@@ -109,6 +123,9 @@
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
min_sdk_version: "29",
+ // Indicates that pre-installed version of this apex can be compressed.
+ // Whether it actually will be compressed is controlled on per-device basis.
+ compressible: true,
}
prebuilt_etc {
diff --git a/apex/manifest.json b/apex/manifest.json
index 4254bdf..ddd642e 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media",
- "version": 300900700
+ "version": 300000000
}
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index a3638d5..1f05d2e 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,6 +1,6 @@
{
"name": "com.android.media.swcodec",
- "version": 300900700,
+ "version": 300000000,
"requireNativeLibs": [
":sphal"
]
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index d86094e..4ff4d06 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
apex_test {
name: "test_com.android.media",
manifest: "test_manifest.json",
diff --git a/camera/Android.bp b/camera/Android.bp
index fa36bb3..93bc68d 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -12,6 +12,37 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_av_camera_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_camera_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-Unicode-DFS",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libcamera_client",
@@ -50,6 +81,7 @@
],
shared_libs: [
+ "libbase",
"libcutils",
"libutils",
"liblog",
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index aecb70a..0b0f584 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -29,6 +29,7 @@
#include <binder/IMemory.h>
#include <camera/CameraBase.h>
+#include <camera/CameraUtils.h>
// needed to instantiate
#include <camera/Camera.h>
@@ -124,9 +125,7 @@
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
- char value[PROPERTY_VALUE_MAX];
- property_get("config.disable_cameraservice", value, "0");
- if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) {
+ if (CameraUtils::isCameraServiceDisabled()) {
return gCameraService;
}
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 135384a..024311f 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -169,6 +169,11 @@
return entryCount() == 0;
}
+size_t CameraMetadata::bufferSize() const {
+ return (mBuffer == NULL) ? 0 :
+ get_camera_metadata_size(mBuffer);
+}
+
status_t CameraMetadata::sort() {
if (mLocked) {
ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 67fc116..af3c492 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -20,6 +20,7 @@
#include <camera/CameraUtils.h>
#include <media/hardware/HardwareAPI.h>
+#include <android-base/properties.h>
#include <system/window.h>
#include <system/graphics.h>
@@ -27,6 +28,8 @@
namespace android {
+const char *kCameraServiceDisabledProperty = "config.disable_cameraservice";
+
status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
/*out*/int32_t* transform) {
ALOGV("%s", __FUNCTION__);
@@ -122,4 +125,8 @@
return OK;
}
+bool CameraUtils::isCameraServiceDisabled() {
+ return base::GetBoolProperty(kCameraServiceDisabledProperty, false);
+}
+
} /* namespace android */
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index c02c81b..bef2ea0 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -142,7 +142,8 @@
camera_frame_metadata_t metadata;
if (data.dataAvail() > 0) {
metadata.number_of_faces = data.readInt32();
- if (metadata.number_of_faces <= 0 ||
+ // Zero faces is a valid case, to notify clients that no faces are now visible
+ if (metadata.number_of_faces < 0 ||
metadata.number_of_faces > (int32_t)(INT32_MAX / sizeof(camera_face_t))) {
ALOGE("%s: Too large face count: %d", __FUNCTION__, metadata.number_of_faces);
return BAD_VALUE;
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 09a333b..f58f20c 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_camera_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_camera_license"],
+}
+
cc_binary {
name: "cameraserver",
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index 9d1b5c7..e883ffa 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -128,6 +128,11 @@
bool isEmpty() const;
/**
+ * Return the allocated camera metadata buffer size in bytes.
+ */
+ size_t bufferSize() const;
+
+ /**
* Sort metadata buffer for faster find
*/
status_t sort();
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index f596f80..a397ccd 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -47,6 +47,11 @@
*/
static bool isNativeHandleMetadata(const sp<IMemory>& imageData);
+ /**
+ * Check if camera service is disabled on this device
+ */
+ static bool isCameraServiceDisabled();
+
private:
CameraUtils();
};
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 7ba82c1..24eaba6 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -16,6 +16,37 @@
// to refer to headers in parent directories and the headers live in
// frameworks/av/include.
+package {
+ default_applicable_licenses: ["frameworks_av_camera_ndk_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_camera_ndk_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-Unicode-DFS",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_library {
name: "libcamera2ndk",
symbol_file: "libcamera2ndk.map.txt",
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index c15c5a5..78974ae 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1361,31 +1361,11 @@
it->second.isSequenceCompleted = true;
}
- if (it->second.isSequenceCompleted && hasCallback) {
- auto cbIt = mSequenceCallbackMap.find(sequenceId);
- CallbackHolder cbh = cbIt->second;
-
- // send seq complete callback
- sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mContext);
- msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
- msg->setInt32(kSequenceIdKey, sequenceId);
- msg->setInt64(kFrameNumberKey, lastFrameNumber);
-
- // Clear the session sp before we send out the message
- // This will guarantee the rare case where the message is processed
- // before cbh goes out of scope and causing we call the session
- // destructor while holding device lock
- cbh.mSession.clear();
- postSessionMsgAndCleanup(msg);
- }
}
if (it->second.isSequenceCompleted && it->second.isInflightCompleted) {
- if (mSequenceCallbackMap.find(sequenceId) != mSequenceCallbackMap.end()) {
- mSequenceCallbackMap.erase(sequenceId);
- }
+ sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
+
it = mSequenceLastFrameNumberMap.erase(it);
ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
} else {
@@ -1412,13 +1392,7 @@
lastCompletedRegularFrameNumber);
if (lastFrameNumber <= lastCompletedRegularFrameNumber) {
if (it->second.isSequenceCompleted) {
- // Check if there is callback for this sequence
- // This should not happen because we always register callback (with nullptr inside)
- if (mSequenceCallbackMap.count(sequenceId) == 0) {
- ALOGW("No callback found for sequenceId %d", sequenceId);
- } else {
- mSequenceCallbackMap.erase(sequenceId);
- }
+ sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
it = mSequenceLastFrameNumberMap.erase(it);
ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
@@ -1709,5 +1683,33 @@
return ret;
}
+void
+CameraDevice::sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber) {
+ auto cbIt = mSequenceCallbackMap.find(sequenceId);
+ if (cbIt != mSequenceCallbackMap.end()) {
+ CallbackHolder cbh = cbIt->second;
+ mSequenceCallbackMap.erase(cbIt);
+
+ // send seq complete callback
+ sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
+ msg->setObject(kSessionSpKey, cbh.mSession);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
+ msg->setInt32(kSequenceIdKey, sequenceId);
+ msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+ // Clear the session sp before we send out the message
+ // This will guarantee the rare case where the message is processed
+ // before cbh goes out of scope and causing we call the session
+ // destructor while holding device lock
+ cbh.mSession.clear();
+ postSessionMsgAndCleanup(msg);
+ } else {
+ // Check if there is callback for this sequence
+ // This should not happen because we always register callback (with nullptr inside)
+ ALOGW("No callback found for sequenceId %d", sequenceId);
+ }
+}
+
} // namespace acam
} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index d937865..3073dfb 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -354,6 +354,7 @@
void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
void checkAndFireSequenceCompleteLocked();
void removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber);
+ void sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber);
// Misc variables
int32_t mShadingMapSize[2]; // const after constructor
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 419250c..73cabbf 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -24,6 +24,7 @@
#include <utils/Vector.h>
#include <cutils/properties.h>
#include <stdlib.h>
+#include <camera/CameraUtils.h>
#include <camera/VendorTagDescriptor.h>
using namespace android::acam;
@@ -70,12 +71,6 @@
mCameraService.clear();
}
-static bool isCameraServiceDisabled() {
- char value[PROPERTY_VALUE_MAX];
- property_get("config.disable_cameraservice", value, "0");
- return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
-}
-
sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
Mutex::Autolock _l(mLock);
return getCameraServiceLocked();
@@ -83,7 +78,7 @@
sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
if (mCameraService.get() == nullptr) {
- if (isCameraServiceDisabled()) {
+ if (CameraUtils::isCameraServiceDisabled()) {
return mCameraService;
}
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 07176cf..6c1cf33 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -45,8 +45,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
/**
* ACameraCaptureSession is an opaque type that manages frame captures of a camera device.
*
@@ -593,10 +591,6 @@
camera_status_t ACameraCaptureSession_abortCaptures(ACameraCaptureSession* session)
__INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 28
-
typedef struct ACaptureSessionOutput ACaptureSessionOutput;
/**
@@ -641,9 +635,7 @@
*/
camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* session,
ACaptureSessionOutput* output) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-#if __ANDROID_API__ >= 29
/**
* The definition of final capture result callback with logical multi-camera support.
*
@@ -788,8 +780,6 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 1537bde..f72fe8d 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -44,8 +44,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
/**
* ACameraDevice is opaque type that provides access to a camera device.
*
@@ -687,10 +685,6 @@
const ACameraCaptureSession_stateCallbacks* callbacks,
/*out*/ACameraCaptureSession** session) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 28
-
/**
* Create a shared ACaptureSessionOutput object.
*
@@ -782,10 +776,6 @@
const ACameraCaptureSession_stateCallbacks* callbacks,
/*out*/ACameraCaptureSession** session) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Create a ACaptureSessionOutput object used for streaming from a physical
* camera as part of a logical camera device.
@@ -890,8 +880,6 @@
const ACameraDevice* device,
const ACaptureSessionOutputContainer* sessionOutputContainer) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif /* _NDK_CAMERA_DEVICE_H */
diff --git a/camera/ndk/include/camera/NdkCameraError.h b/camera/ndk/include/camera/NdkCameraError.h
index fc618ee..9d77eb4 100644
--- a/camera/ndk/include/camera/NdkCameraError.h
+++ b/camera/ndk/include/camera/NdkCameraError.h
@@ -40,8 +40,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
typedef enum {
ACAMERA_OK = 0,
@@ -138,8 +136,6 @@
ACAMERA_ERROR_UNSUPPORTED_OPERATION = ACAMERA_ERROR_BASE - 14,
} camera_status_t;
-#endif /* __ANDROID_API__ >= 24 */
-
__END_DECLS
#endif /* _NDK_CAMERA_ERROR_H */
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index 0a2ee57..be32b11 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -44,8 +44,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
/**
* ACameraManager is opaque type that provides access to camera service.
*
@@ -293,10 +291,6 @@
ACameraDevice_StateCallbacks* callback,
/*out*/ACameraDevice** device) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Definition of camera access permission change callback.
*
@@ -419,8 +413,6 @@
__INTRODUCED_IN(29);
#endif
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif /* _NDK_CAMERA_MANAGER_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h
index a840bd1..0d5e6c4 100644
--- a/camera/ndk/include/camera/NdkCameraMetadata.h
+++ b/camera/ndk/include/camera/NdkCameraMetadata.h
@@ -41,9 +41,7 @@
#include <sys/cdefs.h>
#ifndef __ANDROID_VNDK__
-#if __ANDROID_API__ >= 30
#include "jni.h"
-#endif /* __ANDROID_API__ >= 30 */
#endif /* __ANDROID_VNDK__ */
#include "NdkCameraError.h"
@@ -51,8 +49,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
/**
* ACameraMetadata is opaque type that provides access to read-only camera metadata like camera
* characteristics (via {@link ACameraManager_getCameraCharacteristics}) or capture results (via
@@ -238,10 +234,6 @@
*/
void ACameraMetadata_free(ACameraMetadata* metadata) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Helper function to check if a camera is logical multi-camera.
*
@@ -260,10 +252,7 @@
/*out*/size_t* numPhysicalCameras, /*out*/const char* const** physicalCameraIds)
__INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
#ifndef __ANDROID_VNDK__
-#if __ANDROID_API__ >= 30
/**
* Return a {@link ACameraMetadata} that references the same data as
@@ -290,7 +279,6 @@
ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata)
__INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
#endif /* __ANDROID_VNDK__ */
__END_DECLS
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 7d78571..bc33d6a 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -40,8 +40,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
typedef enum acamera_metadata_section {
ACAMERA_COLOR_CORRECTION,
ACAMERA_CONTROL,
@@ -1890,10 +1888,8 @@
* <li>ACaptureRequest</li>
* </ul></p>
*
- * <p>Instead of using ACAMERA_SCALER_CROP_REGION with dual purposes of crop and zoom, the
- * application can now choose to use this tag to specify the desired zoom level. The
- * ACAMERA_SCALER_CROP_REGION can still be used to specify the horizontal or vertical
- * crop to achieve aspect ratios different than the native camera sensor.</p>
+ * <p>Instead of using ACAMERA_SCALER_CROP_REGION for zoom, the application can now choose to
+ * use this tag to specify the desired zoom level.</p>
* <p>By using this control, the application gains a simpler way to control zoom, which can
* be a combination of optical and digital zoom. For example, a multi-camera system may
* contain more than one lens with different focal lengths, and the user can use optical
@@ -1959,7 +1955,10 @@
* explicitly set ACAMERA_CONTROL_ZOOM_RATIO, its value defaults to 1.0.</p>
* <p>One limitation of controlling zoom using zoomRatio is that the ACAMERA_SCALER_CROP_REGION
* must only be used for letterboxing or pillarboxing of the sensor active array, and no
- * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0.</p>
+ * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0. If
+ * ACAMERA_CONTROL_ZOOM_RATIO is not 1.0, and ACAMERA_SCALER_CROP_REGION is set to be
+ * windowboxing, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be
+ * the active array.</p>
*
* @see ACAMERA_CONTROL_AE_REGIONS
* @see ACAMERA_CONTROL_ZOOM_RATIO
@@ -3413,16 +3412,24 @@
* respectively.</p>
* <p>The camera device may adjust the crop region to account for rounding and other hardware
* requirements; the final crop region used will be included in the output capture result.</p>
+ * <p>The camera sensor output aspect ratio depends on factors such as output stream
+ * combination and ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, and shouldn't be adjusted by using
+ * this control. And the camera device will treat different camera sensor output sizes
+ * (potentially with in-sensor crop) as the same crop of
+ * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE. As a result, the application shouldn't assume the
+ * maximum crop region always maps to the same aspect ratio or field of view for the
+ * sensor output.</p>
* <p>Starting from API level 30, it's strongly recommended to use ACAMERA_CONTROL_ZOOM_RATIO
* to take advantage of better support for zoom with logical multi-camera. The benefits
* include better precision with optical-digital zoom combination, and ability to do
* zoom-out from 1.0x. When using ACAMERA_CONTROL_ZOOM_RATIO for zoom, the crop region in
- * the capture request must be either letterboxing or pillarboxing (but not both). The
+ * the capture request should be left as the default activeArray size. The
* coordinate system is post-zoom, meaning that the activeArraySize or
* preCorrectionActiveArraySize covers the camera device's field of view "after" zoom. See
* ACAMERA_CONTROL_ZOOM_RATIO for details.</p>
* <p>The data representation is int[4], which maps to (left, top, width, height).</p>
*
+ * @see ACAMERA_CONTROL_AE_TARGET_FPS_RANGE
* @see ACAMERA_CONTROL_ZOOM_RATIO
* @see ACAMERA_DISTORTION_CORRECTION_MODE
* @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
@@ -3645,7 +3652,9 @@
* </ol>
* </li>
* <li>Setting ACAMERA_CONTROL_ZOOM_RATIO to values different than 1.0 and
- * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time is undefined behavior.</li>
+ * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time are not supported. In this
+ * case, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be the active
+ * array.</li>
* </ul>
* <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
*
@@ -8987,8 +8996,6 @@
-#endif /* __ANDROID_API__ >= 24 */
-
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_TAGS_H */
diff --git a/camera/ndk/include/camera/NdkCaptureRequest.h b/camera/ndk/include/camera/NdkCaptureRequest.h
index d3f8826..a4dc374 100644
--- a/camera/ndk/include/camera/NdkCaptureRequest.h
+++ b/camera/ndk/include/camera/NdkCaptureRequest.h
@@ -44,8 +44,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
// Container for output targets
typedef struct ACameraOutputTargets ACameraOutputTargets;
@@ -304,10 +302,6 @@
*/
void ACaptureRequest_free(ACaptureRequest* request) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 28
-
/**
* Associate an arbitrary user context pointer to the {@link ACaptureRequest}
*
@@ -356,10 +350,6 @@
*/
ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Get a metadata entry from input {@link ACaptureRequest} for
* a physical camera backing a logical multi-camera device.
@@ -569,8 +559,6 @@
ACaptureRequest* request, const char* physicalId, uint32_t tag,
uint32_t count, const ACameraMetadata_rational* data) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif /* _NDK_CAPTURE_REQUEST_H */
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index e5c1631..7f8078e 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -42,6 +42,9 @@
LOCAL_CFLAGS += -Wall -Wextra -Werror
LOCAL_MODULE:= camera_client_test
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../NOTICE
LOCAL_MODULE_TAGS := tests
include $(BUILD_NATIVE_TEST)
diff --git a/cmds/screenrecord/Android.bp b/cmds/screenrecord/Android.bp
index d7d905f..359a835 100644
--- a/cmds/screenrecord/Android.bp
+++ b/cmds/screenrecord/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_binary {
name: "screenrecord",
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 6470fb1..ef4c568 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -28,6 +28,9 @@
LOCAL_SYSTEM_EXT_MODULE:= true
LOCAL_MODULE:= stagefright
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
@@ -58,6 +61,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= record
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
@@ -86,6 +92,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= recordvideo
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
@@ -115,6 +124,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= audioloop
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
@@ -141,6 +153,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= stream
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
@@ -169,6 +184,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= codec
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
@@ -214,6 +232,9 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= mediafilter
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
LOCAL_SANITIZE := cfi
@@ -242,5 +263,8 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= muxer
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
include $(BUILD_EXECUTABLE)
diff --git a/cmds/stagefright/AudioPlayer.cpp b/cmds/stagefright/AudioPlayer.cpp
index eb76953..55427ca 100644
--- a/cmds/stagefright/AudioPlayer.cpp
+++ b/cmds/stagefright/AudioPlayer.cpp
@@ -134,15 +134,18 @@
success = format->findInt32(kKeySampleRate, &mSampleRate);
CHECK(success);
- int32_t numChannels, channelMask;
+ int32_t numChannels;
success = format->findInt32(kKeyChannelCount, &numChannels);
CHECK(success);
- if(!format->findInt32(kKeyChannelMask, &channelMask)) {
+ audio_channel_mask_t channelMask;
+ if (int32_t rawChannelMask; !format->findInt32(kKeyChannelMask, &rawChannelMask)) {
// log only when there's a risk of ambiguity of channel mask selection
ALOGI_IF(numChannels > 2,
"source format didn't specify channel mask, using (%d) channel order", numChannels);
channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+ } else {
+ channelMask = static_cast<audio_channel_mask_t>(rawChannelMask);
}
audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index f4b8164..e000633 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -272,7 +272,7 @@
status_t SimplePlayer::onPrepare() {
CHECK_EQ(mState, UNPREPARED);
- mExtractor = new NuMediaExtractor;
+ mExtractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
status_t err = mExtractor->setDataSource(
NULL /* httpService */, mPath.c_str());
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index c26e0b9..33c4663 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -79,7 +79,7 @@
static int64_t kTimeout = 500ll;
- sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
fprintf(stderr, "unable to instantiate extractor.\n");
return 1;
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index b894545..ca058ab 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -319,7 +319,8 @@
static int64_t kTimeout = 500ll;
- sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
+
if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
fprintf(stderr, "unable to instantiate extractor.\n");
return 1;
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 4a83a4a..bc7e41e 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -62,7 +62,7 @@
int trimEndTimeMs,
int rotationDegrees,
MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) {
- sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
fprintf(stderr, "unable to instantiate extractor. %s\n", path);
return 1;
diff --git a/drm/common/Android.bp b/drm/common/Android.bp
index 272684c..76ee22e 100644
--- a/drm/common/Android.bp
+++ b/drm/common/Android.bp
@@ -14,7 +14,24 @@
// limitations under the License.
//
-cc_library_static {
+package {
+ default_applicable_licenses: ["frameworks_av_drm_common_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_drm_common_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libdrmframeworkcommon",
srcs: [
@@ -35,7 +52,11 @@
cflags: ["-Wall", "-Werror"],
- shared_libs: ["libbinder"],
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils"
+ ],
export_include_dirs: ["include"],
}
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index fcd291f..df3a6a2 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -14,6 +14,23 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["frameworks_av_drm_drmserver_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_drm_drmserver_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "drmserver",
@@ -31,12 +48,11 @@
"liblog",
"libbinder",
"libdl",
+ "libdrmframeworkcommon",
"libselinux",
"libstagefright_foundation",
],
- static_libs: ["libdrmframeworkcommon"],
-
cflags: [
"-Wall",
"-Wextra",
diff --git a/drm/libdrmframework/Android.bp b/drm/libdrmframework/Android.bp
index 940c17d..dbce5ea 100644
--- a/drm/libdrmframework/Android.bp
+++ b/drm/libdrmframework/Android.bp
@@ -14,6 +14,23 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["frameworks_av_drm_libdrmframework_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_drm_libdrmframework_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libdrmframework",
@@ -29,13 +46,11 @@
"liblog",
"libbinder",
"libdl",
+ "libdrmframeworkcommon",
],
- static_libs: ["libdrmframeworkcommon"],
-
export_include_dirs: ["include"],
- export_static_lib_headers: ["libdrmframeworkcommon"],
+ export_shared_lib_headers: ["libdrmframeworkcommon"],
cflags: ["-Werror"],
}
-
diff --git a/drm/libdrmframework/plugins/common/util/Android.bp b/drm/libdrmframework/plugins/common/util/Android.bp
index 7372eb7..a47b4a1 100644
--- a/drm/libdrmframework/plugins/common/util/Android.bp
+++ b/drm/libdrmframework/plugins/common/util/Android.bp
@@ -14,6 +14,25 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: [
+ "frameworks_av_drm_libdrmframework_plugins_common_util_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_drm_libdrmframework_plugins_common_util_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libdrmutility",
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index bb9d7ec..be2b546 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -14,6 +14,25 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: [
+ "frameworks_av_drm_libdrmframework_plugins_forward-lock_FwdLockEngine_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_drm_libdrmframework_plugins_forward-lock_FwdLockEngine_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libfwdlockengine",
@@ -36,11 +55,11 @@
"libcrypto",
"libssl",
"libdrmframework",
+ "libdrmframeworkcommon",
],
static_libs: [
"libdrmutility",
- "libdrmframeworkcommon",
"libfwdlock-common",
"libfwdlock-converter",
"libfwdlock-decoder",
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp
index 3be327a..2e4070b 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_drm_libdrmframework_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_drm_libdrmframework_license"],
+}
+
cc_library_static {
name: "libfwdlock-common",
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp
index d4e04b8..51c778f 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_drm_libdrmframework_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_drm_libdrmframework_license"],
+}
+
cc_library_static {
name: "libfwdlock-converter",
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp
index 0bf2737..6773fe1 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_drm_libdrmframework_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_drm_libdrmframework_license"],
+}
+
cc_library_static {
name: "libfwdlock-decoder",
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 05b6440..6dffd49 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -14,17 +14,35 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: [
+ "frameworks_av_drm_libdrmframework_plugins_passthru_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_drm_libdrmframework_plugins_passthru_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libdrmpassthruplugin",
srcs: ["src/DrmPassthruPlugIn.cpp"],
- static_libs: ["libdrmframeworkcommon"],
-
shared_libs: [
"libutils",
"liblog",
"libdl",
+ "libdrmframeworkcommon",
],
local_include_dirs: ["include"],
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 1700a95..a82a61d 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -2,6 +2,15 @@
// libmediadrm
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libmediadrm_headers",
@@ -11,7 +20,7 @@
}
-cc_library_shared {
+cc_library {
name: "libmediadrm",
srcs: [
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
index b47b4ff..5f0b26e 100644
--- a/drm/libmediadrm/DrmMetricsConsumer.cpp
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -37,8 +37,8 @@
template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
static const char *type_names[] = {"USABLE", "EXPIRED",
"OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
- "INTERNAL_ERROR"};
- if (((size_t)type) > arraysize(type_names)) {
+ "INTERNAL_ERROR", "USABLE_IN_FUTURE"};
+ if (((size_t)type) >= arraysize(type_names)) {
return "UNKNOWN_TYPE";
}
return type_names[(size_t)type];
@@ -48,7 +48,7 @@
static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
"KEY_EXPIRED", "VENDOR_DEFINED",
"SESSION_RECLAIMED"};
- if (((size_t)type) > arraysize(type_names)) {
+ if (((size_t)type) >= arraysize(type_names)) {
return "UNKNOWN_TYPE";
}
return type_names[(size_t)type];
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
new file mode 100644
index 0000000..2b04702
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_fuzz {
+ name: "mediadrm_fuzzer",
+ srcs: [
+ "mediadrm_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libmediadrm",
+ "liblog",
+ "resourcemanager_aidl_interface-ndk_platform",
+ ],
+ header_libs: [
+ "libmedia_headers",
+ "libmediadrm_headers",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ "libbinder_ndk",
+ "libcutils",
+ "libdl",
+ "libmedia",
+ "libmediadrmmetrics_lite",
+ "libmediametrics#1",
+ "libmediautils",
+ "libstagefright_foundation",
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
+ "android.hardware.drm@1.3",
+ "libhidlallocatorutils",
+ "libhidlbase",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/drm/libmediadrm/fuzzer/README.md b/drm/libmediadrm/fuzzer/README.md
new file mode 100644
index 0000000..3c95cd7
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/README.md
@@ -0,0 +1,56 @@
+# Fuzzer for libmediadrm
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediadrm is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libmediadrm supports the following parameters:
+1. Security Level (parameter name: `securityLevel`)
+2. Mime Type (parameter name: `mimeType`)
+3. Key Type (parameter name: `keyType`)
+4. Crypto Mode (parameter name: `cryptoMode`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `securityLevel` | 0.`DrmPlugin::kSecurityLevelUnknown` 1.`DrmPlugin::kSecurityLevelMax` 2.`DrmPlugin::kSecurityLevelSwSecureCrypto` 3.`DrmPlugin::kSecurityLevelSwSecureDecode` 4.`DrmPlugin::kSecurityLevelHwSecureCrypto` 5.`DrmPlugin::kSecurityLevelHwSecureDecode` 6.`DrmPlugin::kSecurityLevelHwSecureAll`| Value obtained from FuzzedDataProvider in the range 0 to 6|
+| `mimeType` | 0.`video/mp4` 1.`video/mpeg` 2.`video/x-flv` 3.`video/mj2` 4.`video/3gp2` 5.`video/3gpp` 6.`video/3gpp2` 7.`audio/mp4` 8.`audio/mpeg` 9.`audio/aac` 10.`audio/3gp2` 11.`audio/3gpp` 12.`audio/3gpp2` 13.`video/unknown`| Value obtained from FuzzedDataProvider in the range 0 to 13|
+| `keyType` | 0.`DrmPlugin::kKeyType_Offline` 1.`DrmPlugin::kKeyType_Streaming` 2.`DrmPlugin::kKeyType_Release` | Value obtained from FuzzedDataProvider in the range 0 to 2|
+| `cryptoMode` | 0.`CryptoPlugin::kMode_Unencrypted` 1.`CryptoPlugin::kMode_AES_CTR` 2.`CryptoPlugin::kMode_AES_WV` 3.`CryptoPlugin::kMode_AES_CBC` | Value obtained from FuzzedDataProvider in the range 0 to 3|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the drm module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build mediadrm_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) mediadrm_fuzzer
+```
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+ $ adb shell mkdir CORPUS_DIR
+```
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/${TARGET_ARCH}/mediadrm_fuzzer/mediadrm_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
new file mode 100644
index 0000000..8df0477
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include <binder/MemoryDealer.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmHal.h>
+#include <utils/String8.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+#define AES_BLOCK_SIZE 16
+#define UNUSED_PARAM __attribute__((unused))
+
+using namespace std;
+using namespace android;
+using android::hardware::fromHeap;
+using ::android::os::PersistableBundle;
+using drm::V1_0::BufferType;
+
+enum {
+ INVALID_UUID = 0,
+ PSSH_BOX_UUID,
+ CLEARKEY_UUID,
+};
+
+static const uint8_t kInvalidUUID[16] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
+
+static const uint8_t kCommonPsshBoxUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
+
+static const uint8_t kClearKeyUUID[16] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+ 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
+static const uint32_t kUUID[] = {INVALID_UUID, PSSH_BOX_UUID, CLEARKEY_UUID};
+
+const DrmPlugin::SecurityLevel kSecurityLevel[] = {
+ DrmPlugin::kSecurityLevelUnknown, DrmPlugin::kSecurityLevelMax,
+ DrmPlugin::kSecurityLevelSwSecureCrypto, DrmPlugin::kSecurityLevelSwSecureDecode,
+ DrmPlugin::kSecurityLevelHwSecureCrypto, DrmPlugin::kSecurityLevelHwSecureDecode,
+ DrmPlugin::kSecurityLevelHwSecureAll};
+
+const char *kMimeType[] = {"video/mp4", "video/mpeg", "video/x-flv", "video/mj2",
+ "video/3gp2", "video/3gpp", "video/3gpp2", "audio/mp4",
+ "audio/mpeg", "audio/aac", "audio/3gp2", "audio/3gpp",
+ "audio/3gpp2", "video/unknown", "audio/unknown"};
+
+const DrmPlugin::KeyType kKeyType[] = {DrmPlugin::kKeyType_Offline, DrmPlugin::kKeyType_Streaming,
+ DrmPlugin::kKeyType_Release};
+
+const CryptoPlugin::Mode kCryptoMode[] = {CryptoPlugin::kMode_Unencrypted,
+ CryptoPlugin::kMode_AES_CTR, CryptoPlugin::kMode_AES_WV,
+ CryptoPlugin::kMode_AES_CBC};
+
+const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
+const char *kMacAlgorithm[] = {"HmacSHA256", ""};
+const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
+const size_t kNumSecurityLevel = size(kSecurityLevel);
+const size_t kNumMimeType = size(kMimeType);
+const size_t kNumKeyType = size(kKeyType);
+const size_t kNumCryptoMode = size(kCryptoMode);
+const size_t kNumUUID = size(kUUID);
+const size_t kMaxStringLength = 100;
+const size_t kMaxSubSamples = 10;
+const size_t kMaxNumBytes = 1000;
+
+struct DrmListener : virtual public IDrmClient {
+ public:
+ void sendEvent(DrmPlugin::EventType eventType UNUSED_PARAM,
+ const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ const hardware::hidl_vec<uint8_t> &data UNUSED_PARAM) override {}
+
+ void sendExpirationUpdate(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ int64_t expiryTimeInMS UNUSED_PARAM) override {}
+
+ void sendKeysChange(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ const std::vector<DrmKeyStatus> &keyStatusList UNUSED_PARAM,
+ bool hasNewUsableKey UNUSED_PARAM) override {}
+
+ void sendSessionLostState(const hardware::hidl_vec<uint8_t> &) override {}
+ DrmListener() {}
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(DrmListener);
+};
+
+class DrmFuzzer {
+ public:
+ void process(const uint8_t *data, size_t size);
+
+ private:
+ void invokeDrm(const uint8_t *data, size_t size);
+ bool initDrm();
+ void invokeDrmCreatePlugin();
+ void invokeDrmOpenSession();
+ void invokeDrmSetListener();
+ void invokeDrmSetAlgorithmAPI();
+ void invokeDrmPropertyAPI();
+ void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
+ void invokeDrmSecureStopAPI();
+ void invokeDrmOfflineLicenseAPI();
+ void invokeDrmCloseSession();
+ void invokeDrmDestroyPlugin();
+ void invokeCrypto(const uint8_t *data);
+ bool initCrypto();
+ void invokeCryptoCreatePlugin();
+ void invokeCryptoDecrypt(const uint8_t *data);
+ void invokeCryptoDestroyPlugin();
+ sp<DrmHal> mDrm = nullptr;
+ sp<CryptoHal> mCrypto = nullptr;
+ Vector<uint8_t> mSessionId = {};
+ FuzzedDataProvider *mFuzzedDataProvider = nullptr;
+};
+
+bool DrmFuzzer::initDrm() {
+ mDrm = new DrmHal();
+ if (!mDrm) {
+ return false;
+ }
+ return true;
+}
+
+void DrmFuzzer::invokeDrmCreatePlugin() {
+ mDrm->initCheck();
+ String8 packageName(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ uint32_t uuidEnum = kUUID[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumUUID - 1)];
+ switch (uuidEnum) {
+ case INVALID_UUID:
+ mDrm->createPlugin(kInvalidUUID, packageName);
+ break;
+ case PSSH_BOX_UUID:
+ mDrm->createPlugin(kCommonPsshBoxUUID, packageName);
+ break;
+ case CLEARKEY_UUID:
+ mDrm->createPlugin(kClearKeyUUID, packageName);
+ break;
+ default:
+ break;
+ }
+}
+
+void DrmFuzzer::invokeDrmDestroyPlugin() { mDrm->destroyPlugin(); }
+
+void DrmFuzzer::invokeDrmOpenSession() {
+ DrmPlugin::SecurityLevel securityLevel;
+ bool shouldPassRandomSecurityLevel = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomSecurityLevel) {
+ securityLevel =
+ static_cast<DrmPlugin::SecurityLevel>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ securityLevel = kSecurityLevel[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kNumSecurityLevel - 1)];
+ }
+ mDrm->openSession(securityLevel, mSessionId);
+}
+
+void DrmFuzzer::invokeDrmCloseSession() { mDrm->closeSession(mSessionId); }
+
+void DrmFuzzer::invokeDrmSetListener() {
+ sp<DrmListener> listener = new DrmListener();
+ mDrm->setListener(listener);
+}
+
+void DrmFuzzer::invokeDrmSetAlgorithmAPI() {
+ mDrm->setCipherAlgorithm(mSessionId,
+ String8(kCipherAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+ mDrm->setMacAlgorithm(mSessionId, String8(kMacAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+}
+
+void DrmFuzzer::invokeDrmPropertyAPI() {
+ mDrm->setPropertyString(String8("property"), String8("value"));
+ String8 stringValue;
+ mDrm->getPropertyString(String8("property"), stringValue);
+ Vector<uint8_t> value = {};
+ mDrm->setPropertyByteArray(String8("property"), value);
+ Vector<uint8_t> byteValue;
+ mDrm->getPropertyByteArray(String8("property"), byteValue);
+}
+
+void DrmFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size) {
+ uint32_t openSessions = 0;
+ uint32_t maxSessions = 0;
+ mDrm->getNumberOfSessions(&openSessions, &maxSessions);
+
+ DrmPlugin::HdcpLevel connected;
+ DrmPlugin::HdcpLevel max;
+ mDrm->getHdcpLevels(&connected, &max);
+
+ DrmPlugin::SecurityLevel securityLevel;
+ mDrm->getSecurityLevel(mSessionId, &securityLevel);
+
+ // isCryptoSchemeSupported() shall fill isSupported
+ bool isSupported;
+ String8 mimeType(
+ kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+ mDrm->isCryptoSchemeSupported(kClearKeyUUID, mimeType, securityLevel, &isSupported);
+
+ // getProvisionRequest() shall fill legacyRequest and legacyDefaultUrl
+ String8 certificateType(
+ mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ String8 certAuthority(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ Vector<uint8_t> legacyRequest = {};
+ String8 legacyDefaultUrl;
+ mDrm->getProvisionRequest(certificateType, certAuthority, legacyRequest, legacyDefaultUrl);
+
+ // provideProvisionResponse() shall fill certificate and wrappedKey
+ Vector<uint8_t> provisionResponse = {};
+ Vector<uint8_t> certificate = {};
+ Vector<uint8_t> wrappedKey = {};
+ mDrm->provideProvisionResponse(provisionResponse, certificate, wrappedKey);
+
+ // getKeyRequest() shall fill keyRequest, defaultUrl and keyRequestType
+ Vector<uint8_t> initData = {};
+ initData.appendArray(data, size);
+ DrmPlugin::KeyType keyType;
+ bool shouldPassRandomKeyType = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomKeyType) {
+ keyType = static_cast<DrmPlugin::KeyType>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ keyType = kKeyType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumKeyType - 1)];
+ }
+ KeyedVector<String8, String8> mdOptionalParameters = {};
+ Vector<uint8_t> keyRequest = {};
+ String8 defaultUrl;
+ DrmPlugin::KeyRequestType keyRequestType;
+ mDrm->getKeyRequest(mSessionId, initData, mimeType, keyType, mdOptionalParameters, keyRequest,
+ defaultUrl, &keyRequestType);
+
+ // provideKeyResponse() shall fill keySetId
+ Vector<uint8_t> keyResponse = {};
+ keyResponse.appendArray(data, size);
+ Vector<uint8_t> keySetId = {};
+ mDrm->provideKeyResponse(mSessionId, keyResponse, keySetId);
+
+ // restoreKeys
+ mDrm->restoreKeys(mSessionId, keySetId);
+
+ // queryKeyStatus() shall fill infoMap
+ KeyedVector<String8, String8> infoMap = {};
+ mDrm->queryKeyStatus(mSessionId, infoMap);
+
+ // decrypt() shall fill outputVec
+ Vector<uint8_t> keyIdVec = {};
+ keyIdVec.appendArray(data, size);
+
+ Vector<uint8_t> inputVec = {};
+ inputVec.appendArray(data, size);
+
+ Vector<uint8_t> ivVec = {};
+ ivVec.appendArray(data, size);
+
+ Vector<uint8_t> outputVec = {};
+ mDrm->decrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+ // encrypt() shall fill outputVec
+ mDrm->encrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+ // sign() shall fill signature
+ Vector<uint8_t> message = {};
+ message.appendArray(data, size);
+ Vector<uint8_t> signature = {};
+ mDrm->sign(mSessionId, keyIdVec, message, signature);
+
+ // verify() shall fill match
+ bool match;
+ mDrm->verify(mSessionId, keyIdVec, message, signature, match);
+
+ // signRSA() shall fill signature
+ mDrm->signRSA(mSessionId, String8(kRSAAlgorithm[mFuzzedDataProvider->ConsumeBool()]), message,
+ wrappedKey, signature);
+
+ mDrm->removeKeys(mSessionId);
+}
+
+void DrmFuzzer::invokeDrmSecureStopAPI() {
+ // getSecureStops() shall fill secureStops
+ List<Vector<uint8_t>> secureStops = {};
+ mDrm->getSecureStops(secureStops);
+
+ // getSecureStopIds() shall fill secureStopIds
+ List<Vector<uint8_t>> secureStopIds = {};
+ mDrm->getSecureStopIds(secureStopIds);
+
+ // getSecureStop() shall fill secureStop
+ Vector<uint8_t> ssid = {};
+ Vector<uint8_t> secureStop = {};
+ mDrm->getSecureStop(ssid, secureStop);
+
+ mDrm->removeSecureStop(ssid);
+
+ mDrm->releaseSecureStops(ssid);
+
+ mDrm->removeAllSecureStops();
+}
+
+void DrmFuzzer::invokeDrmOfflineLicenseAPI() {
+ // getOfflineLicenseKeySetIds() shall keySetIds
+ List<Vector<uint8_t>> keySetIds = {};
+ mDrm->getOfflineLicenseKeySetIds(keySetIds);
+
+ // getOfflineLicenseState() shall fill state
+ Vector<uint8_t> const keySetIdOfflineLicense = {};
+ DrmPlugin::OfflineLicenseState state;
+ mDrm->getOfflineLicenseState(keySetIdOfflineLicense, &state);
+
+ mDrm->removeOfflineLicense(keySetIdOfflineLicense);
+}
+
+bool DrmFuzzer::initCrypto() {
+ mCrypto = new CryptoHal();
+ if (!mCrypto) {
+ return false;
+ }
+ return true;
+}
+
+void DrmFuzzer::invokeCryptoCreatePlugin() {
+ mCrypto->initCheck();
+
+ mCrypto->isCryptoSchemeSupported(kClearKeyUUID);
+ mCrypto->createPlugin(kClearKeyUUID, NULL, 0);
+}
+
+void DrmFuzzer::invokeCryptoDestroyPlugin() { mCrypto->destroyPlugin(); }
+
+void DrmFuzzer::invokeCryptoDecrypt(const uint8_t *data) {
+ mCrypto->requiresSecureDecoderComponent(
+ kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+
+ uint32_t width = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ uint32_t height = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ mCrypto->notifyResolution(width, height);
+
+ mCrypto->setMediaDrmSession(mSessionId);
+
+ const CryptoPlugin::Pattern pattern = {0, 0};
+
+ size_t totalSize = 0;
+ size_t numSubSamples = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
+
+ CryptoPlugin::SubSample subSamples[numSubSamples];
+
+ for (size_t i = 0; i < numSubSamples; ++i) {
+ uint32_t clearBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+ uint32_t encryptedBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+ subSamples[i].mNumBytesOfClearData = clearBytes;
+ subSamples[i].mNumBytesOfEncryptedData = encryptedBytes;
+ totalSize += subSamples[i].mNumBytesOfClearData;
+ totalSize += subSamples[i].mNumBytesOfEncryptedData;
+ }
+
+ size_t heapSize = totalSize * 2;
+ sp<MemoryDealer> dealer = new MemoryDealer(heapSize, "DrmFuzzerMemory");
+ if (!dealer) {
+ return;
+ }
+
+ sp<HidlMemory> heap = fromHeap(dealer->getMemoryHeap());
+ if (!heap) {
+ return;
+ }
+ int heapSeqNum = mCrypto->setHeap(heap);
+ if (heapSeqNum < 0) {
+ return;
+ }
+
+ const size_t segmentIndex = 0;
+ const uint8_t keyId[AES_BLOCK_SIZE] = {};
+ memcpy((void *)keyId, data, AES_BLOCK_SIZE);
+
+ const uint8_t iv[AES_BLOCK_SIZE] = {};
+ memset((void *)iv, 0, AES_BLOCK_SIZE);
+
+ const SharedBuffer sourceBuffer = {.bufferId = segmentIndex, .offset = 0, .size = totalSize};
+
+ const DestinationBuffer destBuffer = {
+ .type = BufferType::SHARED_MEMORY,
+ {.bufferId = segmentIndex, .offset = totalSize, .size = totalSize},
+ .secureMemory = nullptr};
+
+ const uint64_t offset = 0;
+ AString *errorDetailMsg = nullptr;
+ CryptoPlugin::Mode mode;
+ bool shouldPassRandomCryptoMode = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomCryptoMode) {
+ mode = static_cast<CryptoPlugin::Mode>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ mode =
+ kCryptoMode[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumCryptoMode - 1)];
+ }
+ mCrypto->decrypt(keyId, iv, mode, pattern, sourceBuffer, offset, subSamples, numSubSamples,
+ destBuffer, errorDetailMsg);
+
+ if (heapSeqNum >= 0) {
+ mCrypto->unsetHeap(heapSeqNum);
+ }
+ heap.clear();
+}
+
+void DrmFuzzer::invokeDrm(const uint8_t *data, size_t size) {
+ if (!initDrm()) {
+ return;
+ }
+ invokeDrmCreatePlugin();
+ invokeDrmOpenSession();
+ invokeDrmSetAlgorithmAPI();
+ invokeDrmSetListener();
+ invokeDrmPropertyAPI();
+ invokeDrmDecryptEncryptAPI(data, size);
+ invokeDrmSecureStopAPI();
+ invokeDrmOfflineLicenseAPI();
+ invokeDrmCloseSession();
+ invokeDrmDestroyPlugin();
+}
+
+void DrmFuzzer::invokeCrypto(const uint8_t *data) {
+ if (!initCrypto()) {
+ return;
+ }
+ invokeCryptoCreatePlugin();
+ invokeCryptoDecrypt(data);
+ invokeCryptoDestroyPlugin();
+}
+
+void DrmFuzzer::process(const uint8_t *data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ invokeDrm(data, size);
+ invokeCrypto(data);
+ delete mFuzzedDataProvider;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < AES_BLOCK_SIZE) {
+ return 0;
+ }
+ DrmFuzzer drmFuzzer;
+ drmFuzzer.process(data, size);
+ return 0;
+}
diff --git a/drm/libmediadrm/protos/Android.bp b/drm/libmediadrm/protos/Android.bp
index b26cda4..f8d237a 100644
--- a/drm/libmediadrm/protos/Android.bp
+++ b/drm/libmediadrm/protos/Android.bp
@@ -15,6 +15,15 @@
// This is the version of the drm metrics configured for protobuf full on host.
// It is used by the metrics_dump tool.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_host_shared {
name: "libdrm_metrics_protos_full_host",
vendor_available: true,
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
index 6529387..9267e79 100644
--- a/drm/libmediadrm/tests/Android.bp
+++ b/drm/libmediadrm/tests/Android.bp
@@ -1,5 +1,14 @@
// Build definitions for unit tests.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "CounterMetric_test",
srcs: ["CounterMetric_test.cpp"],
diff --git a/drm/mediacas/plugins/clearkey/Android.bp b/drm/mediacas/plugins/clearkey/Android.bp
index 0113cb8..569cdbe 100644
--- a/drm/mediacas/plugins/clearkey/Android.bp
+++ b/drm/mediacas/plugins/clearkey/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libclearkeycasplugin",
diff --git a/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.h b/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.h
index a537e63..7c6d86c 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.h
+++ b/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.h
@@ -22,7 +22,6 @@
#include <openssl/aes.h>
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
-#include <utils/RefBase.h>
namespace android {
struct ABuffer;
@@ -30,7 +29,7 @@
namespace clearkeycas {
class KeyFetcher;
-class ClearKeyCasSession : public RefBase {
+class ClearKeyCasSession {
public:
explicit ClearKeyCasSession(CasPlugin *plugin);
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.bp b/drm/mediacas/plugins/clearkey/tests/Android.bp
index 575863c..9ad8d1e 100644
--- a/drm/mediacas/plugins/clearkey/tests/Android.bp
+++ b/drm/mediacas/plugins/clearkey/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "ClearKeyFetcherTest",
diff --git a/drm/mediacas/plugins/mock/Android.bp b/drm/mediacas/plugins/mock/Android.bp
index e8a3c6f..6f68c77 100644
--- a/drm/mediacas/plugins/mock/Android.bp
+++ b/drm/mediacas/plugins/mock/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libmockcasplugin",
diff --git a/drm/mediadrm/plugins/clearkey/common/Android.bp b/drm/mediadrm/plugins/clearkey/common/Android.bp
index 2c674e1..7ed8b88 100644
--- a/drm/mediadrm/plugins/clearkey/common/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/common/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libclearkeycommon",
vendor: true,
@@ -35,4 +44,3 @@
integer_overflow: true,
},
}
-
diff --git a/drm/mediadrm/plugins/clearkey/default/Android.bp b/drm/mediadrm/plugins/clearkey/default/Android.bp
index 9803d32..4b5389a 100644
--- a/drm/mediadrm/plugins/clearkey/default/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/default/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libdrmclearkeyplugin",
vendor: true,
@@ -60,4 +69,3 @@
integer_overflow: true,
},
}
-
diff --git a/drm/mediadrm/plugins/clearkey/default/tests/Android.bp b/drm/mediadrm/plugins/clearkey/default/tests/Android.bp
index 4419865..b97e924 100644
--- a/drm/mediadrm/plugins/clearkey/default/tests/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/default/tests/Android.bp
@@ -17,6 +17,15 @@
// Builds ClearKey Drm Tests
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "ClearKeyDrmUnitTest",
vendor: true,
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index a194416..e6e1f80 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -14,6 +14,19 @@
// limitations under the License.
//
+// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+// DEPENDING ON IT IN YOUR PROJECT. ***
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // legacy_by_exception_only (by exception only)
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "clearkey_service_defaults",
vendor: true,
diff --git a/drm/mediadrm/plugins/mock/Android.bp b/drm/mediadrm/plugins/mock/Android.bp
index dd2ad7b..20dfb4a 100644
--- a/drm/mediadrm/plugins/mock/Android.bp
+++ b/drm/mediadrm/plugins/mock/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libmockdrmcryptoplugin",
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 9cabd8b..200e92d 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -182,6 +182,7 @@
// This is set by AudioTrack.setBufferSizeInFrames().
// A write will not fill the buffer above this limit.
volatile uint32_t mBufferSizeInFrames; // effective size of the buffer
+ volatile uint32_t mStartThresholdInFrames; // min frames in buffer to start streaming
public:
@@ -216,6 +217,8 @@
};
size_t frameCount() const { return mFrameCount; }
+ uint32_t getStartThresholdInFrames() const;
+ uint32_t setStartThresholdInFrames(uint32_t startThresholdInFrames);
protected:
// These refer to shared memory, and are virtual addresses with respect to the current process.
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index cf1c14c..acc1b82 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -43,6 +43,9 @@
external/sonic \
LOCAL_MODULE := audioserver
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
LOCAL_INIT_RC := audioserver.rc
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index f05c2d2..f75e4c7 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -6,8 +6,11 @@
capabilities BLOCK_SUSPEND
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
-
- onrestart setprop sys.audio.restart.hal 1
+ onrestart restart vendor.audio-hal
+ onrestart restart vendor.audio-hal-4-0-msd
+ # Keep the original service names for backward compatibility
+ onrestart restart vendor.audio-hal-2-0
+ onrestart restart audio-hal-2-0
on property:vts.native_server.on=1
stop audioserver
@@ -37,11 +40,16 @@
start audio-hal-2-0
on property:sys.audio.restart.hal=1
- restart vendor.audio-hal
- restart vendor.audio-hal-4-0-msd
+ # See b/159966243. Avoid restart loop between audioserver and HAL.
# Keep the original service names for backward compatibility
- restart vendor.audio-hal-2-0
- restart audio-hal-2-0
+ stop vendor.audio-hal
+ stop vendor.audio-hal-4-0-msd
+ stop vendor.audio-hal-2-0
+ stop audio-hal-2-0
+ start vendor.audio-hal
+ start vendor.audio-hal-4-0-msd
+ start vendor.audio-hal-2-0
+ start audio-hal-2-0
# reset the property
setprop sys.audio.restart.hal 0
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index f817c76..16cf920 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libstagefright_bufferpool@1.0",
vendor_available: true,
diff --git a/media/bufferpool/1.0/vts/Android.bp b/media/bufferpool/1.0/vts/Android.bp
index ee5a757..b39871e 100644
--- a/media/bufferpool/1.0/vts/Android.bp
+++ b/media/bufferpool/1.0/vts/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "VtsVndkHidlBufferpoolV1_0TargetSingleTest",
defaults: ["VtsHalTargetTestDefaults"],
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 6111fea..1d2562e 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -39,6 +39,8 @@
static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
static constexpr size_t kMinBufferCountForEviction = 25;
+ static constexpr size_t kMaxUnusedBufferCount = 64;
+ static constexpr size_t kUnusedBufferCountTarget = kMaxUnusedBufferCount - 16;
static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
@@ -724,9 +726,11 @@
}
void Accessor::Impl::BufferPool::cleanUp(bool clearCache) {
- if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs) {
+ if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs ||
+ mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
mLastCleanUpUs = mTimestampUs;
- if (mTimestampUs > mLastLogUs + kLogDurationUs) {
+ if (mTimestampUs > mLastLogUs + kLogDurationUs ||
+ mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
mLastLogUs = mTimestampUs;
ALOGD("bufferpool2 %p : %zu(%zu size) total buffers - "
"%zu(%zu size) used buffers - %zu/%zu (recycle/alloc) - "
@@ -737,8 +741,9 @@
mStats.mTotalFetches, mStats.mTotalTransfers);
}
for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
- if (!clearCache && (mStats.mSizeCached < kMinAllocBytesForEviction
- || mBuffers.size() < kMinBufferCountForEviction)) {
+ if (!clearCache && mStats.buffersNotInUse() <= kUnusedBufferCountTarget &&
+ (mStats.mSizeCached < kMinAllocBytesForEviction ||
+ mBuffers.size() < kMinBufferCountForEviction)) {
break;
}
auto it = mBuffers.find(*freeIt);
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index cd1b4d0..3d39941 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -193,6 +193,12 @@
: mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
+ /// # of currently unused buffers
+ size_t buffersNotInUse() const {
+ ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
+ return mBuffersCached - mBuffersInUse;
+ }
+
/// A new buffer is allocated on an allocation request.
void onBufferAllocated(size_t allocSize) {
mSizeCached += allocSize;
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index 536f75e..0d1fe27 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libstagefright_bufferpool@2.0-default",
srcs: [
@@ -49,4 +58,3 @@
enabled: true,
},
}
-
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index 342fef6..9308b81 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -32,6 +32,8 @@
static constexpr int64_t kReceiveTimeoutUs = 1000000; // 100ms
static constexpr int kPostMaxRetry = 3;
static constexpr int kCacheTtlUs = 1000000; // TODO: tune
+static constexpr size_t kMaxCachedBufferCount = 64;
+static constexpr size_t kCachedBufferCountTarget = kMaxCachedBufferCount - 16;
class BufferPoolClient::Impl
: public std::enable_shared_from_this<BufferPoolClient::Impl> {
@@ -136,6 +138,10 @@
--mActive;
mLastChangeUs = getTimestampNow();
}
+
+ int cachedBufferCount() const {
+ return mBuffers.size() - mActive;
+ }
} mCache;
// FMQ - release notifier
@@ -668,10 +674,12 @@
// should have mCache.mLock
void BufferPoolClient::Impl::evictCaches(bool clearCache) {
int64_t now = getTimestampNow();
- if (now >= mLastEvictCacheUs + kCacheTtlUs || clearCache) {
+ if (now >= mLastEvictCacheUs + kCacheTtlUs ||
+ clearCache || mCache.cachedBufferCount() > kMaxCachedBufferCount) {
size_t evicted = 0;
for (auto it = mCache.mBuffers.begin(); it != mCache.mBuffers.end();) {
- if (!it->second->hasCache() && (it->second->expire() || clearCache)) {
+ if (!it->second->hasCache() && (it->second->expire() ||
+ clearCache || mCache.cachedBufferCount() > kCachedBufferCountTarget)) {
it = mCache.mBuffers.erase(it);
++evicted;
} else {
diff --git a/media/bufferpool/2.0/tests/Android.bp b/media/bufferpool/2.0/tests/Android.bp
index 8b44f61..d6db202 100644
--- a/media/bufferpool/2.0/tests/Android.bp
+++ b/media/bufferpool/2.0/tests/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "VtsVndkHidlBufferpoolV2_0TargetSingleTest",
defaults: ["VtsHalTargetTestDefaults"],
diff --git a/media/codec2/components/aac/Android.bp b/media/codec2/components/aac/Android.bp
index 9eca585..c547e85 100644
--- a/media/codec2/components/aac/Android.bp
+++ b/media/codec2/components/aac/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_aac_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_aac_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_aacdec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +34,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_aacenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 677f316..332696d 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -55,6 +55,8 @@
namespace android {
constexpr char COMPONENT_NAME[] = "c2.android.aac.decoder";
+constexpr size_t kDefaultOutputPortDelay = 2;
+constexpr size_t kMaxOutputPortDelay = 16;
class C2SoftAacDec::IntfImpl : public SimpleInterface<void>::BaseParams {
public:
@@ -73,7 +75,9 @@
addParameter(
DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
- .withConstValue(new C2PortActualDelayTuning::output(2u))
+ .withDefault(new C2PortActualDelayTuning::output(kDefaultOutputPortDelay))
+ .withFields({C2F(mActualOutputDelay, value).inRange(0, kMaxOutputPortDelay)})
+ .withSetter(Setter<decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
.build());
addParameter(
@@ -263,6 +267,7 @@
mAACDecoder(nullptr),
mStreamInfo(nullptr),
mSignalledError(false),
+ mOutputPortDelay(kDefaultOutputPortDelay),
mOutputDelayRingBuffer(nullptr) {
}
@@ -877,10 +882,14 @@
work->worklets.front()->output.configUpdate.push_back(
C2Param::Copy(currentBoostFactor));
- C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
- (C2Config::drc_compression_mode_t) compressMode);
- work->worklets.front()->output.configUpdate.push_back(
- C2Param::Copy(currentCompressMode));
+ if (android_get_device_api_level() < __ANDROID_API_S__) {
+ // We used to report DRC compression mode in the output format
+ // in Q and R, but stopped doing that in S
+ C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
+ (C2Config::drc_compression_mode_t) compressMode);
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(currentCompressMode));
+ }
C2StreamDrcEncodedTargetLevelTuning::input currentEncodedTargetLevel(0u,
(C2FloatValue) (encTargetLevel*-0.25));
@@ -911,6 +920,29 @@
int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
+ size_t numSamplesInOutput = mStreamInfo->frameSize * mStreamInfo->numChannels;
+ if (numSamplesInOutput > 0) {
+ size_t actualOutputPortDelay = (outputDelay + numSamplesInOutput - 1) / numSamplesInOutput;
+ if (actualOutputPortDelay > mOutputPortDelay) {
+ mOutputPortDelay = actualOutputPortDelay;
+ ALOGV("New Output port delay %zu ", mOutputPortDelay);
+
+ C2PortActualDelayTuning::output outputPortDelay(mOutputPortDelay);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err =
+ mIntf->config({&outputPortDelay}, C2_MAY_BLOCK, &failures);
+ if (err == OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(outputPortDelay));
+ } else {
+ ALOGE("Cannot set output delay");
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ }
+ }
mBuffersInfo.push_back(std::move(inInfo));
work->workletsProcessed = 0u;
if (!eos && mOutputDelayCompensated < outputDelay) {
@@ -1061,11 +1093,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAacDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/aac/C2SoftAacDec.h b/media/codec2/components/aac/C2SoftAacDec.h
index 965c29e..986187c 100644
--- a/media/codec2/components/aac/C2SoftAacDec.h
+++ b/media/codec2/components/aac/C2SoftAacDec.h
@@ -57,6 +57,7 @@
size_t mInputBufferCount;
size_t mOutputBufferCount;
bool mSignalledError;
+ size_t mOutputPortDelay;
struct Info {
uint64_t frameIndex;
size_t bufferSize;
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 2e85915..ea76cbb 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -692,11 +692,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAacEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/amr_nb_wb/Android.bp b/media/codec2/components/amr_nb_wb/Android.bp
index ce25bc9..1418ba5 100644
--- a/media/codec2/components/amr_nb_wb/Android.bp
+++ b/media/codec2/components/amr_nb_wb/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_amr_nb_wb_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_amr_nb_wb_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_amrnbdec",
defaults: [
"libcodec2_soft-defaults",
@@ -21,7 +40,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrwbdec",
defaults: [
"libcodec2_soft-defaults",
@@ -40,7 +59,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrnbenc",
defaults: [
"libcodec2_soft-defaults",
@@ -58,7 +77,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrwbenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
index f7943be..c08e02b 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
@@ -420,11 +420,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAMRDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
index e2d8cb6..bb63e1f 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
@@ -337,11 +337,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAmrNbEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
index 84ae4b7..84728ae 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
@@ -411,11 +411,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAmrWbEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
index 61dbd4c..cb9837f 100644
--- a/media/codec2/components/aom/Android.bp
+++ b/media/codec2/components/aom/Android.bp
@@ -1,4 +1,13 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_av1dec_aom",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 9ba3b697..c08cd59 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -800,11 +800,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAomFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/avc/Android.bp b/media/codec2/components/avc/Android.bp
index 4021444..0be1bed 100644
--- a/media/codec2/components/avc/Android.bp
+++ b/media/codec2/components/avc/Android.bp
@@ -1,9 +1,19 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_avcdec",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_signed-defaults",
- ],
+ "libcodec2_soft_sanitize_cfi-defaults",
+ ],
static_libs: ["libavcdec"],
@@ -15,12 +25,13 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_avcenc",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_signed-defaults",
- ],
+ "libcodec2_soft_sanitize_cfi-defaults",
+ ],
static_libs: ["libavcenc"],
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 3afd670..e8287f9 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -26,7 +26,6 @@
#include <SimpleC2Interface.h>
#include "C2SoftAvcDec.h"
-#include "ih264d.h"
namespace android {
@@ -391,12 +390,14 @@
}
while (true) {
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
+ ih264d_video_decode_ip_t s_h264d_decode_ip = {};
+ ih264d_video_decode_op_t s_h264d_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip = &s_h264d_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op = &s_h264d_decode_op.s_ivd_video_decode_op_t;
- setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, nullptr, 0, 0, 0);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (0 == s_decode_op.u4_output_present) {
+ setDecodeArgs(ps_decode_ip, ps_decode_op, nullptr, nullptr, 0, 0, 0);
+ (void) ivdec_api_function(mDecHandle, &s_h264d_decode_ip, &s_h264d_decode_op);
+ if (0 == ps_decode_op->u4_output_present) {
resetPlugin();
break;
}
@@ -411,8 +412,8 @@
}
status_t C2SoftAvcDec::createDecoder() {
- ivdext_create_ip_t s_create_ip;
- ivdext_create_op_t s_create_op;
+ ivdext_create_ip_t s_create_ip = {};
+ ivdext_create_op_t s_create_op = {};
s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
@@ -438,8 +439,8 @@
}
status_t C2SoftAvcDec::setNumCores() {
- ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip;
- ivdext_ctl_set_num_cores_op_t s_set_num_cores_op;
+ ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip = {};
+ ivdext_ctl_set_num_cores_op_t s_set_num_cores_op = {};
s_set_num_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
s_set_num_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -458,22 +459,26 @@
}
status_t C2SoftAvcDec::setParams(size_t stride, IVD_VIDEO_DECODE_MODE_T dec_mode) {
- ivd_ctl_set_config_ip_t s_set_dyn_params_ip;
- ivd_ctl_set_config_op_t s_set_dyn_params_op;
+ ih264d_ctl_set_config_ip_t s_h264d_set_dyn_params_ip = {};
+ ih264d_ctl_set_config_op_t s_h264d_set_dyn_params_op = {};
+ ivd_ctl_set_config_ip_t *ps_set_dyn_params_ip =
+ &s_h264d_set_dyn_params_ip.s_ivd_ctl_set_config_ip_t;
+ ivd_ctl_set_config_op_t *ps_set_dyn_params_op =
+ &s_h264d_set_dyn_params_op.s_ivd_ctl_set_config_op_t;
- s_set_dyn_params_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
- s_set_dyn_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_dyn_params_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
- s_set_dyn_params_ip.u4_disp_wd = (UWORD32) stride;
- s_set_dyn_params_ip.e_frm_skip_mode = IVD_SKIP_NONE;
- s_set_dyn_params_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
- s_set_dyn_params_ip.e_vid_dec_mode = dec_mode;
- s_set_dyn_params_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
+ ps_set_dyn_params_ip->u4_size = sizeof(ih264d_ctl_set_config_ip_t);
+ ps_set_dyn_params_ip->e_cmd = IVD_CMD_VIDEO_CTL;
+ ps_set_dyn_params_ip->e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
+ ps_set_dyn_params_ip->u4_disp_wd = (UWORD32) stride;
+ ps_set_dyn_params_ip->e_frm_skip_mode = IVD_SKIP_NONE;
+ ps_set_dyn_params_ip->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
+ ps_set_dyn_params_ip->e_vid_dec_mode = dec_mode;
+ ps_set_dyn_params_op->u4_size = sizeof(ih264d_ctl_set_config_op_t);
IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_dyn_params_ip,
- &s_set_dyn_params_op);
+ &s_h264d_set_dyn_params_ip,
+ &s_h264d_set_dyn_params_op);
if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__, s_set_dyn_params_op.u4_error_code);
+ ALOGE("error in %s: 0x%x", __func__, ps_set_dyn_params_op->u4_error_code);
return UNKNOWN_ERROR;
}
@@ -481,8 +486,8 @@
}
void C2SoftAvcDec::getVersion() {
- ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip;
- ivd_ctl_getversioninfo_op_t s_get_versioninfo_op;
+ ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip = {};
+ ivd_ctl_getversioninfo_op_t s_get_versioninfo_op = {};
UWORD8 au1_buf[512];
s_get_versioninfo_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
@@ -538,7 +543,7 @@
if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
}
- ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
+ ps_decode_ip->u4_size = sizeof(ih264d_video_decode_ip_t);
ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
if (inBuffer) {
ps_decode_ip->u4_ts = tsMarker;
@@ -567,14 +572,14 @@
ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferFlush + lumaSize + chromaSize;
}
ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
- ps_decode_op->u4_size = sizeof(ivd_video_decode_op_t);
+ ps_decode_op->u4_size = sizeof(ih264d_video_decode_op_t);
return true;
}
bool C2SoftAvcDec::getVuiParams() {
- ivdext_ctl_get_vui_params_ip_t s_get_vui_params_ip;
- ivdext_ctl_get_vui_params_op_t s_get_vui_params_op;
+ ivdext_ctl_get_vui_params_ip_t s_get_vui_params_ip = {};
+ ivdext_ctl_get_vui_params_op_t s_get_vui_params_op = {};
s_get_vui_params_ip.u4_size = sizeof(ivdext_ctl_get_vui_params_ip_t);
s_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -622,8 +627,8 @@
}
status_t C2SoftAvcDec::setFlushMode() {
- ivd_ctl_flush_ip_t s_set_flush_ip;
- ivd_ctl_flush_op_t s_set_flush_op;
+ ivd_ctl_flush_ip_t s_set_flush_ip = {};
+ ivd_ctl_flush_op_t s_set_flush_op = {};
s_set_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
s_set_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -641,8 +646,8 @@
}
status_t C2SoftAvcDec::resetDecoder() {
- ivd_ctl_reset_ip_t s_reset_ip;
- ivd_ctl_reset_op_t s_reset_op;
+ ivd_ctl_reset_ip_t s_reset_ip = {};
+ ivd_ctl_reset_op_t s_reset_op = {};
s_reset_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
s_reset_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -671,8 +676,8 @@
status_t C2SoftAvcDec::deleteDecoder() {
if (mDecHandle) {
- ivdext_delete_ip_t s_delete_ip;
- ivdext_delete_op_t s_delete_op;
+ ivdext_delete_ip_t s_delete_ip = {};
+ ivdext_delete_op_t s_delete_op = {};
s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
@@ -837,8 +842,10 @@
return;
}
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
+ ih264d_video_decode_ip_t s_h264d_decode_ip = {};
+ ih264d_video_decode_op_t s_h264d_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip = &s_h264d_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op = &s_h264d_decode_op.s_ivd_video_decode_op_t;
{
C2GraphicView wView = mOutBlock->map().get();
if (wView.error()) {
@@ -846,7 +853,7 @@
work->result = wView.error();
return;
}
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, &rView, &wView,
+ if (!setDecodeArgs(ps_decode_ip, ps_decode_op, &rView, &wView,
inOffset + inPos, inSize - inPos, workIndex)) {
mSignalledError = true;
work->workletsProcessed = 1u;
@@ -862,26 +869,27 @@
WORD32 delay;
GETTIME(&mTimeStart, nullptr);
TIME_DIFF(mTimeEnd, mTimeStart, delay);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
+ (void) ivdec_api_function(mDecHandle, &s_h264d_decode_ip, &s_h264d_decode_op);
WORD32 decodeTime;
GETTIME(&mTimeEnd, nullptr);
TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
- s_decode_op.u4_num_bytes_consumed);
+ ps_decode_op->u4_num_bytes_consumed);
}
- if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
+ if (IVD_MEM_ALLOC_FAILED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGE("allocation failure in decoder");
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
+ } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED ==
+ (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGE("unsupported resolution : %dx%d", mWidth, mHeight);
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
+ } else if (IVD_RES_CHANGED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGV("resolution changed");
drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
resetDecoder();
@@ -890,16 +898,16 @@
/* Decode header and get new dimensions */
setParams(mStride, IVD_DECODE_HEADER);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- } else if (IS_IVD_FATAL_ERROR(s_decode_op.u4_error_code)) {
- ALOGE("Fatal error in decoder 0x%x", s_decode_op.u4_error_code);
+ (void) ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
+ } else if (IS_IVD_FATAL_ERROR(ps_decode_op->u4_error_code)) {
+ ALOGE("Fatal error in decoder 0x%x", ps_decode_op->u4_error_code);
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
}
- if (s_decode_op.i4_reorder_depth >= 0 && mOutputDelay != s_decode_op.i4_reorder_depth) {
- mOutputDelay = s_decode_op.i4_reorder_depth;
+ if (ps_decode_op->i4_reorder_depth >= 0 && mOutputDelay != ps_decode_op->i4_reorder_depth) {
+ mOutputDelay = ps_decode_op->i4_reorder_depth;
ALOGV("New Output delay %d ", mOutputDelay);
C2PortActualDelayTuning::output outputDelay(mOutputDelay);
@@ -917,16 +925,16 @@
return;
}
}
- if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
+ if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- mStride = ALIGN32(s_decode_op.u4_pic_wd);
+ mStride = ALIGN32(ps_decode_op->u4_pic_wd);
setParams(mStride, IVD_DECODE_FRAME);
}
- if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
- mWidth = s_decode_op.u4_pic_wd;
- mHeight = s_decode_op.u4_pic_ht;
- CHECK_EQ(0u, s_decode_op.u4_output_present);
+ if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
+ mWidth = ps_decode_op->u4_pic_wd;
+ mHeight = ps_decode_op->u4_pic_ht;
+ CHECK_EQ(0u, ps_decode_op->u4_output_present);
C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
std::vector<std::unique_ptr<C2SettingResult>> failures;
@@ -945,11 +953,11 @@
}
}
(void)getVuiParams();
- hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
+ hasPicture |= (1 == ps_decode_op->u4_frame_decoded_flag);
+ if (ps_decode_op->u4_output_present) {
+ finishWork(ps_decode_op->u4_ts, work);
}
- inPos += s_decode_op.u4_num_bytes_consumed;
+ inPos += ps_decode_op->u4_num_bytes_consumed;
}
if (eos) {
drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
@@ -987,16 +995,18 @@
ALOGE("graphic view map failed %d", wView.error());
return C2_CORRUPTED;
}
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, &wView, 0, 0, 0)) {
+ ih264d_video_decode_ip_t s_h264d_decode_ip = {};
+ ih264d_video_decode_op_t s_h264d_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip = &s_h264d_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op = &s_h264d_decode_op.s_ivd_video_decode_op_t;
+ if (!setDecodeArgs(ps_decode_ip, ps_decode_op, nullptr, &wView, 0, 0, 0)) {
mSignalledError = true;
work->workletsProcessed = 1u;
return C2_CORRUPTED;
}
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
+ (void) ivdec_api_function(mDecHandle, &s_h264d_decode_ip, &s_h264d_decode_op);
+ if (ps_decode_op->u4_output_present) {
+ finishWork(ps_decode_op->u4_ts, work);
} else {
fillEmptyWork(work);
break;
@@ -1049,11 +1059,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAvcDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index bd84de0..5c07d29 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -25,8 +25,7 @@
#include <SimpleC2Component.h>
#include "ih264_typedefs.h"
-#include "iv.h"
-#include "ivd.h"
+#include "ih264d.h"
namespace android {
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 1ea7c68..17f0e10 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -1765,11 +1765,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftAvcEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index f10835f..160e250 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -1,6 +1,15 @@
// DO NOT DEPEND ON THIS DIRECTLY
// use libcodec2_soft-defaults instead
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_common",
defaults: ["libcodec2-impl-defaults"],
vendor_available: true,
@@ -20,7 +29,7 @@
shared_libs: [
"libcutils", // for properties
- "liblog", // for ALOG
+ "liblog", // for ALOG
"libsfplugin_ccodec_utils", // for ImageCopy
"libstagefright_foundation", // for Mutexed
],
@@ -38,7 +47,7 @@
filegroup {
name: "codec2_soft_exports",
- srcs: [ "exports.lds" ],
+ srcs: ["exports.lds"],
}
// public dependency for software codec implementation
@@ -91,12 +100,22 @@
misc_undefined: [
"signed-integer-overflow",
],
+ },
+}
+
+cc_defaults {
+ name: "libcodec2_soft_sanitize_cfi-defaults",
+
+ sanitize: {
cfi: true,
+ config: {
+ cfi_assembly_support: true,
+ },
},
}
// TEMP: used by cheets2 project - remove when no longer used
-cc_library_shared {
+cc_library {
name: "libcodec2_simple_component",
vendor_available: true,
@@ -131,4 +150,3 @@
ldflags: ["-Wl,-Bsymbolic"],
}
-
diff --git a/media/codec2/components/cmds/Android.bp b/media/codec2/components/cmds/Android.bp
index a081e28..d6ffd12 100644
--- a/media/codec2/components/cmds/Android.bp
+++ b/media/codec2/components/cmds/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_binary {
name: "codec2play",
defaults: ["libcodec2-impl-defaults"],
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index 48cc51b..1143bed 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_flac_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_flac_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_flacdec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +33,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_flacenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index 4039b9b..e70c289 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -367,11 +367,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftFlacDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 408db7e..1c0babd 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -481,11 +481,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftFlacEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/g711/Android.bp b/media/codec2/components/g711/Android.bp
index 0101b1a..45e85a9 100644
--- a/media/codec2/components/g711/Android.bp
+++ b/media/codec2/components/g711/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_g711_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_g711_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_g711alawdec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +33,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_g711mlawdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/g711/C2SoftG711Dec.cpp b/media/codec2/components/g711/C2SoftG711Dec.cpp
index 7f9c34e..f9299af 100644
--- a/media/codec2/components/g711/C2SoftG711Dec.cpp
+++ b/media/codec2/components/g711/C2SoftG711Dec.cpp
@@ -259,11 +259,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftG711DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/gav1/Android.bp b/media/codec2/components/gav1/Android.bp
index 5c4abb7..7692d37 100644
--- a/media/codec2/components/gav1/Android.bp
+++ b/media/codec2/components/gav1/Android.bp
@@ -1,4 +1,13 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_av1dec_gav1",
defaults: [
"libcodec2_soft-defaults",
@@ -13,8 +22,4 @@
srcs: ["C2SoftGav1Dec.cpp"],
static_libs: ["libgav1"],
-
- include_dirs: [
- "external/libgav1/libgav1/",
- ],
}
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 5dffa50..76345ae 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -288,9 +288,7 @@
void C2SoftGav1Dec::onRelease() { destroyDecoder(); }
c2_status_t C2SoftGav1Dec::onFlush_sm() {
- Libgav1StatusCode status =
- mCodecCtx->EnqueueFrame(/*data=*/nullptr, /*size=*/0,
- /*user_private_data=*/0);
+ Libgav1StatusCode status = mCodecCtx->SignalEOS();
if (status != kLibgav1StatusOk) {
ALOGE("Failed to flush av1 decoder. status: %d.", status);
return C2_CORRUPTED;
@@ -299,7 +297,7 @@
// Dequeue frame (if any) that was enqueued previously.
const libgav1::DecoderBuffer *buffer;
status = mCodecCtx->DequeueFrame(&buffer);
- if (status != kLibgav1StatusOk) {
+ if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
ALOGE("Failed to dequeue frame after flushing the av1 decoder. status: %d",
status);
return C2_CORRUPTED;
@@ -433,7 +431,8 @@
TIME_DIFF(mTimeEnd, mTimeStart, delay);
const Libgav1StatusCode status =
- mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex);
+ mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex,
+ /*buffer_private_data=*/nullptr);
GETTIME(&mTimeEnd, nullptr);
TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
@@ -447,17 +446,6 @@
return;
}
- } else {
- const Libgav1StatusCode status =
- mCodecCtx->EnqueueFrame(/*data=*/nullptr, /*size=*/0,
- /*user_private_data=*/0);
- if (status != kLibgav1StatusOk) {
- ALOGE("Failed to flush av1 decoder. status: %d.", status);
- work->result = C2_CORRUPTED;
- work->workletsProcessed = 1u;
- mSignalledError = true;
- return;
- }
}
(void)outputBuffer(pool, work);
@@ -598,13 +586,14 @@
const libgav1::DecoderBuffer *buffer;
const Libgav1StatusCode status = mCodecCtx->DequeueFrame(&buffer);
- if (status != kLibgav1StatusOk) {
+ if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
ALOGE("av1 decoder DequeueFrame failed. status: %d.", status);
return false;
}
- // |buffer| can be NULL if status was equal to kLibgav1StatusOk. This is not
- // an error. This could mean one of two things:
+ // |buffer| can be NULL if status was equal to kLibgav1StatusOk or
+ // kLibgav1StatusNothingToDequeue. This is not an error. This could mean one
+ // of two things:
// - The EnqueueFrame() call was either a flush (called with nullptr).
// - The enqueued frame did not have any displayable frames.
if (!buffer) {
@@ -724,9 +713,7 @@
return C2_OMITTED;
}
- Libgav1StatusCode status =
- mCodecCtx->EnqueueFrame(/*data=*/nullptr, /*size=*/0,
- /*user_private_data=*/0);
+ const Libgav1StatusCode status = mCodecCtx->SignalEOS();
if (status != kLibgav1StatusOk) {
ALOGE("Failed to flush av1 decoder. status: %d.", status);
return C2_CORRUPTED;
@@ -783,11 +770,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftGav1Factory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index a7c08bb..555adc9 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -18,8 +18,8 @@
#define ANDROID_C2_SOFT_GAV1_DEC_H_
#include <SimpleC2Component.h>
-#include "libgav1/src/decoder.h"
-#include "libgav1/src/decoder_settings.h"
+#include "libgav1/src/gav1/decoder.h"
+#include "libgav1/src/gav1/decoder_settings.h"
#define GETTIME(a, b) gettimeofday(a, b);
#define TIME_DIFF(start, end, diff) \
diff --git a/media/codec2/components/gsm/Android.bp b/media/codec2/components/gsm/Android.bp
index 9330c01..2d0976d 100644
--- a/media/codec2/components/gsm/Android.bp
+++ b/media/codec2/components/gsm/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_gsm_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_gsm_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_gsmdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/gsm/C2SoftGsmDec.cpp b/media/codec2/components/gsm/C2SoftGsmDec.cpp
index 287cfc6..977677d 100644
--- a/media/codec2/components/gsm/C2SoftGsmDec.cpp
+++ b/media/codec2/components/gsm/C2SoftGsmDec.cpp
@@ -294,11 +294,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftGSMDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/hevc/Android.bp b/media/codec2/components/hevc/Android.bp
index 369bd78..d1388b9 100644
--- a/media/codec2/components/hevc/Android.bp
+++ b/media/codec2/components/hevc/Android.bp
@@ -1,8 +1,18 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_hevcdec",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_signed-defaults",
+ "libcodec2_soft_sanitize_cfi-defaults",
],
srcs: ["C2SoftHevcDec.cpp"],
@@ -11,11 +21,12 @@
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_hevcenc",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_signed-defaults",
+ "libcodec2_soft_sanitize_cfi-defaults",
],
srcs: ["C2SoftHevcEnc.cpp"],
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 23104dc..6bcf3a2 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -26,7 +26,6 @@
#include <SimpleC2Interface.h>
#include "C2SoftHevcDec.h"
-#include "ihevcd_cxa.h"
namespace android {
@@ -380,12 +379,14 @@
}
while (true) {
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
+ ihevcd_cxa_video_decode_ip_t s_hevcd_decode_ip = {};
+ ihevcd_cxa_video_decode_op_t s_hevcd_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip = &s_hevcd_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op = &s_hevcd_decode_op.s_ivd_video_decode_op_t;
- setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, nullptr, 0, 0, 0);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (0 == s_decode_op.u4_output_present) {
+ setDecodeArgs(ps_decode_ip, ps_decode_op, nullptr, nullptr, 0, 0, 0);
+ (void) ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
+ if (0 == ps_decode_op->u4_output_present) {
resetPlugin();
break;
}
@@ -400,8 +401,8 @@
}
status_t C2SoftHevcDec::createDecoder() {
- ivdext_create_ip_t s_create_ip;
- ivdext_create_op_t s_create_op;
+ ivdext_create_ip_t s_create_ip = {};
+ ivdext_create_op_t s_create_op = {};
s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
@@ -427,8 +428,8 @@
}
status_t C2SoftHevcDec::setNumCores() {
- ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip;
- ivdext_ctl_set_num_cores_op_t s_set_num_cores_op;
+ ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip = {};
+ ivdext_ctl_set_num_cores_op_t s_set_num_cores_op = {};
s_set_num_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
s_set_num_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -447,22 +448,26 @@
}
status_t C2SoftHevcDec::setParams(size_t stride, IVD_VIDEO_DECODE_MODE_T dec_mode) {
- ivd_ctl_set_config_ip_t s_set_dyn_params_ip;
- ivd_ctl_set_config_op_t s_set_dyn_params_op;
+ ihevcd_cxa_ctl_set_config_ip_t s_hevcd_set_dyn_params_ip = {};
+ ihevcd_cxa_ctl_set_config_op_t s_hevcd_set_dyn_params_op = {};
+ ivd_ctl_set_config_ip_t *ps_set_dyn_params_ip =
+ &s_hevcd_set_dyn_params_ip.s_ivd_ctl_set_config_ip_t;
+ ivd_ctl_set_config_op_t *ps_set_dyn_params_op =
+ &s_hevcd_set_dyn_params_op.s_ivd_ctl_set_config_op_t;
- s_set_dyn_params_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
- s_set_dyn_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
- s_set_dyn_params_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
- s_set_dyn_params_ip.u4_disp_wd = (UWORD32) stride;
- s_set_dyn_params_ip.e_frm_skip_mode = IVD_SKIP_NONE;
- s_set_dyn_params_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
- s_set_dyn_params_ip.e_vid_dec_mode = dec_mode;
- s_set_dyn_params_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
+ ps_set_dyn_params_ip->u4_size = sizeof(ihevcd_cxa_ctl_set_config_ip_t);
+ ps_set_dyn_params_ip->e_cmd = IVD_CMD_VIDEO_CTL;
+ ps_set_dyn_params_ip->e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
+ ps_set_dyn_params_ip->u4_disp_wd = (UWORD32) stride;
+ ps_set_dyn_params_ip->e_frm_skip_mode = IVD_SKIP_NONE;
+ ps_set_dyn_params_ip->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
+ ps_set_dyn_params_ip->e_vid_dec_mode = dec_mode;
+ ps_set_dyn_params_op->u4_size = sizeof(ihevcd_cxa_ctl_set_config_op_t);
IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
- &s_set_dyn_params_ip,
- &s_set_dyn_params_op);
+ ps_set_dyn_params_ip,
+ ps_set_dyn_params_op);
if (status != IV_SUCCESS) {
- ALOGE("error in %s: 0x%x", __func__, s_set_dyn_params_op.u4_error_code);
+ ALOGE("error in %s: 0x%x", __func__, ps_set_dyn_params_op->u4_error_code);
return UNKNOWN_ERROR;
}
@@ -470,8 +475,8 @@
}
status_t C2SoftHevcDec::getVersion() {
- ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip;
- ivd_ctl_getversioninfo_op_t s_get_versioninfo_op;
+ ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip = {};
+ ivd_ctl_getversioninfo_op_t s_get_versioninfo_op = {};
UWORD8 au1_buf[512];
s_get_versioninfo_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
@@ -529,7 +534,7 @@
if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
}
- ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
+ ps_decode_ip->u4_size = sizeof(ihevcd_cxa_video_decode_ip_t);
ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
if (inBuffer) {
ps_decode_ip->u4_ts = tsMarker;
@@ -558,15 +563,15 @@
ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferFlush + lumaSize + chromaSize;
}
ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
- ps_decode_op->u4_size = sizeof(ivd_video_decode_op_t);
+ ps_decode_op->u4_size = sizeof(ihevcd_cxa_video_decode_op_t);
ps_decode_op->u4_output_present = 0;
return true;
}
bool C2SoftHevcDec::getVuiParams() {
- ivdext_ctl_get_vui_params_ip_t s_get_vui_params_ip;
- ivdext_ctl_get_vui_params_op_t s_get_vui_params_op;
+ ivdext_ctl_get_vui_params_ip_t s_get_vui_params_ip = {};
+ ivdext_ctl_get_vui_params_op_t s_get_vui_params_op = {};
s_get_vui_params_ip.u4_size = sizeof(ivdext_ctl_get_vui_params_ip_t);
s_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -614,8 +619,8 @@
}
status_t C2SoftHevcDec::setFlushMode() {
- ivd_ctl_flush_ip_t s_set_flush_ip;
- ivd_ctl_flush_op_t s_set_flush_op;
+ ivd_ctl_flush_ip_t s_set_flush_ip = {};
+ ivd_ctl_flush_op_t s_set_flush_op = {};
s_set_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
s_set_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -633,8 +638,8 @@
}
status_t C2SoftHevcDec::resetDecoder() {
- ivd_ctl_reset_ip_t s_reset_ip;
- ivd_ctl_reset_op_t s_reset_op;
+ ivd_ctl_reset_ip_t s_reset_ip = {};
+ ivd_ctl_reset_op_t s_reset_op = {};
s_reset_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
s_reset_ip.e_cmd = IVD_CMD_VIDEO_CTL;
@@ -662,8 +667,8 @@
status_t C2SoftHevcDec::deleteDecoder() {
if (mDecHandle) {
- ivdext_delete_ip_t s_delete_ip;
- ivdext_delete_op_t s_delete_op;
+ ivdext_delete_ip_t s_delete_ip = {};
+ ivdext_delete_op_t s_delete_op = {};
s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
@@ -835,9 +840,11 @@
work->result = wView.error();
return;
}
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, &rView, &wView,
+ ihevcd_cxa_video_decode_ip_t s_hevcd_decode_ip = {};
+ ihevcd_cxa_video_decode_op_t s_hevcd_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip = &s_hevcd_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op = &s_hevcd_decode_op.s_ivd_video_decode_op_t;
+ if (!setDecodeArgs(ps_decode_ip, ps_decode_op, &rView, &wView,
inOffset + inPos, inSize - inPos, workIndex)) {
mSignalledError = true;
work->workletsProcessed = 1u;
@@ -852,26 +859,26 @@
WORD32 delay;
GETTIME(&mTimeStart, nullptr);
TIME_DIFF(mTimeEnd, mTimeStart, delay);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
+ (void) ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
WORD32 decodeTime;
GETTIME(&mTimeEnd, nullptr);
TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
- s_decode_op.u4_num_bytes_consumed);
- if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
+ ps_decode_op->u4_num_bytes_consumed);
+ if (IVD_MEM_ALLOC_FAILED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGE("allocation failure in decoder");
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
} else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED ==
- (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
+ (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGE("unsupported resolution : %dx%d", mWidth, mHeight);
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
+ } else if (IVD_RES_CHANGED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGV("resolution changed");
drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
resetDecoder();
@@ -880,16 +887,16 @@
/* Decode header and get new dimensions */
setParams(mStride, IVD_DECODE_HEADER);
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- } else if (IS_IVD_FATAL_ERROR(s_decode_op.u4_error_code)) {
- ALOGE("Fatal error in decoder 0x%x", s_decode_op.u4_error_code);
+ (void) ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
+ } else if (IS_IVD_FATAL_ERROR(ps_decode_op->u4_error_code)) {
+ ALOGE("Fatal error in decoder 0x%x", ps_decode_op->u4_error_code);
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
}
- if (s_decode_op.i4_reorder_depth >= 0 && mOutputDelay != s_decode_op.i4_reorder_depth) {
- mOutputDelay = s_decode_op.i4_reorder_depth;
+ if (ps_decode_op->i4_reorder_depth >= 0 && mOutputDelay != ps_decode_op->i4_reorder_depth) {
+ mOutputDelay = ps_decode_op->i4_reorder_depth;
ALOGV("New Output delay %d ", mOutputDelay);
C2PortActualDelayTuning::output outputDelay(mOutputDelay);
@@ -906,17 +913,16 @@
work->result = C2_CORRUPTED;
return;
}
- continue;
}
- if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
+ if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- setParams(ALIGN32(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+ setParams(ALIGN32(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
}
- if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
- mWidth = s_decode_op.u4_pic_wd;
- mHeight = s_decode_op.u4_pic_ht;
- CHECK_EQ(0u, s_decode_op.u4_output_present);
+ if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
+ mWidth = ps_decode_op->u4_pic_wd;
+ mHeight = ps_decode_op->u4_pic_ht;
+ CHECK_EQ(0u, ps_decode_op->u4_output_present);
C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
std::vector<std::unique_ptr<C2SettingResult>> failures;
@@ -936,15 +942,15 @@
}
}
(void) getVuiParams();
- hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
+ hasPicture |= (1 == ps_decode_op->u4_frame_decoded_flag);
+ if (ps_decode_op->u4_output_present) {
+ finishWork(ps_decode_op->u4_ts, work);
}
- if (0 == s_decode_op.u4_num_bytes_consumed) {
+ if (0 == ps_decode_op->u4_num_bytes_consumed) {
ALOGD("Bytes consumed is zero. Ignoring remaining bytes");
break;
}
- inPos += s_decode_op.u4_num_bytes_consumed;
+ inPos += ps_decode_op->u4_num_bytes_consumed;
if (hasPicture && (inSize - inPos)) {
ALOGD("decoded frame in current access nal, ignoring further trailing bytes %d",
(int)inSize - (int)inPos);
@@ -986,16 +992,18 @@
ALOGE("graphic view map failed %d", wView.error());
return C2_CORRUPTED;
}
- ivd_video_decode_ip_t s_decode_ip;
- ivd_video_decode_op_t s_decode_op;
- if (!setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, &wView, 0, 0, 0)) {
+ ihevcd_cxa_video_decode_ip_t s_hevcd_decode_ip = {};
+ ihevcd_cxa_video_decode_op_t s_hevcd_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip = &s_hevcd_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op = &s_hevcd_decode_op.s_ivd_video_decode_op_t;
+ if (!setDecodeArgs(ps_decode_ip, ps_decode_op, nullptr, &wView, 0, 0, 0)) {
mSignalledError = true;
work->workletsProcessed = 1u;
return C2_CORRUPTED;
}
- (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- if (s_decode_op.u4_output_present) {
- finishWork(s_decode_op.u4_ts, work);
+ (void) ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
+ if (ps_decode_op->u4_output_present) {
+ finishWork(ps_decode_op->u4_ts, work);
} else {
fillEmptyWork(work);
break;
@@ -1048,11 +1056,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftHevcDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index 600d7c1..b9b0a48 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -23,8 +23,7 @@
#include <SimpleC2Component.h>
#include "ihevc_typedefs.h"
-#include "iv.h"
-#include "ivd.h"
+#include "ihevcd_cxa.h"
namespace android {
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index c2d2540..436a2c4 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1078,11 +1078,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftHevcEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mp3/Android.bp b/media/codec2/components/mp3/Android.bp
index 66665ed..437d34f 100644
--- a/media/codec2/components/mp3/Android.bp
+++ b/media/codec2/components/mp3/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_mp3_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_mp3_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_mp3dec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
index 5ba7e3d..7137767 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
@@ -539,11 +539,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMp3DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg2/Android.bp b/media/codec2/components/mpeg2/Android.bp
index 841f0a9..daa10ae 100644
--- a/media/codec2/components/mpeg2/Android.bp
+++ b/media/codec2/components/mpeg2/Android.bp
@@ -1,4 +1,13 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_mpeg2dec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 55dd475..b1cf388 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -30,6 +30,7 @@
namespace android {
constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
+constexpr size_t kMaxDimension = 1920;
constexpr char COMPONENT_NAME[] = "c2.android.mpeg2.decoder";
class C2SoftMpeg2Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -64,8 +65,8 @@
DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
.withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
.withFields({
- C2F(mSize, width).inRange(16, 1920, 4),
- C2F(mSize, height).inRange(16, 1088, 4),
+ C2F(mSize, width).inRange(16, kMaxDimension, 2),
+ C2F(mSize, height).inRange(16, kMaxDimension, 2),
})
.withSetter(SizeSetter)
.build());
@@ -91,8 +92,8 @@
DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
.withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
.withFields({
- C2F(mSize, width).inRange(2, 1920, 2),
- C2F(mSize, height).inRange(2, 1088, 2),
+ C2F(mSize, width).inRange(2, kMaxDimension, 2),
+ C2F(mSize, height).inRange(2, kMaxDimension, 2),
})
.withSetter(MaxPictureSizeSetter, mSize)
.build());
@@ -204,8 +205,8 @@
const C2P<C2StreamPictureSizeInfo::output> &size) {
(void)mayBlock;
// TODO: get max width/height from the size's field helpers vs. hardcoding
- me.set().width = c2_min(c2_max(me.v.width, size.v.width), 1920u);
- me.set().height = c2_min(c2_max(me.v.height, size.v.height), 1088u);
+ me.set().width = c2_min(c2_max(me.v.width, size.v.width), kMaxDimension);
+ me.set().height = c2_min(c2_max(me.v.height, size.v.height), kMaxDimension);
return C2R::Ok();
}
@@ -1113,11 +1114,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMpeg2DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg4_h263/Android.bp b/media/codec2/components/mpeg4_h263/Android.bp
index 41e4f44..e19fa45 100644
--- a/media/codec2/components/mpeg4_h263/Android.bp
+++ b/media/codec2/components/mpeg4_h263/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_mpeg4_h263_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_mpeg4_h263_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_mpeg4dec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +34,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_h263dec",
defaults: [
"libcodec2_soft-defaults",
@@ -31,7 +50,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mpeg4enc",
defaults: [
"libcodec2_soft-defaults",
@@ -49,7 +68,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_h263enc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 13cc0ec..ddd312f 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -35,8 +35,10 @@
namespace android {
constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
#ifdef MPEG4
+constexpr size_t kMaxDimension = 1920;
constexpr char COMPONENT_NAME[] = "c2.android.mpeg4.decoder";
#else
+constexpr size_t kMaxDimension = 352;
constexpr char COMPONENT_NAME[] = "c2.android.h263.decoder";
#endif
@@ -75,13 +77,8 @@
DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
.withDefault(new C2StreamPictureSizeInfo::output(0u, 176, 144))
.withFields({
-#ifdef MPEG4
- C2F(mSize, width).inRange(2, 1920, 2),
- C2F(mSize, height).inRange(2, 1088, 2),
-#else
- C2F(mSize, width).inRange(2, 352, 2),
- C2F(mSize, height).inRange(2, 288, 2),
-#endif
+ C2F(mSize, width).inRange(2, kMaxDimension, 2),
+ C2F(mSize, height).inRange(2, kMaxDimension, 2),
})
.withSetter(SizeSetter)
.build());
@@ -130,19 +127,10 @@
addParameter(
DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
-#ifdef MPEG4
- .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 1920, 1088))
-#else
.withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 352, 288))
-#endif
.withFields({
-#ifdef MPEG4
- C2F(mSize, width).inRange(2, 1920, 2),
- C2F(mSize, height).inRange(2, 1088, 2),
-#else
- C2F(mSize, width).inRange(2, 352, 2),
- C2F(mSize, height).inRange(2, 288, 2),
-#endif
+ C2F(mSize, width).inRange(2, kMaxDimension, 2),
+ C2F(mSize, height).inRange(2, kMaxDimension, 2),
})
.withSetter(MaxPictureSizeSetter, mSize)
.build());
@@ -200,13 +188,8 @@
const C2P<C2StreamPictureSizeInfo::output> &size) {
(void)mayBlock;
// TODO: get max width/height from the size's field helpers vs. hardcoding
-#ifdef MPEG4
- me.set().width = c2_min(c2_max(me.v.width, size.v.width), 1920u);
- me.set().height = c2_min(c2_max(me.v.height, size.v.height), 1088u);
-#else
- me.set().width = c2_min(c2_max(me.v.width, size.v.width), 352u);
- me.set().height = c2_min(c2_max(me.v.height, size.v.height), 288u);
-#endif
+ me.set().width = c2_min(c2_max(me.v.width, size.v.width), kMaxDimension);
+ me.set().height = c2_min(c2_max(me.v.height, size.v.height), kMaxDimension);
return C2R::Ok();
}
@@ -747,11 +730,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMpeg4DecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 54c8c47..3c87531 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -448,6 +448,20 @@
work->worklets.front()->output.configUpdate.push_back(std::move(csd));
}
+ // handle dynamic bitrate change
+ {
+ IntfImpl::Lock lock = mIntf->lock();
+ std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
+ lock.unlock();
+
+ if (bitrate != mBitrate) {
+ mBitrate = bitrate;
+ int layerBitrate[2] = {static_cast<int>(mBitrate->value), 0};
+ ALOGV("Calling PVUpdateBitRate %d", layerBitrate[0]);
+ PVUpdateBitRate(mHandle, layerBitrate);
+ }
+ }
+
std::shared_ptr<const C2GraphicView> rView;
std::shared_ptr<C2Buffer> inputBuffer;
bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
@@ -652,11 +666,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftMpeg4EncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/mpeg4_h263/TEST_MAPPING b/media/codec2/components/mpeg4_h263/TEST_MAPPING
new file mode 100644
index 0000000..93fba22
--- /dev/null
+++ b/media/codec2/components/mpeg4_h263/TEST_MAPPING
@@ -0,0 +1,6 @@
+// mappings for frameworks/av/media/codec2/components/mpeg4_h263
+{
+ "presubmit": [
+ { "name": "C2SoftMpeg4DecTest" }
+ ]
+}
diff --git a/media/codec2/components/opus/Android.bp b/media/codec2/components/opus/Android.bp
index 0ed141b..bfba45c 100644
--- a/media/codec2/components/opus/Android.bp
+++ b/media/codec2/components/opus/Android.bp
@@ -1,4 +1,13 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_opusdec",
defaults: [
"libcodec2_soft-defaults",
@@ -9,7 +18,7 @@
shared_libs: ["libopus"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_opusenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index b7c1556..d4987c0 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -473,11 +473,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftOpusDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index 70d1965..b47275f 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -626,11 +626,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftOpusEncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/raw/Android.bp b/media/codec2/components/raw/Android.bp
index dc944da..c0b7613 100644
--- a/media/codec2/components/raw/Android.bp
+++ b/media/codec2/components/raw/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_raw_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_raw_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_rawdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp
index 7b6f21a..31ca705 100644
--- a/media/codec2/components/raw/C2SoftRawDec.cpp
+++ b/media/codec2/components/raw/C2SoftRawDec.cpp
@@ -215,11 +215,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftRawDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/tests/Android.bp b/media/codec2/components/tests/Android.bp
new file mode 100644
index 0000000..3c68eee
--- /dev/null
+++ b/media/codec2/components/tests/Android.bp
@@ -0,0 +1,68 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "C2SoftCodecTest-defaults",
+ gtest: true,
+ host_supported: false,
+ srcs: [
+ "C2SoftCodecTest.cpp",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libion",
+ "libfmq",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "libcodec2",
+ "libhidlbase",
+ "libdmabufheap",
+ "libcodec2_vndk",
+ "libnativewindow",
+ "libcodec2_soft_common",
+ "libsfplugin_ccodec_utils",
+ "libstagefright_foundation",
+ "libstagefright_bufferpool@2.0.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ ],
+
+ shared_libs: [
+ "libui",
+ "libdl",
+ "libhardware",
+ "libvndksupport",
+ "libprocessgroup",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+cc_test {
+ name: "C2SoftMpeg4DecTest",
+ defaults: ["C2SoftCodecTest-defaults"],
+
+ static_libs: [
+ "libstagefright_m4vh263dec",
+ "libcodec2_soft_mpeg4dec",
+ ],
+
+ test_suites: [
+ "general-tests",
+ ],
+}
diff --git a/media/codec2/components/tests/C2SoftCodecTest.cpp b/media/codec2/components/tests/C2SoftCodecTest.cpp
new file mode 100644
index 0000000..84c2562
--- /dev/null
+++ b/media/codec2/components/tests/C2SoftCodecTest.cpp
@@ -0,0 +1,105 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <C2Config.h>
+#include <C2ComponentFactory.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+
+using namespace android;
+extern "C" ::C2ComponentFactory* CreateCodec2Factory();
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory);
+
+class C2SoftCodecTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ mFactory = CreateCodec2Factory();
+ }
+
+ void TearDown() override {
+ if (mFactory) {
+ DestroyCodec2Factory(mFactory);
+ }
+ }
+
+ c2_status_t createComponent(
+ std::shared_ptr<C2Component>* const comp) {
+ if (!mFactory) {
+ return C2_NO_INIT;
+ }
+ return mFactory->createComponent(
+ kPlaceholderId, comp, std::default_delete<C2Component>());
+ }
+
+ c2_status_t createInterface(
+ std::shared_ptr<C2ComponentInterface>* const intf) {
+ if (!mFactory) {
+ return C2_NO_INIT;
+ }
+ return mFactory->createInterface(
+ kPlaceholderId, intf, std::default_delete<C2ComponentInterface>());
+ }
+
+ ::C2ComponentFactory *getFactory() { return mFactory; }
+
+private:
+ static constexpr ::c2_node_id_t kPlaceholderId = 0;
+
+ ::C2ComponentFactory *mFactory;
+};
+
+TEST_F(C2SoftCodecTest, PictureSizeInfoTest) {
+ std::shared_ptr<C2ComponentInterface> interface;
+ c2_status_t status = createInterface(&interface);
+ ASSERT_EQ(status, C2_OK) << "Error in createInterface";
+ ASSERT_NE(interface, nullptr) << "interface is null";
+
+ std::unique_ptr<C2StreamPictureSizeInfo::output> param =
+ std::make_unique<C2StreamPictureSizeInfo::output>();
+ std::vector<C2FieldSupportedValuesQuery> validValueInfos = {
+ C2FieldSupportedValuesQuery::Current(
+ C2ParamField(param.get(), &C2StreamPictureSizeInfo::width)),
+ C2FieldSupportedValuesQuery::Current(
+ C2ParamField(param.get(), &C2StreamPictureSizeInfo::height))};
+ status = interface->querySupportedValues_vb(validValueInfos, C2_MAY_BLOCK);
+ ASSERT_EQ(status, C2_OK) << "Error in querySupportedValues_vb";
+ ASSERT_EQ(validValueInfos.size(), 2) << "querySupportedValues_vb didn't return 2 values";
+
+ ASSERT_EQ(validValueInfos[0].values.range.max.ref<uint32_t>(), 1920)
+ << "Incorrect maximum value for width";
+ ASSERT_EQ(validValueInfos[1].values.range.max.ref<uint32_t>(), 1920)
+ << "Incorrect maximum value for height";
+ ASSERT_EQ(validValueInfos[0].values.range.min.ref<uint32_t>(), 2)
+ << "Incorrect minimum value for width";
+ ASSERT_EQ(validValueInfos[1].values.range.min.ref<uint32_t>(), 2)
+ << "Incorrect minimum value for height";
+ ASSERT_EQ(validValueInfos[0].values.range.step.ref<uint32_t>(), 2)
+ << "Incorrect alignment value for width";
+ ASSERT_EQ(validValueInfos[1].values.range.step.ref<uint32_t>(), 2)
+ << "Incorrect alignment value for height";
+
+ return;
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ return status;
+}
diff --git a/media/codec2/components/vorbis/Android.bp b/media/codec2/components/vorbis/Android.bp
index bc1c380..ccf6f20 100644
--- a/media/codec2/components/vorbis/Android.bp
+++ b/media/codec2/components/vorbis/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_vorbis_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_vorbis_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_vorbisdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
index 15564d9..899fe9b 100644
--- a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
+++ b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
@@ -279,6 +279,8 @@
// skip 7 <type + "vorbis"> bytes
makeBitReader((const uint8_t *)data + 7, inSize - 7, &buf, &ref, &bits);
if (data[0] == 1) {
+ // release any memory that vorbis_info_init will blindly overwrite
+ vorbis_info_clear(mVi);
vorbis_info_init(mVi);
if (0 != _vorbis_unpack_info(mVi, &bits)) {
ALOGE("Encountered error while unpacking info");
@@ -323,6 +325,8 @@
work->result = C2_CORRUPTED;
return;
}
+ // release any memory that vorbis_dsp_init will blindly overwrite
+ vorbis_dsp_clear(mState);
if (0 != vorbis_dsp_init(mState, mVi)) {
ALOGE("Encountered error while dsp init");
mSignalledError = true;
@@ -473,11 +477,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVorbisDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vpx/Android.bp b/media/codec2/components/vpx/Android.bp
index 34f5753..bb6a545 100644
--- a/media/codec2/components/vpx/Android.bp
+++ b/media/codec2/components/vpx/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codec2_components_vpx_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codec2_components_vpx_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
name: "libcodec2_soft_vp9dec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +33,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp8dec",
defaults: [
"libcodec2_soft-defaults",
@@ -26,7 +45,7 @@
shared_libs: ["libvpx"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp9enc",
defaults: [
"libcodec2_soft-defaults",
@@ -43,7 +62,7 @@
cflags: ["-DVP9"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp8enc",
defaults: [
"libcodec2_soft-defaults",
@@ -57,4 +76,3 @@
shared_libs: ["libvpx"],
}
-
diff --git a/media/codec2/components/vpx/C2SoftVp8Enc.cpp b/media/codec2/components/vpx/C2SoftVp8Enc.cpp
index f18f5d0..049ec38 100644
--- a/media/codec2/components/vpx/C2SoftVp8Enc.cpp
+++ b/media/codec2/components/vpx/C2SoftVp8Enc.cpp
@@ -101,11 +101,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVp8EncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vpx/C2SoftVp9Enc.cpp b/media/codec2/components/vpx/C2SoftVp9Enc.cpp
index 740dbda..6401521 100644
--- a/media/codec2/components/vpx/C2SoftVp9Enc.cpp
+++ b/media/codec2/components/vpx/C2SoftVp9Enc.cpp
@@ -131,11 +131,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVp9EncFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 91238e8..2953d90 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -948,11 +948,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftVpxFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/components/xaac/Android.bp b/media/codec2/components/xaac/Android.bp
index 7795cc1..bb3efb5 100644
--- a/media/codec2/components/xaac/Android.bp
+++ b/media/codec2/components/xaac/Android.bp
@@ -1,8 +1,18 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libcodec2_soft_xaacdec",
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_all-defaults",
+ "libcodec2_soft_sanitize_cfi-defaults",
],
srcs: ["C2SoftXaacDec.cpp"],
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index 951d058..6deafda 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -1600,11 +1600,13 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
ALOGV("in %s", __func__);
return new ::android::C2SoftXaacDecFactory();
}
+__attribute__((cfi_canonical_jump_table))
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
ALOGV("in %s", __func__);
delete factory;
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index 33fafa7..64999b7 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libcodec2_headers",
vendor_available: true,
@@ -5,7 +14,7 @@
export_include_dirs: ["include"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2",
vendor_available: true,
min_sdk_version: "29",
@@ -52,4 +61,3 @@
ldflags: ["-Wl,-Bsymbolic"],
}
-
diff --git a/media/codec2/core/include/C2Buffer.h b/media/codec2/core/include/C2Buffer.h
index fe37b05..a5d6fbf 100644
--- a/media/codec2/core/include/C2Buffer.h
+++ b/media/codec2/core/include/C2Buffer.h
@@ -642,7 +642,8 @@
* \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
* \retval C2_OMITTED this allocator does not support 1D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during allocation
+ * (unexpected)
*/
virtual c2_status_t newLinearAllocation(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
@@ -666,7 +667,8 @@
* \retval C2_REFUSED no permission to recreate the allocation
* \retval C2_BAD_VALUE invalid handle (caller error)
* \retval C2_OMITTED this allocator does not support 1D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during allocation
+ * (unexpected)
*/
virtual c2_status_t priorLinearAllocation(
const C2Handle *handle __unused,
@@ -699,7 +701,8 @@
* \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
* \retval C2_OMITTED this allocator does not support 2D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during allocation
+ * (unexpected)
*/
virtual c2_status_t newGraphicAllocation(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
@@ -724,7 +727,8 @@
* \retval C2_REFUSED no permission to recreate the allocation
* \retval C2_BAD_VALUE invalid handle (caller error)
* \retval C2_OMITTED this allocator does not support 2D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during recreation
+ * (unexpected)
*/
virtual c2_status_t priorGraphicAllocation(
const C2Handle *handle __unused,
@@ -908,7 +912,8 @@
* \retval C2_REFUSED no permission to complete any required allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
* \retval C2_OMITTED this pool does not support linear blocks
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation
+ * (unexpected)
*/
virtual c2_status_t fetchLinearBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
@@ -937,7 +942,8 @@
* \retval C2_REFUSED no permission to complete any required allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
* \retval C2_OMITTED this pool does not support circular blocks
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation
+ * (unexpected)
*/
virtual c2_status_t fetchCircularBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
@@ -969,7 +975,8 @@
* \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
* error)
* \retval C2_OMITTED this pool does not support 2D blocks
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation
+ * (unexpected)
*/
virtual c2_status_t fetchGraphicBlock(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
@@ -980,6 +987,90 @@
}
virtual ~C2BlockPool() = default;
+
+ /**
+ * Blocking fetch for linear block. Obtains a linear writable block of given |capacity|
+ * and |usage|. If a block can be successfully obtained, the block is stored in |block|,
+ * |fence| is set to a null-fence and C2_OK is returned.
+ *
+ * If a block cannot be temporarily obtained, |block| is set to nullptr, a waitable fence
+ * is stored into |fence| and C2_BLOCKING is returned.
+ *
+ * Otherwise, |block| is set to nullptr and |fence| is set to a null-fence. The waitable
+ * fence is signalled when the temporary restriction on fetch is lifted.
+ * e.g. more memory is available to fetch because some meomory or prior blocks were released.
+ *
+ * \param capacity the size of requested block.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr will
+ * be stored here on failure
+ * \param fence pointer to where the fence shall be stored on C2_BLOCKING error.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_BLOCKING the operation is blocked
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this pool does not support linear blocks nor fence.
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation
+ * (unexpected)
+ */
+ virtual c2_status_t fetchLinearBlock(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */,
+ C2Fence *fence /* nonnull */) {
+ *block = nullptr;
+ (void) fence;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Blocking fetch for 2D graphic block. Obtains a 2D graphic writable block of given |capacity|
+ * and |usage|. If a block can be successfully obtained, the block is stored in |block|,
+ * |fence| is set to a null-fence and C2_OK is returned.
+ *
+ * If a block cannot be temporarily obtained, |block| is set to nullptr, a waitable fence
+ * is stored into |fence| and C2_BLOCKING is returned.
+ *
+ * Otherwise, |block| is set to nullptr and |fence| is set to a null-fence. The waitable
+ * fence is signalled when the temporary restriction on fetch is lifted.
+ * e.g. more memory is available to fetch because some meomory or prior blocks were released.
+ *
+ * \param width the width of requested block (the obtained block could be slightly larger, e.g.
+ * to accommodate any system-required alignment)
+ * \param height the height of requested block (the obtained block could be slightly larger,
+ * e.g. to accommodate any system-required alignment)
+ * \param format the pixel format of requested block. This could be a vendor specific format.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
+ * \param fence pointer to where the fence shall be stored on C2_BLOCKING error.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_BLOCKING the operation is blocked
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
+ * error)
+ * \retval C2_OMITTED this pool does not support 2D blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation
+ * (unexpected)
+ */
+ virtual c2_status_t fetchGraphicBlock(
+ uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
+ C2MemoryUsage usage __unused,
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
+ C2Fence *fence /* nonnull */) {
+ *block = nullptr;
+ (void) fence;
+ return C2_OMITTED;
+ }
protected:
C2BlockPool() = default;
};
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 38f7389..752140a 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -151,6 +151,7 @@
/* protected content */
kParamIndexSecureMode,
+ kParamIndexEncryptedBuffer, // info-buffer, used with SM_READ_PROTECTED_WITH_ENCRYPTED
// deprecated
kParamIndexDelayRequest = kParamIndexDelay | C2Param::CoreIndex::IS_REQUEST_FLAG,
@@ -221,6 +222,7 @@
kParamIndexDrcEffectType, // drc, enum
kParamIndexDrcOutputLoudness, // drc, float (dBFS)
kParamIndexDrcAlbumMode, // drc, enum
+ kParamIndexAudioFrameSize, // int
/* ============================== platform-defined parameters ============================== */
@@ -1144,6 +1146,8 @@
C2ENUM(C2Config::secure_mode_t, uint32_t,
SM_UNPROTECTED, ///< no content protection
SM_READ_PROTECTED, ///< input and output buffers shall be protected from reading
+ /// both read protected and readable encrypted buffers are used
+ SM_READ_PROTECTED_WITH_ENCRYPTED,
)
typedef C2GlobalParam<C2Tuning, C2SimpleValueStruct<C2Config::secure_mode_t>, kParamIndexSecureMode>
@@ -1969,9 +1973,20 @@
/**
* DRC output loudness in dBFS. Retrieved during decoding
*/
- typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
C2StreamDrcOutputLoudnessTuning;
- constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+
+/**
+ * Audio frame size in samples.
+ *
+ * Audio encoders can expose this parameter to signal the desired audio frame
+ * size that corresponds to a single coded access unit.
+ * Default value is 0, meaning that the encoder accepts input buffers of any size.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexAudioFrameSize>
+ C2StreamAudioFrameSizeInfo;
+constexpr char C2_PARAMKEY_AUDIO_FRAME_SIZE[] = "raw.audio-frame-size";
/* --------------------------------------- AAC components --------------------------------------- */
diff --git a/media/codec2/faultinjection/Android.bp b/media/codec2/faultinjection/Android.bp
index a0ad3ce..c04ecbe 100644
--- a/media/codec2/faultinjection/Android.bp
+++ b/media/codec2/faultinjection/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libcodec2_component_wrapper",
vendor_available: true,
@@ -26,4 +35,3 @@
ldflags: ["-Wl,-Bsymbolic"],
}
-
diff --git a/media/codec2/fuzzer/Android.bp b/media/codec2/fuzzer/Android.bp
new file mode 100644
index 0000000..bd1fac6
--- /dev/null
+++ b/media/codec2/fuzzer/Android.bp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "C2Fuzzer-defaults",
+
+ srcs: [
+ "C2Fuzzer.cpp",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libion",
+ "libfmq",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "libcodec2",
+ "libhidlbase",
+ "libdmabufheap",
+ "libcodec2_vndk",
+ "libnativewindow",
+ "libcodec2_soft_common",
+ "libsfplugin_ccodec_utils",
+ "libstagefright_foundation",
+ "libstagefright_bufferpool@2.0.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ ],
+
+ shared_libs: [
+ "libui",
+ "libdl",
+ "libbinder",
+ "libhardware",
+ "libvndksupport",
+ "libprocessgroup",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAvcDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.avc.decoder\"",
+ ],
+
+ static_libs: [
+ "libavcdec",
+ "libcodec2_soft_avcdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerHevcDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.hevc.decoder\"",
+ ],
+
+ static_libs: [
+ "libhevcdec",
+ "libcodec2_soft_hevcdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerMpeg2Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.mpeg2.decoder\"",
+ ],
+
+ static_libs: [
+ "libmpeg2dec",
+ "libcodec2_soft_mpeg2dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerMpeg4Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.mpeg4.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_m4vh263dec",
+ "libcodec2_soft_mpeg4dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerH263Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.h263.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_m4vh263dec",
+ "libcodec2_soft_h263dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerVp8Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.vp8.decoder\"",
+ ],
+
+ static_libs: [
+ "libvpx",
+ "libcodec2_soft_vp8dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerVp9Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.vp9.decoder\"",
+ ],
+
+ static_libs: [
+ "libvpx",
+ "libcodec2_soft_vp9dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAacDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.aac.decoder\"",
+ ],
+
+ static_libs: [
+ "libFraunhoferAAC",
+ "libcodec2_soft_aacdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAmrnbDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.amrnb.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_amrnbdec",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrnb_common",
+ "libcodec2_soft_amrnbdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerAmrwbDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.amrwb.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_amrnbdec",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrnb_common",
+ "libcodec2_soft_amrwbdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerFlacDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.flac.decoder\"",
+ ],
+
+ static_libs: [
+ "libFLAC",
+ "libstagefright_flacdec",
+ "libcodec2_soft_flacdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerG711AlawDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.g711.alaw.decoder\"",
+ ],
+
+ static_libs: [
+ "codecs_g711dec",
+ "libcodec2_soft_g711alawdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerG711MlawDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.g711.mlaw.decoder\"",
+ ],
+
+ static_libs: [
+ "codecs_g711dec",
+ "libcodec2_soft_g711mlawdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerGsmDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.gsm.decoder\"",
+ ],
+
+ static_libs: [
+ "libgsm",
+ "libcodec2_soft_gsmdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerMp3Dec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.mp3.decoder\"",
+ ],
+
+ static_libs: [
+ "libstagefright_mp3dec",
+ "libcodec2_soft_mp3dec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerOpusDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.opus.decoder\"",
+ ],
+
+ static_libs: [
+ "libopus",
+ "libcodec2_soft_opusdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerRawDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.raw.decoder\"",
+ ],
+
+ static_libs: [
+ "libcodec2_soft_rawdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerVorbisDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.vorbis.decoder\"",
+ ],
+
+ static_libs: [
+ "libvorbisidec",
+ "libcodec2_soft_vorbisdec",
+ ],
+}
+
+cc_fuzz {
+ name: "C2FuzzerXaacDec",
+ defaults: ["C2Fuzzer-defaults"],
+
+ cflags: [
+ "-DC2COMPONENTNAME=\"c2.android.xaac.decoder\"",
+ ],
+
+ static_libs: [
+ "libxaacdec",
+ "libcodec2_soft_xaacdec",
+ ],
+}
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
new file mode 100644
index 0000000..51e1013
--- /dev/null
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -0,0 +1,317 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <stdio.h>
+
+#include <C2Fuzzer.h>
+
+using namespace android;
+
+class LinearBuffer : public C2Buffer {
+ public:
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
+ : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
+ : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
+};
+
+/**
+ * Handle Callback functions onWorkDone_nb(), onTripped_nb(), onError_nb() for C2 Components
+ */
+struct CodecListener : public C2Component::Listener {
+ public:
+ CodecListener(const std::function<void(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems)>
+ fn = nullptr)
+ : callBack(fn) {}
+ virtual void onWorkDone_nb(const std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>> workItems) {
+ if (callBack) {
+ callBack(comp, workItems);
+ }
+ }
+
+ virtual void onTripped_nb(const std::weak_ptr<C2Component> comp,
+ const std::vector<std::shared_ptr<C2SettingResult>> settingResults) {
+ (void)comp;
+ (void)settingResults;
+ }
+
+ virtual void onError_nb(const std::weak_ptr<C2Component> comp, uint32_t errorCode) {
+ (void)comp;
+ (void)errorCode;
+ }
+
+ std::function<void(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
+};
+
+/**
+ * Buffer source implementations to identify a frame and its size
+ */
+bool Codec2Fuzzer::BufferSource::searchForMarker() {
+ while (true) {
+ if (isMarker()) {
+ return true;
+ }
+ --mReadIndex;
+ if (mReadIndex > mSize) {
+ break;
+ }
+ }
+ return false;
+}
+
+void Codec2Fuzzer::BufferSource::parse() {
+ bool isFrameAvailable = true;
+ size_t bytesRemaining = mSize;
+ while (isFrameAvailable) {
+ isFrameAvailable = searchForMarker();
+ if (isFrameAvailable) {
+ size_t location = mReadIndex + kMarkerSize;
+ bool isCSD = isCSDMarker(location);
+ location += kMarkerSuffixSize;
+ uint8_t* framePtr = const_cast<uint8_t*>(&mData[location]);
+ size_t frameSize = bytesRemaining - location;
+ uint32_t flags = 0;
+ if (mFrameList.empty()) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ } else if (isCSD) {
+ flags |= C2FrameData::FLAG_CODEC_CONFIG;
+ }
+ mFrameList.emplace_back(std::make_tuple(framePtr, frameSize, flags));
+ bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
+ --mReadIndex;
+ }
+ }
+ if (mFrameList.empty()) {
+ /**
+ * Scenario where input data does not contain the custom frame markers.
+ * Hence feed the entire data as single frame.
+ */
+ mFrameList.emplace_back(
+ std::make_tuple(const_cast<uint8_t*>(mData), 0, C2FrameData::FLAG_END_OF_STREAM));
+ mFrameList.emplace_back(
+ std::make_tuple(const_cast<uint8_t*>(mData), mSize, C2FrameData::FLAG_CODEC_CONFIG));
+ }
+}
+
+FrameData Codec2Fuzzer::BufferSource::getFrame() {
+ FrameData frame = mFrameList.back();
+ mFrameList.pop_back();
+ return frame;
+}
+
+void Codec2Fuzzer::handleWorkDone(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems) {
+ (void)comp;
+ for (std::unique_ptr<C2Work>& work : workItems) {
+ if (!work->worklets.empty()) {
+ if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
+ mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
+ work->input.buffers.clear();
+ work->worklets.clear();
+ {
+ std::unique_lock<std::mutex> lock(mQueueLock);
+ mWorkQueue.push_back(std::move(work));
+ mQueueCondition.notify_all();
+ }
+ if (mEos) {
+ {
+ std::lock_guard<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
+ }
+ mConditionalVariable.notify_one();
+ }
+ }
+ }
+ }
+}
+
+bool Codec2Fuzzer::initDecoder() {
+ std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> codec2FactoryFunc;
+
+ codec2FactoryFunc.emplace_back(
+ std::make_tuple(C2COMPONENTNAME, &CreateCodec2Factory, &DestroyCodec2Factory));
+
+ std::shared_ptr<C2ComponentStore> componentStore = GetTestComponentStore(codec2FactoryFunc);
+ if (!componentStore) {
+ return false;
+ }
+
+ std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
+ if (!allocatorStore) {
+ return false;
+ }
+
+ c2_status_t status =
+ allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, ++mBlockPoolId);
+ if (!mLinearPool) {
+ return false;
+ }
+
+ for (int32_t i = 0; i < kNumberOfC2WorkItems; ++i) {
+ mWorkQueue.emplace_back(new C2Work);
+ }
+
+ status = componentStore->createComponent(C2COMPONENTNAME, &mComponent);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ status = componentStore->createInterface(C2COMPONENTNAME, &mInterface);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ C2ComponentKindSetting kind;
+ C2ComponentDomainSetting domain;
+ status = mInterface->query_vb({&kind, &domain}, {}, C2_MAY_BLOCK, nullptr);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ std::vector<C2Param*> configParams;
+ if (domain.value == DOMAIN_VIDEO) {
+ C2StreamPictureSizeInfo::input inputSize(0u, kWidthOfVideo, kHeightOfVideo);
+ configParams.push_back(&inputSize);
+ } else if (domain.value == DOMAIN_AUDIO) {
+ C2StreamSampleRateInfo::output sampleRateInfo(0u, kSamplingRateOfAudio);
+ C2StreamChannelCountInfo::output channelCountInfo(0u, kChannelsOfAudio);
+ configParams.push_back(&sampleRateInfo);
+ configParams.push_back(&channelCountInfo);
+ }
+
+ mListener.reset(new CodecListener(
+ [this](std::weak_ptr<C2Component> comp, std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(comp, workItems);
+ }));
+ if (!mListener) {
+ return false;
+ }
+
+ status = mComponent->setListener_vb(mListener, C2_DONT_BLOCK);
+ if (status != C2_OK) {
+ return false;
+ }
+
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ componentStore->config_sm(configParams, &failures);
+ if (failures.size() != 0) {
+ return false;
+ }
+
+ status = mComponent->start();
+ if (status != C2_OK) {
+ return false;
+ }
+
+ return true;
+}
+
+void Codec2Fuzzer::deInitDecoder() {
+ mComponent->stop();
+ mComponent->reset();
+ mComponent->release();
+ mComponent = nullptr;
+}
+
+void Codec2Fuzzer::decodeFrames(const uint8_t* data, size_t size) {
+ mBufferSource = new BufferSource(data, size);
+ if (!mBufferSource) {
+ return;
+ }
+ mBufferSource->parse();
+ c2_status_t status = C2_OK;
+ size_t numFrames = 0;
+ while (!mBufferSource->isEos()) {
+ uint8_t* frame = nullptr;
+ size_t frameSize = 0;
+ FrameData frameData = mBufferSource->getFrame();
+ frame = std::get<0>(frameData);
+ frameSize = std::get<1>(frameData);
+
+ std::unique_ptr<C2Work> work;
+ {
+ std::unique_lock<std::mutex> lock(mQueueLock);
+ if (mWorkQueue.empty()) mQueueCondition.wait_for(lock, kC2FuzzerTimeOut);
+ if (!mWorkQueue.empty()) {
+ work.swap(mWorkQueue.front());
+ mWorkQueue.pop_front();
+ } else {
+ return;
+ }
+ }
+
+ work->input.flags = (C2FrameData::flags_t)std::get<2>(frameData);
+ work->input.ordinal.timestamp = 0;
+ work->input.ordinal.frameIndex = ++numFrames;
+ work->input.buffers.clear();
+ int32_t alignedSize = C2FUZZER_ALIGN(frameSize, PAGE_SIZE);
+
+ std::shared_ptr<C2LinearBlock> block;
+ status = mLinearPool->fetchLinearBlock(
+ alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ if (status != C2_OK || block == nullptr) {
+ return;
+ }
+
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ return;
+ }
+ memcpy(view.base(), frame, frameSize);
+ work->input.buffers.emplace_back(new LinearBuffer(block, frameSize));
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+ status = mComponent->queue_nb(&items);
+ if (status != C2_OK) {
+ return;
+ }
+ }
+ std::unique_lock<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
+ mConditionalVariable.wait_for(waitForDecodeComplete, kC2FuzzerTimeOut, [this] { return mEos; });
+ std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+ mComponent->flush_sm(C2Component::FLUSH_COMPONENT, &c2flushedWorks);
+ delete mBufferSource;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ Codec2Fuzzer* codec = new Codec2Fuzzer();
+ if (!codec) {
+ return 0;
+ }
+ if (codec->initDecoder()) {
+ codec->decodeFrames(data, size);
+ }
+ delete codec;
+ return 0;
+}
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
new file mode 100644
index 0000000..d5ac81a
--- /dev/null
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#ifndef __C2FUZZER_H__
+#define __C2FUZZER_H__
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+#include <C2Component.h>
+#include <C2Config.h>
+#include <C2PlatformSupport.h>
+
+using namespace std::chrono_literals;
+
+extern "C" ::C2ComponentFactory* CreateCodec2Factory();
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory);
+
+namespace android {
+
+#define C2FUZZER_ALIGN(_sz, _align) (((_sz) + ((_align)-1)) & ~((_align)-1))
+
+constexpr std::chrono::milliseconds kC2FuzzerTimeOut = 5000ms;
+constexpr int32_t kNumberOfC2WorkItems = 8;
+constexpr uint32_t kWidthOfVideo = 3840;
+constexpr uint32_t kHeightOfVideo = 2160;
+constexpr uint32_t kSamplingRateOfAudio = 48000;
+constexpr uint32_t kChannelsOfAudio = 8;
+
+typedef std::tuple<uint8_t*, size_t, uint32_t> FrameData;
+
+class Codec2Fuzzer {
+ public:
+ Codec2Fuzzer() = default;
+ ~Codec2Fuzzer() { deInitDecoder(); }
+ bool initDecoder();
+ void deInitDecoder();
+ void decodeFrames(const uint8_t* data, size_t size);
+
+ void handleWorkDone(std::weak_ptr<C2Component> comp,
+ std::list<std::unique_ptr<C2Work>>& workItems);
+
+ private:
+ class BufferSource {
+ public:
+ BufferSource(const uint8_t* data, size_t size) : mData(data), mSize(size) {
+ mReadIndex = (size <= kMarkerSize) ? 0 : (size - kMarkerSize);
+ }
+ ~BufferSource() {
+ mData = nullptr;
+ mSize = 0;
+ mReadIndex = 0;
+ mFrameList.clear();
+ }
+ bool isEos() { return mFrameList.empty(); }
+ void parse();
+ FrameData getFrame();
+
+ private:
+ bool isMarker() {
+ if ((kMarkerSize < mSize) && (mReadIndex < mSize - kMarkerSize)) {
+ return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0);
+ } else {
+ return false;
+ }
+ }
+
+ bool isCSDMarker(size_t position) {
+ if ((kMarkerSuffixSize < mSize) && (position < mSize - kMarkerSuffixSize)) {
+ return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+ } else {
+ return false;
+ }
+ }
+
+ bool searchForMarker();
+
+ const uint8_t* mData = nullptr;
+ size_t mSize = 0;
+ size_t mReadIndex = 0;
+ std::vector<FrameData> mFrameList;
+ static constexpr uint8_t kMarker[] = "_MARK";
+ static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
+ static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
+ // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
+ static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
+ // All marker types should be 3 bytes long ('_H_', '_F_')
+ static constexpr size_t kMarkerSuffixSize = 3;
+ };
+
+ BufferSource* mBufferSource;
+ bool mEos = false;
+ C2BlockPool::local_id_t mBlockPoolId;
+
+ std::shared_ptr<C2BlockPool> mLinearPool;
+ std::shared_ptr<C2Allocator> mLinearAllocator;
+ std::shared_ptr<C2Component::Listener> mListener;
+ std::shared_ptr<C2Component> mComponent;
+ std::shared_ptr<C2ComponentInterface> mInterface;
+ std::mutex mQueueLock;
+ std::condition_variable mQueueCondition;
+ std::list<std::unique_ptr<C2Work>> mWorkQueue;
+ std::mutex mDecodeCompleteMutex;
+ std::condition_variable mConditionalVariable;
+};
+
+} // namespace android
+
+#endif // __C2FUZZER_H__
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index 3b73350..008def8 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -1,5 +1,14 @@
// DO NOT DEPEND ON THIS DIRECTLY
// use libcodec2-hidl-client-defaults instead
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libcodec2_hidl_client@1.0",
@@ -80,6 +89,7 @@
"libbase",
"libcodec2",
"libcodec2_vndk",
+ "libcodec2_hidl_plugin_stub",
"libcutils",
"libhidlbase",
"liblog",
@@ -93,9 +103,17 @@
vendor: {
exclude_shared_libs: [
"libstagefright_bufferqueue_helper_novndk",
+ "libcodec2_hidl_plugin_stub",
],
shared_libs: [
"libstagefright_bufferqueue_helper",
+ "libcodec2_hidl_plugin",
+ ],
+ },
+ apex: {
+ exclude_shared_libs: [
+ "libcodec2_hidl_plugin",
+ "libcodec2_hidl_plugin_stub",
],
},
},
diff --git a/media/codec2/hidl/1.0/utils/Component.cpp b/media/codec2/hidl/1.0/utils/Component.cpp
index 8a84601..082c5e3 100644
--- a/media/codec2/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hidl/1.0/utils/Component.cpp
@@ -22,6 +22,10 @@
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/InputBufferManager.h>
+#ifndef __ANDROID_APEX__
+#include <FilterWrapper.h>
+#endif
+
#include <hidl/HidlBinderSupport.h>
#include <utils/Timers.h>
@@ -390,10 +394,17 @@
uint32_t allocatorId,
createBlockPool_cb _hidl_cb) {
std::shared_ptr<C2BlockPool> blockPool;
+#ifdef __ANDROID_APEX__
c2_status_t status = CreateCodec2BlockPool(
static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
mComponent,
&blockPool);
+#else
+ c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
+ static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+ mComponent,
+ &blockPool);
+#endif
if (status != C2_OK) {
blockPool = nullptr;
}
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index 9b9d449..1c0d5b0 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -35,6 +35,14 @@
#include <ostream>
#include <sstream>
+#ifndef __ANDROID_APEX__
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <dlfcn.h>
+#include <C2Config.h>
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+#endif
+
namespace android {
namespace hardware {
namespace media {
@@ -176,6 +184,16 @@
return mParameterCache;
}
+#ifndef __ANDROID_APEX__
+// static
+std::shared_ptr<FilterWrapper> ComponentStore::GetFilterWrapper() {
+ constexpr const char kPluginPath[] = "libc2filterplugin.so";
+ static std::shared_ptr<FilterWrapper> wrapper = FilterWrapper::Create(
+ std::make_unique<DefaultFilterPlugin>(kPluginPath));
+ return wrapper;
+}
+#endif
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
const hidl_string& name,
@@ -189,6 +207,9 @@
mStore->createComponent(name, &c2component));
if (status == Status::OK) {
+#ifndef __ANDROID_APEX__
+ c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
onInterfaceLoaded(c2component->intf());
component = new Component(c2component, listener, this, pool);
if (!component) {
@@ -214,8 +235,12 @@
createInterface_cb _hidl_cb) {
std::shared_ptr<C2ComponentInterface> c2interface;
c2_status_t res = mStore->createInterface(name, &c2interface);
+
sp<IComponentInterface> interface;
if (res == C2_OK) {
+#ifndef __ANDROID_APEX__
+ c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
+#endif
onInterfaceLoaded(c2interface);
interface = new ComponentInterface(c2interface, mParameterCache);
}
@@ -458,7 +483,6 @@
return Void();
}
-
} // namespace utils
} // namespace V1_0
} // namespace c2
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index fe7d048..27e2a05 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -37,6 +37,8 @@
#include <vector>
namespace android {
+class FilterWrapper;
+
namespace hardware {
namespace media {
namespace c2 {
@@ -74,6 +76,8 @@
*/
std::shared_ptr<ParameterCache> getParameterCache() const;
+ static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
virtual Return<void> createComponent(
const hidl_string& name,
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index 1f0c856..72f7c43 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -895,13 +895,12 @@
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- // TODO: C2InfoBuffer is not implemented.
- (void)d;
- (void)s;
- (void)bufferPoolSender;
- (void)baseBlocks;
- (void)baseBlockIndices;
- LOG(INFO) << "InfoBuffer not implemented.";
+ d->index = static_cast<ParamIndex>(s.index());
+ Buffer& dBuffer = d->buffer;
+ if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2InfoBuffer::data";
+ return false;
+ }
return true;
}
@@ -1336,6 +1335,68 @@
return true;
}
+// InfoBuffer -> C2InfoBuffer
+bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
+ const std::vector<C2BaseBlock>& baseBlocks) {
+
+ // Currently, a non-null C2InfoBufer must contain exactly 1 block.
+ if (s.buffer.blocks.size() == 0) {
+ return true;
+ } else if (s.buffer.blocks.size() != 1) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer "
+ "Currently, a C2InfoBuffer must contain exactly 1 block.";
+ return false;
+ }
+
+ const Block &sBlock = s.buffer.blocks[0];
+ if (sBlock.index >= baseBlocks.size()) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
+ "Array index out of range.";
+ return false;
+ }
+ const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
+
+ // Parse meta.
+ std::vector<C2Param*> sBlockMeta;
+ if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
+ return false;
+ }
+
+ // Copy fence.
+ C2Fence dFence;
+ if (!objcpy(&dFence, sBlock.fence)) {
+ LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
+ return false;
+ }
+
+ // Construct a block.
+ switch (baseBlock.type) {
+ case C2BaseBlock::LINEAR:
+ if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
+ sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
+ C2Hidl_RangeInfo *rangeInfo =
+ reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
+ d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
+ s.index,
+ baseBlock.linear->share(
+ rangeInfo->offset, rangeInfo->length, dFence)));
+ return true;
+ }
+ LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
+ break;
+ case C2BaseBlock::GRAPHIC:
+ // It's not used now
+ LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
+ break;
+ default:
+ LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
+ break;
+ }
+
+ return false;
+}
+
// FrameData -> C2FrameData
bool objcpy(C2FrameData* d, const FrameData& s,
const std::vector<C2BaseBlock>& baseBlocks) {
@@ -1370,8 +1431,18 @@
}
}
- // TODO: Implement this once C2InfoBuffer has constructors.
d->infoBuffers.clear();
+ if (s.infoBuffers.size() == 0) {
+ // InfoBuffer is optional
+ return true;
+ }
+ d->infoBuffers.reserve(s.infoBuffers.size());
+ for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
+ if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
+ LOG(ERROR) << "Invalid Framedata::infoBuffers.";
+ return false;
+ }
+ }
return true;
}
diff --git a/media/codec2/hidl/1.0/vts/functional/Android.bp b/media/codec2/hidl/1.0/vts/functional/Android.bp
index 5ea4825..0ae133c 100644
--- a/media/codec2/hidl/1.0/vts/functional/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
filegroup {
name: "media_c2_v1_audio_decode_res",
path: "res",
@@ -108,4 +117,4 @@
srcs: [
"res/bbb_352x288_420p_30fps_32frames.yuv",
],
-}
\ No newline at end of file
+}
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
index 014cbe9..624aad2 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "VtsHalMediaC2V1_0TargetAudioDecTest",
stem: "vts_media_c2_v1_0_audio_dec_test",
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index 3a47ae9..1f95eaf 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -39,8 +39,44 @@
static std::vector<std::tuple<std::string, std::string, std::string>> kCsdFlushTestParameters;
-// Resource directory
-static std::string sResourceDir = "";
+struct CompToURL {
+ std::string mime;
+ std::string mURL;
+ std::string info;
+};
+
+std::vector<CompToURL> kCompToURL = {
+ {"mp4a-latm",
+ "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"},
+ {"mp4a-latm",
+ "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"},
+ {"audio/mpeg",
+ "bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.info"},
+ {"audio/mpeg",
+ "bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"},
+ {"3gpp",
+ "sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.info"},
+ {"3gpp",
+ "sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"},
+ {"amr-wb",
+ "bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.info"},
+ {"amr-wb",
+ "bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"},
+ {"vorbis",
+ "bbb_vorbis_stereo_128kbps_48000hz.vorbis", "bbb_vorbis_stereo_128kbps_48000hz.info"},
+ {"opus",
+ "bbb_opus_stereo_128kbps_48000hz.opus", "bbb_opus_stereo_128kbps_48000hz.info"},
+ {"g711-alaw",
+ "bbb_g711alaw_1ch_8khz.raw", "bbb_g711alaw_1ch_8khz.info"},
+ {"g711-mlaw",
+ "bbb_g711mulaw_1ch_8khz.raw", "bbb_g711mulaw_1ch_8khz.info"},
+ {"gsm",
+ "bbb_gsm_1ch_8khz_13kbps.raw", "bbb_gsm_1ch_8khz_13kbps.info"},
+ {"raw",
+ "bbb_raw_1ch_8khz_s32le.raw", "bbb_raw_1ch_8khz_s32le.info"},
+ {"flac",
+ "bbb_flac_stereo_680kbps_48000hz.flac", "bbb_flac_stereo_680kbps_48000hz.info"},
+};
class LinearBuffer : public C2Buffer {
public:
@@ -76,33 +112,17 @@
mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
ASSERT_NE(mLinearPool, nullptr);
- mCompName = unknown_comp;
- struct StringToName {
- const char* Name;
- standardComp CompName;
- };
- const StringToName kStringToName[] = {
- {"xaac", xaac}, {"mp3", mp3}, {"amrnb", amrnb},
- {"amrwb", amrwb}, {"aac", aac}, {"vorbis", vorbis},
- {"opus", opus}, {"pcm", pcm}, {"g711.alaw", g711alaw},
- {"g711.mlaw", g711mlaw}, {"gsm", gsm}, {"raw", raw},
- {"flac", flac},
- };
- const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
+ std::vector<std::unique_ptr<C2Param>> queried;
+ mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE}, C2_DONT_BLOCK, &queried);
+ ASSERT_GT(queried.size(), 0);
- // Find the component type
- for (size_t i = 0; i < kNumStringToName; ++i) {
- if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
- mCompName = kStringToName[i].CompName;
- break;
- }
- }
+ mMime = ((C2PortMediaTypeSetting::input*)queried[0].get())->m.value;
+
mEos = false;
mFramesReceived = 0;
mTimestampUs = 0u;
mWorkResult = C2_OK;
mTimestampDevTest = false;
- if (mCompName == unknown_comp) mDisableTest = true;
if (mDisableTest) std::cout << "[ WARN ] Test Disabled \n";
}
@@ -119,6 +139,8 @@
virtual void validateTimestampList(int32_t* bitStreamInfo);
+ void GetURLForComponent(char* mURL, char* info, size_t streamIndex = 0);
+
struct outputMetaData {
uint64_t timestampUs;
uint32_t rangeLength;
@@ -158,29 +180,12 @@
}
}
- enum standardComp {
- xaac,
- mp3,
- amrnb,
- amrwb,
- aac,
- vorbis,
- opus,
- pcm,
- g711alaw,
- g711mlaw,
- gsm,
- raw,
- flac,
- unknown_comp,
- };
-
+ std::string mMime;
std::string mInstanceName;
std::string mComponentName;
bool mEos;
bool mDisableTest;
bool mTimestampDevTest;
- standardComp mCompName;
int32_t mWorkResult;
uint64_t mTimestampUs;
@@ -217,7 +222,7 @@
};
void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2AudioDecHidlTest::standardComp compName, bool& disableTest) {
+ bool& disableTest) {
// Validate its a C2 Component
if (component->getName().find("c2") == std::string::npos) {
ALOGE("Not a c2 component");
@@ -244,13 +249,6 @@
return;
}
}
-
- // Validates component name
- if (compName == Codec2AudioDecHidlTest::unknown_comp) {
- ALOGE("Component InValid");
- disableTest = true;
- return;
- }
ALOGV("Component Valid");
}
@@ -271,7 +269,7 @@
// parsing the header of elementary stream. Client needs to collect this
// information and reconfigure
void getInputChannelInfo(const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2AudioDecHidlTest::standardComp compName, int32_t* bitStreamInfo) {
+ std::string mime, int32_t* bitStreamInfo) {
// query nSampleRate and nChannels
std::initializer_list<C2Param::Index> indices{
C2StreamSampleRateInfo::output::PARAM_TYPE,
@@ -288,89 +286,29 @@
C2Param* param = inParams[i].get();
bitStreamInfo[i] = *(int32_t*)((uint8_t*)param + offset);
}
- switch (compName) {
- case Codec2AudioDecHidlTest::amrnb: {
- ASSERT_EQ(bitStreamInfo[0], 8000);
- ASSERT_EQ(bitStreamInfo[1], 1);
- break;
- }
- case Codec2AudioDecHidlTest::amrwb: {
- ASSERT_EQ(bitStreamInfo[0], 16000);
- ASSERT_EQ(bitStreamInfo[1], 1);
- break;
- }
- case Codec2AudioDecHidlTest::gsm: {
- ASSERT_EQ(bitStreamInfo[0], 8000);
- break;
- }
- default:
- break;
+ if (mime.find("3gpp") != std::string::npos) {
+ ASSERT_EQ(bitStreamInfo[0], 8000);
+ ASSERT_EQ(bitStreamInfo[1], 1);
+ } else if (mime.find("amr-wb") != std::string::npos) {
+ ASSERT_EQ(bitStreamInfo[0], 16000);
+ ASSERT_EQ(bitStreamInfo[1], 1);
+ } else if (mime.find("gsm") != std::string::npos) {
+ ASSERT_EQ(bitStreamInfo[0], 8000);
}
}
}
-// number of elementary streams per component
-#define STREAM_COUNT 2
-
// LookUpTable of clips and metadata for component testing
-void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL, char* info,
- size_t streamIndex = 0) {
- struct CompToURL {
- Codec2AudioDecHidlTest::standardComp comp;
- const char mURL[STREAM_COUNT][512];
- const char info[STREAM_COUNT][512];
- };
- ASSERT_TRUE(streamIndex < STREAM_COUNT);
-
- static const CompToURL kCompToURL[] = {
- {Codec2AudioDecHidlTest::standardComp::xaac,
- {"bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.aac"},
- {"bbb_aac_stereo_128kbps_48000hz.info",
- "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::mp3,
- {"bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.mp3"},
- {"bbb_mp3_stereo_192kbps_48000hz.info",
- "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::aac,
- {"bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.aac"},
- {"bbb_aac_stereo_128kbps_48000hz.info",
- "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::amrnb,
- {"sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
- {"sine_amrnb_1ch_12kbps_8000hz.info",
- "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::amrwb,
- {"bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
- {"bbb_amrwb_1ch_14kbps_16000hz.info",
- "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::vorbis,
- {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
- {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::opus,
- {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
- {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::g711alaw,
- {"bbb_g711alaw_1ch_8khz.raw", ""},
- {"bbb_g711alaw_1ch_8khz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::g711mlaw,
- {"bbb_g711mulaw_1ch_8khz.raw", ""},
- {"bbb_g711mulaw_1ch_8khz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::gsm,
- {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
- {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::raw,
- {"bbb_raw_1ch_8khz_s32le.raw", ""},
- {"bbb_raw_1ch_8khz_s32le.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::flac,
- {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
- {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
- };
-
- for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
- if (kCompToURL[i].comp == comp) {
- strcat(mURL, kCompToURL[i].mURL[streamIndex]);
- strcat(info, kCompToURL[i].info[streamIndex]);
- return;
+void Codec2AudioDecHidlTestBase::GetURLForComponent(char* mURL, char* info, size_t streamIndex) {
+ int streamCount = 0;
+ for (size_t i = 0; i < kCompToURL.size(); ++i) {
+ if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
+ if (streamCount == streamIndex) {
+ strcat(mURL, kCompToURL[i].mURL.c_str());
+ strcat(info, kCompToURL[i].info.c_str());
+ return;
+ }
+ streamCount++;
}
}
}
@@ -461,7 +399,7 @@
void Codec2AudioDecHidlTestBase::validateTimestampList(int32_t* bitStreamInfo) {
uint32_t samplesReceived = 0;
// Update SampleRate and ChannelCount
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
int32_t nSampleRate = bitStreamInfo[0];
int32_t nChannels = bitStreamInfo[1];
std::list<uint64_t>::iterator itIn = mTimestampUslist.begin();
@@ -486,7 +424,7 @@
TEST_P(Codec2AudioDecHidlTest, validateCompName) {
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the given component is a valid audio component");
- validateComponent(mComponent, mCompName, mDisableTest);
+ validateComponent(mComponent, mDisableTest);
ASSERT_EQ(mDisableTest, false);
}
@@ -495,7 +433,7 @@
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ASSERT_EQ(mComponent->start(), C2_OK);
int32_t bitStreamInfo[2] = {0};
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
setupConfigParam(mComponent, bitStreamInfo);
ASSERT_EQ(mComponent->stop(), C2_OK);
}
@@ -523,7 +461,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info, streamIndex);
+ GetURLForComponent(mURL, info, streamIndex);
if (!strcmp(mURL, sResourceDir.c_str())) {
ALOGV("EMPTY INPUT sResourceDir.c_str() %s mURL %s ", sResourceDir.c_str(), mURL);
return;
@@ -536,11 +474,11 @@
mFramesReceived = 0;
mTimestampUs = 0;
int32_t bitStreamInfo[2] = {0};
- if (mCompName == raw) {
+ if (mMime.find("raw") != std::string::npos) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -591,17 +529,17 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
int32_t bitStreamInfo[2] = {0};
- if (mCompName == raw) {
+ if (mMime.find("raw") != std::string::npos) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -683,17 +621,17 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
int32_t bitStreamInfo[2] = {0};
- if (mCompName == raw) {
+ if (mMime.find("raw") != std::string::npos) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -768,7 +706,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
@@ -798,11 +736,11 @@
}
eleInfo.close();
int32_t bitStreamInfo[2] = {0};
- if (mCompName == raw) {
+ if (mMime.find("raw") != std::string::npos) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -853,7 +791,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
if (!strcmp(mURL, sResourceDir.c_str())) {
ALOGV("EMPTY INPUT sResourceDir.c_str() %s mURL %s ", sResourceDir.c_str(), mURL);
return;
@@ -864,11 +802,11 @@
ASSERT_GE(numCsds, 0) << "Error in parsing input info file";
int32_t bitStreamInfo[2] = {0};
- if (mCompName == raw) {
+ if (mMime.find("raw") != std::string::npos) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mMime, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -951,6 +889,7 @@
} // anonymous namespace
int main(int argc, char** argv) {
+ parseArgs(argc, argv);
kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
for (auto params : kTestParameters) {
kDecodeTestParameters.push_back(
@@ -968,15 +907,6 @@
std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
}
- // Set the resource directory based on command line args.
- // Test will fail to set up if the argument is not set.
- for (int i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
- sResourceDir = argv[i + 1];
- break;
- }
- }
-
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index e3a4f68..1445e59 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -38,9 +38,6 @@
static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
kEncodeTestParameters;
-// Resource directory
-static std::string sResourceDir = "";
-
class LinearBuffer : public C2Buffer {
public:
explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
@@ -797,6 +794,7 @@
} // anonymous namespace
int main(int argc, char** argv) {
+ parseArgs(argc, argv);
kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
for (auto params : kTestParameters) {
kEncodeTestParameters.push_back(
@@ -809,15 +807,6 @@
std::make_tuple(std::get<0>(params), std::get<1>(params), "true", "2"));
}
- // Set the resource directory based on command line args.
- // Test will fail to set up if the argument is not set.
- for (int i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
- sResourceDir = argv[i + 1];
- break;
- }
- }
-
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hidl/1.0/vts/functional/common/Android.bp b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
index f9ec5ae..4106be8 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "VtsHalMediaC2V1_0CommonUtil",
defaults: [
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index 0251ec2..de34705 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -22,6 +22,48 @@
#include <android/hardware/media/c2/1.0/IComponentStore.h>
+std::string sResourceDir = "";
+
+std::string sComponentNamePrefix = "";
+
+static constexpr struct option kArgOptions[] = {
+ {"res", required_argument, 0, 'P'},
+ {"prefix", required_argument, 0, 'p'},
+ {"help", required_argument, 0, 'h'},
+ {nullptr, 0, nullptr, 0},
+};
+
+void printUsage(char *me) {
+ std::cerr << "VTS tests to test codec2 components \n";
+ std::cerr << "Usage: " << me << " [options] \n";
+ std::cerr << "\t -P, --res: Mandatory path to a folder that contains test resources \n";
+ std::cerr << "\t -p, --prefix: Optional prefix to select component/s to be tested \n";
+ std::cerr << "\t All codecs are tested by default \n";
+ std::cerr << "\t Eg: c2.android - test codecs starting with c2.android \n";
+ std::cerr << "\t Eg: c2.android.aac.decoder - test a specific codec \n";
+ std::cerr << "\t -h, --help: Print usage \n";
+}
+
+void parseArgs(int argc, char** argv) {
+ int arg;
+ int option_index;
+ while ((arg = getopt_long(argc, argv, ":P:p:h", kArgOptions, &option_index)) != -1) {
+ switch (arg) {
+ case 'P':
+ sResourceDir = optarg;
+ break;
+ case 'p':
+ sComponentNamePrefix = optarg;
+ break;
+ case 'h':
+ printUsage(argv[0]);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
// Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set
void testInputBuffer(const std::shared_ptr<android::Codec2Client::Component>& component,
std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
@@ -157,11 +199,18 @@
(traits.domain != domain || traits.kind != kind)) {
continue;
}
-
+ if (traits.name.rfind(sComponentNamePrefix, 0) != 0) {
+ ALOGD("Skipping tests for %s. Prefix specified is %s", traits.name.c_str(),
+ sComponentNamePrefix.c_str());
+ continue;
+ }
parameters.push_back(std::make_tuple(instance, traits.name));
}
}
+ if (parameters.empty()) {
+ ALOGE("No test parameters added. Verify component prefix passed to the test");
+ }
return parameters;
}
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index 50e3ac5..a2f1561 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -42,6 +42,12 @@
static std::vector<std::tuple<std::string, std::string>> kTestParameters;
+// Resource directory
+extern std::string sResourceDir;
+
+// Component name prefix
+extern std::string sComponentNamePrefix;
+
struct FrameInfo {
int bytesCount;
uint32_t flags;
@@ -105,6 +111,8 @@
std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
};
+void parseArgs(int argc, char** argv);
+
// Return all test parameters, a list of tuple of <instance, component>.
const std::vector<std::tuple<std::string, std::string>>& getTestParameters();
diff --git a/media/codec2/hidl/1.0/vts/functional/component/Android.bp b/media/codec2/hidl/1.0/vts/functional/component/Android.bp
index 7ec64ee..cc019da 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/component/Android.bp
@@ -14,9 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "VtsHalMediaC2V1_0TargetComponentTest",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: ["VtsHalMediaC2V1_0TargetComponentTest.cpp"],
}
-
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 6122225..0648dd9 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -360,6 +360,7 @@
// TODO: Add test for Invalid work,
// TODO: Add test for Invalid states
int main(int argc, char** argv) {
+ parseArgs(argc, argv);
kTestParameters = getTestParameters();
for (auto params : kTestParameters) {
kInputTestParameters.push_back(
diff --git a/media/codec2/hidl/1.0/vts/functional/master/Android.bp b/media/codec2/hidl/1.0/vts/functional/master/Android.bp
index 53e323e..40f5201 100644
--- a/media/codec2/hidl/1.0/vts/functional/master/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/master/Android.bp
@@ -14,9 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "VtsHalMediaC2V1_0TargetMasterTest",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: ["VtsHalMediaC2V1_0TargetMasterTest.cpp"],
}
-
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index c7b0c12..f211ecf 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "VtsHalMediaC2V1_0TargetVideoDecTest",
stem: "vts_media_c2_v1_0_video_dec_test",
@@ -40,4 +49,3 @@
data: [":media_c2_v1_video_encode_res"],
test_config: "VtsHalMediaC2V1_0TargetVideoEncTest.xml",
}
-
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 12ed725..f29da0e 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -45,8 +45,51 @@
static std::vector<std::tuple<std::string, std::string, std::string>> kCsdFlushTestParameters;
-// Resource directory
-static std::string sResourceDir = "";
+struct CompToURL {
+ std::string mime;
+ std::string mURL;
+ std::string info;
+ std::string chksum;
+};
+std::vector<CompToURL> kCompToURL = {
+ {"avc",
+ "bbb_avc_176x144_300kbps_60fps.h264", "bbb_avc_176x144_300kbps_60fps.info",
+ "bbb_avc_176x144_300kbps_60fps_chksum.md5"},
+ {"avc",
+ "bbb_avc_640x360_768kbps_30fps.h264", "bbb_avc_640x360_768kbps_30fps.info",
+ "bbb_avc_640x360_768kbps_30fps_chksum.md5"},
+ {"hevc",
+ "bbb_hevc_176x144_176kbps_60fps.hevc", "bbb_hevc_176x144_176kbps_60fps.info",
+ "bbb_hevc_176x144_176kbps_60fps_chksum.md5"},
+ {"hevc",
+ "bbb_hevc_640x360_1600kbps_30fps.hevc", "bbb_hevc_640x360_1600kbps_30fps.info",
+ "bbb_hevc_640x360_1600kbps_30fps_chksum.md5"},
+ {"mpeg2",
+ "bbb_mpeg2_176x144_105kbps_25fps.m2v", "bbb_mpeg2_176x144_105kbps_25fps.info", ""},
+ {"mpeg2",
+ "bbb_mpeg2_352x288_1mbps_60fps.m2v","bbb_mpeg2_352x288_1mbps_60fps.info", ""},
+ {"3gpp",
+ "bbb_h263_352x288_300kbps_12fps.h263", "bbb_h263_352x288_300kbps_12fps.info", ""},
+ {"mp4v-es",
+ "bbb_mpeg4_352x288_512kbps_30fps.m4v", "bbb_mpeg4_352x288_512kbps_30fps.info", ""},
+ {"vp8",
+ "bbb_vp8_176x144_240kbps_60fps.vp8", "bbb_vp8_176x144_240kbps_60fps.info", ""},
+ {"vp8",
+ "bbb_vp8_640x360_2mbps_30fps.vp8", "bbb_vp8_640x360_2mbps_30fps.info",
+ "bbb_vp8_640x360_2mbps_30fps_chksm.md5"},
+ {"vp9",
+ "bbb_vp9_176x144_285kbps_60fps.vp9", "bbb_vp9_176x144_285kbps_60fps.info", ""},
+ {"vp9",
+ "bbb_vp9_640x360_1600kbps_30fps.vp9", "bbb_vp9_640x360_1600kbps_30fps.info",
+ "bbb_vp9_640x360_1600kbps_30fps_chksm.md5"},
+ {"vp9",
+ "bbb_vp9_704x480_280kbps_24fps_altref_2.vp9",
+ "bbb_vp9_704x480_280kbps_24fps_altref_2.info", ""},
+ {"av01",
+ "bbb_av1_640_360.av1", "bbb_av1_640_360.info", "bbb_av1_640_360_chksum.md5"},
+ {"av01",
+ "bbb_av1_176_144.av1", "bbb_av1_176_144.info", "bbb_av1_176_144_chksm.md5"},
+};
class LinearBuffer : public C2Buffer {
public:
@@ -85,26 +128,11 @@
mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
ASSERT_NE(mLinearPool, nullptr);
- mCompName = unknown_comp;
- struct StringToName {
- const char* Name;
- standardComp CompName;
- };
+ std::vector<std::unique_ptr<C2Param>> queried;
+ mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE}, C2_DONT_BLOCK, &queried);
+ ASSERT_GT(queried.size(), 0);
- const StringToName kStringToName[] = {
- {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
- {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, {"av1", av1},
- };
-
- const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
-
- // Find the component type
- for (size_t i = 0; i < kNumStringToName; ++i) {
- if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
- mCompName = kStringToName[i].CompName;
- break;
- }
- }
+ mMime = ((C2PortMediaTypeSetting::input*)queried[0].get())->m.value;
mEos = false;
mFramesReceived = 0;
mTimestampUs = 0u;
@@ -114,11 +142,11 @@
mMd5Offset = 0;
mMd5Enable = false;
mRefMd5 = nullptr;
- if (mCompName == unknown_comp) mDisableTest = true;
C2SecureModeTuning secureModeTuning{};
mComponent->query({&secureModeTuning}, {}, C2_MAY_BLOCK, nullptr);
- if (secureModeTuning.value == C2Config::SM_READ_PROTECTED) {
+ if (secureModeTuning.value == C2Config::SM_READ_PROTECTED ||
+ secureModeTuning.value == C2Config::SM_READ_PROTECTED_WITH_ENCRYPTED) {
mDisableTest = true;
}
@@ -136,6 +164,9 @@
// Get the test parameters from GetParam call.
virtual void getParams() {}
+ void GetURLChksmForComponent(char* mURL, char* info, char* chksum, size_t streamIndex);
+ void GetURLForComponent(char* mURL, char* info, size_t streamIndex = 0);
+
/* Calculate the CKSUM for the data in inbuf */
void calc_md5_cksum(uint8_t* pu1_inbuf, uint32_t u4_stride, uint32_t u4_width,
uint32_t u4_height, uint8_t* pu1_cksum_p) {
@@ -267,18 +298,7 @@
}
}
- enum standardComp {
- h263,
- avc,
- mpeg2,
- mpeg4,
- hevc,
- vp8,
- vp9,
- av1,
- unknown_comp,
- };
-
+ std::string mMime;
std::string mInstanceName;
std::string mComponentName;
@@ -291,7 +311,6 @@
char* mRefMd5;
std::list<uint64_t> mTimestampUslist;
std::list<uint64_t> mFlushedIndices;
- standardComp mCompName;
int32_t mWorkResult;
int32_t mReorderDepth;
@@ -324,7 +343,7 @@
};
void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2VideoDecHidlTest::standardComp compName, bool& disableTest) {
+ bool& disableTest) {
// Validate its a C2 Component
if (component->getName().find("c2") == std::string::npos) {
ALOGE("Not a c2 component");
@@ -351,83 +370,32 @@
return;
}
}
-
- // Validates component name
- if (compName == Codec2VideoDecHidlTest::unknown_comp) {
- ALOGE("Component InValid");
- disableTest = true;
- return;
- }
ALOGV("Component Valid");
}
// number of elementary streams per component
#define STREAM_COUNT 3
// LookUpTable of clips, metadata and chksum for component testing
-void GetURLChksmForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL, char* info,
- char* chksum, size_t streamIndex = 1) {
- struct CompToURL {
- Codec2VideoDecHidlTest::standardComp comp;
- const char mURL[STREAM_COUNT][512];
- const char info[STREAM_COUNT][512];
- const char chksum[STREAM_COUNT][512];
- };
- ASSERT_TRUE(streamIndex < STREAM_COUNT);
-
- static const CompToURL kCompToURL[] = {
- {Codec2VideoDecHidlTest::standardComp::avc,
- {"bbb_avc_176x144_300kbps_60fps.h264", "bbb_avc_640x360_768kbps_30fps.h264", ""},
- {"bbb_avc_176x144_300kbps_60fps.info", "bbb_avc_640x360_768kbps_30fps.info", ""},
- {"bbb_avc_176x144_300kbps_60fps_chksum.md5",
- "bbb_avc_640x360_768kbps_30fps_chksum.md5", ""}},
- {Codec2VideoDecHidlTest::standardComp::hevc,
- {"bbb_hevc_176x144_176kbps_60fps.hevc", "bbb_hevc_640x360_1600kbps_30fps.hevc", ""},
- {"bbb_hevc_176x144_176kbps_60fps.info", "bbb_hevc_640x360_1600kbps_30fps.info", ""},
- {"bbb_hevc_176x144_176kbps_60fps_chksum.md5",
- "bbb_hevc_640x360_1600kbps_30fps_chksum.md5", ""}},
- {Codec2VideoDecHidlTest::standardComp::mpeg2,
- {"bbb_mpeg2_176x144_105kbps_25fps.m2v", "bbb_mpeg2_352x288_1mbps_60fps.m2v", ""},
- {"bbb_mpeg2_176x144_105kbps_25fps.info", "bbb_mpeg2_352x288_1mbps_60fps.info", ""},
- {"", "", ""}},
- {Codec2VideoDecHidlTest::standardComp::h263,
- {"", "bbb_h263_352x288_300kbps_12fps.h263", ""},
- {"", "bbb_h263_352x288_300kbps_12fps.info", ""},
- {"", "", ""}},
- {Codec2VideoDecHidlTest::standardComp::mpeg4,
- {"", "bbb_mpeg4_352x288_512kbps_30fps.m4v", ""},
- {"", "bbb_mpeg4_352x288_512kbps_30fps.info", ""},
- {"", "", ""}},
- {Codec2VideoDecHidlTest::standardComp::vp8,
- {"bbb_vp8_176x144_240kbps_60fps.vp8", "bbb_vp8_640x360_2mbps_30fps.vp8", ""},
- {"bbb_vp8_176x144_240kbps_60fps.info", "bbb_vp8_640x360_2mbps_30fps.info", ""},
- {"", "bbb_vp8_640x360_2mbps_30fps_chksm.md5", ""}},
- {Codec2VideoDecHidlTest::standardComp::vp9,
- {"bbb_vp9_176x144_285kbps_60fps.vp9", "bbb_vp9_640x360_1600kbps_30fps.vp9",
- "bbb_vp9_704x480_280kbps_24fps_altref_2.vp9"},
- {"bbb_vp9_176x144_285kbps_60fps.info", "bbb_vp9_640x360_1600kbps_30fps.info",
- "bbb_vp9_704x480_280kbps_24fps_altref_2.info"},
- {"", "bbb_vp9_640x360_1600kbps_30fps_chksm.md5", ""}},
- {Codec2VideoDecHidlTest::standardComp::av1,
- {"bbb_av1_640_360.av1", "bbb_av1_176_144.av1", ""},
- {"bbb_av1_640_360.info", "bbb_av1_176_144.info", ""},
- {"bbb_av1_640_360_chksum.md5", "bbb_av1_176_144_chksm.md5", ""}},
- };
-
- for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
- if (kCompToURL[i].comp == comp) {
- strcat(mURL, kCompToURL[i].mURL[streamIndex]);
- strcat(info, kCompToURL[i].info[streamIndex]);
- strcat(chksum, kCompToURL[i].chksum[streamIndex]);
- return;
+void Codec2VideoDecHidlTestBase::GetURLChksmForComponent(char* mURL, char* info, char* chksum,
+ size_t streamIndex) {
+ int streamCount = 0;
+ for (size_t i = 0; i < kCompToURL.size(); ++i) {
+ if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
+ if (streamCount == streamIndex) {
+ strcat(mURL, kCompToURL[i].mURL.c_str());
+ strcat(info, kCompToURL[i].info.c_str());
+ strcat(chksum, kCompToURL[i].chksum.c_str());
+ return;
+ }
+ streamCount++;
}
}
}
-void GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL, char* info,
- size_t streamIndex = 1) {
+void Codec2VideoDecHidlTestBase::GetURLForComponent(char* mURL, char* info, size_t streamIndex) {
char chksum[512];
strcpy(chksum, sResourceDir.c_str());
- GetURLChksmForComponent(comp, mURL, info, chksum, streamIndex);
+ GetURLChksmForComponent(mURL, info, chksum, streamIndex);
}
void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
@@ -517,7 +485,7 @@
TEST_P(Codec2VideoDecHidlTest, validateCompName) {
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the given component is a valid video component");
- validateComponent(mComponent, mCompName, mDisableTest);
+ validateComponent(mComponent, mDisableTest);
ASSERT_EQ(mDisableTest, false);
}
@@ -599,7 +567,7 @@
strcpy(info, sResourceDir.c_str());
strcpy(chksum, sResourceDir.c_str());
- GetURLChksmForComponent(mCompName, mURL, info, chksum, streamIndex);
+ GetURLChksmForComponent(mURL, info, chksum, streamIndex);
if (!(strcmp(mURL, sResourceDir.c_str())) || !(strcmp(info, sResourceDir.c_str()))) {
ALOGV("Skipping Test, Stream not available");
return;
@@ -688,9 +656,11 @@
TEST_P(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
description("Adaptive Decode Test");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- if (!(mCompName == avc || mCompName == hevc || mCompName == vp8 || mCompName == vp9 ||
- mCompName == mpeg2))
+ if (!(strcasestr(mMime.c_str(), "avc") || strcasestr(mMime.c_str(), "hevc") ||
+ strcasestr(mMime.c_str(), "vp8") || strcasestr(mMime.c_str(), "vp9") ||
+ strcasestr(mMime.c_str(), "mpeg2"))) {
return;
+ }
typedef std::unique_lock<std::mutex> ULock;
ASSERT_EQ(mComponent->start(), C2_OK);
@@ -705,7 +675,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info, i % STREAM_COUNT);
+ GetURLForComponent(mURL, info, i % STREAM_COUNT);
if (!(strcmp(mURL, sResourceDir.c_str())) || !(strcmp(info, sResourceDir.c_str()))) {
ALOGV("Stream not available, skipping this index");
continue;
@@ -734,7 +704,7 @@
}
if (timestampMax < timestamp) timestampMax = timestamp;
}
- timestampOffset = timestampMax;
+ timestampOffset = timestampMax + 33333;
eleInfo.close();
// Reset Total frames before second decode loop
@@ -801,7 +771,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
@@ -888,7 +858,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
mFlushedIndices.clear();
@@ -964,7 +934,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
@@ -1038,7 +1008,7 @@
strcpy(mURL, sResourceDir.c_str());
strcpy(info, sResourceDir.c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mURL, info);
int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
ASSERT_GE(numCsds, 0) << "Error in parsing input info file";
@@ -1137,6 +1107,7 @@
// TODO : Video specific configuration Test
int main(int argc, char** argv) {
+ parseArgs(argc, argv);
kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
for (auto params : kTestParameters) {
kDecodeTestParameters.push_back(
@@ -1158,15 +1129,6 @@
std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
}
- // Set the resource directory based on command line args.
- // Test will fail to set up if the argument is not set.
- for (int i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
- sResourceDir = argv[i + 1];
- break;
- }
- }
-
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 5bcea5b..7e35de7 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -46,9 +46,6 @@
static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
kEncodeResolutionTestParameters;
-// Resource directory
-static std::string sResourceDir = "";
-
namespace {
class Codec2VideoEncHidlTestBase : public ::testing::Test {
@@ -110,7 +107,8 @@
C2SecureModeTuning secureModeTuning{};
mComponent->query({&secureModeTuning}, {}, C2_MAY_BLOCK, nullptr);
- if (secureModeTuning.value == C2Config::SM_READ_PROTECTED) {
+ if (secureModeTuning.value == C2Config::SM_READ_PROTECTED ||
+ secureModeTuning.value == C2Config::SM_READ_PROTECTED_WITH_ENCRYPTED) {
mDisableTest = true;
}
@@ -841,6 +839,7 @@
} // anonymous namespace
int main(int argc, char** argv) {
+ parseArgs(argc, argv);
kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
for (auto params : kTestParameters) {
constexpr char const* kBoolString[] = { "false", "true" };
@@ -866,15 +865,6 @@
std::make_tuple(std::get<0>(params), std::get<1>(params), "1400", "442"));
}
- // Set the resource directory based on command line args.
- // Test will fail to set up if the argument is not set.
- for (int i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
- sResourceDir = argv[i + 1];
- break;
- }
- }
-
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hidl/1.1/utils/Android.bp b/media/codec2/hidl/1.1/utils/Android.bp
index ab8635b..839a910 100644
--- a/media/codec2/hidl/1.1/utils/Android.bp
+++ b/media/codec2/hidl/1.1/utils/Android.bp
@@ -1,5 +1,14 @@
// DO NOT DEPEND ON THIS DIRECTLY
// use libcodec2-hidl-client-defaults instead
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libcodec2_hidl_client@1.1",
@@ -91,6 +100,7 @@
"libbase",
"libcodec2",
"libcodec2_hidl@1.0",
+ "libcodec2_hidl_plugin_stub",
"libcodec2_vndk",
"libcutils",
"libhidlbase",
@@ -105,9 +115,17 @@
vendor: {
exclude_shared_libs: [
"libstagefright_bufferqueue_helper_novndk",
+ "libcodec2_hidl_plugin_stub",
],
shared_libs: [
"libstagefright_bufferqueue_helper",
+ "libcodec2_hidl_plugin",
+ ],
+ },
+ apex: {
+ exclude_shared_libs: [
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_hidl_plugin",
],
},
},
diff --git a/media/codec2/hidl/1.1/utils/Component.cpp b/media/codec2/hidl/1.1/utils/Component.cpp
index ed281e6..1d7d3d8 100644
--- a/media/codec2/hidl/1.1/utils/Component.cpp
+++ b/media/codec2/hidl/1.1/utils/Component.cpp
@@ -22,6 +22,10 @@
#include <codec2/hidl/1.1/ComponentStore.h>
#include <codec2/hidl/1.1/InputBufferManager.h>
+#ifndef __ANDROID_APEX__
+#include <FilterWrapper.h>
+#endif
+
#include <hidl/HidlBinderSupport.h>
#include <utils/Timers.h>
@@ -390,10 +394,17 @@
uint32_t allocatorId,
createBlockPool_cb _hidl_cb) {
std::shared_ptr<C2BlockPool> blockPool;
+#ifdef __ANDROID_APEX__
c2_status_t status = CreateCodec2BlockPool(
static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
mComponent,
&blockPool);
+#else
+ c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
+ static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+ mComponent,
+ &blockPool);
+#endif
if (status != C2_OK) {
blockPool = nullptr;
}
diff --git a/media/codec2/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
index 225cd09..163686d 100644
--- a/media/codec2/hidl/1.1/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
@@ -35,6 +35,14 @@
#include <ostream>
#include <sstream>
+#ifndef __ANDROID_APEX__
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <dlfcn.h>
+#include <C2Config.h>
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+#endif
+
namespace android {
namespace hardware {
namespace media {
@@ -176,6 +184,16 @@
return mParameterCache;
}
+#ifndef __ANDROID_APEX__
+// static
+std::shared_ptr<FilterWrapper> ComponentStore::GetFilterWrapper() {
+ constexpr const char kPluginPath[] = "libc2filterplugin.so";
+ static std::shared_ptr<FilterWrapper> wrapper = FilterWrapper::Create(
+ std::make_unique<DefaultFilterPlugin>(kPluginPath));
+ return wrapper;
+}
+#endif
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
const hidl_string& name,
@@ -189,6 +207,9 @@
mStore->createComponent(name, &c2component));
if (status == Status::OK) {
+#ifndef __ANDROID_APEX__
+ c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
onInterfaceLoaded(c2component->intf());
component = new Component(c2component, listener, this, pool);
if (!component) {
@@ -216,6 +237,9 @@
c2_status_t res = mStore->createInterface(name, &c2interface);
sp<IComponentInterface> interface;
if (res == C2_OK) {
+#ifndef __ANDROID_APEX__
+ c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
+#endif
onInterfaceLoaded(c2interface);
interface = new ComponentInterface(c2interface, mParameterCache);
}
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
index 1f04391..f6daee7 100644
--- a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
@@ -38,6 +38,8 @@
#include <vector>
namespace android {
+class FilterWrapper;
+
namespace hardware {
namespace media {
namespace c2 {
@@ -75,6 +77,8 @@
*/
std::shared_ptr<ParameterCache> getParameterCache() const;
+ static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
virtual Return<void> createComponent(
const hidl_string& name,
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index 3c37990..5a34c30 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libcodec2_client",
@@ -39,4 +48,3 @@
],
}
-
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 7e4352d..4650672 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -843,6 +843,11 @@
return;
}
});
+ if (!transStatus.isOk()) {
+ LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
+ << transStatus.description();
+ descriptor.reset();
+ }
return descriptor;
}
diff --git a/media/codec2/hidl/plugin/Android.bp b/media/codec2/hidl/plugin/Android.bp
new file mode 100644
index 0000000..873bb02
--- /dev/null
+++ b/media/codec2/hidl/plugin/Android.bp
@@ -0,0 +1,75 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library_headers {
+ name: "libcodec2_hidl_plugin_headers",
+ vendor_available: true,
+ export_include_dirs: [
+ "include",
+ ],
+}
+
+cc_library {
+ name: "libcodec2_hidl_plugin_stub",
+
+ srcs: [
+ "DefaultFilterPlugin.cpp",
+ "FilterWrapperStub.cpp",
+ ],
+
+ header_libs: [
+ "libcodec2_internal", // private
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcodec2",
+ "libcodec2_vndk",
+ "liblog",
+ "libutils",
+ ],
+
+ export_include_dirs: [
+ "include",
+ "internal",
+ ],
+
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
+ min_sdk_version: "29",
+}
+
+cc_library {
+ name: "libcodec2_hidl_plugin",
+ vendor: true,
+
+ srcs: [
+ "DefaultFilterPlugin.cpp",
+ "FilterWrapper.cpp",
+ ],
+
+ header_libs: [
+ "libcodec2_internal", // private
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcodec2",
+ "libcodec2_vndk",
+ "liblog",
+ "libutils",
+ ],
+
+ export_include_dirs: [
+ "include",
+ "internal",
+ ],
+}
diff --git a/media/codec2/hidl/plugin/DefaultFilterPlugin.cpp b/media/codec2/hidl/plugin/DefaultFilterPlugin.cpp
new file mode 100644
index 0000000..cd1bcb0
--- /dev/null
+++ b/media/codec2/hidl/plugin/DefaultFilterPlugin.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-DefaultFilterPlugin"
+#include <android-base/logging.h>
+
+#include <set>
+
+#include <dlfcn.h>
+
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <C2ParamInternal.h>
+
+#include <codec2/hidl/plugin/FilterPlugin.h>
+
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+
+namespace android {
+
+DefaultFilterPlugin::DefaultFilterPlugin(const char *pluginPath)
+ : mInit(NO_INIT),
+ mHandle(nullptr),
+ mDestroyPlugin(nullptr),
+ mPlugin(nullptr) {
+ mHandle = dlopen(pluginPath, RTLD_NOW | RTLD_NODELETE);
+ if (!mHandle) {
+ LOG(DEBUG) << "FilterPlugin: no plugin detected";
+ return;
+ }
+ GetFilterPluginVersionFunc getVersion =
+ (GetFilterPluginVersionFunc)dlsym(mHandle, "GetFilterPluginVersion");
+ if (!getVersion) {
+ LOG(WARNING) << "FilterPlugin: GetFilterPluginVersion undefined";
+ return;
+ }
+ int32_t version = getVersion();
+ if (version != FilterPlugin_V1::VERSION) {
+ LOG(WARNING) << "FilterPlugin: unrecognized version (" << version << ")";
+ return;
+ }
+ CreateFilterPluginFunc createPlugin =
+ (CreateFilterPluginFunc)dlsym(mHandle, "CreateFilterPlugin");
+ if (!createPlugin) {
+ LOG(WARNING) << "FilterPlugin: CreateFilterPlugin undefined";
+ return;
+ }
+ mDestroyPlugin =
+ (DestroyFilterPluginFunc)dlsym(mHandle, "DestroyFilterPlugin");
+ if (!mDestroyPlugin) {
+ LOG(WARNING) << "FilterPlugin: DestroyFilterPlugin undefined";
+ return;
+ }
+ mPlugin = (FilterPlugin_V1 *)createPlugin();
+ if (!mPlugin) {
+ LOG(WARNING) << "FilterPlugin: CreateFilterPlugin returned nullptr";
+ return;
+ }
+ mStore = mPlugin->getComponentStore();
+ if (!mStore) {
+ LOG(WARNING) << "FilterPlugin: FilterPlugin_V1::getComponentStore returned nullptr";
+ return;
+ }
+ mInit = OK;
+}
+
+DefaultFilterPlugin::~DefaultFilterPlugin() {
+ if (mHandle) {
+ if (mDestroyPlugin && mPlugin) {
+ mDestroyPlugin(mPlugin);
+ mPlugin = nullptr;
+ }
+ dlclose(mHandle);
+ mHandle = nullptr;
+ mDestroyPlugin = nullptr;
+ }
+}
+
+bool DefaultFilterPlugin::describe(C2String name, FilterWrapper::Descriptor *desc) {
+ if (mInit != OK) {
+ return false;
+ }
+ return mPlugin->describe(name, desc);
+}
+
+bool DefaultFilterPlugin::isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) {
+ if (mInit != OK) {
+ return false;
+ }
+ return mPlugin->isFilteringEnabled(intf);
+}
+
+} // namespace android
diff --git a/media/codec2/hidl/plugin/FilterWrapper.cpp b/media/codec2/hidl/plugin/FilterWrapper.cpp
new file mode 100644
index 0000000..0b38bc1
--- /dev/null
+++ b/media/codec2/hidl/plugin/FilterWrapper.cpp
@@ -0,0 +1,921 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-FilterWrapper"
+#include <android-base/logging.h>
+
+#include <set>
+#include <sstream>
+
+#include <dlfcn.h>
+
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <C2ParamInternal.h>
+
+#include <codec2/hidl/plugin/FilterPlugin.h>
+
+#include <FilterWrapper.h>
+
+namespace android {
+
+namespace {
+
+// Indices that the last filter in the chain should consume.
+static constexpr uint32_t kTypesForLastFilter[] = {
+ // In case we have an output surface, we want to use the block pool
+ // backed by the output surface for the output buffer going to the client.
+ C2PortBlockPoolsTuning::output::PARAM_TYPE,
+};
+
+class WrappedDecoderInterface : public C2ComponentInterface {
+public:
+ WrappedDecoderInterface(
+ std::shared_ptr<C2ComponentInterface> intf,
+ std::vector<FilterWrapper::Component> &&filters)
+ : mIntf(intf) {
+ takeFilters(std::move(filters));
+ }
+
+ ~WrappedDecoderInterface() override = default;
+
+ void takeFilters(std::vector<FilterWrapper::Component> &&filters) {
+ std::unique_lock lock(mMutex);
+ std::vector<std::unique_ptr<C2Param>> lastFilterParams;
+ if (!mFilters.empty()) {
+ std::vector<C2Param::Index> indices;
+ std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
+ c2_status_t err = mFilters.back().intf->querySupportedParams_nb(¶mDescs);
+ if (err != C2_OK) {
+ LOG(WARNING) << "WrappedDecoderInterface: " << mFilters.back().traits.name
+ << " returned error for querySupportedParams_nb; err=" << err;
+ paramDescs.clear();
+ }
+ for (const std::shared_ptr<C2ParamDescriptor> ¶mDesc : paramDescs) {
+ C2Param::Index index = paramDesc->index();
+ if (std::count(
+ std::begin(kTypesForLastFilter),
+ std::end(kTypesForLastFilter),
+ index.type()) != 0) {
+ if (index.forStream()) {
+ // querySupportedParams does not return per-stream params.
+ // We only support stream-0 for now.
+ index = index.withStream(0u);
+ }
+ indices.push_back(index);
+ }
+ }
+ if (!indices.empty()) {
+ mFilters.back().intf->query_vb({}, indices, C2_MAY_BLOCK, &lastFilterParams);
+ }
+ }
+
+ // TODO: documentation
+ mFilters = std::move(filters);
+ mTypeToIndexForQuery.clear();
+ mTypeToIndexForConfig.clear();
+ for (size_t i = 0; i < mFilters.size(); ++i) {
+ if (i == 0) {
+ transferParams_l(mIntf, mFilters[0].intf, C2_MAY_BLOCK);
+ } else {
+ transferParams_l(mFilters[i - 1].intf, mFilters[i].intf, C2_MAY_BLOCK);
+ }
+ for (C2Param::Type type : mFilters[i].desc.controlParams) {
+ mTypeToIndexForQuery[type.type()] = i;
+ mTypeToIndexForConfig[type.type() & ~C2Param::CoreIndex::IS_REQUEST_FLAG] = i;
+ }
+ for (C2Param::Type type : mFilters[i].desc.affectedParams) {
+ mTypeToIndexForQuery[type.type()] = i;
+ }
+ }
+ if (!mFilters.empty()) {
+ for (uint32_t type : kTypesForLastFilter) {
+ mTypeToIndexForQuery[type] = mFilters.size() - 1;
+ mTypeToIndexForConfig[type & ~C2Param::CoreIndex::IS_REQUEST_FLAG] =
+ mFilters.size() - 1;
+ }
+ if (!lastFilterParams.empty()) {
+ std::vector<C2Param *> paramPtrs(lastFilterParams.size());
+ std::transform(
+ lastFilterParams.begin(),
+ lastFilterParams.end(),
+ paramPtrs.begin(),
+ [](const std::unique_ptr<C2Param> ¶m) {
+ return param.get();
+ });
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ mFilters.back().intf->config_vb(paramPtrs, C2_MAY_BLOCK, &failures);
+ }
+ }
+ }
+
+ C2String getName() const override { return mIntf->getName(); }
+
+ c2_node_id_t getId() const override { return mIntf->getId(); }
+
+ c2_status_t query_vb(
+ const std::vector<C2Param *> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
+ std::unique_lock lock(mMutex);
+ std::list<C2Param *> stackParamsList(stackParams.size());
+ std::copy_n(stackParams.begin(), stackParams.size(), stackParamsList.begin());
+ heapParams->clear();
+ c2_status_t result = C2_OK;
+ // TODO: loop optimization
+ for (size_t i = 0; i < mFilters.size(); ++i) {
+ // Filter stack params according to mTypeToIndexForQuery
+ std::vector<C2Param *> stackParamsForFilter;
+ for (auto it = stackParamsList.begin(); it != stackParamsList.end(); ) {
+ C2Param *param = *it;
+ uint32_t type = param->type().type();
+ auto it2 = mTypeToIndexForQuery.find(type);
+ if (it2 == mTypeToIndexForQuery.end() || it2->second != i) {
+ ++it;
+ continue;
+ }
+ stackParamsForFilter.push_back(param);
+ it = stackParamsList.erase(it);
+ }
+ // Filter heap params according to mTypeToIndexForQuery
+ std::vector<C2Param::Index> heapParamIndicesForFilter;
+ for (size_t j = 0; j < heapParamIndices.size(); ++j) {
+ uint32_t type = heapParamIndices[j].type();
+ auto it = mTypeToIndexForQuery.find(type);
+ if (it == mTypeToIndexForQuery.end() || it->second != i) {
+ continue;
+ }
+ heapParamIndicesForFilter.push_back(heapParamIndices[j]);
+ }
+ std::vector<std::unique_ptr<C2Param>> heapParamsForFilter;
+ const std::shared_ptr<C2ComponentInterface> &filter = mFilters[i].intf;
+ c2_status_t err = filter->query_vb(
+ stackParamsForFilter, heapParamIndicesForFilter, mayBlock,
+ &heapParamsForFilter);
+ if (err != C2_OK && err != C2_BAD_INDEX) {
+ LOG(WARNING) << "WrappedDecoderInterface: " << filter->getName()
+ << " returned error for query_vb; err=" << err;
+ result = err;
+ continue;
+ }
+ heapParams->insert(
+ heapParams->end(),
+ std::make_move_iterator(heapParamsForFilter.begin()),
+ std::make_move_iterator(heapParamsForFilter.end()));
+ }
+
+ std::vector<C2Param *> stackParamsForIntf;
+ std::copy_n(stackParamsList.begin(), stackParamsList.size(), stackParamsForIntf.begin());
+
+ // Gather heap params that did not get queried from the filter interfaces above.
+ // These need to be queried from the decoder interface.
+ std::vector<C2Param::Index> heapParamIndicesForIntf;
+ for (size_t j = 0; j < heapParamIndices.size(); ++j) {
+ uint32_t type = heapParamIndices[j].type();
+ if (mTypeToIndexForQuery.find(type) != mTypeToIndexForQuery.end()) {
+ continue;
+ }
+ heapParamIndicesForIntf.push_back(heapParamIndices[j]);
+ }
+
+ std::vector<std::unique_ptr<C2Param>> heapParamsForIntf;
+ c2_status_t err = mIntf->query_vb(
+ stackParamsForIntf, heapParamIndicesForIntf, mayBlock, &heapParamsForIntf);
+ if (err != C2_OK) {
+ LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
+ << "WrappedDecoderInterface: " << mIntf->getName()
+ << " returned error for query_vb; err=" << err;
+ result = err;
+ }
+
+ // TODO: params needs to preserve the order
+ heapParams->insert(
+ heapParams->end(),
+ std::make_move_iterator(heapParamsForIntf.begin()),
+ std::make_move_iterator(heapParamsForIntf.end()));
+
+ return result;
+ }
+
+ c2_status_t config_vb(
+ const std::vector<C2Param *> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
+ std::unique_lock lock(mMutex);
+ c2_status_t result = C2_OK;
+ std::vector<C2Param *> paramsForIntf;
+ for (C2Param* param : params) {
+ auto it = mTypeToIndexForConfig.find(param->type().type());
+ if (it != mTypeToIndexForConfig.end()) {
+ continue;
+ }
+ paramsForIntf.push_back(param);
+ }
+ c2_status_t err = mIntf->config_vb(paramsForIntf, mayBlock, failures);
+ if (err != C2_OK) {
+ LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
+ << "WrappedDecoderInterface: " << mIntf->getName()
+ << " returned error for config_vb; err=" << err;
+ result = err;
+ }
+ for (size_t i = 0; i < mFilters.size(); ++i) {
+ if (i == 0) {
+ transferParams_l(mIntf, mFilters[0].intf, mayBlock);
+ } else {
+ transferParams_l(mFilters[i - 1].intf, mFilters[i].intf, mayBlock);
+ }
+ const std::shared_ptr<C2ComponentInterface> &filter = mFilters[i].intf;
+ std::vector<std::unique_ptr<C2SettingResult>> filterFailures;
+ std::vector<C2Param *> paramsForFilter;
+ for (C2Param* param : params) {
+ auto it = mTypeToIndexForConfig.find(param->type().type());
+ if (it != mTypeToIndexForConfig.end() && it->second != i) {
+ continue;
+ }
+ paramsForFilter.push_back(param);
+ }
+ c2_status_t err = filter->config_vb(paramsForFilter, mayBlock, &filterFailures);
+ if (err != C2_OK) {
+ LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
+ << "WrappedDecoderInterface: " << filter->getName()
+ << " returned error for config_vb; err=" << err;
+ result = err;
+ }
+ }
+
+ return result;
+ }
+
+ c2_status_t createTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
+ c2_status_t releaseTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
+
+ c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
+ std::unique_lock lock(mMutex);
+ c2_status_t result = mIntf->querySupportedParams_nb(params);
+ if (result != C2_OK) {
+ LOG(WARNING) << "WrappedDecoderInterface: " << mIntf->getName()
+ << " returned error for querySupportedParams_nb; err=" << result;
+ return result;
+ }
+ // TODO: optimization idea --- pre-compute at takeFilter().
+ for (const FilterWrapper::Component &filter : mFilters) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> filterParams;
+ c2_status_t err = filter.intf->querySupportedParams_nb(&filterParams);
+ if (err != C2_OK) {
+ LOG(WARNING) << "WrappedDecoderInterface: " << filter.intf->getName()
+ << " returned error for querySupportedParams_nb; err=" << result;
+ result = err;
+ continue;
+ }
+ for (const std::shared_ptr<C2ParamDescriptor> ¶mDesc : filterParams) {
+ if (std::count(
+ filter.desc.controlParams.begin(),
+ filter.desc.controlParams.end(),
+ paramDesc->index().type()) == 0) {
+ continue;
+ }
+ params->push_back(paramDesc);
+ }
+ }
+ return result;
+ }
+
+ c2_status_t querySupportedValues_vb(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const override {
+ std::unique_lock lock(mMutex);
+ c2_status_t result = mIntf->querySupportedValues_vb(fields, mayBlock);
+ if (result != C2_OK && result != C2_BAD_INDEX) {
+ LOG(WARNING) << "WrappedDecoderInterface: " << mIntf->getName()
+ << " returned error for querySupportedParams_nb; err=" << result;
+ return result;
+ }
+ for (const FilterWrapper::Component &filter : mFilters) {
+ std::vector<C2FieldSupportedValuesQuery> filterFields;
+ std::vector<size_t> indices;
+ for (size_t i = 0; i < fields.size(); ++i) {
+ const C2FieldSupportedValuesQuery &field = fields[i];
+ uint32_t type = C2Param::Index(_C2ParamInspector::GetIndex(field.field())).type();
+ if (std::count(
+ filter.desc.controlParams.begin(),
+ filter.desc.controlParams.end(),
+ type) == 0) {
+ continue;
+ }
+ filterFields.push_back(field);
+ indices.push_back(i);
+ }
+ c2_status_t err = filter.intf->querySupportedValues_vb(filterFields, mayBlock);
+ if (err != C2_OK && err != C2_BAD_INDEX) {
+ LOG(WARNING) << "WrappedDecoderInterface: " << filter.intf->getName()
+ << " returned error for querySupportedParams_nb; err=" << result;
+ result = err;
+ continue;
+ }
+ for (size_t i = 0; i < filterFields.size(); ++i) {
+ fields[indices[i]] = filterFields[i];
+ }
+ }
+ return result;
+ }
+
+private:
+ mutable std::mutex mMutex;
+ std::shared_ptr<C2ComponentInterface> mIntf;
+ std::vector<FilterWrapper::Component> mFilters;
+ std::map<uint32_t, size_t> mTypeToIndexForQuery;
+ std::map<uint32_t, size_t> mTypeToIndexForConfig;
+
+ c2_status_t transferParams_l(
+ const std::shared_ptr<C2ComponentInterface> &curr,
+ const std::shared_ptr<C2ComponentInterface> &next,
+ c2_blocking_t mayBlock) {
+ // NOTE: this implementation is preliminary --- it could change once
+ // we define what parameters needs to be propagated in component chaining.
+ std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
+ c2_status_t err = next->querySupportedParams_nb(¶mDescs);
+ if (err != C2_OK) {
+ LOG(DEBUG) << "WrappedDecoderInterface: " << next->getName()
+ << " returned error for querySupportedParams_nb; err=" << err;
+ return err;
+ }
+ // Find supported input params from the next interface and flip direction
+ // so they become output params.
+ std::vector<C2Param::Index> indices;
+ for (const std::shared_ptr<C2ParamDescriptor> ¶mDesc : paramDescs) {
+ C2Param::Index index = paramDesc->index();
+ if (!index.forInput() || paramDesc->isReadOnly()) {
+ continue;
+ }
+ if (index.forStream()) {
+ uint32_t stream = index.stream();
+ index = index.withPort(true /* output */).withStream(stream);
+ } else {
+ index = index.withPort(true /* output */);
+ }
+ indices.push_back(index);
+ }
+ // Query those output params from the current interface
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ err = curr->query_vb({}, indices, mayBlock, &heapParams);
+ if (err != C2_OK && err != C2_BAD_INDEX) {
+ LOG(DEBUG) << "WrappedDecoderInterface: " << curr->getName()
+ << " returned error for query_vb; err=" << err;
+ return err;
+ }
+ // Flip the direction of the queried params, so they become input parameters.
+ // Configure the next interface with the params.
+ std::vector<C2Param *> configParams;
+ for (size_t i = 0; i < heapParams.size(); ++i) {
+ if (heapParams[i]->forStream()) {
+ heapParams[i] = C2Param::CopyAsStream(
+ *heapParams[i], false /* output */, heapParams[i]->stream());
+ } else {
+ heapParams[i] = C2Param::CopyAsPort(*heapParams[i], false /* output */);
+ }
+ configParams.push_back(heapParams[i].get());
+ }
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ err = next->config_vb(configParams, mayBlock, &failures);
+ if (err != C2_OK && err != C2_BAD_INDEX) {
+ LOG(DEBUG) << "WrappedDecoderInterface: " << next->getName()
+ << " returned error for config_vb; err=" << err;
+ return err;
+ }
+ return C2_OK;
+ }
+};
+
+class WrappedDecoder : public C2Component, public std::enable_shared_from_this<WrappedDecoder> {
+public:
+ WrappedDecoder(
+ std::shared_ptr<C2Component> comp,
+ std::vector<FilterWrapper::Component> &&filters,
+ std::weak_ptr<FilterWrapper> filterWrapper)
+ : mComp(comp), mFilters(std::move(filters)), mFilterWrapper(filterWrapper) {
+ std::vector<FilterWrapper::Component> filtersDup(mFilters);
+ mIntf = std::make_shared<WrappedDecoderInterface>(
+ comp->intf(), std::move(filtersDup));
+ }
+
+ ~WrappedDecoder() override = default;
+
+ std::shared_ptr<C2ComponentInterface> intf() override { return mIntf; }
+
+ c2_status_t setListener_vb(
+ const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) override {
+ if (listener) {
+ setListenerInternal(mFilters, listener, mayBlock);
+ } else {
+ mComp->setListener_vb(nullptr, mayBlock);
+ for (FilterWrapper::Component &filter : mFilters) {
+ filter.comp->setListener_vb(nullptr, mayBlock);
+ }
+ }
+ mListener = listener;
+ return C2_OK;
+ }
+
+ c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override {
+ return mComp->queue_nb(items);
+ }
+
+ c2_status_t announce_nb(const std::vector<C2WorkOutline> &) override {
+ return C2_OMITTED;
+ }
+
+ c2_status_t flush_sm(
+ flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override {
+ c2_status_t result = mComp->flush_sm(mode, flushedWork);
+ std::list<std::unique_ptr<C2Work>> filterFlushedWork;
+ for (FilterWrapper::Component filter : mRunningFilters) {
+ c2_status_t err = filter.comp->flush_sm(mode, &filterFlushedWork);
+ if (err != C2_OK) {
+ result = err;
+ }
+ flushedWork->splice(flushedWork->end(), filterFlushedWork);
+ }
+ return result;
+ }
+
+ c2_status_t drain_nb(drain_mode_t mode) override {
+ // TODO: simplify using comp->drain_nb(mode)
+ switch (mode) {
+ case DRAIN_COMPONENT_WITH_EOS: {
+ std::unique_ptr<C2Work> eosWork{new C2Work};
+ eosWork->input.flags = C2FrameData::FLAG_END_OF_STREAM;
+ eosWork->worklets.push_back(std::make_unique<C2Worklet>());
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(eosWork));
+ mComp->queue_nb(&items);
+ return C2_OK;
+ }
+ case DRAIN_COMPONENT_NO_EOS:
+ case DRAIN_CHAIN:
+ default:
+ return C2_BAD_VALUE;
+ }
+ }
+
+ c2_status_t start() override {
+ std::vector<FilterWrapper::Component> filters;
+ if (std::shared_ptr<FilterWrapper> filterWrapper = mFilterWrapper.lock()) {
+ // Let's check if we have filters that we can skip
+ for (FilterWrapper::Component &filter : mFilters) {
+ if (!filterWrapper->isFilteringEnabled(filter.intf)) {
+ LOG(VERBOSE) << "filtering disabled for " << filter.traits.name;
+ continue;
+ }
+ LOG(VERBOSE) << "filtering enabled for " << filter.traits.name;
+ filters.push_back(filter);
+ }
+ if (filters.size() < mFilters.size()) {
+ LOG(VERBOSE) << (mFilters.size() - filters.size()) << " filter(s) skipped";
+ setListenerInternal(filters, mListener, C2_MAY_BLOCK);
+ std::vector filtersCopy(filters);
+ mIntf->takeFilters(std::move(filtersCopy));
+ }
+ }
+
+ c2_status_t err = mComp->start();
+ if (err != C2_OK) {
+ return err;
+ }
+ for (FilterWrapper::Component &filter : filters) {
+ c2_status_t err = filter.comp->start();
+ if (err != C2_OK) {
+ // Previous components are already started successfully;
+ // we ended up in an incoherent state.
+ return C2_CORRUPTED;
+ }
+ }
+ mRunningFilters = std::move(filters);
+ return C2_OK;
+ }
+
+ c2_status_t stop() override {
+ c2_status_t err = mComp->stop();
+ if (err != C2_OK) {
+ return err;
+ }
+ for (FilterWrapper::Component filter : mRunningFilters) {
+ c2_status_t err = filter.comp->stop();
+ if (err != C2_OK) {
+ // Previous components are already stopped successfully;
+ // we ended up in an incoherent state.
+ return C2_CORRUPTED;
+ }
+ }
+ mRunningFilters.clear();
+ return C2_OK;
+ }
+
+ c2_status_t reset() override {
+ c2_status_t result = mComp->reset();
+ if (result != C2_OK) {
+ result = C2_CORRUPTED;
+ }
+ for (FilterWrapper::Component filter : mFilters) {
+ c2_status_t err = filter.comp->reset();
+ if (err != C2_OK) {
+ // Previous components are already reset successfully;
+ // we ended up in an incoherent state.
+ result = C2_CORRUPTED;
+ // continue for the rest of the chain
+ }
+ }
+ mRunningFilters.clear();
+ return result;
+ }
+
+ c2_status_t release() override {
+ c2_status_t result = mComp->release();
+ if (result != C2_OK) {
+ result = C2_CORRUPTED;
+ }
+ for (FilterWrapper::Component filter : mFilters) {
+ c2_status_t err = filter.comp->release();
+ if (err != C2_OK) {
+ // Previous components are already released successfully;
+ // we ended up in an incoherent state.
+ result = C2_CORRUPTED;
+ // continue for the rest of the chain
+ }
+ }
+ mRunningFilters.clear();
+ return result;
+ }
+
+private:
+ class PassingListener : public Listener {
+ public:
+ PassingListener(
+ std::shared_ptr<C2Component> wrappedComponent,
+ const std::shared_ptr<Listener> &wrappedComponentListener,
+ std::shared_ptr<C2Component> nextComponent)
+ : mWrappedComponent(wrappedComponent),
+ mWrappedComponentListener(wrappedComponentListener),
+ mNextComponent(nextComponent) {
+ }
+
+ void onWorkDone_nb(
+ std::weak_ptr<C2Component>,
+ std::list<std::unique_ptr<C2Work>> workItems) override {
+ std::shared_ptr<C2Component> nextComponent = mNextComponent.lock();
+ std::list<std::unique_ptr<C2Work>> failedWorkItems;
+ if (!nextComponent) {
+ for (std::unique_ptr<C2Work> &work : workItems) {
+ // Next component unexpectedly released while the work is
+ // in-flight. Report C2_CORRUPTED to the client.
+ work->result = C2_CORRUPTED;
+ failedWorkItems.push_back(std::move(work));
+ }
+ workItems.clear();
+ } else {
+ for (auto it = workItems.begin(); it != workItems.end(); ) {
+ const std::unique_ptr<C2Work> &work = *it;
+ if (work->result != C2_OK
+ || work->worklets.size() != 1) {
+ failedWorkItems.push_back(std::move(*it));
+ it = workItems.erase(it);
+ continue;
+ }
+ C2FrameData &output = work->worklets.front()->output;
+ c2_cntr64_t customOrdinal = work->input.ordinal.customOrdinal;
+ work->input = std::move(output);
+ work->input.ordinal.customOrdinal = customOrdinal;
+ output.flags = C2FrameData::flags_t(0);
+ output.buffers.clear();
+ output.configUpdate.clear();
+ output.infoBuffers.clear();
+ ++it;
+ }
+ }
+ if (!failedWorkItems.empty()) {
+ for (const std::unique_ptr<C2Work> &work : failedWorkItems) {
+ LOG(VERBOSE) << "work #" << work->input.ordinal.frameIndex.peek()
+ << " failed: err=" << work->result
+ << " worklets.size()=" << work->worklets.size();
+ }
+ if (std::shared_ptr<Listener> wrappedComponentListener =
+ mWrappedComponentListener.lock()) {
+ wrappedComponentListener->onWorkDone_nb(
+ mWrappedComponent, std::move(failedWorkItems));
+ }
+ }
+ if (!workItems.empty()) {
+ nextComponent->queue_nb(&workItems);
+ }
+ }
+
+ void onTripped_nb(
+ std::weak_ptr<C2Component>,
+ std::vector<std::shared_ptr<C2SettingResult>>) override {
+ // Trip not supported
+ }
+
+ void onError_nb(std::weak_ptr<C2Component>, uint32_t errorCode) {
+ if (std::shared_ptr<Listener> wrappedComponentListener =
+ mWrappedComponentListener.lock()) {
+ wrappedComponentListener->onError_nb(mWrappedComponent, errorCode);
+ }
+ }
+
+ private:
+ std::weak_ptr<C2Component> mWrappedComponent;
+ std::weak_ptr<Listener> mWrappedComponentListener;
+ std::weak_ptr<C2Component> mNextComponent;
+ };
+
+ class LastListener : public Listener {
+ public:
+ LastListener(
+ std::shared_ptr<C2Component> wrappedComponent,
+ const std::shared_ptr<Listener> &wrappedComponentListener)
+ : mWrappedComponent(wrappedComponent),
+ mWrappedComponentListener(wrappedComponentListener) {
+ }
+
+ void onWorkDone_nb(
+ std::weak_ptr<C2Component>,
+ std::list<std::unique_ptr<C2Work>> workItems) override {
+ if (mWrappedComponent.expired()) {
+ return;
+ }
+ if (std::shared_ptr<Listener> wrappedComponentListener =
+ mWrappedComponentListener.lock()) {
+ wrappedComponentListener->onWorkDone_nb(
+ mWrappedComponent, std::move(workItems));
+ }
+ }
+
+ void onTripped_nb(
+ std::weak_ptr<C2Component>,
+ std::vector<std::shared_ptr<C2SettingResult>>) override {
+ // Trip not supported
+ }
+
+ void onError_nb(std::weak_ptr<C2Component>, uint32_t errorCode) {
+ if (mWrappedComponent.expired()) {
+ return;
+ }
+ if (std::shared_ptr<Listener> wrappedComponentListener =
+ mWrappedComponentListener.lock()) {
+ wrappedComponentListener->onError_nb(mWrappedComponent, errorCode);
+ }
+ }
+
+ private:
+ std::weak_ptr<C2Component> mWrappedComponent;
+ std::weak_ptr<Listener> mWrappedComponentListener;
+ };
+
+ std::shared_ptr<C2Component> mComp;
+ std::shared_ptr<WrappedDecoderInterface> mIntf;
+ std::vector<FilterWrapper::Component> mFilters;
+ std::vector<FilterWrapper::Component> mRunningFilters;
+ std::weak_ptr<FilterWrapper> mFilterWrapper;
+ std::shared_ptr<Listener> mListener;
+#if defined(LOG_NDEBUG) && !LOG_NDEBUG
+ base::ScopedLogSeverity mScopedLogSeverity{base::VERBOSE};
+#endif
+
+ c2_status_t setListenerInternal(
+ const std::vector<FilterWrapper::Component> &filters,
+ const std::shared_ptr<Listener> &listener,
+ c2_blocking_t mayBlock) {
+ if (filters.empty()) {
+ return mComp->setListener_vb(listener, mayBlock);
+ }
+ std::shared_ptr passingListener = std::make_shared<PassingListener>(
+ shared_from_this(),
+ listener,
+ filters.front().comp);
+ mComp->setListener_vb(passingListener, mayBlock);
+ for (size_t i = 0; i < filters.size() - 1; ++i) {
+ filters[i].comp->setListener_vb(
+ std::make_shared<PassingListener>(
+ shared_from_this(),
+ listener,
+ filters[i + 1].comp),
+ mayBlock);
+ }
+ filters.back().comp->setListener_vb(
+ std::make_shared<LastListener>(shared_from_this(), listener), mayBlock);
+ return C2_OK;
+ }
+};
+
+} // anonymous namespace
+
+FilterWrapper::FilterWrapper(std::unique_ptr<Plugin> &&plugin)
+ : mInit(NO_INIT),
+ mPlugin(std::move(plugin)) {
+ if (mPlugin->status() != OK) {
+ LOG(ERROR) << "plugin not OK: " << mPlugin->status();
+ mPlugin.reset();
+ return;
+ }
+ mStore = mPlugin->getStore();
+ if (!mStore) {
+ LOG(ERROR) << "no store";
+ mPlugin.reset();
+ return;
+ }
+ std::vector<std::shared_ptr<const C2Component::Traits>> traits =
+ mStore->listComponents();
+ std::sort(
+ traits.begin(),
+ traits.end(),
+ [](std::shared_ptr<const C2Component::Traits> &a,
+ std::shared_ptr<const C2Component::Traits> &b) {
+ return a->rank < b->rank;
+ });
+ for (size_t i = 0; i < traits.size(); ++i) {
+ const std::shared_ptr<const C2Component::Traits> &trait = traits[i];
+ if (trait->domain == C2Component::DOMAIN_OTHER
+ || trait->domain == C2Component::DOMAIN_AUDIO
+ || trait->kind != C2Component::KIND_OTHER) {
+ LOG(DEBUG) << trait->name << " is ignored because of domain/kind: "
+ << trait->domain << "/" << trait->kind;
+ continue;
+ }
+ Descriptor desc;
+ if (!mPlugin->describe(trait->name, &desc)) {
+ LOG(DEBUG) << trait->name << " is ignored because describe() failed";
+ continue;
+ }
+ mComponents.push_back({nullptr, nullptr, *trait, desc});
+ }
+ if (mComponents.empty()) {
+ LOG(DEBUG) << "FilterWrapper: no filter component found";
+ mPlugin.reset();
+ return;
+ }
+ mInit = OK;
+}
+
+FilterWrapper::~FilterWrapper() {
+}
+
+std::vector<FilterWrapper::Component> FilterWrapper::createFilters() {
+ std::vector<FilterWrapper::Component> filters;
+ for (const FilterWrapper::Component &filter : mComponents) {
+ std::shared_ptr<C2Component> comp;
+ std::shared_ptr<C2ComponentInterface> intf;
+ if (C2_OK != mStore->createComponent(filter.traits.name, &comp)) {
+ return {};
+ }
+ if (C2_OK != mStore->createInterface(filter.traits.name, &intf)) {
+ return {};
+ }
+ filters.push_back({comp, intf, filter.traits, filter.desc});
+ }
+ return filters;
+}
+
+C2Component::Traits FilterWrapper::getTraits(
+ const std::shared_ptr<C2ComponentInterface> &intf) {
+ {
+ std::unique_lock lock(mCacheMutex);
+ if (mCachedTraits.count(intf->getName())) {
+ return mCachedTraits.at(intf->getName());
+ }
+ }
+ C2ComponentDomainSetting domain;
+ C2ComponentKindSetting kind;
+ c2_status_t err = intf->query_vb({&domain, &kind}, {}, C2_MAY_BLOCK, nullptr);
+ C2Component::Traits traits = {
+ "query failed", // name
+ C2Component::DOMAIN_OTHER,
+ C2Component::KIND_OTHER,
+ 0, // rank, unused
+ "", // media type, unused
+ "", // owner, unused
+ {}, // aliases, unused
+ };
+ if (err == C2_OK) {
+ traits = {
+ intf->getName(),
+ domain.value,
+ kind.value,
+ 0, // rank, unused
+ "", // media type, unused
+ "", // owner, unused
+ {}, // aliases, unused
+ };
+ std::unique_lock lock(mCacheMutex);
+ mCachedTraits[traits.name] = traits;
+ }
+ return traits;
+}
+
+std::shared_ptr<C2ComponentInterface> FilterWrapper::maybeWrapInterface(
+ const std::shared_ptr<C2ComponentInterface> intf) {
+ if (mInit != OK) {
+ LOG(VERBOSE) << "maybeWrapInterface: Wrapper not initialized: "
+ << intf->getName() << " is not wrapped.";
+ return intf;
+ }
+ C2Component::Traits traits = getTraits(intf);
+ if (traits.name != intf->getName()) {
+ LOG(INFO) << "maybeWrapInterface: Querying traits from " << intf->getName()
+ << " failed; not wrapping the interface";
+ return intf;
+ }
+ if ((traits.domain != C2Component::DOMAIN_VIDEO && traits.domain != C2Component::DOMAIN_IMAGE)
+ || traits.kind != C2Component::KIND_DECODER) {
+ LOG(VERBOSE) << "maybeWrapInterface: " << traits.name
+ << " is not video/image decoder; not wrapping the interface";
+ return intf;
+ }
+ return std::make_shared<WrappedDecoderInterface>(intf, createFilters());
+}
+
+std::shared_ptr<C2Component> FilterWrapper::maybeWrapComponent(
+ const std::shared_ptr<C2Component> comp) {
+ if (mInit != OK) {
+ LOG(VERBOSE) << "maybeWrapComponent: Wrapper not initialized: "
+ << comp->intf()->getName() << " is not wrapped.";
+ return comp;
+ }
+ C2Component::Traits traits = getTraits(comp->intf());
+ if (traits.name != comp->intf()->getName()) {
+ LOG(INFO) << "maybeWrapComponent: Querying traits from " << comp->intf()->getName()
+ << " failed; not wrapping the component";
+ return comp;
+ }
+ if ((traits.domain != C2Component::DOMAIN_VIDEO && traits.domain != C2Component::DOMAIN_IMAGE)
+ || traits.kind != C2Component::KIND_DECODER) {
+ LOG(VERBOSE) << "maybeWrapComponent: " << traits.name
+ << " is not video/image decoder; not wrapping the component";
+ return comp;
+ }
+ std::vector<Component> filters = createFilters();
+ std::shared_ptr wrapped = std::make_shared<WrappedDecoder>(
+ comp, std::move(filters), weak_from_this());
+ {
+ std::unique_lock lock(mWrappedComponentsMutex);
+ std::vector<std::weak_ptr<const C2Component>> &components =
+ mWrappedComponents.emplace_back();
+ components.push_back(wrapped);
+ components.push_back(comp);
+ for (const Component &filter : filters) {
+ components.push_back(filter.comp);
+ }
+ }
+ return wrapped;
+}
+
+bool FilterWrapper::isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) {
+ if (mInit != OK) {
+ LOG(WARNING) << "isFilteringEnabled: Wrapper not initialized: ";
+ return false;
+ }
+ return mPlugin->isFilteringEnabled(intf);
+}
+
+c2_status_t FilterWrapper::createBlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
+ std::unique_lock lock(mWrappedComponentsMutex);
+ for (auto it = mWrappedComponents.begin(); it != mWrappedComponents.end(); ) {
+ std::shared_ptr<const C2Component> comp = it->front().lock();
+ if (!comp) {
+ it = mWrappedComponents.erase(it);
+ continue;
+ }
+ if (component == comp) {
+ std::vector<std::shared_ptr<const C2Component>> components(it->size());
+ std::transform(
+ it->begin(), it->end(), components.begin(),
+ [](const std::weak_ptr<const C2Component> &el) {
+ return el.lock();
+ });
+ if (C2_OK == CreateCodec2BlockPool(allocatorId, components, pool)) {
+ return C2_OK;
+ }
+ }
+ ++it;
+ }
+ return CreateCodec2BlockPool(allocatorId, component, pool);
+}
+
+} // namespace android
diff --git a/media/codec2/hidl/plugin/FilterWrapperStub.cpp b/media/codec2/hidl/plugin/FilterWrapperStub.cpp
new file mode 100644
index 0000000..1b94a1a
--- /dev/null
+++ b/media/codec2/hidl/plugin/FilterWrapperStub.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-FilterWrapperStub"
+
+#include <FilterWrapper.h>
+
+namespace android {
+
+FilterWrapper::FilterWrapper(std::unique_ptr<Plugin> &&) {
+}
+
+FilterWrapper::~FilterWrapper() {
+}
+
+std::shared_ptr<C2ComponentInterface> FilterWrapper::maybeWrapInterface(
+ const std::shared_ptr<C2ComponentInterface> intf) {
+ return intf;
+}
+
+std::shared_ptr<C2Component> FilterWrapper::maybeWrapComponent(
+ const std::shared_ptr<C2Component> comp) {
+ return comp;
+}
+
+bool FilterWrapper::isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &) {
+ return false;
+}
+
+c2_status_t FilterWrapper::createBlockPool(
+ C2PlatformAllocatorStore::id_t,
+ std::shared_ptr<const C2Component>,
+ std::shared_ptr<C2BlockPool> *) {
+ return C2_OMITTED;
+}
+
+} // namespace android
diff --git a/media/codec2/hidl/plugin/include/codec2/hidl/plugin/FilterPlugin.h b/media/codec2/hidl/plugin/include/codec2/hidl/plugin/FilterPlugin.h
new file mode 100644
index 0000000..6f1f907
--- /dev/null
+++ b/media/codec2/hidl/plugin/include/codec2/hidl/plugin/FilterPlugin.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_PLUGIN_FILTER_PLUGIN_H
+
+#define CODEC2_HIDL_PLUGIN_FILTER_PLUGIN_H
+
+#include <memory>
+
+#include <C2Component.h>
+
+namespace android {
+
+class FilterPlugin_V1 {
+public:
+ static constexpr int32_t VERSION = 1;
+
+ virtual ~FilterPlugin_V1() = default;
+
+ /**
+ * Returns a C2ComponentStore object with which clients can create
+ * filter components / interfaces.
+ */
+ virtual std::shared_ptr<C2ComponentStore> getComponentStore() = 0;
+ struct Descriptor {
+ // Parameters that client sets for filter control.
+ std::initializer_list<C2Param::Type> controlParams;
+ // Parameters that the component changes after filtering.
+ std::initializer_list<C2Param::Type> affectedParams;
+ };
+
+ /**
+ * Describe a filter component.
+ *
+ * @param name[in] filter's name
+ * @param desc[out] pointer to filter descriptor to be populated
+ * @return true if |name| is in the store and |desc| is populated;
+ * false if |name| is not recognized
+ */
+ virtual bool describe(C2String name, Descriptor *desc) = 0;
+
+ /**
+ * Returns true if a component will apply filtering after all given the
+ * current configuration; false if it will be no-op.
+ */
+ virtual bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) = 0;
+};
+
+} // namespace android
+
+extern "C" {
+
+typedef int32_t (*GetFilterPluginVersionFunc)();
+int32_t GetFilterPluginVersion();
+
+typedef void* (*CreateFilterPluginFunc)();
+void *CreateFilterPlugin();
+
+typedef void (*DestroyFilterPluginFunc)(void *);
+void DestroyFilterPlugin(void *plugin);
+
+} // extern "C"
+
+#endif // CODEC2_HIDL_PLUGIN_FILTER_PLUGIN_H
diff --git a/media/codec2/hidl/plugin/internal/DefaultFilterPlugin.h b/media/codec2/hidl/plugin/internal/DefaultFilterPlugin.h
new file mode 100644
index 0000000..f856324
--- /dev/null
+++ b/media/codec2/hidl/plugin/internal/DefaultFilterPlugin.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_PLUGIN_DEFAULT_FILTER_PLUGIN_H
+
+#define CODEC2_HIDL_PLUGIN_DEFAULT_FILTER_PLUGIN_H
+
+#include <codec2/hidl/plugin/FilterPlugin.h>
+
+#include <FilterWrapper.h>
+
+namespace android {
+
+class DefaultFilterPlugin : public FilterWrapper::Plugin {
+public:
+ explicit DefaultFilterPlugin(const char *pluginPath);
+
+ ~DefaultFilterPlugin();
+
+ status_t status() const override { return mInit; }
+
+ std::shared_ptr<C2ComponentStore> getStore() override { return mStore; }
+ bool describe(C2String name, FilterWrapper::Descriptor *desc) override;
+ bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) override;
+
+private:
+ status_t mInit;
+ void *mHandle;
+ DestroyFilterPluginFunc mDestroyPlugin;
+ FilterPlugin_V1 *mPlugin;
+ std::shared_ptr<C2ComponentStore> mStore;
+};
+
+} // namespace android
+
+#endif // CODEC2_HIDL_PLUGIN_DEFAULT_FILTER_PLUGIN_H
diff --git a/media/codec2/hidl/plugin/internal/FilterWrapper.h b/media/codec2/hidl/plugin/internal/FilterWrapper.h
new file mode 100644
index 0000000..5ced435
--- /dev/null
+++ b/media/codec2/hidl/plugin/internal/FilterWrapper.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_PLUGIN_FILTER_WRAPPER_H
+
+#define CODEC2_HIDL_PLUGIN_FILTER_WRAPPER_H
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <C2Component.h>
+#include <C2PlatformSupport.h>
+
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+// TODO: documentation
+class FilterWrapper : public std::enable_shared_from_this<FilterWrapper> {
+public:
+ using Descriptor = FilterPlugin_V1::Descriptor;
+
+ class Plugin {
+ public:
+ Plugin() = default;
+ virtual ~Plugin() = default;
+ virtual status_t status() const = 0;
+ virtual std::shared_ptr<C2ComponentStore> getStore() = 0;
+ virtual bool describe(C2String name, Descriptor *desc) = 0;
+ virtual bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) = 0;
+ C2_DO_NOT_COPY(Plugin);
+ };
+
+ struct Component {
+ const std::shared_ptr<C2Component> comp;
+ const std::shared_ptr<C2ComponentInterface> intf;
+ const C2Component::Traits traits;
+ const Descriptor desc;
+ };
+
+private:
+ explicit FilterWrapper(std::unique_ptr<Plugin> &&plugin);
+public:
+ static std::shared_ptr<FilterWrapper> Create(std::unique_ptr<Plugin> &&plugin) {
+ return std::shared_ptr<FilterWrapper>(new FilterWrapper(std::move(plugin)));
+ }
+ ~FilterWrapper();
+
+ /**
+ * Returns wrapped interface, or |intf| if wrapping is not possible / needed.
+ */
+ std::shared_ptr<C2ComponentInterface> maybeWrapInterface(
+ const std::shared_ptr<C2ComponentInterface> intf);
+
+ /**
+ * Returns wrapped component, or |comp| if wrapping is not possible / needed.
+ */
+ std::shared_ptr<C2Component> maybeWrapComponent(
+ const std::shared_ptr<C2Component> comp);
+
+ /**
+ * Returns ture iff the filtering will apply to the buffer in current configuration.
+ */
+ bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf);
+
+ c2_status_t createBlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool);
+
+private:
+ status_t mInit;
+ std::unique_ptr<Plugin> mPlugin;
+ std::shared_ptr<C2ComponentStore> mStore;
+ std::list<FilterWrapper::Component> mComponents;
+
+ std::mutex mCacheMutex;
+ std::map<std::string, C2Component::Traits> mCachedTraits;
+
+ std::mutex mWrappedComponentsMutex;
+ std::list<std::vector<std::weak_ptr<const C2Component>>> mWrappedComponents;
+
+ std::vector<FilterWrapper::Component> createFilters();
+ C2Component::Traits getTraits(const std::shared_ptr<C2ComponentInterface> &intf);
+
+ C2_DO_NOT_COPY(FilterWrapper);
+};
+
+} // namespace android
+
+#endif // CODEC2_HIDL_PLUGIN_FILTER_WRAPPER_H
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 3780a5a..5a23217 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -29,6 +29,15 @@
// The seccomp_policy file name and its content can be modified, but note that
// vendor.cpp also needs to be updated because it needs the absolute path to the
// seccomp policy file on the device.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_binary {
name: "android.hardware.media.c2@1.1-default-service",
vendor: true,
@@ -87,4 +96,3 @@
// This may be removed.
required: ["crash_dump.policy"],
}
-
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 94034b5..2bc748f 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libsfplugin_ccodec",
@@ -11,6 +20,7 @@
"CCodecConfig.cpp",
"Codec2Buffer.cpp",
"Codec2InfoBuilder.cpp",
+ "FrameReassembler.cpp",
"PipelineWatcher.cpp",
"ReflectedParamUpdater.cpp",
],
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index dd1f485..2460490 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -33,12 +33,14 @@
#include <OMX_IndexExt.h>
#include <android/fdsan.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/omx/OMXUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
#include <utils/Thread.h>
+#include "utils/Codec2Mapper.h"
#include "C2OMXNode.h"
namespace android {
@@ -71,6 +73,23 @@
jobs->cond.broadcast();
}
+ void setDataspace(android_dataspace dataspace) {
+ Mutexed<Jobs>::Locked jobs(mJobs);
+ ColorUtils::convertDataSpaceToV0(dataspace);
+ jobs->configUpdate.emplace_back(new C2StreamDataSpaceInfo::input(0u, dataspace));
+ int32_t standard;
+ int32_t transfer;
+ int32_t range;
+ ColorUtils::getColorConfigFromDataSpace(dataspace, &range, &standard, &transfer);
+ std::unique_ptr<C2StreamColorAspectsInfo::input> colorAspects =
+ std::make_unique<C2StreamColorAspectsInfo::input>(0u);
+ if (C2Mapper::map(standard, &colorAspects->primaries, &colorAspects->matrix)
+ && C2Mapper::map(transfer, &colorAspects->transfer)
+ && C2Mapper::map(range, &colorAspects->range)) {
+ jobs->configUpdate.push_back(std::move(colorAspects));
+ }
+ }
+
protected:
bool threadLoop() override {
constexpr nsecs_t kIntervalNs = nsecs_t(10) * 1000 * 1000; // 10ms
@@ -102,6 +121,9 @@
uniqueFds.push_back(std::move(queue.workList.front().fd1));
queue.workList.pop_front();
}
+ for (const std::unique_ptr<C2Param> ¶m : jobs->configUpdate) {
+ items.front()->input.configUpdate.emplace_back(C2Param::Copy(*param));
+ }
jobs.unlock();
for (int fenceFd : fenceFds) {
@@ -119,6 +141,7 @@
queued = true;
}
if (queued) {
+ jobs->configUpdate.clear();
return true;
}
if (i == 0) {
@@ -161,6 +184,7 @@
std::map<std::weak_ptr<Codec2Client::Component>,
Queue,
std::owner_less<std::weak_ptr<Codec2Client::Component>>> queues;
+ std::vector<std::unique_ptr<C2Param>> configUpdate;
Condition cond;
};
Mutexed<Jobs> mJobs;
@@ -172,6 +196,9 @@
mQueueThread(new QueueThread) {
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
mQueueThread->run("C2OMXNode", PRIORITY_AUDIO);
+
+ Mutexed<android_dataspace>::Locked ds(mDataspace);
+ *ds = HAL_DATASPACE_UNKNOWN;
}
status_t C2OMXNode::freeNode() {
@@ -209,15 +236,23 @@
pDef->nBufferCountActual = 16;
- std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
- C2PortActualDelayTuning::input inputDelay(0);
- C2ActualPipelineDelayTuning pipelineDelay(0);
- c2_status_t c2err = comp->query(
- {&inputDelay, &pipelineDelay}, {}, C2_DONT_BLOCK, nullptr);
- if (c2err == C2_OK || c2err == C2_BAD_INDEX) {
- pDef->nBufferCountActual = 4;
- pDef->nBufferCountActual += (inputDelay ? inputDelay.value : 0u);
- pDef->nBufferCountActual += (pipelineDelay ? pipelineDelay.value : 0u);
+ // WORKAROUND: having more slots improve performance while consuming
+ // more memory. This is a temporary workaround to reduce memory for
+ // larger-than-4K scenario.
+ if (mWidth * mHeight > 4096 * 2340) {
+ std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
+ C2PortActualDelayTuning::input inputDelay(0);
+ C2ActualPipelineDelayTuning pipelineDelay(0);
+ c2_status_t c2err = C2_NOT_FOUND;
+ if (comp) {
+ c2err = comp->query(
+ {&inputDelay, &pipelineDelay}, {}, C2_DONT_BLOCK, nullptr);
+ }
+ if (c2err == C2_OK || c2err == C2_BAD_INDEX) {
+ pDef->nBufferCountActual = 4;
+ pDef->nBufferCountActual += (inputDelay ? inputDelay.value : 0u);
+ pDef->nBufferCountActual += (pipelineDelay ? pipelineDelay.value : 0u);
+ }
}
pDef->eDomain = OMX_PortDomainVideo;
@@ -451,8 +486,11 @@
android_dataspace dataSpace = (android_dataspace)msg.u.event_data.data1;
uint32_t pixelFormat = msg.u.event_data.data3;
- // TODO: set dataspace on component to see if it impacts color aspects
ALOGD("dataspace changed to %#x pixel format: %#x", dataSpace, pixelFormat);
+ mQueueThread->setDataspace(dataSpace);
+
+ Mutexed<android_dataspace>::Locked ds(mDataspace);
+ *ds = dataSpace;
return OK;
}
@@ -485,4 +523,8 @@
(void)mBufferSource->onInputBufferEmptied(bufferId, -1);
}
+android_dataspace C2OMXNode::getDataspace() {
+ return *mDataspace.lock();
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/C2OMXNode.h b/media/codec2/sfplugin/C2OMXNode.h
index 1717c96..9c04969 100644
--- a/media/codec2/sfplugin/C2OMXNode.h
+++ b/media/codec2/sfplugin/C2OMXNode.h
@@ -93,6 +93,11 @@
*/
void onInputBufferDone(c2_cntr64_t index);
+ /**
+ * Returns dataspace information from GraphicBufferSource.
+ */
+ android_dataspace getDataspace();
+
private:
std::weak_ptr<Codec2Client::Component> mComp;
sp<IOMXBufferSource> mBufferSource;
@@ -101,6 +106,7 @@
uint32_t mWidth;
uint32_t mHeight;
uint64_t mUsage;
+ Mutexed<android_dataspace> mDataspace;
// WORKAROUND: timestamp adjustment
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 1405b97..b203d24 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -44,6 +44,7 @@
#include <media/stagefright/BufferProducerWrapper.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/PersistentSurface.h>
+#include <utils/NativeHandle.h>
#include "C2OMXNode.h"
#include "CCodecBufferChannel.h"
@@ -210,8 +211,6 @@
(OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
&usage, sizeof(usage));
- // NOTE: we do not use/pass through color aspects from GraphicBufferSource as we
- // communicate that directly to the component.
mSource->configure(
mOmxNode, static_cast<hardware::graphics::common::V1_0::Dataspace>(mDataSpace));
return OK;
@@ -246,8 +245,19 @@
if (source == nullptr) {
return NO_INIT;
}
- constexpr size_t kNumSlots = 16;
- for (size_t i = 0; i < kNumSlots; ++i) {
+
+ size_t numSlots = 16;
+ constexpr OMX_U32 kPortIndexInput = 0;
+
+ OMX_PARAM_PORTDEFINITIONTYPE param;
+ param.nPortIndex = kPortIndexInput;
+ status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
+ ¶m, sizeof(param));
+ if (err == OK) {
+ numSlots = param.nBufferCountActual;
+ }
+
+ for (size_t i = 0; i < numSlots; ++i) {
source->onInputBufferAdded(i);
}
@@ -399,6 +409,10 @@
mNode->onInputBufferDone(index);
}
+ android_dataspace getDataspace() override {
+ return mNode->getDataspace();
+ }
+
private:
sp<HGraphicBufferSource> mSource;
sp<C2OMXNode> mNode;
@@ -471,6 +485,34 @@
}
};
+void RevertOutputFormatIfNeeded(
+ const sp<AMessage> &oldFormat, sp<AMessage> ¤tFormat) {
+ // We used to not report changes to these keys to the client.
+ const static std::set<std::string> sIgnoredKeys({
+ KEY_BIT_RATE,
+ KEY_FRAME_RATE,
+ KEY_MAX_BIT_RATE,
+ KEY_MAX_WIDTH,
+ KEY_MAX_HEIGHT,
+ "csd-0",
+ "csd-1",
+ "csd-2",
+ });
+ if (currentFormat == oldFormat) {
+ return;
+ }
+ sp<AMessage> diff = currentFormat->changesFrom(oldFormat);
+ AMessage::Type type;
+ for (size_t i = diff->countEntries(); i > 0; --i) {
+ if (sIgnoredKeys.count(diff->getEntryNameAt(i - 1, &type)) > 0) {
+ diff->removeEntryAt(i - 1);
+ }
+ }
+ if (diff->countEntries() == 0) {
+ currentFormat = oldFormat;
+ }
+}
+
} // namespace
// CCodec::ClientListener
@@ -502,9 +544,26 @@
virtual void onError(
const std::weak_ptr<Codec2Client::Component>& component,
uint32_t errorCode) override {
- // TODO
- (void)component;
- (void)errorCode;
+ {
+ // Component is only used for reporting as we use a separate listener for each instance
+ std::shared_ptr<Codec2Client::Component> comp = component.lock();
+ if (!comp) {
+ ALOGD("Component died with error: 0x%x", errorCode);
+ } else {
+ ALOGD("Component \"%s\" returned error: 0x%x", comp->getName().c_str(), errorCode);
+ }
+ }
+
+ // Report to MediaCodec
+ // Note: for now we do not propagate the error code to MediaCodec
+ // except for C2_NO_MEMORY, as we would need to translate to a MediaCodec error.
+ sp<CCodec> codec(mCodec.promote());
+ if (!codec || !codec->mCallback) {
+ return;
+ }
+ codec->mCallback->onError(
+ errorCode == C2_NO_MEMORY ? NO_MEMORY : UNKNOWN_ERROR,
+ ACTION_CODE_FATAL);
}
virtual void onDeath(
@@ -739,10 +798,30 @@
mChannel->setMetaMode(CCodecBufferChannel::MODE_ANW);
}
+ status_t err = OK;
sp<RefBase> obj;
sp<Surface> surface;
if (msg->findObject("native-window", &obj)) {
surface = static_cast<Surface *>(obj.get());
+ // setup tunneled playback
+ if (surface != nullptr) {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ if ((config->mDomain & Config::IS_DECODER)
+ && (config->mDomain & Config::IS_VIDEO)) {
+ int32_t tunneled;
+ if (msg->findInt32("feature-tunneled-playback", &tunneled) && tunneled != 0) {
+ ALOGI("Configuring TUNNELED video playback.");
+
+ err = configureTunneledVideoPlayback(comp, &config->mSidebandHandle, msg);
+ if (err != OK) {
+ ALOGE("configureTunneledVideoPlayback failed!");
+ return err;
+ }
+ config->mTunneled = true;
+ }
+ }
+ }
setSurface(surface);
}
@@ -773,12 +852,14 @@
return BAD_VALUE;
}
}
+ int32_t width = 0;
+ int32_t height = 0;
if (config->mDomain & (Config::IS_IMAGE | Config::IS_VIDEO)) {
- if (!msg->findInt32(KEY_WIDTH, &i32)) {
+ if (!msg->findInt32(KEY_WIDTH, &width)) {
ALOGD("width is missing, which is required for image/video components.");
return BAD_VALUE;
}
- if (!msg->findInt32(KEY_HEIGHT, &i32)) {
+ if (!msg->findInt32(KEY_HEIGHT, &height)) {
ALOGD("height is missing, which is required for image/video components.");
return BAD_VALUE;
}
@@ -867,23 +948,116 @@
/*
* Handle desired color format.
*/
+ int32_t defaultColorFormat = COLOR_FormatYUV420Flexible;
if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
- int32_t format = -1;
+ int32_t format = 0;
+ // Query vendor format for Flexible YUV
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
+ if (mClient->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo = C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].get());
+ } else {
+ pixelFormatInfo = nullptr;
+ }
+ std::optional<uint32_t> flexPixelFormat{};
+ std::optional<uint32_t> flexPlanarPixelFormat{};
+ std::optional<uint32_t> flexSemiPlanarPixelFormat{};
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ const C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ if (desc.bitDepth != 8
+ || desc.subsampling != C2Color::YUV_420
+ // TODO(b/180076105): some device report wrong layout
+ // || desc.layout == C2Color::INTERLEAVED_PACKED
+ // || desc.layout == C2Color::INTERLEAVED_ALIGNED
+ || desc.layout == C2Color::UNKNOWN_LAYOUT) {
+ continue;
+ }
+ if (!flexPixelFormat) {
+ flexPixelFormat = desc.pixelFormat;
+ }
+ if (desc.layout == C2Color::PLANAR_PACKED && !flexPlanarPixelFormat) {
+ flexPlanarPixelFormat = desc.pixelFormat;
+ }
+ if (desc.layout == C2Color::SEMIPLANAR_PACKED && !flexSemiPlanarPixelFormat) {
+ flexSemiPlanarPixelFormat = desc.pixelFormat;
+ }
+ }
+ }
if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
- /*
- * Also handle default color format (encoders require color format, so this is only
- * needed for decoders.
- */
+ // Also handle default color format (encoders require color format, so this is only
+ // needed for decoders.
if (!(config->mDomain & Config::IS_ENCODER)) {
- format = (surface == nullptr) ? COLOR_FormatYUV420Planar : COLOR_FormatSurface;
+ if (surface == nullptr) {
+ const char *prefix = "";
+ if (flexSemiPlanarPixelFormat) {
+ format = COLOR_FormatYUV420SemiPlanar;
+ prefix = "semi-";
+ } else {
+ format = COLOR_FormatYUV420Planar;
+ }
+ ALOGD("Client requested ByteBuffer mode decoder w/o color format set: "
+ "using default %splanar color format", prefix);
+ } else {
+ format = COLOR_FormatSurface;
+ }
+ defaultColorFormat = format;
+ }
+ } else {
+ if ((config->mDomain & Config::IS_ENCODER) || !surface) {
+ switch (format) {
+ case COLOR_FormatYUV420Flexible:
+ format = flexPixelFormat.value_or(COLOR_FormatYUV420Planar);
+ break;
+ case COLOR_FormatYUV420Planar:
+ case COLOR_FormatYUV420PackedPlanar:
+ format = flexPlanarPixelFormat.value_or(
+ flexPixelFormat.value_or(format));
+ break;
+ case COLOR_FormatYUV420SemiPlanar:
+ case COLOR_FormatYUV420PackedSemiPlanar:
+ format = flexSemiPlanarPixelFormat.value_or(
+ flexPixelFormat.value_or(format));
+ break;
+ default:
+ // No-op
+ break;
+ }
}
}
- if (format >= 0) {
+ if (format != 0) {
msg->setInt32("android._color-format", format);
}
}
+ /*
+ * Handle dataspace
+ */
+ int32_t usingRecorder;
+ if (msg->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) {
+ android_dataspace dataSpace = HAL_DATASPACE_BT709;
+ int32_t width, height;
+ if (msg->findInt32("width", &width)
+ && msg->findInt32("height", &height)) {
+ ColorAspects aspects;
+ getColorAspectsFromFormat(msg, aspects);
+ setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
+ // TODO: read dataspace / color aspect from the component
+ setColorAspectsIntoFormat(aspects, const_cast<sp<AMessage> &>(msg));
+ dataSpace = getDataSpaceForColorAspects(aspects, true /* mayexpand */);
+ }
+ msg->setInt32("android._dataspace", (int32_t)dataSpace);
+ ALOGD("setting dataspace to %x", dataSpace);
+ }
+
int32_t subscribeToAllVendorParams;
if (msg->findInt32("x-*", &subscribeToAllVendorParams) && subscribeToAllVendorParams) {
if (config->subscribeToAllVendorParams(comp, C2_MAY_BLOCK) != OK) {
@@ -900,7 +1074,7 @@
sdkParams = msg->dup();
sdkParams->removeEntryAt(sdkParams->findEntryByName(PARAMETER_KEY_VIDEO_BITRATE));
}
- status_t err = config->getConfigUpdateFromSdkParams(
+ err = config->getConfigUpdateFromSdkParams(
comp, sdkParams, Config::IS_CONFIG, C2_DONT_BLOCK, &configUpdate);
if (err != OK) {
ALOGW("failed to convert configuration to c2 params");
@@ -932,7 +1106,10 @@
C2StreamMaxBufferSizeInfo::input maxInputSize(0u, 0u);
C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
+ C2Param::Index colorAspectsRequestIndex =
+ C2StreamColorAspectsInfo::output::PARAM_TYPE | C2Param::CoreIndex::IS_REQUEST_FLAG;
std::initializer_list<C2Param::Index> indices {
+ colorAspectsRequestIndex.withStream(0u),
};
c2_status_t c2err = comp->query(
{ &usage, &maxInputSize, &prepend },
@@ -943,11 +1120,6 @@
ALOGE("Failed to query component interface: %d", c2err);
return UNKNOWN_ERROR;
}
- if (params.size() != indices.size()) {
- ALOGE("Component returns wrong number of params: expected %zu actual %zu",
- indices.size(), params.size());
- return UNKNOWN_ERROR;
- }
if (usage) {
if (usage.value & C2MemoryUsage::CPU_READ) {
config->mInputFormat->setInt32("using-sw-read-often", true);
@@ -1012,13 +1184,14 @@
int32_t clientPrepend;
if ((config->mDomain & Config::IS_VIDEO)
&& (config->mDomain & Config::IS_ENCODER)
- && msg->findInt32(KEY_PREPEND_HEADERS_TO_SYNC_FRAMES, &clientPrepend)
+ && msg->findInt32(KEY_PREPEND_HEADER_TO_SYNC_FRAMES, &clientPrepend)
&& clientPrepend
&& (!prepend || prepend.value != PREPEND_HEADER_TO_ALL_SYNC)) {
- ALOGE("Failed to set KEY_PREPEND_HEADERS_TO_SYNC_FRAMES");
+ ALOGE("Failed to set KEY_PREPEND_HEADER_TO_SYNC_FRAMES");
return BAD_VALUE;
}
+ int32_t componentColorFormat = 0;
if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
// propagate HDR static info to output format for both encoders and decoders
// if component supports this info, we will update from component, but only the raw port,
@@ -1031,12 +1204,16 @@
// Set desired color format from configuration parameter
int32_t format;
- if (msg->findInt32("android._color-format", &format)) {
- if (config->mDomain & Config::IS_ENCODER) {
- config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
- } else {
- config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
+ if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
+ format = defaultColorFormat;
+ }
+ if (config->mDomain & Config::IS_ENCODER) {
+ config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
+ if (msg->findInt32("android._color-format", &componentColorFormat)) {
+ config->mInputFormat->setInt32("android._color-format", componentColorFormat);
}
+ } else {
+ config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
}
}
@@ -1064,8 +1241,86 @@
}
}
- ALOGD("setup formats input: %s and output: %s",
- config->mInputFormat->debugString().c_str(),
+ std::unique_ptr<C2Param> colorTransferRequestParam;
+ for (std::unique_ptr<C2Param> ¶m : params) {
+ if (param->index() == colorAspectsRequestIndex.withStream(0u)) {
+ ALOGI("found color transfer request param");
+ colorTransferRequestParam = std::move(param);
+ }
+ }
+ int32_t colorTransferRequest = 0;
+ if (config->mDomain & (Config::IS_IMAGE | Config::IS_VIDEO)
+ && !sdkParams->findInt32("color-transfer-request", &colorTransferRequest)) {
+ colorTransferRequest = 0;
+ }
+
+ if (colorTransferRequest != 0) {
+ if (colorTransferRequestParam && *colorTransferRequestParam) {
+ C2StreamColorAspectsInfo::output *info =
+ static_cast<C2StreamColorAspectsInfo::output *>(
+ colorTransferRequestParam.get());
+ if (!C2Mapper::map(info->transfer, &colorTransferRequest)) {
+ colorTransferRequest = 0;
+ }
+ } else {
+ colorTransferRequest = 0;
+ }
+ config->mInputFormat->setInt32("color-transfer-request", colorTransferRequest);
+ }
+
+ if (componentColorFormat != 0 && componentColorFormat != COLOR_FormatSurface) {
+ // Need to get stride/vstride
+ uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
+ if (C2Mapper::mapPixelFormatFrameworkToCodec(componentColorFormat, &pixelFormat)) {
+ // TODO: retrieve these values without allocating a buffer.
+ // Currently allocating a buffer is necessary to retrieve the layout.
+ int64_t blockUsage =
+ usage.value | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE;
+ std::shared_ptr<C2GraphicBlock> block = FetchGraphicBlock(
+ width, height, pixelFormat, blockUsage, {comp->getName()});
+ sp<GraphicBlockBuffer> buffer;
+ if (block) {
+ buffer = GraphicBlockBuffer::Allocate(
+ config->mInputFormat,
+ block,
+ [](size_t size) -> sp<ABuffer> { return new ABuffer(size); });
+ } else {
+ ALOGD("Failed to allocate a graphic block "
+ "(width=%d height=%d pixelFormat=%u usage=%llx)",
+ width, height, pixelFormat, (long long)blockUsage);
+ // This means that byte buffer mode is not supported in this configuration
+ // anyway. Skip setting stride/vstride to input format.
+ }
+ if (buffer) {
+ sp<ABuffer> imageData = buffer->getImageData();
+ MediaImage2 *img = nullptr;
+ if (imageData && imageData->data()
+ && imageData->size() >= sizeof(MediaImage2)) {
+ img = (MediaImage2*)imageData->data();
+ }
+ if (img && img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
+ int32_t stride = img->mPlane[0].mRowInc;
+ config->mInputFormat->setInt32(KEY_STRIDE, stride);
+ if (img->mNumPlanes > 1 && stride > 0) {
+ int64_t offsetDelta =
+ (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
+ if (offsetDelta % stride == 0) {
+ int32_t vstride = int32_t(offsetDelta / stride);
+ config->mInputFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
+ } else {
+ ALOGD("Cannot report accurate slice height: "
+ "offsetDelta = %lld stride = %d",
+ (long long)offsetDelta, stride);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ALOGD("setup formats input: %s",
+ config->mInputFormat->debugString().c_str());
+ ALOGD("setup formats output: %s",
config->mOutputFormat->debugString().c_str());
return OK;
};
@@ -1076,6 +1331,8 @@
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
+ config->queryConfiguration(comp);
+
mCallback->onComponentConfigured(config->mInputFormat, config->mOutputFormat);
}
@@ -1324,6 +1581,7 @@
outputFormat = config->mOutputFormat = config->mOutputFormat->dup();
if (config->mInputSurface) {
err2 = config->mInputSurface->start();
+ config->mInputSurfaceDataspace = config->mInputSurface->getDataspace();
}
buffersBoundToCodec = config->mBuffersBoundToCodec;
}
@@ -1411,6 +1669,7 @@
if (config->mInputSurface) {
config->mInputSurface->disconnect();
config->mInputSurface = nullptr;
+ config->mInputSurfaceDataspace = HAL_DATASPACE_UNKNOWN;
}
}
{
@@ -1460,6 +1719,7 @@
if (config->mInputSurface) {
config->mInputSurface->disconnect();
config->mInputSurface = nullptr;
+ config->mInputSurfaceDataspace = HAL_DATASPACE_UNKNOWN;
}
}
@@ -1497,6 +1757,19 @@
}
status_t CCodec::setSurface(const sp<Surface> &surface) {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ if (config->mTunneled && config->mSidebandHandle != nullptr) {
+ sp<ANativeWindow> nativeWindow = static_cast<ANativeWindow *>(surface.get());
+ status_t err = native_window_set_sideband_stream(
+ nativeWindow.get(),
+ const_cast<native_handle_t *>(config->mSidebandHandle->handle()));
+ if (err != OK) {
+ ALOGE("NativeWindow(%p) native_window_set_sideband_stream(%p) failed! (err %d).",
+ nativeWindow.get(), config->mSidebandHandle->handle(), err);
+ return err;
+ }
+ }
return mChannel->setSurface(surface);
}
@@ -1581,7 +1854,9 @@
{
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
+ sp<AMessage> outputFormat = config->mOutputFormat;
config->queryConfiguration(comp);
+ RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
}
(void)mChannel->start(nullptr, nullptr, [&]{
@@ -1627,6 +1902,12 @@
params->removeEntryAt(params->findEntryByName(KEY_BIT_RATE));
}
+ int32_t syncId = 0;
+ if (params->findInt32("audio-hw-sync", &syncId)
+ || params->findInt32("hw-av-sync-id", &syncId)) {
+ configureTunneledVideoPlayback(comp, nullptr, params);
+ }
+
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
@@ -1669,7 +1950,9 @@
|| comp->getName().find("c2.android.") == 0)) {
mChannel->setParameters(configUpdate);
} else {
+ sp<AMessage> outputFormat = config->mOutputFormat;
(void)config->setParameters(comp, configUpdate, C2_MAY_BLOCK);
+ RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
}
}
@@ -1696,6 +1979,39 @@
config->setParameters(comp, params, C2_MAY_BLOCK);
}
+status_t CCodec::querySupportedParameters(std::vector<std::string> *names) {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ return config->querySupportedParameters(names);
+}
+
+status_t CCodec::describeParameter(
+ const std::string &name, CodecParameterDescriptor *desc) {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ return config->describe(name, desc);
+}
+
+status_t CCodec::subscribeToParameters(const std::vector<std::string> &names) {
+ std::shared_ptr<Codec2Client::Component> comp = mState.lock()->comp;
+ if (!comp) {
+ return INVALID_OPERATION;
+ }
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ return config->subscribeToVendorConfigUpdate(comp, names);
+}
+
+status_t CCodec::unsubscribeFromParameters(const std::vector<std::string> &names) {
+ std::shared_ptr<Codec2Client::Component> comp = mState.lock()->comp;
+ if (!comp) {
+ return INVALID_OPERATION;
+ }
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ return config->unsubscribeFromVendorConfigUpdate(comp, names);
+}
+
void CCodec::onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
if (!workItems.empty()) {
Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue);
@@ -1794,7 +2110,6 @@
// handle configuration changes in work done
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
- bool changed = false;
Config::Watcher<C2StreamInitDataInfo::output> initData =
config->watch<C2StreamInitDataInfo::output>();
if (!work->worklets.empty()
@@ -1829,9 +2144,9 @@
++stream;
}
- if (config->updateConfiguration(updates, config->mOutputDomain)) {
- changed = true;
- }
+ sp<AMessage> outputFormat = config->mOutputFormat;
+ config->updateConfiguration(updates, config->mOutputDomain);
+ RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
// copy standard infos to graphic buffers if not already present (otherwise, we
// may overwrite the actual intermediate value with a final value)
@@ -1865,7 +2180,7 @@
config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
}
mChannel->onWorkDone(
- std::move(work), changed ? config->mOutputFormat->dup() : nullptr,
+ std::move(work), config->mOutputFormat,
initData.hasChanged() ? initData.update().get() : nullptr);
break;
}
@@ -1890,6 +2205,55 @@
deadline->set(now + (timeout * mult), name);
}
+status_t CCodec::configureTunneledVideoPlayback(
+ std::shared_ptr<Codec2Client::Component> comp,
+ sp<NativeHandle> *sidebandHandle,
+ const sp<AMessage> &msg) {
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+
+ std::unique_ptr<C2PortTunneledModeTuning::output> tunneledPlayback =
+ C2PortTunneledModeTuning::output::AllocUnique(
+ 1,
+ C2PortTunneledModeTuning::Struct::SIDEBAND,
+ C2PortTunneledModeTuning::Struct::REALTIME,
+ 0);
+ // TODO: use KEY_AUDIO_HW_SYNC, KEY_HARDWARE_AV_SYNC_ID when they are in MediaCodecConstants.h
+ if (msg->findInt32("audio-hw-sync", &tunneledPlayback->m.syncId[0])) {
+ tunneledPlayback->m.syncType = C2PortTunneledModeTuning::Struct::sync_type_t::AUDIO_HW_SYNC;
+ } else if (msg->findInt32("hw-av-sync-id", &tunneledPlayback->m.syncId[0])) {
+ tunneledPlayback->m.syncType = C2PortTunneledModeTuning::Struct::sync_type_t::HW_AV_SYNC;
+ } else {
+ tunneledPlayback->m.syncType = C2PortTunneledModeTuning::Struct::sync_type_t::REALTIME;
+ tunneledPlayback->setFlexCount(0);
+ }
+ c2_status_t c2err = comp->config({ tunneledPlayback.get() }, C2_MAY_BLOCK, &failures);
+ if (c2err != C2_OK) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (sidebandHandle == nullptr) {
+ return OK;
+ }
+
+ std::vector<std::unique_ptr<C2Param>> params;
+ c2err = comp->query({}, {C2PortTunnelHandleTuning::output::PARAM_TYPE}, C2_DONT_BLOCK, ¶ms);
+ if (c2err == C2_OK && params.size() == 1u) {
+ C2PortTunnelHandleTuning::output *videoTunnelSideband =
+ C2PortTunnelHandleTuning::output::From(params[0].get());
+ // Currently, Codec2 only supports non-fd case for sideband native_handle.
+ native_handle_t *handle = native_handle_create(0, videoTunnelSideband->flexCount());
+ *sidebandHandle = NativeHandle::create(handle, true /* ownsHandle */);
+ if (handle != nullptr && videoTunnelSideband->flexCount()) {
+ memcpy(handle->data, videoTunnelSideband->m.values,
+ sizeof(int32_t) * videoTunnelSideband->flexCount());
+ return OK;
+ } else {
+ return NO_MEMORY;
+ }
+ }
+ return UNKNOWN_ERROR;
+}
+
void CCodec::initiateReleaseIfStuck() {
std::string name;
bool pendingDeadline = false;
@@ -1902,7 +2266,9 @@
pendingDeadline = true;
}
}
- if (name.empty()) {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ if (config->mTunneled == false && name.empty()) {
constexpr std::chrono::steady_clock::duration kWorkDurationThreshold = 3s;
std::chrono::steady_clock::duration elapsed = mChannel->elapsed();
if (elapsed >= kWorkDurationThreshold) {
@@ -1994,7 +2360,7 @@
}
if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
mInputAllocators.reset(
- C2PortAllocatorsTuning::input::From(params[0].get()));
+ C2PortAllocatorsTuning::input::From(param));
}
}
mInitStatus = OK;
@@ -2291,4 +2657,3 @@
}
} // namespace android
-
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index aa4a004..ad02edb 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -30,6 +30,7 @@
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryDealer.h>
@@ -143,7 +144,8 @@
mFrameIndex(0u),
mFirstValidFrameIndex(0u),
mMetaMode(MODE_NONE),
- mInputMetEos(false) {
+ mInputMetEos(false),
+ mSendEncryptedInfoBuffer(false) {
mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
{
Mutexed<Input>::Locked input(mInput);
@@ -188,7 +190,10 @@
return mInputSurface->signalEndOfInputStream();
}
-status_t CCodecBufferChannel::queueInputBufferInternal(sp<MediaCodecBuffer> buffer) {
+status_t CCodecBufferChannel::queueInputBufferInternal(
+ sp<MediaCodecBuffer> buffer,
+ std::shared_ptr<C2LinearBlock> encryptedBlock,
+ size_t blockSize) {
int64_t timeUs;
CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
@@ -209,6 +214,7 @@
flags |= C2FrameData::FLAG_CODEC_CONFIG;
}
ALOGV("[%s] queueInputBuffer: buffer->size() = %zu", mName, buffer->size());
+ std::list<std::unique_ptr<C2Work>> items;
std::unique_ptr<C2Work> work(new C2Work);
work->input.ordinal.timestamp = timeUs;
work->input.ordinal.frameIndex = mFrameIndex++;
@@ -218,9 +224,8 @@
work->input.ordinal.customOrdinal = timeUs;
work->input.buffers.clear();
- uint64_t queuedFrameIndex = work->input.ordinal.frameIndex.peeku();
- std::vector<std::shared_ptr<C2Buffer>> queuedBuffers;
sp<Codec2Buffer> copy;
+ bool usesFrameReassembler = false;
if (buffer->size() > 0u) {
Mutexed<Input>::Locked input(mInput);
@@ -245,30 +250,48 @@
"buffer starvation on component.", mName);
}
}
- work->input.buffers.push_back(c2buffer);
- queuedBuffers.push_back(c2buffer);
+ if (input->frameReassembler) {
+ usesFrameReassembler = true;
+ input->frameReassembler.process(buffer, &items);
+ } else {
+ int32_t cvo = 0;
+ if (buffer->meta()->findInt32("cvo", &cvo)) {
+ int32_t rotation = cvo % 360;
+ // change rotation to counter-clock wise.
+ rotation = ((rotation <= 0) ? 0 : 360) - rotation;
+
+ Mutexed<OutputSurface>::Locked output(mOutputSurface);
+ uint64_t frameIndex = work->input.ordinal.frameIndex.peeku();
+ output->rotation[frameIndex] = rotation;
+ }
+ work->input.buffers.push_back(c2buffer);
+ if (encryptedBlock) {
+ work->input.infoBuffers.emplace_back(C2InfoBuffer::CreateLinearBuffer(
+ kParamIndexEncryptedBuffer,
+ encryptedBlock->share(0, blockSize, C2Fence())));
+ }
+ }
} else if (eos) {
flags |= C2FrameData::FLAG_END_OF_STREAM;
}
- work->input.flags = (C2FrameData::flags_t)flags;
- // TODO: fill info's
+ if (usesFrameReassembler) {
+ if (!items.empty()) {
+ items.front()->input.configUpdate = std::move(mParamsToBeSet);
+ mFrameIndex = (items.back()->input.ordinal.frameIndex + 1).peek();
+ }
+ } else {
+ work->input.flags = (C2FrameData::flags_t)flags;
+ // TODO: fill info's
- work->input.configUpdate = std::move(mParamsToBeSet);
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
+ work->input.configUpdate = std::move(mParamsToBeSet);
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
- mPipelineWatcher.lock()->onWorkQueued(
- queuedFrameIndex,
- std::move(queuedBuffers),
- PipelineWatcher::Clock::now());
- c2_status_t err = mComponent->queue(&items);
- if (err != C2_OK) {
- mPipelineWatcher.lock()->onWorkDone(queuedFrameIndex);
+ items.push_back(std::move(work));
+
+ eos = eos && buffer->size() > 0u;
}
-
- if (err == C2_OK && eos && buffer->size() > 0u) {
+ if (eos) {
work.reset(new C2Work);
work->input.ordinal.timestamp = timeUs;
work->input.ordinal.frameIndex = mFrameIndex++;
@@ -277,23 +300,28 @@
work->input.buffers.clear();
work->input.flags = C2FrameData::FLAG_END_OF_STREAM;
work->worklets.emplace_back(new C2Worklet);
-
- queuedFrameIndex = work->input.ordinal.frameIndex.peeku();
- queuedBuffers.clear();
-
- items.clear();
items.push_back(std::move(work));
-
- mPipelineWatcher.lock()->onWorkQueued(
- queuedFrameIndex,
- std::move(queuedBuffers),
- PipelineWatcher::Clock::now());
- err = mComponent->queue(&items);
- if (err != C2_OK) {
- mPipelineWatcher.lock()->onWorkDone(queuedFrameIndex);
- }
}
- if (err == C2_OK) {
+ c2_status_t err = C2_OK;
+ if (!items.empty()) {
+ {
+ Mutexed<PipelineWatcher>::Locked watcher(mPipelineWatcher);
+ PipelineWatcher::Clock::time_point now = PipelineWatcher::Clock::now();
+ for (const std::unique_ptr<C2Work> &work : items) {
+ watcher->onWorkQueued(
+ work->input.ordinal.frameIndex.peeku(),
+ std::vector(work->input.buffers),
+ now);
+ }
+ }
+ err = mComponent->queue(&items);
+ }
+ if (err != C2_OK) {
+ Mutexed<PipelineWatcher>::Locked watcher(mPipelineWatcher);
+ for (const std::unique_ptr<C2Work> &work : items) {
+ watcher->onWorkDone(work->input.ordinal.frameIndex.peeku());
+ }
+ } else {
Mutexed<Input>::Locked input(mInput);
bool released = false;
if (buffer) {
@@ -514,6 +542,40 @@
}
sp<EncryptedLinearBlockBuffer> encryptedBuffer((EncryptedLinearBlockBuffer *)buffer.get());
+ std::shared_ptr<C2LinearBlock> block;
+ size_t allocSize = buffer->size();
+ size_t bufferSize = 0;
+ c2_status_t blockRes = C2_OK;
+ bool copied = false;
+ if (mSendEncryptedInfoBuffer) {
+ static const C2MemoryUsage kDefaultReadWriteUsage{
+ C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+ constexpr int kAllocGranule0 = 1024 * 64;
+ constexpr int kAllocGranule1 = 1024 * 1024;
+ std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool;
+ // round up encrypted sizes to limit fragmentation and encourage buffer reuse
+ if (allocSize <= kAllocGranule1) {
+ bufferSize = align(allocSize, kAllocGranule0);
+ } else {
+ bufferSize = align(allocSize, kAllocGranule1);
+ }
+ blockRes = pool->fetchLinearBlock(
+ bufferSize, kDefaultReadWriteUsage, &block);
+
+ if (blockRes == C2_OK) {
+ C2WriteView view = block->map().get();
+ if (view.error() == C2_OK && view.size() == bufferSize) {
+ copied = true;
+ // TODO: only copy clear sections
+ memcpy(view.data(), buffer->data(), allocSize);
+ }
+ }
+ }
+
+ if (!copied) {
+ block.reset();
+ }
+
ssize_t result = -1;
ssize_t codecDataOffset = 0;
if (numSubSamples == 1
@@ -605,7 +667,8 @@
}
buffer->setRange(codecDataOffset, result - codecDataOffset);
- return queueInputBufferInternal(buffer);
+
+ return queueInputBufferInternal(buffer, block, bufferSize);
}
void CCodecBufferChannel::feedInputBufferIfAvailable() {
@@ -695,6 +758,22 @@
c2Buffer->getInfo(C2StreamRotationInfo::output::PARAM_TYPE));
bool flip = rotation && (rotation->flip & 1);
uint32_t quarters = ((rotation ? rotation->value : 0) / 90) & 3;
+
+ {
+ Mutexed<OutputSurface>::Locked output(mOutputSurface);
+ if (output->surface == nullptr) {
+ ALOGI("[%s] cannot render buffer without surface", mName);
+ return OK;
+ }
+ int64_t frameIndex;
+ buffer->meta()->findInt64("frameIndex", &frameIndex);
+ if (output->rotation.count(frameIndex) != 0) {
+ auto it = output->rotation.find(frameIndex);
+ quarters = (it->second / 90) & 3;
+ output->rotation.erase(it);
+ }
+ }
+
uint32_t transform = 0;
switch (quarters) {
case 0: // no rotation
@@ -738,14 +817,6 @@
hdr10PlusInfo.reset();
}
- {
- Mutexed<OutputSurface>::Locked output(mOutputSurface);
- if (output->surface == nullptr) {
- ALOGI("[%s] cannot render buffer without surface", mName);
- return OK;
- }
- }
-
std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
if (blocks.size() != 1u) {
ALOGD("[%s] expected 1 graphic block, but got %zu", mName, blocks.size());
@@ -821,7 +892,12 @@
}
return result;
}
- ALOGV("[%s] queue buffer successful", mName);
+
+ if(android::base::GetBoolProperty("debug.stagefright.fps", false)) {
+ ALOGD("[%s] queue buffer successful", mName);
+ } else {
+ ALOGV("[%s] queue buffer successful", mName);
+ }
int64_t mediaTimeUs = 0;
(void)buffer->meta()->findInt64("timeUs", &mediaTimeUs);
@@ -882,27 +958,31 @@
bool buffersBoundToCodec) {
C2StreamBufferTypeSetting::input iStreamFormat(0u);
C2StreamBufferTypeSetting::output oStreamFormat(0u);
+ C2ComponentKindSetting kind;
C2PortReorderBufferDepthTuning::output reorderDepth;
C2PortReorderKeySetting::output reorderKey;
C2PortActualDelayTuning::input inputDelay(0);
C2PortActualDelayTuning::output outputDelay(0);
C2ActualPipelineDelayTuning pipelineDelay(0);
+ C2SecureModeTuning secureMode(C2Config::SM_UNPROTECTED);
c2_status_t err = mComponent->query(
{
&iStreamFormat,
&oStreamFormat,
+ &kind,
&reorderDepth,
&reorderKey,
&inputDelay,
&pipelineDelay,
&outputDelay,
+ &secureMode,
},
{},
C2_DONT_BLOCK,
nullptr);
if (err == C2_BAD_INDEX) {
- if (!iStreamFormat || !oStreamFormat) {
+ if (!iStreamFormat || !oStreamFormat || !kind) {
return UNKNOWN_ERROR;
}
} else if (err != C2_OK) {
@@ -919,18 +999,26 @@
// TODO: get this from input format
bool secure = mComponent->getName().find(".secure") != std::string::npos;
+ // secure mode is a static parameter (shall not change in the executing state)
+ mSendEncryptedInfoBuffer = secureMode.value == C2Config::SM_READ_PROTECTED_WITH_ENCRYPTED;
+
std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
int poolMask = GetCodec2PoolMask();
C2PlatformAllocatorStore::id_t preferredLinearId = GetPreferredLinearAllocatorId(poolMask);
if (inputFormat != nullptr) {
bool graphic = (iStreamFormat.value == C2BufferData::GRAPHIC);
+ bool audioEncoder = !graphic && (kind.value == C2Component::KIND_ENCODER);
C2Config::api_feature_t apiFeatures = C2Config::api_feature_t(
API_REFLECTION |
API_VALUES |
API_CURRENT_VALUES |
API_DEPENDENCY |
API_SAME_INPUT_BUFFER);
+ C2StreamAudioFrameSizeInfo::input encoderFrameSize(0u);
+ C2StreamSampleRateInfo::input sampleRate(0u);
+ C2StreamChannelCountInfo::input channelCount(0u);
+ C2StreamPcmEncodingInfo::input pcmEncoding(0u);
std::shared_ptr<C2BlockPool> pool;
{
Mutexed<BlockPools>::Locked pools(mBlockPools);
@@ -943,7 +1031,19 @@
// from component, create the input block pool with given ID. Otherwise, use default IDs.
std::vector<std::unique_ptr<C2Param>> params;
C2ApiFeaturesSetting featuresSetting{apiFeatures};
- err = mComponent->query({ &featuresSetting },
+ std::vector<C2Param *> stackParams({&featuresSetting});
+ if (audioEncoder) {
+ stackParams.push_back(&encoderFrameSize);
+ stackParams.push_back(&sampleRate);
+ stackParams.push_back(&channelCount);
+ stackParams.push_back(&pcmEncoding);
+ } else {
+ encoderFrameSize.invalidate();
+ sampleRate.invalidate();
+ channelCount.invalidate();
+ pcmEncoding.invalidate();
+ }
+ err = mComponent->query(stackParams,
{ C2PortAllocatorsTuning::input::PARAM_TYPE },
C2_DONT_BLOCK,
¶ms);
@@ -1001,10 +1101,21 @@
input->numSlots = numInputSlots;
input->extraBuffers.flush();
input->numExtraSlots = 0u;
+ if (audioEncoder && encoderFrameSize && sampleRate && channelCount) {
+ input->frameReassembler.init(
+ pool,
+ {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+ encoderFrameSize.value,
+ sampleRate.value,
+ channelCount.value,
+ pcmEncoding ? pcmEncoding.value : C2Config::PCM_16);
+ }
bool conforming = (apiFeatures & API_SAME_INPUT_BUFFER);
// For encrypted content, framework decrypts source buffer (ashmem) into
// C2Buffers. Thus non-conforming codecs can process these.
- if (!buffersBoundToCodec && (hasCryptoOrDescrambler() || conforming)) {
+ if (!buffersBoundToCodec
+ && !input->frameReassembler
+ && (hasCryptoOrDescrambler() || conforming)) {
input->buffers.reset(new SlotInputBuffers(mName));
} else if (graphic) {
if (mInputSurface) {
@@ -1300,54 +1411,30 @@
return a.capacity < b.capacity;
});
- {
- Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
- if (!configs->empty()) {
- while (!configs->empty()) {
- sp<ABuffer> config = configs->front();
- configs->pop_front();
- // Find the smallest input buffer that can fit the config.
- auto i = std::find_if(
- clientInputBuffers.begin(),
- clientInputBuffers.end(),
- [cfgSize = config->size()](const ClientInputBuffer& b) {
- return b.capacity >= cfgSize;
- });
- if (i == clientInputBuffers.end()) {
- ALOGW("[%s] no input buffer large enough for the config "
- "(%zu bytes)",
- mName, config->size());
- return NO_MEMORY;
- }
- sp<MediaCodecBuffer> buffer = i->buffer;
- memcpy(buffer->base(), config->data(), config->size());
- buffer->setRange(0, config->size());
- buffer->meta()->clear();
- buffer->meta()->setInt64("timeUs", 0);
- buffer->meta()->setInt32("csd", 1);
- if (queueInputBufferInternal(buffer) != OK) {
- ALOGW("[%s] Error while queueing a flushed config",
- mName);
- return UNKNOWN_ERROR;
- }
- clientInputBuffers.erase(i);
- }
- } else if (oStreamFormat.value == C2BufferData::LINEAR &&
- (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
- sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
- // WORKAROUND: Some apps expect CSD available without queueing
- // any input. Queue an empty buffer to get the CSD.
- buffer->setRange(0, 0);
- buffer->meta()->clear();
- buffer->meta()->setInt64("timeUs", 0);
- if (queueInputBufferInternal(buffer) != OK) {
- ALOGW("[%s] Error while queueing an empty buffer to get CSD",
- mName);
- return UNKNOWN_ERROR;
- }
- clientInputBuffers.pop_front();
+ std::list<std::unique_ptr<C2Work>> flushedConfigs;
+ mFlushedConfigs.lock()->swap(flushedConfigs);
+ if (!flushedConfigs.empty()) {
+ err = mComponent->queue(&flushedConfigs);
+ if (err != C2_OK) {
+ ALOGW("[%s] Error while queueing a flushed config", mName);
+ return UNKNOWN_ERROR;
}
}
+ if (oStreamFormat.value == C2BufferData::LINEAR &&
+ (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
+ sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
+ // WORKAROUND: Some apps expect CSD available without queueing
+ // any input. Queue an empty buffer to get the CSD.
+ buffer->setRange(0, 0);
+ buffer->meta()->clear();
+ buffer->meta()->setInt64("timeUs", 0);
+ if (queueInputBufferInternal(buffer) != OK) {
+ ALOGW("[%s] Error while queueing an empty buffer to get CSD",
+ mName);
+ return UNKNOWN_ERROR;
+ }
+ clientInputBuffers.pop_front();
+ }
for (const ClientInputBuffer& clientInputBuffer: clientInputBuffers) {
mCallback->onInputBufferAvailable(
@@ -1396,27 +1483,36 @@
void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
ALOGV("[%s] flush", mName);
- {
- Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
- for (const std::unique_ptr<C2Work> &work : flushedWork) {
- if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
- continue;
- }
- if (work->input.buffers.empty()
- || work->input.buffers.front()->data().linearBlocks().empty()) {
- ALOGD("[%s] no linear codec config data found", mName);
- continue;
- }
- C2ReadView view =
- work->input.buffers.front()->data().linearBlocks().front().map().get();
- if (view.error() != C2_OK) {
- ALOGD("[%s] failed to map flushed codec config data: %d", mName, view.error());
- continue;
- }
- configs->push_back(ABuffer::CreateAsCopy(view.data(), view.capacity()));
- ALOGV("[%s] stashed flushed codec config data (size=%u)", mName, view.capacity());
+ std::list<std::unique_ptr<C2Work>> configs;
+ for (const std::unique_ptr<C2Work> &work : flushedWork) {
+ if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
+ continue;
}
+ if (work->input.buffers.empty()
+ || work->input.buffers.front() == nullptr
+ || work->input.buffers.front()->data().linearBlocks().empty()) {
+ ALOGD("[%s] no linear codec config data found", mName);
+ continue;
+ }
+ std::unique_ptr<C2Work> copy(new C2Work);
+ copy->input.flags = C2FrameData::flags_t(work->input.flags | C2FrameData::FLAG_DROP_FRAME);
+ copy->input.ordinal = work->input.ordinal;
+ copy->input.buffers.insert(
+ copy->input.buffers.begin(),
+ work->input.buffers.begin(),
+ work->input.buffers.end());
+ for (const std::unique_ptr<C2Param> ¶m : work->input.configUpdate) {
+ copy->input.configUpdate.push_back(C2Param::Copy(*param));
+ }
+ copy->input.infoBuffers.insert(
+ copy->input.infoBuffers.begin(),
+ work->input.infoBuffers.begin(),
+ work->input.infoBuffers.end());
+ copy->worklets.emplace_back(new C2Worklet);
+ configs.push_back(std::move(copy));
+ ALOGV("[%s] stashed flushed codec config data", mName);
}
+ mFlushedConfigs.lock()->swap(configs);
{
Mutexed<Input>::Locked input(mInput);
input->buffers->flush();
@@ -1616,6 +1712,17 @@
}
break;
}
+ case C2PortTunnelSystemTime::CORE_INDEX: {
+ C2PortTunnelSystemTime::output frameRenderTime;
+ if (frameRenderTime.updateFrom(*param)) {
+ ALOGV("[%s] onWorkDone: frame rendered (sys:%lld ns, media:%lld us)",
+ mName, (long long)frameRenderTime.value,
+ (long long)worklet->output.ordinal.timestamp.peekll());
+ mCCodecCallback->onOutputFramesRendered(
+ worklet->output.ordinal.timestamp.peek(), frameRenderTime.value);
+ }
+ break;
+ }
default:
ALOGV("[%s] onWorkDone: unrecognized config update (%08X)",
mName, param->index());
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 046c5c3..45da003 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -31,6 +31,7 @@
#include <media/stagefright/CodecBase.h>
#include "CCodecBuffers.h"
+#include "FrameReassembler.h"
#include "InputSurfaceWrapper.h"
#include "PipelineWatcher.h"
@@ -238,7 +239,9 @@
void feedInputBufferIfAvailable();
void feedInputBufferIfAvailableInternal();
- status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer);
+ status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer,
+ std::shared_ptr<C2LinearBlock> encryptedBlock = nullptr,
+ size_t blockSize = 0);
bool handleWork(
std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
const C2StreamInitDataInfo::output *initData);
@@ -269,6 +272,8 @@
size_t numExtraSlots;
uint32_t inputDelay;
uint32_t pipelineDelay;
+
+ FrameReassembler frameReassembler;
};
Mutexed<Input> mInput;
struct Output {
@@ -277,7 +282,7 @@
uint32_t outputDelay;
};
Mutexed<Output> mOutput;
- Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs;
+ Mutexed<std::list<std::unique_ptr<C2Work>>> mFlushedConfigs;
std::atomic_uint64_t mFrameIndex;
std::atomic_uint64_t mFirstValidFrameIndex;
@@ -288,6 +293,7 @@
sp<Surface> surface;
uint32_t generation;
int maxDequeueBuffers;
+ std::map<uint64_t, int> rotation;
};
Mutexed<OutputSurface> mOutputSurface;
@@ -315,6 +321,7 @@
inline bool hasCryptoOrDescrambler() {
return mCrypto != nullptr || mDescrambler != nullptr;
}
+ std::atomic_bool mSendEncryptedInfoBuffer;
};
// Conversion of a c2_status_t value to a status_t value may depend on the
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 692da58..ba44074 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -27,6 +27,7 @@
#include <mediadrm/ICrypto.h>
#include "CCodecBuffers.h"
+#include "Codec2Mapper.h"
namespace android {
@@ -76,31 +77,39 @@
void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
sp<ABuffer> imageDataCandidate = buffer->getImageData();
if (imageDataCandidate == nullptr) {
+ if (mFormatWithImageData) {
+ // We previously sent the format with image data, so use the same format.
+ buffer->setFormat(mFormatWithImageData);
+ }
return;
}
- sp<ABuffer> imageData;
- if (!mFormat->findBuffer("image-data", &imageData)
- || imageDataCandidate->size() != imageData->size()
- || memcmp(imageDataCandidate->data(), imageData->data(), imageData->size()) != 0) {
+ if (!mLastImageData
+ || imageDataCandidate->size() != mLastImageData->size()
+ || memcmp(imageDataCandidate->data(),
+ mLastImageData->data(),
+ mLastImageData->size()) != 0) {
ALOGD("[%s] updating image-data", mName);
- sp<AMessage> newFormat = dupFormat();
- newFormat->setBuffer("image-data", imageDataCandidate);
+ mFormatWithImageData = dupFormat();
+ mLastImageData = imageDataCandidate;
+ mFormatWithImageData->setBuffer("image-data", imageDataCandidate);
MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
int32_t stride = img->mPlane[0].mRowInc;
- newFormat->setInt32(KEY_STRIDE, stride);
+ mFormatWithImageData->setInt32(KEY_STRIDE, stride);
ALOGD("[%s] updating stride = %d", mName, stride);
if (img->mNumPlanes > 1 && stride > 0) {
int64_t offsetDelta =
(int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
int32_t vstride = int32_t(offsetDelta / stride);
- newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
+ mFormatWithImageData->setInt32(KEY_SLICE_HEIGHT, vstride);
ALOGD("[%s] updating vstride = %d", mName, vstride);
+ buffer->setRange(
+ img->mPlane[0].mOffset,
+ buffer->size() - img->mPlane[0].mOffset);
}
}
- setFormat(newFormat);
- buffer->setFormat(newFormat);
}
+ buffer->setFormat(mFormatWithImageData);
}
// InputBuffers
@@ -158,8 +167,7 @@
setSkipCutBuffer(delay, padding);
}
-void OutputBuffers::updateSkipCutBuffer(
- const sp<AMessage> &format, bool notify) {
+void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
AString mediaType;
if (format->findString(KEY_MIME, &mediaType)
&& mediaType == MIMETYPE_AUDIO_RAW) {
@@ -170,9 +178,6 @@
updateSkipCutBuffer(sampleRate, channelCount);
}
}
- if (notify) {
- mUnreportedFormat = nullptr;
- }
}
void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
@@ -196,7 +201,6 @@
mReorderStash.clear();
mDepth = 0;
mKey = C2Config::ORDINAL;
- mUnreportedFormat = nullptr;
}
void OutputBuffers::flushStash() {
@@ -272,25 +276,15 @@
*c2Buffer = entry.buffer;
sp<AMessage> outputFormat = entry.format;
- // The output format can be processed without a registered slot.
- if (outputFormat) {
- updateSkipCutBuffer(outputFormat, entry.notify);
- }
-
- if (entry.notify) {
- if (outputFormat) {
- setFormat(outputFormat);
- } else if (mUnreportedFormat) {
- outputFormat = mUnreportedFormat;
- setFormat(outputFormat);
- }
- mUnreportedFormat = nullptr;
- } else {
- if (outputFormat) {
- mUnreportedFormat = outputFormat;
- } else if (!mUnreportedFormat) {
- mUnreportedFormat = mFormat;
- }
+ if (entry.notify && mFormat != outputFormat) {
+ updateSkipCutBuffer(outputFormat);
+ // Trigger image data processing to the new format
+ mLastImageData.clear();
+ ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
+ mName, mFormat.get(), outputFormat.get());
+ ALOGD("[%s] popFromStashAndRegister: at %lldus, output format changed to %s",
+ mName, (long long)entry.timestamp, outputFormat->debugString().c_str());
+ setFormat(outputFormat);
}
// Flushing mReorderStash because no other buffers should come after output
@@ -301,10 +295,6 @@
}
if (!entry.notify) {
- if (outputFormat) {
- ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
- mName, outputFormat->debugString().c_str());
- }
mPending.pop_front();
return DISCARD;
}
@@ -321,10 +311,7 @@
// Append information from the front stash entry to outBuffer.
(*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
(*outBuffer)->meta()->setInt32("flags", entry.flags);
- if (outputFormat) {
- ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
- mName, outputFormat->debugString().c_str());
- }
+ (*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
ALOGV("[%s] popFromStashAndRegister: "
"out buffer index = %zu [%p] => %p + %zu (%lld)",
mName, *index, outBuffer->get(),
@@ -1016,18 +1003,32 @@
// track of the flushed work.
}
+static uint32_t extractPixelFormat(const sp<AMessage> &format) {
+ int32_t frameworkColorFormat = 0;
+ if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
+ if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
+ return pixelFormat;
+ }
+ return PIXEL_FORMAT_UNKNOWN;
+}
+
std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
std::unique_ptr<InputBuffersArray> array(
new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
array->setPool(mPool);
array->setFormat(mFormat);
+ uint32_t pixelFormat = extractPixelFormat(mFormat);
array->initialize(
mImpl,
size,
- [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
+ [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
+ -> sp<Codec2Buffer> {
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
return AllocateGraphicBuffer(
- pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
+ pool, format, pixelFormat, usage, lbp);
});
return std::move(array);
}
@@ -1040,7 +1041,7 @@
// TODO: read usage from intf
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
return AllocateGraphicBuffer(
- mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
+ mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
}
// OutputBuffersArray
@@ -1176,7 +1177,6 @@
void OutputBuffersArray::transferFrom(OutputBuffers* source) {
mFormat = source->mFormat;
mSkipCutBuffer = source->mSkipCutBuffer;
- mUnreportedFormat = source->mUnreportedFormat;
mPending = std::move(source->mPending);
mReorderStash = std::move(source->mReorderStash);
mDepth = source->mDepth;
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index c383a7c..995d3a4 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -86,6 +86,9 @@
// Format to be used for creating MediaCodec-facing buffers.
sp<AMessage> mFormat;
+ sp<ABuffer> mLastImageData;
+ sp<AMessage> mFormatWithImageData;
+
private:
DISALLOW_EVIL_CONSTRUCTORS(CCodecBuffers);
};
@@ -215,10 +218,8 @@
/**
* Update SkipCutBuffer from format. The @p format must not be null.
- * @p notify determines whether the format comes with a buffer that should
- * be reported to the client or not.
*/
- void updateSkipCutBuffer(const sp<AMessage> &format, bool notify = true);
+ void updateSkipCutBuffer(const sp<AMessage> &format);
/**
* Output Stash
@@ -392,9 +393,6 @@
// Output stash
- // Output format that has not been made available to the client.
- sp<AMessage> mUnreportedFormat;
-
// Struct for an entry in the output stash (mPending and mReorderStash)
struct StashEntry {
inline StashEntry()
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 96f86e8..ad28545 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -18,11 +18,13 @@
#define LOG_TAG "CCodecConfig"
#include <cutils/properties.h>
#include <log/log.h>
+#include <utils/NativeHandle.h>
#include <C2Component.h>
#include <C2Param.h>
#include <util/C2InterfaceHelper.h>
+#include <media/stagefright/CodecBase.h>
#include <media/stagefright/MediaCodecConstants.h>
#include "CCodecConfig.h"
@@ -289,8 +291,8 @@
std::vector<std::string> getPathsForDomain(
Domain any, Domain all = Domain::ALL) const {
std::vector<std::string> res;
- for (const std::pair<std::string, std::vector<ConfigMapper>> &el : mConfigMappers) {
- for (const ConfigMapper &cm : el.second) {
+ for (const auto &[key, mappers] : mConfigMappers) {
+ for (const ConfigMapper &cm : mappers) {
ALOGV("filtering %s %x %x %x %x", cm.path().c_str(), cm.domain(), any,
(cm.domain() & any), (cm.domain() & any & all));
if ((cm.domain() & any) && ((cm.domain() & any & all) == (any & all))) {
@@ -321,7 +323,8 @@
CCodecConfig::CCodecConfig()
: mInputFormat(new AMessage),
mOutputFormat(new AMessage),
- mUsingSurface(false) { }
+ mUsingSurface(false),
+ mTunneled(false) { }
void CCodecConfig::initializeStandardParams() {
typedef Domain D;
@@ -415,19 +418,38 @@
add(ConfigMapper("color-matrix", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "matrix")
.limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & (D::CONFIG | D::PARAM)));
+ // read back default for decoders. This is needed in case the component does not support
+ // color aspects. In that case, these values get copied to color-* keys.
+ // TRICKY: We read these values at raw port, since that's where we want to read these.
+ add(ConfigMapper("default-color-range", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "range")
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ)
+ .withC2Mappers<C2Color::range_t>());
+ add(ConfigMapper("default-color-transfer", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "transfer")
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ)
+ .withC2Mappers<C2Color::transfer_t>());
+ add(ConfigMapper("default-color-primaries", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "primaries")
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ));
+ add(ConfigMapper("default-color-matrix", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "matrix")
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ));
+
// read back final for decoder output (also, configure final aspects as well. This should be
// overwritten based on coded/default values if component supports color aspects, but is used
// as final values if component does not support aspects at all)
add(ConfigMapper(KEY_COLOR_RANGE, C2_PARAMKEY_COLOR_ASPECTS, "range")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW)
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ)
.withC2Mappers<C2Color::range_t>());
add(ConfigMapper(KEY_COLOR_TRANSFER, C2_PARAMKEY_COLOR_ASPECTS, "transfer")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW)
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ)
.withC2Mappers<C2Color::transfer_t>());
add(ConfigMapper("color-primaries", C2_PARAMKEY_COLOR_ASPECTS, "primaries")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW));
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ));
add(ConfigMapper("color-matrix", C2_PARAMKEY_COLOR_ASPECTS, "matrix")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW));
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ));
+
+ // configure transfer request
+ add(ConfigMapper("color-transfer-request", C2_PARAMKEY_COLOR_ASPECTS, "transfer")
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::CONFIG)
+ .withC2Mappers<C2Color::transfer_t>());
// configure source aspects for encoders and read them back on the coded(!) port.
// This is to ensure muxing the desired aspects into the container.
@@ -488,7 +510,7 @@
add(ConfigMapper(std::string(KEY_FEATURE_) + FEATURE_SecurePlayback,
C2_PARAMKEY_SECURE_MODE, "value"));
- add(ConfigMapper(KEY_PREPEND_HEADERS_TO_SYNC_FRAMES,
+ add(ConfigMapper(KEY_PREPEND_HEADER_TO_SYNC_FRAMES,
C2_PARAMKEY_PREPEND_HEADER_MODE, "value")
.limitTo(D::ENCODER & D::VIDEO)
.withMappers([](C2Value v) -> C2Value {
@@ -512,7 +534,7 @@
return C2Value();
}));
// remove when codecs switch to PARAMKEY
- deprecated(ConfigMapper(KEY_PREPEND_HEADERS_TO_SYNC_FRAMES,
+ deprecated(ConfigMapper(KEY_PREPEND_HEADER_TO_SYNC_FRAMES,
"coding.add-csd-to-sync-frames", "value")
.limitTo(D::ENCODER & D::VIDEO));
// convert to timestamp base
@@ -765,21 +787,13 @@
// convert to compression type and add default
add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
- .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
- .withMappers([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM))
+ .withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
value = property_get_int32(PROP_DRC_OVERRIDE_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
}
return value == 1 ? C2Config::DRC_COMPRESSION_HEAVY : C2Config::DRC_COMPRESSION_LIGHT;
- },[](C2Value v) -> C2Value {
- int32_t value;
- if (v.get(&value)) {
- return value;
- }
- else {
- return C2Value();
- }
}));
// convert to dBFS and add default
@@ -1009,11 +1023,14 @@
new C2StreamPixelAspectRatioInfo::output(0u, 1u, 1u),
C2_PARAMKEY_PIXEL_ASPECT_RATIO);
addLocalParam(new C2StreamRotationInfo::output(0u, 0), C2_PARAMKEY_ROTATION);
- addLocalParam(new C2StreamColorAspectsInfo::output(0u), C2_PARAMKEY_COLOR_ASPECTS);
+ addLocalParam(
+ new C2StreamColorAspectsTuning::output(0u),
+ C2_PARAMKEY_DEFAULT_COLOR_ASPECTS);
addLocalParam<C2StreamDataSpaceInfo::output>(C2_PARAMKEY_DATA_SPACE);
addLocalParam<C2StreamHdrStaticInfo::output>(C2_PARAMKEY_HDR_STATIC_INFO);
- addLocalParam(new C2StreamSurfaceScalingInfo::output(0u, VIDEO_SCALING_MODE_SCALE_TO_FIT),
- C2_PARAMKEY_SURFACE_SCALING_MODE);
+ addLocalParam(
+ new C2StreamSurfaceScalingInfo::output(0u, VIDEO_SCALING_MODE_SCALE_TO_FIT),
+ C2_PARAMKEY_SURFACE_SCALING_MODE);
} else {
addLocalParam(new C2StreamColorAspectsInfo::input(0u), C2_PARAMKEY_COLOR_ASPECTS);
}
@@ -1045,7 +1062,7 @@
std::vector<std::string> keys;
mParamUpdater->getKeysForParamIndex(desc->index(), &keys);
for (const std::string &key : keys) {
- mVendorParamIndices.insert_or_assign(key, desc->index());
+ mVendorParams.insert_or_assign(key, desc);
}
}
}
@@ -1112,6 +1129,12 @@
insertion.first->second = std::move(p);
}
}
+ if (mInputSurface
+ && (domain & mOutputDomain)
+ && mInputSurfaceDataspace != mInputSurface->getDataspace()) {
+ changed = true;
+ mInputSurfaceDataspace = mInputSurface->getDataspace();
+ }
ALOGV("updated configuration has %zu params (%s)", mCurrentConfig.size(),
changed ? "CHANGED" : "no change");
@@ -1151,14 +1174,11 @@
bool changed = false;
if (domain & mInputDomain) {
- sp<AMessage> oldFormat = mInputFormat;
- mInputFormat = mInputFormat->dup(); // trigger format changed
+ sp<AMessage> oldFormat = mInputFormat->dup();
mInputFormat->extend(getFormatForDomain(reflected, mInputDomain));
if (mInputFormat->countEntries() != oldFormat->countEntries()
|| mInputFormat->changesFrom(oldFormat)->countEntries() > 0) {
changed = true;
- } else {
- mInputFormat = oldFormat; // no change
}
}
if (domain & mOutputDomain) {
@@ -1180,8 +1200,8 @@
const ReflectedParamUpdater::Dict &reflected,
Domain portDomain) const {
sp<AMessage> msg = new AMessage;
- for (const std::pair<std::string, std::vector<ConfigMapper>> &el : mStandardParams->getKeys()) {
- for (const ConfigMapper &cm : el.second) {
+ for (const auto &[key, mappers] : mStandardParams->getKeys()) {
+ for (const ConfigMapper &cm : mappers) {
if ((cm.domain() & portDomain) == 0 // input-output-coded-raw
|| (cm.domain() & mDomain) != mDomain // component domain + kind (these must match)
|| (cm.domain() & IS_READ) == 0) {
@@ -1205,26 +1225,26 @@
ALOGD("unexpected untyped query value for key: %s", cm.path().c_str());
continue;
}
- msg->setItem(el.first.c_str(), item);
+ msg->setItem(key.c_str(), item);
}
}
bool input = (portDomain & Domain::IS_INPUT);
std::vector<std::string> vendorKeys;
- for (const std::pair<std::string, ReflectedParamUpdater::Value> &entry : reflected) {
- auto it = mVendorParamIndices.find(entry.first);
- if (it == mVendorParamIndices.end()) {
+ for (const auto &[key, value] : reflected) {
+ auto it = mVendorParams.find(key);
+ if (it == mVendorParams.end()) {
continue;
}
- if (mSubscribedIndices.count(it->second) == 0) {
+ C2Param::Index index = it->second->index();
+ if (mSubscribedIndices.count(index) == 0) {
continue;
}
// For vendor parameters, we only care about direction
- if ((input && !it->second.forInput())
- || (!input && !it->second.forOutput())) {
+ if ((input && !index.forInput())
+ || (!input && !index.forOutput())) {
continue;
}
- const ReflectedParamUpdater::Value &value = entry.second;
C2Value c2Value;
sp<ABuffer> bufValue;
AString strValue;
@@ -1236,10 +1256,10 @@
} else if (value.find(&strValue)) {
item.set(strValue);
} else {
- ALOGD("unexpected untyped query value for key: %s", entry.first.c_str());
+ ALOGD("unexpected untyped query value for key: %s", key.c_str());
continue;
}
- msg->setItem(entry.first.c_str(), item);
+ msg->setItem(key.c_str(), item);
}
{ // convert from Codec 2.0 rect to MediaFormat rect and add crop rect if not present
@@ -1300,8 +1320,37 @@
}
{ // convert color info
+ // move default color to color aspect if not read from the component
+ int32_t tmp;
+ int32_t range;
+ if (msg->findInt32("default-color-range", &range)) {
+ if (!msg->findInt32(KEY_COLOR_RANGE, &tmp)) {
+ msg->setInt32(KEY_COLOR_RANGE, range);
+ }
+ msg->removeEntryAt(msg->findEntryByName("default-color-range"));
+ }
+ int32_t transfer;
+ if (msg->findInt32("default-color-transfer", &transfer)) {
+ if (!msg->findInt32(KEY_COLOR_TRANSFER, &tmp)) {
+ msg->setInt32(KEY_COLOR_TRANSFER, transfer);
+ }
+ msg->removeEntryAt(msg->findEntryByName("default-color-transfer"));
+ }
C2Color::primaries_t primaries;
+ if (msg->findInt32("default-color-primaries", (int32_t*)&primaries)) {
+ if (!msg->findInt32("color-primaries", &tmp)) {
+ msg->setInt32("color-primaries", primaries);
+ }
+ msg->removeEntryAt(msg->findEntryByName("default-color-primaries"));
+ }
C2Color::matrix_t matrix;
+ if (msg->findInt32("default-color-matrix", (int32_t*)&matrix)) {
+ if (!msg->findInt32("color-matrix", &tmp)) {
+ msg->setInt32("color-matrix", matrix);
+ }
+ msg->removeEntryAt(msg->findEntryByName("default-color-matrix"));
+ }
+
if (msg->findInt32("color-primaries", (int32_t*)&primaries)
&& msg->findInt32("color-matrix", (int32_t*)&matrix)) {
int32_t standard;
@@ -1314,7 +1363,6 @@
msg->removeEntryAt(msg->findEntryByName("color-matrix"));
}
-
// calculate dataspace for raw graphic buffers if not specified by component, or if
// using surface with unspecified aspects (as those must be defaulted which may change
// the dataspace)
@@ -1352,6 +1400,23 @@
}
}
+ if (mInputSurface) {
+ android_dataspace dataspace = mInputSurface->getDataspace();
+ ColorUtils::convertDataSpaceToV0(dataspace);
+ int32_t standard;
+ ColorUtils::getColorConfigFromDataSpace(dataspace, &range, &standard, &transfer);
+ if (range != 0) {
+ msg->setInt32(KEY_COLOR_RANGE, range);
+ }
+ if (standard != 0) {
+ msg->setInt32(KEY_COLOR_STANDARD, standard);
+ }
+ if (transfer != 0) {
+ msg->setInt32(KEY_COLOR_TRANSFER, transfer);
+ }
+ msg->setInt32("android._dataspace", dataspace);
+ }
+
// HDR static info
C2HdrStaticMetadataStruct hdr;
@@ -1393,22 +1458,22 @@
meta.sType1.mMinDisplayLuminance = hdr.mastering.minLuminance / 0.0001 + 0.5;
meta.sType1.mMaxContentLightLevel = hdr.maxCll + 0.5;
meta.sType1.mMaxFrameAverageLightLevel = hdr.maxFall + 0.5;
- msg->removeEntryAt(msg->findEntryByName("smpte2086.red.x"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.red.y"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.green.x"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.green.y"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.blue.x"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.blue.y"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.white.x"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.white.y"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.max-luminance"));
- msg->removeEntryAt(msg->findEntryByName("smpte2086.min-luminance"));
- msg->removeEntryAt(msg->findEntryByName("cta861.max-cll"));
- msg->removeEntryAt(msg->findEntryByName("cta861.max-fall"));
msg->setBuffer(KEY_HDR_STATIC_INFO, ABuffer::CreateAsCopy(&meta, sizeof(meta)));
} else {
ALOGD("found invalid HDR static metadata %s", msg->debugString(8).c_str());
}
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.red.x"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.red.y"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.green.x"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.green.y"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.blue.x"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.blue.y"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.white.x"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.white.y"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.max-luminance"));
+ msg->removeEntryAt(msg->findEntryByName("smpte2086.min-luminance"));
+ msg->removeEntryAt(msg->findEntryByName("cta861.max-cll"));
+ msg->removeEntryAt(msg->findEntryByName("cta861.max-fall"));
}
}
@@ -1643,8 +1708,8 @@
}
}
}
- ALOGV("filtered %s to %s", params->debugString(4).c_str(),
- filtered.debugString(4).c_str());
+ ALOGV("filter src msg %s", params->debugString(4).c_str());
+ ALOGV("filter dst params %s", filtered.debugString(4).c_str());
return filtered;
}
@@ -1769,8 +1834,81 @@
status_t CCodecConfig::subscribeToAllVendorParams(
const std::shared_ptr<Codec2Client::Configurable> &configurable,
c2_blocking_t blocking) {
- for (const std::pair<std::string, C2Param::Index> &entry : mVendorParamIndices) {
- mSubscribedIndices.insert(entry.second);
+ for (const auto &[path, desc] : mVendorParams) {
+ mSubscribedIndices.insert(desc->index());
+ }
+ return subscribeToConfigUpdate(configurable, {}, blocking);
+}
+
+status_t CCodecConfig::querySupportedParameters(std::vector<std::string> *names) {
+ if (!names) {
+ return BAD_VALUE;
+ }
+ names->clear();
+ // TODO: expand to standard params
+ for (const auto &[key, desc] : mVendorParams) {
+ names->push_back(key);
+ }
+ return OK;
+}
+
+status_t CCodecConfig::describe(const std::string &name, CodecParameterDescriptor *desc) {
+ if (!desc) {
+ return BAD_VALUE;
+ }
+ // TODO: expand to standard params
+ desc->name = name;
+ switch (mParamUpdater->getTypeForKey(name)) {
+ case C2FieldDescriptor::INT32:
+ case C2FieldDescriptor::UINT32:
+ case C2FieldDescriptor::CNTR32:
+ desc->type = AMessage::kTypeInt32;
+ return OK;
+ case C2FieldDescriptor::INT64:
+ case C2FieldDescriptor::UINT64:
+ case C2FieldDescriptor::CNTR64:
+ desc->type = AMessage::kTypeInt64;
+ return OK;
+ case C2FieldDescriptor::FLOAT:
+ desc->type = AMessage::kTypeFloat;
+ return OK;
+ case C2FieldDescriptor::STRING:
+ desc->type = AMessage::kTypeString;
+ return OK;
+ case C2FieldDescriptor::BLOB:
+ desc->type = AMessage::kTypeBuffer;
+ return OK;
+ default:
+ return NAME_NOT_FOUND;
+ }
+}
+
+status_t CCodecConfig::subscribeToVendorConfigUpdate(
+ const std::shared_ptr<Codec2Client::Configurable> &configurable,
+ const std::vector<std::string> &names,
+ c2_blocking_t blocking) {
+ for (const std::string &name : names) {
+ auto it = mVendorParams.find(name);
+ if (it == mVendorParams.end()) {
+ ALOGD("%s is not a recognized vendor parameter; ignored.", name.c_str());
+ continue;
+ }
+ mSubscribedIndices.insert(it->second->index());
+ }
+ return subscribeToConfigUpdate(configurable, {}, blocking);
+}
+
+status_t CCodecConfig::unsubscribeFromVendorConfigUpdate(
+ const std::shared_ptr<Codec2Client::Configurable> &configurable,
+ const std::vector<std::string> &names,
+ c2_blocking_t blocking) {
+ for (const std::string &name : names) {
+ auto it = mVendorParams.find(name);
+ if (it == mVendorParams.end()) {
+ ALOGD("%s is not a recognized vendor parameter; ignored.", name.c_str());
+ continue;
+ }
+ mSubscribedIndices.erase(it->second->index());
}
return subscribeToConfigUpdate(configurable, {}, blocking);
}
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 2895746..417b773 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -35,6 +35,8 @@
namespace android {
struct AMessage;
+struct CodecParameterDescriptor;
+class NativeHandle;
struct StandardParams;
/**
@@ -123,6 +125,7 @@
std::shared_ptr<InputSurfaceWrapper> mInputSurface;
std::unique_ptr<InputSurfaceWrapper::Config> mISConfig;
+ android_dataspace mInputSurfaceDataspace;
/// the current configuration. Updated after configure() and based on configUpdate in
/// onWorkDone
@@ -136,11 +139,15 @@
/// For now support a validation function.
std::map<C2Param::Index, LocalParamValidator> mLocalParams;
- /// Vendor field name -> index map.
- std::map<std::string, C2Param::Index> mVendorParamIndices;
+ /// Vendor field name -> desc map.
+ std::map<std::string, std::shared_ptr<C2ParamDescriptor>> mVendorParams;
std::set<std::string> mLastConfig;
+ /// Tunneled codecs
+ bool mTunneled;
+ sp<NativeHandle> mSidebandHandle;
+
CCodecConfig();
/// initializes the members required to manage the format: descriptors, reflector,
@@ -321,6 +328,41 @@
return Watcher<T>(index, this);
}
+ /**
+ * Queries supported parameters and put the keys to |names|.
+ * TODO: currently this method queries vendor parameter keys only.
+ *
+ * \return OK if successful.
+ * BAD_VALUE if |names| is nullptr.
+ */
+ status_t querySupportedParameters(std::vector<std::string> *names);
+
+ /**
+ * Describe the parameter with |name|, filling the information into |desc|
+ * TODO: currently this method works only for vendor parameters.
+ *
+ * \return OK if successful.
+ * BAD_VALUE if |desc| is nullptr.
+ * NAME_NOT_FOUND if |name| is not a recognized parameter name.
+ */
+ status_t describe(const std::string &name, CodecParameterDescriptor *desc);
+
+ /**
+ * Find corresponding indices for |names| and subscribe to them.
+ */
+ status_t subscribeToVendorConfigUpdate(
+ const std::shared_ptr<Codec2Client::Configurable> &configurable,
+ const std::vector<std::string> &names,
+ c2_blocking_t blocking = C2_DONT_BLOCK);
+
+ /**
+ * Find corresponding indices for |names| and unsubscribe from them.
+ */
+ status_t unsubscribeFromVendorConfigUpdate(
+ const std::shared_ptr<Codec2Client::Configurable> &configurable,
+ const std::vector<std::string> &names,
+ c2_blocking_t blocking = C2_DONT_BLOCK);
+
private:
/// initializes the standard MediaCodec to Codec 2.0 params mapping
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 25e7da9..fc4ee51 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2Buffer"
#include <utils/Log.h>
+#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <android/hardware/drm/1.0/types.h>
#include <hidlmemory/FrameworkUtils.h>
@@ -211,21 +212,24 @@
* Creates a C2GraphicView <=> MediaImage converter
*
* \param view C2GraphicView object
- * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
- * an attempt is made to simply represent the graphic view as a flexible SDK format
- * without a memcpy)
+ * \param format buffer format
* \param copy whether the converter is used for copy or not
*/
GraphicView2MediaImageConverter(
- const C2GraphicView &view, int32_t colorFormat, bool copy)
+ const C2GraphicView &view, const sp<AMessage> &format, bool copy)
: mInitCheck(NO_INIT),
mView(view),
mWidth(view.width()),
mHeight(view.height()),
- mColorFormat(colorFormat),
mAllocatedDepth(0),
mBackBufferSize(0),
mMediaImage(new ABuffer(sizeof(MediaImage2))) {
+ if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
+ mClientColorFormat = COLOR_FormatYUV420Flexible;
+ }
+ if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
+ mComponentColorFormat = COLOR_FormatYUV420Flexible;
+ }
if (view.error() != C2_OK) {
ALOGD("Converter: view.error() = %d", view.error());
mInitCheck = BAD_VALUE;
@@ -246,68 +250,57 @@
uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
uint32_t vStride = align(view.crop().height, 2);
+ bool tryWrapping = !copy;
+
switch (layout.type) {
- case C2PlanarLayout::TYPE_YUV:
+ case C2PlanarLayout::TYPE_YUV: {
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
if (layout.numPlanes != 3) {
ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
mInitCheck = BAD_VALUE;
return;
}
- if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y
- || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB
- || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR
- || layout.planes[0].colSampling != 1
- || layout.planes[0].rowSampling != 1
- || layout.planes[1].colSampling != 2
- || layout.planes[1].rowSampling != 2
- || layout.planes[2].colSampling != 2
- || layout.planes[2].rowSampling != 2) {
- ALOGD("Converter: not YUV420 for YUV layout");
+ C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+ if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
+ || uPlane.channel != C2PlaneInfo::CHANNEL_CB
+ || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
+ ALOGD("Converter: not YUV layout");
mInitCheck = BAD_VALUE;
return;
}
- switch (mColorFormat) {
- case COLOR_FormatYUV420Flexible:
- if (!copy) {
- // try to map directly. check if the planes are near one another
- const uint8_t *minPtr = mView.data()[0];
- const uint8_t *maxPtr = mView.data()[0];
- int32_t planeSize = 0;
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- ssize_t minOffset = plane.minOffset(mWidth, mHeight);
- ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
- if (minPtr > mView.data()[i] + minOffset) {
- minPtr = mView.data()[i] + minOffset;
- }
- if (maxPtr < mView.data()[i] + maxOffset) {
- maxPtr = mView.data()[i] + maxOffset;
- }
- planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
- / plane.rowSampling / plane.colSampling
- * divUp(mAllocatedDepth, 8u);
- }
-
- if ((maxPtr - minPtr + 1) <= planeSize) {
- // FIXME: this is risky as reading/writing data out of bound results
- // in an undefined behavior, but gralloc does assume a
- // contiguous mapping
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
- mediaImage->mPlane[i].mColInc = plane.colInc;
- mediaImage->mPlane[i].mRowInc = plane.rowInc;
- mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
- }
- mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
- maxPtr - minPtr + 1);
- break;
- }
+ bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
+ && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+ && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
+ if (yuv420888) {
+ for (uint32_t i = 0; i < 3; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
+ yuv420888 = false;
+ break;
}
- [[fallthrough]];
-
+ }
+ yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
+ }
+ int32_t copyFormat = mClientColorFormat;
+ if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
+ if (uPlane.colInc == 2 && vPlane.colInc == 2
+ && yPlane.rowInc == uPlane.rowInc) {
+ copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
+ } else if (uPlane.colInc == 1 && vPlane.colInc == 1
+ && yPlane.rowInc == uPlane.rowInc * 2) {
+ copyFormat = COLOR_FormatYUV420PackedPlanar;
+ }
+ }
+ ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
+ "v:{colInc=%d rowInc=%d}",
+ mClientColorFormat,
+ yPlane.colInc, yPlane.rowInc,
+ uPlane.colInc, uPlane.rowInc,
+ vPlane.colInc, vPlane.rowInc);
+ switch (copyFormat) {
+ case COLOR_FormatYUV420Flexible:
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420PackedPlanar:
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
@@ -327,6 +320,13 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+ if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+ tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
+ && yPlane.rowInc == uPlane.rowInc * 2
+ && view.data()[0] < view.data()[1]
+ && view.data()[1] < view.data()[2];
+ }
break;
case COLOR_FormatYUV420SemiPlanar:
@@ -348,64 +348,165 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+ if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+ tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
+ && yPlane.rowInc == uPlane.rowInc
+ && view.data()[0] < view.data()[1]
+ && view.data()[1] < view.data()[2];
+ }
break;
- default:
- ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
+ case COLOR_FormatYUVP010:
+ mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+ mediaImage->mPlane[mediaImage->Y].mColInc = 2;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
+ mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
+
+ mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride * 2;
+ mediaImage->mPlane[mediaImage->U].mColInc = 4;
+ mediaImage->mPlane[mediaImage->U].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
+ mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
+
+ mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 2 + 2;
+ mediaImage->mPlane[mediaImage->V].mColInc = 4;
+ mediaImage->mPlane[mediaImage->V].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
+ mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+ if (tryWrapping) {
+ tryWrapping = yPlane.allocatedDepth == 16
+ && uPlane.allocatedDepth == 16
+ && vPlane.allocatedDepth == 16
+ && yPlane.bitDepth == 10
+ && uPlane.bitDepth == 10
+ && vPlane.bitDepth == 10
+ && yPlane.rightShift == 6
+ && uPlane.rightShift == 6
+ && vPlane.rightShift == 6
+ && yPlane.rowSampling == 1 && yPlane.colSampling == 1
+ && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+ && vPlane.rowSampling == 2 && vPlane.colSampling == 2
+ && yPlane.colInc == 2
+ && uPlane.colInc == 4
+ && vPlane.colInc == 4
+ && yPlane.rowInc == uPlane.rowInc
+ && yPlane.rowInc == vPlane.rowInc;
+ }
+ break;
+
+ default: {
+ // default to fully planar format --- this will be overridden if wrapping
+ // TODO: keep interleaved format
+ int32_t colInc = divUp(mAllocatedDepth, 8u);
+ int32_t rowInc = stride * colInc / yPlane.colSampling;
+ mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+ mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
+ mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
+ int32_t offset = rowInc * vStride / yPlane.rowSampling;
+
+ rowInc = stride * colInc / uPlane.colSampling;
+ mediaImage->mPlane[mediaImage->U].mOffset = offset;
+ mediaImage->mPlane[mediaImage->U].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
+ mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
+ offset += rowInc * vStride / uPlane.rowSampling;
+
+ rowInc = stride * colInc / vPlane.colSampling;
+ mediaImage->mPlane[mediaImage->V].mOffset = offset;
+ mediaImage->mPlane[mediaImage->V].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
+ mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
+ break;
+ }
}
break;
+ }
+
case C2PlanarLayout::TYPE_YUVA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
- // We don't have an SDK YUVA format
- ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
- mInitCheck = BAD_VALUE;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for YUVA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
return;
case C2PlanarLayout::TYPE_RGB:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
- switch (mColorFormat) {
- // TODO media image
- case COLOR_FormatRGBFlexible:
- case COLOR_Format24bitBGR888:
- case COLOR_Format24bitRGB888:
- break;
- default:
- ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (layout.numPlanes != 3) {
- ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
- mInitCheck = BAD_VALUE;
- return;
- }
- break;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ // TODO: support MediaImage layout
+ return;
case C2PlanarLayout::TYPE_RGBA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
- switch (mColorFormat) {
- // TODO media image
- case COLOR_FormatRGBAFlexible:
- case COLOR_Format32bitABGR8888:
- case COLOR_Format32bitARGB8888:
- case COLOR_Format32bitBGRA8888:
- break;
- default:
- ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (layout.numPlanes != 4) {
- ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
- mInitCheck = BAD_VALUE;
- return;
- }
- break;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ // TODO: support MediaImage layout
+ return;
default:
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
- ALOGD("Unknown layout");
- mInitCheck = BAD_VALUE;
- return;
+ if (layout.numPlanes == 1) {
+ const C2PlaneInfo &plane = layout.planes[0];
+ if (plane.colInc < 0 || plane.rowInc < 0) {
+ // Copy-only if we have negative colInc/rowInc
+ tryWrapping = false;
+ }
+ mediaImage->mPlane[0].mOffset = 0;
+ mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
+ mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
+ mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
+ mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
+ } else {
+ ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ return;
+ }
+ break;
+ }
+ if (tryWrapping) {
+ // try to map directly. check if the planes are near one another
+ const uint8_t *minPtr = mView.data()[0];
+ const uint8_t *maxPtr = mView.data()[0];
+ int32_t planeSize = 0;
+ for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
+ ssize_t minOffset = plane.minOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ ssize_t maxOffset = plane.maxOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ if (minPtr > mView.data()[i] + minOffset) {
+ minPtr = mView.data()[i] + minOffset;
+ }
+ if (maxPtr < mView.data()[i] + maxOffset) {
+ maxPtr = mView.data()[i] + maxOffset;
+ }
+ planeSize += planeStride * divUp(mAllocatedDepth, 8u)
+ * align(mHeight, 64) / plane.rowSampling;
+ }
+
+ if ((maxPtr - minPtr + 1) <= planeSize) {
+ // FIXME: this is risky as reading/writing data out of bound results
+ // in an undefined behavior, but gralloc does assume a
+ // contiguous mapping
+ for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
+ mediaImage->mPlane[i].mColInc = plane.colInc;
+ mediaImage->mPlane[i].mRowInc = plane.rowInc;
+ mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
+ mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
+ }
+ mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
+ maxPtr - minPtr + 1);
+ ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
+ }
}
mediaImage->mNumPlanes = layout.numPlanes;
mediaImage->mWidth = view.crop().width;
@@ -428,12 +529,12 @@
return;
}
if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
- ALOGV("different allocatedDepth/bitDepth per plane unsupported");
+ ALOGD("different allocatedDepth/bitDepth per plane unsupported");
mInitCheck = BAD_VALUE;
return;
}
bufferSize += stride * vStride
- / plane.rowSampling / plane.colSampling;
+ / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
}
mBackBufferSize = bufferSize;
@@ -488,7 +589,8 @@
const C2GraphicView mView;
uint32_t mWidth;
uint32_t mHeight;
- int32_t mColorFormat; ///< SDK color format for MediaImage
+ int32_t mClientColorFormat; ///< SDK color format for MediaImage
+ int32_t mComponentColorFormat; ///< SDK color format from component
sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
uint32_t mAllocatedDepth;
uint32_t mBackBufferSize;
@@ -517,10 +619,7 @@
return nullptr;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- (void)format->findInt32("color-format", &colorFormat);
-
- GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
+ GraphicView2MediaImageConverter converter(view, format, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -578,7 +677,23 @@
}
std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
-#ifndef __LP64__
+#ifdef __LP64__
+ static std::once_flag s_checkOnce;
+ static bool s_64bitonly {false};
+ std::call_once(s_checkOnce, [&](){
+ const std::string abi32list =
+ ::android::base::GetProperty("ro.product.cpu.abilist32", "");
+ if (abi32list.empty()) {
+ s_64bitonly = true;
+ }
+ });
+
+ if (!s_64bitonly) {
+ ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object");
+ return nullptr;
+ }
+#endif
+
VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
if (buffer == nullptr) {
@@ -611,10 +726,6 @@
}
return C2Buffer::CreateGraphicBuffer(
block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
-#else
- ALOGE("GraphicMetadataBuffer does not work on 64-bit arch");
- return nullptr;
-#endif
}
// ConstGraphicBlockBuffer
@@ -634,10 +745,7 @@
buffer->data().graphicBlocks()[0].map().get()));
std::unique_ptr<const C2GraphicView> holder;
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- (void)format->findInt32("color-format", &colorFormat);
-
- GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
+ GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -729,12 +837,11 @@
return false;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- // FIXME: format() is not const, but we cannot change it, so do a const cast here
- const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
-
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
+ buffer->data().graphicBlocks()[0].map().get(),
+ // FIXME: format() is not const, but we cannot change it, so do a const cast here
+ const_cast<ConstGraphicBlockBuffer *>(this)->format(),
+ true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
return false;
@@ -752,11 +859,9 @@
setRange(0, 0);
return true;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- format()->findInt32("color-format", &colorFormat);
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
+ buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
return false;
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index b112249..a26f89e 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -103,11 +103,16 @@
c2_status_t err1 = intf->querySupportedParams(¶mDescs);
if (err1 == C2_OK) {
for (const std::shared_ptr<C2ParamDescriptor> &desc : paramDescs) {
- switch ((uint32_t)desc->index()) {
- case C2StreamHdr10PlusInfo::output::PARAM_TYPE:
+ C2Param::Type type = desc->index();
+ // only consider supported parameters on raw ports
+ if (!(encoder ? type.forInput() : type.forOutput())) {
+ continue;
+ }
+ switch (type.coreIndex()) {
+ case C2StreamHdr10PlusInfo::CORE_INDEX:
supportsHdr10Plus = true;
break;
- case C2StreamHdrStaticInfo::output::PARAM_TYPE:
+ case C2StreamHdrStaticInfo::CORE_INDEX:
supportsHdr = true;
break;
default:
diff --git a/media/codec2/sfplugin/FrameReassembler.cpp b/media/codec2/sfplugin/FrameReassembler.cpp
new file mode 100644
index 0000000..f8e6937
--- /dev/null
+++ b/media/codec2/sfplugin/FrameReassembler.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "FrameReassembler"
+
+#include <log/log.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+
+#include "FrameReassembler.h"
+
+namespace android {
+
+static constexpr uint64_t kToleranceUs = 1000; // 1ms
+
+FrameReassembler::FrameReassembler()
+ : mUsage{0, 0},
+ mSampleRate(0u),
+ mChannelCount(0u),
+ mEncoding(C2Config::PCM_16),
+ mCurrentOrdinal({0, 0, 0}) {
+}
+
+void FrameReassembler::init(
+ const std::shared_ptr<C2BlockPool> &pool,
+ C2MemoryUsage usage,
+ uint32_t frameSize,
+ uint32_t sampleRate,
+ uint32_t channelCount,
+ C2Config::pcm_encoding_t encoding) {
+ mBlockPool = pool;
+ mUsage = usage;
+ mFrameSize = frameSize;
+ mSampleRate = sampleRate;
+ mChannelCount = channelCount;
+ mEncoding = encoding;
+}
+
+void FrameReassembler::updateFrameSize(uint32_t frameSize) {
+ finishCurrentBlock(&mPendingWork);
+ mFrameSize = frameSize;
+}
+
+void FrameReassembler::updateSampleRate(uint32_t sampleRate) {
+ finishCurrentBlock(&mPendingWork);
+ mSampleRate = sampleRate;
+}
+
+void FrameReassembler::updateChannelCount(uint32_t channelCount) {
+ finishCurrentBlock(&mPendingWork);
+ mChannelCount = channelCount;
+}
+
+void FrameReassembler::updatePcmEncoding(C2Config::pcm_encoding_t encoding) {
+ finishCurrentBlock(&mPendingWork);
+ mEncoding = encoding;
+}
+
+void FrameReassembler::reset() {
+ flush();
+ mCurrentOrdinal = {0, 0, 0};
+ mBlockPool.reset();
+ mFrameSize.reset();
+ mSampleRate = 0u;
+ mChannelCount = 0u;
+ mEncoding = C2Config::PCM_16;
+}
+
+FrameReassembler::operator bool() const {
+ return mFrameSize.has_value();
+}
+
+c2_status_t FrameReassembler::process(
+ const sp<MediaCodecBuffer> &buffer,
+ std::list<std::unique_ptr<C2Work>> *items) {
+ int64_t timeUs;
+ if (buffer->size() == 0u
+ || !buffer->meta()->findInt64("timeUs", &timeUs)) {
+ return C2_BAD_VALUE;
+ }
+
+ items->splice(items->end(), mPendingWork);
+
+ // Fill mCurrentBlock
+ if (mCurrentBlock) {
+ // First check the timestamp
+ c2_cntr64_t endTimestampUs = mCurrentOrdinal.timestamp;
+ endTimestampUs += bytesToSamples(mWriteView->size()) * 1000000 / mSampleRate;
+ if (timeUs < endTimestampUs.peek()) {
+ uint64_t diffUs = (endTimestampUs - timeUs).peeku();
+ if (diffUs > kToleranceUs) {
+ // The timestamp is going back in time in large amount.
+ // TODO: b/145702136
+ ALOGW("timestamp going back in time! from %lld to %lld",
+ endTimestampUs.peekll(), (long long)timeUs);
+ }
+ } else { // timeUs >= endTimestampUs.peek()
+ uint64_t diffUs = (timeUs - endTimestampUs).peeku();
+ if (diffUs > kToleranceUs) {
+ // The timestamp is going forward; add silence as necessary.
+ size_t gapSamples = usToSamples(diffUs);
+ size_t remainingSamples =
+ (mWriteView->capacity() - mWriteView->size())
+ / mChannelCount / bytesPerSample();
+ if (gapSamples < remainingSamples) {
+ size_t gapBytes = gapSamples * mChannelCount * bytesPerSample();
+ memset(mWriteView->base() + mWriteView->size(), 0u, gapBytes);
+ mWriteView->setSize(mWriteView->size() + gapBytes);
+ } else {
+ finishCurrentBlock(items);
+ }
+ }
+ }
+ }
+
+ if (mCurrentBlock) {
+ // Append the data at the end of the current block
+ size_t copySize = std::min(
+ buffer->size(),
+ size_t(mWriteView->capacity() - mWriteView->size()));
+ memcpy(mWriteView->base() + mWriteView->size(), buffer->data(), copySize);
+ buffer->setRange(buffer->offset() + copySize, buffer->size() - copySize);
+ mWriteView->setSize(mWriteView->size() + copySize);
+ if (mWriteView->size() == mWriteView->capacity()) {
+ finishCurrentBlock(items);
+ }
+ timeUs += bytesToSamples(copySize) * 1000000 / mSampleRate;
+ }
+
+ if (buffer->size() > 0) {
+ mCurrentOrdinal.timestamp = timeUs;
+ }
+
+ size_t frameSizeBytes = mFrameSize.value() * mChannelCount * bytesPerSample();
+ while (buffer->size() > 0) {
+ LOG_ALWAYS_FATAL_IF(
+ mCurrentBlock,
+ "There's remaining data but the pending block is not filled & finished");
+ std::unique_ptr<C2Work> work(new C2Work);
+ c2_status_t err = mBlockPool->fetchLinearBlock(frameSizeBytes, mUsage, &mCurrentBlock);
+ if (err != C2_OK) {
+ return err;
+ }
+ size_t copySize = std::min(buffer->size(), frameSizeBytes);
+ mWriteView = mCurrentBlock->map().get();
+ if (mWriteView->error() != C2_OK) {
+ return mWriteView->error();
+ }
+ ALOGV("buffer={offset=%zu size=%zu) copySize=%zu",
+ buffer->offset(), buffer->size(), copySize);
+ memcpy(mWriteView->base(), buffer->data(), copySize);
+ mWriteView->setOffset(0u);
+ mWriteView->setSize(copySize);
+ buffer->setRange(buffer->offset() + copySize, buffer->size() - copySize);
+ if (copySize == frameSizeBytes) {
+ finishCurrentBlock(items);
+ }
+ }
+
+ int32_t eos = 0;
+ if (buffer->meta()->findInt32("eos", &eos) && eos) {
+ finishCurrentBlock(items);
+ }
+
+ return C2_OK;
+}
+
+void FrameReassembler::flush() {
+ mPendingWork.clear();
+ mWriteView.reset();
+ mCurrentBlock.reset();
+}
+
+uint64_t FrameReassembler::bytesToSamples(size_t numBytes) const {
+ return numBytes / mChannelCount / bytesPerSample();
+}
+
+size_t FrameReassembler::usToSamples(uint64_t us) const {
+ return (us * mChannelCount * mSampleRate / 1000000);
+}
+
+uint32_t FrameReassembler::bytesPerSample() const {
+ return (mEncoding == C2Config::PCM_8) ? 1
+ : (mEncoding == C2Config::PCM_16) ? 2
+ : (mEncoding == C2Config::PCM_FLOAT) ? 4 : 0;
+}
+
+void FrameReassembler::finishCurrentBlock(std::list<std::unique_ptr<C2Work>> *items) {
+ if (!mCurrentBlock) {
+ // No-op
+ return;
+ }
+ if (mWriteView->size() < mWriteView->capacity()) {
+ memset(mWriteView->base() + mWriteView->size(), 0u,
+ mWriteView->capacity() - mWriteView->size());
+ mWriteView->setSize(mWriteView->capacity());
+ }
+ std::unique_ptr<C2Work> work{std::make_unique<C2Work>()};
+ work->input.ordinal = mCurrentOrdinal;
+ work->input.buffers.push_back(C2Buffer::CreateLinearBuffer(
+ mCurrentBlock->share(0, mCurrentBlock->capacity(), C2Fence())));
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+ items->push_back(std::move(work));
+
+ ++mCurrentOrdinal.frameIndex;
+ mCurrentOrdinal.timestamp += mFrameSize.value() * 1000000 / mSampleRate;
+ mCurrentBlock.reset();
+ mWriteView.reset();
+}
+
+} // namespace android
diff --git a/media/codec2/sfplugin/FrameReassembler.h b/media/codec2/sfplugin/FrameReassembler.h
new file mode 100644
index 0000000..17ac06d
--- /dev/null
+++ b/media/codec2/sfplugin/FrameReassembler.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAME_REASSEMBLER_H_
+#define FRAME_REASSEMBLER_H_
+
+#include <set>
+#include <memory>
+
+#include <media/MediaCodecBuffer.h>
+
+#include <C2Config.h>
+#include <C2Work.h>
+
+namespace android {
+
+class FrameReassembler {
+public:
+ FrameReassembler();
+
+ void init(
+ const std::shared_ptr<C2BlockPool> &pool,
+ C2MemoryUsage usage,
+ uint32_t frameSize,
+ uint32_t sampleRate,
+ uint32_t channelCount,
+ C2Config::pcm_encoding_t encoding);
+ void updateFrameSize(uint32_t frameSize);
+ void updateSampleRate(uint32_t sampleRate);
+ void updateChannelCount(uint32_t channelCount);
+ void updatePcmEncoding(C2Config::pcm_encoding_t encoding);
+ void reset();
+ void flush();
+
+ explicit operator bool() const;
+
+ c2_status_t process(
+ const sp<MediaCodecBuffer> &buffer,
+ std::list<std::unique_ptr<C2Work>> *items);
+
+private:
+ std::shared_ptr<C2BlockPool> mBlockPool;
+ C2MemoryUsage mUsage;
+ std::optional<uint32_t> mFrameSize;
+ uint32_t mSampleRate;
+ uint32_t mChannelCount;
+ C2Config::pcm_encoding_t mEncoding;
+ std::list<std::unique_ptr<C2Work>> mPendingWork;
+ C2WorkOrdinalStruct mCurrentOrdinal;
+ std::shared_ptr<C2LinearBlock> mCurrentBlock;
+ std::optional<C2WriteView> mWriteView;
+
+ uint64_t bytesToSamples(size_t numBytes) const;
+ size_t usToSamples(uint64_t us) const;
+ uint32_t bytesPerSample() const;
+
+ void finishCurrentBlock(std::list<std::unique_ptr<C2Work>> *items);
+};
+
+} // namespace android
+
+#endif // FRAME_REASSEMBLER_H_
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index bb35763..3ddae01 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -106,6 +106,11 @@
*/
virtual void onInputBufferDone(c2_cntr64_t /* index */) {}
+ /**
+ * Returns dataspace information from GraphicBufferSource.
+ */
+ virtual android_dataspace getDataspace() { return mDataSpace; }
+
protected:
android_dataspace mDataSpace;
};
diff --git a/media/codec2/sfplugin/ReflectedParamUpdater.cpp b/media/codec2/sfplugin/ReflectedParamUpdater.cpp
index f39051b..d14b9b0 100644
--- a/media/codec2/sfplugin/ReflectedParamUpdater.cpp
+++ b/media/codec2/sfplugin/ReflectedParamUpdater.cpp
@@ -288,6 +288,20 @@
}
}
+C2FieldDescriptor::type_t ReflectedParamUpdater::getTypeForKey(
+ const std::string &key) const {
+ auto it = mMap.find(key);
+ if (it == mMap.end()) {
+ return C2FieldDescriptor::type_t(~0);
+ }
+
+ if (it->second.fieldDesc) {
+ return it->second.fieldDesc->type();
+ }
+ // whole param is exposed as a blob
+ return C2FieldDescriptor::BLOB;
+}
+
void ReflectedParamUpdater::updateParamsFromMessage(
const Dict ¶ms,
std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const {
diff --git a/media/codec2/sfplugin/ReflectedParamUpdater.h b/media/codec2/sfplugin/ReflectedParamUpdater.h
index 752c7e4..6dcf2a3 100644
--- a/media/codec2/sfplugin/ReflectedParamUpdater.h
+++ b/media/codec2/sfplugin/ReflectedParamUpdater.h
@@ -176,6 +176,14 @@
std::vector<std::string> *keys /* nonnull */) const;
/**
+ * Get field type for the given name
+ *
+ * \param key[in] field name
+ * \return type of the field, or type_t(~0) if not found.
+ */
+ C2FieldDescriptor::type_t getTypeForKey(const std::string &name) const;
+
+ /**
* Update C2Param objects from field name and value in AMessage object.
*
* \param params[in] Dict object with field name to value pairs.
diff --git a/media/codec2/sfplugin/include/media/stagefright/CCodec.h b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
index dbbb5d5..ec18128 100644
--- a/media/codec2/sfplugin/include/media/stagefright/CCodec.h
+++ b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
@@ -65,6 +65,12 @@
virtual void signalEndOfInputStream() override;
virtual void signalRequestIDRFrame() override;
+ virtual status_t querySupportedParameters(std::vector<std::string> *names) override;
+ virtual status_t describeParameter(
+ const std::string &name, CodecParameterDescriptor *desc) override;
+ virtual status_t subscribeToParameters(const std::vector<std::string> &names) override;
+ virtual status_t unsubscribeFromParameters(const std::vector<std::string> &names) override;
+
void initiateReleaseIfStuck();
void onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex);
@@ -126,6 +132,11 @@
const std::chrono::milliseconds &timeout,
const char *name);
+ status_t configureTunneledVideoPlayback(
+ const std::shared_ptr<Codec2Client::Component> comp,
+ sp<NativeHandle> *sidebandHandle,
+ const sp<AMessage> &msg);
+
enum {
kWhatAllocate,
kWhatConfigure,
diff --git a/media/codec2/sfplugin/tests/Android.bp b/media/codec2/sfplugin/tests/Android.bp
index 8d1a9c3..f9c7969 100644
--- a/media/codec2/sfplugin/tests/Android.bp
+++ b/media/codec2/sfplugin/tests/Android.bp
@@ -1,9 +1,19 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "ccodec_unit_test",
srcs: [
"CCodecBuffers_test.cpp",
"CCodecConfig_test.cpp",
+ "FrameReassembler_test.cpp",
"ReflectedParamUpdater_test.cpp",
],
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
index 5bee605..66b7622 100644
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -18,22 +18,32 @@
#include <gtest/gtest.h>
+#include <codec2/hidl/client.h>
#include <media/stagefright/MediaCodecConstants.h>
+#include <C2BlockInternal.h>
#include <C2PlatformSupport.h>
+#include <Codec2Mapper.h>
namespace android {
+static std::shared_ptr<RawGraphicOutputBuffers> GetRawGraphicOutputBuffers(
+ int32_t width, int32_t height) {
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>("test");
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_WIDTH, width);
+ format->setInt32(KEY_HEIGHT, height);
+ buffers->setFormat(format);
+ return buffers;
+}
+
TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
constexpr int32_t kWidth = 3840;
constexpr int32_t kHeight = 2160;
std::shared_ptr<RawGraphicOutputBuffers> buffers =
- std::make_shared<RawGraphicOutputBuffers>("test");
- sp<AMessage> format{new AMessage};
- format->setInt32("width", kWidth);
- format->setInt32("height", kHeight);
- buffers->setFormat(format);
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
std::shared_ptr<C2BlockPool> pool;
ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
@@ -96,4 +106,746 @@
}
}
+TEST(RawGraphicOutputBuffersTest, FlexYuvColorFormat) {
+ constexpr int32_t kWidth = 320;
+ constexpr int32_t kHeight = 240;
+
+ std::vector<uint32_t> flexPixelFormats({HAL_PIXEL_FORMAT_YCbCr_420_888});
+ std::shared_ptr<Codec2Client> client = Codec2Client::CreateFromService("default");
+ if (client) {
+ // Query vendor format for Flexible YUV
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
+ if (client->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo = C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].get());
+ } else {
+ pixelFormatInfo = nullptr;
+ }
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ const C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ if (desc.bitDepth != 8
+ || desc.subsampling != C2Color::YUV_420
+ // TODO(b/180076105): some devices report wrong layouts
+ // || desc.layout == C2Color::INTERLEAVED_PACKED
+ // || desc.layout == C2Color::INTERLEAVED_ALIGNED
+ || desc.layout == C2Color::UNKNOWN_LAYOUT) {
+ continue;
+ }
+ flexPixelFormats.push_back(desc.pixelFormat);
+ }
+ }
+ }
+
+ for (uint32_t pixelFormat : flexPixelFormats) {
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>(
+ AStringPrintf("test pixel format 0x%x", pixelFormat).c_str());
+
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_WIDTH, kWidth);
+ format->setInt32(KEY_HEIGHT, kHeight);
+ format->setInt32(KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);
+ int32_t fwkPixelFormat = 0;
+ if (C2Mapper::mapPixelFormatCodecToFramework(pixelFormat, &fwkPixelFormat)) {
+ format->setInt32("android._color-format", fwkPixelFormat);
+ }
+ buffers->setFormat(format);
+
+ std::shared_ptr<C2BlockPool> pool;
+ ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
+
+ std::shared_ptr<C2GraphicBlock> block;
+ ASSERT_EQ(OK, pool->fetchGraphicBlock(
+ kWidth, kHeight, pixelFormat,
+ C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
+
+ {
+ C2GraphicView view = block->map().get();
+ C2PlanarLayout layout = view.layout();
+
+ // Verify the block is in YUV420 format
+ ASSERT_EQ(C2PlanarLayout::TYPE_YUV, layout.type);
+ ASSERT_EQ(3u, layout.numPlanes);
+ const C2PlaneInfo& yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ const C2PlaneInfo& uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ const C2PlaneInfo& vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+
+ // Y plane
+ ASSERT_EQ(1u, yPlane.colSampling);
+ ASSERT_EQ(1u, yPlane.rowSampling);
+ ASSERT_EQ(8u, yPlane.allocatedDepth);
+ ASSERT_EQ(8u, yPlane.bitDepth);
+ ASSERT_EQ(0u, yPlane.rightShift);
+
+ // U plane
+ ASSERT_EQ(2u, uPlane.colSampling);
+ ASSERT_EQ(2u, uPlane.rowSampling);
+ ASSERT_EQ(8u, uPlane.allocatedDepth);
+ ASSERT_EQ(8u, uPlane.bitDepth);
+ ASSERT_EQ(0u, uPlane.rightShift);
+
+ // V plane
+ ASSERT_EQ(2u, vPlane.colSampling);
+ ASSERT_EQ(2u, vPlane.rowSampling);
+ ASSERT_EQ(8u, vPlane.allocatedDepth);
+ ASSERT_EQ(8u, vPlane.bitDepth);
+ ASSERT_EQ(0u, vPlane.rightShift);
+
+ uint8_t *yRowPtr = view.data()[C2PlanarLayout::PLANE_Y];
+ uint8_t *uRowPtr = view.data()[C2PlanarLayout::PLANE_U];
+ uint8_t *vRowPtr = view.data()[C2PlanarLayout::PLANE_V];
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ *yPtr = ((row + col) & 0xFF);
+ yPtr += yPlane.colInc;
+
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ *uPtr = ((row + col + 1) & 0xFF);
+ *vPtr = ((row + col + 2) & 0xFF);
+ uPtr += uPlane.colInc;
+ vPtr += vPlane.colInc;
+ }
+ }
+ yRowPtr += yPlane.rowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.rowInc;
+ vRowPtr += vPlane.rowInc;
+ }
+ }
+ }
+
+ std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateGraphicBuffer(block->share(
+ block->crop(), C2Fence{}));
+ size_t index;
+ sp<MediaCodecBuffer> clientBuffer;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ sp<ABuffer> imageData;
+ ASSERT_TRUE(clientBuffer->format()->findBuffer("image-data", &imageData));
+ MediaImage2 *img = (MediaImage2 *)imageData->data();
+ ASSERT_EQ(MediaImage2::MEDIA_IMAGE_TYPE_YUV, img->mType);
+ ASSERT_EQ(3u, img->mNumPlanes);
+ ASSERT_EQ(kWidth, img->mWidth);
+ ASSERT_EQ(kHeight, img->mHeight);
+ ASSERT_EQ(8u, img->mBitDepth);
+ ASSERT_EQ(8u, img->mBitDepthAllocated);
+ const MediaImage2::PlaneInfo &yPlane = img->mPlane[MediaImage2::Y];
+ const MediaImage2::PlaneInfo &uPlane = img->mPlane[MediaImage2::U];
+ const MediaImage2::PlaneInfo &vPlane = img->mPlane[MediaImage2::V];
+ ASSERT_EQ(1u, yPlane.mHorizSubsampling);
+ ASSERT_EQ(1u, yPlane.mVertSubsampling);
+ ASSERT_EQ(2u, uPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, uPlane.mVertSubsampling);
+ ASSERT_EQ(2u, vPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, vPlane.mVertSubsampling);
+
+ uint8_t *yRowPtr = clientBuffer->data() + yPlane.mOffset;
+ uint8_t *uRowPtr = clientBuffer->data() + uPlane.mOffset;
+ uint8_t *vRowPtr = clientBuffer->data() + vPlane.mOffset;
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ ASSERT_EQ((row + col) & 0xFF, *yPtr);
+ yPtr += yPlane.mColInc;
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ ASSERT_EQ((row + col + 1) & 0xFF, *uPtr);
+ ASSERT_EQ((row + col + 2) & 0xFF, *vPtr);
+ uPtr += uPlane.mColInc;
+ vPtr += vPlane.mColInc;
+ }
+ }
+ yRowPtr += yPlane.mRowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.mRowInc;
+ vRowPtr += vPlane.mRowInc;
+ }
+ }
+ }
+}
+
+TEST(RawGraphicOutputBuffersTest, P010ColorFormat) {
+ constexpr int32_t kWidth = 320;
+ constexpr int32_t kHeight = 240;
+
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>("test P010");
+
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_WIDTH, kWidth);
+ format->setInt32(KEY_HEIGHT, kHeight);
+ format->setInt32(KEY_COLOR_FORMAT, COLOR_FormatYUVP010);
+ int32_t fwkPixelFormat = 0;
+ if (C2Mapper::mapPixelFormatCodecToFramework(HAL_PIXEL_FORMAT_YCBCR_P010, &fwkPixelFormat)) {
+ format->setInt32("android._color-format", fwkPixelFormat);
+ }
+ buffers->setFormat(format);
+
+ std::shared_ptr<C2BlockPool> pool;
+ ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
+
+ std::shared_ptr<C2GraphicBlock> block;
+ c2_status_t err = pool->fetchGraphicBlock(
+ kWidth, kHeight, HAL_PIXEL_FORMAT_YCBCR_P010,
+ C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ if (err != C2_OK) {
+ GTEST_SKIP();
+ }
+
+ {
+ C2GraphicView view = block->map().get();
+ C2PlanarLayout layout = view.layout();
+
+ // Verify the block is in YUV420 format
+ ASSERT_EQ(C2PlanarLayout::TYPE_YUV, layout.type);
+ ASSERT_EQ(3u, layout.numPlanes);
+ const C2PlaneInfo& yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ const C2PlaneInfo& uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ const C2PlaneInfo& vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+
+ // Y plane
+ ASSERT_EQ(1u, yPlane.colSampling);
+ ASSERT_EQ(1u, yPlane.rowSampling);
+ ASSERT_EQ(16u, yPlane.allocatedDepth);
+ ASSERT_EQ(10u, yPlane.bitDepth);
+ ASSERT_EQ(6u, yPlane.rightShift);
+
+ // U plane
+ ASSERT_EQ(2u, uPlane.colSampling);
+ ASSERT_EQ(2u, uPlane.rowSampling);
+ ASSERT_EQ(16u, uPlane.allocatedDepth);
+ ASSERT_EQ(10u, uPlane.bitDepth);
+ ASSERT_EQ(6u, uPlane.rightShift);
+
+ // V plane
+ ASSERT_EQ(2u, vPlane.colSampling);
+ ASSERT_EQ(2u, vPlane.rowSampling);
+ ASSERT_EQ(16u, vPlane.allocatedDepth);
+ ASSERT_EQ(10u, vPlane.bitDepth);
+ ASSERT_EQ(6u, vPlane.rightShift);
+
+ uint8_t *yRowPtr = view.data()[C2PlanarLayout::PLANE_Y];
+ uint8_t *uRowPtr = view.data()[C2PlanarLayout::PLANE_U];
+ uint8_t *vRowPtr = view.data()[C2PlanarLayout::PLANE_V];
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ yPtr[0] = ((row + col) & 0x3) << 6;
+ yPtr[1] = ((row + col) & 0x3FC) >> 2;
+ yPtr += yPlane.colInc;
+
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ uPtr[0] = ((row + col + 1) & 0x3) << 6;
+ uPtr[1] = ((row + col + 1) & 0x3FC) >> 2;
+ vPtr[0] = ((row + col + 2) & 0x3) << 6;
+ vPtr[1] = ((row + col + 2) & 0x3FC) >> 2;
+ uPtr += uPlane.colInc;
+ vPtr += vPlane.colInc;
+ }
+ }
+ yRowPtr += yPlane.rowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.rowInc;
+ vRowPtr += vPlane.rowInc;
+ }
+ }
+ }
+
+ std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateGraphicBuffer(block->share(
+ block->crop(), C2Fence{}));
+ size_t index;
+ sp<MediaCodecBuffer> clientBuffer;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ sp<ABuffer> imageData;
+ ASSERT_TRUE(clientBuffer->format()->findBuffer("image-data", &imageData));
+ MediaImage2 *img = (MediaImage2 *)imageData->data();
+ ASSERT_EQ(MediaImage2::MEDIA_IMAGE_TYPE_YUV, img->mType);
+ ASSERT_EQ(3u, img->mNumPlanes);
+ ASSERT_EQ(kWidth, img->mWidth);
+ ASSERT_EQ(kHeight, img->mHeight);
+ ASSERT_EQ(10u, img->mBitDepth);
+ ASSERT_EQ(16u, img->mBitDepthAllocated);
+ const MediaImage2::PlaneInfo &yPlane = img->mPlane[MediaImage2::Y];
+ const MediaImage2::PlaneInfo &uPlane = img->mPlane[MediaImage2::U];
+ const MediaImage2::PlaneInfo &vPlane = img->mPlane[MediaImage2::V];
+ ASSERT_EQ(1u, yPlane.mHorizSubsampling);
+ ASSERT_EQ(1u, yPlane.mVertSubsampling);
+ ASSERT_EQ(2u, uPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, uPlane.mVertSubsampling);
+ ASSERT_EQ(2u, vPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, vPlane.mVertSubsampling);
+
+ uint8_t *yRowPtr = clientBuffer->data() + yPlane.mOffset;
+ uint8_t *uRowPtr = clientBuffer->data() + uPlane.mOffset;
+ uint8_t *vRowPtr = clientBuffer->data() + vPlane.mOffset;
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ ASSERT_EQ(((row + col) & 0x3) << 6, yPtr[0]);
+ ASSERT_EQ(((row + col) & 0x3FC) >> 2, yPtr[1]);
+ yPtr += yPlane.mColInc;
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ ASSERT_EQ(((row + col + 1) & 0x3) << 6, uPtr[0]);
+ ASSERT_EQ(((row + col + 1) & 0x3FC) >> 2, uPtr[1]);
+ ASSERT_EQ(((row + col + 2) & 0x3) << 6, vPtr[0]);
+ ASSERT_EQ(((row + col + 2) & 0x3FC) >> 2, vPtr[1]);
+ uPtr += uPlane.mColInc;
+ vPtr += vPlane.mColInc;
+ }
+ }
+ yRowPtr += yPlane.mRowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.mRowInc;
+ vRowPtr += vPlane.mRowInc;
+ }
+ }
+}
+
+class TestGraphicAllocation : public C2GraphicAllocation {
+public:
+ TestGraphicAllocation(
+ uint32_t width,
+ uint32_t height,
+ const C2PlanarLayout &layout,
+ size_t capacity,
+ std::vector<size_t> offsets)
+ : C2GraphicAllocation(width, height),
+ mLayout(layout),
+ mMemory(capacity, 0xAA),
+ mOffsets(offsets) {
+ }
+
+ c2_status_t map(
+ C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+ C2PlanarLayout *layout, uint8_t **addr) override {
+ (void)rect;
+ (void)usage;
+ (void)fence;
+ *layout = mLayout;
+ for (size_t i = 0; i < mLayout.numPlanes; ++i) {
+ addr[i] = mMemory.data() + mOffsets[i];
+ }
+ return C2_OK;
+ }
+
+ c2_status_t unmap(uint8_t **, C2Rect, C2Fence *) override { return C2_OK; }
+
+ C2Allocator::id_t getAllocatorId() const override { return -1; }
+
+ const C2Handle *handle() const override { return nullptr; }
+
+ bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override {
+ return other.get() == this;
+ }
+
+private:
+ C2PlanarLayout mLayout;
+ std::vector<uint8_t> mMemory;
+ std::vector<uint8_t *> mAddr;
+ std::vector<size_t> mOffsets;
+};
+
+class LayoutTest : public ::testing::TestWithParam<std::tuple<bool, std::string, bool, int32_t>> {
+private:
+ static C2PlanarLayout YUVPlanarLayout(int32_t stride) {
+ C2PlanarLayout layout = {
+ C2PlanarLayout::TYPE_YUV,
+ 3, /* numPlanes */
+ 3, /* rootPlanes */
+ {}, /* planes --- to be filled below */
+ };
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y,
+ 1, /* colInc */
+ stride, /* rowInc */
+ 1, /* colSampling */
+ 1, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_Y, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB,
+ 1, /* colInc */
+ stride / 2, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_U, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR,
+ 1, /* colInc */
+ stride / 2, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_V, /* rootIx */
+ 0, /* offset */
+ };
+ return layout;
+ }
+
+ static C2PlanarLayout YUVSemiPlanarLayout(int32_t stride) {
+ C2PlanarLayout layout = {
+ C2PlanarLayout::TYPE_YUV,
+ 3, /* numPlanes */
+ 2, /* rootPlanes */
+ {}, /* planes --- to be filled below */
+ };
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y,
+ 1, /* colInc */
+ stride, /* rowInc */
+ 1, /* colSampling */
+ 1, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_Y, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_U, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_U, /* rootIx */
+ 1, /* offset */
+ };
+ return layout;
+ }
+
+ static C2PlanarLayout YVUSemiPlanarLayout(int32_t stride) {
+ C2PlanarLayout layout = {
+ C2PlanarLayout::TYPE_YUV,
+ 3, /* numPlanes */
+ 2, /* rootPlanes */
+ {}, /* planes --- to be filled below */
+ };
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y,
+ 1, /* colInc */
+ stride, /* rowInc */
+ 1, /* colSampling */
+ 1, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_Y, /* rootIx */
+ 0, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_V, /* rootIx */
+ 1, /* offset */
+ };
+ layout.planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR,
+ 2, /* colInc */
+ stride, /* rowInc */
+ 2, /* colSampling */
+ 2, /* rowSampling */
+ 8, /* allocatedDepth */
+ 8, /* bitDepth */
+ 0, /* rightShift */
+ C2PlaneInfo::NATIVE,
+ C2PlanarLayout::PLANE_V, /* rootIx */
+ 0, /* offset */
+ };
+ return layout;
+ }
+
+ static std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
+ uint32_t width,
+ uint32_t height,
+ const C2PlanarLayout &layout,
+ size_t capacity,
+ std::vector<size_t> offsets) {
+ std::shared_ptr<C2GraphicAllocation> alloc = std::make_shared<TestGraphicAllocation>(
+ width,
+ height,
+ layout,
+ capacity,
+ offsets);
+
+ return _C2BlockFactory::CreateGraphicBlock(alloc);
+ }
+
+ static constexpr uint8_t GetPixelValue(uint8_t value, uint32_t row, uint32_t col) {
+ return (uint32_t(value) * row + col) & 0xFF;
+ }
+
+ static void FillPlane(C2GraphicView &view, size_t index, uint8_t value) {
+ C2PlanarLayout layout = view.layout();
+
+ uint8_t *rowPtr = view.data()[index];
+ C2PlaneInfo plane = layout.planes[index];
+ for (uint32_t row = 0; row < view.height() / plane.rowSampling; ++row) {
+ uint8_t *colPtr = rowPtr;
+ for (uint32_t col = 0; col < view.width() / plane.colSampling; ++col) {
+ *colPtr = GetPixelValue(value, row, col);
+ colPtr += plane.colInc;
+ }
+ rowPtr += plane.rowInc;
+ }
+ }
+
+ static void FillBlock(const std::shared_ptr<C2GraphicBlock> &block) {
+ C2GraphicView view = block->map().get();
+
+ FillPlane(view, C2PlanarLayout::PLANE_Y, 'Y');
+ FillPlane(view, C2PlanarLayout::PLANE_U, 'U');
+ FillPlane(view, C2PlanarLayout::PLANE_V, 'V');
+ }
+
+ static bool VerifyPlane(
+ const MediaImage2 *mediaImage,
+ const uint8_t *base,
+ uint32_t index,
+ uint8_t value,
+ std::string *errorMsg) {
+ *errorMsg = "";
+ MediaImage2::PlaneInfo plane = mediaImage->mPlane[index];
+ const uint8_t *rowPtr = base + plane.mOffset;
+ for (uint32_t row = 0; row < mediaImage->mHeight / plane.mVertSubsampling; ++row) {
+ const uint8_t *colPtr = rowPtr;
+ for (uint32_t col = 0; col < mediaImage->mWidth / plane.mHorizSubsampling; ++col) {
+ if (GetPixelValue(value, row, col) != *colPtr) {
+ *errorMsg = AStringPrintf("row=%u col=%u expected=%02x actual=%02x",
+ row, col, GetPixelValue(value, row, col), *colPtr).c_str();
+ return false;
+ }
+ colPtr += plane.mColInc;
+ }
+ rowPtr += plane.mRowInc;
+ }
+ return true;
+ }
+
+public:
+ static constexpr int32_t kWidth = 320;
+ static constexpr int32_t kHeight = 240;
+ static constexpr int32_t kGapLength = kWidth * kHeight * 10;
+
+ static std::shared_ptr<C2Buffer> CreateAndFillBufferFromParam(const ParamType ¶m) {
+ bool contiguous = std::get<0>(param);
+ std::string planeOrderStr = std::get<1>(param);
+ bool planar = std::get<2>(param);
+ int32_t stride = std::get<3>(param);
+
+ C2PlanarLayout::plane_index_t planeOrder[3];
+ C2PlanarLayout layout;
+
+ if (planeOrderStr.size() != 3) {
+ return nullptr;
+ }
+ for (size_t i = 0; i < 3; ++i) {
+ C2PlanarLayout::plane_index_t planeIndex;
+ switch (planeOrderStr[i]) {
+ case 'Y': planeIndex = C2PlanarLayout::PLANE_Y; break;
+ case 'U': planeIndex = C2PlanarLayout::PLANE_U; break;
+ case 'V': planeIndex = C2PlanarLayout::PLANE_V; break;
+ default: return nullptr;
+ }
+ planeOrder[i] = planeIndex;
+ }
+
+ if (planar) {
+ layout = YUVPlanarLayout(stride);
+ } else { // semi-planar
+ for (size_t i = 0; i < 3; ++i) {
+ if (planeOrder[i] == C2PlanarLayout::PLANE_U) {
+ layout = YUVSemiPlanarLayout(stride);
+ break;
+ }
+ if (planeOrder[i] == C2PlanarLayout::PLANE_V) {
+ layout = YVUSemiPlanarLayout(stride);
+ break;
+ }
+ }
+ }
+ size_t yPlaneSize = stride * kHeight;
+ size_t uvPlaneSize = stride * kHeight / 4;
+ size_t capacity = yPlaneSize + uvPlaneSize * 2;
+ std::vector<size_t> offsets(3);
+
+ if (!contiguous) {
+ if (planar) {
+ capacity += kGapLength * 2;
+ } else { // semi-planar
+ capacity += kGapLength;
+ }
+ }
+
+ offsets[planeOrder[0]] = 0;
+ size_t planeSize = (planeOrder[0] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
+ for (size_t i = 1; i < 3; ++i) {
+ offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + planeSize;
+ if (!contiguous) {
+ offsets[planeOrder[i]] += kGapLength;
+ }
+ planeSize = (planeOrder[i] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
+ if (!planar // semi-planar
+ && planeOrder[i - 1] != C2PlanarLayout::PLANE_Y
+ && planeOrder[i] != C2PlanarLayout::PLANE_Y) {
+ offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + 1;
+ planeSize = uvPlaneSize * 2 - 1;
+ }
+ }
+
+ std::shared_ptr<C2GraphicBlock> block = CreateGraphicBlock(
+ kWidth,
+ kHeight,
+ layout,
+ capacity,
+ offsets);
+ FillBlock(block);
+ return C2Buffer::CreateGraphicBuffer(
+ block->share(block->crop(), C2Fence()));
+ }
+
+ static bool VerifyClientBuffer(
+ const sp<MediaCodecBuffer> &buffer, std::string *errorMsg) {
+ *errorMsg = "";
+ sp<ABuffer> imageData;
+ if (!buffer->format()->findBuffer("image-data", &imageData)) {
+ *errorMsg = "Missing image data";
+ return false;
+ }
+ MediaImage2 *mediaImage = (MediaImage2 *)imageData->data();
+ if (mediaImage->mType != MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
+ *errorMsg = AStringPrintf("Unexpected type: %d", mediaImage->mType).c_str();
+ return false;
+ }
+ std::string planeErrorMsg;
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
+ *errorMsg = "Y plane does not match: " + planeErrorMsg;
+ return false;
+ }
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::U, 'U', &planeErrorMsg)) {
+ *errorMsg = "U plane does not match: " + planeErrorMsg;
+ return false;
+ }
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::V, 'V', &planeErrorMsg)) {
+ *errorMsg = "V plane does not match: " + planeErrorMsg;
+ return false;
+ }
+
+ int32_t width, height, stride;
+ buffer->format()->findInt32(KEY_WIDTH, &width);
+ buffer->format()->findInt32(KEY_HEIGHT, &height);
+ buffer->format()->findInt32(KEY_STRIDE, &stride);
+
+ MediaImage2 legacyYLayout = {
+ MediaImage2::MEDIA_IMAGE_TYPE_Y,
+ 1, // mNumPlanes
+ uint32_t(width),
+ uint32_t(height),
+ 8,
+ 8,
+ {}, // mPlane
+ };
+ legacyYLayout.mPlane[MediaImage2::Y] = {
+ 0, // mOffset
+ 1, // mColInc
+ stride, // mRowInc
+ 1, // mHorizSubsampling
+ 1, // mVertSubsampling
+ };
+ if (!VerifyPlane(&legacyYLayout, buffer->data(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
+ *errorMsg = "Y plane by legacy layout does not match: " + planeErrorMsg;
+ return false;
+ }
+ return true;
+ }
+
+};
+
+TEST_P(LayoutTest, VerifyLayout) {
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
+
+ std::shared_ptr<C2Buffer> c2Buffer = CreateAndFillBufferFromParam(GetParam());
+ ASSERT_NE(nullptr, c2Buffer);
+ sp<MediaCodecBuffer> clientBuffer;
+ size_t index;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ std::string errorMsg;
+ ASSERT_TRUE(VerifyClientBuffer(clientBuffer, &errorMsg)) << errorMsg;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ RawGraphicOutputBuffersTest,
+ LayoutTest,
+ ::testing::Combine(
+ ::testing::Bool(), /* contiguous */
+ ::testing::Values("YUV", "YVU", "UVY", "VUY"),
+ ::testing::Bool(), /* planar */
+ ::testing::Values(320, 512)),
+ [](const ::testing::TestParamInfo<LayoutTest::ParamType> &info) {
+ std::string contiguous = std::get<0>(info.param) ? "Contiguous" : "Noncontiguous";
+ std::string planar = std::get<2>(info.param) ? "Planar" : "SemiPlanar";
+ return contiguous
+ + std::get<1>(info.param)
+ + planar
+ + std::to_string(std::get<3>(info.param));
+ });
+
} // namespace android
diff --git a/media/codec2/sfplugin/tests/CCodecConfig_test.cpp b/media/codec2/sfplugin/tests/CCodecConfig_test.cpp
index c9caa01..7c660dc 100644
--- a/media/codec2/sfplugin/tests/CCodecConfig_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecConfig_test.cpp
@@ -208,6 +208,24 @@
.withSetter(Setter<C2StreamPixelAspectRatioInfo::output>)
.build());
+ if (isEncoder) {
+ addParameter(
+ DefineParam(mInputBitrate, C2_PARAMKEY_BITRATE)
+ .withDefault(new C2StreamBitrateInfo::input(0u))
+ .withFields({C2F(mInputBitrate, value).any()})
+ .withSetter(Setter<C2StreamBitrateInfo::input>)
+ .build());
+
+ addParameter(
+ DefineParam(mOutputBitrate, C2_PARAMKEY_BITRATE)
+ .withDefault(new C2StreamBitrateInfo::output(0u))
+ .withFields({C2F(mOutputBitrate, value).any()})
+ .calculatedAs(
+ Copy<C2StreamBitrateInfo::output, C2StreamBitrateInfo::input>,
+ mInputBitrate)
+ .build());
+ }
+
// TODO: more SDK params
}
private:
@@ -221,11 +239,19 @@
std::shared_ptr<C2StreamVendorInt64Info::output> mInt64Output;
std::shared_ptr<C2PortVendorStringInfo::input> mStringInput;
std::shared_ptr<C2StreamPixelAspectRatioInfo::output> mPixelAspectRatio;
+ std::shared_ptr<C2StreamBitrateInfo::input> mInputBitrate;
+ std::shared_ptr<C2StreamBitrateInfo::output> mOutputBitrate;
template<typename T>
static C2R Setter(bool, C2P<T> &) {
return C2R::Ok();
}
+
+ template<typename ME, typename DEP>
+ static C2R Copy(bool, C2P<ME> &me, const C2P<DEP> &dep) {
+ me.set().value = dep.v.value;
+ return C2R::Ok();
+ }
};
Impl mImpl;
@@ -457,4 +483,97 @@
<< "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
}
+TEST_F(CCodecConfigTest, DataspaceUpdate) {
+ init(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER, MIMETYPE_VIDEO_AVC);
+
+ ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+ class InputSurfaceStub : public InputSurfaceWrapper {
+ public:
+ ~InputSurfaceStub() override = default;
+ status_t connect(const std::shared_ptr<Codec2Client::Component> &) override {
+ return OK;
+ }
+ void disconnect() override {}
+ status_t start() override { return OK; }
+ status_t signalEndOfInputStream() override { return OK; }
+ status_t configure(Config &) override { return OK; }
+ };
+ mConfig.mInputSurface = std::make_shared<InputSurfaceStub>();
+
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_COLOR_RANGE, COLOR_RANGE_LIMITED);
+ format->setInt32(KEY_COLOR_STANDARD, COLOR_STANDARD_BT709);
+ format->setInt32(KEY_COLOR_TRANSFER, COLOR_TRANSFER_SDR_VIDEO);
+ format->setInt32(KEY_BIT_RATE, 100);
+
+ std::vector<std::unique_ptr<C2Param>> configUpdate;
+ ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
+ mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
+ ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
+
+ int32_t range{0};
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_RANGE, &range))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_RANGE_LIMITED, range)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ int32_t standard{0};
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_STANDARD, &standard))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_STANDARD_BT709, standard)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ int32_t transfer{0};
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_TRANSFER, &transfer))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_TRANSFER_SDR_VIDEO, transfer)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ mConfig.mInputSurface->setDataSpace(HAL_DATASPACE_BT2020_PQ);
+
+ // Dataspace from input surface should override the configured setting
+ mConfig.updateFormats(D::ALL);
+
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_RANGE, &range))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_RANGE_FULL, range)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_STANDARD, &standard))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_STANDARD_BT2020, standard)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_TRANSFER, &transfer))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_TRANSFER_ST2084, transfer)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ // Simulate bitrate update
+ format = new AMessage;
+ format->setInt32(KEY_BIT_RATE, 200);
+ configUpdate.clear();
+ ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
+ mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
+ ASSERT_EQ(OK, mConfig.setParameters(mConfigurable, configUpdate, C2_MAY_BLOCK));
+
+ // Color information should remain the same
+ mConfig.updateFormats(D::ALL);
+
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_RANGE, &range))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_RANGE_FULL, range)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_STANDARD, &standard))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_STANDARD_BT2020, standard)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+ ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_COLOR_TRANSFER, &transfer))
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+ EXPECT_EQ(COLOR_TRANSFER_ST2084, transfer)
+ << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/tests/FrameReassembler_test.cpp b/media/codec2/sfplugin/tests/FrameReassembler_test.cpp
new file mode 100644
index 0000000..6738ee7
--- /dev/null
+++ b/media/codec2/sfplugin/tests/FrameReassembler_test.cpp
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrameReassembler.h"
+
+#include <gtest/gtest.h>
+
+#include <C2PlatformSupport.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+static size_t BytesPerSample(C2Config::pcm_encoding_t encoding) {
+ return encoding == PCM_8 ? 1
+ : encoding == PCM_16 ? 2
+ : encoding == PCM_FLOAT ? 4 : 0;
+}
+
+static uint64_t Diff(c2_cntr64_t a, c2_cntr64_t b) {
+ return std::abs((a - b).peek());
+}
+
+class FrameReassemblerTest : public ::testing::Test {
+public:
+ static const C2MemoryUsage kUsage;
+ static constexpr uint64_t kTimestampToleranceUs = 100;
+
+ FrameReassemblerTest() {
+ mInitStatus = GetCodec2BlockPool(C2BlockPool::BASIC_LINEAR, nullptr, &mPool);
+ }
+
+ status_t initStatus() const { return mInitStatus; }
+
+ void testPushSameSize(
+ size_t encoderFrameSize,
+ size_t sampleRate,
+ size_t channelCount,
+ C2Config::pcm_encoding_t encoding,
+ size_t inputFrameSizeInBytes,
+ size_t count,
+ size_t expectedOutputSize) {
+ FrameReassembler frameReassembler;
+ frameReassembler.init(
+ mPool,
+ kUsage,
+ encoderFrameSize,
+ sampleRate,
+ channelCount,
+ encoding);
+
+ ASSERT_TRUE(frameReassembler) << "FrameReassembler init failed";
+
+ size_t inputIndex = 0, outputIndex = 0;
+ size_t expectCount = 0;
+ for (size_t i = 0; i < count; ++i) {
+ sp<MediaCodecBuffer> buffer = new MediaCodecBuffer(
+ new AMessage, new ABuffer(inputFrameSizeInBytes));
+ buffer->setRange(0, inputFrameSizeInBytes);
+ buffer->meta()->setInt64(
+ "timeUs",
+ inputIndex * 1000000 / sampleRate / channelCount / BytesPerSample(encoding));
+ if (i == count - 1) {
+ buffer->meta()->setInt32("eos", 1);
+ }
+ for (size_t j = 0; j < inputFrameSizeInBytes; ++j, ++inputIndex) {
+ buffer->base()[j] = (inputIndex & 0xFF);
+ }
+ std::list<std::unique_ptr<C2Work>> items;
+ ASSERT_EQ(C2_OK, frameReassembler.process(buffer, &items));
+ while (!items.empty()) {
+ std::unique_ptr<C2Work> work = std::move(*items.begin());
+ items.erase(items.begin());
+ // Verify timestamp
+ uint64_t expectedTimeUs =
+ outputIndex * 1000000 / sampleRate / channelCount / BytesPerSample(encoding);
+ EXPECT_GE(
+ kTimestampToleranceUs,
+ Diff(expectedTimeUs, work->input.ordinal.timestamp))
+ << "expected timestamp: " << expectedTimeUs
+ << " actual timestamp: " << work->input.ordinal.timestamp.peeku()
+ << " output index: " << outputIndex;
+
+ // Verify buffer
+ ASSERT_EQ(1u, work->input.buffers.size());
+ std::shared_ptr<C2Buffer> buffer = work->input.buffers.front();
+ ASSERT_EQ(C2BufferData::LINEAR, buffer->data().type());
+ ASSERT_EQ(1u, buffer->data().linearBlocks().size());
+ C2ReadView view = buffer->data().linearBlocks().front().map().get();
+ ASSERT_EQ(C2_OK, view.error());
+ ASSERT_EQ(encoderFrameSize * BytesPerSample(encoding), view.capacity());
+ for (size_t j = 0; j < view.capacity(); ++j, ++outputIndex) {
+ ASSERT_TRUE(outputIndex < inputIndex
+ || inputIndex == inputFrameSizeInBytes * count);
+ uint8_t expected = outputIndex < inputIndex ? (outputIndex & 0xFF) : 0;
+ if (expectCount < 10) {
+ ++expectCount;
+ EXPECT_EQ(expected, view.data()[j]) << "output index = " << outputIndex;
+ }
+ }
+ }
+ }
+
+ ASSERT_EQ(inputFrameSizeInBytes * count, inputIndex);
+ size_t encoderFrameSizeInBytes =
+ encoderFrameSize * channelCount * BytesPerSample(encoding);
+ ASSERT_EQ(0, outputIndex % encoderFrameSizeInBytes)
+ << "output size must be multiple of frame size: output size = " << outputIndex
+ << " frame size = " << encoderFrameSizeInBytes;
+ ASSERT_EQ(expectedOutputSize, outputIndex)
+ << "output size must be smallest multiple of frame size, "
+ << "equal to or larger than input size. output size = " << outputIndex
+ << " input size = " << inputIndex << " frame size = " << encoderFrameSizeInBytes;
+ }
+
+private:
+ status_t mInitStatus;
+ std::shared_ptr<C2BlockPool> mPool;
+};
+
+const C2MemoryUsage FrameReassemblerTest::kUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+// Push frames with exactly the same size as the encoder requested.
+TEST_F(FrameReassemblerTest, PushExactFrameSize) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 1024 /* input frame size in bytes = 1024 samples * 1 channel * 1 bytes/sample */,
+ 10 /* count */,
+ 10240 /* expected output size = 10 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 2048 /* input frame size in bytes = 1024 samples * 1 channel * 2 bytes/sample */,
+ 10 /* count */,
+ 20480 /* expected output size = 10 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 4096 /* input frame size in bytes = 1024 samples * 1 channel * 4 bytes/sample */,
+ 10 /* count */,
+ 40960 /* expected output size = 10 * 4096 bytes/frame */);
+}
+
+// Push frames with half the size that the encoder requested.
+TEST_F(FrameReassemblerTest, PushHalfFrameSize) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 512 /* input frame size in bytes = 512 samples * 1 channel * 1 bytes per sample */,
+ 10 /* count */,
+ 5120 /* expected output size = 5 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 1024 /* input frame size in bytes = 512 samples * 1 channel * 2 bytes per sample */,
+ 10 /* count */,
+ 10240 /* expected output size = 5 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 2048 /* input frame size in bytes = 512 samples * 1 channel * 4 bytes per sample */,
+ 10 /* count */,
+ 20480 /* expected output size = 5 * 4096 bytes/frame */);
+}
+
+// Push frames with twice the size that the encoder requested.
+TEST_F(FrameReassemblerTest, PushDoubleFrameSize) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 2048 /* input frame size in bytes = 2048 samples * 1 channel * 1 bytes per sample */,
+ 10 /* count */,
+ 20480 /* expected output size = 20 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 4096 /* input frame size in bytes = 2048 samples * 1 channel * 2 bytes per sample */,
+ 10 /* count */,
+ 40960 /* expected output size = 20 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 8192 /* input frame size in bytes = 2048 samples * 1 channel * 4 bytes per sample */,
+ 10 /* count */,
+ 81920 /* expected output size = 20 * 4096 bytes/frame */);
+}
+
+// Push frames with a little bit larger (+5 samples) than the requested size.
+TEST_F(FrameReassemblerTest, PushLittleLargerFrameSize) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 1029 /* input frame size in bytes = 1029 samples * 1 channel * 1 bytes per sample */,
+ 10 /* count */,
+ 11264 /* expected output size = 11 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 2058 /* input frame size in bytes = 1029 samples * 1 channel * 2 bytes per sample */,
+ 10 /* count */,
+ 22528 /* expected output size = 11 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 4116 /* input frame size in bytes = 1029 samples * 1 channel * 4 bytes per sample */,
+ 10 /* count */,
+ 45056 /* expected output size = 11 * 4096 bytes/frame */);
+}
+
+// Push frames with a little bit smaller (-5 samples) than the requested size.
+TEST_F(FrameReassemblerTest, PushLittleSmallerFrameSize) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 1019 /* input frame size in bytes = 1019 samples * 1 channel * 1 bytes per sample */,
+ 10 /* count */,
+ 10240 /* expected output size = 10 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 2038 /* input frame size in bytes = 1019 samples * 1 channel * 2 bytes per sample */,
+ 10 /* count */,
+ 20480 /* expected output size = 10 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 4076 /* input frame size in bytes = 1019 samples * 1 channel * 4 bytes per sample */,
+ 10 /* count */,
+ 40960 /* expected output size = 10 * 4096 bytes/frame */);
+}
+
+// Push single-byte frames
+TEST_F(FrameReassemblerTest, PushSingleByte) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 1 /* input frame size in bytes */,
+ 100000 /* count */,
+ 100352 /* expected output size = 98 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 1 /* input frame size in bytes */,
+ 100000 /* count */,
+ 100352 /* expected output size = 49 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 1 /* input frame size in bytes */,
+ 100000 /* count */,
+ 102400 /* expected output size = 25 * 4096 bytes/frame */);
+}
+
+// Push one big chunk.
+TEST_F(FrameReassemblerTest, PushBigChunk) {
+ ASSERT_EQ(OK, initStatus());
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_8,
+ 100000 /* input frame size in bytes */,
+ 1 /* count */,
+ 100352 /* expected output size = 98 * 1024 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_16,
+ 100000 /* input frame size in bytes */,
+ 1 /* count */,
+ 100352 /* expected output size = 49 * 2048 bytes/frame */);
+ testPushSameSize(
+ 1024 /* frame size in samples */,
+ 48000 /* sample rate */,
+ 1 /* channel count */,
+ PCM_FLOAT,
+ 100000 /* input frame size in bytes */,
+ 1 /* count */,
+ 102400 /* expected output size = 25 * 4096 bytes/frame */);
+}
+
+} // namespace android
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 6287221..74e7ef1 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -1,4 +1,13 @@
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libsfplugin_ccodec_utils",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index bf2a07e..a54af83 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -121,34 +121,46 @@
if (view.crop().width != img->mWidth || view.crop().height != img->mHeight) {
return BAD_VALUE;
}
+ const uint8_t* src_y = view.data()[0];
+ const uint8_t* src_u = view.data()[1];
+ const uint8_t* src_v = view.data()[2];
+ int32_t src_stride_y = view.layout().planes[0].rowInc;
+ int32_t src_stride_u = view.layout().planes[1].rowInc;
+ int32_t src_stride_v = view.layout().planes[2].rowInc;
+ uint8_t* dst_y = imgBase + img->mPlane[0].mOffset;
+ uint8_t* dst_u = imgBase + img->mPlane[1].mOffset;
+ uint8_t* dst_v = imgBase + img->mPlane[2].mOffset;
+ int32_t dst_stride_y = img->mPlane[0].mRowInc;
+ int32_t dst_stride_u = img->mPlane[1].mRowInc;
+ int32_t dst_stride_v = img->mPlane[2].mRowInc;
+ int width = view.crop().width;
+ int height = view.crop().height;
+
if ((IsNV12(view) && IsI420(img)) || (IsI420(view) && IsNV12(img))) {
// Take shortcuts to use libyuv functions between NV12 and I420 conversion.
- const uint8_t* src_y = view.data()[0];
- const uint8_t* src_u = view.data()[1];
- const uint8_t* src_v = view.data()[2];
- int32_t src_stride_y = view.layout().planes[0].rowInc;
- int32_t src_stride_u = view.layout().planes[1].rowInc;
- int32_t src_stride_v = view.layout().planes[2].rowInc;
- uint8_t* dst_y = imgBase + img->mPlane[0].mOffset;
- uint8_t* dst_u = imgBase + img->mPlane[1].mOffset;
- uint8_t* dst_v = imgBase + img->mPlane[2].mOffset;
- int32_t dst_stride_y = img->mPlane[0].mRowInc;
- int32_t dst_stride_u = img->mPlane[1].mRowInc;
- int32_t dst_stride_v = img->mPlane[2].mRowInc;
if (IsNV12(view) && IsI420(img)) {
if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
- dst_u, dst_stride_u, dst_v, dst_stride_v, view.crop().width,
- view.crop().height)) {
+ dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
return OK;
}
} else {
if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
- dst_y, dst_stride_y, dst_u, dst_stride_u, view.crop().width,
- view.crop().height)) {
+ dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
return OK;
}
}
}
+ if (IsNV12(view) && IsNV12(img)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
+ return OK;
+ }
+ if (IsI420(view) && IsI420(img)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
+ return OK;
+ }
return _ImageCopy<true>(view, img, imgBase);
}
@@ -156,34 +168,47 @@
if (view.crop().width != img->mWidth || view.crop().height != img->mHeight) {
return BAD_VALUE;
}
+ const uint8_t* src_y = imgBase + img->mPlane[0].mOffset;
+ const uint8_t* src_u = imgBase + img->mPlane[1].mOffset;
+ const uint8_t* src_v = imgBase + img->mPlane[2].mOffset;
+ int32_t src_stride_y = img->mPlane[0].mRowInc;
+ int32_t src_stride_u = img->mPlane[1].mRowInc;
+ int32_t src_stride_v = img->mPlane[2].mRowInc;
+ uint8_t* dst_y = view.data()[0];
+ uint8_t* dst_u = view.data()[1];
+ uint8_t* dst_v = view.data()[2];
+ int32_t dst_stride_y = view.layout().planes[0].rowInc;
+ int32_t dst_stride_u = view.layout().planes[1].rowInc;
+ int32_t dst_stride_v = view.layout().planes[2].rowInc;
+ int width = view.crop().width;
+ int height = view.crop().height;
if ((IsNV12(img) && IsI420(view)) || (IsI420(img) && IsNV12(view))) {
// Take shortcuts to use libyuv functions between NV12 and I420 conversion.
- const uint8_t* src_y = imgBase + img->mPlane[0].mOffset;
- const uint8_t* src_u = imgBase + img->mPlane[1].mOffset;
- const uint8_t* src_v = imgBase + img->mPlane[2].mOffset;
- int32_t src_stride_y = img->mPlane[0].mRowInc;
- int32_t src_stride_u = img->mPlane[1].mRowInc;
- int32_t src_stride_v = img->mPlane[2].mRowInc;
- uint8_t* dst_y = view.data()[0];
- uint8_t* dst_u = view.data()[1];
- uint8_t* dst_v = view.data()[2];
- int32_t dst_stride_y = view.layout().planes[0].rowInc;
- int32_t dst_stride_u = view.layout().planes[1].rowInc;
- int32_t dst_stride_v = view.layout().planes[2].rowInc;
if (IsNV12(img) && IsI420(view)) {
if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
- dst_u, dst_stride_u, dst_v, dst_stride_v, view.width(),
- view.height())) {
+ dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
return OK;
}
} else {
if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
- dst_y, dst_stride_y, dst_u, dst_stride_u, view.width(),
- view.height())) {
+ dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
return OK;
}
}
}
+ if (IsNV12(img) && IsNV12(view)) {
+ // For NV12, copy Y and UV plane
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
+ return OK;
+ }
+ if (IsI420(img) && IsI420(view)) {
+ // For I420, copy Y, U and V plane.
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
+ return OK;
+ }
return _ImageCopy<false>(view, img, imgBase);
}
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 903db6c..1390642 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -958,17 +958,16 @@
*c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
return true;
case COLOR_FormatYUV420Flexible:
- *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
- return true;
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420SemiPlanar:
case COLOR_FormatYUV420PackedPlanar:
case COLOR_FormatYUV420PackedSemiPlanar:
- *c2Value = HAL_PIXEL_FORMAT_YV12;
+ *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
return true;
default:
- // TODO: support some sort of passthrough
- return false;
+ // Passthrough
+ *c2Value = uint32_t(frameworkValue);
+ return true;
}
}
@@ -979,11 +978,16 @@
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
*frameworkValue = COLOR_FormatSurface;
return true;
- case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCBCR_422_SP:
+ case HAL_PIXEL_FORMAT_YCRCB_420_SP:
+ case HAL_PIXEL_FORMAT_YCBCR_422_I:
case HAL_PIXEL_FORMAT_YCBCR_420_888:
+ case HAL_PIXEL_FORMAT_YV12:
*frameworkValue = COLOR_FormatYUV420Flexible;
return true;
default:
- return false;
+ // Passthrough
+ *frameworkValue = int32_t(c2Value);
+ return true;
}
}
diff --git a/media/codec2/tests/Android.bp b/media/codec2/tests/Android.bp
index fce6e21..8ebb6c0 100644
--- a/media/codec2/tests/Android.bp
+++ b/media/codec2/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "codec2_core_param_test",
diff --git a/media/codec2/tests/vndk/C2BufferTest.cpp b/media/codec2/tests/vndk/C2BufferTest.cpp
index a9f8e17..0cfb465 100644
--- a/media/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/codec2/tests/vndk/C2BufferTest.cpp
@@ -16,11 +16,12 @@
#include <gtest/gtest.h>
-#include <C2AllocatorIon.h>
#include <C2AllocatorGralloc.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
+#include <C2Config.h>
#include <C2ParamDef.h>
+#include <C2PlatformSupport.h>
#include <system/graphics.h>
@@ -233,10 +234,10 @@
public:
C2BufferTest()
: mBlockPoolId(C2BlockPool::PLATFORM_START),
- mLinearAllocator(std::make_shared<C2AllocatorIon>('i')),
mSize(0u),
mAddr(nullptr),
mGraphicAllocator(std::make_shared<C2AllocatorGralloc>('g')) {
+ getLinearAllocator(&mLinearAllocator);
}
~C2BufferTest() = default;
@@ -329,6 +330,11 @@
}
private:
+ void getLinearAllocator(std::shared_ptr<C2Allocator>* mLinearAllocator) {
+ std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+ ASSERT_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, mLinearAllocator), C2_OK);
+ }
+
C2BlockPool::local_id_t mBlockPoolId;
std::shared_ptr<C2Allocator> mLinearAllocator;
std::shared_ptr<C2LinearAllocation> mLinearAllocation;
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 60f4736..0401c1d 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libcodec2_internal",
@@ -13,7 +22,7 @@
// !!!DO NOT DEPEND ON THIS SHARED LIBRARY DIRECTLY!!!
// use libcodec2-impl-defaults instead
-cc_library_shared {
+cc_library {
name: "libcodec2_vndk",
vendor_available: true,
min_sdk_version: "29",
@@ -112,4 +121,3 @@
// TODO: separate internal headers so they can be exposed here
}
-
diff --git a/media/codec2/vndk/C2AllocatorBlob.cpp b/media/codec2/vndk/C2AllocatorBlob.cpp
index 565137c..6340cba 100644
--- a/media/codec2/vndk/C2AllocatorBlob.cpp
+++ b/media/codec2/vndk/C2AllocatorBlob.cpp
@@ -17,6 +17,8 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "C2AllocatorBlob"
+#include <set>
+
#include <C2AllocatorBlob.h>
#include <C2PlatformSupport.h>
@@ -67,6 +69,10 @@
private:
const std::shared_ptr<C2GraphicAllocation> mGraphicAllocation;
const C2Allocator::id_t mAllocatorId;
+
+ std::mutex mMapLock;
+ std::multiset<std::pair<size_t, size_t>> mMappedOffsetSize;
+ uint8_t *mMappedAddr;
};
C2AllocationBlob::C2AllocationBlob(
@@ -74,20 +80,74 @@
C2Allocator::id_t allocatorId)
: C2LinearAllocation(capacity),
mGraphicAllocation(std::move(graphicAllocation)),
- mAllocatorId(allocatorId) {}
+ mAllocatorId(allocatorId),
+ mMappedAddr(nullptr) {}
-C2AllocationBlob::~C2AllocationBlob() {}
+C2AllocationBlob::~C2AllocationBlob() {
+ if (mMappedAddr) {
+ C2Rect rect(capacity(), kLinearBufferHeight);
+ mGraphicAllocation->unmap(&mMappedAddr, rect, nullptr);
+ }
+}
c2_status_t C2AllocationBlob::map(size_t offset, size_t size, C2MemoryUsage usage,
C2Fence* fence, void** addr /* nonnull */) {
+ *addr = nullptr;
+ if (size > capacity() || offset > capacity() || offset > capacity() - size) {
+ ALOGV("C2AllocationBlob: map: bad offset / size: offset=%zu size=%zu capacity=%u",
+ offset, size, capacity());
+ return C2_BAD_VALUE;
+ }
+ std::unique_lock<std::mutex> lock(mMapLock);
+ if (mMappedAddr) {
+ *addr = mMappedAddr + offset;
+ mMappedOffsetSize.insert({offset, size});
+ ALOGV("C2AllocationBlob: mapped from existing mapping: offset=%zu size=%zu capacity=%u",
+ offset, size, capacity());
+ return C2_OK;
+ }
C2PlanarLayout layout;
- C2Rect rect = C2Rect(size, kLinearBufferHeight).at(offset, 0u);
- return mGraphicAllocation->map(rect, usage, fence, &layout, reinterpret_cast<uint8_t**>(addr));
+ C2Rect rect = C2Rect(capacity(), kLinearBufferHeight);
+ c2_status_t err = mGraphicAllocation->map(rect, usage, fence, &layout, &mMappedAddr);
+ if (err != C2_OK) {
+ ALOGV("C2AllocationBlob: map failed: offset=%zu size=%zu capacity=%u err=%d",
+ offset, size, capacity(), err);
+ mMappedAddr = nullptr;
+ return err;
+ }
+ *addr = mMappedAddr + offset;
+ mMappedOffsetSize.insert({offset, size});
+ ALOGV("C2AllocationBlob: new map succeeded: offset=%zu size=%zu capacity=%u",
+ offset, size, capacity());
+ return C2_OK;
}
c2_status_t C2AllocationBlob::unmap(void* addr, size_t size, C2Fence* fenceFd) {
- C2Rect rect(size, kLinearBufferHeight);
- return mGraphicAllocation->unmap(reinterpret_cast<uint8_t**>(&addr), rect, fenceFd);
+ std::unique_lock<std::mutex> lock(mMapLock);
+ uint8_t *u8Addr = static_cast<uint8_t *>(addr);
+ if (u8Addr < mMappedAddr || mMappedAddr + capacity() < u8Addr + size) {
+ ALOGV("C2AllocationBlob: unmap: Bad addr / size: addr=%p size=%zu capacity=%u",
+ addr, size, capacity());
+ return C2_BAD_VALUE;
+ }
+ auto it = mMappedOffsetSize.find(std::make_pair(u8Addr - mMappedAddr, size));
+ if (it == mMappedOffsetSize.end()) {
+ ALOGV("C2AllocationBlob: unrecognized map: addr=%p size=%zu capacity=%u",
+ addr, size, capacity());
+ return C2_BAD_VALUE;
+ }
+ mMappedOffsetSize.erase(it);
+ if (!mMappedOffsetSize.empty()) {
+ ALOGV("C2AllocationBlob: still maintain mapping: addr=%p size=%zu capacity=%u",
+ addr, size, capacity());
+ return C2_OK;
+ }
+ C2Rect rect(capacity(), kLinearBufferHeight);
+ c2_status_t err = mGraphicAllocation->unmap(&mMappedAddr, rect, fenceFd);
+ ALOGV("C2AllocationBlob: last unmap: addr=%p size=%zu capacity=%u err=%d",
+ addr, size, capacity(), err);
+ mMappedAddr = nullptr;
+ return err;
}
/* ====================================== BLOB ALLOCATOR ====================================== */
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 4d7e619..bee6b7f 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -25,6 +25,7 @@
#include <hardware/gralloc.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
+#include <ui/Rect.h>
#include <C2AllocatorGralloc.h>
#include <C2Buffer.h>
@@ -253,7 +254,7 @@
virtual ~C2AllocationGralloc() override;
virtual c2_status_t map(
- C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+ C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
virtual c2_status_t unmap(
uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
@@ -336,8 +337,12 @@
}
c2_status_t C2AllocationGralloc::map(
- C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+ C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
+ const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
+ (int32_t)(c2Rect.left + c2Rect.width) /* right */,
+ (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
+
uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
ALOGV("mapping buffer with usage %#llx => %#llx",
(long long)usage.expected, (long long)grallocUsage);
@@ -386,10 +391,7 @@
void *pointer = nullptr;
// TODO: fence
status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t *>(mBuffer), grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top,
- (int32_t)rect.width, (int32_t)rect.height },
- &pointer);
+ const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
if (err) {
ALOGE("failed transaction: lock(RGBA_1010102)");
return C2_CORRUPTED;
@@ -464,10 +466,7 @@
void *pointer = nullptr;
// TODO: fence
status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top,
- (int32_t)rect.width, (int32_t)rect.height },
- &pointer);
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
if (err) {
ALOGE("failed transaction: lock(RGBA_8888)");
return C2_CORRUPTED;
@@ -524,10 +523,7 @@
void *pointer = nullptr;
// TODO: fence
status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top,
- (int32_t)rect.width, (int32_t)rect.height },
- &pointer);
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
if (err) {
ALOGE("failed transaction: lock(BLOB)");
return C2_CORRUPTED;
@@ -536,20 +532,33 @@
break;
}
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
+ // fall-through
case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
// fall-through
- case static_cast<uint32_t>(PixelFormat4::YV12):
- // fall-through
- default: {
+ case static_cast<uint32_t>(PixelFormat4::YV12): {
android_ycbcr ycbcrLayout;
status_t err = GraphicBufferMapper::get().lockYCbCr(
- const_cast<native_handle_t*>(mBuffer), grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top,
- (int32_t)rect.width, (int32_t)rect.height },
- &ycbcrLayout);
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
if (err) {
- ALOGE("failed transaction: lockYCbCr");
+ ALOGE("failed transaction: lockYCbCr (err=%d)", err);
+ return C2_CORRUPTED;
+ }
+ if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
+ || ycbcrLayout.ystride == 0
+ || ycbcrLayout.cstride == 0
+ || ycbcrLayout.chroma_step == 0) {
+ ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
+ "ystride=%zu cstride=%zu chroma_step=%zu)",
+ ycbcrLayout.y ? "(non-null)" : "(null)",
+ ycbcrLayout.cb ? "(non-null)" : "(null)",
+ ycbcrLayout.cr ? "(non-null)" : "(null)",
+ ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
return C2_CORRUPTED;
}
@@ -611,6 +620,161 @@
}
break;
}
+
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
+ void *pointer = nullptr;
+ status_t err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(YCBCR_P010)");
+ return C2_CORRUPTED;
+ }
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + mStride * 2 * rect.height();
+ addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 2, // colInc
+ static_cast<int32_t>(2 * mStride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ 4, // colInc
+ static_cast<int32_t>(2 * mStride), // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ 4, // colInc
+ static_cast<int32_t>(2 * mStride), // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 2, // offset
+ };
+ break;
+ }
+
+ default: {
+ // We don't know what it is, but let's try to lock it.
+ android_ycbcr ycbcrLayout;
+
+ status_t err = GraphicBufferMapper::get().lockYCbCr(
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
+ if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
+ && ycbcrLayout.ystride > 0
+ && ycbcrLayout.cstride > 0
+ && ycbcrLayout.chroma_step > 0) {
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
+ addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 3;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 1, // colInc
+ (int32_t)ycbcrLayout.ystride, // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_V, // rootIx
+ 0, // offset
+ };
+ // handle interleaved formats
+ intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
+ if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
+ layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
+ } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
+ layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
+ }
+ break;
+ }
+
+ // We really don't know what this is; lock the buffer and pass it through ---
+ // the client may know how to interpret it.
+ void *pointer = nullptr;
+ err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(??? %x)", mFormat);
+ return C2_CORRUPTED;
+ }
+ addr[0] = (uint8_t *)pointer;
+ layout->type = C2PlanarLayout::TYPE_UNKNOWN;
+ layout->numPlanes = 1;
+ layout->rootPlanes = 1;
+ layout->planes[0] = {
+ // TODO: CHANNEL_UNKNOWN?
+ C2PlaneInfo::channel_t(0xFF), // channel
+ 1, // colInc
+ int32_t(mStride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ 0, // rootIx
+ 0, // offset
+ };
+ break;
+ }
}
mLocked = true;
diff --git a/media/codec2/vndk/C2DmaBufAllocator.cpp b/media/codec2/vndk/C2DmaBufAllocator.cpp
index 59e82e2..750aa31 100644
--- a/media/codec2/vndk/C2DmaBufAllocator.cpp
+++ b/media/codec2/vndk/C2DmaBufAllocator.cpp
@@ -315,8 +315,8 @@
if (mUsageMapper) {
res = mUsageMapper(usage, capacity, heap_name, flags);
} else {
- // No system-uncached yet, so disabled for now
- if (0 && !(usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)))
+ if (C2DmaBufAllocator::system_uncached_supported() &&
+ !(usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)))
*heap_name = "system-uncached";
else
*heap_name = "system";
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 1e907c1..c07c09e 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -102,16 +102,30 @@
}
static bool using_ion(void) {
- static int cached_result = -1;
-
- if (cached_result == -1) {
+ static int cached_result = []()->int {
struct stat buffer;
- cached_result = (stat("/dev/ion", &buffer) == 0);
- if (cached_result)
+ int ret = (stat("/dev/ion", &buffer) == 0);
+
+ if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
+ /*
+ * Double check that the system heap is present so we
+ * can gracefully fail back to ION if we cannot satisfy
+ * the override
+ */
+ ret = (stat("/dev/dma_heap/system", &buffer) != 0);
+ if (ret)
+ ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
+ else
+ ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
+ }
+
+ if (ret)
ALOGD("Using ION\n");
else
ALOGD("Using DMABUF Heaps\n");
- }
+ return ret;
+ }();
+
return (cached_result == 1);
}
@@ -431,7 +445,7 @@
c2_status_t _createBlockPool(
C2PlatformAllocatorStore::id_t allocatorId,
- std::shared_ptr<const C2Component> component,
+ std::vector<std::shared_ptr<const C2Component>> components,
C2BlockPool::local_id_t poolId,
std::shared_ptr<C2BlockPool> *pool) {
std::shared_ptr<C2AllocatorStore> allocatorStore =
@@ -452,7 +466,9 @@
allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
case C2PlatformAllocatorStore::BLOB:
@@ -464,7 +480,9 @@
allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
case C2PlatformAllocatorStore::GRALLOC:
@@ -476,7 +494,9 @@
std::make_shared<C2PooledBlockPool>(allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
case C2PlatformAllocatorStore::BUFFERQUEUE:
@@ -488,7 +508,9 @@
allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
default:
@@ -499,7 +521,9 @@
if (res == C2_OK) {
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
}
@@ -508,9 +532,9 @@
c2_status_t createBlockPool(
C2PlatformAllocatorStore::id_t allocatorId,
- std::shared_ptr<const C2Component> component,
+ std::vector<std::shared_ptr<const C2Component>> components,
std::shared_ptr<C2BlockPool> *pool) {
- return _createBlockPool(allocatorId, component, mBlockPoolSeqId++, pool);
+ return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
}
bool getBlockPool(
@@ -526,8 +550,13 @@
mBlockPools.erase(it);
mComponents.erase(blockPoolId);
} else {
- auto found = mComponents.find(blockPoolId);
- if (component == found->second.lock()) {
+ auto found = std::find_if(
+ mComponents[blockPoolId].begin(),
+ mComponents[blockPoolId].end(),
+ [component](const std::weak_ptr<const C2Component> &ptr) {
+ return component == ptr.lock();
+ });
+ if (found != mComponents[blockPoolId].end()) {
*pool = ptr;
return true;
}
@@ -540,7 +569,7 @@
C2BlockPool::local_id_t mBlockPoolSeqId;
std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
- std::map<C2BlockPool::local_id_t, std::weak_ptr<const C2Component>> mComponents;
+ std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
};
static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
@@ -580,7 +609,7 @@
// TODO: remove this. this is temporary
case C2BlockPool::PLATFORM_START:
res = sBlockPoolCache->_createBlockPool(
- C2PlatformAllocatorStore::BUFFERQUEUE, component, id, pool);
+ C2PlatformAllocatorStore::BUFFERQUEUE, {component}, id, pool);
break;
default:
break;
@@ -590,12 +619,22 @@
c2_status_t CreateCodec2BlockPool(
C2PlatformAllocatorStore::id_t allocatorId,
+ const std::vector<std::shared_ptr<const C2Component>> &components,
+ std::shared_ptr<C2BlockPool> *pool) {
+ pool->reset();
+
+ std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
+ return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
+}
+
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
std::shared_ptr<const C2Component> component,
std::shared_ptr<C2BlockPool> *pool) {
pool->reset();
std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
- return sBlockPoolCache->createBlockPool(allocatorId, component, pool);
+ return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
}
class C2PlatformComponentStore : public C2ComponentStore {
@@ -622,6 +661,12 @@
std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
C2PlatformComponentStore();
+ // For testing only
+ C2PlatformComponentStore(
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>>);
+
virtual ~C2PlatformComponentStore() override = default;
private:
@@ -662,6 +707,24 @@
}
/**
+ * Creates an uninitialized component module.
+ * NOTE: For testing only
+ *
+ * \param name[in] component name.
+ *
+ * \note Only used by ComponentLoader.
+ */
+ ComponentModule(
+ C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
+ C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
+ : mInit(C2_NO_INIT),
+ mLibHandle(nullptr),
+ createFactory(createFactory),
+ destroyFactory(destroyFactory),
+ mComponentFactory(nullptr) {
+ }
+
+ /**
* Initializes a component module with a given library path. Must be called exactly once.
*
* \note Only used by ComponentLoader.
@@ -717,7 +780,13 @@
std::lock_guard<std::mutex> lock(mMutex);
std::shared_ptr<ComponentModule> localModule = mModule.lock();
if (localModule == nullptr) {
- localModule = std::make_shared<ComponentModule>();
+ if(mCreateFactory) {
+ // For testing only
+ localModule = std::make_shared<ComponentModule>(mCreateFactory,
+ mDestroyFactory);
+ } else {
+ localModule = std::make_shared<ComponentModule>();
+ }
res = localModule->init(mLibPath);
if (res == C2_OK) {
mModule = localModule;
@@ -733,10 +802,22 @@
ComponentLoader(std::string libPath)
: mLibPath(libPath) {}
+ // For testing only
+ ComponentLoader(std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc> func)
+ : mLibPath(std::get<0>(func)),
+ mCreateFactory(std::get<1>(func)),
+ mDestroyFactory(std::get<2>(func)) {}
+
private:
std::mutex mMutex; ///< mutex guarding the module
std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
std::string mLibPath; ///< library path
+
+ // For testing only
+ C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
+ C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
};
struct Interface : public C2InterfaceHelper {
@@ -780,7 +861,13 @@
};
static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
- strncpy(me.set().m.heapName, "system", me.v.flexCount());
+ long long usage = (long long)me.get().m.usage;
+ if (C2DmaBufAllocator::system_uncached_supported() &&
+ !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
+ strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
+ } else {
+ strncpy(me.set().m.heapName, "system", me.v.flexCount());
+ }
me.set().m.allocFlags = 0;
return C2R::Ok();
};
@@ -846,25 +933,33 @@
std::shared_ptr<C2ReflectorHelper> mReflector;
Interface mInterface;
+
+ // For testing only
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
};
c2_status_t C2PlatformComponentStore::ComponentModule::init(
std::string libPath) {
ALOGV("in %s", __func__);
ALOGV("loading dll");
- mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
- LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
- "could not dlopen %s: %s", libPath.c_str(), dlerror());
- createFactory =
- (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
- LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
- "createFactory is null in %s", libPath.c_str());
+ if(!createFactory) {
+ mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
+ LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
+ "could not dlopen %s: %s", libPath.c_str(), dlerror());
- destroyFactory =
- (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
- LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
- "destroyFactory is null in %s", libPath.c_str());
+ createFactory =
+ (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
+ LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
+ "createFactory is null in %s", libPath.c_str());
+
+ destroyFactory =
+ (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
+ LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
+ "destroyFactory is null in %s", libPath.c_str());
+ }
mComponentFactory = createFactory();
if (mComponentFactory == nullptr) {
@@ -887,58 +982,10 @@
std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
if (traits) {
- traits->name = intf->getName();
-
- C2ComponentKindSetting kind;
- C2ComponentDomainSetting domain;
- res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
- bool fixDomain = res != C2_OK;
- if (res == C2_OK) {
- traits->kind = kind.value;
- traits->domain = domain.value;
- } else {
- // TODO: remove this fall-back
- ALOGD("failed to query interface for kind and domain: %d", res);
-
- traits->kind =
- (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
- (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
- C2Component::KIND_OTHER;
- }
-
- uint32_t mediaTypeIndex =
- traits->kind == C2Component::KIND_ENCODER ? C2PortMediaTypeSetting::output::PARAM_TYPE
- : C2PortMediaTypeSetting::input::PARAM_TYPE;
- std::vector<std::unique_ptr<C2Param>> params;
- res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms);
- if (res != C2_OK) {
- ALOGD("failed to query interface: %d", res);
+ if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
+ ALOGD("Failed to fill traits from interface");
return mInit;
}
- if (params.size() != 1u) {
- ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
- return mInit;
- }
- C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
- if (mediaTypeConfig == nullptr) {
- ALOGD("failed to query media type");
- return mInit;
- }
- traits->mediaType =
- std::string(mediaTypeConfig->m.value,
- strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
-
- if (fixDomain) {
- if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
- traits->domain = C2Component::DOMAIN_AUDIO;
- } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
- traits->domain = C2Component::DOMAIN_VIDEO;
- } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
- traits->domain = C2Component::DOMAIN_IMAGE;
- } else {
- traits->domain = C2Component::DOMAIN_OTHER;
- }
- }
// TODO: get this properly from the store during emplace
switch (traits->domain) {
@@ -948,26 +995,6 @@
default:
traits->rank = 512;
}
-
- params.clear();
- res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, ¶ms);
- if (res == C2_OK && params.size() == 1u) {
- C2ComponentAliasesSetting *aliasesSetting =
- C2ComponentAliasesSetting::From(params[0].get());
- if (aliasesSetting) {
- // Split aliases on ','
- // This looks simpler in plain C and even std::string would still make a copy.
- char *aliases = ::strndup(aliasesSetting->m.value, aliasesSetting->flexCount());
- ALOGD("'%s' has aliases: '%s'", intf->getName().c_str(), aliases);
-
- for (char *tok, *ptr, *str = aliases; (tok = ::strtok_r(str, ",", &ptr));
- str = nullptr) {
- traits->aliases.push_back(tok);
- ALOGD("adding alias: '%s'", tok);
- }
- free(aliases);
- }
- }
}
mTraits = traits;
@@ -1065,6 +1092,22 @@
emplace("libcodec2_soft_vp8enc.so");
emplace("libcodec2_soft_vp9dec.so");
emplace("libcodec2_soft_vp9enc.so");
+
+}
+
+// For testing only
+C2PlatformComponentStore::C2PlatformComponentStore(
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
+ : mVisited(false),
+ mReflector(std::make_shared<C2ReflectorHelper>()),
+ mInterface(mReflector),
+ mCodec2FactoryFuncs(funcs) {
+
+ for(auto const& func: mCodec2FactoryFuncs) {
+ mComponents.emplace(std::get<0>(func), func);
+ }
}
c2_status_t C2PlatformComponentStore::copyBuffer(
@@ -1184,4 +1227,11 @@
return store;
}
+// For testing only
+std::shared_ptr<C2ComponentStore> GetTestComponentStore(
+ std::vector<std::tuple<C2String,
+ C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
+ return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
+}
} // namespace android
diff --git a/media/codec2/vndk/include/C2DmaBufAllocator.h b/media/codec2/vndk/include/C2DmaBufAllocator.h
index abb8307..d84c8c6 100644
--- a/media/codec2/vndk/include/C2DmaBufAllocator.h
+++ b/media/codec2/vndk/include/C2DmaBufAllocator.h
@@ -84,6 +84,16 @@
void setUsageMapper(const UsageMapperFn& mapper, uint64_t minUsage, uint64_t maxUsage,
uint64_t blockSize);
+ static bool system_uncached_supported(void) {
+ static int cached_result = -1;
+
+ if (cached_result == -1) {
+ struct stat buffer;
+ cached_result = (stat("/dev/dma_heap/system-uncached", &buffer) == 0);
+ }
+ return (cached_result == 1);
+ };
+
private:
c2_status_t mInit;
BufferAllocator mBufferAllocator;
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index 4814494..dc82e82 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -138,12 +138,38 @@
std::shared_ptr<C2BlockPool> *pool);
/**
+ * Creates a block pool.
+ * \param allocatorId the allocator ID which is used to allocate blocks
+ * \param components the components using the block pool
+ * \param pool pointer to where the created block pool shall be store on success.
+ * nullptr will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
+ const std::vector<std::shared_ptr<const C2Component>> &components,
+ std::shared_ptr<C2BlockPool> *pool);
+
+/**
* Returns the platform component store.
* \retval nullptr if the platform component store could not be obtained
*/
std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore();
/**
+ * Returns the platform component store.
+ * NOTE: For testing only
+ * \retval nullptr if the platform component store could not be obtained
+ */
+std::shared_ptr<C2ComponentStore> GetTestComponentStore(
+ std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
+ C2ComponentFactory::DestroyCodec2FactoryFunc>>);
+
+/**
* Sets the preferred component store in this process for the sole purpose of accessing its
* interface. If this is not called, the default IComponentStore HAL (if exists) is the preferred
* store for this purpose. If the default IComponentStore HAL is not present, the platform
diff --git a/media/codec2/vndk/include/util/C2InterfaceUtils.h b/media/codec2/vndk/include/util/C2InterfaceUtils.h
index e9037e5..13bdac3 100644
--- a/media/codec2/vndk/include/util/C2InterfaceUtils.h
+++ b/media/codec2/vndk/include/util/C2InterfaceUtils.h
@@ -17,6 +17,7 @@
#ifndef C2UTILS_INTERFACE_UTILS_H_
#define C2UTILS_INTERFACE_UTILS_H_
+#include <C2Component.h>
#include <C2Param.h>
#include <C2Work.h>
@@ -1130,6 +1131,19 @@
};
+/**
+ * Utility class for C2ComponentInterface
+ */
+struct C2InterfaceUtils {
+ /**
+ * Create traits from C2ComponentInterface. Note that rank cannot be queried from interfaces,
+ * so left untouched.
+ */
+ static bool FillTraitsFromInterface(
+ C2Component::Traits *traits,
+ const std::shared_ptr<C2ComponentInterface> &intf);
+};
+
#include <util/C2Debug-interface.h>
#endif // C2UTILS_INTERFACE_UTILS_H_
diff --git a/media/codec2/vndk/util/C2InterfaceHelper.cpp b/media/codec2/vndk/util/C2InterfaceHelper.cpp
index 9eb52d2..19d2295 100644
--- a/media/codec2/vndk/util/C2InterfaceHelper.cpp
+++ b/media/codec2/vndk/util/C2InterfaceHelper.cpp
@@ -645,6 +645,7 @@
lateReadParams.emplace_back(p);
std::unique_ptr<C2Param> request(C2Param::CopyAsRequest(*p));
p = request.get();
+ paramIx = p->index();
paramRequests.emplace_back(std::move(request));
}
}
diff --git a/media/codec2/vndk/util/C2InterfaceUtils.cpp b/media/codec2/vndk/util/C2InterfaceUtils.cpp
index 0c1729b..b5bc691 100644
--- a/media/codec2/vndk/util/C2InterfaceUtils.cpp
+++ b/media/codec2/vndk/util/C2InterfaceUtils.cpp
@@ -21,6 +21,7 @@
#define C2_LOG_VERBOSE
+#include <C2Config.h>
#include <C2Debug.h>
#include <C2Param.h>
#include <C2ParamDef.h>
@@ -30,6 +31,7 @@
#include <cmath>
#include <limits>
#include <map>
+#include <sstream>
#include <type_traits>
#include <android-base/stringprintf.h>
@@ -1304,3 +1306,81 @@
return std::vector<Info>(location.begin(), location.end());
}
+//static
+bool C2InterfaceUtils::FillTraitsFromInterface(
+ C2Component::Traits *traits,
+ const std::shared_ptr<C2ComponentInterface> &intf) {
+ if (!traits) {
+ return false;
+ }
+ traits->name = intf->getName();
+
+ C2ComponentKindSetting kind;
+ C2ComponentDomainSetting domain;
+ c2_status_t res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
+ bool fixDomain = res != C2_OK;
+ if (res == C2_OK) {
+ traits->kind = kind.value;
+ traits->domain = domain.value;
+ } else {
+ // TODO: remove this fall-back
+ C2_LOG(DEBUG) << "failed to query interface for kind and domain: " << res;
+
+ traits->kind =
+ (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
+ (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
+ C2Component::KIND_OTHER;
+ }
+
+ uint32_t mediaTypeIndex = traits->kind == C2Component::KIND_ENCODER
+ ? C2PortMediaTypeSetting::output::PARAM_TYPE
+ : C2PortMediaTypeSetting::input::PARAM_TYPE;
+ std::vector<std::unique_ptr<C2Param>> params;
+ res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms);
+ if (res != C2_OK) {
+ C2_LOG(DEBUG) << "failed to query interface: " << res;
+ return false;
+ }
+ if (params.size() != 1u) {
+ C2_LOG(DEBUG) << "failed to query interface: unexpected vector size: " << params.size();
+ return false;
+ }
+ C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
+ if (mediaTypeConfig == nullptr) {
+ C2_LOG(DEBUG) << "failed to query media type";
+ return false;
+ }
+ traits->mediaType =
+ std::string(mediaTypeConfig->m.value,
+ strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
+
+ if (fixDomain) {
+ if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
+ traits->domain = C2Component::DOMAIN_AUDIO;
+ } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
+ traits->domain = C2Component::DOMAIN_VIDEO;
+ } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
+ traits->domain = C2Component::DOMAIN_IMAGE;
+ } else {
+ traits->domain = C2Component::DOMAIN_OTHER;
+ }
+ }
+
+ params.clear();
+ res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, ¶ms);
+ if (res == C2_OK && params.size() == 1u) {
+ C2ComponentAliasesSetting *aliasesSetting =
+ C2ComponentAliasesSetting::From(params[0].get());
+ if (aliasesSetting) {
+ std::istringstream iss(
+ std::string(aliasesSetting->m.value, aliasesSetting->flexCount()));
+ C2_LOG(DEBUG) << intf->getName() << " has aliases: " << iss.str();
+
+ for (std::string tok; std::getline(iss, tok, ','); ) {
+ traits->aliases.push_back(tok);
+ C2_LOG(DEBUG) << "adding alias: " << tok;
+ }
+ }
+ }
+ return true;
+}
diff --git a/media/codecs/amrnb/TEST_MAPPING b/media/codecs/amrnb/TEST_MAPPING
new file mode 100644
index 0000000..343d08a
--- /dev/null
+++ b/media/codecs/amrnb/TEST_MAPPING
@@ -0,0 +1,10 @@
+// mappings for frameworks/av/media/libstagefright/codecs/amrnb
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "AmrnbDecoderTest"},
+ { "name": "AmrnbEncoderTest"}
+ ]
+}
diff --git a/media/libstagefright/codecs/amrnb/common/Android.bp b/media/codecs/amrnb/common/Android.bp
similarity index 83%
rename from media/libstagefright/codecs/amrnb/common/Android.bp
rename to media/codecs/amrnb/common/Android.bp
index 59a791d..bae65f3 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.bp
+++ b/media/codecs/amrnb/common/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrnb_common_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_amrnb_common_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libstagefright_amrnb_common",
vendor_available: true,
diff --git a/media/libstagefright/codecs/amrnb/common/MODULE_LICENSE_APACHE2 b/media/codecs/amrnb/common/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/MODULE_LICENSE_APACHE2
rename to media/codecs/amrnb/common/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/common/NOTICE b/media/codecs/amrnb/common/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/NOTICE
rename to media/codecs/amrnb/common/NOTICE
diff --git a/media/libstagefright/codecs/amrnb/common/include/abs_s.h b/media/codecs/amrnb/common/include/abs_s.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/abs_s.h
rename to media/codecs/amrnb/common/include/abs_s.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/add.h b/media/codecs/amrnb/common/include/add.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/add.h
rename to media/codecs/amrnb/common/include/add.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/az_lsp.h b/media/codecs/amrnb/common/include/az_lsp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/az_lsp.h
rename to media/codecs/amrnb/common/include/az_lsp.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op.h b/media/codecs/amrnb/common/include/basic_op.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/basic_op.h
rename to media/codecs/amrnb/common/include/basic_op.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h b/media/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
rename to media/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_v5.h b/media/codecs/amrnb/common/include/basic_op_arm_v5.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/basic_op_arm_v5.h
rename to media/codecs/amrnb/common/include/basic_op_arm_v5.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h b/media/codecs/amrnb/common/include/basic_op_c_equivalent.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h
rename to media/codecs/amrnb/common/include/basic_op_c_equivalent.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/basicop_malloc.h b/media/codecs/amrnb/common/include/basicop_malloc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/basicop_malloc.h
rename to media/codecs/amrnb/common/include/basicop_malloc.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/bitno_tab.h b/media/codecs/amrnb/common/include/bitno_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/bitno_tab.h
rename to media/codecs/amrnb/common/include/bitno_tab.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/bitreorder_tab.h b/media/codecs/amrnb/common/include/bitreorder_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/bitreorder_tab.h
rename to media/codecs/amrnb/common/include/bitreorder_tab.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/bits2prm.h b/media/codecs/amrnb/common/include/bits2prm.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/bits2prm.h
rename to media/codecs/amrnb/common/include/bits2prm.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/cnst.h b/media/codecs/amrnb/common/include/cnst.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/cnst.h
rename to media/codecs/amrnb/common/include/cnst.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/cnst_vad.h b/media/codecs/amrnb/common/include/cnst_vad.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/cnst_vad.h
rename to media/codecs/amrnb/common/include/cnst_vad.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/copy.h b/media/codecs/amrnb/common/include/copy.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/copy.h
rename to media/codecs/amrnb/common/include/copy.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/d_gain_c.h b/media/codecs/amrnb/common/include/d_gain_c.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/d_gain_c.h
rename to media/codecs/amrnb/common/include/d_gain_c.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/d_gain_p.h b/media/codecs/amrnb/common/include/d_gain_p.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/d_gain_p.h
rename to media/codecs/amrnb/common/include/d_gain_p.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/d_plsf.h b/media/codecs/amrnb/common/include/d_plsf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/d_plsf.h
rename to media/codecs/amrnb/common/include/d_plsf.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/div_32.h b/media/codecs/amrnb/common/include/div_32.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/div_32.h
rename to media/codecs/amrnb/common/include/div_32.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/div_s.h b/media/codecs/amrnb/common/include/div_s.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/div_s.h
rename to media/codecs/amrnb/common/include/div_s.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/dtx_common_def.h b/media/codecs/amrnb/common/include/dtx_common_def.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/dtx_common_def.h
rename to media/codecs/amrnb/common/include/dtx_common_def.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/extract_h.h b/media/codecs/amrnb/common/include/extract_h.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/extract_h.h
rename to media/codecs/amrnb/common/include/extract_h.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/extract_l.h b/media/codecs/amrnb/common/include/extract_l.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/extract_l.h
rename to media/codecs/amrnb/common/include/extract_l.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/frame.h b/media/codecs/amrnb/common/include/frame.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/frame.h
rename to media/codecs/amrnb/common/include/frame.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h b/media/codecs/amrnb/common/include/frame_type_3gpp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h
rename to media/codecs/amrnb/common/include/frame_type_3gpp.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/gc_pred.h b/media/codecs/amrnb/common/include/gc_pred.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/gc_pred.h
rename to media/codecs/amrnb/common/include/gc_pred.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/gmed_n.h b/media/codecs/amrnb/common/include/gmed_n.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/gmed_n.h
rename to media/codecs/amrnb/common/include/gmed_n.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/gsm_amr_typedefs.h b/media/codecs/amrnb/common/include/gsm_amr_typedefs.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/gsm_amr_typedefs.h
rename to media/codecs/amrnb/common/include/gsm_amr_typedefs.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/int_lpc.h b/media/codecs/amrnb/common/include/int_lpc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/int_lpc.h
rename to media/codecs/amrnb/common/include/int_lpc.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/int_lsf.h b/media/codecs/amrnb/common/include/int_lsf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/int_lsf.h
rename to media/codecs/amrnb/common/include/int_lsf.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h b/media/codecs/amrnb/common/include/inv_sqrt.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h
rename to media/codecs/amrnb/common/include/inv_sqrt.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_abs.h b/media/codecs/amrnb/common/include/l_abs.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_abs.h
rename to media/codecs/amrnb/common/include/l_abs.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_add.h b/media/codecs/amrnb/common/include/l_add.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_add.h
rename to media/codecs/amrnb/common/include/l_add.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_add_c.h b/media/codecs/amrnb/common/include/l_add_c.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_add_c.h
rename to media/codecs/amrnb/common/include/l_add_c.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_comp.h b/media/codecs/amrnb/common/include/l_comp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_comp.h
rename to media/codecs/amrnb/common/include/l_comp.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_deposit_h.h b/media/codecs/amrnb/common/include/l_deposit_h.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_deposit_h.h
rename to media/codecs/amrnb/common/include/l_deposit_h.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_deposit_l.h b/media/codecs/amrnb/common/include/l_deposit_l.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_deposit_l.h
rename to media/codecs/amrnb/common/include/l_deposit_l.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_extract.h b/media/codecs/amrnb/common/include/l_extract.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_extract.h
rename to media/codecs/amrnb/common/include/l_extract.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_mac.h b/media/codecs/amrnb/common/include/l_mac.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_mac.h
rename to media/codecs/amrnb/common/include/l_mac.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_msu.h b/media/codecs/amrnb/common/include/l_msu.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_msu.h
rename to media/codecs/amrnb/common/include/l_msu.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_mult.h b/media/codecs/amrnb/common/include/l_mult.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_mult.h
rename to media/codecs/amrnb/common/include/l_mult.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_negate.h b/media/codecs/amrnb/common/include/l_negate.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_negate.h
rename to media/codecs/amrnb/common/include/l_negate.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_shl.h b/media/codecs/amrnb/common/include/l_shl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_shl.h
rename to media/codecs/amrnb/common/include/l_shl.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_shr.h b/media/codecs/amrnb/common/include/l_shr.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_shr.h
rename to media/codecs/amrnb/common/include/l_shr.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_shr_r.h b/media/codecs/amrnb/common/include/l_shr_r.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_shr_r.h
rename to media/codecs/amrnb/common/include/l_shr_r.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_sub.h b/media/codecs/amrnb/common/include/l_sub.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/l_sub.h
rename to media/codecs/amrnb/common/include/l_sub.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/log2.h b/media/codecs/amrnb/common/include/log2.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/log2.h
rename to media/codecs/amrnb/common/include/log2.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/log2_norm.h b/media/codecs/amrnb/common/include/log2_norm.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/log2_norm.h
rename to media/codecs/amrnb/common/include/log2_norm.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsfwt.h b/media/codecs/amrnb/common/include/lsfwt.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/lsfwt.h
rename to media/codecs/amrnb/common/include/lsfwt.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp.h b/media/codecs/amrnb/common/include/lsp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/lsp.h
rename to media/codecs/amrnb/common/include/lsp.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp_az.h b/media/codecs/amrnb/common/include/lsp_az.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/lsp_az.h
rename to media/codecs/amrnb/common/include/lsp_az.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp_lsf.h b/media/codecs/amrnb/common/include/lsp_lsf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/lsp_lsf.h
rename to media/codecs/amrnb/common/include/lsp_lsf.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp_tab.h b/media/codecs/amrnb/common/include/lsp_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/lsp_tab.h
rename to media/codecs/amrnb/common/include/lsp_tab.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/mac_32.h b/media/codecs/amrnb/common/include/mac_32.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/mac_32.h
rename to media/codecs/amrnb/common/include/mac_32.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/mode.h b/media/codecs/amrnb/common/include/mode.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/mode.h
rename to media/codecs/amrnb/common/include/mode.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/mpy_32.h b/media/codecs/amrnb/common/include/mpy_32.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/mpy_32.h
rename to media/codecs/amrnb/common/include/mpy_32.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/mpy_32_16.h b/media/codecs/amrnb/common/include/mpy_32_16.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/mpy_32_16.h
rename to media/codecs/amrnb/common/include/mpy_32_16.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/mult.h b/media/codecs/amrnb/common/include/mult.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/mult.h
rename to media/codecs/amrnb/common/include/mult.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/mult_r.h b/media/codecs/amrnb/common/include/mult_r.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/mult_r.h
rename to media/codecs/amrnb/common/include/mult_r.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/n_proc.h b/media/codecs/amrnb/common/include/n_proc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/n_proc.h
rename to media/codecs/amrnb/common/include/n_proc.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/negate.h b/media/codecs/amrnb/common/include/negate.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/negate.h
rename to media/codecs/amrnb/common/include/negate.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/norm_l.h b/media/codecs/amrnb/common/include/norm_l.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/norm_l.h
rename to media/codecs/amrnb/common/include/norm_l.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/norm_s.h b/media/codecs/amrnb/common/include/norm_s.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/norm_s.h
rename to media/codecs/amrnb/common/include/norm_s.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/oper_32b.h b/media/codecs/amrnb/common/include/oper_32b.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/oper_32b.h
rename to media/codecs/amrnb/common/include/oper_32b.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/p_ol_wgh.h b/media/codecs/amrnb/common/include/p_ol_wgh.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/p_ol_wgh.h
rename to media/codecs/amrnb/common/include/p_ol_wgh.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/pow2.h b/media/codecs/amrnb/common/include/pow2.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/pow2.h
rename to media/codecs/amrnb/common/include/pow2.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/pred_lt.h b/media/codecs/amrnb/common/include/pred_lt.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/pred_lt.h
rename to media/codecs/amrnb/common/include/pred_lt.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/q_plsf.h b/media/codecs/amrnb/common/include/q_plsf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/q_plsf.h
rename to media/codecs/amrnb/common/include/q_plsf.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/q_plsf_3_tbl.h b/media/codecs/amrnb/common/include/q_plsf_3_tbl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/q_plsf_3_tbl.h
rename to media/codecs/amrnb/common/include/q_plsf_3_tbl.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/q_plsf_5_tbl.h b/media/codecs/amrnb/common/include/q_plsf_5_tbl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/q_plsf_5_tbl.h
rename to media/codecs/amrnb/common/include/q_plsf_5_tbl.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/qgain475_tab.h b/media/codecs/amrnb/common/include/qgain475_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/qgain475_tab.h
rename to media/codecs/amrnb/common/include/qgain475_tab.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/qua_gain.h b/media/codecs/amrnb/common/include/qua_gain.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/qua_gain.h
rename to media/codecs/amrnb/common/include/qua_gain.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/qua_gain_tbl.h b/media/codecs/amrnb/common/include/qua_gain_tbl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/qua_gain_tbl.h
rename to media/codecs/amrnb/common/include/qua_gain_tbl.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/reorder.h b/media/codecs/amrnb/common/include/reorder.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/reorder.h
rename to media/codecs/amrnb/common/include/reorder.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/residu.h b/media/codecs/amrnb/common/include/residu.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/residu.h
rename to media/codecs/amrnb/common/include/residu.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/reverse_bits.h b/media/codecs/amrnb/common/include/reverse_bits.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/reverse_bits.h
rename to media/codecs/amrnb/common/include/reverse_bits.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/round.h b/media/codecs/amrnb/common/include/round.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/round.h
rename to media/codecs/amrnb/common/include/round.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/set_zero.h b/media/codecs/amrnb/common/include/set_zero.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/set_zero.h
rename to media/codecs/amrnb/common/include/set_zero.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/shl.h b/media/codecs/amrnb/common/include/shl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/shl.h
rename to media/codecs/amrnb/common/include/shl.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/shr.h b/media/codecs/amrnb/common/include/shr.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/shr.h
rename to media/codecs/amrnb/common/include/shr.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/shr_r.h b/media/codecs/amrnb/common/include/shr_r.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/shr_r.h
rename to media/codecs/amrnb/common/include/shr_r.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h b/media/codecs/amrnb/common/include/sqrt_l.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/sqrt_l.h
rename to media/codecs/amrnb/common/include/sqrt_l.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/sub.h b/media/codecs/amrnb/common/include/sub.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/sub.h
rename to media/codecs/amrnb/common/include/sub.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/syn_filt.h b/media/codecs/amrnb/common/include/syn_filt.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/syn_filt.h
rename to media/codecs/amrnb/common/include/syn_filt.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/typedef.h b/media/codecs/amrnb/common/include/typedef.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/typedef.h
rename to media/codecs/amrnb/common/include/typedef.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/vad.h b/media/codecs/amrnb/common/include/vad.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/vad.h
rename to media/codecs/amrnb/common/include/vad.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/vad1.h b/media/codecs/amrnb/common/include/vad1.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/vad1.h
rename to media/codecs/amrnb/common/include/vad1.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/vad2.h b/media/codecs/amrnb/common/include/vad2.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/vad2.h
rename to media/codecs/amrnb/common/include/vad2.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/weight_a.h b/media/codecs/amrnb/common/include/weight_a.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/weight_a.h
rename to media/codecs/amrnb/common/include/weight_a.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/window_tab.h b/media/codecs/amrnb/common/include/window_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/window_tab.h
rename to media/codecs/amrnb/common/include/window_tab.h
diff --git a/media/libstagefright/codecs/amrnb/common/include/wmf_to_ets.h b/media/codecs/amrnb/common/include/wmf_to_ets.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/include/wmf_to_ets.h
rename to media/codecs/amrnb/common/include/wmf_to_ets.h
diff --git a/media/libstagefright/codecs/amrnb/common/src/add.cpp b/media/codecs/amrnb/common/src/add.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/add.cpp
rename to media/codecs/amrnb/common/src/add.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp b/media/codecs/amrnb/common/src/az_lsp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp
rename to media/codecs/amrnb/common/src/az_lsp.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp b/media/codecs/amrnb/common/src/bitno_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp
rename to media/codecs/amrnb/common/src/bitno_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp b/media/codecs/amrnb/common/src/bitreorder_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp
rename to media/codecs/amrnb/common/src/bitreorder_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/bits2prm.cpp b/media/codecs/amrnb/common/src/bits2prm.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/bits2prm.cpp
rename to media/codecs/amrnb/common/src/bits2prm.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp b/media/codecs/amrnb/common/src/c2_9pf_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp
rename to media/codecs/amrnb/common/src/c2_9pf_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/copy.cpp b/media/codecs/amrnb/common/src/copy.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/copy.cpp
rename to media/codecs/amrnb/common/src/copy.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/div_32.cpp b/media/codecs/amrnb/common/src/div_32.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/div_32.cpp
rename to media/codecs/amrnb/common/src/div_32.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/div_s.cpp b/media/codecs/amrnb/common/src/div_s.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/div_s.cpp
rename to media/codecs/amrnb/common/src/div_s.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/extract_h.cpp b/media/codecs/amrnb/common/src/extract_h.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/extract_h.cpp
rename to media/codecs/amrnb/common/src/extract_h.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/extract_l.cpp b/media/codecs/amrnb/common/src/extract_l.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/extract_l.cpp
rename to media/codecs/amrnb/common/src/extract_l.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp b/media/codecs/amrnb/common/src/gains_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp
rename to media/codecs/amrnb/common/src/gains_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp b/media/codecs/amrnb/common/src/gc_pred.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp
rename to media/codecs/amrnb/common/src/gc_pred.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp b/media/codecs/amrnb/common/src/gmed_n.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp
rename to media/codecs/amrnb/common/src/gmed_n.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp b/media/codecs/amrnb/common/src/gray_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp
rename to media/codecs/amrnb/common/src/gray_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp b/media/codecs/amrnb/common/src/grid_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp
rename to media/codecs/amrnb/common/src/grid_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/int_lpc.cpp b/media/codecs/amrnb/common/src/int_lpc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/int_lpc.cpp
rename to media/codecs/amrnb/common/src/int_lpc.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/inv_sqrt.cpp b/media/codecs/amrnb/common/src/inv_sqrt.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/inv_sqrt.cpp
rename to media/codecs/amrnb/common/src/inv_sqrt.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp b/media/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
rename to media/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp b/media/codecs/amrnb/common/src/l_abs.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/l_abs.cpp
rename to media/codecs/amrnb/common/src/l_abs.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_deposit_h.cpp b/media/codecs/amrnb/common/src/l_deposit_h.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/l_deposit_h.cpp
rename to media/codecs/amrnb/common/src/l_deposit_h.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_deposit_l.cpp b/media/codecs/amrnb/common/src/l_deposit_l.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/l_deposit_l.cpp
rename to media/codecs/amrnb/common/src/l_deposit_l.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp b/media/codecs/amrnb/common/src/l_shr_r.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp
rename to media/codecs/amrnb/common/src/l_shr_r.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/log2.cpp b/media/codecs/amrnb/common/src/log2.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/log2.cpp
rename to media/codecs/amrnb/common/src/log2.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/log2_norm.cpp b/media/codecs/amrnb/common/src/log2_norm.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/log2_norm.cpp
rename to media/codecs/amrnb/common/src/log2_norm.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp b/media/codecs/amrnb/common/src/log2_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp
rename to media/codecs/amrnb/common/src/log2_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsfwt.cpp b/media/codecs/amrnb/common/src/lsfwt.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/lsfwt.cpp
rename to media/codecs/amrnb/common/src/lsfwt.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp.cpp b/media/codecs/amrnb/common/src/lsp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/lsp.cpp
rename to media/codecs/amrnb/common/src/lsp.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp b/media/codecs/amrnb/common/src/lsp_az.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp
rename to media/codecs/amrnb/common/src/lsp_az.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_lsf.cpp b/media/codecs/amrnb/common/src/lsp_lsf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/lsp_lsf.cpp
rename to media/codecs/amrnb/common/src/lsp_lsf.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp b/media/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
rename to media/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp b/media/codecs/amrnb/common/src/lsp_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp
rename to media/codecs/amrnb/common/src/lsp_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp b/media/codecs/amrnb/common/src/mult_r.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/mult_r.cpp
rename to media/codecs/amrnb/common/src/mult_r.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/negate.cpp b/media/codecs/amrnb/common/src/negate.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/negate.cpp
rename to media/codecs/amrnb/common/src/negate.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp b/media/codecs/amrnb/common/src/norm_l.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/norm_l.cpp
rename to media/codecs/amrnb/common/src/norm_l.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp b/media/codecs/amrnb/common/src/norm_s.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/norm_s.cpp
rename to media/codecs/amrnb/common/src/norm_s.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp b/media/codecs/amrnb/common/src/ph_disp_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp
rename to media/codecs/amrnb/common/src/ph_disp_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/pow2.cpp b/media/codecs/amrnb/common/src/pow2.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/pow2.cpp
rename to media/codecs/amrnb/common/src/pow2.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp b/media/codecs/amrnb/common/src/pow2_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp
rename to media/codecs/amrnb/common/src/pow2_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp b/media/codecs/amrnb/common/src/pred_lt.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp
rename to media/codecs/amrnb/common/src/pred_lt.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf.cpp b/media/codecs/amrnb/common/src/q_plsf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/q_plsf.cpp
rename to media/codecs/amrnb/common/src/q_plsf.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp b/media/codecs/amrnb/common/src/q_plsf_3.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp
rename to media/codecs/amrnb/common/src/q_plsf_3.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_3_tbl.cpp b/media/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
rename to media/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_5.cpp b/media/codecs/amrnb/common/src/q_plsf_5.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/q_plsf_5.cpp
rename to media/codecs/amrnb/common/src/q_plsf_5.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp b/media/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
rename to media/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp b/media/codecs/amrnb/common/src/qua_gain_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp
rename to media/codecs/amrnb/common/src/qua_gain_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/reorder.cpp b/media/codecs/amrnb/common/src/reorder.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/reorder.cpp
rename to media/codecs/amrnb/common/src/reorder.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/residu.cpp b/media/codecs/amrnb/common/src/residu.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/residu.cpp
rename to media/codecs/amrnb/common/src/residu.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/round.cpp b/media/codecs/amrnb/common/src/round.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/round.cpp
rename to media/codecs/amrnb/common/src/round.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/set_zero.cpp b/media/codecs/amrnb/common/src/set_zero.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/set_zero.cpp
rename to media/codecs/amrnb/common/src/set_zero.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/shr.cpp b/media/codecs/amrnb/common/src/shr.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/shr.cpp
rename to media/codecs/amrnb/common/src/shr.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp b/media/codecs/amrnb/common/src/shr_r.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/shr_r.cpp
rename to media/codecs/amrnb/common/src/shr_r.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/sqrt_l.cpp b/media/codecs/amrnb/common/src/sqrt_l.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/sqrt_l.cpp
rename to media/codecs/amrnb/common/src/sqrt_l.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp b/media/codecs/amrnb/common/src/sqrt_l_tbl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp
rename to media/codecs/amrnb/common/src/sqrt_l_tbl.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/sub.cpp b/media/codecs/amrnb/common/src/sub.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/sub.cpp
rename to media/codecs/amrnb/common/src/sub.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/syn_filt.cpp b/media/codecs/amrnb/common/src/syn_filt.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/syn_filt.cpp
rename to media/codecs/amrnb/common/src/syn_filt.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/vad1.cpp b/media/codecs/amrnb/common/src/vad1.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/vad1.cpp
rename to media/codecs/amrnb/common/src/vad1.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp b/media/codecs/amrnb/common/src/weight_a.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/weight_a.cpp
rename to media/codecs/amrnb/common/src/weight_a.cpp
diff --git a/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp b/media/codecs/amrnb/common/src/window_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/common/src/window_tab.cpp
rename to media/codecs/amrnb/common/src/window_tab.cpp
diff --git a/media/codecs/amrnb/dec/Android.bp b/media/codecs/amrnb/dec/Android.bp
new file mode 100644
index 0000000..1083b82
--- /dev/null
+++ b/media/codecs/amrnb/dec/Android.bp
@@ -0,0 +1,138 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrnb_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_amrnb_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library_static {
+ name: "libstagefright_amrnbdec",
+ vendor_available: true,
+ host_supported: true,
+ min_sdk_version: "29",
+
+ srcs: [
+ "src/a_refl.cpp",
+ "src/agc.cpp",
+ "src/amrdecode.cpp",
+ "src/b_cn_cod.cpp",
+ "src/bgnscd.cpp",
+ "src/c_g_aver.cpp",
+ "src/d1035pf.cpp",
+ "src/d2_11pf.cpp",
+ "src/d2_9pf.cpp",
+ "src/d3_14pf.cpp",
+ "src/d4_17pf.cpp",
+ "src/d8_31pf.cpp",
+ "src/d_gain_c.cpp",
+ "src/d_gain_p.cpp",
+ "src/d_plsf.cpp",
+ "src/d_plsf_3.cpp",
+ "src/d_plsf_5.cpp",
+ "src/dec_amr.cpp",
+ "src/dec_gain.cpp",
+ "src/dec_input_format_tab.cpp",
+ "src/dec_lag3.cpp",
+ "src/dec_lag6.cpp",
+ "src/dtx_dec.cpp",
+ "src/ec_gains.cpp",
+ "src/ex_ctrl.cpp",
+ "src/if2_to_ets.cpp",
+ "src/int_lsf.cpp",
+ "src/lsp_avg.cpp",
+ "src/ph_disp.cpp",
+ "src/post_pro.cpp",
+ "src/preemph.cpp",
+ "src/pstfilt.cpp",
+ "src/qgain475_tab.cpp",
+ "src/sp_dec.cpp",
+ "src/wmf_to_ets.cpp",
+ ],
+
+ export_include_dirs: ["src"],
+
+ cflags: [
+ "-DOSCL_UNUSED_ARG(x)=(void)(x)",
+ "-DOSCL_IMPORT_REF=",
+
+ "-Werror",
+ ],
+
+ //sanitize: {
+ // misc_undefined: [
+ // "signed-integer-overflow",
+ // ],
+ //},
+
+ shared_libs: [
+ "libstagefright_amrnb_common",
+ "liblog",
+ ],
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+//###############################################################################
+cc_test {
+ name: "libstagefright_amrnbdec_test",
+ gtest: false,
+ host_supported: true,
+
+ srcs: ["test/amrnbdec_test.cpp"],
+
+ cflags: ["-Wall", "-Werror"],
+
+ local_include_dirs: ["src"],
+
+ static_libs: [
+ "libstagefright_amrnbdec",
+ "libsndfile",
+ ],
+
+ shared_libs: [
+ "libstagefright_amrnb_common",
+ "libaudioutils",
+ "liblog",
+ ],
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
+ //sanitize: {
+ // misc_undefined: [
+ // "signed-integer-overflow",
+ // ],
+ //},
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2 b/media/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
rename to media/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/dec/NOTICE b/media/codecs/amrnb/dec/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/NOTICE
rename to media/codecs/amrnb/dec/NOTICE
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp b/media/codecs/amrnb/dec/src/a_refl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
rename to media/codecs/amrnb/dec/src/a_refl.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.h b/media/codecs/amrnb/dec/src/a_refl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/a_refl.h
rename to media/codecs/amrnb/dec/src/a_refl.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/agc.cpp b/media/codecs/amrnb/dec/src/agc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/agc.cpp
rename to media/codecs/amrnb/dec/src/agc.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/agc.h b/media/codecs/amrnb/dec/src/agc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/agc.h
rename to media/codecs/amrnb/dec/src/agc.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp b/media/codecs/amrnb/dec/src/amrdecode.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp
rename to media/codecs/amrnb/dec/src/amrdecode.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h b/media/codecs/amrnb/dec/src/amrdecode.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/amrdecode.h
rename to media/codecs/amrnb/dec/src/amrdecode.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.cpp b/media/codecs/amrnb/dec/src/b_cn_cod.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.cpp
rename to media/codecs/amrnb/dec/src/b_cn_cod.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.h b/media/codecs/amrnb/dec/src/b_cn_cod.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.h
rename to media/codecs/amrnb/dec/src/b_cn_cod.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/bgnscd.cpp b/media/codecs/amrnb/dec/src/bgnscd.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/bgnscd.cpp
rename to media/codecs/amrnb/dec/src/bgnscd.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/bgnscd.h b/media/codecs/amrnb/dec/src/bgnscd.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/bgnscd.h
rename to media/codecs/amrnb/dec/src/bgnscd.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.cpp b/media/codecs/amrnb/dec/src/c_g_aver.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/c_g_aver.cpp
rename to media/codecs/amrnb/dec/src/c_g_aver.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.h b/media/codecs/amrnb/dec/src/c_g_aver.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/c_g_aver.h
rename to media/codecs/amrnb/dec/src/c_g_aver.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp b/media/codecs/amrnb/dec/src/d1035pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp
rename to media/codecs/amrnb/dec/src/d1035pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d1035pf.h b/media/codecs/amrnb/dec/src/d1035pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d1035pf.h
rename to media/codecs/amrnb/dec/src/d1035pf.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.cpp b/media/codecs/amrnb/dec/src/d2_11pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d2_11pf.cpp
rename to media/codecs/amrnb/dec/src/d2_11pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.h b/media/codecs/amrnb/dec/src/d2_11pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d2_11pf.h
rename to media/codecs/amrnb/dec/src/d2_11pf.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.cpp b/media/codecs/amrnb/dec/src/d2_9pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d2_9pf.cpp
rename to media/codecs/amrnb/dec/src/d2_9pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.h b/media/codecs/amrnb/dec/src/d2_9pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d2_9pf.h
rename to media/codecs/amrnb/dec/src/d2_9pf.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.cpp b/media/codecs/amrnb/dec/src/d3_14pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d3_14pf.cpp
rename to media/codecs/amrnb/dec/src/d3_14pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.h b/media/codecs/amrnb/dec/src/d3_14pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d3_14pf.h
rename to media/codecs/amrnb/dec/src/d3_14pf.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.cpp b/media/codecs/amrnb/dec/src/d4_17pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d4_17pf.cpp
rename to media/codecs/amrnb/dec/src/d4_17pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.h b/media/codecs/amrnb/dec/src/d4_17pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d4_17pf.h
rename to media/codecs/amrnb/dec/src/d4_17pf.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.cpp b/media/codecs/amrnb/dec/src/d8_31pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d8_31pf.cpp
rename to media/codecs/amrnb/dec/src/d8_31pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.h b/media/codecs/amrnb/dec/src/d8_31pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d8_31pf.h
rename to media/codecs/amrnb/dec/src/d8_31pf.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_gain_c.cpp b/media/codecs/amrnb/dec/src/d_gain_c.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d_gain_c.cpp
rename to media/codecs/amrnb/dec/src/d_gain_c.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_gain_p.cpp b/media/codecs/amrnb/dec/src/d_gain_p.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d_gain_p.cpp
rename to media/codecs/amrnb/dec/src/d_gain_p.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf.cpp b/media/codecs/amrnb/dec/src/d_plsf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d_plsf.cpp
rename to media/codecs/amrnb/dec/src/d_plsf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf_3.cpp b/media/codecs/amrnb/dec/src/d_plsf_3.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d_plsf_3.cpp
rename to media/codecs/amrnb/dec/src/d_plsf_3.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp b/media/codecs/amrnb/dec/src/d_plsf_5.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp
rename to media/codecs/amrnb/dec/src/d_plsf_5.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_amr.cpp b/media/codecs/amrnb/dec/src/dec_amr.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_amr.cpp
rename to media/codecs/amrnb/dec/src/dec_amr.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_amr.h b/media/codecs/amrnb/dec/src/dec_amr.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_amr.h
rename to media/codecs/amrnb/dec/src/dec_amr.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_gain.cpp b/media/codecs/amrnb/dec/src/dec_gain.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_gain.cpp
rename to media/codecs/amrnb/dec/src/dec_gain.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_gain.h b/media/codecs/amrnb/dec/src/dec_gain.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_gain.h
rename to media/codecs/amrnb/dec/src/dec_gain.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp b/media/codecs/amrnb/dec/src/dec_input_format_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp
rename to media/codecs/amrnb/dec/src/dec_input_format_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.cpp b/media/codecs/amrnb/dec/src/dec_lag3.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_lag3.cpp
rename to media/codecs/amrnb/dec/src/dec_lag3.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.h b/media/codecs/amrnb/dec/src/dec_lag3.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_lag3.h
rename to media/codecs/amrnb/dec/src/dec_lag3.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.cpp b/media/codecs/amrnb/dec/src/dec_lag6.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_lag6.cpp
rename to media/codecs/amrnb/dec/src/dec_lag6.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.h b/media/codecs/amrnb/dec/src/dec_lag6.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dec_lag6.h
rename to media/codecs/amrnb/dec/src/dec_lag6.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.cpp b/media/codecs/amrnb/dec/src/dtx_dec.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dtx_dec.cpp
rename to media/codecs/amrnb/dec/src/dtx_dec.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.h b/media/codecs/amrnb/dec/src/dtx_dec.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/dtx_dec.h
rename to media/codecs/amrnb/dec/src/dtx_dec.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ec_gains.cpp b/media/codecs/amrnb/dec/src/ec_gains.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/ec_gains.cpp
rename to media/codecs/amrnb/dec/src/ec_gains.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ec_gains.h b/media/codecs/amrnb/dec/src/ec_gains.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/ec_gains.h
rename to media/codecs/amrnb/dec/src/ec_gains.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.cpp b/media/codecs/amrnb/dec/src/ex_ctrl.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.cpp
rename to media/codecs/amrnb/dec/src/ex_ctrl.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.h b/media/codecs/amrnb/dec/src/ex_ctrl.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.h
rename to media/codecs/amrnb/dec/src/ex_ctrl.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h b/media/codecs/amrnb/dec/src/gsmamr_dec.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h
rename to media/codecs/amrnb/dec/src/gsmamr_dec.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.cpp b/media/codecs/amrnb/dec/src/if2_to_ets.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.cpp
rename to media/codecs/amrnb/dec/src/if2_to_ets.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.h b/media/codecs/amrnb/dec/src/if2_to_ets.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.h
rename to media/codecs/amrnb/dec/src/if2_to_ets.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp b/media/codecs/amrnb/dec/src/int_lsf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp
rename to media/codecs/amrnb/dec/src/int_lsf.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.cpp b/media/codecs/amrnb/dec/src/lsp_avg.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/lsp_avg.cpp
rename to media/codecs/amrnb/dec/src/lsp_avg.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.h b/media/codecs/amrnb/dec/src/lsp_avg.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/lsp_avg.h
rename to media/codecs/amrnb/dec/src/lsp_avg.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp b/media/codecs/amrnb/dec/src/ph_disp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp
rename to media/codecs/amrnb/dec/src/ph_disp.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ph_disp.h b/media/codecs/amrnb/dec/src/ph_disp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/ph_disp.h
rename to media/codecs/amrnb/dec/src/ph_disp.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/post_pro.cpp b/media/codecs/amrnb/dec/src/post_pro.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/post_pro.cpp
rename to media/codecs/amrnb/dec/src/post_pro.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/post_pro.h b/media/codecs/amrnb/dec/src/post_pro.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/post_pro.h
rename to media/codecs/amrnb/dec/src/post_pro.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/preemph.cpp b/media/codecs/amrnb/dec/src/preemph.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/preemph.cpp
rename to media/codecs/amrnb/dec/src/preemph.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/preemph.h b/media/codecs/amrnb/dec/src/preemph.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/preemph.h
rename to media/codecs/amrnb/dec/src/preemph.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp b/media/codecs/amrnb/dec/src/pstfilt.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
rename to media/codecs/amrnb/dec/src/pstfilt.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.h b/media/codecs/amrnb/dec/src/pstfilt.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/pstfilt.h
rename to media/codecs/amrnb/dec/src/pstfilt.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp b/media/codecs/amrnb/dec/src/qgain475_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp
rename to media/codecs/amrnb/dec/src/qgain475_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp b/media/codecs/amrnb/dec/src/sp_dec.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp
rename to media/codecs/amrnb/dec/src/sp_dec.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/src/sp_dec.h b/media/codecs/amrnb/dec/src/sp_dec.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/sp_dec.h
rename to media/codecs/amrnb/dec/src/sp_dec.h
diff --git a/media/libstagefright/codecs/amrnb/dec/src/wmf_to_ets.cpp b/media/codecs/amrnb/dec/src/wmf_to_ets.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/src/wmf_to_ets.cpp
rename to media/codecs/amrnb/dec/src/wmf_to_ets.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h b/media/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
rename to media/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
diff --git a/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp b/media/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
rename to media/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
diff --git a/media/libstagefright/codecs/amrnb/dec/test/Android.bp b/media/codecs/amrnb/dec/test/Android.bp
similarity index 72%
rename from media/libstagefright/codecs/amrnb/dec/test/Android.bp
rename to media/codecs/amrnb/dec/test/Android.bp
index 7a95cfa..b882481 100644
--- a/media/libstagefright/codecs/amrnb/dec/test/Android.bp
+++ b/media/codecs/amrnb/dec/test/Android.bp
@@ -14,6 +14,18 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrnb_dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrnb_dec_license",
+ ],
+}
+
cc_test {
name: "AmrnbDecoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/amrnb/dec/test/AndroidTest.xml b/media/codecs/amrnb/dec/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/test/AndroidTest.xml
rename to media/codecs/amrnb/dec/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/amrnb/dec/test/README.md b/media/codecs/amrnb/dec/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/test/README.md
rename to media/codecs/amrnb/dec/test/README.md
diff --git a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp b/media/codecs/amrnb/dec/test/amrnbdec_test.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
rename to media/codecs/amrnb/dec/test/amrnbdec_test.cpp
diff --git a/media/codecs/amrnb/enc/Android.bp b/media/codecs/amrnb/enc/Android.bp
new file mode 100644
index 0000000..9e947e9
--- /dev/null
+++ b/media/codecs/amrnb/enc/Android.bp
@@ -0,0 +1,145 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrnb_enc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_amrnb_enc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library_static {
+ name: "libstagefright_amrnbenc",
+ vendor_available: true,
+ min_sdk_version: "29",
+
+ srcs: [
+ "src/amrencode.cpp",
+ "src/autocorr.cpp",
+ "src/c1035pf.cpp",
+ "src/c2_11pf.cpp",
+ "src/c2_9pf.cpp",
+ "src/c3_14pf.cpp",
+ "src/c4_17pf.cpp",
+ "src/c8_31pf.cpp",
+ "src/calc_cor.cpp",
+ "src/calc_en.cpp",
+ "src/cbsearch.cpp",
+ "src/cl_ltp.cpp",
+ "src/cod_amr.cpp",
+ "src/convolve.cpp",
+ "src/cor_h.cpp",
+ "src/cor_h_x.cpp",
+ "src/cor_h_x2.cpp",
+ "src/corrwght_tab.cpp",
+ "src/dtx_enc.cpp",
+ "src/enc_lag3.cpp",
+ "src/enc_lag6.cpp",
+ "src/enc_output_format_tab.cpp",
+ "src/ets_to_if2.cpp",
+ "src/ets_to_wmf.cpp",
+ "src/g_adapt.cpp",
+ "src/g_code.cpp",
+ "src/g_pitch.cpp",
+ "src/gain_q.cpp",
+ "src/hp_max.cpp",
+ "src/inter_36.cpp",
+ "src/inter_36_tab.cpp",
+ "src/l_comp.cpp",
+ "src/l_extract.cpp",
+ "src/l_negate.cpp",
+ "src/lag_wind.cpp",
+ "src/lag_wind_tab.cpp",
+ "src/levinson.cpp",
+ "src/lpc.cpp",
+ "src/ol_ltp.cpp",
+ "src/p_ol_wgh.cpp",
+ "src/pitch_fr.cpp",
+ "src/pitch_ol.cpp",
+ "src/pre_big.cpp",
+ "src/pre_proc.cpp",
+ "src/prm2bits.cpp",
+ "src/q_gain_c.cpp",
+ "src/q_gain_p.cpp",
+ "src/qgain475.cpp",
+ "src/qgain795.cpp",
+ "src/qua_gain.cpp",
+ "src/s10_8pf.cpp",
+ "src/set_sign.cpp",
+ "src/sid_sync.cpp",
+ "src/sp_enc.cpp",
+ "src/spreproc.cpp",
+ "src/spstproc.cpp",
+ "src/ton_stab.cpp",
+ ],
+
+ header_libs: ["libstagefright_headers"],
+ export_include_dirs: ["src"],
+
+ cflags: [
+ "-DOSCL_UNUSED_ARG(x)=(void)(x)",
+ "-Werror",
+ ],
+
+ //addressing b/25409744
+ //sanitize: {
+ // misc_undefined: [
+ // "signed-integer-overflow",
+ // ],
+ //},
+
+ shared_libs: ["libstagefright_amrnb_common"],
+
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+//###############################################################################
+
+cc_test {
+ name: "libstagefright_amrnbenc_test",
+ gtest: false,
+
+ srcs: ["test/amrnb_enc_test.cpp"],
+
+ cflags: ["-Wall", "-Werror"],
+
+ local_include_dirs: ["src"],
+
+ static_libs: ["libstagefright_amrnbenc"],
+
+ shared_libs: ["libstagefright_amrnb_common"],
+
+ //addressing b/25409744
+ //sanitize: {
+ // misc_undefined: [
+ // "signed-integer-overflow",
+ // ],
+ //},
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2 b/media/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
rename to media/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/enc/NOTICE b/media/codecs/amrnb/enc/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/NOTICE
rename to media/codecs/amrnb/enc/NOTICE
diff --git a/media/libstagefright/codecs/amrnb/enc/fuzzer/Android.bp b/media/codecs/amrnb/enc/fuzzer/Android.bp
similarity index 75%
rename from media/libstagefright/codecs/amrnb/enc/fuzzer/Android.bp
rename to media/codecs/amrnb/enc/fuzzer/Android.bp
index e88e5eb..2c041b7 100644
--- a/media/libstagefright/codecs/amrnb/enc/fuzzer/Android.bp
+++ b/media/codecs/amrnb/enc/fuzzer/Android.bp
@@ -18,6 +18,17 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrnb_enc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrnb_enc_license",
+ ],
+}
+
cc_fuzz {
name: "amrnb_enc_fuzzer",
host_supported: true,
diff --git a/media/libstagefright/codecs/amrnb/enc/fuzzer/README.md b/media/codecs/amrnb/enc/fuzzer/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/fuzzer/README.md
rename to media/codecs/amrnb/enc/fuzzer/README.md
diff --git a/media/libstagefright/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp b/media/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
rename to media/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/amrencode.cpp b/media/codecs/amrnb/enc/src/amrencode.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/amrencode.cpp
rename to media/codecs/amrnb/enc/src/amrencode.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/amrencode.h b/media/codecs/amrnb/enc/src/amrencode.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/amrencode.h
rename to media/codecs/amrnb/enc/src/amrencode.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp b/media/codecs/amrnb/enc/src/autocorr.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp
rename to media/codecs/amrnb/enc/src/autocorr.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/autocorr.h b/media/codecs/amrnb/enc/src/autocorr.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/autocorr.h
rename to media/codecs/amrnb/enc/src/autocorr.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c1035pf.cpp b/media/codecs/amrnb/enc/src/c1035pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c1035pf.cpp
rename to media/codecs/amrnb/enc/src/c1035pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c1035pf.h b/media/codecs/amrnb/enc/src/c1035pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c1035pf.h
rename to media/codecs/amrnb/enc/src/c1035pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.cpp b/media/codecs/amrnb/enc/src/c2_11pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c2_11pf.cpp
rename to media/codecs/amrnb/enc/src/c2_11pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.h b/media/codecs/amrnb/enc/src/c2_11pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c2_11pf.h
rename to media/codecs/amrnb/enc/src/c2_11pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp b/media/codecs/amrnb/enc/src/c2_9pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp
rename to media/codecs/amrnb/enc/src/c2_9pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.h b/media/codecs/amrnb/enc/src/c2_9pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c2_9pf.h
rename to media/codecs/amrnb/enc/src/c2_9pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.cpp b/media/codecs/amrnb/enc/src/c3_14pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c3_14pf.cpp
rename to media/codecs/amrnb/enc/src/c3_14pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.h b/media/codecs/amrnb/enc/src/c3_14pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c3_14pf.h
rename to media/codecs/amrnb/enc/src/c3_14pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.cpp b/media/codecs/amrnb/enc/src/c4_17pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c4_17pf.cpp
rename to media/codecs/amrnb/enc/src/c4_17pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.h b/media/codecs/amrnb/enc/src/c4_17pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c4_17pf.h
rename to media/codecs/amrnb/enc/src/c4_17pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.cpp b/media/codecs/amrnb/enc/src/c8_31pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c8_31pf.cpp
rename to media/codecs/amrnb/enc/src/c8_31pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.h b/media/codecs/amrnb/enc/src/c8_31pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/c8_31pf.h
rename to media/codecs/amrnb/enc/src/c8_31pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_cor.cpp b/media/codecs/amrnb/enc/src/calc_cor.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/calc_cor.cpp
rename to media/codecs/amrnb/enc/src/calc_cor.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_cor.h b/media/codecs/amrnb/enc/src/calc_cor.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/calc_cor.h
rename to media/codecs/amrnb/enc/src/calc_cor.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_en.cpp b/media/codecs/amrnb/enc/src/calc_en.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/calc_en.cpp
rename to media/codecs/amrnb/enc/src/calc_en.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_en.h b/media/codecs/amrnb/enc/src/calc_en.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/calc_en.h
rename to media/codecs/amrnb/enc/src/calc_en.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cbsearch.cpp b/media/codecs/amrnb/enc/src/cbsearch.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cbsearch.cpp
rename to media/codecs/amrnb/enc/src/cbsearch.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cbsearch.h b/media/codecs/amrnb/enc/src/cbsearch.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cbsearch.h
rename to media/codecs/amrnb/enc/src/cbsearch.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp b/media/codecs/amrnb/enc/src/cl_ltp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp
rename to media/codecs/amrnb/enc/src/cl_ltp.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.h b/media/codecs/amrnb/enc/src/cl_ltp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cl_ltp.h
rename to media/codecs/amrnb/enc/src/cl_ltp.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cod_amr.cpp b/media/codecs/amrnb/enc/src/cod_amr.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cod_amr.cpp
rename to media/codecs/amrnb/enc/src/cod_amr.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cod_amr.h b/media/codecs/amrnb/enc/src/cod_amr.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cod_amr.h
rename to media/codecs/amrnb/enc/src/cod_amr.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp b/media/codecs/amrnb/enc/src/convolve.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/convolve.cpp
rename to media/codecs/amrnb/enc/src/convolve.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/convolve.h b/media/codecs/amrnb/enc/src/convolve.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/convolve.h
rename to media/codecs/amrnb/enc/src/convolve.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp b/media/codecs/amrnb/enc/src/cor_h.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp
rename to media/codecs/amrnb/enc/src/cor_h.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h.h b/media/codecs/amrnb/enc/src/cor_h.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cor_h.h
rename to media/codecs/amrnb/enc/src/cor_h.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp b/media/codecs/amrnb/enc/src/cor_h_x.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp
rename to media/codecs/amrnb/enc/src/cor_h_x.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.h b/media/codecs/amrnb/enc/src/cor_h_x.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cor_h_x.h
rename to media/codecs/amrnb/enc/src/cor_h_x.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp b/media/codecs/amrnb/enc/src/cor_h_x2.cpp
similarity index 99%
rename from media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
rename to media/codecs/amrnb/enc/src/cor_h_x2.cpp
index b4fd867..e32eb4a 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
+++ b/media/codecs/amrnb/enc/src/cor_h_x2.cpp
@@ -240,7 +240,7 @@
Word16 j;
Word16 k;
Word32 s;
- Word32 y32[L_CODE];
+ Word32 y32[L_CODE]{};
Word32 max;
Word32 tot;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.h b/media/codecs/amrnb/enc/src/cor_h_x2.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.h
rename to media/codecs/amrnb/enc/src/cor_h_x2.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp b/media/codecs/amrnb/enc/src/corrwght_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp
rename to media/codecs/amrnb/enc/src/corrwght_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp b/media/codecs/amrnb/enc/src/dtx_enc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp
rename to media/codecs/amrnb/enc/src/dtx_enc.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.h b/media/codecs/amrnb/enc/src/dtx_enc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/dtx_enc.h
rename to media/codecs/amrnb/enc/src/dtx_enc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.cpp b/media/codecs/amrnb/enc/src/enc_lag3.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/enc_lag3.cpp
rename to media/codecs/amrnb/enc/src/enc_lag3.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.h b/media/codecs/amrnb/enc/src/enc_lag3.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/enc_lag3.h
rename to media/codecs/amrnb/enc/src/enc_lag3.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.cpp b/media/codecs/amrnb/enc/src/enc_lag6.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/enc_lag6.cpp
rename to media/codecs/amrnb/enc/src/enc_lag6.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.h b/media/codecs/amrnb/enc/src/enc_lag6.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/enc_lag6.h
rename to media/codecs/amrnb/enc/src/enc_lag6.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp b/media/codecs/amrnb/enc/src/enc_output_format_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp
rename to media/codecs/amrnb/enc/src/enc_output_format_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.cpp b/media/codecs/amrnb/enc/src/ets_to_if2.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.cpp
rename to media/codecs/amrnb/enc/src/ets_to_if2.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.h b/media/codecs/amrnb/enc/src/ets_to_if2.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.h
rename to media/codecs/amrnb/enc/src/ets_to_if2.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.cpp b/media/codecs/amrnb/enc/src/ets_to_wmf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.cpp
rename to media/codecs/amrnb/enc/src/ets_to_wmf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.h b/media/codecs/amrnb/enc/src/ets_to_wmf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.h
rename to media/codecs/amrnb/enc/src/ets_to_wmf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_adapt.cpp b/media/codecs/amrnb/enc/src/g_adapt.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/g_adapt.cpp
rename to media/codecs/amrnb/enc/src/g_adapt.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_adapt.h b/media/codecs/amrnb/enc/src/g_adapt.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/g_adapt.h
rename to media/codecs/amrnb/enc/src/g_adapt.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_code.cpp b/media/codecs/amrnb/enc/src/g_code.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/g_code.cpp
rename to media/codecs/amrnb/enc/src/g_code.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_code.h b/media/codecs/amrnb/enc/src/g_code.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/g_code.h
rename to media/codecs/amrnb/enc/src/g_code.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_pitch.cpp b/media/codecs/amrnb/enc/src/g_pitch.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/g_pitch.cpp
rename to media/codecs/amrnb/enc/src/g_pitch.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_pitch.h b/media/codecs/amrnb/enc/src/g_pitch.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/g_pitch.h
rename to media/codecs/amrnb/enc/src/g_pitch.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/gain_q.cpp b/media/codecs/amrnb/enc/src/gain_q.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/gain_q.cpp
rename to media/codecs/amrnb/enc/src/gain_q.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/gain_q.h b/media/codecs/amrnb/enc/src/gain_q.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/gain_q.h
rename to media/codecs/amrnb/enc/src/gain_q.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h b/media/codecs/amrnb/enc/src/gsmamr_enc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h
rename to media/codecs/amrnb/enc/src/gsmamr_enc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/hp_max.cpp b/media/codecs/amrnb/enc/src/hp_max.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/hp_max.cpp
rename to media/codecs/amrnb/enc/src/hp_max.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/hp_max.h b/media/codecs/amrnb/enc/src/hp_max.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/hp_max.h
rename to media/codecs/amrnb/enc/src/hp_max.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36.cpp b/media/codecs/amrnb/enc/src/inter_36.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/inter_36.cpp
rename to media/codecs/amrnb/enc/src/inter_36.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36.h b/media/codecs/amrnb/enc/src/inter_36.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/inter_36.h
rename to media/codecs/amrnb/enc/src/inter_36.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp b/media/codecs/amrnb/enc/src/inter_36_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp
rename to media/codecs/amrnb/enc/src/inter_36_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.h b/media/codecs/amrnb/enc/src/inter_36_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.h
rename to media/codecs/amrnb/enc/src/inter_36_tab.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_comp.cpp b/media/codecs/amrnb/enc/src/l_comp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/l_comp.cpp
rename to media/codecs/amrnb/enc/src/l_comp.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_extract.cpp b/media/codecs/amrnb/enc/src/l_extract.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/l_extract.cpp
rename to media/codecs/amrnb/enc/src/l_extract.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp b/media/codecs/amrnb/enc/src/l_negate.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp
rename to media/codecs/amrnb/enc/src/l_negate.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind.cpp b/media/codecs/amrnb/enc/src/lag_wind.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/lag_wind.cpp
rename to media/codecs/amrnb/enc/src/lag_wind.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind.h b/media/codecs/amrnb/enc/src/lag_wind.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/lag_wind.h
rename to media/codecs/amrnb/enc/src/lag_wind.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp b/media/codecs/amrnb/enc/src/lag_wind_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp
rename to media/codecs/amrnb/enc/src/lag_wind_tab.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.h b/media/codecs/amrnb/enc/src/lag_wind_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.h
rename to media/codecs/amrnb/enc/src/lag_wind_tab.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp b/media/codecs/amrnb/enc/src/levinson.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/levinson.cpp
rename to media/codecs/amrnb/enc/src/levinson.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/levinson.h b/media/codecs/amrnb/enc/src/levinson.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/levinson.h
rename to media/codecs/amrnb/enc/src/levinson.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lpc.cpp b/media/codecs/amrnb/enc/src/lpc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/lpc.cpp
rename to media/codecs/amrnb/enc/src/lpc.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lpc.h b/media/codecs/amrnb/enc/src/lpc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/lpc.h
rename to media/codecs/amrnb/enc/src/lpc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.cpp b/media/codecs/amrnb/enc/src/ol_ltp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ol_ltp.cpp
rename to media/codecs/amrnb/enc/src/ol_ltp.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.h b/media/codecs/amrnb/enc/src/ol_ltp.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ol_ltp.h
rename to media/codecs/amrnb/enc/src/ol_ltp.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/p_ol_wgh.cpp b/media/codecs/amrnb/enc/src/p_ol_wgh.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/p_ol_wgh.cpp
rename to media/codecs/amrnb/enc/src/p_ol_wgh.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp b/media/codecs/amrnb/enc/src/pitch_fr.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
rename to media/codecs/amrnb/enc/src/pitch_fr.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.h b/media/codecs/amrnb/enc/src/pitch_fr.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pitch_fr.h
rename to media/codecs/amrnb/enc/src/pitch_fr.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp b/media/codecs/amrnb/enc/src/pitch_ol.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp
rename to media/codecs/amrnb/enc/src/pitch_ol.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.h b/media/codecs/amrnb/enc/src/pitch_ol.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pitch_ol.h
rename to media/codecs/amrnb/enc/src/pitch_ol.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_big.cpp b/media/codecs/amrnb/enc/src/pre_big.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pre_big.cpp
rename to media/codecs/amrnb/enc/src/pre_big.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_big.h b/media/codecs/amrnb/enc/src/pre_big.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pre_big.h
rename to media/codecs/amrnb/enc/src/pre_big.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp b/media/codecs/amrnb/enc/src/pre_proc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp
rename to media/codecs/amrnb/enc/src/pre_proc.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_proc.h b/media/codecs/amrnb/enc/src/pre_proc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/pre_proc.h
rename to media/codecs/amrnb/enc/src/pre_proc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/prm2bits.cpp b/media/codecs/amrnb/enc/src/prm2bits.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/prm2bits.cpp
rename to media/codecs/amrnb/enc/src/prm2bits.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/prm2bits.h b/media/codecs/amrnb/enc/src/prm2bits.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/prm2bits.h
rename to media/codecs/amrnb/enc/src/prm2bits.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.cpp b/media/codecs/amrnb/enc/src/q_gain_c.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/q_gain_c.cpp
rename to media/codecs/amrnb/enc/src/q_gain_c.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.h b/media/codecs/amrnb/enc/src/q_gain_c.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/q_gain_c.h
rename to media/codecs/amrnb/enc/src/q_gain_c.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.cpp b/media/codecs/amrnb/enc/src/q_gain_p.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/q_gain_p.cpp
rename to media/codecs/amrnb/enc/src/q_gain_p.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.h b/media/codecs/amrnb/enc/src/q_gain_p.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/q_gain_p.h
rename to media/codecs/amrnb/enc/src/q_gain_p.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp b/media/codecs/amrnb/enc/src/qgain475.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp
rename to media/codecs/amrnb/enc/src/qgain475.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain475.h b/media/codecs/amrnb/enc/src/qgain475.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/qgain475.h
rename to media/codecs/amrnb/enc/src/qgain475.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain795.cpp b/media/codecs/amrnb/enc/src/qgain795.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/qgain795.cpp
rename to media/codecs/amrnb/enc/src/qgain795.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain795.h b/media/codecs/amrnb/enc/src/qgain795.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/qgain795.h
rename to media/codecs/amrnb/enc/src/qgain795.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qua_gain.cpp b/media/codecs/amrnb/enc/src/qua_gain.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/qua_gain.cpp
rename to media/codecs/amrnb/enc/src/qua_gain.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.cpp b/media/codecs/amrnb/enc/src/s10_8pf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/s10_8pf.cpp
rename to media/codecs/amrnb/enc/src/s10_8pf.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.h b/media/codecs/amrnb/enc/src/s10_8pf.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/s10_8pf.h
rename to media/codecs/amrnb/enc/src/s10_8pf.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp b/media/codecs/amrnb/enc/src/set_sign.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp
rename to media/codecs/amrnb/enc/src/set_sign.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/set_sign.h b/media/codecs/amrnb/enc/src/set_sign.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/set_sign.h
rename to media/codecs/amrnb/enc/src/set_sign.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sid_sync.cpp b/media/codecs/amrnb/enc/src/sid_sync.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/sid_sync.cpp
rename to media/codecs/amrnb/enc/src/sid_sync.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sid_sync.h b/media/codecs/amrnb/enc/src/sid_sync.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/sid_sync.h
rename to media/codecs/amrnb/enc/src/sid_sync.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sp_enc.cpp b/media/codecs/amrnb/enc/src/sp_enc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/sp_enc.cpp
rename to media/codecs/amrnb/enc/src/sp_enc.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sp_enc.h b/media/codecs/amrnb/enc/src/sp_enc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/sp_enc.h
rename to media/codecs/amrnb/enc/src/sp_enc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spreproc.cpp b/media/codecs/amrnb/enc/src/spreproc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/spreproc.cpp
rename to media/codecs/amrnb/enc/src/spreproc.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spreproc.h b/media/codecs/amrnb/enc/src/spreproc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/spreproc.h
rename to media/codecs/amrnb/enc/src/spreproc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spstproc.cpp b/media/codecs/amrnb/enc/src/spstproc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/spstproc.cpp
rename to media/codecs/amrnb/enc/src/spstproc.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spstproc.h b/media/codecs/amrnb/enc/src/spstproc.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/spstproc.h
rename to media/codecs/amrnb/enc/src/spstproc.h
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ton_stab.cpp b/media/codecs/amrnb/enc/src/ton_stab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ton_stab.cpp
rename to media/codecs/amrnb/enc/src/ton_stab.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ton_stab.h b/media/codecs/amrnb/enc/src/ton_stab.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/src/ton_stab.h
rename to media/codecs/amrnb/enc/src/ton_stab.h
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h b/media/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
rename to media/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp b/media/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
rename to media/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
diff --git a/media/libstagefright/codecs/amrnb/enc/test/Android.bp b/media/codecs/amrnb/enc/test/Android.bp
similarity index 72%
rename from media/libstagefright/codecs/amrnb/enc/test/Android.bp
rename to media/codecs/amrnb/enc/test/Android.bp
index e8982fe..a94ffd4 100644
--- a/media/libstagefright/codecs/amrnb/enc/test/Android.bp
+++ b/media/codecs/amrnb/enc/test/Android.bp
@@ -14,6 +14,18 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrnb_enc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrnb_enc_license",
+ ],
+}
+
cc_test {
name: "AmrnbEncoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AndroidTest.xml b/media/codecs/amrnb/enc/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/test/AndroidTest.xml
rename to media/codecs/amrnb/enc/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/amrnb/enc/test/README.md b/media/codecs/amrnb/enc/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/test/README.md
rename to media/codecs/amrnb/enc/test/README.md
diff --git a/media/libstagefright/codecs/amrnb/enc/test/amrnb_enc_test.cpp b/media/codecs/amrnb/enc/test/amrnb_enc_test.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/enc/test/amrnb_enc_test.cpp
rename to media/codecs/amrnb/enc/test/amrnb_enc_test.cpp
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/Android.bp b/media/codecs/amrnb/fuzzer/Android.bp
similarity index 79%
rename from media/libstagefright/codecs/amrnb/fuzzer/Android.bp
rename to media/codecs/amrnb/fuzzer/Android.bp
index c1eaa53..833a7ba 100644
--- a/media/libstagefright/codecs/amrnb/fuzzer/Android.bp
+++ b/media/codecs/amrnb/fuzzer/Android.bp
@@ -18,6 +18,15 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_fuzz {
name: "amrnb_dec_fuzzer",
host_supported: true,
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/README.md b/media/codecs/amrnb/fuzzer/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrnb/fuzzer/README.md
rename to media/codecs/amrnb/fuzzer/README.md
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp b/media/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
rename to media/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
diff --git a/media/libstagefright/codecs/amrnb/patent_disclaimer.txt b/media/codecs/amrnb/patent_disclaimer.txt
similarity index 100%
rename from media/libstagefright/codecs/amrnb/patent_disclaimer.txt
rename to media/codecs/amrnb/patent_disclaimer.txt
diff --git a/media/libstagefright/codecs/amrwb/Android.bp b/media/codecs/amrwb/dec/Android.bp
similarity index 67%
rename from media/libstagefright/codecs/amrwb/Android.bp
rename to media/codecs/amrwb/dec/Android.bp
index 204cbe3..228ea80 100644
--- a/media/libstagefright/codecs/amrwb/Android.bp
+++ b/media/codecs/amrwb/dec/Android.bp
@@ -1,3 +1,35 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_amrwb_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libstagefright_amrwbdec",
vendor_available: true,
diff --git a/media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2 b/media/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
similarity index 100%
copy from media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
copy to media/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/dec/NOTICE b/media/codecs/amrwb/dec/NOTICE
similarity index 100%
copy from media/libstagefright/codecs/amrnb/dec/NOTICE
copy to media/codecs/amrwb/dec/NOTICE
diff --git a/media/codecs/amrwb/dec/TEST_MAPPING b/media/codecs/amrwb/dec/TEST_MAPPING
new file mode 100644
index 0000000..0278d26
--- /dev/null
+++ b/media/codecs/amrwb/dec/TEST_MAPPING
@@ -0,0 +1,10 @@
+// mappings for frameworks/av/media/libstagefright/codecs/amrwb
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "AmrwbDecoderTest"}
+
+ ]
+}
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/Android.bp b/media/codecs/amrwb/dec/fuzzer/Android.bp
similarity index 75%
rename from media/libstagefright/codecs/amrwb/fuzzer/Android.bp
rename to media/codecs/amrwb/dec/fuzzer/Android.bp
index 7106a30..16f08fa 100644
--- a/media/libstagefright/codecs/amrwb/fuzzer/Android.bp
+++ b/media/codecs/amrwb/dec/fuzzer/Android.bp
@@ -18,6 +18,17 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrwb_dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_dec_license",
+ ],
+}
+
cc_fuzz {
name: "amrwb_dec_fuzzer",
host_supported: true,
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/README.md b/media/codecs/amrwb/dec/fuzzer/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrwb/fuzzer/README.md
rename to media/codecs/amrwb/dec/fuzzer/README.md
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp b/media/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
rename to media/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
diff --git a/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h b/media/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h
rename to media/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
diff --git a/media/libstagefright/codecs/mp3dec/patent_disclaimer.txt b/media/codecs/amrwb/dec/patent_disclaimer.txt
similarity index 100%
copy from media/libstagefright/codecs/mp3dec/patent_disclaimer.txt
copy to media/codecs/amrwb/dec/patent_disclaimer.txt
diff --git a/media/libstagefright/codecs/amrwb/src/agc2_amr_wb.cpp b/media/codecs/amrwb/dec/src/agc2_amr_wb.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/agc2_amr_wb.cpp
rename to media/codecs/amrwb/dec/src/agc2_amr_wb.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/band_pass_6k_7k.cpp b/media/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/band_pass_6k_7k.cpp
rename to media/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/dec_acelp_2p_in_64.cpp b/media/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/dec_acelp_2p_in_64.cpp
rename to media/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp b/media/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp
rename to media/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/dec_alg_codebook.cpp b/media/codecs/amrwb/dec/src/dec_alg_codebook.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/dec_alg_codebook.cpp
rename to media/codecs/amrwb/dec/src/dec_alg_codebook.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/dec_gain2_amr_wb.cpp b/media/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/dec_gain2_amr_wb.cpp
rename to media/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp b/media/codecs/amrwb/dec/src/deemphasis_32.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp
rename to media/codecs/amrwb/dec/src/deemphasis_32.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/dtx.h b/media/codecs/amrwb/dec/src/dtx.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/dtx.h
rename to media/codecs/amrwb/dec/src/dtx.h
diff --git a/media/libstagefright/codecs/amrwb/src/dtx_decoder_amr_wb.cpp b/media/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/dtx_decoder_amr_wb.cpp
rename to media/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/e_pv_amrwbdec.h b/media/codecs/amrwb/dec/src/e_pv_amrwbdec.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/e_pv_amrwbdec.h
rename to media/codecs/amrwb/dec/src/e_pv_amrwbdec.h
diff --git a/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.cpp b/media/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.cpp
rename to media/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.h b/media/codecs/amrwb/dec/src/get_amr_wb_bits.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.h
rename to media/codecs/amrwb/dec/src/get_amr_wb_bits.h
diff --git a/media/libstagefright/codecs/amrwb/src/highpass_400hz_at_12k8.cpp b/media/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/highpass_400hz_at_12k8.cpp
rename to media/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/highpass_50hz_at_12k8.cpp b/media/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/highpass_50hz_at_12k8.cpp
rename to media/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp b/media/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp
rename to media/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/interpolate_isp.cpp b/media/codecs/amrwb/dec/src/interpolate_isp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/interpolate_isp.cpp
rename to media/codecs/amrwb/dec/src/interpolate_isp.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/isf_extrapolation.cpp b/media/codecs/amrwb/dec/src/isf_extrapolation.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/isf_extrapolation.cpp
rename to media/codecs/amrwb/dec/src/isf_extrapolation.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/isp_az.cpp b/media/codecs/amrwb/dec/src/isp_az.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/isp_az.cpp
rename to media/codecs/amrwb/dec/src/isp_az.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/isp_isf.cpp b/media/codecs/amrwb/dec/src/isp_isf.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/isp_isf.cpp
rename to media/codecs/amrwb/dec/src/isp_isf.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/lagconceal.cpp b/media/codecs/amrwb/dec/src/lagconceal.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/lagconceal.cpp
rename to media/codecs/amrwb/dec/src/lagconceal.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/low_pass_filt_7k.cpp b/media/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/low_pass_filt_7k.cpp
rename to media/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/median5.cpp b/media/codecs/amrwb/dec/src/median5.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/median5.cpp
rename to media/codecs/amrwb/dec/src/median5.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/mime_io.cpp b/media/codecs/amrwb/dec/src/mime_io.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/mime_io.cpp
rename to media/codecs/amrwb/dec/src/mime_io.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/mime_io.h b/media/codecs/amrwb/dec/src/mime_io.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/mime_io.h
rename to media/codecs/amrwb/dec/src/mime_io.h
diff --git a/media/libstagefright/codecs/amrwb/src/noise_gen_amrwb.cpp b/media/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/noise_gen_amrwb.cpp
rename to media/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp b/media/codecs/amrwb/dec/src/normalize_amr_wb.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp
rename to media/codecs/amrwb/dec/src/normalize_amr_wb.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.h b/media/codecs/amrwb/dec/src/normalize_amr_wb.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/normalize_amr_wb.h
rename to media/codecs/amrwb/dec/src/normalize_amr_wb.h
diff --git a/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp b/media/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp
rename to media/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp b/media/codecs/amrwb/dec/src/phase_dispersion.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp
rename to media/codecs/amrwb/dec/src/phase_dispersion.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/pit_shrp.cpp b/media/codecs/amrwb/dec/src/pit_shrp.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pit_shrp.cpp
rename to media/codecs/amrwb/dec/src/pit_shrp.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/pred_lt4.cpp b/media/codecs/amrwb/dec/src/pred_lt4.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pred_lt4.cpp
rename to media/codecs/amrwb/dec/src/pred_lt4.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/preemph_amrwb_dec.cpp b/media/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/preemph_amrwb_dec.cpp
rename to media/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/pv_amr_wb_type_defs.h b/media/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pv_amr_wb_type_defs.h
rename to media/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp b/media/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp
rename to media/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.h b/media/codecs/amrwb/dec/src/pvamrwb_math_op.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.h
rename to media/codecs/amrwb/dec/src/pvamrwb_math_op.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp b/media/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_acelp.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_acelp.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_armv5.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_armv5.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_cequivalent.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_cequivalent.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_gcc_armv5.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_gcc_armv5.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_cnst.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_cnst.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_mem_funcs.h b/media/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_mem_funcs.h
rename to media/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
diff --git a/media/libstagefright/codecs/amrwb/src/q_gain2_tab.cpp b/media/codecs/amrwb/dec/src/q_gain2_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/q_gain2_tab.cpp
rename to media/codecs/amrwb/dec/src/q_gain2_tab.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/q_pulse.h b/media/codecs/amrwb/dec/src/q_pulse.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/q_pulse.h
rename to media/codecs/amrwb/dec/src/q_pulse.h
diff --git a/media/libstagefright/codecs/amrwb/src/qisf_ns.cpp b/media/codecs/amrwb/dec/src/qisf_ns.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/qisf_ns.cpp
rename to media/codecs/amrwb/dec/src/qisf_ns.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/qisf_ns.h b/media/codecs/amrwb/dec/src/qisf_ns.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/qisf_ns.h
rename to media/codecs/amrwb/dec/src/qisf_ns.h
diff --git a/media/libstagefright/codecs/amrwb/src/qisf_ns_tab.cpp b/media/codecs/amrwb/dec/src/qisf_ns_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/qisf_ns_tab.cpp
rename to media/codecs/amrwb/dec/src/qisf_ns_tab.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/qpisf_2s.cpp b/media/codecs/amrwb/dec/src/qpisf_2s.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/qpisf_2s.cpp
rename to media/codecs/amrwb/dec/src/qpisf_2s.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/qpisf_2s.h b/media/codecs/amrwb/dec/src/qpisf_2s.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/qpisf_2s.h
rename to media/codecs/amrwb/dec/src/qpisf_2s.h
diff --git a/media/libstagefright/codecs/amrwb/src/qpisf_2s_tab.cpp b/media/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/qpisf_2s_tab.cpp
rename to media/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/scale_signal.cpp b/media/codecs/amrwb/dec/src/scale_signal.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/scale_signal.cpp
rename to media/codecs/amrwb/dec/src/scale_signal.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.cpp b/media/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.cpp
rename to media/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.h b/media/codecs/amrwb/dec/src/synthesis_amr_wb.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.h
rename to media/codecs/amrwb/dec/src/synthesis_amr_wb.h
diff --git a/media/libstagefright/codecs/amrwb/src/voice_factor.cpp b/media/codecs/amrwb/dec/src/voice_factor.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/voice_factor.cpp
rename to media/codecs/amrwb/dec/src/voice_factor.cpp
diff --git a/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp b/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
similarity index 97%
rename from media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
rename to media/codecs/amrwb/dec/src/wb_syn_filt.cpp
index d960322..f12828d 100644
--- a/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
+++ b/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
@@ -181,12 +181,14 @@
L_tmp4 = fxp_mac_16by16(yy[(i<<2)+3 - j], a[j], L_tmp4);
L_tmp1 = shl_int32(L_tmp1, 4);
+ L_tmp1 = L_tmp1 == INT32_MIN ? INT32_MIN + 1 : L_tmp1;
y[(i<<2)] = yy[(i<<2)] = amr_wb_round(-L_tmp1);
L_tmp2 = fxp_mac_16by16(yy[(i<<2)], a[1], L_tmp2);
L_tmp2 = shl_int32(L_tmp2, 4);
+ L_tmp2 = L_tmp2 == INT32_MIN ? INT32_MIN + 1 : L_tmp2;
y[(i<<2)+1] = yy[(i<<2)+1] = amr_wb_round(-L_tmp2);
@@ -197,12 +199,14 @@
L_tmp3 = fxp_mac_16by16(yy[(i<<2) + 1], a[1], L_tmp3);
L_tmp3 = shl_int32(L_tmp3, 4);
+ L_tmp3 = L_tmp3 == INT32_MIN ? INT32_MIN + 1 : L_tmp3;
y[(i<<2)+2] = yy[(i<<2)+2] = amr_wb_round(-L_tmp3);
L_tmp4 = fxp_mac_16by16(yy[(i<<2)+2], a[1], L_tmp4);
L_tmp4 = shl_int32(L_tmp4, 4);
+ L_tmp4 = L_tmp4 == INT32_MIN ? INT32_MIN + 1 : L_tmp4;
y[(i<<2)+3] = yy[(i<<2)+3] = amr_wb_round(-L_tmp4);
}
diff --git a/media/libstagefright/codecs/amrwb/src/weight_amrwb_lpc.cpp b/media/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/src/weight_amrwb_lpc.cpp
rename to media/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
diff --git a/media/libstagefright/codecs/amrwb/test/AmrwbDecTestEnvironment.h b/media/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/amrwb/test/AmrwbDecTestEnvironment.h
rename to media/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
diff --git a/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp b/media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp
rename to media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
diff --git a/media/libstagefright/codecs/amrwb/test/Android.bp b/media/codecs/amrwb/dec/test/Android.bp
similarity index 71%
rename from media/libstagefright/codecs/amrwb/test/Android.bp
rename to media/codecs/amrwb/dec/test/Android.bp
index 968215a..cc120d3 100644
--- a/media/libstagefright/codecs/amrwb/test/Android.bp
+++ b/media/codecs/amrwb/dec/test/Android.bp
@@ -14,6 +14,18 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrwb_dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_dec_license",
+ ],
+}
+
cc_test {
name: "AmrwbDecoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/amrwb/test/AndroidTest.xml b/media/codecs/amrwb/dec/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/amrwb/test/AndroidTest.xml
rename to media/codecs/amrwb/dec/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/amrwb/test/README.md b/media/codecs/amrwb/dec/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrwb/test/README.md
rename to media/codecs/amrwb/dec/test/README.md
diff --git a/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp b/media/codecs/amrwb/dec/test/amrwbdec_test.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
rename to media/codecs/amrwb/dec/test/amrwbdec_test.cpp
diff --git a/media/codecs/amrwb/enc/Android.bp b/media/codecs/amrwb/enc/Android.bp
new file mode 100644
index 0000000..cc72eb7
--- /dev/null
+++ b/media/codecs/amrwb/enc/Android.bp
@@ -0,0 +1,166 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_enc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_amrwb_enc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library_static {
+ name: "libstagefright_amrwbenc",
+ vendor_available: true,
+ min_sdk_version: "29",
+
+ srcs: [
+ "src/autocorr.c",
+ "src/az_isp.c",
+ "src/bits.c",
+ "src/c2t64fx.c",
+ "src/c4t64fx.c",
+ "src/convolve.c",
+ "src/cor_h_x.c",
+ "src/decim54.c",
+ "src/deemph.c",
+ "src/dtx.c",
+ "src/g_pitch.c",
+ "src/gpclip.c",
+ "src/homing.c",
+ "src/hp400.c",
+ "src/hp50.c",
+ "src/hp6k.c",
+ "src/hp_wsp.c",
+ "src/int_lpc.c",
+ "src/isp_az.c",
+ "src/isp_isf.c",
+ "src/lag_wind.c",
+ "src/levinson.c",
+ "src/log2.c",
+ "src/lp_dec2.c",
+ "src/math_op.c",
+ "src/oper_32b.c",
+ "src/p_med_ol.c",
+ "src/pit_shrp.c",
+ "src/pitch_f4.c",
+ "src/pred_lt4.c",
+ "src/preemph.c",
+ "src/q_gain2.c",
+ "src/q_pulse.c",
+ "src/qisf_ns.c",
+ "src/qpisf_2s.c",
+ "src/random.c",
+ "src/residu.c",
+ "src/scale.c",
+ "src/stream.c",
+ "src/syn_filt.c",
+ "src/updt_tar.c",
+ "src/util.c",
+ "src/voAMRWBEnc.c",
+ "src/voicefac.c",
+ "src/wb_vad.c",
+ "src/weight_a.c",
+ "src/mem_align.c",
+ ],
+
+ arch: {
+ arm: {
+ srcs: [
+ "src/asm/ARMV5E/convolve_opt.s",
+ "src/asm/ARMV5E/cor_h_vec_opt.s",
+ "src/asm/ARMV5E/Deemph_32_opt.s",
+ "src/asm/ARMV5E/Dot_p_opt.s",
+ "src/asm/ARMV5E/Filt_6k_7k_opt.s",
+ "src/asm/ARMV5E/Norm_Corr_opt.s",
+ "src/asm/ARMV5E/pred_lt4_1_opt.s",
+ "src/asm/ARMV5E/residu_asm_opt.s",
+ "src/asm/ARMV5E/scale_sig_opt.s",
+ "src/asm/ARMV5E/Syn_filt_32_opt.s",
+ "src/asm/ARMV5E/syn_filt_opt.s",
+ ],
+
+ cflags: [
+ "-DARM",
+ "-DASM_OPT",
+ ],
+ local_include_dirs: ["src/asm/ARMV5E"],
+
+ instruction_set: "arm",
+
+ neon: {
+ exclude_srcs: [
+ "src/asm/ARMV5E/convolve_opt.s",
+ "src/asm/ARMV5E/cor_h_vec_opt.s",
+ "src/asm/ARMV5E/Deemph_32_opt.s",
+ "src/asm/ARMV5E/Dot_p_opt.s",
+ "src/asm/ARMV5E/Filt_6k_7k_opt.s",
+ "src/asm/ARMV5E/Norm_Corr_opt.s",
+ "src/asm/ARMV5E/pred_lt4_1_opt.s",
+ "src/asm/ARMV5E/residu_asm_opt.s",
+ "src/asm/ARMV5E/scale_sig_opt.s",
+ "src/asm/ARMV5E/Syn_filt_32_opt.s",
+ "src/asm/ARMV5E/syn_filt_opt.s",
+ ],
+
+ srcs: [
+ "src/asm/ARMV7/convolve_neon.s",
+ "src/asm/ARMV7/cor_h_vec_neon.s",
+ "src/asm/ARMV7/Deemph_32_neon.s",
+ "src/asm/ARMV7/Dot_p_neon.s",
+ "src/asm/ARMV7/Filt_6k_7k_neon.s",
+ "src/asm/ARMV7/Norm_Corr_neon.s",
+ "src/asm/ARMV7/pred_lt4_1_neon.s",
+ "src/asm/ARMV7/residu_asm_neon.s",
+ "src/asm/ARMV7/scale_sig_neon.s",
+ "src/asm/ARMV7/Syn_filt_32_neon.s",
+ "src/asm/ARMV7/syn_filt_neon.s",
+ ],
+
+ // don't actually generate neon instructions, see bug 26932980
+ cflags: [
+ "-DARMV7",
+ "-mfpu=vfpv3",
+ ],
+ local_include_dirs: [
+ "src/asm/ARMV5E",
+ "src/asm/ARMV7",
+ ],
+ },
+
+ },
+ },
+
+ include_dirs: [
+ "frameworks/av/include",
+ "frameworks/av/media/libstagefright/include",
+ ],
+
+ local_include_dirs: ["src"],
+ export_include_dirs: ["inc"],
+
+ shared_libs: [
+ "libstagefright_enc_common",
+ "liblog",
+ ],
+
+ cflags: ["-Werror"],
+ sanitize: {
+ cfi: true,
+ },
+
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2 b/media/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
similarity index 100%
copy from media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
copy to media/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/enc/NOTICE b/media/codecs/amrwb/enc/NOTICE
similarity index 100%
copy from media/libstagefright/codecs/amrnb/enc/NOTICE
copy to media/codecs/amrwb/enc/NOTICE
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
rename to media/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
diff --git a/media/codecs/amrwb/enc/SampleCode/Android.bp b/media/codecs/amrwb/enc/SampleCode/Android.bp
new file mode 100644
index 0000000..1448364
--- /dev/null
+++ b/media/codecs/amrwb/enc/SampleCode/Android.bp
@@ -0,0 +1,47 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_enc_SampleCode_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_amrwb_enc_SampleCode_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_test {
+ name: "AMRWBEncTest",
+ gtest: false,
+
+ srcs: ["AMRWB_E_SAMPLE.c"],
+
+ cflags: ["-Wall", "-Werror"],
+
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+
+ shared_libs: [
+ "libdl",
+ "liblog",
+ ],
+
+ static_libs: [
+ "libstagefright_amrwbenc",
+ "libstagefright_enc_common",
+ ],
+
+ sanitize: {
+ cfi: true,
+ },
+}
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/MODULE_LICENSE_APACHE2 b/media/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/SampleCode/MODULE_LICENSE_APACHE2
rename to media/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/NOTICE b/media/codecs/amrwb/enc/SampleCode/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/SampleCode/NOTICE
rename to media/codecs/amrwb/enc/SampleCode/NOTICE
diff --git a/media/codecs/amrwb/enc/TEST_MAPPING b/media/codecs/amrwb/enc/TEST_MAPPING
new file mode 100644
index 0000000..045e8b3
--- /dev/null
+++ b/media/codecs/amrwb/enc/TEST_MAPPING
@@ -0,0 +1,10 @@
+// mappings for frameworks/av/media/libstagefright/codecs/amrwbenc
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "AmrwbEncoderTest"}
+
+ ]
+}
diff --git a/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf b/media/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf
rename to media/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
Binary files differ
diff --git a/media/libstagefright/codecs/amrwbenc/fuzzer/Android.bp b/media/codecs/amrwb/enc/fuzzer/Android.bp
similarity index 75%
rename from media/libstagefright/codecs/amrwbenc/fuzzer/Android.bp
rename to media/codecs/amrwb/enc/fuzzer/Android.bp
index e3473d6..f74fa4f 100644
--- a/media/libstagefright/codecs/amrwbenc/fuzzer/Android.bp
+++ b/media/codecs/amrwb/enc/fuzzer/Android.bp
@@ -18,6 +18,17 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrwb_enc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_enc_license",
+ ],
+}
+
cc_fuzz {
name: "amrwb_enc_fuzzer",
host_supported: true,
diff --git a/media/libstagefright/codecs/amrwbenc/fuzzer/README.md b/media/codecs/amrwb/enc/fuzzer/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/fuzzer/README.md
rename to media/codecs/amrwb/enc/fuzzer/README.md
diff --git a/media/libstagefright/codecs/amrwbenc/fuzzer/amrwb_enc_fuzzer.cpp b/media/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/fuzzer/amrwb_enc_fuzzer.cpp
rename to media/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
diff --git a/media/libstagefright/codecs/amrwbenc/inc/acelp.h b/media/codecs/amrwb/enc/inc/acelp.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/acelp.h
rename to media/codecs/amrwb/enc/inc/acelp.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/codecs/amrwb/enc/inc/basic_op.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/basic_op.h
rename to media/codecs/amrwb/enc/inc/basic_op.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/bits.h b/media/codecs/amrwb/enc/inc/bits.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/bits.h
rename to media/codecs/amrwb/enc/inc/bits.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/cnst.h b/media/codecs/amrwb/enc/inc/cnst.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/cnst.h
rename to media/codecs/amrwb/enc/inc/cnst.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/cod_main.h b/media/codecs/amrwb/enc/inc/cod_main.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/cod_main.h
rename to media/codecs/amrwb/enc/inc/cod_main.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/dtx.h b/media/codecs/amrwb/enc/inc/dtx.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/dtx.h
rename to media/codecs/amrwb/enc/inc/dtx.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/grid100.tab b/media/codecs/amrwb/enc/inc/grid100.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/grid100.tab
rename to media/codecs/amrwb/enc/inc/grid100.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab b/media/codecs/amrwb/enc/inc/ham_wind.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab
rename to media/codecs/amrwb/enc/inc/ham_wind.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/homing.tab b/media/codecs/amrwb/enc/inc/homing.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/homing.tab
rename to media/codecs/amrwb/enc/inc/homing.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab b/media/codecs/amrwb/enc/inc/isp_isf.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab
rename to media/codecs/amrwb/enc/inc/isp_isf.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab b/media/codecs/amrwb/enc/inc/lag_wind.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab
rename to media/codecs/amrwb/enc/inc/lag_wind.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2.h b/media/codecs/amrwb/enc/inc/log2.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/log2.h
rename to media/codecs/amrwb/enc/inc/log2.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h b/media/codecs/amrwb/enc/inc/log2_tab.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/log2_tab.h
rename to media/codecs/amrwb/enc/inc/log2_tab.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/main.h b/media/codecs/amrwb/enc/inc/main.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/main.h
rename to media/codecs/amrwb/enc/inc/main.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/math_op.h b/media/codecs/amrwb/enc/inc/math_op.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/math_op.h
rename to media/codecs/amrwb/enc/inc/math_op.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/mem_align.h b/media/codecs/amrwb/enc/inc/mem_align.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/mem_align.h
rename to media/codecs/amrwb/enc/inc/mem_align.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab b/media/codecs/amrwb/enc/inc/mime_io.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/mime_io.tab
rename to media/codecs/amrwb/enc/inc/mime_io.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h b/media/codecs/amrwb/enc/inc/oper_32b.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/oper_32b.h
rename to media/codecs/amrwb/enc/inc/oper_32b.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h b/media/codecs/amrwb/enc/inc/p_med_o.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/p_med_o.h
rename to media/codecs/amrwb/enc/inc/p_med_o.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab b/media/codecs/amrwb/enc/inc/p_med_ol.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab
rename to media/codecs/amrwb/enc/inc/p_med_ol.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab b/media/codecs/amrwb/enc/inc/q_gain2.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab
rename to media/codecs/amrwb/enc/inc/q_gain2.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h b/media/codecs/amrwb/enc/inc/q_pulse.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/q_pulse.h
rename to media/codecs/amrwb/enc/inc/q_pulse.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab b/media/codecs/amrwb/enc/inc/qisf_ns.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab
rename to media/codecs/amrwb/enc/inc/qisf_ns.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab b/media/codecs/amrwb/enc/inc/qpisf_2s.tab
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab
rename to media/codecs/amrwb/enc/inc/qpisf_2s.tab
diff --git a/media/libstagefright/codecs/amrwbenc/inc/stream.h b/media/codecs/amrwb/enc/inc/stream.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/stream.h
rename to media/codecs/amrwb/enc/inc/stream.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedef.h b/media/codecs/amrwb/enc/inc/typedef.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/typedef.h
rename to media/codecs/amrwb/enc/inc/typedef.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedefs.h b/media/codecs/amrwb/enc/inc/typedefs.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/typedefs.h
rename to media/codecs/amrwb/enc/inc/typedefs.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h b/media/codecs/amrwb/enc/inc/wb_vad.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/wb_vad.h
rename to media/codecs/amrwb/enc/inc/wb_vad.h
diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h b/media/codecs/amrwb/enc/inc/wb_vad_c.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h
rename to media/codecs/amrwb/enc/inc/wb_vad_c.h
diff --git a/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt b/media/codecs/amrwb/enc/patent_disclaimer.txt
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt
rename to media/codecs/amrwb/enc/patent_disclaimer.txt
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s b/media/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s
rename to media/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s b/media/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s
rename to media/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
diff --git a/media/libstagefright/codecs/amrwbenc/src/autocorr.c b/media/codecs/amrwb/enc/src/autocorr.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/autocorr.c
rename to media/codecs/amrwb/enc/src/autocorr.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/az_isp.c b/media/codecs/amrwb/enc/src/az_isp.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/az_isp.c
rename to media/codecs/amrwb/enc/src/az_isp.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/bits.c b/media/codecs/amrwb/enc/src/bits.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/bits.c
rename to media/codecs/amrwb/enc/src/bits.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c b/media/codecs/amrwb/enc/src/c2t64fx.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
rename to media/codecs/amrwb/enc/src/c2t64fx.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/codecs/amrwb/enc/src/c4t64fx.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
rename to media/codecs/amrwb/enc/src/c4t64fx.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/convolve.c b/media/codecs/amrwb/enc/src/convolve.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/convolve.c
rename to media/codecs/amrwb/enc/src/convolve.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c b/media/codecs/amrwb/enc/src/cor_h_x.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
rename to media/codecs/amrwb/enc/src/cor_h_x.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/decim54.c b/media/codecs/amrwb/enc/src/decim54.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/decim54.c
rename to media/codecs/amrwb/enc/src/decim54.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/deemph.c b/media/codecs/amrwb/enc/src/deemph.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/deemph.c
rename to media/codecs/amrwb/enc/src/deemph.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/dtx.c b/media/codecs/amrwb/enc/src/dtx.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/dtx.c
rename to media/codecs/amrwb/enc/src/dtx.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/g_pitch.c b/media/codecs/amrwb/enc/src/g_pitch.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/g_pitch.c
rename to media/codecs/amrwb/enc/src/g_pitch.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/gpclip.c b/media/codecs/amrwb/enc/src/gpclip.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/gpclip.c
rename to media/codecs/amrwb/enc/src/gpclip.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/homing.c b/media/codecs/amrwb/enc/src/homing.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/homing.c
rename to media/codecs/amrwb/enc/src/homing.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp400.c b/media/codecs/amrwb/enc/src/hp400.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/hp400.c
rename to media/codecs/amrwb/enc/src/hp400.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp50.c b/media/codecs/amrwb/enc/src/hp50.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/hp50.c
rename to media/codecs/amrwb/enc/src/hp50.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp6k.c b/media/codecs/amrwb/enc/src/hp6k.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/hp6k.c
rename to media/codecs/amrwb/enc/src/hp6k.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c b/media/codecs/amrwb/enc/src/hp_wsp.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/hp_wsp.c
rename to media/codecs/amrwb/enc/src/hp_wsp.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/int_lpc.c b/media/codecs/amrwb/enc/src/int_lpc.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/int_lpc.c
rename to media/codecs/amrwb/enc/src/int_lpc.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_az.c b/media/codecs/amrwb/enc/src/isp_az.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/isp_az.c
rename to media/codecs/amrwb/enc/src/isp_az.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_isf.c b/media/codecs/amrwb/enc/src/isp_isf.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/isp_isf.c
rename to media/codecs/amrwb/enc/src/isp_isf.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/lag_wind.c b/media/codecs/amrwb/enc/src/lag_wind.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/lag_wind.c
rename to media/codecs/amrwb/enc/src/lag_wind.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/levinson.c b/media/codecs/amrwb/enc/src/levinson.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/levinson.c
rename to media/codecs/amrwb/enc/src/levinson.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/log2.c b/media/codecs/amrwb/enc/src/log2.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/log2.c
rename to media/codecs/amrwb/enc/src/log2.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c b/media/codecs/amrwb/enc/src/lp_dec2.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/lp_dec2.c
rename to media/codecs/amrwb/enc/src/lp_dec2.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/math_op.c b/media/codecs/amrwb/enc/src/math_op.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/math_op.c
rename to media/codecs/amrwb/enc/src/math_op.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/mem_align.c b/media/codecs/amrwb/enc/src/mem_align.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/mem_align.c
rename to media/codecs/amrwb/enc/src/mem_align.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/oper_32b.c b/media/codecs/amrwb/enc/src/oper_32b.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/oper_32b.c
rename to media/codecs/amrwb/enc/src/oper_32b.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c b/media/codecs/amrwb/enc/src/p_med_ol.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/p_med_ol.c
rename to media/codecs/amrwb/enc/src/p_med_ol.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c b/media/codecs/amrwb/enc/src/pit_shrp.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/pit_shrp.c
rename to media/codecs/amrwb/enc/src/pit_shrp.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c b/media/codecs/amrwb/enc/src/pitch_f4.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/pitch_f4.c
rename to media/codecs/amrwb/enc/src/pitch_f4.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c b/media/codecs/amrwb/enc/src/pred_lt4.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/pred_lt4.c
rename to media/codecs/amrwb/enc/src/pred_lt4.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/preemph.c b/media/codecs/amrwb/enc/src/preemph.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/preemph.c
rename to media/codecs/amrwb/enc/src/preemph.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/q_gain2.c b/media/codecs/amrwb/enc/src/q_gain2.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/q_gain2.c
rename to media/codecs/amrwb/enc/src/q_gain2.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c b/media/codecs/amrwb/enc/src/q_pulse.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/q_pulse.c
rename to media/codecs/amrwb/enc/src/q_pulse.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c b/media/codecs/amrwb/enc/src/qisf_ns.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/qisf_ns.c
rename to media/codecs/amrwb/enc/src/qisf_ns.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c b/media/codecs/amrwb/enc/src/qpisf_2s.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c
rename to media/codecs/amrwb/enc/src/qpisf_2s.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/random.c b/media/codecs/amrwb/enc/src/random.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/random.c
rename to media/codecs/amrwb/enc/src/random.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/residu.c b/media/codecs/amrwb/enc/src/residu.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/residu.c
rename to media/codecs/amrwb/enc/src/residu.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/scale.c b/media/codecs/amrwb/enc/src/scale.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/scale.c
rename to media/codecs/amrwb/enc/src/scale.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/stream.c b/media/codecs/amrwb/enc/src/stream.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/stream.c
rename to media/codecs/amrwb/enc/src/stream.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/syn_filt.c b/media/codecs/amrwb/enc/src/syn_filt.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/syn_filt.c
rename to media/codecs/amrwb/enc/src/syn_filt.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/updt_tar.c b/media/codecs/amrwb/enc/src/updt_tar.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/updt_tar.c
rename to media/codecs/amrwb/enc/src/updt_tar.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/util.c b/media/codecs/amrwb/enc/src/util.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/util.c
rename to media/codecs/amrwb/enc/src/util.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/codecs/amrwb/enc/src/voAMRWBEnc.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c
rename to media/codecs/amrwb/enc/src/voAMRWBEnc.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/voicefac.c b/media/codecs/amrwb/enc/src/voicefac.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/voicefac.c
rename to media/codecs/amrwb/enc/src/voicefac.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/wb_vad.c b/media/codecs/amrwb/enc/src/wb_vad.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/wb_vad.c
rename to media/codecs/amrwb/enc/src/wb_vad.c
diff --git a/media/libstagefright/codecs/amrwbenc/src/weight_a.c b/media/codecs/amrwb/enc/src/weight_a.c
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/src/weight_a.c
rename to media/codecs/amrwb/enc/src/weight_a.c
diff --git a/media/libstagefright/codecs/amrwbenc/test/AmrwbEncTestEnvironment.h b/media/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/test/AmrwbEncTestEnvironment.h
rename to media/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
diff --git a/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.cpp b/media/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.cpp
rename to media/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
diff --git a/media/libstagefright/codecs/amrwbenc/test/Android.bp b/media/codecs/amrwb/enc/test/Android.bp
similarity index 74%
rename from media/libstagefright/codecs/amrwbenc/test/Android.bp
rename to media/codecs/amrwb/enc/test/Android.bp
index 7042bc5..e4b7771 100644
--- a/media/libstagefright/codecs/amrwbenc/test/Android.bp
+++ b/media/codecs/amrwb/enc/test/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_amrwb_enc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_amrwb_enc_license",
+ ],
+}
+
cc_test {
name: "AmrwbEncoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml b/media/codecs/amrwb/enc/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml
rename to media/codecs/amrwb/enc/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/amrwbenc/test/README.md b/media/codecs/amrwb/enc/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/amrwbenc/test/README.md
rename to media/codecs/amrwb/enc/test/README.md
diff --git a/media/codecs/g711/decoder/Android.bp b/media/codecs/g711/decoder/Android.bp
index efff60b..07f7ed4 100644
--- a/media/codecs/g711/decoder/Android.bp
+++ b/media/codecs/g711/decoder/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "codecs_g711dec",
vendor_available: true,
diff --git a/media/codecs/g711/fuzzer/Android.bp b/media/codecs/g711/fuzzer/Android.bp
index ff5efa9..376cce7 100644
--- a/media/codecs/g711/fuzzer/Android.bp
+++ b/media/codecs/g711/fuzzer/Android.bp
@@ -18,6 +18,15 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_fuzz {
name: "g711alaw_dec_fuzzer",
host_supported: true,
diff --git a/media/codecs/m4v_h263/TEST_MAPPING b/media/codecs/m4v_h263/TEST_MAPPING
new file mode 100644
index 0000000..ba3ff1c
--- /dev/null
+++ b/media/codecs/m4v_h263/TEST_MAPPING
@@ -0,0 +1,18 @@
+// mappings for frameworks/av/media/libstagefright/codecs/m4v_h263
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+
+ // the decoder reports something bad about an unexpected newline in the *config file
+ // and the config file looks like the AndroidTest.xml file that we put in there.
+ // I don't get this from the Encoder -- and I don't see any substantive difference
+ // between decode and encode AndroidTest.xml files -- except that encode does NOT
+ // finish with a newline.
+ // strange.
+ { "name": "Mpeg4H263DecoderTest"},
+ { "name": "Mpeg4H263EncoderTest"}
+
+ ]
+}
diff --git a/media/codecs/m4v_h263/dec/Android.bp b/media/codecs/m4v_h263/dec/Android.bp
new file mode 100644
index 0000000..038d0e1
--- /dev/null
+++ b/media/codecs/m4v_h263/dec/Android.bp
@@ -0,0 +1,76 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_m4v_h263_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_m4v_h263_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library_static {
+ name: "libstagefright_m4vh263dec",
+ vendor_available: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
+ min_sdk_version: "29",
+ host_supported: true,
+ shared_libs: ["liblog"],
+
+ srcs: [
+ "src/bitstream.cpp",
+ "src/block_idct.cpp",
+ "src/cal_dc_scaler.cpp",
+ "src/combined_decode.cpp",
+ "src/conceal.cpp",
+ "src/datapart_decode.cpp",
+ "src/dcac_prediction.cpp",
+ "src/dec_pred_intra_dc.cpp",
+ "src/get_pred_adv_b_add.cpp",
+ "src/get_pred_outside.cpp",
+ "src/idct.cpp",
+ "src/idct_vca.cpp",
+ "src/mb_motion_comp.cpp",
+ "src/mb_utils.cpp",
+ "src/packet_util.cpp",
+ "src/post_filter.cpp",
+ "src/pvdec_api.cpp",
+ "src/scaling_tab.cpp",
+ "src/vlc_decode.cpp",
+ "src/vlc_dequant.cpp",
+ "src/vlc_tab.cpp",
+ "src/vop.cpp",
+ "src/zigzag_tab.cpp",
+ ],
+
+ local_include_dirs: ["src"],
+ export_include_dirs: ["include"],
+
+ cflags: [
+ "-Werror",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2 b/media/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
rename to media/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/m4v_h263/dec/NOTICE b/media/codecs/m4v_h263/dec/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/NOTICE
rename to media/codecs/m4v_h263/dec/NOTICE
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h b/media/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
rename to media/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h b/media/codecs/m4v_h263/dec/include/mp4dec_api.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h
rename to media/codecs/m4v_h263/dec/include/mp4dec_api.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/visual_header.h b/media/codecs/m4v_h263/dec/include/visual_header.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/include/visual_header.h
rename to media/codecs/m4v_h263/dec/include/visual_header.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp b/media/codecs/m4v_h263/dec/src/bitstream.cpp
similarity index 97%
rename from media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
rename to media/codecs/m4v_h263/dec/src/bitstream.cpp
index 37250f3..5b19db4 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
+++ b/media/codecs/m4v_h263/dec/src/bitstream.cpp
@@ -649,8 +649,11 @@
-void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
+PV_STATUS PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
{
+ PV_STATUS status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) return status;
+
uint8 *ptr;
int32 byte_pos = (stream->bitcnt >> 3);
@@ -658,10 +661,14 @@
ptr = stream->bitstreamBuffer + byte_pos;
stream->data_end_pos = PVLocateFrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
+ return PV_SUCCESS;
}
-void PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
+PV_STATUS PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
{
+ PV_STATUS status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) return status;
+
uint8 *ptr;
int32 byte_pos = (stream->bitcnt >> 3);
@@ -669,6 +676,7 @@
ptr = stream->bitstreamBuffer + byte_pos;
stream->data_end_pos = PVLocateH263FrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
+ return PV_SUCCESS;
}
/* ======================================================================== */
@@ -687,7 +695,8 @@
if (stream->searched_frame_boundary == 0)
{
- PVLocateM4VFrameBoundary(stream);
+ status = PVLocateM4VFrameBoundary(stream);
+ if (status != PV_SUCCESS) return status;
}
do
@@ -711,7 +720,8 @@
if (stream->searched_frame_boundary == 0)
{
- PVLocateH263FrameBoundary(stream);
+ status = PVLocateH263FrameBoundary(stream);
+ if (status != PV_SUCCESS) return status;
}
do
@@ -789,7 +799,8 @@
if (stream->searched_frame_boundary == 0)
{
- PVLocateM4VFrameBoundary(stream);
+ status = PVLocateM4VFrameBoundary(stream);
+ if (status != PV_SUCCESS) return status;
}
while (TRUE)
@@ -880,7 +891,8 @@
if (stream->searched_frame_boundary == 0)
{
- PVLocateM4VFrameBoundary(stream);
+ status = PVLocateM4VFrameBoundary(stream);
+ if (status != PV_SUCCESS) return status;
}
while (TRUE)
@@ -956,7 +968,8 @@
if (stream->searched_frame_boundary == 0)
{
- PVLocateH263FrameBoundary(stream);
+ status = PVLocateH263FrameBoundary(stream);
+ if (status != PV_SUCCESS) return status;
}
while (TRUE)
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h b/media/codecs/m4v_h263/dec/src/bitstream.h
similarity index 97%
rename from media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
rename to media/codecs/m4v_h263/dec/src/bitstream.h
index d52fa87..0cf903d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
+++ b/media/codecs/m4v_h263/dec/src/bitstream.h
@@ -156,8 +156,8 @@
/* for error concealment & soft-decoding */
- void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream);
- void PVSearchH263FrameBoundary(BitstreamDecVideo *stream);
+ PV_STATUS PVLocateM4VFrameBoundary(BitstreamDecVideo *stream);
+ PV_STATUS PVSearchH263FrameBoundary(BitstreamDecVideo *stream);
PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream);
PV_STATUS quickSearchDCM(BitstreamDecVideo *stream);
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/block_idct.cpp b/media/codecs/m4v_h263/dec/src/block_idct.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/block_idct.cpp
rename to media/codecs/m4v_h263/dec/src/block_idct.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp b/media/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
rename to media/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/combined_decode.cpp b/media/codecs/m4v_h263/dec/src/combined_decode.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/combined_decode.cpp
rename to media/codecs/m4v_h263/dec/src/combined_decode.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp b/media/codecs/m4v_h263/dec/src/conceal.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
rename to media/codecs/m4v_h263/dec/src/conceal.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/datapart_decode.cpp b/media/codecs/m4v_h263/dec/src/datapart_decode.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/datapart_decode.cpp
rename to media/codecs/m4v_h263/dec/src/datapart_decode.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/dcac_prediction.cpp b/media/codecs/m4v_h263/dec/src/dcac_prediction.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/dcac_prediction.cpp
rename to media/codecs/m4v_h263/dec/src/dcac_prediction.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp b/media/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
rename to media/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp b/media/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
rename to media/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_outside.cpp b/media/codecs/m4v_h263/dec/src/get_pred_outside.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/get_pred_outside.cpp
rename to media/codecs/m4v_h263/dec/src/get_pred_outside.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/idct.cpp b/media/codecs/m4v_h263/dec/src/idct.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/idct.cpp
rename to media/codecs/m4v_h263/dec/src/idct.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/idct.h b/media/codecs/m4v_h263/dec/src/idct.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/idct.h
rename to media/codecs/m4v_h263/dec/src/idct.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/idct_vca.cpp b/media/codecs/m4v_h263/dec/src/idct_vca.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/idct_vca.cpp
rename to media/codecs/m4v_h263/dec/src/idct_vca.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/max_level.h b/media/codecs/m4v_h263/dec/src/max_level.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/max_level.h
rename to media/codecs/m4v_h263/dec/src/max_level.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp b/media/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
rename to media/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mb_utils.cpp b/media/codecs/m4v_h263/dec/src/mb_utils.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/mb_utils.cpp
rename to media/codecs/m4v_h263/dec/src/mb_utils.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mbtype_mode.h b/media/codecs/m4v_h263/dec/src/mbtype_mode.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/mbtype_mode.h
rename to media/codecs/m4v_h263/dec/src/mbtype_mode.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/motion_comp.h b/media/codecs/m4v_h263/dec/src/motion_comp.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/motion_comp.h
rename to media/codecs/m4v_h263/dec/src/motion_comp.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mp4dec_lib.h b/media/codecs/m4v_h263/dec/src/mp4dec_lib.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/mp4dec_lib.h
rename to media/codecs/m4v_h263/dec/src/mp4dec_lib.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mp4def.h b/media/codecs/m4v_h263/dec/src/mp4def.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/mp4def.h
rename to media/codecs/m4v_h263/dec/src/mp4def.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mp4lib_int.h b/media/codecs/m4v_h263/dec/src/mp4lib_int.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/mp4lib_int.h
rename to media/codecs/m4v_h263/dec/src/mp4lib_int.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp b/media/codecs/m4v_h263/dec/src/packet_util.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp
rename to media/codecs/m4v_h263/dec/src/packet_util.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/post_filter.cpp b/media/codecs/m4v_h263/dec/src/post_filter.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/post_filter.cpp
rename to media/codecs/m4v_h263/dec/src/post_filter.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/post_proc.h b/media/codecs/m4v_h263/dec/src/post_proc.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/post_proc.h
rename to media/codecs/m4v_h263/dec/src/post_proc.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/codecs/m4v_h263/dec/src/pvdec_api.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
rename to media/codecs/m4v_h263/dec/src/pvdec_api.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/scaling.h b/media/codecs/m4v_h263/dec/src/scaling.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/scaling.h
rename to media/codecs/m4v_h263/dec/src/scaling.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/scaling_tab.cpp b/media/codecs/m4v_h263/dec/src/scaling_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/scaling_tab.cpp
rename to media/codecs/m4v_h263/dec/src/scaling_tab.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dec_tab.h b/media/codecs/m4v_h263/dec/src/vlc_dec_tab.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/vlc_dec_tab.h
rename to media/codecs/m4v_h263/dec/src/vlc_dec_tab.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp b/media/codecs/m4v_h263/dec/src/vlc_decode.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp
rename to media/codecs/m4v_h263/dec/src/vlc_decode.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.h b/media/codecs/m4v_h263/dec/src/vlc_decode.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.h
rename to media/codecs/m4v_h263/dec/src/vlc_decode.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dequant.cpp b/media/codecs/m4v_h263/dec/src/vlc_dequant.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/vlc_dequant.cpp
rename to media/codecs/m4v_h263/dec/src/vlc_dequant.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_tab.cpp b/media/codecs/m4v_h263/dec/src/vlc_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/vlc_tab.cpp
rename to media/codecs/m4v_h263/dec/src/vlc_tab.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/codecs/m4v_h263/dec/src/vop.cpp
similarity index 98%
rename from media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
rename to media/codecs/m4v_h263/dec/src/vop.cpp
index 335846c..7b32498 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/codecs/m4v_h263/dec/src/vop.cpp
@@ -497,6 +497,13 @@
}
while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
+ /* qmatrix must have at least one non-zero value, which means
+ i would be non-zero in valid cases */
+ if (i == 0)
+ {
+ return PV_FAIL;
+ }
+
for (j = i; j < 64; j++)
qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
}
@@ -520,6 +527,13 @@
}
while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
+ /* qmatrix must have at least one non-zero value, which means
+ i would be non-zero in valid cases */
+ if (i == 0)
+ {
+ return PV_FAIL;
+ }
+
for (j = i; j < 64; j++)
qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/zigzag.h b/media/codecs/m4v_h263/dec/src/zigzag.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/zigzag.h
rename to media/codecs/m4v_h263/dec/src/zigzag.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/zigzag_tab.cpp b/media/codecs/m4v_h263/dec/src/zigzag_tab.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/src/zigzag_tab.cpp
rename to media/codecs/m4v_h263/dec/src/zigzag_tab.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp b/media/codecs/m4v_h263/dec/test/Android.bp
similarity index 73%
rename from media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
rename to media/codecs/m4v_h263/dec/test/Android.bp
index 655491a..4ae5e73 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/codecs/m4v_h263/dec/test/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_m4v_h263_dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_m4v_h263_dec_license",
+ ],
+}
+
cc_test {
name: "Mpeg4H263DecoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/codecs/m4v_h263/dec/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml
rename to media/codecs/m4v_h263/dec/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp b/media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
rename to media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h b/media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
rename to media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/README.md b/media/codecs/m4v_h263/dec/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/dec/test/README.md
rename to media/codecs/m4v_h263/dec/test/README.md
diff --git a/media/codecs/m4v_h263/enc/Android.bp b/media/codecs/m4v_h263/enc/Android.bp
new file mode 100644
index 0000000..e303404
--- /dev/null
+++ b/media/codecs/m4v_h263/enc/Android.bp
@@ -0,0 +1,107 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_m4v_h263_enc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_m4v_h263_enc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library_static {
+ name: "libstagefright_m4vh263enc",
+ vendor_available: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
+ min_sdk_version: "29",
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
+ srcs: [
+ "src/bitstream_io.cpp",
+ "src/combined_encode.cpp", "src/datapart_encode.cpp",
+ "src/dct.cpp",
+ "src/findhalfpel.cpp",
+ "src/fastcodemb.cpp",
+ "src/fastidct.cpp",
+ "src/fastquant.cpp",
+ "src/me_utils.cpp",
+ "src/mp4enc_api.cpp",
+ "src/rate_control.cpp",
+ "src/motion_est.cpp",
+ "src/motion_comp.cpp",
+ "src/sad.cpp",
+ "src/sad_halfpel.cpp",
+ "src/vlc_encode.cpp",
+ "src/vop.cpp",
+ ],
+
+ cflags: [
+ "-DBX_RC",
+ "-Werror",
+ ],
+
+ local_include_dirs: ["src"],
+ export_include_dirs: ["include"],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+}
+
+//###############################################################################
+
+cc_test {
+ name: "libstagefright_m4vh263enc_test",
+ gtest: false,
+
+ srcs: ["test/m4v_h263_enc_test.cpp"],
+
+ local_include_dirs: ["src"],
+
+ cflags: [
+ "-DBX_RC",
+ "-Wall",
+ "-Werror",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+
+ static_libs: ["libstagefright_m4vh263enc"],
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2 b/media/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
rename to media/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/m4v_h263/enc/NOTICE b/media/codecs/m4v_h263/enc/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/NOTICE
rename to media/codecs/m4v_h263/enc/NOTICE
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h b/media/codecs/m4v_h263/enc/include/cvei.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/include/cvei.h
rename to media/codecs/m4v_h263/enc/include/cvei.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/codecs/m4v_h263/enc/include/mp4enc_api.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
rename to media/codecs/m4v_h263/enc/include/mp4enc_api.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp b/media/codecs/m4v_h263/enc/src/bitstream_io.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp
rename to media/codecs/m4v_h263/enc/src/bitstream_io.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h b/media/codecs/m4v_h263/enc/src/bitstream_io.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h
rename to media/codecs/m4v_h263/enc/src/bitstream_io.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp b/media/codecs/m4v_h263/enc/src/combined_encode.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp
rename to media/codecs/m4v_h263/enc/src/combined_encode.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp b/media/codecs/m4v_h263/enc/src/datapart_encode.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp
rename to media/codecs/m4v_h263/enc/src/datapart_encode.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp b/media/codecs/m4v_h263/enc/src/dct.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
rename to media/codecs/m4v_h263/enc/src/dct.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.h b/media/codecs/m4v_h263/enc/src/dct.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/dct.h
rename to media/codecs/m4v_h263/enc/src/dct.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h b/media/codecs/m4v_h263/enc/src/dct_inline.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h
rename to media/codecs/m4v_h263/enc/src/dct_inline.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/codecs/m4v_h263/enc/src/fastcodemb.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp
rename to media/codecs/m4v_h263/enc/src/fastcodemb.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h b/media/codecs/m4v_h263/enc/src/fastcodemb.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h
rename to media/codecs/m4v_h263/enc/src/fastcodemb.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp b/media/codecs/m4v_h263/enc/src/fastidct.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp
rename to media/codecs/m4v_h263/enc/src/fastidct.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp b/media/codecs/m4v_h263/enc/src/fastquant.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp
rename to media/codecs/m4v_h263/enc/src/fastquant.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h b/media/codecs/m4v_h263/enc/src/fastquant_inline.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h
rename to media/codecs/m4v_h263/enc/src/fastquant_inline.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp b/media/codecs/m4v_h263/enc/src/findhalfpel.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp
rename to media/codecs/m4v_h263/enc/src/findhalfpel.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h b/media/codecs/m4v_h263/enc/src/m4venc_oscl.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h
rename to media/codecs/m4v_h263/enc/src/m4venc_oscl.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp b/media/codecs/m4v_h263/enc/src/me_utils.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp
rename to media/codecs/m4v_h263/enc/src/me_utils.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/codecs/m4v_h263/enc/src/motion_comp.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp
rename to media/codecs/m4v_h263/enc/src/motion_comp.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp b/media/codecs/m4v_h263/enc/src/motion_est.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
rename to media/codecs/m4v_h263/enc/src/motion_est.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h b/media/codecs/m4v_h263/enc/src/mp4def.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h
rename to media/codecs/m4v_h263/enc/src/mp4def.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
similarity index 99%
rename from media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
rename to media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 7ab8f45..4555203 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -524,11 +524,9 @@
}
/* check bit rate */
- /* set max bit rate */
for (i = 0; i < encParams->nLayers; i++)
{
encParams->LayerBitRate[i] = encOption->bitRate[i];
- encParams->LayerMaxBitRate[i] = encOption->bitRate[i];
}
if (encParams->nLayers > 1)
{
@@ -1579,7 +1577,7 @@
if (currLayer == 0)
{
video->forwardRefVop = tempForwRefVop; /* For P-Vop base only */
- video->forwardRefVop->refSelectCode = tempRefSelCode;
+ if (video->forwardRefVop != NULL) video->forwardRefVop->refSelectCode = tempRefSelCode;
}
return status;
@@ -3302,6 +3300,3 @@
}
#endif /* #ifndef ORIGINAL_VERSION */
-
-
-
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h b/media/codecs/m4v_h263/enc/src/mp4enc_lib.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h
rename to media/codecs/m4v_h263/enc/src/mp4enc_lib.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h b/media/codecs/m4v_h263/enc/src/mp4lib_int.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
rename to media/codecs/m4v_h263/enc/src/mp4lib_int.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp b/media/codecs/m4v_h263/enc/src/rate_control.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
rename to media/codecs/m4v_h263/enc/src/rate_control.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h b/media/codecs/m4v_h263/enc/src/rate_control.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h
rename to media/codecs/m4v_h263/enc/src/rate_control.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp b/media/codecs/m4v_h263/enc/src/sad.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp
rename to media/codecs/m4v_h263/enc/src/sad.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp b/media/codecs/m4v_h263/enc/src/sad_halfpel.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp
rename to media/codecs/m4v_h263/enc/src/sad_halfpel.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h b/media/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
rename to media/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h b/media/codecs/m4v_h263/enc/src/sad_inline.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h
rename to media/codecs/m4v_h263/enc/src/sad_inline.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h b/media/codecs/m4v_h263/enc/src/sad_mb_offset.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h
rename to media/codecs/m4v_h263/enc/src/sad_mb_offset.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h b/media/codecs/m4v_h263/enc/src/vlc_enc_tab.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h
rename to media/codecs/m4v_h263/enc/src/vlc_enc_tab.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/codecs/m4v_h263/enc/src/vlc_encode.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
rename to media/codecs/m4v_h263/enc/src/vlc_encode.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h b/media/codecs/m4v_h263/enc/src/vlc_encode.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h
rename to media/codecs/m4v_h263/enc/src/vlc_encode.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h b/media/codecs/m4v_h263/enc/src/vlc_encode_inline.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h
rename to media/codecs/m4v_h263/enc/src/vlc_encode_inline.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp b/media/codecs/m4v_h263/enc/src/vop.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp
rename to media/codecs/m4v_h263/enc/src/vop.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp b/media/codecs/m4v_h263/enc/test/Android.bp
similarity index 71%
rename from media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
rename to media/codecs/m4v_h263/enc/test/Android.bp
index b9a8117..e1ce4aa 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/codecs/m4v_h263/enc/test/Android.bp
@@ -14,6 +14,18 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_m4v_h263_enc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: [
+ "frameworks_av_media_codecs_m4v_h263_enc_license",
+ ],
+}
+
cc_test {
name: "Mpeg4H263EncoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/codecs/m4v_h263/enc/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
rename to media/codecs/m4v_h263/enc/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
rename to media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
rename to media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/README.md b/media/codecs/m4v_h263/enc/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/test/README.md
rename to media/codecs/m4v_h263/enc/test/README.md
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp b/media/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
rename to media/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/Android.bp b/media/codecs/m4v_h263/fuzzer/Android.bp
similarity index 86%
rename from media/libstagefright/codecs/m4v_h263/fuzzer/Android.bp
rename to media/codecs/m4v_h263/fuzzer/Android.bp
index 778dafb..a052c11 100644
--- a/media/libstagefright/codecs/m4v_h263/fuzzer/Android.bp
+++ b/media/codecs/m4v_h263/fuzzer/Android.bp
@@ -18,6 +18,15 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "mpeg4_h263_dec_fuzz_defaults",
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/README.md b/media/codecs/m4v_h263/fuzzer/README.md
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/fuzzer/README.md
rename to media/codecs/m4v_h263/fuzzer/README.md
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict b/media/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
rename to media/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict b/media/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
rename to media/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp b/media/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
rename to media/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp b/media/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
rename to media/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
diff --git a/media/libstagefright/codecs/m4v_h263/patent_disclaimer.txt b/media/codecs/m4v_h263/patent_disclaimer.txt
similarity index 100%
rename from media/libstagefright/codecs/m4v_h263/patent_disclaimer.txt
rename to media/codecs/m4v_h263/patent_disclaimer.txt
diff --git a/media/codecs/mp3dec/Android.bp b/media/codecs/mp3dec/Android.bp
new file mode 100644
index 0000000..015b8b6
--- /dev/null
+++ b/media/codecs/mp3dec/Android.bp
@@ -0,0 +1,158 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_codecs_mp3dec_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_codecs_mp3dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library_headers {
+ name: "libstagefright_mp3dec_headers",
+ vendor_available: true,
+ min_sdk_version: "29",
+ host_supported:true,
+ export_include_dirs: [
+ "include",
+ "src",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
+}
+
+cc_library_static {
+ name: "libstagefright_mp3dec",
+ vendor_available: true,
+ min_sdk_version: "29",
+
+ host_supported:true,
+ srcs: [
+ "src/pvmp3_normalize.cpp",
+ "src/pvmp3_alias_reduction.cpp",
+ "src/pvmp3_crc.cpp",
+ "src/pvmp3_decode_header.cpp",
+ "src/pvmp3_decode_huff_cw.cpp",
+ "src/pvmp3_getbits.cpp",
+ "src/pvmp3_dequantize_sample.cpp",
+ "src/pvmp3_framedecoder.cpp",
+ "src/pvmp3_get_main_data_size.cpp",
+ "src/pvmp3_get_side_info.cpp",
+ "src/pvmp3_get_scale_factors.cpp",
+ "src/pvmp3_mpeg2_get_scale_data.cpp",
+ "src/pvmp3_mpeg2_get_scale_factors.cpp",
+ "src/pvmp3_mpeg2_stereo_proc.cpp",
+ "src/pvmp3_huffman_decoding.cpp",
+ "src/pvmp3_huffman_parsing.cpp",
+ "src/pvmp3_tables.cpp",
+ "src/pvmp3_imdct_synth.cpp",
+ "src/pvmp3_mdct_6.cpp",
+ "src/pvmp3_dct_6.cpp",
+ "src/pvmp3_poly_phase_synthesis.cpp",
+ "src/pvmp3_equalizer.cpp",
+ "src/pvmp3_seek_synch.cpp",
+ "src/pvmp3_stereo_proc.cpp",
+ "src/pvmp3_reorder.cpp",
+
+ "src/pvmp3_polyphase_filter_window.cpp",
+ "src/pvmp3_mdct_18.cpp",
+ "src/pvmp3_dct_9.cpp",
+ "src/pvmp3_dct_16.cpp",
+ ],
+
+ arch: {
+ arm: {
+ exclude_srcs: [
+ "src/pvmp3_polyphase_filter_window.cpp",
+ "src/pvmp3_mdct_18.cpp",
+ "src/pvmp3_dct_9.cpp",
+ "src/pvmp3_dct_16.cpp",
+ ],
+ srcs: [
+ "src/asm/pvmp3_polyphase_filter_window_gcc.s",
+ "src/asm/pvmp3_mdct_18_gcc.s",
+ "src/asm/pvmp3_dct_9_gcc.s",
+ "src/asm/pvmp3_dct_16_gcc.s",
+ ],
+
+ instruction_set: "arm",
+ },
+ },
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+
+ include_dirs: ["frameworks/av/media/libstagefright/include"],
+
+ header_libs: ["libstagefright_mp3dec_headers"],
+ export_header_lib_headers: ["libstagefright_mp3dec_headers"],
+
+ cflags: [
+ "-DOSCL_UNUSED_ARG(x)=(void)(x)",
+ "-Werror",
+ ],
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+//###############################################################################
+cc_test {
+ name: "libstagefright_mp3dec_test",
+ gtest: false,
+
+ srcs: [
+ "test/mp3dec_test.cpp",
+ "test/mp3reader.cpp",
+ ],
+
+ cflags: ["-Wall", "-Werror"],
+
+ local_include_dirs: [
+ "src",
+ "include",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+
+ static_libs: [
+ "libstagefright_mp3dec",
+ "libsndfile",
+ ],
+
+ shared_libs: ["libaudioutils"],
+}
diff --git a/media/libstagefright/codecs/mp3dec/MODULE_LICENSE_APACHE2 b/media/codecs/mp3dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/MODULE_LICENSE_APACHE2
rename to media/codecs/mp3dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/mp3dec/NOTICE b/media/codecs/mp3dec/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/NOTICE
rename to media/codecs/mp3dec/NOTICE
diff --git a/media/codecs/mp3dec/TEST_MAPPING b/media/codecs/mp3dec/TEST_MAPPING
new file mode 100644
index 0000000..4ef4317
--- /dev/null
+++ b/media/codecs/mp3dec/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/libstagefright/codecs/mp3dec
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "Mp3DecoderTest"}
+ ]
+}
diff --git a/media/libstagefright/codecs/mp3dec/fuzzer/Android.bp b/media/codecs/mp3dec/fuzzer/Android.bp
similarity index 75%
rename from media/libstagefright/codecs/mp3dec/fuzzer/Android.bp
rename to media/codecs/mp3dec/fuzzer/Android.bp
index 79fa1e9..514a8a8 100644
--- a/media/libstagefright/codecs/mp3dec/fuzzer/Android.bp
+++ b/media/codecs/mp3dec/fuzzer/Android.bp
@@ -18,6 +18,15 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_mp3dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_codecs_mp3dec_license"],
+}
+
cc_fuzz {
name: "mp3_dec_fuzzer",
host_supported: true,
diff --git a/media/libstagefright/codecs/mp3dec/fuzzer/README.md b/media/codecs/mp3dec/fuzzer/README.md
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/fuzzer/README.md
rename to media/codecs/mp3dec/fuzzer/README.md
diff --git a/media/libstagefright/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp b/media/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
rename to media/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
diff --git a/media/libstagefright/codecs/mp3dec/include/mp3_decoder_selection.h b/media/codecs/mp3dec/include/mp3_decoder_selection.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/include/mp3_decoder_selection.h
rename to media/codecs/mp3dec/include/mp3_decoder_selection.h
diff --git a/media/libstagefright/codecs/mp3dec/include/pvmp3_audio_type_defs.h b/media/codecs/mp3dec/include/pvmp3_audio_type_defs.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/include/pvmp3_audio_type_defs.h
rename to media/codecs/mp3dec/include/pvmp3_audio_type_defs.h
diff --git a/media/libstagefright/codecs/mp3dec/include/pvmp3decoder_api.h b/media/codecs/mp3dec/include/pvmp3decoder_api.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/include/pvmp3decoder_api.h
rename to media/codecs/mp3dec/include/pvmp3decoder_api.h
diff --git a/media/libstagefright/codecs/mp3dec/patent_disclaimer.txt b/media/codecs/mp3dec/patent_disclaimer.txt
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/patent_disclaimer.txt
rename to media/codecs/mp3dec/patent_disclaimer.txt
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s b/media/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
rename to media/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s b/media/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
rename to media/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s b/media/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
rename to media/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s b/media/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
rename to media/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
diff --git a/media/libstagefright/codecs/mp3dec/src/mp3_mem_funcs.h b/media/codecs/mp3dec/src/mp3_mem_funcs.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/mp3_mem_funcs.h
rename to media/codecs/mp3dec/src/mp3_mem_funcs.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3_huffman.h b/media/codecs/mp3dec/src/pv_mp3_huffman.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pv_mp3_huffman.h
rename to media/codecs/mp3dec/src/pv_mp3_huffman.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op.h b/media/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
rename to media/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h b/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
rename to media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h b/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
rename to media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h b/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
rename to media/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h b/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
rename to media/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp b/media/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
rename to media/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.h b/media/codecs/mp3dec/src/pvmp3_alias_reduction.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.h
rename to media/codecs/mp3dec/src/pvmp3_alias_reduction.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.cpp b/media/codecs/mp3dec/src/pvmp3_crc.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_crc.cpp
rename to media/codecs/mp3dec/src/pvmp3_crc.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.h b/media/codecs/mp3dec/src/pvmp3_crc.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_crc.h
rename to media/codecs/mp3dec/src/pvmp3_crc.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.cpp b/media/codecs/mp3dec/src/pvmp3_dct_16.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.cpp
rename to media/codecs/mp3dec/src/pvmp3_dct_16.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.h b/media/codecs/mp3dec/src/pvmp3_dct_16.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.h
rename to media/codecs/mp3dec/src/pvmp3_dct_16.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_6.cpp b/media/codecs/mp3dec/src/pvmp3_dct_6.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dct_6.cpp
rename to media/codecs/mp3dec/src/pvmp3_dct_6.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp b/media/codecs/mp3dec/src/pvmp3_dct_9.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
rename to media/codecs/mp3dec/src/pvmp3_dct_9.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dec_defs.h b/media/codecs/mp3dec/src/pvmp3_dec_defs.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dec_defs.h
rename to media/codecs/mp3dec/src/pvmp3_dec_defs.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp b/media/codecs/mp3dec/src/pvmp3_decode_header.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp
rename to media/codecs/mp3dec/src/pvmp3_decode_header.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.h b/media/codecs/mp3dec/src/pvmp3_decode_header.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.h
rename to media/codecs/mp3dec/src/pvmp3_decode_header.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp b/media/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
rename to media/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.h b/media/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
rename to media/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp b/media/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
rename to media/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.h b/media/codecs/mp3dec/src/pvmp3_dequantize_sample.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.h
rename to media/codecs/mp3dec/src/pvmp3_dequantize_sample.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.cpp b/media/codecs/mp3dec/src/pvmp3_equalizer.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.cpp
rename to media/codecs/mp3dec/src/pvmp3_equalizer.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.h b/media/codecs/mp3dec/src/pvmp3_equalizer.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.h
rename to media/codecs/mp3dec/src/pvmp3_equalizer.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
rename to media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.h b/media/codecs/mp3dec/src/pvmp3_framedecoder.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.h
rename to media/codecs/mp3dec/src/pvmp3_framedecoder.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp b/media/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
rename to media/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.h b/media/codecs/mp3dec/src/pvmp3_get_main_data_size.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.h
rename to media/codecs/mp3dec/src/pvmp3_get_main_data_size.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp b/media/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
rename to media/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.h b/media/codecs/mp3dec/src/pvmp3_get_scale_factors.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.h
rename to media/codecs/mp3dec/src/pvmp3_get_scale_factors.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/codecs/mp3dec/src/pvmp3_get_side_info.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
rename to media/codecs/mp3dec/src/pvmp3_get_side_info.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.h b/media/codecs/mp3dec/src/pvmp3_get_side_info.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.h
rename to media/codecs/mp3dec/src/pvmp3_get_side_info.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/codecs/mp3dec/src/pvmp3_getbits.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
rename to media/codecs/mp3dec/src/pvmp3_getbits.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h b/media/codecs/mp3dec/src/pvmp3_getbits.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
rename to media/codecs/mp3dec/src/pvmp3_getbits.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp b/media/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
rename to media/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp b/media/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
rename to media/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.cpp b/media/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
rename to media/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.h b/media/codecs/mp3dec/src/pvmp3_imdct_synth.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.h
rename to media/codecs/mp3dec/src/pvmp3_imdct_synth.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.cpp b/media/codecs/mp3dec/src/pvmp3_mdct_18.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.cpp
rename to media/codecs/mp3dec/src/pvmp3_mdct_18.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.h b/media/codecs/mp3dec/src/pvmp3_mdct_18.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.h
rename to media/codecs/mp3dec/src/pvmp3_mdct_18.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.cpp b/media/codecs/mp3dec/src/pvmp3_mdct_6.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.cpp
rename to media/codecs/mp3dec/src/pvmp3_mdct_6.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.h b/media/codecs/mp3dec/src/pvmp3_mdct_6.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.h
rename to media/codecs/mp3dec/src/pvmp3_mdct_6.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp b/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
rename to media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h b/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
rename to media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp b/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
rename to media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h b/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
rename to media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp b/media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
rename to media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h b/media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
rename to media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp b/media/codecs/mp3dec/src/pvmp3_normalize.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp
rename to media/codecs/mp3dec/src/pvmp3_normalize.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.h b/media/codecs/mp3dec/src/pvmp3_normalize.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.h
rename to media/codecs/mp3dec/src/pvmp3_normalize.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp b/media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
rename to media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h b/media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
rename to media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp b/media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
rename to media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h b/media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
rename to media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp b/media/codecs/mp3dec/src/pvmp3_reorder.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp
rename to media/codecs/mp3dec/src/pvmp3_reorder.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h b/media/codecs/mp3dec/src/pvmp3_reorder.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h
rename to media/codecs/mp3dec/src/pvmp3_reorder.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.cpp b/media/codecs/mp3dec/src/pvmp3_seek_synch.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.cpp
rename to media/codecs/mp3dec/src/pvmp3_seek_synch.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.h b/media/codecs/mp3dec/src/pvmp3_seek_synch.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.h
rename to media/codecs/mp3dec/src/pvmp3_seek_synch.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp b/media/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
rename to media/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.h b/media/codecs/mp3dec/src/pvmp3_stereo_proc.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.h
rename to media/codecs/mp3dec/src/pvmp3_stereo_proc.h
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.cpp b/media/codecs/mp3dec/src/pvmp3_tables.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_tables.cpp
rename to media/codecs/mp3dec/src/pvmp3_tables.cpp
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.h b/media/codecs/mp3dec/src/pvmp3_tables.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/pvmp3_tables.h
rename to media/codecs/mp3dec/src/pvmp3_tables.h
diff --git a/media/libstagefright/codecs/mp3dec/src/s_huffcodetab.h b/media/codecs/mp3dec/src/s_huffcodetab.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/s_huffcodetab.h
rename to media/codecs/mp3dec/src/s_huffcodetab.h
diff --git a/media/libstagefright/codecs/mp3dec/src/s_mp3bits.h b/media/codecs/mp3dec/src/s_mp3bits.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/s_mp3bits.h
rename to media/codecs/mp3dec/src/s_mp3bits.h
diff --git a/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_chan.h b/media/codecs/mp3dec/src/s_tmp3dec_chan.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/s_tmp3dec_chan.h
rename to media/codecs/mp3dec/src/s_tmp3dec_chan.h
diff --git a/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h b/media/codecs/mp3dec/src/s_tmp3dec_file.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h
rename to media/codecs/mp3dec/src/s_tmp3dec_file.h
diff --git a/media/libstagefright/codecs/mp3dec/test/Android.bp b/media/codecs/mp3dec/test/Android.bp
similarity index 73%
rename from media/libstagefright/codecs/mp3dec/test/Android.bp
rename to media/codecs/mp3dec/test/Android.bp
index 0ff8b12..8003068 100644
--- a/media/libstagefright/codecs/mp3dec/test/Android.bp
+++ b/media/codecs/mp3dec/test/Android.bp
@@ -14,6 +14,16 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_codecs_mp3dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: ["frameworks_av_media_codecs_mp3dec_license"],
+}
+
cc_test {
name: "Mp3DecoderTest",
gtest: true,
diff --git a/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml b/media/codecs/mp3dec/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
rename to media/codecs/mp3dec/test/AndroidTest.xml
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/codecs/mp3dec/test/Mp3DecoderTest.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
rename to media/codecs/mp3dec/test/Mp3DecoderTest.cpp
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h b/media/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
rename to media/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
diff --git a/media/libstagefright/codecs/mp3dec/test/README.md b/media/codecs/mp3dec/test/README.md
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/README.md
rename to media/codecs/mp3dec/test/README.md
diff --git a/media/libstagefright/codecs/mp3dec/test/mp3dec_test.cpp b/media/codecs/mp3dec/test/mp3dec_test.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/mp3dec_test.cpp
rename to media/codecs/mp3dec/test/mp3dec_test.cpp
diff --git a/media/libstagefright/codecs/mp3dec/test/mp3reader.cpp b/media/codecs/mp3dec/test/mp3reader.cpp
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/mp3reader.cpp
rename to media/codecs/mp3dec/test/mp3reader.cpp
diff --git a/media/libstagefright/codecs/mp3dec/test/mp3reader.h b/media/codecs/mp3dec/test/mp3reader.h
similarity index 100%
rename from media/libstagefright/codecs/mp3dec/test/mp3reader.h
rename to media/codecs/mp3dec/test/mp3reader.h
diff --git a/media/extractors/Android.bp b/media/extractors/Android.bp
index f9abfe3..7513cb1 100644
--- a/media/extractors/Android.bp
+++ b/media/extractors/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "extractor-defaults",
@@ -60,4 +69,4 @@
"signed-integer-overflow",
],
},
-}
\ No newline at end of file
+}
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index c036bb5..7bf3a13 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_aac_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_aac_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libaacextractor",
defaults: ["extractor-defaults"],
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index 440065f..712360d 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_amr_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_amr_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libamrextractor",
defaults: ["extractor-defaults"],
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 2593000..9a2a76b 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -1,6 +1,25 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_extractors_flac_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_flac_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libflacextractor",
- defaults: ["extractor-defaults"],
+ defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
srcs: ["FLACExtractor.cpp"],
diff --git a/media/extractors/fuzzers/Android.bp b/media/extractors/fuzzers/Android.bp
index 31d6f83..f9e82fb 100644
--- a/media/extractors/fuzzers/Android.bp
+++ b/media/extractors/fuzzers/Android.bp
@@ -17,6 +17,15 @@
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "extractor-fuzzerbase-defaults",
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index b8255fc..f82fc41 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_extractors_midi_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_midi_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libmidiextractor",
defaults: ["extractor-defaults"],
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 330d4fe..840c9fc 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_mkv_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_mkv_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libmkvextractor",
defaults: ["extractor-defaults"],
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index fd6a8c6..4fd3a56 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -840,7 +840,7 @@
}
if (err != OK) {
- mPendingFrames.clear();
+ clearPendingFrames();
mBlockIter.advance();
mbuf->release();
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 7d70548..75b9b7b 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libmp3extractor",
defaults: ["extractor-defaults"],
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index afa055f..7fa6bfd 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_mp4_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_mp4_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libmp4extractor",
defaults: ["extractor-defaults"],
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 4c25314..7e6247b 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_extractors_mpeg2_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_mpeg2_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libmpeg2extractor",
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 579065e..d7540c4 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_ogg_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_ogg_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "liboggextractor",
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 828bcd6..eb2246d 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -1304,8 +1304,8 @@
|| audioChannelCount <= 0 || audioChannelCount > FCC_8) {
ALOGE("Invalid haptic channel count found in metadata: %d", mHapticChannelCount);
} else {
- const audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(
- audioChannelCount) | hapticChannelMask;
+ const audio_channel_mask_t channelMask = static_cast<audio_channel_mask_t>(
+ audio_channel_out_mask_from_count(audioChannelCount) | hapticChannelMask);
AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK, channelMask);
AMediaFormat_setInt32(
mMeta, AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT, mHapticChannelCount);
diff --git a/media/extractors/tests/Android.bp b/media/extractors/tests/Android.bp
index b3afe2f..f46fa7b 100644
--- a/media/extractors/tests/Android.bp
+++ b/media/extractors/tests/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "ExtractorUnitTest",
gtest: true,
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 85d4cce..cc5e1c7 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -1,7 +1,24 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_wav_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_extractors_wav_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libwavextractor",
- defaults: ["extractor-defaults"],
+ defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
srcs: ["WAVExtractor.cpp"],
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index d19447a..901b29d 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -95,9 +95,9 @@
AMediaFormat *mMeta;
uint16_t mWaveFormat;
const bool mOutputFloat;
- int32_t mSampleRate;
- int32_t mNumChannels;
- int32_t mBitsPerSample;
+ uint32_t mSampleRate;
+ uint32_t mNumChannels;
+ uint32_t mBitsPerSample;
off64_t mOffset;
size_t mSize;
bool mStarted;
@@ -379,9 +379,9 @@
mOffset(offset),
mSize(size),
mStarted(false) {
- CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate));
- CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &mNumChannels));
- CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &mBitsPerSample));
+ CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) &mSampleRate));
+ CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, (int32_t*) &mNumChannels));
+ CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, (int32_t*) &mBitsPerSample));
}
WAVSource::~WAVSource() {
@@ -472,7 +472,7 @@
}
const size_t maxBytesAvailable =
- (mCurrentPos - mOffset >= (off64_t)mSize)
+ (mCurrentPos < mOffset || mCurrentPos - mOffset >= (off64_t)mSize)
? 0 : mSize - (mCurrentPos - mOffset);
if (maxBytesToRead > maxBytesAvailable) {
diff --git a/media/img_utils/Android.bp b/media/img_utils/Android.bp
index 64530e1..237cd2b 100644
--- a/media/img_utils/Android.bp
+++ b/media/img_utils/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libimg_utils",
diff --git a/media/janitors/OWNERS-codecs b/media/janitors/codec_OWNERS
similarity index 100%
rename from media/janitors/OWNERS-codecs
rename to media/janitors/codec_OWNERS
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index 140052f..05c788c 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
ndk_headers {
name: "libAAudio_headers",
from: "include",
@@ -33,4 +42,3 @@
name: "libaaudio_headers",
export_include_dirs: ["include"],
}
-
diff --git a/media/libaaudio/examples/Android.bp b/media/libaaudio/examples/Android.bp
index 49bd5ee..e2c1878 100644
--- a/media/libaaudio/examples/Android.bp
+++ b/media/libaaudio/examples/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaaudio_example_utils",
export_include_dirs: ["utils"],
diff --git a/media/libaaudio/examples/input_monitor/Android.bp b/media/libaaudio/examples/input_monitor/Android.bp
index d8c5843..72adfd7 100644
--- a/media/libaaudio/examples/input_monitor/Android.bp
+++ b/media/libaaudio/examples/input_monitor/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "input_monitor",
gtest: false,
diff --git a/media/libaaudio/examples/loopback/Android.bp b/media/libaaudio/examples/loopback/Android.bp
index 5b7d956..8d86e95 100644
--- a/media/libaaudio/examples/loopback/Android.bp
+++ b/media/libaaudio/examples/loopback/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "aaudio_loopback",
gtest: false,
diff --git a/media/libaaudio/examples/write_sine/Android.bp b/media/libaaudio/examples/write_sine/Android.bp
index aa25e67..1c7e0f1 100644
--- a/media/libaaudio/examples/write_sine/Android.bp
+++ b/media/libaaudio/examples/write_sine/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "write_sine",
srcs: ["src/write_sine.cpp"],
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 7aaf908..709c656 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1024,7 +1024,6 @@
// Stream Control
// ============================================================
-#if __ANDROID_API__ >= 30
/**
* Free the audio resources associated with a stream created by
* AAudioStreamBuilder_openStream().
@@ -1037,11 +1036,17 @@
* but still allow queries to the stream to occur from other threads. This often
* happens if you are monitoring stream progress from a UI thread.
*
+ * NOTE: This function is only fully implemented for MMAP streams,
+ * which are low latency streams supported by some devices.
+ * On other "Legacy" streams some audio resources will still be in use
+ * and some callbacks may still be in process after this call.
+ *
+ * Available since API level 30.
+ *
* @param stream reference provided by AAudioStreamBuilder_openStream()
* @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_release(AAudioStream* stream) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__
/**
* Delete the internal data structures associated with the stream created
@@ -1049,6 +1054,8 @@
*
* If AAudioStream_release() has not been called then it will be called automatically.
*
+ * Available since API level 26.
+ *
* @param stream reference provided by AAudioStreamBuilder_openStream()
* @return {@link #AAUDIO_OK} or a negative error.
*/
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 717f31a..fdbc9c5 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libaaudio",
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 9fa2e40..fce322b 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \
- : "AudioStreamInternalCapture_Client")
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -29,6 +27,14 @@
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <utils/Trace.h>
+// We do this after the #includes because if a header uses ALOG.
+// it would fail on the reference to mInService.
+#undef LOG_TAG
+// This file is used in both client and server processes.
+// This is needed to make sense of the logs more easily.
+#define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \
+ : "AudioStreamInternalCapture_Client")
+
using android::WrappingBuffer;
using namespace aaudio;
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 1303daf..d6b73b4 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG (mInService ? "AudioStreamInternalPlay_Service" \
- : "AudioStreamInternalPlay_Client")
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -26,6 +24,14 @@
#include "client/AudioStreamInternalPlay.h"
#include "utility/AudioClock.h"
+// We do this after the #includes because if a header uses ALOG.
+// it would fail on the reference to mInService.
+#undef LOG_TAG
+// This file is used in both client and server processes.
+// This is needed to make sense of the logs more easily.
+#define LOG_TAG (mInService ? "AudioStreamInternalPlay_Service" \
+ : "AudioStreamInternalPlay_Client")
+
using android::WrappingBuffer;
using namespace aaudio;
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8965875..cfa7221 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -255,17 +255,16 @@
if (audioStream != nullptr) {
aaudio_stream_id_t id = audioStream->getId();
ALOGD("%s(s#%u) called ---------------", __func__, id);
- result = audioStream->safeRelease();
- // safeRelease will only fail if called illegally, for example, from a callback.
+ result = audioStream->safeReleaseClose();
+ // safeReleaseClose will only fail if called illegally, for example, from a callback.
// That would result in deleting an active stream, which would cause a crash.
if (result != AAUDIO_OK) {
ALOGW("%s(s#%u) failed. Close it from another thread.",
__func__, id);
} else {
audioStream->unregisterPlayerBase();
- // Mark CLOSED to keep destructors from asserting.
- audioStream->closeFinal();
- delete audioStream;
+ // Allow the stream to be deleted.
+ AudioStreamBuilder::stopUsingStream(audioStream);
}
ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index f5c75ca..f439310 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -39,7 +39,7 @@
}
AudioStream::AudioStream()
- : mPlayerBase(new MyPlayerBase(this))
+ : mPlayerBase(new MyPlayerBase())
, mStreamId(AAudio_getNextStreamId())
{
// mThread is a pthread_t of unknown size so we need memset.
@@ -48,6 +48,10 @@
}
AudioStream::~AudioStream() {
+ // Please preserve this log because there have been several bugs related to
+ // AudioStream deletion and late callbacks.
+ ALOGD("%s(s#%u) mPlayerBase strongCount = %d",
+ __func__, getId(), mPlayerBase->getStrongCount());
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
@@ -55,8 +59,6 @@
|| getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
"~AudioStream() - still in use, state = %s",
AudioGlobal_convertStreamStateToText(getState()));
-
- mPlayerBase->clearParentReference(); // remove reference to this AudioStream
}
aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
@@ -301,18 +303,29 @@
}
aaudio_result_t AudioStream::safeRelease() {
- // This get temporarily unlocked in the release() when joining callback threads.
+ // This get temporarily unlocked in the MMAP release() when joining callback threads.
std::lock_guard<std::mutex> lock(mStreamLock);
if (collidesWithCallback()) {
ALOGE("%s cannot be called from a callback!", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}
- if (getState() == AAUDIO_STREAM_STATE_CLOSING) {
+ if (getState() == AAUDIO_STREAM_STATE_CLOSING) { // already released?
return AAUDIO_OK;
}
return release_l();
}
+aaudio_result_t AudioStream::safeReleaseClose() {
+ // This get temporarily unlocked in the MMAP release() when joining callback threads.
+ std::lock_guard<std::mutex> lock(mStreamLock);
+ if (collidesWithCallback()) {
+ ALOGE("%s cannot be called from a callback!", __func__);
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ releaseCloseFinal();
+ return AAUDIO_OK;
+}
+
void AudioStream::setState(aaudio_stream_state_t state) {
ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
// Track transition to DISCONNECTED state.
@@ -391,7 +404,9 @@
// It converts the 'C' function call to a C++ method call.
static void* AudioStream_internalThreadProc(void* threadArg) {
AudioStream *audioStream = (AudioStream *) threadArg;
- return audioStream->wrapUserThread();
+ // Use an sp<> to prevent the stream from being deleted while running.
+ android::sp<AudioStream> protectedStream(audioStream);
+ return protectedStream->wrapUserThread();
}
// This is not exposed in the API.
@@ -520,11 +535,18 @@
}
#if AAUDIO_USE_VOLUME_SHAPER
-android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
- const android::media::VolumeShaper::Configuration& configuration __unused,
- const android::media::VolumeShaper::Operation& operation __unused) {
- ALOGW("applyVolumeShaper() is not supported");
- return android::media::VolumeShaper::Status::ok();
+::android::binder::Status AudioStream::MyPlayerBase::applyVolumeShaper(
+ const ::android::media::VolumeShaper::Configuration& configuration,
+ const ::android::media::VolumeShaper::Operation& operation) {
+ android::sp<AudioStream> audioStream;
+ {
+ std::lock_guard<std::mutex> lock(mParentLock);
+ audioStream = mParent.promote();
+ }
+ if (audioStream) {
+ return audioStream->applyVolumeShaper(configuration, operation);
+ }
+ return android::NO_ERROR;
}
#endif
@@ -534,26 +556,36 @@
doSetVolume(); // apply this change
}
-AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
-}
-
-AudioStream::MyPlayerBase::~MyPlayerBase() {
-}
-
-void AudioStream::MyPlayerBase::registerWithAudioManager() {
+void AudioStream::MyPlayerBase::registerWithAudioManager(const android::sp<AudioStream>& parent) {
+ std::lock_guard<std::mutex> lock(mParentLock);
+ mParent = parent;
if (!mRegistered) {
- init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(mParent->getUsage()));
+ init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(parent->getUsage()));
mRegistered = true;
}
}
void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
+ std::lock_guard<std::mutex> lock(mParentLock);
if (mRegistered) {
baseDestroy();
mRegistered = false;
}
}
+android::status_t AudioStream::MyPlayerBase::playerSetVolume() {
+ android::sp<AudioStream> audioStream;
+ {
+ std::lock_guard<std::mutex> lock(mParentLock);
+ audioStream = mParent.promote();
+ }
+ if (audioStream) {
+ // No pan and only left volume is taken into account from IPLayer interface
+ audioStream->setDuckAndMuteVolume(mVolumeMultiplierL /* * mPanMultiplierL */);
+ }
+ return android::NO_ERROR;
+}
+
void AudioStream::MyPlayerBase::destroy() {
unregisterWithAudioManager();
}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index fb71c36..e0bd9d8 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -25,8 +25,10 @@
#include <binder/Status.h>
#include <utils/StrongPointer.h>
-#include "media/VolumeShaper.h"
-#include "media/PlayerBase.h"
+#include <media/AudioSystem.h>
+#include <media/PlayerBase.h>
+#include <media/VolumeShaper.h>
+
#include "utility/AAudioUtilities.h"
#include "utility/MonotonicCounter.h"
@@ -45,7 +47,8 @@
/**
* AAudio audio stream.
*/
-class AudioStream {
+// By extending AudioDeviceCallback, we also inherit from RefBase.
+class AudioStream : public android::AudioSystem::AudioDeviceCallback {
public:
AudioStream();
@@ -117,6 +120,17 @@
virtual void logOpen();
void logReleaseBufferState();
+ /* Note about naming for "release" and "close" related methods.
+ *
+ * These names are intended to match the public AAudio API.
+ * The original AAudio API had an AAudioStream_close() function that
+ * released the hardware and deleted the stream. That made it difficult
+ * because apps want to release the HW ASAP but are not in a rush to delete
+ * the stream object. So in R we added an AAudioStream_release() function
+ * that just released the hardware.
+ * The AAudioStream_close() method releases if needed and then closes.
+ */
+
/**
* Free any hardware or system resources from the open() call.
* It is safe to call release_l() multiple times.
@@ -126,22 +140,27 @@
return AAUDIO_OK;
}
- aaudio_result_t closeFinal() {
+ /**
+ * Free any resources not already freed by release_l().
+ * Assume release_l() already called.
+ */
+ virtual void close_l() {
+ // Releasing the stream will set the state to CLOSING.
+ assert(getState() == AAUDIO_STREAM_STATE_CLOSING);
+ // setState() prevents a transition from CLOSING to any state other than CLOSED.
// State is checked by destructor.
setState(AAUDIO_STREAM_STATE_CLOSED);
- return AAUDIO_OK;
}
/**
* Release then close the stream.
- * @return AAUDIO_OK or negative error.
*/
- aaudio_result_t releaseCloseFinal() {
- aaudio_result_t result = release_l(); // TODO review locking
- if (result == AAUDIO_OK) {
- result = closeFinal();
+ void releaseCloseFinal() {
+ if (getState() != AAUDIO_STREAM_STATE_CLOSING) { // not already released?
+ // Ignore result and keep closing.
+ (void) release_l();
}
- return result;
+ close_l();
}
// This is only used to identify a stream in the logs without
@@ -328,6 +347,10 @@
*/
bool collidesWithCallback() const;
+ // Implement AudioDeviceCallback
+ void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId) override {};
+
// ============== I/O ===========================
// A Stream will only implement read() or write() depending on its direction.
virtual aaudio_result_t write(const void *buffer __unused,
@@ -366,7 +389,7 @@
*/
void registerPlayerBase() {
if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
- mPlayerBase->registerWithAudioManager();
+ mPlayerBase->registerWithAudioManager(this);
}
}
@@ -395,21 +418,33 @@
*/
aaudio_result_t systemStopFromCallback();
+ /**
+ * Safely RELEASE a stream after taking mStreamLock and checking
+ * to make sure we are not being called from a callback.
+ * @return AAUDIO_OK or a negative error
+ */
aaudio_result_t safeRelease();
+ /**
+ * Safely RELEASE and CLOSE a stream after taking mStreamLock and checking
+ * to make sure we are not being called from a callback.
+ * @return AAUDIO_OK or a negative error
+ */
+ aaudio_result_t safeReleaseClose();
+
protected:
// PlayerBase allows the system to control the stream volume.
class MyPlayerBase : public android::PlayerBase {
public:
- explicit MyPlayerBase(AudioStream *parent);
+ MyPlayerBase() {};
- virtual ~MyPlayerBase();
+ virtual ~MyPlayerBase() = default;
/**
* Register for volume changes and remote control.
*/
- void registerWithAudioManager();
+ void registerWithAudioManager(const android::sp<AudioStream>& parent);
/**
* UnRegister.
@@ -421,8 +456,6 @@
*/
void destroy() override;
- void clearParentReference() { mParent = nullptr; }
-
// Just a stub. The ability to start audio through PlayerBase is being deprecated.
android::status_t playerStart() override {
return android::NO_ERROR;
@@ -438,18 +471,10 @@
return android::NO_ERROR;
}
- android::status_t playerSetVolume() override {
- // No pan and only left volume is taken into account from IPLayer interface
- mParent->setDuckAndMuteVolume(mVolumeMultiplierL /* * mPanMultiplierL */);
- return android::NO_ERROR;
- }
+ android::status_t playerSetVolume() override;
#if AAUDIO_USE_VOLUME_SHAPER
- ::android::binder::Status applyVolumeShaper(
- const ::android::media::VolumeShaper::Configuration& configuration,
- const ::android::media::VolumeShaper::Operation& operation) {
- return mParent->applyVolumeShaper(configuration, operation);
- }
+ ::android::binder::Status applyVolumeShaper();
#endif
aaudio_result_t getResult() {
@@ -457,9 +482,12 @@
}
private:
- AudioStream *mParent;
- aaudio_result_t mResult = AAUDIO_OK;
- bool mRegistered = false;
+ // Use a weak pointer so the AudioStream can be deleted.
+
+ std::mutex mParentLock;
+ android::wp<AudioStream> mParent;
+ aaudio_result_t mResult = AAUDIO_OK;
+ bool mRegistered = false;
};
/**
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 60dad84..630b289 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -63,27 +63,26 @@
static aaudio_result_t builder_createStream(aaudio_direction_t direction,
aaudio_sharing_mode_t sharingMode,
bool tryMMap,
- AudioStream **audioStreamPtr) {
- *audioStreamPtr = nullptr;
+ android::sp<AudioStream> &stream) {
aaudio_result_t result = AAUDIO_OK;
switch (direction) {
case AAUDIO_DIRECTION_INPUT:
if (tryMMap) {
- *audioStreamPtr = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(),
+ stream = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(),
false);
} else {
- *audioStreamPtr = new AudioStreamRecord();
+ stream = new AudioStreamRecord();
}
break;
case AAUDIO_DIRECTION_OUTPUT:
if (tryMMap) {
- *audioStreamPtr = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(),
+ stream = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(),
false);
} else {
- *audioStreamPtr = new AudioStreamTrack();
+ stream = new AudioStreamTrack();
}
break;
@@ -98,7 +97,7 @@
// Fall back to Legacy path if MMAP not available.
// Exact behavior is controlled by MMapPolicy.
aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
- AudioStream *audioStream = nullptr;
+
if (streamPtr == nullptr) {
ALOGE("%s() streamPtr is null", __func__);
return AAUDIO_ERROR_NULL;
@@ -171,41 +170,48 @@
setPrivacySensitive(true);
}
- result = builder_createStream(getDirection(), sharingMode, allowMMap, &audioStream);
+ android::sp<AudioStream> audioStream;
+ result = builder_createStream(getDirection(), sharingMode, allowMMap, audioStream);
if (result == AAUDIO_OK) {
// Open the stream using the parameters from the builder.
result = audioStream->open(*this);
- if (result == AAUDIO_OK) {
- *streamPtr = audioStream;
- } else {
+ if (result != AAUDIO_OK) {
bool isMMap = audioStream->isMMap();
- delete audioStream;
- audioStream = nullptr;
-
if (isMMap && allowLegacy) {
ALOGV("%s() MMAP stream did not open so try Legacy path", __func__);
// If MMAP stream failed to open then TRY using a legacy stream.
result = builder_createStream(getDirection(), sharingMode,
- false, &audioStream);
+ false, audioStream);
if (result == AAUDIO_OK) {
result = audioStream->open(*this);
- if (result == AAUDIO_OK) {
- *streamPtr = audioStream;
- } else {
- delete audioStream;
- audioStream = nullptr;
- }
}
}
}
- if (audioStream != nullptr) {
+ if (result == AAUDIO_OK) {
audioStream->logOpen();
- }
+ *streamPtr = startUsingStream(audioStream);
+ } // else audioStream will go out of scope and be deleted
}
return result;
}
+AudioStream *AudioStreamBuilder::startUsingStream(android::sp<AudioStream> &audioStream) {
+ // Increment the smart pointer so it will not get deleted when
+ // we pass it to the C caller and it goes out of scope.
+ // The C code cannot hold a smart pointer so we increment the reference
+ // count to indicate that the C app owns a reference.
+ audioStream->incStrong(nullptr);
+ return audioStream.get();
+}
+
+void AudioStreamBuilder::stopUsingStream(AudioStream *stream) {
+ // Undo the effect of startUsingStream()
+ android::sp<AudioStream> spAudioStream(stream);
+ ALOGV("%s() strongCount = %d", __func__, spAudioStream->getStrongCount());
+ spAudioStream->decStrong(nullptr);
+}
+
aaudio_result_t AudioStreamBuilder::validate() const {
// Check for values that are ridiculously out of range to prevent math overflow exploits.
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index d5fb80d..9f93341 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -108,9 +108,16 @@
virtual aaudio_result_t validate() const override;
+
void logParameters() const;
+ // Mark the stream so it can be deleted.
+ static void stopUsingStream(AudioStream *stream);
+
private:
+ // Extract a raw pointer that we can pass to a 'C' app.
+ static AudioStream *startUsingStream(android::sp<AudioStream> &spAudioStream);
+
bool mSharingModeMatchRequired = false; // must match sharing mode requested
aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index c062882..33c1bf5 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -34,8 +34,7 @@
using namespace aaudio;
AudioStreamLegacy::AudioStreamLegacy()
- : AudioStream()
- , mDeviceCallback(new StreamDeviceCallback(this)) {
+ : AudioStream() {
}
AudioStreamLegacy::~AudioStreamLegacy() {
@@ -163,7 +162,11 @@
}
void AudioStreamLegacy::forceDisconnect(bool errorCallbackEnabled) {
- if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+ // There is no need to disconnect if already in these states.
+ if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED
+ && getState() != AAUDIO_STREAM_STATE_CLOSING
+ && getState() != AAUDIO_STREAM_STATE_CLOSED
+ ) {
setState(AAUDIO_STREAM_STATE_DISCONNECTED);
if (errorCallbackEnabled) {
maybeCallErrorCallback(AAUDIO_ERROR_DISCONNECTED);
@@ -205,24 +208,30 @@
return AAudioConvert_androidToAAudioResult(status);
}
-void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
-{
+void AudioStreamLegacy::onAudioDeviceUpdate(audio_io_handle_t /* audioIo */,
+ audio_port_handle_t deviceId) {
// Device routing is a common source of errors and DISCONNECTS.
- // Please leave this log in place.
- ALOGD("%s() devId %d => %d", __func__, (int) getDeviceId(), (int)deviceId);
- if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
- getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+ // Please leave this log in place. If there is a bug then this might
+ // get called after the stream has been deleted so log before we
+ // touch the stream object.
+ ALOGD("%s(deviceId = %d)", __func__, (int)deviceId);
+ if (getDeviceId() != AAUDIO_UNSPECIFIED
+ && getDeviceId() != deviceId
+ && getState() != AAUDIO_STREAM_STATE_DISCONNECTED
+ ) {
// Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
// If we have a data callback and the stream is active, then ask the data callback
// to DISCONNECT and call the error callback.
if (isDataCallbackActive()) {
- ALOGD("onAudioDeviceUpdate() request DISCONNECT in data callback due to device change");
+ ALOGD("%s() request DISCONNECT in data callback, device %d => %d",
+ __func__, (int) getDeviceId(), (int) deviceId);
// If the stream is stopped before the data callback has a chance to handle the
// request then the requestStop() and requestPause() methods will handle it after
// the callback has stopped.
mRequestDisconnect.request();
} else {
- ALOGD("onAudioDeviceUpdate() DISCONNECT the stream now");
+ ALOGD("%s() DISCONNECT the stream now, device %d => %d",
+ __func__, (int) getDeviceId(), (int) deviceId);
forceDisconnect();
}
}
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 9c24b2b..fefe6e0 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -87,29 +87,13 @@
protected:
- class StreamDeviceCallback : public android::AudioSystem::AudioDeviceCallback
- {
- public:
-
- StreamDeviceCallback(AudioStreamLegacy *parent) : mParent(parent) {}
- virtual ~StreamDeviceCallback() {}
-
- virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo __unused,
- audio_port_handle_t deviceId) {
- if (mParent != nullptr) {
- mParent->onAudioDeviceUpdate(deviceId);
- }
- }
-
- AudioStreamLegacy *mParent;
- };
-
aaudio_result_t getBestTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds,
android::ExtendedTimestamp *extendedTimestamp);
- void onAudioDeviceUpdate(audio_port_handle_t deviceId);
+ void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId) override;
/*
* Check to see whether a callback thread has requested a disconnected.
@@ -140,7 +124,6 @@
int32_t mBlockAdapterBytesPerFrame = 0;
aaudio_wrapping_frames_t mPositionWhenStarting = 0;
int32_t mCallbackBufferSize = 0;
- const android::sp<StreamDeviceCallback> mDeviceCallback;
AtomicRequestor mRequestDisconnect;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index b0dc59e..d62951e 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -282,7 +282,7 @@
: (aaudio_session_id_t) mAudioRecord->getSessionId();
setSessionId(actualSessionId);
- mAudioRecord->addAudioDeviceCallback(mDeviceCallback);
+ mAudioRecord->addAudioDeviceCallback(this);
return AAUDIO_OK;
}
@@ -291,16 +291,24 @@
// TODO add close() or release() to AudioFlinger's AudioRecord API.
// Then call it from here
if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
- mAudioRecord->removeAudioDeviceCallback(mDeviceCallback);
+ mAudioRecord->removeAudioDeviceCallback(this);
logReleaseBufferState();
- mAudioRecord.clear();
- mFixedBlockWriter.close();
+ // Data callbacks may still be running!
return AudioStream::release_l();
} else {
return AAUDIO_OK; // already released
}
}
+void AudioStreamRecord::close_l() {
+ mAudioRecord.clear();
+ // Do not close mFixedBlockWriter because a data callback
+ // thread might still be running if someone else has a reference
+ // to mAudioRecord.
+ // It has a unique_ptr to its buffer so it will clean up by itself.
+ AudioStream::close_l();
+}
+
const void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, int32_t numFrames) {
if (mFormatConversionBufferFloat.get() != nullptr) {
LOG_ALWAYS_FATAL_IF(numFrames > mFormatConversionBufferSizeInFrames,
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index c5944c7..e4ef1c0 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -39,6 +39,7 @@
aaudio_result_t open(const AudioStreamBuilder & builder) override;
aaudio_result_t release_l() override;
+ void close_l() override;
aaudio_result_t requestStart() override;
aaudio_result_t requestStop() override;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 4869480..3831046 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -224,7 +224,7 @@
mInitialBufferCapacity = getBufferCapacity();
mInitialFramesPerBurst = getFramesPerBurst();
- mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
+ mAudioTrack->addAudioDeviceCallback(this);
// Update performance mode based on the actual stream flags.
// For example, if the sample rate is not allowed then you won't get a FAST track.
@@ -253,19 +253,26 @@
aaudio_result_t AudioStreamTrack::release_l() {
if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
- mAudioTrack->removeAudioDeviceCallback(mDeviceCallback);
+ status_t err = mAudioTrack->removeAudioDeviceCallback(this);
+ ALOGE_IF(err, "%s() removeAudioDeviceCallback returned %d", __func__, err);
logReleaseBufferState();
- // TODO Investigate why clear() causes a hang in test_various.cpp
- // if I call close() from a data callback.
- // But the same thing in AudioRecord is OK!
- // mAudioTrack.clear();
- mFixedBlockReader.close();
+ // Data callbacks may still be running!
return AudioStream::release_l();
} else {
return AAUDIO_OK; // already released
}
}
+void AudioStreamTrack::close_l() {
+ // Stop callbacks before deleting mFixedBlockReader memory.
+ mAudioTrack.clear();
+ // Do not close mFixedBlockReader because a data callback
+ // thread might still be running if someone else has a reference
+ // to mAudioRecord.
+ // It has a unique_ptr to its buffer so it will clean up by itself.
+ AudioStream::close_l();
+}
+
void AudioStreamTrack::processCallback(int event, void *info) {
switch (event) {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 93a1ff4..6334f66 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -42,6 +42,7 @@
aaudio_result_t open(const AudioStreamBuilder & builder) override;
aaudio_result_t release_l() override;
+ void close_l() override;
aaudio_result_t requestStart() override;
aaudio_result_t requestPause() override;
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 9007b10..3dfb801 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -27,7 +27,7 @@
#include "core/AudioGlobal.h"
#include <aaudio/AAudioTesting.h>
#include <math.h>
-#include <system/audio-base.h>
+#include <system/audio.h>
#include <assert.h>
#include "utility/AAudioUtilities.h"
@@ -231,7 +231,8 @@
case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
return AUDIO_FLAG_NO_MEDIA_PROJECTION;
case AAUDIO_ALLOW_CAPTURE_BY_NONE:
- return AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+ return static_cast<audio_flags_mask_t>(
+ AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE);
default:
ALOGE("%s() 0x%08X unrecognized", __func__, policy);
return AUDIO_FLAG_NONE; //
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 8935d57..ccfbea3 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libaaudio_tests_defaults",
cflags: [
diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp
index a20c799..cbf863f 100644
--- a/media/libaaudio/tests/test_various.cpp
+++ b/media/libaaudio/tests/test_various.cpp
@@ -33,6 +33,11 @@
void *audioData,
int32_t numFrames
) {
+ aaudio_direction_t direction = AAudioStream_getDirection(stream);
+ if (direction == AAUDIO_DIRECTION_INPUT) {
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+ }
+ // Check to make sure the buffer is initialized to all zeros.
int channels = AAudioStream_getChannelCount(stream);
int numSamples = channels * numFrames;
bool allZeros = true;
@@ -48,7 +53,8 @@
constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
- aaudio_sharing_mode_t sharingMode) {
+ aaudio_sharing_mode_t sharingMode,
+ aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
AAudioStreamBuilder* aaudioBuilder = nullptr;
AAudioStream* aaudioStream = nullptr;
@@ -61,6 +67,7 @@
nullptr);
AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
+ AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
// Create an AAudioStream using the Builder.
@@ -88,14 +95,28 @@
// We should NOT be able to start or change a stream after it has been released.
EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStart(aaudioStream));
EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
- EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestPause(aaudioStream));
+ // Pause is only implemented for OUTPUT.
+ if (direction == AAUDIO_DIRECTION_OUTPUT) {
+ EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
+ AAudioStream_requestPause(aaudioStream));
+ }
EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStop(aaudioStream));
EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
// Does this crash?
- EXPECT_LT(0, AAudioStream_getFramesRead(aaudioStream));
- EXPECT_LT(0, AAudioStream_getFramesWritten(aaudioStream));
+ EXPECT_GT(AAudioStream_getFramesRead(aaudioStream), 0);
+ EXPECT_GT(AAudioStream_getFramesWritten(aaudioStream), 0);
+ EXPECT_GT(AAudioStream_getFramesPerBurst(aaudioStream), 0);
+ EXPECT_GE(AAudioStream_getXRunCount(aaudioStream), 0);
+ EXPECT_GT(AAudioStream_getBufferCapacityInFrames(aaudioStream), 0);
+ EXPECT_GT(AAudioStream_getBufferSizeInFrames(aaudioStream), 0);
+
+ int64_t timestampFrames = 0;
+ int64_t timestampNanos = 0;
+ aaudio_result_t result = AAudioStream_getTimestamp(aaudioStream, CLOCK_MONOTONIC,
+ ×tampFrames, ×tampNanos);
+ EXPECT_TRUE(result == AAUDIO_ERROR_INVALID_STATE || result == AAUDIO_ERROR_UNIMPLEMENTED);
// Verify Closing State. Does this crash?
aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
@@ -107,20 +128,42 @@
EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
}
-TEST(test_various, aaudio_release_close_none) {
+TEST(test_various, aaudio_release_close_none_output) {
checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
- AAUDIO_SHARING_MODE_SHARED);
+ AAUDIO_SHARING_MODE_SHARED,
+ AAUDIO_DIRECTION_OUTPUT);
// No EXCLUSIVE streams with MODE_NONE.
}
-TEST(test_various, aaudio_release_close_low_shared) {
- checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
- AAUDIO_SHARING_MODE_SHARED);
+TEST(test_various, aaudio_release_close_none_input) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
+ AAUDIO_SHARING_MODE_SHARED,
+ AAUDIO_DIRECTION_INPUT);
+ // No EXCLUSIVE streams with MODE_NONE.
}
-TEST(test_various, aaudio_release_close_low_exclusive) {
+TEST(test_various, aaudio_release_close_low_shared_output) {
checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
- AAUDIO_SHARING_MODE_EXCLUSIVE);
+ AAUDIO_SHARING_MODE_SHARED,
+ AAUDIO_DIRECTION_OUTPUT);
+}
+
+TEST(test_various, aaudio_release_close_low_shared_input) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+ AAUDIO_SHARING_MODE_SHARED,
+ AAUDIO_DIRECTION_INPUT);
+}
+
+TEST(test_various, aaudio_release_close_low_exclusive_output) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+ AAUDIO_SHARING_MODE_EXCLUSIVE,
+ AAUDIO_DIRECTION_OUTPUT);
+}
+
+TEST(test_various, aaudio_release_close_low_exclusive_input) {
+ checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+ AAUDIO_SHARING_MODE_EXCLUSIVE,
+ AAUDIO_DIRECTION_INPUT);
}
enum FunctionToCall {
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index e8e1a09..0c11e0f 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudioclient_headers",
vendor_available: true,
@@ -48,7 +57,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libaudioclient",
aidl: {
@@ -69,6 +78,7 @@
"AudioEffect.cpp",
"AudioRecord.cpp",
+ "AudioSanitizer.cpp",
"AudioSystem.cpp",
"AudioTrack.cpp",
"AudioTrackShared.cpp",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 509e063..55b836f 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -279,7 +279,8 @@
mAttributes.source = inputSource;
if (inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION
|| inputSource == AUDIO_SOURCE_CAMCORDER) {
- mAttributes.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+ mAttributes.flags = static_cast<audio_flags_mask_t>(
+ mAttributes.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
}
} else {
// stream type shouldn't be looked at, this track has audio attributes
@@ -742,6 +743,8 @@
void *iMemPointer;
audio_track_cblk_t* cblk;
status_t status;
+ static const int32_t kMaxCreateAttempts = 3;
+ int32_t remainingAttempts = kMaxCreateAttempts;
if (audioFlinger == 0) {
ALOGE("%s(%d): Could not get audioflinger", __func__, mPortId);
@@ -803,15 +806,24 @@
input.sessionId = mSessionId;
originalSessionId = mSessionId;
- record = audioFlinger->createRecord(input,
- output,
- &status);
+ do {
+ record = audioFlinger->createRecord(input, output, &status);
+ if (status == NO_ERROR) {
+ break;
+ }
+ if (status != FAILED_TRANSACTION || --remainingAttempts <= 0) {
+ ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
+ __func__, mPortId, status);
+ goto exit;
+ }
+ // FAILED_TRANSACTION happens under very specific conditions causing a state mismatch
+ // between audio policy manager and audio flinger during the input stream open sequence
+ // and can be recovered by retrying.
+ // Leave time for race condition to clear before retrying and randomize delay
+ // to reduce the probability of concurrent retries in locked steps.
+ usleep((20 + rand() % 30) * 10000);
+ } while (1);
- if (status != NO_ERROR) {
- ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
- __func__, mPortId, status);
- goto exit;
- }
ALOG_ASSERT(record != 0);
// AudioFlinger now owns the reference to the I/O handle,
diff --git a/media/libaudioclient/AudioSanitizer.cpp b/media/libaudioclient/AudioSanitizer.cpp
new file mode 100644
index 0000000..44ca956
--- /dev/null
+++ b/media/libaudioclient/AudioSanitizer.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/AudioSanitizer.h>
+
+namespace android {
+
+ /** returns true if string overflow was prevented by zero termination */
+template <size_t size>
+bool preventStringOverflow(char (&s)[size]) {
+ if (strnlen(s, size) < size) return false;
+ s[size - 1] = '\0';
+ return true;
+}
+
+status_t safetyNetLog(status_t status, const char *bugNumber) {
+ if (status != NO_ERROR && bugNumber != nullptr) {
+ android_errorWriteLog(0x534e4554, bugNumber); // SafetyNet logging
+ }
+ return status;
+}
+
+status_t AudioSanitizer::sanitizeAudioAttributes(
+ audio_attributes_t *attr, const char *bugNumber)
+{
+ status_t status = NO_ERROR;
+ const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
+ if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
+ status = BAD_VALUE;
+ }
+ attr->tags[tagsMaxSize - 1] = '\0';
+ return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeEffectDescriptor(
+ effect_descriptor_t *desc, const char *bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (preventStringOverflow(desc->name)
+ | /* always */ preventStringOverflow(desc->implementor)) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPortConfig(
+ struct audio_port_config *config, const char *bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (config->type == AUDIO_PORT_TYPE_DEVICE &&
+ preventStringOverflow(config->ext.device.address)) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPort(
+ struct audio_port *port, const char *bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (preventStringOverflow(port->name)) {
+ status = BAD_VALUE;
+ }
+ if (sanitizeAudioPortConfig(&port->active_config) != NO_ERROR) {
+ status = BAD_VALUE;
+ }
+ if (port->type == AUDIO_PORT_TYPE_DEVICE &&
+ preventStringOverflow(port->ext.device.address)) {
+ status = BAD_VALUE;
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPatch(
+ struct audio_patch *patch, const char *bugNumber)
+{
+ status_t status = NO_ERROR;
+ if (patch->num_sources > AUDIO_PATCH_PORTS_MAX) {
+ patch->num_sources = AUDIO_PATCH_PORTS_MAX;
+ status = BAD_VALUE;
+ }
+ if (patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
+ patch->num_sinks = AUDIO_PATCH_PORTS_MAX;
+ status = BAD_VALUE;
+ }
+ for (size_t i = 0; i < patch->num_sources; i++) {
+ if (sanitizeAudioPortConfig(&patch->sources[i]) != NO_ERROR) {
+ status = BAD_VALUE;
+ }
+ }
+ for (size_t i = 0; i < patch->num_sinks; i++) {
+ if (sanitizeAudioPortConfig(&patch->sinks[i]) != NO_ERROR) {
+ status = BAD_VALUE;
+ }
+ }
+ return safetyNetLog(status, bugNumber);
+}
+
+}; // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index f621aa5..edb0889 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -47,8 +47,9 @@
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
// Required to be held while calling into gSoundTriggerCaptureStateListener.
+class CaptureStateListenerImpl;
Mutex gSoundTriggerCaptureStateListenerLock;
-sp<AudioSystem::CaptureStateListener> gSoundTriggerCaptureStateListener = nullptr;
+sp<CaptureStateListenerImpl> gSoundTriggerCaptureStateListener = nullptr;
// establish binder interface to AudioFlinger service
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
@@ -1362,7 +1363,7 @@
return aps->registerPolicyMixes(mixes, registration);
}
-status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -1376,7 +1377,7 @@
}
status_t AudioSystem::setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices)
+ const AudioDeviceTypeAddrVector& devices)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -1603,74 +1604,141 @@
return aps->isCallScreenModeSupported();
}
-status_t AudioSystem::setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device)
+status_t AudioSystem::setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
- return aps->setPreferredDeviceForStrategy(strategy, device);
+ return aps->setDevicesRoleForStrategy(strategy, role, devices);
}
-status_t AudioSystem::removePreferredDeviceForStrategy(product_strategy_t strategy)
+status_t AudioSystem::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
- return aps->removePreferredDeviceForStrategy(strategy);
+ return aps->removeDevicesRoleForStrategy(strategy, role);
}
-status_t AudioSystem::getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device)
+status_t AudioSystem::getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
- return aps->getPreferredDeviceForStrategy(strategy, device);
+ return aps->getDevicesForRoleAndStrategy(strategy, role, devices);
+}
+
+status_t AudioSystem::setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+ return aps->setDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t AudioSystem::addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+ return aps->addDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t AudioSystem::removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector& devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+ return aps->removeDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t AudioSystem::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+ return aps->clearDevicesRoleForCapturePreset(audioSource, role);
+}
+
+status_t AudioSystem::getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+ return aps->getDevicesForRoleAndCapturePreset(audioSource, role, devices);
}
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
public:
+ CaptureStateListenerImpl(
+ const sp<IAudioPolicyService>& aps,
+ const sp<AudioSystem::CaptureStateListener>& listener)
+ : mAps(aps), mListener(listener) {}
+
+ void init() {
+ bool active;
+ status_t status = mAps->registerSoundTriggerCaptureStateListener(this, &active);
+ if (status != NO_ERROR) {
+ mListener->onServiceDied();
+ return;
+ }
+ mListener->onStateChanged(active);
+ IInterface::asBinder(mAps)->linkToDeath(this);
+ }
+
binder::Status setCaptureState(bool active) override {
Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
- gSoundTriggerCaptureStateListener->onStateChanged(active);
+ mListener->onStateChanged(active);
return binder::Status::ok();
}
void binderDied(const wp<IBinder>&) override {
Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
- gSoundTriggerCaptureStateListener->onServiceDied();
+ mListener->onServiceDied();
gSoundTriggerCaptureStateListener = nullptr;
}
+
+private:
+ // Need this in order to keep the death receipent alive.
+ sp<IAudioPolicyService> mAps;
+ sp<AudioSystem::CaptureStateListener> mListener;
};
status_t AudioSystem::registerSoundTriggerCaptureStateListener(
const sp<CaptureStateListener>& listener) {
+ LOG_ALWAYS_FATAL_IF(listener == nullptr);
+
const sp<IAudioPolicyService>& aps =
AudioSystem::get_audio_policy_service();
if (aps == 0) {
return PERMISSION_DENIED;
}
- sp<CaptureStateListenerImpl> wrapper = new CaptureStateListenerImpl();
-
Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
+ gSoundTriggerCaptureStateListener = new CaptureStateListenerImpl(aps, listener);
+ gSoundTriggerCaptureStateListener->init();
- bool active;
- status_t status =
- aps->registerSoundTriggerCaptureStateListener(wrapper, &active);
- if (status != NO_ERROR) {
- listener->onServiceDied();
- return NO_ERROR;
- }
- gSoundTriggerCaptureStateListener = listener;
- listener->onStateChanged(active);
- sp<IBinder> binder = IInterface::asBinder(aps);
- binder->linkToDeath(wrapper);
return NO_ERROR;
}
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 807aa13..e37cc12 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -210,7 +210,11 @@
return NO_ERROR;
}
-AudioTrack::AudioTrack()
+AudioTrack::AudioTrack() : AudioTrack("" /*opPackageName*/)
+{
+}
+
+AudioTrack::AudioTrack(const std::string& opPackageName)
: mStatus(NO_INIT),
mState(STATE_STOPPED),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -218,11 +222,12 @@
mPausedPosition(0),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mOpPackageName(opPackageName),
mAudioTrackCallback(new AudioTrackCallback())
{
mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
mAttributes.usage = AUDIO_USAGE_UNKNOWN;
- mAttributes.flags = 0x0;
+ mAttributes.flags = AUDIO_FLAG_NONE;
strcpy(mAttributes.tags, "");
}
@@ -244,12 +249,14 @@
const audio_attributes_t* pAttributes,
bool doNotReconnect,
float maxRequiredSpeed,
- audio_port_handle_t selectedDeviceId)
+ audio_port_handle_t selectedDeviceId,
+ const std::string& opPackageName)
: mStatus(NO_INIT),
mState(STATE_STOPPED),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
+ mOpPackageName(opPackageName),
mAudioTrackCallback(new AudioTrackCallback())
{
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -277,13 +284,15 @@
pid_t pid,
const audio_attributes_t* pAttributes,
bool doNotReconnect,
- float maxRequiredSpeed)
+ float maxRequiredSpeed,
+ const std::string& opPackageName)
: mStatus(NO_INIT),
mState(STATE_STOPPED),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mOpPackageName(opPackageName),
mAudioTrackCallback(new AudioTrackCallback())
{
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -458,7 +467,7 @@
if (format == AUDIO_FORMAT_DEFAULT) {
format = AUDIO_FORMAT_PCM_16_BIT;
} else if (format == AUDIO_FORMAT_IEC61937) { // HDMI pass-through?
- mAttributes.flags |= AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+ flags = static_cast<audio_output_flags_t>(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO);
}
// validate parameters
@@ -635,6 +644,36 @@
return status;
}
+
+status_t AudioTrack::set(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ size_t frameCount,
+ audio_output_flags_t flags,
+ callback_t cbf,
+ void* user,
+ int32_t notificationFrames,
+ const sp<IMemory>& sharedBuffer,
+ bool threadCanCallJava,
+ audio_session_t sessionId,
+ transfer_type transferType,
+ const audio_offload_info_t *offloadInfo,
+ uid_t uid,
+ pid_t pid,
+ const audio_attributes_t* pAttributes,
+ bool doNotReconnect,
+ float maxRequiredSpeed,
+ audio_port_handle_t selectedDeviceId)
+{
+ return set(streamType, sampleRate, format,
+ static_cast<audio_channel_mask_t>(channelMask),
+ frameCount, flags, cbf, user, notificationFrames, sharedBuffer,
+ threadCanCallJava, sessionId, transferType, offloadInfo, uid, pid,
+ pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+}
+
// -------------------------------------------------------------------------
status_t AudioTrack::start()
@@ -1036,6 +1075,40 @@
return mOriginalSampleRate;
}
+status_t AudioTrack::setDualMonoMode(audio_dual_mono_mode_t mode)
+{
+ AutoMutex lock(mLock);
+ return setDualMonoMode_l(mode);
+}
+
+status_t AudioTrack::setDualMonoMode_l(audio_dual_mono_mode_t mode)
+{
+ return mAudioTrack->setDualMonoMode(mode);
+}
+
+status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
+{
+ AutoMutex lock(mLock);
+ return mAudioTrack->getDualMonoMode(mode);
+}
+
+status_t AudioTrack::setAudioDescriptionMixLevel(float leveldB)
+{
+ AutoMutex lock(mLock);
+ return setAudioDescriptionMixLevel_l(leveldB);
+}
+
+status_t AudioTrack::setAudioDescriptionMixLevel_l(float leveldB)
+{
+ return mAudioTrack->setAudioDescriptionMixLevel(leveldB);
+}
+
+status_t AudioTrack::getAudioDescriptionMixLevel(float* leveldB) const
+{
+ AutoMutex lock(mLock);
+ return mAudioTrack->getAudioDescriptionMixLevel(leveldB);
+}
+
status_t AudioTrack::setPlaybackRate(const AudioPlaybackRate &playbackRate)
{
AutoMutex lock(mLock);
@@ -1043,7 +1116,11 @@
return NO_ERROR;
}
if (isOffloadedOrDirect_l()) {
- return INVALID_OPERATION;
+ status_t status = mAudioTrack->setPlaybackRateParameters(playbackRate);
+ if (status == NO_ERROR) {
+ mPlaybackRate = playbackRate;
+ }
+ return status;
}
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
return INVALID_OPERATION;
@@ -1108,9 +1185,16 @@
return NO_ERROR;
}
-const AudioPlaybackRate& AudioTrack::getPlaybackRate() const
+const AudioPlaybackRate& AudioTrack::getPlaybackRate()
{
AutoMutex lock(mLock);
+ if (isOffloadedOrDirect_l()) {
+ audio_playback_rate_t playbackRateTemp;
+ const status_t status = mAudioTrack->getPlaybackRateParameters(&playbackRateTemp);
+ if (status == NO_ERROR) { // update local version if changed.
+ mPlaybackRate = playbackRateTemp;
+ }
+ }
return mPlaybackRate;
}
@@ -1165,6 +1249,46 @@
return finalBufferSize;
}
+ssize_t AudioTrack::getStartThresholdInFrames() const
+{
+ AutoMutex lock(mLock);
+ if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) {
+ return NO_INIT;
+ }
+ return (ssize_t) mProxy->getStartThresholdInFrames();
+}
+
+ssize_t AudioTrack::setStartThresholdInFrames(size_t startThresholdInFrames)
+{
+ if (startThresholdInFrames > INT32_MAX || startThresholdInFrames == 0) {
+ // contractually we could simply return the current threshold in frames
+ // to indicate the request was ignored, but we return an error here.
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ // We do not permit calling setStartThresholdInFrames() between the AudioTrack
+ // default ctor AudioTrack() and set(...) but rather fail such an attempt.
+ // (To do so would require a cached mOrigStartThresholdInFrames and we may
+ // not have proper validation for the actual set value).
+ if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) {
+ return NO_INIT;
+ }
+ const uint32_t original = mProxy->getStartThresholdInFrames();
+ const uint32_t final = mProxy->setStartThresholdInFrames(startThresholdInFrames);
+ if (original != final) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETSTARTTHRESHOLD)
+ .set(AMEDIAMETRICS_PROP_STARTTHRESHOLDFRAMES, (int32_t)final)
+ .record();
+ if (original > final) {
+ // restart track if it was disabled by audioflinger due to previous underrun
+ // and we reduced the number of frames for the threshold.
+ restartIfDisabled();
+ }
+ }
+ return final;
+}
+
status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
{
if (mSharedBuffer == 0 || isOffloadedOrDirect()) {
@@ -1555,6 +1679,7 @@
input.selectedDeviceId = mSelectedDeviceId;
input.sessionId = mSessionId;
input.audioTrackCallback = mAudioTrackCallback;
+ input.opPackageName = mOpPackageName;
IAudioFlinger::CreateTrackOutput output;
@@ -1705,6 +1830,13 @@
mProxy->setPlaybackRate(playbackRateTemp);
mProxy->setMinimum(mNotificationFramesAct);
+ if (mDualMonoMode != AUDIO_DUAL_MONO_MODE_OFF) {
+ setDualMonoMode_l(mDualMonoMode);
+ }
+ if (mAudioDescriptionMixLeveldB != -std::numeric_limits<float>::infinity()) {
+ setAudioDescriptionMixLevel_l(mAudioDescriptionMixLeveldB);
+ }
+
mDeathNotifier = new DeathNotifier(this);
IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
@@ -2470,6 +2602,10 @@
staticPosition = mStaticProxy->getPosition().unsignedValue();
}
+ // save the old startThreshold and framecount
+ const uint32_t originalStartThresholdInFrames = mProxy->getStartThresholdInFrames();
+ const uint32_t originalFrameCount = mProxy->frameCount();
+
// See b/74409267. Connecting to a BT A2DP device supporting multiple codecs
// causes a lot of churn on the service side, and it can reject starting
// playback of a previously created track. May also apply to other cases.
@@ -2524,6 +2660,18 @@
return mAudioTrack->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
});
+ // restore the original start threshold if different than frameCount.
+ if (originalStartThresholdInFrames != originalFrameCount) {
+ // Note: mProxy->setStartThresholdInFrames() call is in the Proxy
+ // and does not trigger a restart.
+ // (Also CBLK_DISABLED is not set, buffers are empty after track recreation).
+ // Any start would be triggered on the mState == ACTIVE check below.
+ const uint32_t currentThreshold =
+ mProxy->setStartThresholdInFrames(originalStartThresholdInFrames);
+ ALOGD_IF(originalStartThresholdInFrames != currentThreshold,
+ "%s(%d) startThresholdInFrames changing from %u to %u",
+ __func__, mPortId, originalStartThresholdInFrames, currentThreshold);
+ }
if (mState == STATE_ACTIVE) {
result = mAudioTrack->start();
}
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index f1f8f9c..35719be 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "AudioTrackShared"
//#define LOG_NDEBUG 0
+#include <atomic>
#include <android-base/macros.h>
#include <private/media/AudioTrackShared.h>
#include <utils/Log.h>
@@ -33,6 +34,21 @@
return sizeof(T) > sizeof(size_t) && x > (T) SIZE_MAX ? SIZE_MAX : x < 0 ? 0 : (size_t) x;
}
+// compile-time safe atomics. TODO: update all methods to use it
+template <typename T>
+T android_atomic_load(const volatile T* addr) {
+ static_assert(sizeof(T) == sizeof(std::atomic<T>)); // no extra sync data required.
+ static_assert(std::atomic<T>::is_always_lock_free); // no hash lock somewhere.
+ return atomic_load((std::atomic<T>*)addr); // memory_order_seq_cst
+}
+
+template <typename T>
+void android_atomic_store(const volatile T* addr, T value) {
+ static_assert(sizeof(T) == sizeof(std::atomic<T>)); // no extra sync data required.
+ static_assert(std::atomic<T>::is_always_lock_free); // no hash lock somewhere.
+ atomic_store((std::atomic<T>*)addr, value); // memory_order_seq_cst
+}
+
// incrementSequence is used to determine the next sequence value
// for the loop and position sequence counters. It should return
// a value between "other" + 1 and "other" + INT32_MAX, the choice of
@@ -51,6 +67,7 @@
: mServer(0), mFutex(0), mMinimum(0)
, mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0)
, mBufferSizeInFrames(0)
+ , mStartThresholdInFrames(0) // filled in by the server.
, mFlags(0)
{
memset(&u, 0, sizeof(u));
@@ -66,6 +83,26 @@
{
}
+uint32_t Proxy::getStartThresholdInFrames() const
+{
+ const uint32_t startThresholdInFrames =
+ android_atomic_load(&mCblk->mStartThresholdInFrames);
+ if (startThresholdInFrames == 0 || startThresholdInFrames > mFrameCount) {
+ ALOGD("%s: startThresholdInFrames %u not between 1 and frameCount %zu, "
+ "setting to frameCount",
+ __func__, startThresholdInFrames, mFrameCount);
+ return mFrameCount;
+ }
+ return startThresholdInFrames;
+}
+
+uint32_t Proxy::setStartThresholdInFrames(uint32_t startThresholdInFrames)
+{
+ const uint32_t actual = std::min((size_t)startThresholdInFrames, frameCount());
+ android_atomic_store(&mCblk->mStartThresholdInFrames, actual);
+ return actual;
+}
+
// ---------------------------------------------------------------------------
ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
@@ -663,6 +700,7 @@
, mTimestampMutator(&cblk->mExtendedTimestampQueue)
{
cblk->mBufferSizeInFrames = frameCount;
+ cblk->mStartThresholdInFrames = frameCount;
}
__attribute__((no_sanitize("integer")))
@@ -900,11 +938,8 @@
}
audio_track_cblk_t* cblk = mCblk;
- int32_t flush = cblk->u.mStreaming.mFlush;
- if (flush != mFlush) {
- // FIXME should return an accurate value, but over-estimate is better than under-estimate
- return mFrameCount;
- }
+ flushBufferIfNeeded();
+
const int32_t rear = getRear();
ssize_t filled = audio_utils::safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
// pipe should not already be overfull
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 6d79aba..08f307d 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,6 +24,7 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
+#include <media/AudioSanitizer.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/TimeCheck.h>
#include "IAudioFlinger.h"
@@ -1210,7 +1211,7 @@
CHECK_INTERFACE(IAudioFlinger, data, reply);
uint32_t sampleRate = data.readInt32();
audio_format_t format = (audio_format_t) data.readInt32();
- audio_channel_mask_t channelMask = data.readInt32();
+ audio_channel_mask_t channelMask = (audio_channel_mask_t) data.readInt32();
reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) );
return NO_ERROR;
} break;
@@ -1483,10 +1484,15 @@
case GET_AUDIO_PORT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
struct audio_port port = {};
- if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+ status_t status = data.read(&port, sizeof(struct audio_port));
+ if (status != NO_ERROR) {
ALOGE("b/23905951");
+ return status;
}
- status_t status = getAudioPort(&port);
+ status = AudioSanitizer::sanitizeAudioPort(&port);
+ if (status == NO_ERROR) {
+ status = getAudioPort(&port);
+ }
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&port, sizeof(struct audio_port));
@@ -1496,12 +1502,20 @@
case CREATE_AUDIO_PATCH: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
struct audio_patch patch;
- data.read(&patch, sizeof(struct audio_patch));
- audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
- if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
- ALOGE("b/23905951");
+ status_t status = data.read(&patch, sizeof(struct audio_patch));
+ if (status != NO_ERROR) {
+ return status;
}
- status_t status = createAudioPatch(&patch, &handle);
+ audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+ status = data.read(&handle, sizeof(audio_patch_handle_t));
+ if (status != NO_ERROR) {
+ ALOGE("b/23905951");
+ return status;
+ }
+ status = AudioSanitizer::sanitizeAudioPatch(&patch);
+ if (status == NO_ERROR) {
+ status = createAudioPatch(&patch, &handle);
+ }
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&handle, sizeof(audio_patch_handle_t));
@@ -1546,8 +1560,14 @@
case SET_AUDIO_PORT_CONFIG: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
struct audio_port_config config;
- data.read(&config, sizeof(struct audio_port_config));
- status_t status = setAudioPortConfig(&config);
+ status_t status = data.read(&config, sizeof(struct audio_port_config));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = AudioSanitizer::sanitizeAudioPortConfig(&config);
+ if (status == NO_ERROR) {
+ status = setAudioPortConfig(&config);
+ }
reply->writeInt32(status);
return NO_ERROR;
} break;
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 60af84b..81f9dff 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -26,6 +26,7 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <media/AudioEffect.h>
+#include <media/AudioSanitizer.h>
#include <media/IAudioPolicyService.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/TimeCheck.h>
@@ -112,13 +113,18 @@
MOVE_EFFECTS_TO_IO,
SET_RTT_ENABLED,
IS_CALL_SCREEN_MODE_SUPPORTED,
- SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
- REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
- GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+ SET_DEVICES_ROLE_FOR_PRODUCT_STRATEGY,
+ REMOVE_DEVICES_ROLE_FOR_PRODUCT_STRATEGY,
+ GET_DEVICES_FOR_ROLE_AND_PRODUCT_STRATEGY,
GET_DEVICES_FOR_ATTRIBUTES,
AUDIO_MODULES_UPDATED, // oneway
SET_CURRENT_IME_UID,
REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER,
+ SET_DEVICES_ROLE_FOR_CAPTURE_PRESET,
+ ADD_DEVICES_ROLE_FOR_CAPTURE_PRESET,
+ REMOVE_DEVICES_ROLE_FOR_CAPTURE_PRESET,
+ CLEAR_DEVICES_ROLE_FOR_CAPTURE_PRESET,
+ GET_DEVICES_FOR_ROLE_AND_CAPTURE_PRESET,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -1173,31 +1179,18 @@
return reply.readBool();
}
- virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ virtual status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32((int32_t) uid);
- size_t size = devices.size();
- size_t sizePosition = data.dataPosition();
- data.writeInt32((int32_t) size);
- size_t finalSize = size;
- for (size_t i = 0; i < size; i++) {
- size_t position = data.dataPosition();
- if (devices[i].writeToParcel(&data) != NO_ERROR) {
- data.setDataPosition(position);
- finalSize--;
- }
- }
- if (size != finalSize) {
- size_t position = data.dataPosition();
- data.setDataPosition(sizePosition);
- data.writeInt32(finalSize);
- data.setDataPosition(position);
+ status_t status = data.writeParcelableVector(devices);
+ if (status != NO_ERROR) {
+ return status;
}
- status_t status = remote()->transact(SET_UID_DEVICE_AFFINITY, data, &reply);
+ status = remote()->transact(SET_UID_DEVICE_AFFINITY, data, &reply);
if (status == NO_ERROR) {
status = (status_t)reply.readInt32();
}
@@ -1218,51 +1211,37 @@
return status;
}
- virtual status_t setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ virtual status_t setUserIdDeviceAffinities(int userId, const AudioDeviceTypeAddrVector& devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
- data.writeInt32((int32_t) userId);
- size_t size = devices.size();
- size_t sizePosition = data.dataPosition();
- data.writeInt32((int32_t) size);
- size_t finalSize = size;
- for (size_t i = 0; i < size; i++) {
- size_t position = data.dataPosition();
- if (devices[i].writeToParcel(&data) != NO_ERROR) {
- data.setDataPosition(position);
- finalSize--;
- }
- }
- if (size != finalSize) {
- size_t position = data.dataPosition();
- data.setDataPosition(sizePosition);
- data.writeInt32(finalSize);
- data.setDataPosition(position);
- }
-
- status_t status = remote()->transact(SET_USERID_DEVICE_AFFINITY, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
+ data.writeInt32((int32_t) userId);
+ status_t status = data.writeParcelableVector(devices);
+ if (status != NO_ERROR) {
return status;
}
- virtual status_t removeUserIdDeviceAffinities(int userId) {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
-
- data.writeInt32((int32_t) userId);
-
- status_t status =
- remote()->transact(REMOVE_USERID_DEVICE_AFFINITY, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t) reply.readInt32();
- }
- return status;
+ status = remote()->transact(SET_USERID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
}
+ return status;
+ }
+
+ virtual status_t removeUserIdDeviceAffinities(int userId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) userId);
+
+ status_t status =
+ remote()->transact(REMOVE_USERID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t) reply.readInt32();
+ }
+ return status;
+ }
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies)
{
@@ -1384,17 +1363,31 @@
return reply.readBool();
}
- virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device)
+ virtual status_t setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role, const AudioDeviceTypeAddrVector &devices)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeUint32(static_cast<uint32_t>(strategy));
- status_t status = device.writeToParcel(&data);
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = data.writeParcelableVector(devices);
if (status != NO_ERROR) {
return BAD_VALUE;
}
- status = remote()->transact(SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+ status = remote()->transact(SET_DEVICES_ROLE_FOR_PRODUCT_STRATEGY, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
+ virtual status_t removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeUint32(static_cast<uint32_t>(strategy));
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = remote()->transact(REMOVE_DEVICES_ROLE_FOR_PRODUCT_STRATEGY,
data, &reply);
if (status != NO_ERROR) {
return status;
@@ -1402,31 +1395,108 @@
return static_cast<status_t>(reply.readInt32());
}
- virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy)
+ virtual status_t getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role, AudioDeviceTypeAddrVector &devices)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeUint32(static_cast<uint32_t>(strategy));
- status_t status = remote()->transact(REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
- data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return static_cast<status_t>(reply.readInt32());
- }
-
- virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
- data.writeUint32(static_cast<uint32_t>(strategy));
- status_t status = remote()->transact(GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = remote()->transact(GET_DEVICES_FOR_ROLE_AND_PRODUCT_STRATEGY,
data, &reply);
if (status != NO_ERROR) {
return status;
}
- status = device.readFromParcel(&reply);
+ status = reply.readParcelableVector(&devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
+ virtual status_t setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector &devices) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeUint32(static_cast<uint32_t>(audioSource));
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = data.writeParcelableVector(devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(SET_DEVICES_ROLE_FOR_CAPTURE_PRESET, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
+ virtual status_t addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector &devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeUint32(static_cast<uint32_t>(audioSource));
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = data.writeParcelableVector(devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(ADD_DEVICES_ROLE_FOR_CAPTURE_PRESET, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
+ virtual status_t removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector& devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeUint32(static_cast<uint32_t>(audioSource));
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = data.writeParcelableVector(devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(REMOVE_DEVICES_ROLE_FOR_CAPTURE_PRESET,
+ data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
+ virtual status_t clearDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeUint32(static_cast<uint32_t>(audioSource));
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = remote()->transact(CLEAR_DEVICES_ROLE_FOR_CAPTURE_PRESET,
+ data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
+ virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role, AudioDeviceTypeAddrVector &devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeUint32(static_cast<uint32_t>(audioSource));
+ data.writeUint32(static_cast<uint32_t>(role));
+ status_t status = remote()->transact(GET_DEVICES_FOR_ROLE_AND_CAPTURE_PRESET,
+ data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readParcelableVector(&devices);
if (status != NO_ERROR) {
return status;
}
@@ -1561,15 +1631,20 @@
case RELEASE_SOUNDTRIGGER_SESSION:
case SET_RTT_ENABLED:
case IS_CALL_SCREEN_MODE_SUPPORTED:
- case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
+ case SET_DEVICES_ROLE_FOR_PRODUCT_STRATEGY:
case SET_SUPPORTED_SYSTEM_USAGES:
- case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
- case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
+ case REMOVE_DEVICES_ROLE_FOR_PRODUCT_STRATEGY:
+ case GET_DEVICES_FOR_ROLE_AND_PRODUCT_STRATEGY:
case GET_DEVICES_FOR_ATTRIBUTES:
case SET_ALLOWED_CAPTURE_POLICY:
case AUDIO_MODULES_UPDATED:
case SET_CURRENT_IME_UID:
- case REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER: {
+ case REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER:
+ case SET_DEVICES_ROLE_FOR_CAPTURE_PRESET:
+ case ADD_DEVICES_ROLE_FOR_CAPTURE_PRESET:
+ case REMOVE_DEVICES_ROLE_FOR_CAPTURE_PRESET:
+ case CLEAR_DEVICES_ROLE_FOR_CAPTURE_PRESET:
+ case GET_DEVICES_FOR_ROLE_AND_CAPTURE_PRESET: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1685,7 +1760,6 @@
if (status != NO_ERROR) {
return status;
}
- sanetizeAudioAttributes(&attr);
audio_session_t session = (audio_session_t)data.readInt32();
audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
bool hasStream = data.readInt32() != 0;
@@ -1703,10 +1777,14 @@
audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
audio_io_handle_t output = 0;
std::vector<audio_io_handle_t> secondaryOutputs;
- status = getOutputForAttr(&attr,
- &output, session, &stream, pid, uid,
- &config,
- flags, &selectedDeviceId, &portId, &secondaryOutputs);
+
+ status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
+ if (status == NO_ERROR) {
+ status = getOutputForAttr(&attr,
+ &output, session, &stream, pid, uid,
+ &config,
+ flags, &selectedDeviceId, &portId, &secondaryOutputs);
+ }
reply->writeInt32(status);
status = reply->write(&attr, sizeof(audio_attributes_t));
if (status != NO_ERROR) {
@@ -1745,8 +1823,11 @@
case GET_INPUT_FOR_ATTR: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_attributes_t attr = {};
- data.read(&attr, sizeof(audio_attributes_t));
- sanetizeAudioAttributes(&attr);
+ status_t status = data.read(&attr, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+
audio_io_handle_t input = (audio_io_handle_t)data.readInt32();
audio_unique_id_t riid = (audio_unique_id_t)data.readInt32();
audio_session_t session = (audio_session_t)data.readInt32();
@@ -1759,9 +1840,13 @@
audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
audio_port_handle_t selectedDeviceId = (audio_port_handle_t) data.readInt32();
audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
- status_t status = getInputForAttr(&attr, &input, riid, session, pid, uid,
- opPackageName, &config,
- flags, &selectedDeviceId, &portId);
+
+ status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
+ if (status == NO_ERROR) {
+ status = getInputForAttr(&attr, &input, riid, session, pid, uid,
+ opPackageName, &config,
+ flags, &selectedDeviceId, &portId);
+ }
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->writeInt32(input);
@@ -1842,11 +1927,15 @@
if (status != NO_ERROR) {
return status;
}
+
int index = data.readInt32();
audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
- reply->writeInt32(static_cast <uint32_t>(setVolumeIndexForAttributes(attributes,
- index, device)));
+ status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+ if (status == NO_ERROR) {
+ status = setVolumeIndexForAttributes(attributes, index, device);
+ }
+ reply->writeInt32(static_cast <int32_t>(status));
return NO_ERROR;
} break;
@@ -1860,8 +1949,11 @@
audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
int index = 0;
- status = getVolumeIndexForAttributes(attributes, index, device);
- reply->writeInt32(static_cast <uint32_t>(status));
+ status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+ if (status == NO_ERROR) {
+ status = getVolumeIndexForAttributes(attributes, index, device);
+ }
+ reply->writeInt32(static_cast <int32_t>(status));
if (status == NO_ERROR) {
reply->writeInt32(index);
}
@@ -1877,8 +1969,11 @@
}
int index = 0;
- status = getMinVolumeIndexForAttributes(attributes, index);
- reply->writeInt32(static_cast <uint32_t>(status));
+ status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+ if (status == NO_ERROR) {
+ status = getMinVolumeIndexForAttributes(attributes, index);
+ }
+ reply->writeInt32(static_cast <int32_t>(status));
if (status == NO_ERROR) {
reply->writeInt32(index);
}
@@ -1894,8 +1989,11 @@
}
int index = 0;
- status = getMaxVolumeIndexForAttributes(attributes, index);
- reply->writeInt32(static_cast <uint32_t>(status));
+ status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+ if (status == NO_ERROR) {
+ status = getMaxVolumeIndexForAttributes(attributes, index);
+ }
+ reply->writeInt32(static_cast <int32_t>(status));
if (status == NO_ERROR) {
reply->writeInt32(index);
}
@@ -1913,31 +2011,37 @@
case GET_OUTPUT_FOR_EFFECT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
effect_descriptor_t desc = {};
- if (data.read(&desc, sizeof(desc)) != NO_ERROR) {
+ status_t status = data.read(&desc, sizeof(desc));
+ if (status != NO_ERROR) {
android_errorWriteLog(0x534e4554, "73126106");
+ return status;
}
- (void)sanitizeEffectDescriptor(&desc);
- audio_io_handle_t output = getOutputForEffect(&desc);
- reply->writeInt32(static_cast <int>(output));
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ status = AudioSanitizer::sanitizeEffectDescriptor(&desc, "73126106");
+ if (status == NO_ERROR) {
+ output = getOutputForEffect(&desc);
+ }
+ reply->writeInt32(static_cast <int32_t>(output));
return NO_ERROR;
} break;
case REGISTER_EFFECT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
effect_descriptor_t desc = {};
- if (data.read(&desc, sizeof(desc)) != NO_ERROR) {
+ status_t status = data.read(&desc, sizeof(desc));
+ if (status != NO_ERROR) {
android_errorWriteLog(0x534e4554, "73126106");
+ return status;
}
- (void)sanitizeEffectDescriptor(&desc);
audio_io_handle_t io = data.readInt32();
uint32_t strategy = data.readInt32();
audio_session_t session = (audio_session_t) data.readInt32();
int id = data.readInt32();
- reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
- io,
- strategy,
- session,
- id)));
+ status = AudioSanitizer::sanitizeEffectDescriptor(&desc, "73126106");
+ if (status == NO_ERROR) {
+ status = registerEffect(&desc, io, strategy, session, id);
+ }
+ reply->writeInt32(static_cast <int32_t>(status));
return NO_ERROR;
} break;
@@ -2046,7 +2150,11 @@
if (status != NO_ERROR) return status;
status = data.read(&attributes, sizeof(audio_attributes_t));
if (status != NO_ERROR) return status;
- reply->writeInt32(isDirectOutputSupported(config, attributes));
+ status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+ if (status == NO_ERROR) {
+ status = isDirectOutputSupported(config, attributes);
+ }
+ reply->writeInt32(static_cast <int32_t>(status));
return NO_ERROR;
}
@@ -2085,10 +2193,15 @@
case GET_AUDIO_PORT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
struct audio_port port = {};
- if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+ status_t status = data.read(&port, sizeof(struct audio_port));
+ if (status != NO_ERROR) {
ALOGE("b/23912202");
+ return status;
}
- status_t status = getAudioPort(&port);
+ status = AudioSanitizer::sanitizeAudioPort(&port);
+ if (status == NO_ERROR) {
+ status = getAudioPort(&port);
+ }
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&port, sizeof(struct audio_port));
@@ -2099,12 +2212,20 @@
case CREATE_AUDIO_PATCH: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
struct audio_patch patch = {};
- data.read(&patch, sizeof(struct audio_patch));
- audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
- if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
- ALOGE("b/23912202");
+ status_t status = data.read(&patch, sizeof(struct audio_patch));
+ if (status != NO_ERROR) {
+ return status;
}
- status_t status = createAudioPatch(&patch, &handle);
+ audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+ status = data.read(&handle, sizeof(audio_patch_handle_t));
+ if (status != NO_ERROR) {
+ ALOGE("b/23912202");
+ return status;
+ }
+ status = AudioSanitizer::sanitizeAudioPatch(&patch);
+ if (status == NO_ERROR) {
+ status = createAudioPatch(&patch, &handle);
+ }
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&handle, sizeof(audio_patch_handle_t));
@@ -2154,9 +2275,12 @@
case SET_AUDIO_PORT_CONFIG: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
struct audio_port_config config = {};
- data.read(&config, sizeof(struct audio_port_config));
- (void)sanitizeAudioPortConfig(&config);
- status_t status = setAudioPortConfig(&config);
+ status_t status = data.read(&config, sizeof(struct audio_port_config));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ (void)AudioSanitizer::sanitizeAudioPortConfig(&config);
+ status = setAudioPortConfig(&config);
reply->writeInt32(status);
return NO_ERROR;
}
@@ -2232,13 +2356,25 @@
case START_AUDIO_SOURCE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
struct audio_port_config source = {};
- data.read(&source, sizeof(struct audio_port_config));
- (void)sanitizeAudioPortConfig(&source);
+ status_t status = data.read(&source, sizeof(struct audio_port_config));
+ if (status != NO_ERROR) {
+ return status;
+ }
audio_attributes_t attributes = {};
- data.read(&attributes, sizeof(audio_attributes_t));
- sanetizeAudioAttributes(&attributes);
+ status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = AudioSanitizer::sanitizeAudioPortConfig(&source);
+ if (status == NO_ERROR) {
+ // OK to not always sanitize attributes as startAudioSource() is not called if
+ // the port config is invalid.
+ status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "68953950");
+ }
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
- status_t status = startAudioSource(&source, &attributes, &portId);
+ if (status == NO_ERROR) {
+ status = startAudioSource(&source, &attributes, &portId);
+ }
reply->writeInt32(status);
reply->writeInt32(portId);
return NO_ERROR;
@@ -2460,15 +2596,12 @@
case SET_UID_DEVICE_AFFINITY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
const uid_t uid = (uid_t) data.readInt32();
- Vector<AudioDeviceTypeAddr> devices;
- size_t size = (size_t)data.readInt32();
- for (size_t i = 0; i < size; i++) {
- AudioDeviceTypeAddr device;
- if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
- devices.add(device);
- }
+ AudioDeviceTypeAddrVector devices;
+ status_t status = data.readParcelableVector(&devices);
+ if (status != NO_ERROR) {
+ return status;
}
- status_t status = setUidDeviceAffinities(uid, devices);
+ status = setUidDeviceAffinities(uid, devices);
reply->writeInt32(status);
return NO_ERROR;
}
@@ -2484,15 +2617,12 @@
case SET_USERID_DEVICE_AFFINITY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
const int userId = (int) data.readInt32();
- Vector<AudioDeviceTypeAddr> devices;
- size_t size = (size_t)data.readInt32();
- for (size_t i = 0; i < size; i++) {
- AudioDeviceTypeAddr device;
- if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
- devices.add(device);
- }
+ AudioDeviceTypeAddrVector devices;
+ status_t status = data.readParcelableVector(&devices);
+ if (status != NO_ERROR) {
+ return status;
}
- status_t status = setUserIdDeviceAffinities(userId, devices);
+ status = setUserIdDeviceAffinities(userId, devices);
reply->writeInt32(status);
return NO_ERROR;
}
@@ -2628,7 +2758,7 @@
case SET_ALLOWED_CAPTURE_POLICY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
uid_t uid = data.readInt32();
- audio_flags_mask_t flags = data.readInt32();
+ audio_flags_mask_t flags = static_cast<audio_flags_mask_t>(data.readInt32());
status_t status = setAllowedCapturePolicy(uid, flags);
reply->writeInt32(status);
return NO_ERROR;
@@ -2649,33 +2779,36 @@
return NO_ERROR;
}
- case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
+ case SET_DEVICES_ROLE_FOR_PRODUCT_STRATEGY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
product_strategy_t strategy = (product_strategy_t) data.readUint32();
- AudioDeviceTypeAddr device;
- status_t status = device.readFromParcel((Parcel*)&data);
+ device_role_t role = (device_role_t) data.readUint32();
+ AudioDeviceTypeAddrVector devices;
+ status_t status = data.readParcelableVector(&devices);
if (status != NO_ERROR) {
return status;
}
- status = setPreferredDeviceForStrategy(strategy, device);
+ status = setDevicesRoleForStrategy(strategy, role, devices);
reply->writeInt32(status);
return NO_ERROR;
}
- case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
+ case REMOVE_DEVICES_ROLE_FOR_PRODUCT_STRATEGY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
product_strategy_t strategy = (product_strategy_t) data.readUint32();
- status_t status = removePreferredDeviceForStrategy(strategy);
+ device_role_t role = (device_role_t) data.readUint32();
+ status_t status = removeDevicesRoleForStrategy(strategy, role);
reply->writeInt32(status);
return NO_ERROR;
}
- case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
+ case GET_DEVICES_FOR_ROLE_AND_PRODUCT_STRATEGY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
product_strategy_t strategy = (product_strategy_t) data.readUint32();
- AudioDeviceTypeAddr device;
- status_t status = getPreferredDeviceForStrategy(strategy, device);
- status_t marshall_status = device.writeToParcel(reply);
+ device_role_t role = (device_role_t) data.readUint32();
+ AudioDeviceTypeAddrVector devices;
+ status_t status = getDevicesForRoleAndStrategy(strategy, role, devices);
+ status_t marshall_status = reply->writeParcelableVector(devices);
if (marshall_status != NO_ERROR) {
return marshall_status;
}
@@ -2757,49 +2890,76 @@
return NO_ERROR;
} break;
+ case SET_DEVICES_ROLE_FOR_CAPTURE_PRESET: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_source_t audioSource = (audio_source_t) data.readUint32();
+ device_role_t role = (device_role_t) data.readUint32();
+ AudioDeviceTypeAddrVector devices;
+ status_t status = data.readParcelableVector(&devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = setDevicesRoleForCapturePreset(audioSource, role, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case ADD_DEVICES_ROLE_FOR_CAPTURE_PRESET: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_source_t audioSource = (audio_source_t) data.readUint32();
+ device_role_t role = (device_role_t) data.readUint32();
+ AudioDeviceTypeAddrVector devices;
+ status_t status = data.readParcelableVector(&devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = addDevicesRoleForCapturePreset(audioSource, role, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case REMOVE_DEVICES_ROLE_FOR_CAPTURE_PRESET: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_source_t audioSource = (audio_source_t) data.readUint32();
+ device_role_t role = (device_role_t) data.readUint32();
+ AudioDeviceTypeAddrVector devices;
+ status_t status = data.readParcelableVector(&devices);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = removeDevicesRoleForCapturePreset(audioSource, role, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case CLEAR_DEVICES_ROLE_FOR_CAPTURE_PRESET: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_source_t audioSource = (audio_source_t) data.readUint32();
+ device_role_t role = (device_role_t) data.readUint32();
+ status_t status = clearDevicesRoleForCapturePreset(audioSource, role);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case GET_DEVICES_FOR_ROLE_AND_CAPTURE_PRESET: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_source_t audioSource = (audio_source_t) data.readUint32();
+ device_role_t role = (device_role_t) data.readUint32();
+ AudioDeviceTypeAddrVector devices;
+ status_t status = getDevicesForRoleAndCapturePreset(audioSource, role, devices);
+ status_t marshall_status = reply->writeParcelableVector(devices);
+ if (marshall_status != NO_ERROR) {
+ return marshall_status;
+ }
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
-/** returns true if string overflow was prevented by zero termination */
-template <size_t size>
-static bool preventStringOverflow(char (&s)[size]) {
- if (strnlen(s, size) < size) return false;
- s[size - 1] = '\0';
- return true;
-}
-
-void BnAudioPolicyService::sanetizeAudioAttributes(audio_attributes_t* attr)
-{
- const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
- if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
- android_errorWriteLog(0x534e4554, "68953950"); // SafetyNet logging
- }
- attr->tags[tagsMaxSize - 1] = '\0';
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t BnAudioPolicyService::sanitizeEffectDescriptor(effect_descriptor_t* desc)
-{
- if (preventStringOverflow(desc->name)
- | /* always */ preventStringOverflow(desc->implementor)) {
- android_errorWriteLog(0x534e4554, "73126106"); // SafetyNet logging
- return BAD_VALUE;
- }
- return NO_ERROR;
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t BnAudioPolicyService::sanitizeAudioPortConfig(struct audio_port_config* config)
-{
- if (config->type == AUDIO_PORT_TYPE_DEVICE &&
- preventStringOverflow(config->ext.device.address)) {
- return BAD_VALUE;
- }
- return NO_ERROR;
-}
-
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libaudioclient/IAudioTrack.cpp b/media/libaudioclient/IAudioTrack.cpp
index 6219e7a..6fcf300 100644
--- a/media/libaudioclient/IAudioTrack.cpp
+++ b/media/libaudioclient/IAudioTrack.cpp
@@ -44,6 +44,12 @@
SIGNAL,
APPLY_VOLUME_SHAPER,
GET_VOLUME_SHAPER_STATE,
+ SET_DUAL_MONO_MODE,
+ GET_DUAL_MONO_MODE,
+ SET_AUDIO_DESCRIPTION_MIX_LEVEL,
+ GET_AUDIO_DESCRIPTION_MIX_LEVEL,
+ SET_PLAYBACK_RATE_PARAMETERS,
+ GET_PLAYBACK_RATE_PARAMETERS,
};
class BpAudioTrack : public BpInterface<IAudioTrack>
@@ -207,6 +213,92 @@
}
return state;
}
+
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_DUAL_MONO_MODE, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ *mode = (audio_dual_mono_mode_t)reply.readInt32();
+ return NO_ERROR;
+ }
+
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32((int32_t)mode);
+ status_t status = remote()->transact(SET_DUAL_MONO_MODE, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readInt32();
+ }
+
+ status_t getAudioDescriptionMixLevel(float* leveldB) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_AUDIO_DESCRIPTION_MIX_LEVEL, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ *leveldB = reply.readFloat();
+ return NO_ERROR;
+ }
+
+ status_t setAudioDescriptionMixLevel(float leveldB) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeFloat(leveldB);
+ status_t status = remote()->transact(SET_AUDIO_DESCRIPTION_MIX_LEVEL, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readInt32();
+ }
+
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_PLAYBACK_RATE_PARAMETERS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ playbackRate->mSpeed = reply.readFloat();
+ playbackRate->mPitch = reply.readFloat();
+ playbackRate->mStretchMode =
+ static_cast<audio_timestretch_stretch_mode_t>(reply.readInt32());
+ playbackRate->mFallbackMode =
+ static_cast<audio_timestretch_fallback_mode_t>(reply.readInt32());
+ return NO_ERROR;
+ }
+
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeFloat(playbackRate.mSpeed);
+ data.writeFloat(playbackRate.mPitch);
+ data.writeInt32(playbackRate.mStretchMode);
+ data.writeInt32(playbackRate.mFallbackMode);
+ status_t status = remote()->transact(SET_PLAYBACK_RATE_PARAMETERS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
@@ -309,6 +401,59 @@
}
return NO_ERROR;
} break;
+ case SET_DUAL_MONO_MODE: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32( setDualMonoMode((audio_dual_mono_mode_t)data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case GET_DUAL_MONO_MODE: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ audio_dual_mono_mode_t mode;
+ const status_t status = getDualMonoMode(&mode);
+ reply->writeInt32((int32_t)status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(mode);
+ }
+ return NO_ERROR;
+ } break;
+ case SET_AUDIO_DESCRIPTION_MIX_LEVEL: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32( setAudioDescriptionMixLevel(data.readFloat()) );
+ return NO_ERROR;
+ } break;
+ case GET_AUDIO_DESCRIPTION_MIX_LEVEL: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ float f;
+ const status_t status = getAudioDescriptionMixLevel(&f);
+ reply->writeInt32((int32_t)status);
+ if (status == NO_ERROR) {
+ reply->writeFloat(f);
+ }
+ return NO_ERROR;
+ } break;
+ case SET_PLAYBACK_RATE_PARAMETERS: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ audio_playback_rate_t playbackRate = {
+ data.readFloat(),
+ data.readFloat(),
+ static_cast<audio_timestretch_stretch_mode_t>(data.readInt32()),
+ static_cast<audio_timestretch_fallback_mode_t>(data.readInt32())};
+ reply->writeInt32( setPlaybackRateParameters(playbackRate) );
+ return NO_ERROR;
+ } break;
+ case GET_PLAYBACK_RATE_PARAMETERS: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ audio_playback_rate_t playbackRate;
+ const status_t status = getPlaybackRateParameters(&playbackRate);
+ reply->writeInt32((int32_t)status);
+ if (status == NO_ERROR) {
+ reply->writeFloat(playbackRate.mSpeed);
+ reply->writeFloat(playbackRate.mPitch);
+ reply->writeInt32(playbackRate.mStretchMode);
+ reply->writeInt32(playbackRate.mFallbackMode);
+ }
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 050ad65..ee78a2d 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -853,6 +853,11 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_INDIA_RINGTONE
+ { .segments = { { .duration = 1000, .waveFreq = { 440, 480, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_TW_RINGTONE
};
// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -937,6 +942,16 @@
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_INDIA_CALL_WAITING, // TONE_SUP_CALL_WAITING
TONE_INDIA_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // TAIWAN
+ TONE_SUP_DIAL, // TONE_SUP_DIAL
+ TONE_SUP_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_TW_RINGTONE // TONE_SUP_RINGTONE
}
};
@@ -1010,6 +1025,8 @@
mRegion = IRELAND;
} else if (strstr(value, "in") != NULL) {
mRegion = INDIA;
+ } else if (strstr(value, "tw") != NULL) {
+ mRegion = TAIWAN;
} else {
mRegion = CEPT;
}
diff --git a/media/libaudioclient/include/media/AudioSanitizer.h b/media/libaudioclient/include/media/AudioSanitizer.h
new file mode 100644
index 0000000..1475c7b
--- /dev/null
+++ b/media/libaudioclient/include/media/AudioSanitizer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_SANITIZER_H_
+#define ANDROID_AUDIO_SANITIZER_H_
+
+#include <system/audio.h>
+#include <system/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+namespace android {
+
+class AudioSanitizer {
+public:
+ static status_t sanitizeAudioAttributes(
+ audio_attributes_t *attr, const char *bugNumber = nullptr);
+
+ static status_t sanitizeEffectDescriptor(
+ effect_descriptor_t *desc, const char *bugNumber = nullptr);
+
+ static status_t sanitizeAudioPortConfig(
+ struct audio_port_config *config, const char *bugNumber = nullptr);
+
+ static status_t sanitizeAudioPort(
+ struct audio_port *port, const char *bugNumber = nullptr);
+
+ static status_t sanitizeAudioPatch(
+ struct audio_patch *patch, const char *bugNumber = nullptr);
+};
+
+}; // namespace android
+
+#endif /*ANDROID_AUDIO_SANITIZER_H_*/
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 19c2cbd..848743a 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -361,11 +361,11 @@
static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
- static status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+ static status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices);
static status_t removeUidDeviceAffinities(uid_t uid);
- static status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+ static status_t setUserIdDeviceAffinities(int userId, const AudioDeviceTypeAddrVector& devices);
static status_t removeUserIdDeviceAffinities(int userId);
@@ -425,13 +425,29 @@
*/
static status_t setAudioHalPids(const std::vector<pid_t>& pids);
- static status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device);
+ static status_t setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role, const AudioDeviceTypeAddrVector &devices);
- static status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
+ static status_t removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role);
- static status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device);
+ static status_t getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role, AudioDeviceTypeAddrVector &devices);
+
+ static status_t setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector &devices);
+
+ static status_t addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector &devices);
+
+ static status_t removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector& devices);
+
+ static status_t clearDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role);
+
+ static status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role, AudioDeviceTypeAddrVector &devices);
static status_t getDeviceForStrategy(product_strategy_t strategy,
AudioDeviceTypeAddr &device);
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 0dbd842..4afa9c9 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -26,6 +26,8 @@
#include <media/Modulo.h>
#include <utils/threads.h>
+#include <string>
+
#include "android/media/BnAudioTrackCallback.h"
#include "android/media/IAudioTrackCallback.h"
@@ -177,6 +179,8 @@
*/
AudioTrack();
+ AudioTrack(const std::string& opPackageName);
+
/* Creates an AudioTrack object and registers it with AudioFlinger.
* Once created, the track needs to be started before it can be used.
* Unspecified values are set to appropriate default values.
@@ -258,7 +262,8 @@
const audio_attributes_t* pAttributes = NULL,
bool doNotReconnect = false,
float maxRequiredSpeed = 1.0f,
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
+ const std::string& opPackageName = "");
/* Creates an audio track and registers it with AudioFlinger.
* With this constructor, the track is configured for static buffer mode.
@@ -288,7 +293,8 @@
pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL,
bool doNotReconnect = false,
- float maxRequiredSpeed = 1.0f);
+ float maxRequiredSpeed = 1.0f,
+ const std::string& opPackageName = "");
/* Terminates the AudioTrack and unregisters it from AudioFlinger.
* Also destroys all resources associated with the AudioTrack.
@@ -338,6 +344,27 @@
bool doNotReconnect = false,
float maxRequiredSpeed = 1.0f,
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+ // FIXME(b/169889714): Vendor code depends on the old method signature at link time
+ status_t set(audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ size_t frameCount = 0,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+ callback_t cbf = NULL,
+ void* user = NULL,
+ int32_t notificationFrames = 0,
+ const sp<IMemory>& sharedBuffer = 0,
+ bool threadCanCallJava = false,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
+ transfer_type transferType = TRANSFER_DEFAULT,
+ const audio_offload_info_t *offloadInfo = NULL,
+ uid_t uid = AUDIO_UID_INVALID,
+ pid_t pid = -1,
+ const audio_attributes_t* pAttributes = NULL,
+ bool doNotReconnect = false,
+ float maxRequiredSpeed = 1.0f,
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
/* Result of constructing the AudioTrack. This must be checked for successful initialization
* before using any AudioTrack API (except for set()), because using
@@ -402,6 +429,19 @@
*/
ssize_t setBufferSizeInFrames(size_t size);
+ /* Returns the start threshold on the buffer for audio streaming
+ * or a negative value if the AudioTrack is not initialized.
+ */
+ ssize_t getStartThresholdInFrames() const;
+
+ /* Sets the start threshold in frames on the buffer for audio streaming.
+ *
+ * May be clamped internally. Returns the actual value set, or a negative
+ * value if the AudioTrack is not initialized or if the input
+ * is zero or greater than INT_MAX.
+ */
+ ssize_t setStartThresholdInFrames(size_t startThresholdInFrames);
+
/* Return the static buffer specified in constructor or set(), or 0 for streaming mode */
sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
@@ -486,6 +526,18 @@
*/
uint32_t getOriginalSampleRate() const;
+ /* Sets the Dual Mono mode presentation on the output device. */
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode);
+
+ /* Returns the Dual Mono mode presentation setting. */
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const;
+
+ /* Sets the Audio Description Mix level in dB. */
+ status_t setAudioDescriptionMixLevel(float leveldB);
+
+ /* Returns the Audio Description Mix level in dB. */
+ status_t getAudioDescriptionMixLevel(float* leveldB) const;
+
/* Set source playback rate for timestretch
* 1.0 is normal speed: < 1.0 is slower, > 1.0 is faster
* 1.0 is normal pitch: < 1.0 is lower pitch, > 1.0 is higher pitch
@@ -499,7 +551,7 @@
status_t setPlaybackRate(const AudioPlaybackRate &playbackRate);
/* Return current playback rate */
- const AudioPlaybackRate& getPlaybackRate() const;
+ const AudioPlaybackRate& getPlaybackRate();
/* Enables looping and sets the start and end points of looping.
* Only supported for static buffer mode.
@@ -1043,6 +1095,12 @@
void updateRoutedDeviceId_l();
+ /* Sets the Dual Mono mode presentation on the output device. */
+ status_t setDualMonoMode_l(audio_dual_mono_mode_t mode);
+
+ /* Sets the Audio Description Mix level in dB. */
+ status_t setAudioDescriptionMixLevel_l(float leveldB);
+
// Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
@@ -1236,6 +1294,8 @@
sp<media::VolumeHandler> mVolumeHandler;
+ const std::string mOpPackageName;
+
private:
class DeathNotifier : public IBinder::DeathRecipient {
public:
@@ -1253,6 +1313,10 @@
wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+ // Cached values to restore along with the AudioTrack.
+ audio_dual_mono_mode_t mDualMonoMode = AUDIO_DUAL_MONO_MODE_OFF;
+ float mAudioDescriptionMixLeveldB = -std::numeric_limits<float>::infinity();
+
private:
class MediaMetrics {
public:
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 612ce7a..bcc11f4 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -37,6 +37,7 @@
#include <media/IEffectClient.h>
#include <utils/String8.h>
#include <media/MicrophoneInfo.h>
+#include <string>
#include <vector>
#include "android/media/IAudioRecord.h"
@@ -85,6 +86,11 @@
speed = parcel->readFloat();
audioTrackCallback = interface_cast<media::IAudioTrackCallback>(
parcel->readStrongBinder());
+ const char* opPackageNamePtr = parcel->readCString();
+ if (opPackageNamePtr == nullptr) {
+ return FAILED_TRANSACTION;
+ }
+ opPackageName = opPackageNamePtr;
/* input/output arguments*/
(void)parcel->read(&flags, sizeof(audio_output_flags_t));
@@ -109,6 +115,7 @@
(void)parcel->writeInt32(notificationsPerBuffer);
(void)parcel->writeFloat(speed);
(void)parcel->writeStrongBinder(IInterface::asBinder(audioTrackCallback));
+ (void)parcel->writeCString(opPackageName.c_str());
/* input/output arguments*/
(void)parcel->write(&flags, sizeof(audio_output_flags_t));
@@ -127,6 +134,7 @@
uint32_t notificationsPerBuffer;
float speed;
sp<media::IAudioTrackCallback> audioTrackCallback;
+ std::string opPackageName;
/* input/output */
audio_output_flags_t flags;
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index bb1c07f..837375d 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -196,13 +196,13 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration) = 0;
- virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ virtual status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices)
= 0;
virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
virtual status_t setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices) = 0;
+ const AudioDeviceTypeAddrVector& devices) = 0;
virtual status_t removeUserIdDeviceAffinities(int userId) = 0;
@@ -241,13 +241,35 @@
virtual bool isCallScreenModeSupported() = 0;
- virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device) = 0;
+ virtual status_t setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
- virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
+ virtual status_t removeDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role) = 0;
- virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device) = 0;
+ virtual status_t getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices) = 0;
+
+ virtual status_t setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
+
+ virtual status_t addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
+
+ virtual status_t removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector& devices) = 0;
+
+ virtual status_t clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role) = 0;
+
+ virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices) = 0;
// The return code here is only intended to represent transport errors. The
// actual server implementation should always return NO_ERROR.
@@ -266,10 +288,6 @@
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
-private:
- void sanetizeAudioAttributes(audio_attributes_t* attr);
- status_t sanitizeEffectDescriptor(effect_descriptor_t* desc);
- status_t sanitizeAudioPortConfig(struct audio_port_config* config);
};
// ----------------------------------------------------------------------------
diff --git a/media/libaudioclient/include/media/IAudioTrack.h b/media/libaudioclient/include/media/IAudioTrack.h
index 06e786d..dbbbf35 100644
--- a/media/libaudioclient/include/media/IAudioTrack.h
+++ b/media/libaudioclient/include/media/IAudioTrack.h
@@ -27,6 +27,7 @@
#include <utils/String8.h>
#include <media/AudioTimestamp.h>
#include <media/VolumeShaper.h>
+#include <system/audio.h>
namespace android {
@@ -86,6 +87,24 @@
/* gets the volume shaper state */
virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) = 0;
+
+ /* Returns the Dual Mono mode presentation setting. */
+ virtual status_t getDualMonoMode(audio_dual_mono_mode_t* mode) = 0;
+
+ /* Sets the Dual Mono mode presentation on the output device. */
+ virtual status_t setDualMonoMode(audio_dual_mono_mode_t mode) = 0;
+
+ /* Returns the Audio Description Mix level in dB. */
+ virtual status_t getAudioDescriptionMixLevel(float* leveldB) = 0;
+
+ /* Sets the Audio Description Mix level in dB. */
+ virtual status_t setAudioDescriptionMixLevel(float leveldB) = 0;
+
+ /* Retrieves current playback rate parameters. */
+ virtual status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) = 0;
+
+ /* Sets the playback rate parameters that control playback behavior. */
+ virtual status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 5b0689a..04357a8 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -218,6 +218,7 @@
TONE_INDIA_CONGESTION, // Congestion tone: 400 Hz, 250ms ON, 250ms OFF...
TONE_INDIA_CALL_WAITING, // Call waiting tone: 400 Hz, tone repeated in a 0.2s on, 0.1s off, 0.2s on, 7.5s off pattern.
TONE_INDIA_RINGTONE, // Ring tone: 400 Hz tone modulated with 25Hz, 0.4 on 0.2 off 0.4 on 2..0 off
+ TONE_TW_RINGTONE, // Ring Tone: 440 Hz + 480 Hz repeated with pattern 1s on, 3s off.
NUM_ALTERNATE_TONES
};
@@ -230,6 +231,7 @@
HONGKONG,
IRELAND,
INDIA,
+ TAIWAN,
CEPT,
NUM_REGIONS
};
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 350a780..92c6ec0 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libaudioclient_tests_defaults",
cflags: [
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index a8e6c31..b2fa007 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudiofoundation_headers",
vendor_available: true,
diff --git a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
index b44043a..a47337b 100644
--- a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
+++ b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
@@ -16,12 +16,57 @@
#include <media/AudioDeviceTypeAddr.h>
+#include <arpa/inet.h>
+#include <iostream>
+#include <regex>
+#include <set>
+#include <sstream>
+
namespace android {
+namespace {
+
+static const std::string SUPPRESSED = "SUPPRESSED";
+static const std::regex MAC_ADDRESS_REGEX("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
+
+bool isSenstiveAddress(const std::string &address) {
+ if (std::regex_match(address, MAC_ADDRESS_REGEX)) {
+ return true;
+ }
+
+ sockaddr_storage ss4;
+ if (inet_pton(AF_INET, address.c_str(), &ss4) > 0) {
+ return true;
+ }
+
+ sockaddr_storage ss6;
+ if (inet_pton(AF_INET6, address.c_str(), &ss6) > 0) {
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+AudioDeviceTypeAddr::AudioDeviceTypeAddr(audio_devices_t type, const std::string &address) :
+ mType(type), mAddress(address) {
+ mIsAddressSensitive = isSenstiveAddress(mAddress);
+}
+
const char* AudioDeviceTypeAddr::getAddress() const {
return mAddress.c_str();
}
+const std::string& AudioDeviceTypeAddr::address() const {
+ return mAddress;
+}
+
+void AudioDeviceTypeAddr::setAddress(const std::string& address) {
+ mAddress = address;
+ mIsAddressSensitive = isSenstiveAddress(mAddress);
+}
+
bool AudioDeviceTypeAddr::equals(const AudioDeviceTypeAddr& other) const {
return mType == other.mType && mAddress == other.mAddress;
}
@@ -36,14 +81,34 @@
return false;
}
+bool AudioDeviceTypeAddr::operator==(const AudioDeviceTypeAddr &rhs) const {
+ return equals(rhs);
+}
+
+bool AudioDeviceTypeAddr::operator!=(const AudioDeviceTypeAddr &rhs) const {
+ return !operator==(rhs);
+}
+
void AudioDeviceTypeAddr::reset() {
mType = AUDIO_DEVICE_NONE;
- mAddress = "";
+ setAddress("");
+}
+
+std::string AudioDeviceTypeAddr::toString(bool includeSensitiveInfo) const {
+ std::stringstream sstream;
+ sstream << "type:0x" << std::hex << mType;
+ // IP and MAC address are sensitive information. The sensitive information will be suppressed
+ // is `includeSensitiveInfo` is false.
+ sstream << ",@:"
+ << (!includeSensitiveInfo && mIsAddressSensitive ? SUPPRESSED : mAddress);
+ return sstream.str();
}
status_t AudioDeviceTypeAddr::readFromParcel(const Parcel *parcel) {
status_t status;
- if ((status = parcel->readUint32(&mType)) != NO_ERROR) return status;
+ uint32_t rawDeviceType;
+ if ((status = parcel->readUint32(&rawDeviceType)) != NO_ERROR) return status;
+ mType = static_cast<audio_devices_t>(rawDeviceType);
status = parcel->readUtf8FromUtf16(&mAddress);
return status;
}
@@ -64,4 +129,30 @@
return deviceTypes;
}
-}
\ No newline at end of file
+AudioDeviceTypeAddrVector excludeDeviceTypeAddrsFrom(
+ const AudioDeviceTypeAddrVector& devices,
+ const AudioDeviceTypeAddrVector& devicesToExclude) {
+ std::set<AudioDeviceTypeAddr> devicesToExcludeSet(
+ devicesToExclude.begin(), devicesToExclude.end());
+ AudioDeviceTypeAddrVector remainedDevices;
+ for (const auto& device : devices) {
+ if (devicesToExcludeSet.count(device) == 0) {
+ remainedDevices.push_back(device);
+ }
+ }
+ return remainedDevices;
+}
+
+std::string dumpAudioDeviceTypeAddrVector(const AudioDeviceTypeAddrVector& deviceTypeAddrs,
+ bool includeSensitiveInfo) {
+ std::stringstream stream;
+ for (auto it = deviceTypeAddrs.begin(); it != deviceTypeAddrs.end(); ++it) {
+ if (it != deviceTypeAddrs.begin()) {
+ stream << " ";
+ }
+ stream << it->toString(includeSensitiveInfo);
+ }
+ return stream.str();
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 0d28335..759140e 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -152,8 +152,12 @@
if ((status = parcel->readInt32(&mIndex)) != NO_ERROR) return status;
if ((status = parcel->readBool(&mUseInChannelMask)) != NO_ERROR) return status;
if ((status = parcel->readBool(&mUseForVolume)) != NO_ERROR) return status;
- if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
- if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+ uint32_t rawGainMode;
+ if ((status = parcel->readUint32(&rawGainMode)) != NO_ERROR) return status;
+ mGain.mode = static_cast<audio_gain_mode_t>(rawGainMode);
+ uint32_t rawChannelMask;
+ if ((status = parcel->readUint32(&rawChannelMask)) != NO_ERROR) return status;
+ mGain.channel_mask = static_cast<audio_channel_mask_t>(rawChannelMask);
if ((status = parcel->readInt32(&mGain.min_value)) != NO_ERROR) return status;
if ((status = parcel->readInt32(&mGain.max_value)) != NO_ERROR) return status;
if ((status = parcel->readInt32(&mGain.default_value)) != NO_ERROR) return status;
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index f988690..1846a6b 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -268,12 +268,17 @@
if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
return status;
}
- if ((status = parcel->readUint32(&mChannelMask)) != NO_ERROR) return status;
+ uint32_t rawChannelMask;
+ if ((status = parcel->readUint32(&rawChannelMask)) != NO_ERROR) return status;
+ mChannelMask = static_cast<audio_channel_mask_t>(rawChannelMask);
if ((status = parcel->readInt32(&mId)) != NO_ERROR) return status;
// Read mGain from parcel.
if ((status = parcel->readInt32(&mGain.index)) != NO_ERROR) return status;
- if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
- if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+ uint32_t rawGainMode;
+ if ((status = parcel->readUint32(&rawGainMode)) != NO_ERROR) return status;
+ mGain.mode = static_cast<audio_gain_mode_t>(rawGainMode);
+ if ((status = parcel->readUint32(&rawChannelMask)) != NO_ERROR) return status;
+ mGain.channel_mask = static_cast<audio_channel_mask_t>(rawChannelMask);
if ((status = parcel->readUint32(&mGain.ramp_duration_ms)) != NO_ERROR) return status;
std::vector<int> values;
if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 91be346..67b600e 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -157,7 +157,9 @@
std::vector<int> values;
if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
mChannelMasks.clear();
- mChannelMasks.insert(values.begin(), values.end());
+ for (auto raw : values) {
+ mChannelMasks.insert(static_cast<audio_channel_mask_t>(raw));
+ }
values.clear();
if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
mSamplingRates.clear();
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index e9b589d..16cf71a 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -22,9 +22,6 @@
#include <media/DeviceDescriptorBase.h>
#include <media/TypeConverter.h>
-#include <arpa/inet.h>
-#include <regex>
-
namespace android {
DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type) :
@@ -37,46 +34,19 @@
{
}
-namespace {
-
-static const std::string SUPPRESSED = "SUPPRESSED";
-static const std::regex MAC_ADDRESS_REGEX("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
-
-bool isAddressSensitive(const std::string &address) {
- if (std::regex_match(address, MAC_ADDRESS_REGEX)) {
- return true;
- }
-
- sockaddr_storage ss4;
- if (inet_pton(AF_INET, address.c_str(), &ss4) > 0) {
- return true;
- }
-
- sockaddr_storage ss6;
- if (inet_pton(AF_INET6, address.c_str(), &ss6) > 0) {
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
DeviceDescriptorBase::DeviceDescriptorBase(const AudioDeviceTypeAddr &deviceTypeAddr) :
AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(deviceTypeAddr.mType) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
mDeviceTypeAddr(deviceTypeAddr)
{
- if (mDeviceTypeAddr.mAddress.empty() && audio_is_remote_submix_device(mDeviceTypeAddr.mType)) {
- mDeviceTypeAddr.mAddress = "0";
+ if (mDeviceTypeAddr.address().empty() && audio_is_remote_submix_device(mDeviceTypeAddr.mType)) {
+ mDeviceTypeAddr.setAddress("0");
}
- mIsAddressSensitive = isAddressSensitive(mDeviceTypeAddr.mAddress);
}
void DeviceDescriptorBase::setAddress(const std::string &address) {
- mDeviceTypeAddr.mAddress = address;
- mIsAddressSensitive = isAddressSensitive(address);
+ mDeviceTypeAddr.setAddress(address);
}
void DeviceDescriptorBase::toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -157,7 +127,7 @@
"%*s- supported encapsulation metadata types: %u",
spaces, "", mEncapsulationMetadataTypes));
- if (mDeviceTypeAddr.mAddress.size() != 0) {
+ if (mDeviceTypeAddr.address().size() != 0) {
dst->append(base::StringPrintf(
"%*s- address: %-32s\n", spaces, "", mDeviceTypeAddr.getAddress()));
}
@@ -166,14 +136,7 @@
std::string DeviceDescriptorBase::toString(bool includeSensitiveInfo) const
{
- std::stringstream sstream;
- sstream << "type:0x" << std::hex << type();
- // IP and MAC address are sensitive information. The sensitive information will be suppressed
- // is `includeSensitiveInfo` is false.
- sstream << ",@:"
- << (!includeSensitiveInfo && mIsAddressSensitive ? SUPPRESSED
- : mDeviceTypeAddr.mAddress);
- return sstream.str();
+ return mDeviceTypeAddr.toString(includeSensitiveInfo);
}
void DeviceDescriptorBase::log() const
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 72fda49..aa7ca69 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -96,7 +96,7 @@
static inline audio_devices_t deviceTypesToBitMask(const DeviceTypeSet& deviceTypes) {
audio_devices_t types = AUDIO_DEVICE_NONE;
for (auto deviceType : deviceTypes) {
- types |= deviceType;
+ types = static_cast<audio_devices_t>(types | deviceType);
}
return types;
}
@@ -131,4 +131,4 @@
std::string toString(const DeviceTypeSet& deviceTypes);
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
index 60ea78e..7497faf 100644
--- a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
+++ b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
@@ -27,28 +27,43 @@
namespace android {
-struct AudioDeviceTypeAddr : public Parcelable {
+class AudioDeviceTypeAddr : public Parcelable {
+public:
AudioDeviceTypeAddr() = default;
- AudioDeviceTypeAddr(audio_devices_t type, const std::string& address) :
- mType(type), mAddress(address) {}
+ AudioDeviceTypeAddr(audio_devices_t type, const std::string& address);
const char* getAddress() const;
+ const std::string& address() const;
+
+ void setAddress(const std::string& address);
+
+ bool isAddressSensitive();
+
bool equals(const AudioDeviceTypeAddr& other) const;
AudioDeviceTypeAddr& operator= (const AudioDeviceTypeAddr&) = default;
bool operator<(const AudioDeviceTypeAddr& other) const;
+ bool operator==(const AudioDeviceTypeAddr& rhs) const;
+
+ bool operator!=(const AudioDeviceTypeAddr& rhs) const;
+
void reset();
+ std::string toString(bool includeSensitiveInfo=false) const;
+
status_t readFromParcel(const Parcel *parcel) override;
status_t writeToParcel(Parcel *parcel) const override;
audio_devices_t mType = AUDIO_DEVICE_NONE;
+
+private:
std::string mAddress;
+ bool mIsAddressSensitive;
};
using AudioDeviceTypeAddrVector = std::vector<AudioDeviceTypeAddr>;
@@ -58,4 +73,15 @@
*/
DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs);
-}
+/**
+ * Return a collection of AudioDeviceTypeAddrs that are shown in `devices` but not
+ * in `devicesToExclude`
+ */
+AudioDeviceTypeAddrVector excludeDeviceTypeAddrsFrom(
+ const AudioDeviceTypeAddrVector& devices,
+ const AudioDeviceTypeAddrVector& devicesToExclude);
+
+std::string dumpAudioDeviceTypeAddrVector(const AudioDeviceTypeAddrVector& deviceTypeAddrs,
+ bool includeSensitiveInfo=false);
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index c143c7e..0cbd1de 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -41,7 +41,7 @@
virtual ~DeviceDescriptorBase() {}
audio_devices_t type() const { return mDeviceTypeAddr.mType; }
- std::string address() const { return mDeviceTypeAddr.mAddress; }
+ const std::string& address() const { return mDeviceTypeAddr.address(); }
void setAddress(const std::string &address);
const AudioDeviceTypeAddr& getDeviceTypeAddr() const { return mDeviceTypeAddr; }
@@ -77,7 +77,6 @@
protected:
AudioDeviceTypeAddr mDeviceTypeAddr;
- bool mIsAddressSensitive;
uint32_t mEncapsulationModes = 0;
uint32_t mEncapsulationMetadataTypes = 0;
};
diff --git a/media/libaudiofoundation/tests/Android.bp b/media/libaudiofoundation/tests/Android.bp
index f258b14..bb9a5f2 100644
--- a/media/libaudiofoundation/tests/Android.bp
+++ b/media/libaudiofoundation/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "audiofoundation_parcelable_test",
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index fab0fea..dbe342a 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libaudiohal",
@@ -14,11 +23,10 @@
],
required: [
- "libaudiohal@2.0",
"libaudiohal@4.0",
"libaudiohal@5.0",
"libaudiohal@6.0",
-// "libaudiohal@7.0",
+ "libaudiohal@7.0",
],
shared_libs: [
diff --git a/media/libaudiohal/FactoryHalHidl.cpp b/media/libaudiohal/FactoryHalHidl.cpp
index 7228b22..e420d07 100644
--- a/media/libaudiohal/FactoryHalHidl.cpp
+++ b/media/libaudiohal/FactoryHalHidl.cpp
@@ -35,7 +35,6 @@
"6.0",
"5.0",
"4.0",
- "2.0",
nullptr
};
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index df006b5..91a7a17 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libaudiohal_default",
@@ -53,29 +62,15 @@
}
cc_library_shared {
- name: "libaudiohal@2.0",
- defaults: ["libaudiohal_default"],
- shared_libs: [
- "android.hardware.audio.common@2.0",
- "android.hardware.audio.common@2.0-util",
- "android.hardware.audio.effect@2.0",
- "android.hardware.audio@2.0",
- ],
- cflags: [
- "-DMAJOR_VERSION=2",
- "-DMINOR_VERSION=0",
- "-include common/all-versions/VersionMacro.h",
- ]
-}
-
-cc_library_shared {
name: "libaudiohal@4.0",
defaults: ["libaudiohal_default"],
shared_libs: [
"android.hardware.audio.common@4.0",
"android.hardware.audio.common@4.0-util",
"android.hardware.audio.effect@4.0",
+ "android.hardware.audio.effect@4.0-util",
"android.hardware.audio@4.0",
+ "android.hardware.audio@4.0-util",
],
cflags: [
"-DMAJOR_VERSION=4",
@@ -91,7 +86,9 @@
"android.hardware.audio.common@5.0",
"android.hardware.audio.common@5.0-util",
"android.hardware.audio.effect@5.0",
+ "android.hardware.audio.effect@5.0-util",
"android.hardware.audio@5.0",
+ "android.hardware.audio@5.0-util",
],
cflags: [
"-DMAJOR_VERSION=5",
@@ -107,7 +104,9 @@
"android.hardware.audio.common@6.0",
"android.hardware.audio.common@6.0-util",
"android.hardware.audio.effect@6.0",
+ "android.hardware.audio.effect@6.0-util",
"android.hardware.audio@6.0",
+ "android.hardware.audio@6.0-util",
],
cflags: [
"-DMAJOR_VERSION=6",
@@ -117,14 +116,15 @@
}
cc_library_shared {
- enabled: false,
name: "libaudiohal@7.0",
defaults: ["libaudiohal_default"],
shared_libs: [
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-util",
"android.hardware.audio.effect@7.0",
+ "android.hardware.audio.effect@7.0-util",
"android.hardware.audio@7.0",
+ "android.hardware.audio@7.0-util",
],
cflags: [
"-DMAJOR_VERSION=7",
@@ -132,4 +132,3 @@
"-include common/all-versions/VersionMacro.h",
]
}
-
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.cpp b/media/libaudiohal/impl/ConversionHelperHidl.cpp
index ebed5fd..b6fee6d 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperHidl.cpp
@@ -50,12 +50,20 @@
halKeys.get(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES),
value) == NO_ERROR;
+ const bool keepDelayValue =
+ halKeys.get(String8(AUDIO_PARAMETER_DEVICE_ADDITIONAL_OUTPUT_DELAY),
+ value) == NO_ERROR ||
+ halKeys.get(String8(AUDIO_PARAMETER_DEVICE_MAX_ADDITIONAL_OUTPUT_DELAY),
+ value) == NO_ERROR;
+
for (size_t i = 0; i < halKeys.size(); ++i) {
String8 key;
status_t status = halKeys.getAt(i, key);
if (status != OK) return status;
if ((keepFormatValue && key == AudioParameter::keyFormat) ||
- (keepRoutingValue && key == AudioParameter::keyRouting)) {
+ (keepRoutingValue && key == AudioParameter::keyRouting) ||
+ (keepDelayValue && key == AUDIO_PARAMETER_DEVICE_ADDITIONAL_OUTPUT_DELAY) ||
+ (keepDelayValue && key == AUDIO_PARAMETER_DEVICE_MAX_ADDITIONAL_OUTPUT_DELAY)) {
AudioParameter keepValueParam;
halKeys.getAt(i, key, value);
keepValueParam.add(key, value);
@@ -112,129 +120,5 @@
ALOGE("%s %p %s: %s (from rpc)", mClassName, this, funcName, description);
}
-#if MAJOR_VERSION >= 4
-// TODO: Use the same implementation in the hal when it moves to a util library.
-static std::string deviceAddressToHal(const DeviceAddress& address) {
- // HAL assumes that the address is NUL-terminated.
- char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
- memset(halAddress, 0, sizeof(halAddress));
- audio_devices_t halDevice = static_cast<audio_devices_t>(address.device);
- if (getAudioDeviceOutAllA2dpSet().count(halDevice) > 0 ||
- halDevice == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
- snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
- address.address.mac[0], address.address.mac[1], address.address.mac[2],
- address.address.mac[3], address.address.mac[4], address.address.mac[5]);
- } else if (halDevice == AUDIO_DEVICE_OUT_IP || halDevice == AUDIO_DEVICE_IN_IP) {
- snprintf(halAddress, sizeof(halAddress), "%d.%d.%d.%d", address.address.ipv4[0],
- address.address.ipv4[1], address.address.ipv4[2], address.address.ipv4[3]);
- } else if (getAudioDeviceOutAllUsbSet().count(halDevice) > 0 ||
- getAudioDeviceInAllUsbSet().count(halDevice) > 0) {
- snprintf(halAddress, sizeof(halAddress), "card=%d;device=%d", address.address.alsa.card,
- address.address.alsa.device);
- } else if (halDevice == AUDIO_DEVICE_OUT_BUS || halDevice == AUDIO_DEVICE_IN_BUS) {
- snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
- } else if (halDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
- halDevice == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
- snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
- } else {
- snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
- }
- return halAddress;
-}
-
-//local conversion helpers
-
-static audio_microphone_channel_mapping_t channelMappingToHal(AudioMicrophoneChannelMapping mapping) {
- switch (mapping) {
- case AudioMicrophoneChannelMapping::UNUSED:
- return AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
- case AudioMicrophoneChannelMapping::DIRECT:
- return AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
- case AudioMicrophoneChannelMapping::PROCESSED:
- return AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
- default:
- LOG_ALWAYS_FATAL("Unknown channelMappingToHal conversion %d", mapping);
- }
-}
-
-static audio_microphone_location_t locationToHal(AudioMicrophoneLocation location) {
- switch (location) {
- case AudioMicrophoneLocation::UNKNOWN:
- return AUDIO_MICROPHONE_LOCATION_UNKNOWN;
- case AudioMicrophoneLocation::MAINBODY:
- return AUDIO_MICROPHONE_LOCATION_MAINBODY;
- case AudioMicrophoneLocation::MAINBODY_MOVABLE:
- return AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE;
- case AudioMicrophoneLocation::PERIPHERAL:
- return AUDIO_MICROPHONE_LOCATION_PERIPHERAL;
- default:
- LOG_ALWAYS_FATAL("Unknown locationToHal conversion %d", location);
- }
-}
-static audio_microphone_directionality_t directionalityToHal(AudioMicrophoneDirectionality dir) {
- switch (dir) {
- case AudioMicrophoneDirectionality::UNKNOWN:
- return AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN;
- case AudioMicrophoneDirectionality::OMNI:
- return AUDIO_MICROPHONE_DIRECTIONALITY_OMNI;
- case AudioMicrophoneDirectionality::BI_DIRECTIONAL:
- return AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL;
- case AudioMicrophoneDirectionality::CARDIOID:
- return AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID;
- case AudioMicrophoneDirectionality::HYPER_CARDIOID:
- return AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID;
- case AudioMicrophoneDirectionality::SUPER_CARDIOID:
- return AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID;
- default:
- LOG_ALWAYS_FATAL("Unknown directionalityToHal conversion %d", dir);
- }
-}
-
-void microphoneInfoToHal(const MicrophoneInfo& src,
- audio_microphone_characteristic_t *pDst) {
- if (pDst != NULL) {
- snprintf(pDst->device_id, sizeof(pDst->device_id),
- "%s", src.deviceId.c_str());
- pDst->device = static_cast<audio_devices_t>(src.deviceAddress.device);
- snprintf(pDst->address, sizeof(pDst->address),
- "%s", deviceAddressToHal(src.deviceAddress).c_str());
- if (src.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
- ALOGW("microphoneInfoToStruct found %zu channelMapping elements. Max expected is %d",
- src.channelMapping.size(), AUDIO_CHANNEL_COUNT_MAX);
- }
- size_t ch;
- for (ch = 0; ch < src.channelMapping.size() && ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
- pDst->channel_mapping[ch] = channelMappingToHal(src.channelMapping[ch]);
- }
- for (; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
- pDst->channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
- }
- pDst->location = locationToHal(src.location);
- pDst->group = (audio_microphone_group_t)src.group;
- pDst->index_in_the_group = (unsigned int)src.indexInTheGroup;
- pDst->sensitivity = src.sensitivity;
- pDst->max_spl = src.maxSpl;
- pDst->min_spl = src.minSpl;
- pDst->directionality = directionalityToHal(src.directionality);
- pDst->num_frequency_responses = (unsigned int)src.frequencyResponse.size();
- if (pDst->num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
- ALOGW("microphoneInfoToStruct found %d frequency responses. Max expected is %d",
- pDst->num_frequency_responses, AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES);
- pDst->num_frequency_responses = AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES;
- }
- for (size_t k = 0; k < pDst->num_frequency_responses; k++) {
- pDst->frequency_responses[0][k] = src.frequencyResponse[k].frequency;
- pDst->frequency_responses[1][k] = src.frequencyResponse[k].level;
- }
- pDst->geometric_location.x = src.position.x;
- pDst->geometric_location.y = src.position.y;
- pDst->geometric_location.z = src.position.z;
- pDst->orientation.x = src.orientation.x;
- pDst->orientation.y = src.orientation.y;
- pDst->orientation.z = src.orientation.z;
- }
-}
-#endif
-
} // namespace CPP_VERSION
} // namespace android
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.h b/media/libaudiohal/impl/ConversionHelperHidl.h
index fb3bb9d..59122c7 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.h
+++ b/media/libaudiohal/impl/ConversionHelperHidl.h
@@ -82,12 +82,6 @@
void emitError(const char* funcName, const char* description);
};
-#if MAJOR_VERSION >= 4
-using ::android::hardware::audio::CPP_VERSION::MicrophoneInfo;
-void microphoneInfoToHal(const MicrophoneInfo& src,
- audio_microphone_characteristic_t *pDst);
-#endif
-
} // namespace CPP_VERSION
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 7d0d83d..ca4f663 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -19,22 +19,24 @@
#define LOG_TAG "DeviceHalHidl"
//#define LOG_NDEBUG 0
-#include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
#include <cutils/native_handle.h>
#include <hwbinder/IPCThreadState.h>
#include <media/AudioContainers.h>
#include <utils/Log.h>
+#include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
+#include <HidlUtils.h>
#include <common/all-versions/VersionUtils.h>
+#include <util/CoreUtils.h>
#include "DeviceHalHidl.h"
#include "EffectHalHidl.h"
-#include "HidlUtils.h"
+#include "ParameterUtils.h"
#include "StreamHalHidl.h"
-#include "VersionUtils.h"
using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::audio::common::utils::EnumBitfield;
+using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -46,47 +48,6 @@
using EffectHalHidl = ::android::effect::CPP_VERSION::EffectHalHidl;
-namespace {
-
-status_t deviceAddressFromHal(
- audio_devices_t device, const char* halAddress, DeviceAddress* address) {
- address->device = AudioDevice(device);
-
- if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
- return OK;
- }
- if (getAudioDeviceOutAllA2dpSet().count(device) > 0
- || device == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
- int status = sscanf(halAddress,
- "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
- &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
- &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
- return status == 6 ? OK : BAD_VALUE;
- } else if (device == AUDIO_DEVICE_OUT_IP || device == AUDIO_DEVICE_IN_IP) {
- int status = sscanf(halAddress,
- "%hhu.%hhu.%hhu.%hhu",
- &address->address.ipv4[0], &address->address.ipv4[1],
- &address->address.ipv4[2], &address->address.ipv4[3]);
- return status == 4 ? OK : BAD_VALUE;
- } else if (getAudioDeviceOutAllUsbSet().count(device) > 0
- || getAudioDeviceInAllUsbSet().count(device) > 0) {
- int status = sscanf(halAddress,
- "card=%d;device=%d",
- &address->address.alsa.card, &address->address.alsa.device);
- return status == 2 ? OK : BAD_VALUE;
- } else if (device == AUDIO_DEVICE_OUT_BUS || device == AUDIO_DEVICE_IN_BUS) {
- address->busAddress = halAddress;
- return OK;
- } else if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
- || device == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
- address->rSubmixAddress = halAddress;
- return OK;
- }
- return OK;
-}
-
-} // namespace
-
DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
: ConversionHelperHidl("Device"), mDevice(device),
mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
@@ -212,7 +173,7 @@
const struct audio_config *config, size_t *size) {
if (mDevice == 0) return NO_INIT;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
Result retval;
Return<void> ret = mDevice->getInputBufferSize(
hidlConfig,
@@ -234,16 +195,22 @@
sp<StreamOutHalInterface> *outStream) {
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
- status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
- if (status != OK) return status;
+ if (status_t status = CoreUtils::deviceAddressFromHal(deviceType, address, &hidlDevice);
+ status != OK) {
+ return status;
+ }
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ if (status_t status = HidlUtils::audioConfigFromHal(*config, false /*isInput*/, &hidlConfig);
+ status != OK) {
+ return status;
+ }
+ CoreUtils::AudioOutputFlags hidlFlags;
+ if (status_t status = CoreUtils::audioOutputFlagsFromHal(flags, &hidlFlags); status != OK) {
+ return status;
+ }
Result retval = Result::NOT_INITIALIZED;
Return<void> ret = mDevice->openOutputStream(
- handle,
- hidlDevice,
- hidlConfig,
- EnumBitfield<AudioOutputFlag>(flags),
+ handle, hidlDevice, hidlConfig, hidlFlags,
#if MAJOR_VERSION >= 4
{} /* metadata */,
#endif
@@ -269,39 +236,54 @@
sp<StreamInHalInterface> *inStream) {
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
- status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
- if (status != OK) return status;
+ if (status_t status = CoreUtils::deviceAddressFromHal(devices, address, &hidlDevice);
+ status != OK) {
+ return status;
+ }
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ if (status_t status = HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
+ status != OK) {
+ return status;
+ }
+ CoreUtils::AudioInputFlags hidlFlags;
+#if MAJOR_VERSION <= 5
+ // Some flags were specific to framework and must not leak to the HAL.
+ flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
+#endif
+ if (status_t status = CoreUtils::audioInputFlagsFromHal(flags, &hidlFlags); status != OK) {
+ return status;
+ }
Result retval = Result::NOT_INITIALIZED;
#if MAJOR_VERSION == 2
auto sinkMetadata = AudioSource(source);
#elif MAJOR_VERSION >= 4
// TODO: correctly propagate the tracks sources and volume
// for now, only send the main source at 1dbfs
- SinkMetadata sinkMetadata = {{{ .source = AudioSource(source), .gain = 1 }}};
+ AudioSource hidlSource;
+ if (status_t status = HidlUtils::audioSourceFromHal(source, &hidlSource); status != OK) {
+ return status;
+ }
+ SinkMetadata sinkMetadata = {{{ .source = std::move(hidlSource), .gain = 1 }}};
#endif
#if MAJOR_VERSION < 5
(void)outputDevice;
(void)outputDeviceAddress;
#else
+#if MAJOR_VERSION >= 7
+ (void)HidlUtils::audioChannelMaskFromHal(
+ AUDIO_CHANNEL_NONE, true /*isInput*/, &sinkMetadata.tracks[0].channelMask);
+#endif
if (outputDevice != AUDIO_DEVICE_NONE) {
DeviceAddress hidlOutputDevice;
- status = deviceAddressFromHal(outputDevice, outputDeviceAddress, &hidlOutputDevice);
- if (status != OK) return status;
+ if (status_t status = CoreUtils::deviceAddressFromHal(
+ outputDevice, outputDeviceAddress, &hidlOutputDevice); status != OK) {
+ return status;
+ }
sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
}
#endif
-#if MAJOR_VERSION <= 5
- // Some flags were specific to framework and must not leak to the HAL.
- flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
-#endif
Return<void> ret = mDevice->openInputStream(
- handle,
- hidlDevice,
- hidlConfig,
- EnumBitfield<AudioInputFlag>(flags),
- sinkMetadata,
+ handle, hidlDevice, hidlConfig, hidlFlags, sinkMetadata,
[&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
retval = r;
if (retval == Result::OK) {
@@ -372,7 +354,8 @@
return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
}
-status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
+template <typename HalPort>
+status_t DeviceHalHidl::getAudioPortImpl(HalPort *port) {
if (mDevice == 0) return NO_INIT;
AudioPort hidlPort;
HidlUtils::audioPortFromHal(*port, &hidlPort);
@@ -388,6 +371,30 @@
return processReturn("getAudioPort", ret, retval);
}
+status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
+ return getAudioPortImpl(port);
+}
+
+status_t DeviceHalHidl::getAudioPort(struct audio_port_v7 *port) {
+#if MAJOR_VERSION >= 7
+ return getAudioPortImpl(port);
+#else
+ struct audio_port audioPort = {};
+ status_t result = NO_ERROR;
+ if (!audio_populate_audio_port(port, &audioPort)) {
+ ALOGE("Failed to populate legacy audio port from audio_port_v7");
+ result = BAD_VALUE;
+ }
+ status_t status = getAudioPort(&audioPort);
+ if (status == NO_ERROR) {
+ audio_populate_audio_port_v7(&audioPort, port);
+ } else {
+ result = status;
+ }
+ return result;
+#endif
+}
+
status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
if (mDevice == 0) return NO_INIT;
AudioPortConfig hidlConfig;
@@ -411,7 +418,7 @@
for (size_t k = 0; k < micArrayHal.size(); k++) {
audio_microphone_characteristic_t dst;
//convert
- microphoneInfoToHal(micArrayHal[k], &dst);
+ (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
microphonesInfo->push_back(microphone);
}
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index d342d4a..2c847cf 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -107,6 +107,9 @@
// Fills the list of supported attributes for a given audio port.
virtual status_t getAudioPort(struct audio_port *port);
+ // Fills the list of supported attributes for a given audio port.
+ virtual status_t getAudioPort(struct audio_port_v7 *port);
+
// Set audio port configuration.
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
@@ -128,6 +131,8 @@
// The destructor automatically closes the device.
virtual ~DeviceHalHidl();
+
+ template <typename HalPort> status_t getAudioPortImpl(HalPort *port);
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/impl/DeviceHalLocal.cpp b/media/libaudiohal/impl/DeviceHalLocal.cpp
index 8021d92..af7dc1a 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.cpp
+++ b/media/libaudiohal/impl/DeviceHalLocal.cpp
@@ -180,6 +180,22 @@
return mDev->get_audio_port(mDev, port);
}
+status_t DeviceHalLocal::getAudioPort(struct audio_port_v7 *port) {
+#if MAJOR_VERSION >= 7
+ if (version() >= AUDIO_DEVICE_API_VERSION_3_2) {
+ // get_audio_port_v7 is mandatory if legacy HAL support this API version.
+ return mDev->get_audio_port_v7(mDev, port);
+ }
+#endif
+ struct audio_port audioPort = {};
+ audio_populate_audio_port(port, &audioPort);
+ status_t status = getAudioPort(&audioPort);
+ if (status == NO_ERROR) {
+ audio_populate_audio_port_v7(&audioPort, port);
+ }
+ return status;
+}
+
status_t DeviceHalLocal::setAudioPortConfig(const struct audio_port_config *config) {
if (version() >= AUDIO_DEVICE_API_VERSION_3_0)
return mDev->set_audio_port_config(mDev, config);
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index d85e2a7..46b510b 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -100,6 +100,9 @@
// Fills the list of supported attributes for a given audio port.
virtual status_t getAudioPort(struct audio_port *port);
+ // Fills the list of supported attributes for a given audio port.
+ virtual status_t getAudioPort(struct audio_port_v7 *port);
+
// Set audio port configuration.
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
@@ -114,6 +117,8 @@
void closeOutputStream(struct audio_stream_out *stream_out);
void closeInputStream(struct audio_stream_in *stream_in);
+ uint32_t version() const { return mDev->common.version; }
+
private:
audio_hw_device_t *mDev;
@@ -124,8 +129,6 @@
// The destructor automatically closes the device.
virtual ~DeviceHalLocal();
-
- uint32_t version() const { return mDev->common.version; }
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index caf575c..c589a48 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -23,12 +23,13 @@
#include <media/EffectsFactoryApi.h>
#include <utils/Log.h>
+#include <util/EffectUtils.h>
+
#include "EffectBufferHalHidl.h"
#include "EffectHalHidl.h"
-#include "HidlUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::audio::common::utils::EnumBitfield;
+using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
using ::android::hardware::hidl_vec;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
@@ -42,6 +43,10 @@
EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
: mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
+ effect_descriptor_t halDescriptor{};
+ if (EffectHalHidl::getDescriptor(&halDescriptor) == NO_ERROR) {
+ mIsInput = (halDescriptor.flags & EFFECT_FLAG_TYPE_PRE_PROC) == EFFECT_FLAG_TYPE_PRE_PROC;
+ }
}
EffectHalHidl::~EffectHalHidl() {
@@ -56,59 +61,6 @@
}
// static
-void EffectHalHidl::effectDescriptorToHal(
- const EffectDescriptor& descriptor, effect_descriptor_t* halDescriptor) {
- HidlUtils::uuidToHal(descriptor.type, &halDescriptor->type);
- HidlUtils::uuidToHal(descriptor.uuid, &halDescriptor->uuid);
- halDescriptor->flags = static_cast<uint32_t>(descriptor.flags);
- halDescriptor->cpuLoad = descriptor.cpuLoad;
- halDescriptor->memoryUsage = descriptor.memoryUsage;
- memcpy(halDescriptor->name, descriptor.name.data(), descriptor.name.size());
- memcpy(halDescriptor->implementor,
- descriptor.implementor.data(), descriptor.implementor.size());
-}
-
-// TODO(mnaganov): These buffer conversion functions should be shared with Effect wrapper
-// via HidlUtils. Move them there when hardware/interfaces will get un-frozen again.
-
-// static
-void EffectHalHidl::effectBufferConfigFromHal(
- const buffer_config_t& halConfig, EffectBufferConfig* config) {
- config->samplingRateHz = halConfig.samplingRate;
- config->channels = EnumBitfield<AudioChannelMask>(halConfig.channels);
- config->format = AudioFormat(halConfig.format);
- config->accessMode = EffectBufferAccess(halConfig.accessMode);
- config->mask = EnumBitfield<EffectConfigParameters>(halConfig.mask);
-}
-
-// static
-void EffectHalHidl::effectBufferConfigToHal(
- const EffectBufferConfig& config, buffer_config_t* halConfig) {
- halConfig->buffer.frameCount = 0;
- halConfig->buffer.raw = NULL;
- halConfig->samplingRate = config.samplingRateHz;
- halConfig->channels = static_cast<uint32_t>(config.channels);
- halConfig->bufferProvider.cookie = NULL;
- halConfig->bufferProvider.getBuffer = NULL;
- halConfig->bufferProvider.releaseBuffer = NULL;
- halConfig->format = static_cast<uint8_t>(config.format);
- halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
- halConfig->mask = static_cast<uint8_t>(config.mask);
-}
-
-// static
-void EffectHalHidl::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
- effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
- effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
-}
-
-// static
-void EffectHalHidl::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
- effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
- effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
-}
-
-// static
status_t EffectHalHidl::analyzeResult(const Result& result) {
switch (result) {
case Result::OK: return OK;
@@ -269,7 +221,7 @@
[&](Result r, const EffectDescriptor& result) {
retval = r;
if (retval == Result::OK) {
- effectDescriptorToHal(result, pDescriptor);
+ EffectUtils::effectDescriptorToHal(result, pDescriptor);
}
});
return ret.isOk() ? analyzeResult(retval) : FAILED_TRANSACTION;
@@ -301,14 +253,16 @@
ret = mEffect->getConfig([&] (Result r, const EffectConfig &hidlConfig) {
result = analyzeResult(r);
if (r == Result::OK) {
- effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
+ EffectUtils::effectConfigToHal(
+ hidlConfig, static_cast<effect_config_t*>(pReplyData));
}
});
} else {
ret = mEffect->getConfigReverse([&] (Result r, const EffectConfig &hidlConfig) {
result = analyzeResult(r);
if (r == Result::OK) {
- effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
+ EffectUtils::effectConfigToHal(
+ hidlConfig, static_cast<effect_config_t*>(pReplyData));
}
});
}
@@ -332,7 +286,7 @@
ALOGE("Buffer provider callbacks are not supported");
}
EffectConfig hidlConfig;
- effectConfigFromHal(*halConfig, &hidlConfig);
+ EffectUtils::effectConfigFromHal(*halConfig, mIsInput, &hidlConfig);
Return<Result> ret = cmdCode == EFFECT_CMD_SET_CONFIG ?
mEffect->setConfig(hidlConfig, nullptr, nullptr) :
mEffect->setConfigReverse(hidlConfig, nullptr, nullptr);
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index 1f238c0..8e46638 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -65,9 +65,6 @@
uint64_t effectId() const { return mEffectId; }
- static void effectDescriptorToHal(
- const EffectDescriptor& descriptor, effect_descriptor_t* halDescriptor);
-
private:
friend class EffectsFactoryHalHidl;
typedef MessageQueue<Result, hardware::kSynchronizedReadWrite> StatusMQ;
@@ -79,14 +76,9 @@
bool mBuffersChanged;
std::unique_ptr<StatusMQ> mStatusMQ;
EventFlag* mEfGroup;
+ bool mIsInput = false;
static status_t analyzeResult(const Result& result);
- static void effectBufferConfigFromHal(
- const buffer_config_t& halConfig, EffectBufferConfig* config);
- static void effectBufferConfigToHal(
- const EffectBufferConfig& config, buffer_config_t* halConfig);
- static void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
- static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
// Can not be constructed directly by clients.
EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId);
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 9192a31..8d15592 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -19,13 +19,16 @@
#include <cutils/native_handle.h>
+#include <UuidUtils.h>
+#include <util/EffectUtils.h>
+
#include "ConversionHelperHidl.h"
#include "EffectBufferHalHidl.h"
#include "EffectHalHidl.h"
#include "EffectsFactoryHalHidl.h"
-#include "HidlUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
using ::android::hardware::Return;
namespace android {
@@ -76,7 +79,7 @@
if (queryResult != OK) return queryResult;
}
if (index >= mLastDescriptors.size()) return NAME_NOT_FOUND;
- EffectHalHidl::effectDescriptorToHal(mLastDescriptors[index], pDescriptor);
+ EffectUtils::effectDescriptorToHal(mLastDescriptors[index], pDescriptor);
return OK;
}
@@ -85,13 +88,13 @@
// TODO: check for nullptr
if (mEffectsFactory == 0) return NO_INIT;
Uuid hidlUuid;
- HidlUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
+ UuidUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
Result retval = Result::NOT_INITIALIZED;
Return<void> ret = mEffectsFactory->getDescriptor(hidlUuid,
[&](Result r, const EffectDescriptor& result) {
retval = r;
if (retval == Result::OK) {
- EffectHalHidl::effectDescriptorToHal(result, pDescriptor);
+ EffectUtils::effectDescriptorToHal(result, pDescriptor);
}
});
if (ret.isOk()) {
@@ -107,7 +110,7 @@
int32_t deviceId __unused, sp<EffectHalInterface> *effect) {
if (mEffectsFactory == 0) return NO_INIT;
Uuid hidlUuid;
- HidlUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
+ UuidUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
Result retval = Result::NOT_INITIALIZED;
Return<void> ret;
#if MAJOR_VERSION >= 6
diff --git a/media/libaudiohal/impl/VersionUtils.h b/media/libaudiohal/impl/ParameterUtils.h
similarity index 91%
rename from media/libaudiohal/impl/VersionUtils.h
rename to media/libaudiohal/impl/ParameterUtils.h
index eb0a42a..9cab72e 100644
--- a/media/libaudiohal/impl/VersionUtils.h
+++ b/media/libaudiohal/impl/ParameterUtils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_VERSION_UTILS_H
-#define ANDROID_HARDWARE_VERSION_UTILS_H
+#pragma once
#include PATH(android/hardware/audio/FILE_VERSION/types.h)
#include <hidl/HidlSupport.h>
@@ -59,5 +58,3 @@
} // namespace utils
} // namespace CPP_VERSION
} // namespace android
-
-#endif // ANDROID_HARDWARE_VERSION_UTILS_H
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2726e36..6da8bbd 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -17,17 +17,23 @@
#define LOG_TAG "StreamHalHidl"
//#define LOG_NDEBUG 0
-#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutCallback.h)
+#include <android/hidl/manager/1.0/IServiceManager.h>
#include <hwbinder/IPCThreadState.h>
#include <media/AudioParameter.h>
#include <mediautils/SchedulingPolicyService.h>
#include <utils/Log.h>
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutCallback.h)
+#include <HidlUtils.h>
+#include <util/CoreUtils.h>
+
#include "DeviceHalHidl.h"
#include "EffectHalHidl.h"
+#include "ParameterUtils.h"
#include "StreamHalHidl.h"
-#include "VersionUtils.h"
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
using ::android::hardware::Void;
@@ -49,14 +55,11 @@
// Instrument audio signal power logging.
// Note: This assumes channel mask, format, and sample rate do not change after creation.
- if (mStream != nullptr /* && mStreamPowerLog.isUserDebugOrEngBuild() */) {
- // Obtain audio properties (see StreamHalHidl::getAudioProperties() below).
- Return<void> ret = mStream->getAudioProperties(
- [&](auto sr, auto m, auto f) {
- mStreamPowerLog.init(sr,
- static_cast<audio_channel_mask_t>(m),
- static_cast<audio_format_t>(f));
- });
+ audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+ if (/* mStreamPowerLog.isUserDebugOrEngBuild() && */
+ StreamHalHidl::getAudioProperties(
+ &config.sample_rate, &config.channel_mask, &config.format) == NO_ERROR) {
+ mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
}
}
@@ -64,9 +67,12 @@
mStream = nullptr;
}
+// Note: this method will be removed
status_t StreamHalHidl::getSampleRate(uint32_t *rate) {
- if (!mStream) return NO_INIT;
- return processReturn("getSampleRate", mStream->getSampleRate(), rate);
+ audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+ status_t status = getAudioProperties(&config.sample_rate, &config.channel_mask, &config.format);
+ *rate = config.sample_rate;
+ return status;
}
status_t StreamHalHidl::getBufferSize(size_t *size) {
@@ -78,19 +84,26 @@
return status;
}
+// Note: this method will be removed
status_t StreamHalHidl::getChannelMask(audio_channel_mask_t *mask) {
- if (!mStream) return NO_INIT;
- return processReturn("getChannelMask", mStream->getChannelMask(), mask);
+ audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+ status_t status = getAudioProperties(&config.sample_rate, &config.channel_mask, &config.format);
+ *mask = config.channel_mask;
+ return status;
}
+// Note: this method will be removed
status_t StreamHalHidl::getFormat(audio_format_t *format) {
- if (!mStream) return NO_INIT;
- return processReturn("getFormat", mStream->getFormat(), format);
+ audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+ status_t status = getAudioProperties(&config.sample_rate, &config.channel_mask, &config.format);
+ *format = config.format;
+ return status;
}
status_t StreamHalHidl::getAudioProperties(
uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) {
if (!mStream) return NO_INIT;
+#if MAJOR_VERSION <= 6
Return<void> ret = mStream->getAudioProperties(
[&](uint32_t sr, auto m, auto f) {
*sampleRate = sr;
@@ -98,6 +111,26 @@
*format = static_cast<audio_format_t>(f);
});
return processReturn("getAudioProperties", ret);
+#else
+ Result retval;
+ status_t conversionStatus = BAD_VALUE;
+ audio_config_base_t halConfig = AUDIO_CONFIG_BASE_INITIALIZER;
+ Return<void> ret = mStream->getAudioProperties(
+ [&](Result r, const AudioConfigBase& config) {
+ retval = r;
+ if (retval == Result::OK) {
+ conversionStatus = HidlUtils::audioConfigBaseToHal(config, &halConfig);
+ }
+ });
+ if (status_t status = processReturn("getAudioProperties", ret, retval); status == NO_ERROR) {
+ *sampleRate = halConfig.sample_rate;
+ *mask = halConfig.channel_mask;
+ *format = halConfig.format;
+ return conversionStatus;
+ } else {
+ return status;
+ }
+#endif
}
status_t StreamHalHidl::setParameters(const String8& kvPairs) {
@@ -225,6 +258,24 @@
return getBufferSize(size);
}
+status_t StreamHalHidl::getHalPid(pid_t *pid) {
+ using ::android::hidl::base::V1_0::DebugInfo;
+ using ::android::hidl::manager::V1_0::IServiceManager;
+
+ DebugInfo debugInfo;
+ auto ret = mStream->getDebugInfo([&] (const auto &info) {
+ debugInfo = info;
+ });
+ if (!ret.isOk()) {
+ return INVALID_OPERATION;
+ }
+ if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
+ *pid = debugInfo.pid;
+ return NO_ERROR;
+ }
+ return NAME_NOT_FOUND;
+}
+
bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
return true;
@@ -453,7 +504,7 @@
const CommandMQ::Descriptor& commandMQ,
const DataMQ::Descriptor& dataMQ,
const StatusMQ::Descriptor& statusMQ,
- const ThreadInfo& halThreadInfo) {
+ const auto& halThreadInfo) {
retval = r;
if (retval == Result::OK) {
tempCommandMQ.reset(new CommandMQ(commandMQ));
@@ -462,8 +513,12 @@
if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
}
+#if MAJOR_VERSION <= 6
halThreadPid = halThreadInfo.pid;
halThreadTid = halThreadInfo.tid;
+#else
+ halThreadTid = halThreadInfo;
+#endif
}
});
if (!ret.isOk() || retval != Result::OK) {
@@ -484,6 +539,11 @@
ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
return NO_INIT;
}
+#if MAJOR_VERSION >= 7
+ if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
+ return status;
+ }
+#endif
requestHalThreadPriority(halThreadPid, halThreadTid);
mCommandMQ = std::move(tempCommandMQ);
@@ -597,31 +657,45 @@
return INVALID_OPERATION;
}
#elif MAJOR_VERSION >= 4
-/** Transform a standard collection to an HIDL vector. */
-template <class Values, class ElementConverter>
-static auto transformToHidlVec(const Values& values, ElementConverter converter) {
- hidl_vec<decltype(converter(*values.begin()))> result{values.size()};
- using namespace std;
- transform(begin(values), end(values), begin(result), converter);
- return result;
-}
-
status_t StreamOutHalHidl::updateSourceMetadata(
const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
- CPP_VERSION::SourceMetadata halMetadata = {
- .tracks = transformToHidlVec(sourceMetadata.tracks,
- [](const playback_track_metadata& metadata) -> PlaybackTrackMetadata {
- return {
- .usage=static_cast<AudioUsage>(metadata.usage),
- .contentType=static_cast<AudioContentType>(metadata.content_type),
- .gain=metadata.gain,
- };
- })};
- return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(halMetadata));
+ CPP_VERSION::SourceMetadata hidlMetadata;
+ if (status_t status = CoreUtils::sourceMetadataFromHalV7(
+ sourceMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
+ status != OK) {
+ return status;
+ }
+ return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(hidlMetadata));
}
#endif
#if MAJOR_VERSION < 6
+status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalHidl::getPlaybackRateParameters(
+ audio_playback_rate_t* playbackRate __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalHidl::setPlaybackRateParameters(
+ const audio_playback_rate_t& playbackRate __unused) {
+ return INVALID_OPERATION;
+}
+
status_t StreamOutHalHidl::setEventCallback(
const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
// Codec format callback is supported starting from audio HAL V6.0
@@ -629,6 +703,73 @@
}
#else
+status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
+ if (mStream == 0) return NO_INIT;
+ Result retval;
+ Return<void> ret = mStream->getDualMonoMode(
+ [&](Result r, DualMonoMode hidlMode) {
+ retval = r;
+ if (retval == Result::OK) {
+ *mode = static_cast<audio_dual_mono_mode_t>(hidlMode);
+ }
+ });
+ return processReturn("getDualMonoMode", ret, retval);
+}
+
+status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
+ if (mStream == 0) return NO_INIT;
+ return processReturn(
+ "setDualMonoMode", mStream->setDualMonoMode(static_cast<DualMonoMode>(mode)));
+}
+
+status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB) {
+ if (mStream == 0) return NO_INIT;
+ Result retval;
+ Return<void> ret = mStream->getAudioDescriptionMixLevel(
+ [&](Result r, float hidlLeveldB) {
+ retval = r;
+ if (retval == Result::OK) {
+ *leveldB = hidlLeveldB;
+ }
+ });
+ return processReturn("getAudioDescriptionMixLevel", ret, retval);
+}
+
+status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB) {
+ if (mStream == 0) return NO_INIT;
+ return processReturn(
+ "setAudioDescriptionMixLevel", mStream->setAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalHidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
+ if (mStream == 0) return NO_INIT;
+ Result retval;
+ Return<void> ret = mStream->getPlaybackRateParameters(
+ [&](Result r, PlaybackRate hidlPlaybackRate) {
+ retval = r;
+ if (retval == Result::OK) {
+ playbackRate->mSpeed = hidlPlaybackRate.speed;
+ playbackRate->mPitch = hidlPlaybackRate.pitch;
+ playbackRate->mStretchMode =
+ static_cast<audio_timestretch_stretch_mode_t>(
+ hidlPlaybackRate.timestretchMode);
+ playbackRate->mFallbackMode =
+ static_cast<audio_timestretch_fallback_mode_t>(
+ hidlPlaybackRate.fallbackMode);
+ }
+ });
+ return processReturn("getPlaybackRateParameters", ret, retval);
+}
+
+status_t StreamOutHalHidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
+ if (mStream == 0) return NO_INIT;
+ return processReturn(
+ "setPlaybackRateParameters", mStream->setPlaybackRateParameters(
+ PlaybackRate{playbackRate.mSpeed, playbackRate.mPitch,
+ static_cast<TimestretchMode>(playbackRate.mStretchMode),
+ static_cast<TimestretchFallbackMode>(playbackRate.mFallbackMode)}));
+}
+
#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutEventCallback.h)
namespace {
@@ -797,7 +938,7 @@
const CommandMQ::Descriptor& commandMQ,
const DataMQ::Descriptor& dataMQ,
const StatusMQ::Descriptor& statusMQ,
- const ThreadInfo& halThreadInfo) {
+ const auto& halThreadInfo) {
retval = r;
if (retval == Result::OK) {
tempCommandMQ.reset(new CommandMQ(commandMQ));
@@ -806,8 +947,12 @@
if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
}
+#if MAJOR_VERSION <= 6
halThreadPid = halThreadInfo.pid;
halThreadTid = halThreadInfo.tid;
+#else
+ halThreadTid = halThreadInfo;
+#endif
}
});
if (!ret.isOk() || retval != Result::OK) {
@@ -828,6 +973,11 @@
ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
return NO_INIT;
}
+#if MAJOR_VERSION >= 7
+ if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
+ return status;
+ }
+#endif
requestHalThreadPriority(halThreadPid, halThreadTid);
mCommandMQ = std::move(tempCommandMQ);
@@ -890,7 +1040,7 @@
for (size_t k = 0; k < micArrayHal.size(); k++) {
audio_microphone_characteristic_t dst;
// convert
- microphoneInfoToHal(micArrayHal[k], &dst);
+ (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
microphonesInfo->push_back(microphone);
}
@@ -900,15 +1050,13 @@
status_t StreamInHalHidl::updateSinkMetadata(const
StreamInHalInterface::SinkMetadata& sinkMetadata) {
- CPP_VERSION::SinkMetadata halMetadata = {
- .tracks = transformToHidlVec(sinkMetadata.tracks,
- [](const record_track_metadata& metadata) -> RecordTrackMetadata {
- return {
- .source=static_cast<AudioSource>(metadata.source),
- .gain=metadata.gain,
- };
- })};
- return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(halMetadata));
+ CPP_VERSION::SinkMetadata hidlMetadata;
+ if (status_t status = CoreUtils::sinkMetadataFromHalV7(
+ sinkMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
+ status != OK) {
+ return status;
+ }
+ return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(hidlMetadata));
}
#endif
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 88f8587..72ce60b 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -105,6 +105,8 @@
status_t getCachedBufferSize(size_t *size);
+ status_t getHalPid(pid_t *pid);
+
bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
// mStreamPowerLog is used for audio signal power logging.
@@ -173,6 +175,24 @@
void onDrainReady();
void onError();
+ // Returns the Dual Mono mode presentation setting.
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override;
+
+ // Sets the Dual Mono mode presentation on the output device.
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) override;
+
+ // Returns the Audio Description Mix level in dB.
+ status_t getAudioDescriptionMixLevel(float* leveldB) override;
+
+ // Sets the Audio Description Mix level in dB.
+ status_t setAudioDescriptionMixLevel(float leveldB) override;
+
+ // Retrieves current playback rate parameters.
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override;
+
+ // Sets the playback rate parameters that control playback behavior.
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override;
+
status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
// Methods used by StreamCodecFormatCallback (HIDL).
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 69be303..e89b288 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -22,8 +22,8 @@
#include <utils/Log.h>
#include "DeviceHalLocal.h"
+#include "ParameterUtils.h"
#include "StreamHalLocal.h"
-#include "VersionUtils.h"
namespace android {
namespace CPP_VERSION {
@@ -241,19 +241,55 @@
return mStream->get_presentation_position(mStream, frames, timestamp);
}
+void StreamOutHalLocal::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
+ std::vector<playback_track_metadata> halTracks;
+ halTracks.reserve(sourceMetadata.tracks.size());
+ for (auto& metadata : sourceMetadata.tracks) {
+ playback_track_metadata halTrackMetadata;
+ playback_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
+ }
+ const source_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_source_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamOutHalLocal::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
+ const source_metadata_v7_t metadata {
+ .track_count = sourceMetadata.tracks.size(),
+ // const cast is fine as it is in a const structure
+ .tracks = const_cast<playback_track_metadata_v7*>(sourceMetadata.tracks.data()),
+ };
+ mStream->update_source_metadata_v7(mStream, &metadata);
+}
+#endif
+
status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+#if MAJOR_VERSION < 7
if (mStream->update_source_metadata == nullptr) {
return INVALID_OPERATION;
}
- const source_metadata_t metadata {
- .track_count = sourceMetadata.tracks.size(),
- // const cast is fine as it is in a const structure
- .tracks = const_cast<playback_track_metadata*>(sourceMetadata.tracks.data()),
- };
- mStream->update_source_metadata(mStream, &metadata);
+ doUpdateSourceMetadata(sourceMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+ } else {
+ if (mStream->update_source_metadata_v7 == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadataV7(sourceMetadata);
+ }
+#endif
return OK;
}
+
status_t StreamOutHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);
@@ -275,6 +311,36 @@
return mStream->get_mmap_position(mStream, position);
}
+status_t StreamOutHalLocal::getDualMonoMode(audio_dual_mono_mode_t* mode) {
+ if (mStream->get_dual_mono_mode == nullptr) return INVALID_OPERATION;
+ return mStream->get_dual_mono_mode(mStream, mode);
+}
+
+status_t StreamOutHalLocal::setDualMonoMode(audio_dual_mono_mode_t mode) {
+ if (mStream->set_dual_mono_mode == nullptr) return INVALID_OPERATION;
+ return mStream->set_dual_mono_mode(mStream, mode);
+}
+
+status_t StreamOutHalLocal::getAudioDescriptionMixLevel(float* leveldB) {
+ if (mStream->get_audio_description_mix_level == nullptr) return INVALID_OPERATION;
+ return mStream->get_audio_description_mix_level(mStream, leveldB);
+}
+
+status_t StreamOutHalLocal::setAudioDescriptionMixLevel(float leveldB) {
+ if (mStream->set_audio_description_mix_level == nullptr) return INVALID_OPERATION;
+ return mStream->set_audio_description_mix_level(mStream, leveldB);
+}
+
+status_t StreamOutHalLocal::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
+ if (mStream->get_playback_rate_parameters == nullptr) return INVALID_OPERATION;
+ return mStream->get_playback_rate_parameters(mStream, playbackRate);
+}
+
+status_t StreamOutHalLocal::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
+ if (mStream->set_playback_rate_parameters == nullptr) return INVALID_OPERATION;
+ return mStream->set_playback_rate_parameters(mStream, &playbackRate);
+}
+
status_t StreamOutHalLocal::setEventCallback(
const sp<StreamOutHalInterfaceEventCallback>& callback) {
if (mStream->set_event_callback == nullptr) {
@@ -352,16 +418,51 @@
return mStream->get_capture_position(mStream, frames, time);
}
-status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
- if (mStream->update_sink_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamInHalLocal::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
+ std::vector<record_track_metadata> halTracks;
+ halTracks.reserve(sinkMetadata.tracks.size());
+ for (auto& metadata : sinkMetadata.tracks) {
+ record_track_metadata halTrackMetadata;
+ record_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
- const sink_metadata_t metadata {
+ const sink_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_sink_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamInHalLocal::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
+ const sink_metadata_v7_t halMetadata {
.track_count = sinkMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<record_track_metadata*>(sinkMetadata.tracks.data()),
+ .tracks = const_cast<record_track_metadata_v7*>(sinkMetadata.tracks.data()),
};
- mStream->update_sink_metadata(mStream, &metadata);
+ mStream->update_sink_metadata_v7(mStream, &halMetadata);
+}
+#endif
+
+status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+#if MAJOR_VERSION < 7
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+ } else {
+ if (mStream->update_sink_metadata_v7 == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadataV7(sinkMetadata);
+ }
+#endif
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index d17f9f3..e228104 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -156,6 +156,24 @@
// Called when the metadata of the stream's source has been changed.
status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
+ // Returns the Dual Mono mode presentation setting.
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override;
+
+ // Sets the Dual Mono mode presentation on the output device.
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) override;
+
+ // Returns the Audio Description Mix level in dB.
+ status_t getAudioDescriptionMixLevel(float* leveldB) override;
+
+ // Sets the Audio Description Mix level in dB.
+ status_t setAudioDescriptionMixLevel(float leveldB) override;
+
+ // Retrieves current playback rate parameters.
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override;
+
+ // Sets the playback rate parameters that control playback behavior.
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override;
+
status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
private:
@@ -173,6 +191,9 @@
static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
+
+ void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+ void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
};
class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
@@ -227,6 +248,9 @@
StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
virtual ~StreamInHalLocal();
+
+ void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
+ void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 1e04b21..29ef011 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -106,6 +106,9 @@
// Fills the list of supported attributes for a given audio port.
virtual status_t getAudioPort(struct audio_port *port) = 0;
+ // Fills the list of supported attributes for a given audio port.
+ virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
+
// Set audio port configuration.
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index e30cb72..b47f536 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -31,18 +31,22 @@
class StreamHalInterface : public virtual RefBase
{
public:
+ // TODO(mnaganov): Remove
// Return the sampling rate in Hz - eg. 44100.
virtual status_t getSampleRate(uint32_t *rate) = 0;
// Return size of input/output buffer in bytes for this stream - eg. 4800.
virtual status_t getBufferSize(size_t *size) = 0;
+ // TODO(mnaganov): Remove
// Return the channel mask.
virtual status_t getChannelMask(audio_channel_mask_t *mask) = 0;
+ // TODO(mnaganov): Remove
// Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT.
virtual status_t getFormat(audio_format_t *format) = 0;
+ // TODO(mnaganov): Change to use audio_config_base_t
// Convenience method.
virtual status_t getAudioProperties(
uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) = 0;
@@ -158,14 +162,33 @@
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
struct SourceMetadata {
- std::vector<playback_track_metadata_t> tracks;
+ std::vector<playback_track_metadata_v7_t> tracks;
};
+
/**
* Called when the metadata of the stream's source has been changed.
* @param sourceMetadata Description of the audio that is played by the clients.
*/
virtual status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) = 0;
+ // Returns the Dual Mono mode presentation setting.
+ virtual status_t getDualMonoMode(audio_dual_mono_mode_t* mode) = 0;
+
+ // Sets the Dual Mono mode presentation on the output device.
+ virtual status_t setDualMonoMode(audio_dual_mono_mode_t mode) = 0;
+
+ // Returns the Audio Description Mix level in dB.
+ virtual status_t getAudioDescriptionMixLevel(float* leveldB) = 0;
+
+ // Sets the Audio Description Mix level in dB.
+ virtual status_t setAudioDescriptionMixLevel(float leveldB) = 0;
+
+ // Retrieves current playback rate parameters.
+ virtual status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) = 0;
+
+ // Sets the playback rate parameters that control playback behavior.
+ virtual status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) = 0;
+
virtual status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) = 0;
protected:
@@ -197,7 +220,7 @@
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
struct SinkMetadata {
- std::vector<record_track_metadata_t> tracks;
+ std::vector<record_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's sink has been changed.
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 39b0ceb..309765a 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libaudioprocessing_defaults",
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 1a31420..00baea2 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -79,10 +79,14 @@
&& mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
return false; // no need to change
}
- const audio_channel_mask_t hapticChannelMask = trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
- trackChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
- const audio_channel_mask_t mixerHapticChannelMask = mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
- mixerChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+ const audio_channel_mask_t hapticChannelMask =
+ static_cast<audio_channel_mask_t>(trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+ trackChannelMask = static_cast<audio_channel_mask_t>(
+ trackChannelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
+ const audio_channel_mask_t mixerHapticChannelMask = static_cast<audio_channel_mask_t>(
+ mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+ mixerChannelMask = static_cast<audio_channel_mask_t>(
+ mixerChannelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
// always recompute for both channel masks even if only one has changed.
const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
@@ -362,7 +366,8 @@
const audio_channel_mask_t trackChannelMask =
static_cast<audio_channel_mask_t>(valueInt);
if (setChannelMasks(name, trackChannelMask,
- (track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
+ static_cast<audio_channel_mask_t>(
+ track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
invalidate();
}
@@ -407,7 +412,8 @@
case MIXER_CHANNEL_MASK: {
const audio_channel_mask_t mixerChannelMask =
static_cast<audio_channel_mask_t>(valueInt);
- if (setChannelMasks(name, track->channelMask | track->mHapticChannelMask,
+ if (setChannelMasks(name, static_cast<audio_channel_mask_t>(
+ track->channelMask | track->mHapticChannelMask),
mixerChannelMask)) {
ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
invalidate();
@@ -533,9 +539,10 @@
Track* t = static_cast<Track*>(track);
audio_channel_mask_t channelMask = t->channelMask;
- t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ t->mHapticChannelMask = static_cast<audio_channel_mask_t>(
+ channelMask & AUDIO_CHANNEL_HAPTIC_ALL);
t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
- channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+ channelMask = static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
t->channelCount = audio_channel_count_from_out_mask(channelMask);
ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
"Non-stereo channel mask: %d\n", channelMask);
diff --git a/media/libaudioprocessing/audio-resampler/Android.bp b/media/libaudioprocessing/audio-resampler/Android.bp
index dc70310..4ea75e7 100644
--- a/media/libaudioprocessing/audio-resampler/Android.bp
+++ b/media/libaudioprocessing/audio-resampler/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libaudio-resampler",
diff --git a/media/libaudioprocessing/include/media/AudioResamplerPublic.h b/media/libaudioprocessing/include/media/AudioResamplerPublic.h
index 1b39067..200a4c8 100644
--- a/media/libaudioprocessing/include/media/AudioResamplerPublic.h
+++ b/media/libaudioprocessing/include/media/AudioResamplerPublic.h
@@ -59,7 +59,7 @@
static inline bool isAudioPlaybackRateValid(const AudioPlaybackRate &playbackRate) {
if (playbackRate.mFallbackMode == AUDIO_TIMESTRETCH_FALLBACK_FAIL &&
- (playbackRate.mStretchMode == AUDIO_TIMESTRETCH_STRETCH_SPEECH ||
+ (playbackRate.mStretchMode == AUDIO_TIMESTRETCH_STRETCH_VOICE ||
playbackRate.mStretchMode == AUDIO_TIMESTRETCH_STRETCH_DEFAULT)) {
//test sonic specific constraints
return playbackRate.mSpeed >= TIMESTRETCH_SONIC_SPEED_MIN &&
diff --git a/media/libaudioprocessing/tests/Android.bp b/media/libaudioprocessing/tests/Android.bp
index 18acef7..3856817 100644
--- a/media/libaudioprocessing/tests/Android.bp
+++ b/media/libaudioprocessing/tests/Android.bp
@@ -1,5 +1,14 @@
// Build the unit tests for libaudioprocessing
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libaudioprocessing_test_defaults",
diff --git a/media/libaudioprocessing/tests/fuzzer/Android.bp b/media/libaudioprocessing/tests/fuzzer/Android.bp
index 2a0dec4..8fb6fff 100644
--- a/media/libaudioprocessing/tests/fuzzer/Android.bp
+++ b/media/libaudioprocessing/tests/fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_fuzz {
name: "libaudioprocessing_resampler_fuzzer",
srcs: [
diff --git a/media/libaudioprocessing/tests/test-mixer.cpp b/media/libaudioprocessing/tests/test-mixer.cpp
index bc9d2a6..1bbb863 100644
--- a/media/libaudioprocessing/tests/test-mixer.cpp
+++ b/media/libaudioprocessing/tests/test-mixer.cpp
@@ -241,7 +241,8 @@
// set up the tracks.
for (size_t i = 0; i < providers.size(); ++i) {
//printf("track %d out of %d\n", i, providers.size());
- uint32_t channelMask = audio_channel_out_mask_from_count(providers[i].getNumChannels());
+ audio_channel_mask_t channelMask =
+ audio_channel_out_mask_from_count(providers[i].getNumChannels());
const int name = i;
const status_t status = mixer->create(
name, channelMask, formats[i], AUDIO_SESSION_OUTPUT_MIX);
diff --git a/media/libcpustats/Android.bp b/media/libcpustats/Android.bp
index 6e8ca1d..1ab1de0 100644
--- a/media/libcpustats/Android.bp
+++ b/media/libcpustats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libcpustats",
diff --git a/media/libdatasource/Android.bp b/media/libdatasource/Android.bp
index f191c21..e0c6808 100644
--- a/media/libdatasource/Android.bp
+++ b/media/libdatasource/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libdatasource",
diff --git a/media/libeffects/config/Android.bp b/media/libeffects/config/Android.bp
index 8493e30..b02dcb6 100644
--- a/media/libeffects/config/Android.bp
+++ b/media/libeffects/config/Android.bp
@@ -1,4 +1,13 @@
// Effect configuration
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libeffectsconfig",
vendor_available: true,
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 26eaaf8..1696233 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -138,7 +138,7 @@
template <>
bool stringToStreamType(const char *streamName, audio_devices_t* type) {
- return deviceFromString(streamName, *type);
+ return DeviceConverter::fromString(streamName, *type);
}
/** Parse a library xml note and push the result in libraries or return false on failure. */
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index 2a2f36e..b40317f 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -1,4 +1,23 @@
// Multichannel downmix effect library
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_downmix_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libeffects_downmix_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libdownmix",
diff --git a/media/libeffects/downmix/tests/Android.bp b/media/libeffects/downmix/tests/Android.bp
index 63afc54..4077312 100644
--- a/media/libeffects/downmix/tests/Android.bp
+++ b/media/libeffects/downmix/tests/Android.bp
@@ -1,4 +1,15 @@
// Build testbench for downmix module.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libeffects_downmix_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_downmix_license",
+ ],
+}
+
cc_test {
name:"downmixtest",
host_supported: false,
diff --git a/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh b/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
index d0faebe..8aadfbf 100755
--- a/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
@@ -39,8 +39,7 @@
echo "testing Downmix"
adb shell mkdir $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw \
-$testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
adb push $OUT/testcases/downmixtest/arm64/downmixtest $testdir
#run the downmix test application for test.
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index eafc483..84131a4 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -13,6 +13,25 @@
// limitations under the License.
// DynamicsProcessing library
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_dynamicsproc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libeffects_dynamicsproc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libdynproc",
diff --git a/media/libeffects/factory/Android.bp b/media/libeffects/factory/Android.bp
index ddbfdd8..22838a3 100644
--- a/media/libeffects/factory/Android.bp
+++ b/media/libeffects/factory/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libeffects_headers",
vendor_available: true,
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index 5a13af6..bcd6947 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -1,4 +1,23 @@
// LoudnessEnhancer library
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_loudness_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libeffects_loudness_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libldnhncr",
diff --git a/media/libeffects/lvm/benchmarks/Android.bp b/media/libeffects/lvm/benchmarks/Android.bp
index 420e172..8a25b85 100644
--- a/media/libeffects/lvm/benchmarks/Android.bp
+++ b/media/libeffects/lvm/benchmarks/Android.bp
@@ -1,6 +1,16 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_benchmark {
name: "lvm_benchmark",
vendor: true,
+ host_supported: true,
srcs: ["lvm_benchmark.cpp"],
static_libs: [
"libbundlewrapper",
@@ -14,3 +24,25 @@
"libhardware_headers",
],
}
+
+cc_benchmark {
+ name: "reverb_benchmark",
+ vendor: true,
+ host_supported: true,
+ include_dirs: [
+ "frameworks/av/media/libeffects/lvm/wrapper/Reverb",
+ ],
+ srcs: ["reverb_benchmark.cpp"],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "liblog",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+}
diff --git a/media/libeffects/lvm/benchmarks/lvm_benchmark.cpp b/media/libeffects/lvm/benchmarks/lvm_benchmark.cpp
index ee9da3f..bdb66d8 100644
--- a/media/libeffects/lvm/benchmarks/lvm_benchmark.cpp
+++ b/media/libeffects/lvm/benchmarks/lvm_benchmark.cpp
@@ -41,15 +41,18 @@
constexpr size_t kFrameCount = 2048;
constexpr audio_channel_mask_t kChMasks[] = {
- AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO, AUDIO_CHANNEL_OUT_2POINT1,
- AUDIO_CHANNEL_OUT_QUAD, AUDIO_CHANNEL_OUT_PENTA, AUDIO_CHANNEL_OUT_5POINT1,
- AUDIO_CHANNEL_OUT_6POINT1, AUDIO_CHANNEL_OUT_7POINT1,
+ AUDIO_CHANNEL_INDEX_MASK_1, AUDIO_CHANNEL_INDEX_MASK_2, AUDIO_CHANNEL_INDEX_MASK_3,
+ AUDIO_CHANNEL_INDEX_MASK_4, AUDIO_CHANNEL_INDEX_MASK_5, AUDIO_CHANNEL_INDEX_MASK_6,
+ AUDIO_CHANNEL_INDEX_MASK_7, AUDIO_CHANNEL_INDEX_MASK_8, AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10, AUDIO_CHANNEL_INDEX_MASK_11, AUDIO_CHANNEL_INDEX_MASK_12,
+ AUDIO_CHANNEL_INDEX_MASK_13, AUDIO_CHANNEL_INDEX_MASK_14, AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16, AUDIO_CHANNEL_INDEX_MASK_17, AUDIO_CHANNEL_INDEX_MASK_18,
+ AUDIO_CHANNEL_INDEX_MASK_19, AUDIO_CHANNEL_INDEX_MASK_20, AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22, AUDIO_CHANNEL_INDEX_MASK_23, AUDIO_CHANNEL_INDEX_MASK_24,
};
constexpr size_t kNumChMasks = std::size(kChMasks);
constexpr int kSampleRate = 44100;
-// TODO(b/131240940) Remove once effects are updated to produce mono output
-constexpr size_t kMinOutputChannelCount = 2;
/*******************************************************************
* A test result running on Pixel 3 for comparison.
@@ -59,34 +62,102 @@
* -----------------------------------------------------
* Benchmark Time CPU Iterations
* -----------------------------------------------------
- * BM_LVM/2/0 131279 ns 130855 ns 5195
- * BM_LVM/2/1 184814 ns 184219 ns 3799
- * BM_LVM/2/2 91935 ns 91649 ns 7647
- * BM_LVM/2/3 26707 ns 26623 ns 26281
- * BM_LVM/3/0 172130 ns 171562 ns 4085
- * BM_LVM/3/1 192443 ns 191923 ns 3644
- * BM_LVM/3/2 127444 ns 127107 ns 5483
- * BM_LVM/3/3 26811 ns 26730 ns 26163
- * BM_LVM/4/0 223688 ns 223076 ns 3133
- * BM_LVM/4/1 204961 ns 204408 ns 3425
- * BM_LVM/4/2 169162 ns 168708 ns 4143
- * BM_LVM/4/3 37330 ns 37225 ns 18795
- * BM_LVM/5/0 272628 ns 271668 ns 2568
- * BM_LVM/5/1 218487 ns 217883 ns 3212
- * BM_LVM/5/2 211049 ns 210479 ns 3324
- * BM_LVM/5/3 46962 ns 46835 ns 15051
- * BM_LVM/6/0 318881 ns 317734 ns 2216
- * BM_LVM/6/1 231899 ns 231244 ns 3028
- * BM_LVM/6/2 252655 ns 251963 ns 2771
- * BM_LVM/6/3 54944 ns 54794 ns 12799
- * BM_LVM/7/0 366622 ns 365262 ns 1916
- * BM_LVM/7/1 245076 ns 244388 ns 2866
- * BM_LVM/7/2 295105 ns 294304 ns 2379
- * BM_LVM/7/3 63595 ns 63420 ns 11070
- * BM_LVM/8/0 410957 ns 409387 ns 1706
- * BM_LVM/8/1 257824 ns 257098 ns 2723
- * BM_LVM/8/2 342546 ns 341530 ns 2059
- * BM_LVM/8/3 72896 ns 72700 ns 9685
+ * BM_LVM/1/0 52123 ns 51971 ns 13437
+ * BM_LVM/1/1 75397 ns 75175 ns 9382
+ * BM_LVM/1/2 40253 ns 40140 ns 17418
+ * BM_LVM/1/3 19918 ns 19860 ns 35230
+ * BM_LVM/2/0 62455 ns 62283 ns 11214
+ * BM_LVM/2/1 110086 ns 109751 ns 6350
+ * BM_LVM/2/2 44017 ns 43890 ns 15982
+ * BM_LVM/2/3 21660 ns 21596 ns 32568
+ * BM_LVM/3/0 71925 ns 71698 ns 9745
+ * BM_LVM/3/1 117043 ns 116754 ns 6007
+ * BM_LVM/3/2 48899 ns 48781 ns 14334
+ * BM_LVM/3/3 23607 ns 23540 ns 29739
+ * BM_LVM/4/0 81296 ns 81095 ns 8632
+ * BM_LVM/4/1 122435 ns 122132 ns 5733
+ * BM_LVM/4/2 53744 ns 53612 ns 13068
+ * BM_LVM/4/3 25846 ns 25783 ns 27188
+ * BM_LVM/5/0 98557 ns 98311 ns 7120
+ * BM_LVM/5/1 131626 ns 131269 ns 5296
+ * BM_LVM/5/2 66892 ns 66732 ns 10458
+ * BM_LVM/5/3 31797 ns 31721 ns 22092
+ * BM_LVM/6/0 111880 ns 111596 ns 6278
+ * BM_LVM/6/1 140207 ns 139846 ns 5000
+ * BM_LVM/6/2 75683 ns 75496 ns 9253
+ * BM_LVM/6/3 37669 ns 37571 ns 18663
+ * BM_LVM/7/0 128265 ns 127957 ns 5470
+ * BM_LVM/7/1 149522 ns 149159 ns 4699
+ * BM_LVM/7/2 92024 ns 91798 ns 7631
+ * BM_LVM/7/3 43372 ns 43268 ns 16181
+ * BM_LVM/8/0 141897 ns 141548 ns 4945
+ * BM_LVM/8/1 158062 ns 157661 ns 4438
+ * BM_LVM/8/2 98042 ns 97801 ns 7151
+ * BM_LVM/8/3 49044 ns 48923 ns 14314
+ * BM_LVM/9/0 174692 ns 174228 ns 4026
+ * BM_LVM/9/1 183048 ns 182560 ns 3834
+ * BM_LVM/9/2 131020 ns 130675 ns 5347
+ * BM_LVM/9/3 71102 ns 70915 ns 9801
+ * BM_LVM/10/0 189079 ns 188576 ns 3699
+ * BM_LVM/10/1 187989 ns 187472 ns 3737
+ * BM_LVM/10/2 140093 ns 139717 ns 5007
+ * BM_LVM/10/3 78175 ns 77963 ns 8919
+ * BM_LVM/11/0 207577 ns 207007 ns 3371
+ * BM_LVM/11/1 198186 ns 197640 ns 3535
+ * BM_LVM/11/2 157214 ns 156786 ns 4459
+ * BM_LVM/11/3 85912 ns 85681 ns 8153
+ * BM_LVM/12/0 220861 ns 220265 ns 3169
+ * BM_LVM/12/1 208759 ns 208184 ns 3355
+ * BM_LVM/12/2 165533 ns 165088 ns 4234
+ * BM_LVM/12/3 92616 ns 92364 ns 7528
+ * BM_LVM/13/0 238573 ns 237920 ns 2945
+ * BM_LVM/13/1 219130 ns 218520 ns 3209
+ * BM_LVM/13/2 183193 ns 182692 ns 3830
+ * BM_LVM/13/3 100546 ns 100274 ns 7005
+ * BM_LVM/14/0 254820 ns 254135 ns 2748
+ * BM_LVM/14/1 230161 ns 229530 ns 3049
+ * BM_LVM/14/2 192195 ns 191671 ns 3635
+ * BM_LVM/14/3 107770 ns 107477 ns 6502
+ * BM_LVM/15/0 273695 ns 272954 ns 2531
+ * BM_LVM/15/1 240718 ns 240049 ns 2801
+ * BM_LVM/15/2 220914 ns 220309 ns 3191
+ * BM_LVM/15/3 124321 ns 123978 ns 5664
+ * BM_LVM/16/0 285769 ns 284969 ns 2459
+ * BM_LVM/16/1 251692 ns 250983 ns 2789
+ * BM_LVM/16/2 224554 ns 223917 ns 3132
+ * BM_LVM/16/3 122048 ns 121706 ns 5753
+ * BM_LVM/17/0 310027 ns 309154 ns 2266
+ * BM_LVM/17/1 262008 ns 261259 ns 2681
+ * BM_LVM/17/2 247530 ns 246827 ns 2842
+ * BM_LVM/17/3 129513 ns 129146 ns 5418
+ * BM_LVM/18/0 322755 ns 321844 ns 2173
+ * BM_LVM/18/1 263266 ns 262514 ns 2671
+ * BM_LVM/18/2 257606 ns 256875 ns 2731
+ * BM_LVM/18/3 136550 ns 136164 ns 5129
+ * BM_LVM/19/0 338551 ns 337591 ns 2069
+ * BM_LVM/19/1 275929 ns 275134 ns 2535
+ * BM_LVM/19/2 270331 ns 269554 ns 2596
+ * BM_LVM/19/3 144551 ns 144138 ns 4838
+ * BM_LVM/20/0 352633 ns 351617 ns 1993
+ * BM_LVM/20/1 286607 ns 285713 ns 2371
+ * BM_LVM/20/2 283541 ns 282689 ns 2407
+ * BM_LVM/20/3 152355 ns 151904 ns 4604
+ * BM_LVM/21/0 370557 ns 369456 ns 1889
+ * BM_LVM/21/1 298251 ns 297351 ns 2352
+ * BM_LVM/21/2 296806 ns 295917 ns 2364
+ * BM_LVM/21/3 160212 ns 159735 ns 4330
+ * BM_LVM/22/0 386431 ns 385224 ns 1826
+ * BM_LVM/22/1 308901 ns 307925 ns 2273
+ * BM_LVM/22/2 309077 ns 308140 ns 2274
+ * BM_LVM/22/3 167492 ns 166987 ns 4194
+ * BM_LVM/23/0 404455 ns 403218 ns 1729
+ * BM_LVM/23/1 322026 ns 321014 ns 2187
+ * BM_LVM/23/2 326616 ns 325623 ns 2152
+ * BM_LVM/23/3 175873 ns 175328 ns 4007
+ * BM_LVM/24/0 416949 ns 415676 ns 1684
+ * BM_LVM/24/1 329803 ns 328779 ns 2128
+ * BM_LVM/24/2 337648 ns 336626 ns 2080
+ * BM_LVM/24/3 183192 ns 182634 ns 3824
*******************************************************************/
static void BM_LVM(benchmark::State& state) {
@@ -134,7 +205,7 @@
// Run the test
for (auto _ : state) {
- std::vector<float> output(kFrameCount * std::max(channelCount, kMinOutputChannelCount));
+ std::vector<float> output(kFrameCount * channelCount);
benchmark::DoNotOptimize(input.data());
benchmark::DoNotOptimize(output.data());
@@ -155,8 +226,7 @@
}
static void LVMArgs(benchmark::internal::Benchmark* b) {
- // TODO(b/131240940) Test single channel once effects are updated to process mono data
- for (int i = 2; i <= kNumChMasks; i++) {
+ for (int i = FCC_1; i <= kNumChMasks; i++) {
for (int j = 0; j < kNumEffectUuids; ++j) {
b->Args({i, j});
}
diff --git a/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
new file mode 100644
index 0000000..00a7ff2
--- /dev/null
+++ b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <climits>
+#include <cstdlib>
+#include <random>
+#include <vector>
+#include <log/log.h>
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <system/audio.h>
+#include "EffectReverb.h"
+
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+constexpr effect_uuid_t kEffectUuids[] = {
+ {0x172cdf00,
+ 0xa3bc,
+ 0x11df,
+ 0xa72f,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-insert mode
+ {0xf29a1400,
+ 0xa3bb,
+ 0x11df,
+ 0x8ddc,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-aux mode
+};
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+constexpr size_t kFrameCount = 2048;
+
+constexpr int kPresets[] = {
+ REVERB_PRESET_NONE, REVERB_PRESET_SMALLROOM, REVERB_PRESET_MEDIUMROOM,
+ REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
+ REVERB_PRESET_PLATE,
+};
+
+constexpr size_t kNumPresets = std::size(kPresets);
+
+constexpr int kSampleRate = 44100;
+
+int reverbSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {paramType, paramValue};
+ auto effectParam = (effect_param_t*)malloc(sizeof(effect_param_t) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ effectParam->vsize = sizeof(paramData[1]);
+ int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + sizeof(paramData), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ if (status != 0) {
+ ALOGE("Reverb set config returned an error = %d\n", status);
+ return status;
+ }
+ return reply;
+}
+
+/*******************************************************************
+ * A test result running on Pixel 3 with for comparison.
+ * The first parameter indicates the preset level id.
+ * The second parameter indicates the effect.
+ * 0: preset-insert mode, 1: preset-aux mode
+ * --------------------------------------------------------
+ * Benchmark Time CPU Iterations
+ * --------------------------------------------------------
+ * BM_REVERB/0/0 19312 ns 19249 ns 36282
+ * BM_REVERB/0/1 5613 ns 5596 ns 125032
+ * BM_REVERB/1/0 605453 ns 603714 ns 1131
+ * BM_REVERB/1/1 589421 ns 587758 ns 1161
+ * BM_REVERB/2/0 605760 ns 604006 ns 1131
+ * BM_REVERB/2/1 589434 ns 587777 ns 1161
+ * BM_REVERB/3/0 605574 ns 603828 ns 1131
+ * BM_REVERB/3/1 589566 ns 587862 ns 1162
+ * BM_REVERB/4/0 605634 ns 603894 ns 1131
+ * BM_REVERB/4/1 589506 ns 587856 ns 1161
+ * BM_REVERB/5/0 605644 ns 603929 ns 1131
+ * BM_REVERB/5/1 589592 ns 587863 ns 1161
+ * BM_REVERB/6/0 610544 ns 608561 ns 1131
+ * BM_REVERB/6/1 589686 ns 587871 ns 1161
+ *******************************************************************/
+
+static void BM_REVERB(benchmark::State& state) {
+ const size_t chMask = AUDIO_CHANNEL_OUT_STEREO;
+ const size_t preset = kPresets[state.range(0)];
+ const effect_uuid_t uuid = kEffectUuids[state.range(1)];
+ const size_t channelCount = audio_channel_count_from_out_mask(chMask);
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::minstd_rand gen(chMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ std::vector<float> input(kFrameCount * channelCount);
+ std::vector<float> output(kFrameCount * channelCount);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+
+ effect_handle_t effectHandle = nullptr;
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&uuid, 1, 1, &effectHandle);
+ status != 0) {
+ ALOGE("create_effect returned an error = %d\n", status);
+ return;
+ }
+
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
+ config.inputCfg.channels = config.outputCfg.channels = chMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ status != 0) {
+ ALOGE("command returned an error = %d\n", status);
+ return;
+ }
+
+ if (int status =
+ (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ status != 0) {
+ ALOGE("Command enable call returned error %d\n", reply);
+ return;
+ }
+
+ if (int status = reverbSetConfigParam(REVERB_PARAM_PRESET, preset, effectHandle); status != 0) {
+ ALOGE("Invalid reverb preset. Error %d\n", status);
+ return;
+ }
+
+ // Run the test
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(input.data());
+ benchmark::DoNotOptimize(output.data());
+
+ audio_buffer_t inBuffer = {.frameCount = kFrameCount, .f32 = input.data()};
+ audio_buffer_t outBuffer = {.frameCount = kFrameCount, .f32 = output.data()};
+ (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+ benchmark::ClobberMemory();
+ }
+
+ state.SetComplexityN(state.range(0));
+
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
+ ALOGE("release_effect returned an error = %d\n", status);
+ return;
+ }
+}
+
+static void REVERBArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < kNumPresets; i++) {
+ for (int j = 0; j < kNumEffectUuids; ++j) {
+ b->Args({i, j});
+ }
+ }
+}
+
+BENCHMARK(BM_REVERB)->Apply(REVERBArgs);
+
+BENCHMARK_MAIN();
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 8f2f016..5d75055 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -1,4 +1,23 @@
// Music bundle
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_lvm_lib_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libeffects_lvm_lib_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libmusicbundle",
@@ -9,6 +28,7 @@
},
vendor: true,
+ host_supported: true,
srcs: [
"StereoWidening/src/LVCS_BypassMix.cpp",
"StereoWidening/src/LVCS_Control.cpp",
@@ -39,58 +59,21 @@
"Eq/src/LVEQNB_Init.cpp",
"Eq/src/LVEQNB_Process.cpp",
"Eq/src/LVEQNB_Tables.cpp",
- "Common/src/InstAlloc.cpp",
"Common/src/DC_2I_D16_TRC_WRA_01.cpp",
"Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp",
- "Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp",
- "Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp",
- "Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp",
- "Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp",
- "Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp",
- "Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp",
- "Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp",
- "Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp",
- "Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp",
- "Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp",
- "Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp",
- "Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp",
- "Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp",
- "Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp",
- "Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp",
- "Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp",
- "Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp",
- "Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp",
- "Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp",
- "Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp",
- "Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp",
- "Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp",
- "Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp",
- "Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp",
- "Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp",
- "Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp",
- "Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp",
- "Common/src/Int16LShiftToInt32_16x32.cpp",
- "Common/src/From2iToMono_16.cpp",
"Common/src/Copy_16.cpp",
- "Common/src/MonoTo2I_16.cpp",
"Common/src/MonoTo2I_32.cpp",
- "Common/src/LoadConst_16.cpp",
"Common/src/LoadConst_32.cpp",
"Common/src/dB_to_Lin32.cpp",
"Common/src/Shift_Sat_v16xv16.cpp",
"Common/src/Shift_Sat_v32xv32.cpp",
- "Common/src/Abs_32.cpp",
- "Common/src/Int32RShiftToInt16_Sat_32x16.cpp",
"Common/src/From2iToMono_32.cpp",
- "Common/src/mult3s_16x16.cpp",
"Common/src/Mult3s_32x16.cpp",
"Common/src/NonLinComp_D16.cpp",
"Common/src/DelayMix_16x16.cpp",
"Common/src/MSTo2i_Sat_16x16.cpp",
"Common/src/From2iToMS_16x16.cpp",
- "Common/src/Mac3s_Sat_16x16.cpp",
"Common/src/Mac3s_Sat_32x16.cpp",
- "Common/src/Add2_Sat_16x16.cpp",
"Common/src/Add2_Sat_32x32.cpp",
"Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp",
"Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp",
@@ -131,12 +114,14 @@
shared_libs: [
"liblog",
],
+ static_libs: [
+ "libaudioutils",
+ ],
header_libs: [
"libhardware_headers",
],
cppflags: [
"-fvisibility=hidden",
-
"-Wall",
"-Werror",
],
@@ -154,27 +139,20 @@
},
vendor: true,
+ host_supported: true,
srcs: [
"Reverb/src/LVREV_ApplyNewSettings.cpp",
"Reverb/src/LVREV_ClearAudioBuffers.cpp",
"Reverb/src/LVREV_GetControlParameters.cpp",
"Reverb/src/LVREV_GetInstanceHandle.cpp",
- "Reverb/src/LVREV_GetMemoryTable.cpp",
"Reverb/src/LVREV_Process.cpp",
"Reverb/src/LVREV_SetControlParameters.cpp",
"Reverb/src/LVREV_Tables.cpp",
- "Common/src/Abs_32.cpp",
- "Common/src/InstAlloc.cpp",
- "Common/src/LoadConst_16.cpp",
"Common/src/LoadConst_32.cpp",
"Common/src/From2iToMono_32.cpp",
"Common/src/Mult3s_32x16.cpp",
- "Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp",
- "Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp",
- "Common/src/DelayAllPass_Sat_32x16To32.cpp",
"Common/src/Copy_16.cpp",
"Common/src/Mac3s_Sat_32x16.cpp",
- "Common/src/DelayWrite_32.cpp",
"Common/src/Shift_Sat_v32xv32.cpp",
"Common/src/Add2_Sat_32x32.cpp",
"Common/src/JoinTo2i_32x32.cpp",
@@ -201,10 +179,11 @@
"Reverb/lib",
"Common/lib",
],
-
+ static_libs: [
+ "libaudioutils",
+ ],
cppflags: [
"-fvisibility=hidden",
-
"-Wall",
"-Werror",
],
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index 5b47aa6..9fe8116 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -21,6 +21,8 @@
/* */
/****************************************************************************************/
+#include <audio_utils/BiquadFilter.h>
+#include <system/audio.h>
#include "LVDBE.h"
#include "LVDBE_Private.h"
#include "VectorArithmetic.h"
@@ -107,22 +109,19 @@
/*
* Setup the high pass filter
*/
- LoadConst_Float(0, /* Clear the history, value 0 */
- (LVM_FLOAT*)&pInstance->pData->HPFTaps, /* Destination */
- sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
- BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
- &pInstance->pData->HPFTaps,
- (BQ_FLOAT_Coefs_t*)&LVDBE_HPF_Table[Offset]);
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVDBE_HPF_Table[Offset].A0, LVDBE_HPF_Table[Offset].A1, LVDBE_HPF_Table[Offset].A2,
+ -(LVDBE_HPF_Table[Offset].B1), -(LVDBE_HPF_Table[Offset].B2)};
+ pInstance->pHPFBiquad
+ ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
/*
* Setup the band pass filter
*/
- LoadConst_Float(0, /* Clear the history, value 0 */
- (LVM_FLOAT*)&pInstance->pData->BPFTaps, /* Destination */
- sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
- BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
- &pInstance->pData->BPFTaps,
- (BP_FLOAT_Coefs_t*)&LVDBE_BPF_Table[Offset]);
+ coefs = {LVDBE_BPF_Table[Offset].A0, 0.0, -(LVDBE_BPF_Table[Offset].A0),
+ -(LVDBE_BPF_Table[Offset].B1), -(LVDBE_BPF_Table[Offset].B2)};
+ pInstance->pBPFBiquad
+ ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
}
/************************************************************************************/
@@ -276,9 +275,17 @@
LVMixer3_2St_FLOAT_st* pBypassMixer_Instance = &pInstance->pData->BypassMixer;
/*
+ * Create biquad instance
+ */
+ if (pInstance->Params.NrChannels != pParams->NrChannels) {
+ pInstance->pHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels));
+ }
+ /*
* Update the filters
*/
if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.NrChannels != pParams->NrChannels) ||
(pInstance->Params.CentreFrequency != pParams->CentreFrequency)) {
LVDBE_SetFilters(pInstance, /* Instance pointer */
pParams); /* New parameters */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
index 12af162..b113f48 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
@@ -20,8 +20,9 @@
/* Includes */
/* */
/****************************************************************************************/
-#include <stdlib.h>
+#include <system/audio.h>
+#include <stdlib.h>
#include "LVDBE.h"
#include "LVDBE_Private.h"
@@ -56,10 +57,7 @@
* Create the instance handle if not already initialised
*/
if (*phInstance == LVM_NULL) {
- *phInstance = calloc(1, sizeof(*pInstance));
- }
- if (*phInstance == LVM_NULL) {
- return LVDBE_NULLADDRESS;
+ *phInstance = new LVDBE_Instance_t{};
}
pInstance = (LVDBE_Instance_t*)*phInstance;
@@ -81,6 +79,7 @@
pInstance->Params.SampleRate = LVDBE_FS_8000;
pInstance->Params.VolumeControl = LVDBE_VOLUME_OFF;
pInstance->Params.VolumedB = 0;
+ pInstance->Params.NrChannels = FCC_2;
/*
* Create pointer to data and coef memory
@@ -89,10 +88,12 @@
if (pInstance->pData == NULL) {
return LVDBE_NULLADDRESS;
}
- pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
- if (pInstance->pCoef == NULL) {
- return LVDBE_NULLADDRESS;
- }
+ /*
+ * Create biquad instance
+ */
+ pInstance->pHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(pInstance->Params.NrChannels));
+ pInstance->pBPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
/*
* Initialise the filters
@@ -182,10 +183,6 @@
free(pInstance->pData);
pInstance->pData = LVM_NULL;
}
- if (pInstance->pCoef != LVM_NULL) {
- free(pInstance->pCoef);
- pInstance->pCoef = LVM_NULL;
- }
- free(pInstance);
+ delete pInstance;
*phInstance = LVM_NULL;
}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 4fef1ef..7ac5db3 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -33,6 +33,7 @@
/* */
/****************************************************************************************/
+#include <audio_utils/BiquadFilter.h>
#include "LVDBE.h" /* Calling or Application layer definitions */
#include "BIQUAD.h"
#include "LVC_Mixer.h"
@@ -63,19 +64,12 @@
AGC_MIX_VOL_2St1Mon_FLOAT_t AGCInstance; /* AGC instance parameters */
/* Process variables */
- Biquad_2I_Order2_FLOAT_Taps_t HPFTaps; /* High pass filter taps */
- Biquad_1I_Order2_FLOAT_Taps_t BPFTaps; /* Band pass filter taps */
LVMixer3_1St_FLOAT_st BypassVolume; /* Bypass volume scaler */
LVMixer3_2St_FLOAT_st BypassMixer; /* Bypass Mixer for Click Removal */
} LVDBE_Data_FLOAT_t;
-/* Coefs structure */
-typedef struct {
- /* Process variables */
- Biquad_FLOAT_Instance_t HPFInstance; /* High pass filter instance */
- Biquad_FLOAT_Instance_t BPFInstance; /* Band pass filter instance */
-} LVDBE_Coef_FLOAT_t;
+
/* Instance structure */
typedef struct {
/* Public parameters */
@@ -84,8 +78,11 @@
/* Data and coefficient pointers */
LVDBE_Data_FLOAT_t* pData; /* Instance data */
- LVDBE_Coef_FLOAT_t* pCoef; /* Instance coefficients */
void* pScratch; /* scratch pointer */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pHPFBiquad; /* Biquad filter instance for HPF */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pBPFBiquad; /* Biquad filter instance for BPF */
} LVDBE_Instance_t;
/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
index f4a4d6f..0969053 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -20,6 +20,7 @@
/* Includes */
/* */
/****************************************************************************************/
+#include <audio_utils/BiquadFilter.h>
#include <string.h> // memset
#include "LVDBE.h"
@@ -78,11 +79,7 @@
const LVM_UINT16 NrFrames) // updated to use samples = frames * channels.
{
LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
-
- /*Extract number of Channels info*/
- // Mono passed in as stereo
- const LVM_INT32 NrChannels =
- pInstance->Params.NrChannels == 1 ? 2 : pInstance->Params.NrChannels;
+ const LVM_INT32 NrChannels = pInstance->Params.NrChannels;
const LVM_INT32 NrSamples = NrChannels * NrFrames;
/* Space to store DBE path computation */
@@ -125,10 +122,7 @@
* Apply the high pass filter if selected
*/
if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
- BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
- pScratch, /* Source */
- pScratch, /* Destination */
- (LVM_INT16)NrFrames, (LVM_INT16)NrChannels);
+ pInstance->pHPFBiquad->process(pScratch, pScratch, NrFrames);
}
/*
@@ -142,10 +136,7 @@
/*
* Apply the band pass filter
*/
- BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
- pMono, /* Source */
- pMono, /* Destination */
- (LVM_INT16)NrFrames);
+ pInstance->pBPFBiquad->process(pMono, pMono, NrFrames);
/*
* Apply the AGC and mix
@@ -156,15 +147,6 @@
pScratch, /* Destination */
NrFrames, /* Number of frames */
NrChannels); /* Number of channels */
-
- for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
- // TODO: replace with existing clamping function
- if (pScratch[ii] < -1.0) {
- pScratch[ii] = -1.0;
- } else if (pScratch[ii] > 1.0) {
- pScratch[ii] = 1.0;
- }
- }
} else {
// clear DBE processed path
memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp
index fbb0fe1..1d913d7 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp
@@ -487,10 +487,6 @@
void LVM_BufferUnmanagedOut(LVM_Handle_t hInstance, LVM_UINT16* pNumSamples) {
LVM_Instance_t* pInstance = (LVM_Instance_t*)hInstance;
LVM_INT16 NumChannels = pInstance->NrChannels;
- if (NumChannels == 1) {
- /* Mono input is processed as stereo by LVM module */
- NumChannels = 2;
- }
#undef NrFrames
#define NrFrames (*pNumSamples) // alias for clarity
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
index 3118e77..b2a35d8 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
@@ -276,18 +276,14 @@
*/
Offset = (LVM_INT16)(EffectLevel - 1 +
TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
- FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
- &pInstance->pTE_Taps->TrebleBoost_Taps,
- &LVM_TrebleBoostCoefs[Offset]);
-
/*
- * Clear the taps
+ * Create biquad instance
*/
- LoadConst_Float((LVM_FLOAT)0, /* Value */
- (LVM_FLOAT*)&pInstance->pTE_Taps->TrebleBoost_Taps, /* Destination.\
- Cast to void: no dereferencing in function */
- (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) /
- sizeof(LVM_FLOAT))); /* Number of words */
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVM_TrebleBoostCoefs[Offset].A0, LVM_TrebleBoostCoefs[Offset].A1, 0.0,
+ -(LVM_TrebleBoostCoefs[Offset].B1), 0.0};
+ pInstance->pTEBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels, coefs));
}
} else {
/*
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
index bb962df..9f5f448 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
@@ -25,7 +25,6 @@
#include "LVM_Private.h"
#include "LVM_Tables.h"
#include "VectorArithmetic.h"
-#include "InstAlloc.h"
/****************************************************************************************/
/* */
@@ -93,10 +92,7 @@
/*
* Create the instance handle
*/
- *phInstance = (LVM_Handle_t)calloc(1, sizeof(*pInstance));
- if (*phInstance == LVM_NULL) {
- return LVM_NULLADDRESS;
- }
+ *phInstance = new LVM_Instance_t{};
pInstance = (LVM_Instance_t*)*phInstance;
pInstance->InstParams = *pInstParams;
@@ -174,14 +170,6 @@
/*
* Treble Enhancement
*/
- pInstance->pTE_Taps = (LVM_TE_Data_t*)calloc(1, sizeof(*(pInstance->pTE_Taps)));
- if (pInstance->pTE_Taps == LVM_NULL) {
- return LVM_NULLADDRESS;
- }
- pInstance->pTE_State = (LVM_TE_Coefs_t*)calloc(1, sizeof(*(pInstance->pTE_State)));
- if (pInstance->pTE_State == LVM_NULL) {
- return LVM_NULLADDRESS;
- }
pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
pInstance->Params.TE_EffectLevel = 0;
pInstance->TE_Active = LVM_FALSE;
@@ -494,14 +482,6 @@
/*
* Treble Enhancement
*/
- if (pInstance->pTE_Taps != LVM_NULL) {
- free(pInstance->pTE_Taps);
- pInstance->pTE_Taps = LVM_NULL;
- }
- if (pInstance->pTE_State != LVM_NULL) {
- free(pInstance->pTE_State);
- pInstance->pTE_State = LVM_NULL;
- }
/*
* Free the default EQNB pre-gain and pointer to the band definitions
@@ -559,7 +539,7 @@
pInstance->pPSAInput = LVM_NULL;
}
- free(*phInstance);
+ delete pInstance;
return;
}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 90a1f19..63c83c0 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -33,6 +33,7 @@
/* */
/************************************************************************************/
+#include <audio_utils/BiquadFilter.h>
#include "LVM.h" /* LifeVibes */
#include "LVM_Common.h" /* LifeVibes common */
#include "BIQUAD.h" /* Biquad library */
@@ -127,15 +128,6 @@
LVM_INT16 SamplesToOutput; /* Samples to write to the output */
} LVM_Buffer_t;
-/* Filter taps */
-typedef struct {
- Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps; /* Treble boost Taps */
-} LVM_TE_Data_t;
-
-/* Coefficients */
-typedef struct {
- Biquad_FLOAT_Instance_t TrebleBoost_State; /* State for the treble boost filter */
-} LVM_TE_Coefs_t;
typedef struct {
/* Public parameters */
@@ -185,8 +177,8 @@
LVM_INT16 VC_AVLFixedVolume; /* AVL fixed volume */
/* Treble Enhancement */
- LVM_TE_Data_t* pTE_Taps; /* Treble boost Taps */
- LVM_TE_Coefs_t* pTE_State; /* State for the treble boost filter */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pTEBiquad; /* Biquad filter instance */
LVM_INT16 TE_Active; /* Control flag */
/* Headroom */
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index c94c469..20058a1 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -111,19 +111,6 @@
}
/*
- * Convert from Mono if necessary
- */
- if (pInstance->Params.SourceFormat == LVM_MONO) {
- MonoTo2I_Float(pInData, /* Source */
- pOutData, /* Destination */
- (LVM_INT16)NumSamples); /* Number of input samples */
- pInput = pOutData;
- pToProcess = pOutData;
- NrChannels = 2;
- ChMask = AUDIO_CHANNEL_OUT_STEREO;
- }
-
- /*
* Process the data with managed buffers
*/
while (SampleCount != 0) {
@@ -190,9 +177,7 @@
/*
* Apply the filter
*/
- FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
- pProcessed, pProcessed, (LVM_INT16)NrFrames,
- (LVM_INT16)NrChannels);
+ pInstance->pTEBiquad->process(pProcessed, pProcessed, NrFrames);
}
/*
* Volume balance
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
index c20b49a..31c8200 100644
--- a/media/libeffects/lvm/lib/Common/lib/AGC.h
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -48,11 +48,6 @@
/* Function Prototypes */
/* */
/**********************************************************************************/
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
- const LVM_FLOAT* pStSrc, /* Stereo source */
- const LVM_FLOAT* pMonoSrc, /* Mono source */
- LVM_FLOAT* pDst, /* Stereo destination */
- LVM_UINT16 n); /* Number of samples */
void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
const LVM_FLOAT* pStSrc, /* Source */
const LVM_FLOAT* pMonoSrc, /* Mono source */
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
index b38e9fb..00b539a 100644
--- a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -72,131 +72,6 @@
LVM_FLOAT G; /* Gain */
} PK_FLOAT_Coefs_t;
-/**********************************************************************************
- TAPS TYPE DEFINITIONS
-***********************************************************************************/
-
-/*** Types used for first order and shelving filter *******************************/
-typedef struct {
- LVM_FLOAT Storage[(1 * 2)]; /* One channel, two taps of size LVM_INT32 */
-} Biquad_1I_Order1_FLOAT_Taps_t;
-
-typedef struct {
- /* LVM_MAX_CHANNELS channels, two taps of size LVM_FLOAT */
- LVM_FLOAT Storage[(LVM_MAX_CHANNELS * 2)];
-} Biquad_2I_Order1_FLOAT_Taps_t;
-
-/*** Types used for biquad, band pass and peaking filter **************************/
-typedef struct {
- LVM_FLOAT Storage[(1 * 4)]; /* One channel, four taps of size LVM_FLOAT */
-} Biquad_1I_Order2_FLOAT_Taps_t;
-
-typedef struct {
- /* LVM_MAX_CHANNELS, four taps of size LVM_FLOAT */
- LVM_FLOAT Storage[(LVM_MAX_CHANNELS * 4)];
-} Biquad_2I_Order2_FLOAT_Taps_t;
-/* The names of the functions are changed to satisfy QAC rules: Name should be Unique within 16
- * characters*/
-#define BQ_2I_D32F32Cll_TRC_WRA_01_Init Init_BQ_2I_D32F32Cll_TRC_WRA_01
-#define BP_1I_D32F32C30_TRC_WRA_02 TWO_BP_1I_D32F32C30_TRC_WRA_02
-
-/**********************************************************************************
- FUNCTION PROTOTYPES: BIQUAD FILTERS
-***********************************************************************************/
-
-/*** 16 bit data path *************************************************************/
-
-void BQ_2I_D16F32Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps, BQ_FLOAT_Coefs_t* pCoef);
-
-void BQ_2I_D16F32C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void BQ_2I_D16F32C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void BQ_2I_D16F32C13_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void BQ_2I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps, BQ_FLOAT_Coefs_t* pCoef);
-
-void BQ_2I_D16F16C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void BQ_2I_D16F16C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void BQ_1I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BQ_FLOAT_Coefs_t* pCoef);
-
-void BQ_1I_D16F16C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void BQ_1I_D16F32Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BQ_FLOAT_Coefs_t* pCoef);
-
-void BQ_1I_D16F32C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-/*** 32 bit data path *************************************************************/
-void BQ_2I_D32F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps, BQ_FLOAT_Coefs_t* pCoef);
-void BQ_2I_D32F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-void BQ_MC_D32F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-
-/**********************************************************************************
- FUNCTION PROTOTYPES: FIRST ORDER FILTERS
-***********************************************************************************/
-
-/*** 16 bit data path *************************************************************/
-void FO_1I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order1_FLOAT_Taps_t* pTaps, FO_FLOAT_Coefs_t* pCoef);
-
-void FO_1I_D16F16C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order1_FLOAT_Taps_t* pTaps,
- FO_FLOAT_LShx_Coefs_t* pCoef);
-
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-/*** 32 bit data path *************************************************************/
-void FO_1I_D32F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order1_FLOAT_Taps_t* pTaps, FO_FLOAT_Coefs_t* pCoef);
-void FO_1I_D32F32C31_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-/**********************************************************************************
- FUNCTION PROTOTYPES: BAND PASS FILTERS
-***********************************************************************************/
-
-/*** 16 bit data path *************************************************************/
-void BP_1I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
-void BP_1I_D16F16C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-void BP_1I_D16F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
-void BP_1I_D16F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-/*** 32 bit data path *************************************************************/
-void BP_1I_D32F32Cll_TRC_WRA_02_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
-void BP_1I_D32F32C30_TRC_WRA_02(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-
-/*** 32 bit data path STEREO ******************************************************/
-void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
- PK_FLOAT_Coefs_t* pCoef);
-void PK_2I_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
-void PK_Mc_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
/**********************************************************************************
FUNCTION PROTOTYPES: DC REMOVAL FILTERS
diff --git a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
deleted file mode 100644
index 17699ef..0000000
--- a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __INSTALLOC_H__
-#define __INSTALLOC_H__
-
-#include "LVM_Types.h"
-/*######################################################################################*/
-/* Type declarations */
-/*######################################################################################*/
-typedef struct {
- LVM_UINT32 TotalSize; /* Accumulative total memory size */
- uintptr_t pNextMember; /* Pointer to the next instance member to be allocated */
-} INST_ALLOC;
-
-/*######################################################################################*/
-/* Function prototypes */
-/*######################################################################################*/
-
-/****************************************************************************************
- * Name : InstAlloc_Init()
- * Input : pms - Pointer to the INST_ALLOC instance
- StartAddr - Base address of the instance memory
- * Returns : Error code
- * Description : Initializes the instance distribution and memory size calculation function
- * Remarks :
- ****************************************************************************************/
-
-void InstAlloc_Init(INST_ALLOC* pms, void* StartAddr);
-
-/****************************************************************************************
- * Name : InstAlloc_AddMember()
- * Input : pms - Pointer to the INST_ALLOC instance
- Size - The size in bytes of the new added member
- * Returns : A pointer to the new added member
- * Description : Allocates space for a new member in the instance memory and returns
- a pointer to this new member. The start address of all members will
- be 32 bit alligned.
- * Remarks :
- ****************************************************************************************/
-
-void* InstAlloc_AddMember(INST_ALLOC* pms, LVM_UINT32 Size);
-
-/****************************************************************************************
- * Name : InstAlloc_GetTotal()
- * Input : pms - Pointer to the INST_ALLOC instance
- * Returns : The instance memory size
- * Description : This functions returns the calculated instance memory size
- * Remarks :
- ****************************************************************************************/
-
-LVM_UINT32 InstAlloc_GetTotal(INST_ALLOC* pms);
-
-void* InstAlloc_AddMemberAllRet(INST_ALLOC* pms, LVM_UINT32 Size[], void** ptr);
-
-void* InstAlloc_AddMemberAll(INST_ALLOC* pms, LVM_UINT32 Size[], LVM_MemoryTable_st* pMemoryTable);
-
-void InstAlloc_InitAll(INST_ALLOC* pms, LVM_MemoryTable_st* pMemoryTable);
-
-void InstAlloc_InitAll_NULL(INST_ALLOC* pms);
-
-#endif /* __JBS_INSTALLOC_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index fb797be..7cfaf27 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -26,7 +26,7 @@
#define LVM_TYPES_H
#include <stdint.h>
-
+#include <system/audio.h>
/****************************************************************************************/
/* */
/* definitions */
@@ -82,7 +82,7 @@
#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
typedef float effect_buffer_t;
-#define LVM_MAX_CHANNELS 8 // FCC_8
+#define LVM_MAX_CHANNELS FCC_24
/****************************************************************************************/
/* */
@@ -121,26 +121,18 @@
LVM_FS_DUMMY = LVM_MAXENUM
} LVM_Fs_en;
-/* Memory Types */
-typedef enum {
- LVM_PERSISTENT_SLOW_DATA = LVM_MEMREGION_PERSISTENT_SLOW_DATA,
- LVM_PERSISTENT_FAST_DATA = LVM_MEMREGION_PERSISTENT_FAST_DATA,
- LVM_PERSISTENT_FAST_COEF = LVM_MEMREGION_PERSISTENT_FAST_COEF,
- LVM_TEMPORARY_FAST = LVM_MEMREGION_TEMPORARY_FAST,
- LVM_MEMORYTYPE_DUMMY = LVM_MAXENUM
-} LVM_MemoryTypes_en;
-
-/* Memory region definition */
-typedef struct {
- LVM_UINT32 Size; /* Region size in bytes */
- LVM_MemoryTypes_en Type; /* Region type */
- void* pBaseAddress; /* Pointer to the region base address */
-} LVM_MemoryRegion_st;
-
-/* Memory table containing the region definitions */
-typedef struct {
- LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */
-} LVM_MemoryTable_st;
+static inline LVM_Fs_en lvmFsForSampleRate(int sampleRate) {
+ static const std::map<int, LVM_Fs_en> kLVMFsMap = {
+ {8000, LVM_FS_8000}, {11025, LVM_FS_11025}, {12000, LVM_FS_12000},
+ {16000, LVM_FS_16000}, {22050, LVM_FS_22050}, {24000, LVM_FS_24000},
+ {32000, LVM_FS_32000}, {44100, LVM_FS_44100}, {48000, LVM_FS_48000},
+ {88200, LVM_FS_88200}, {96000, LVM_FS_96000}, {176400, LVM_FS_176400},
+ {192000, LVM_FS_192000}};
+ if (kLVMFsMap.find(sampleRate) != kLVMFsMap.end()) {
+ return kLVMFsMap.at(sampleRate);
+ }
+ return LVM_FS_INVALID;
+}
/****************************************************************************************/
/* */
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
index 04b180c..36c4cd2 100644
--- a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -21,7 +21,7 @@
/*######################################################################################*/
/* Include files */
/*######################################################################################*/
-
+#include <math.h>
#include "LVM_Types.h"
/*######################################################################################*/
@@ -30,7 +30,13 @@
/* Absolute value including the corner case for the extreme negative value */
-LVM_FLOAT Abs_Float(LVM_FLOAT input);
+static inline LVM_FLOAT Abs_Float(LVM_FLOAT input) {
+ return fabs(input);
+}
+
+static inline LVM_FLOAT LVM_Clamp(LVM_FLOAT val) {
+ return fmin(fmax(val, -1.0f), 1.0f);
+}
/****************************************************************************************
* Name : dB_to_Lin32()
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
index 66e3e79..18de85b 100644
--- a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -29,48 +29,20 @@
void Copy_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n);
void Copy_Float_Mc_Stereo(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 NrFrames,
LVM_INT32 NrChannels);
-void Copy_Float_Stereo_Mc(const LVM_FLOAT* src, LVM_FLOAT* StereoOut, LVM_FLOAT* dst,
+void Copy_Float_Stereo_Mc(const LVM_FLOAT* src, const LVM_FLOAT* StereoOut, LVM_FLOAT* dst,
LVM_INT16 NrFrames, LVM_INT32 NrChannels);
-/*********************************************************************************
- * note: In Mult3s_16x16() saturation of result is not taken care when *
- * overflow occurs. *
- * For example when *src = 0x8000, val = *0x8000 *
- * The function gives the output as 0x8000 instead of 0x7fff *
- * This is the only case which will give wrong result. *
- * For more information refer to Vector_Arithmetic.doc in /doc folder *
- *********************************************************************************/
void Mult3s_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n);
-/*********************************************************************************
- * note: In Mult3s_32x16() saturation of result is not taken care when *
- * overflow occurs. *
- * For example when *src = 0x8000000, val = *0x8000 *
- * The function gives the output as 0x8000000 instead of 0x7fffffff *
- * This is the only extreme condition which is giving unexpected result *
- * For more information refer to Vector_Arithmetic.doc in /doc folder *
- *********************************************************************************/
-void Mult3s_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n);
-void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
- LVM_FLOAT* delay, /* Delay buffer */
- LVM_INT16 size, /* Delay size */
- LVM_FLOAT* dst, /* Source/destination */
- LVM_INT16* pOffset, /* Delay offset */
- LVM_INT16 n); /* Number of stereo samples */
-void DelayWrite_32(const LVM_INT32* src, /* Source 1, to be delayed */
- LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_UINT16* pOffset, /* Delay offset */
- LVM_INT16 n);
+void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
+ LVM_FLOAT* delay, /* Delay buffer */
+ LVM_INT16 size, /* Delay size */
+ LVM_FLOAT* dst, /* Source/destination */
+ LVM_INT16* pOffset, /* Delay offset */
+ LVM_INT16 n, /* Number of stereo samples */
+ LVM_INT32 NrChannels); /* Number of channels */
void Add2_Sat_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n);
void Mac3s_Sat_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n);
-void DelayAllPass_Sat_32x16To32(LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_INT16 coeff, /* All pass filter coefficient */
- LVM_UINT16 DelayOffset, /* Simple delay offset */
- LVM_UINT16* pAllPassOffset, /* All pass filter delay offset */
- LVM_INT32* dst, /* Source/destination */
- LVM_INT16 n);
/**********************************************************************************
SHIFT FUNCTIONS
@@ -87,15 +59,6 @@
void From2iToMS_Float(const LVM_FLOAT* src, LVM_FLOAT* dstM, LVM_FLOAT* dstS, LVM_INT16 n);
void JoinTo2i_Float(const LVM_FLOAT* srcL, const LVM_FLOAT* srcR, LVM_FLOAT* dst, LVM_INT16 n);
-/**********************************************************************************
- DATA TYPE CONVERSION FUNCTIONS
-***********************************************************************************/
-
-void Int16LShiftToInt32_16x32(const LVM_INT16* src, LVM_INT32* dst, LVM_INT16 n, LVM_INT16 shift);
-
-void Int32RShiftToInt16_Sat_32x16(const LVM_INT32* src, LVM_INT16* dst, LVM_INT16 n,
- LVM_INT16 shift);
-
/**********************************************************************************/
#endif /* _VECTOR_ARITHMETIC_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
index ae8cdad..78f329e 100644
--- a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
@@ -20,7 +20,6 @@
/* Includes */
/* */
/****************************************************************************************/
-
#include "AGC.h"
#include "ScalarArithmetic.h"
@@ -37,135 +36,6 @@
/****************************************************************************************/
/* */
-/* FUNCTION: AGC_MIX_VOL_2St1Mon_D32_WRA */
-/* */
-/* DESCRIPTION: */
-/* Apply AGC and mix signals */
-/* */
-/* */
-/* StSrc ------------------| */
-/* | */
-/* ______ _|_ ________ */
-/* | | | | | | */
-/* MonoSrc -->| AGC |---->| + |----->| Volume |------------------------------+---> */
-/* | Gain | |___| | Gain | | */
-/* |______| |________| | */
-/* /|\ __________ ________ | */
-/* | | | | | | */
-/* |-------------------------------| AGC Gain |<--| Peak |<--| */
-/* | Update | | Detect | */
-/* |__________| |________| */
-/* */
-/* */
-/* PARAMETERS: */
-/* pInstance Instance pointer */
-/* pStereoIn Stereo source */
-/* pMonoIn Mono band pass source */
-/* pStereoOut Stereo destination */
-/* */
-/* RETURNS: */
-/* Void */
-/* */
-/* NOTES: */
-/* */
-/****************************************************************************************/
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
- const LVM_FLOAT* pStSrc, /* Stereo source */
- const LVM_FLOAT* pMonoSrc, /* Mono source */
- LVM_FLOAT* pDst, /* Stereo destination */
- LVM_UINT16 NumSamples) /* Number of samples */
-{
- /*
- * General variables
- */
- LVM_UINT16 i; /* Sample index */
- LVM_FLOAT Left; /* Left sample */
- LVM_FLOAT Right; /* Right sample */
- LVM_FLOAT Mono; /* Mono sample */
- LVM_FLOAT AbsPeak; /* Absolute peak signal */
- LVM_FLOAT AGC_Mult; /* Short AGC gain */
- LVM_FLOAT Vol_Mult; /* Short volume */
-
- /*
- * Instance control variables
- */
- LVM_FLOAT AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */
- LVM_FLOAT AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */
- LVM_FLOAT AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */
- LVM_FLOAT AGC_Decay = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT))); /* Decay scaler */
- LVM_FLOAT AGC_Target = pInstance->AGC_Target; /* Get the target level */
- LVM_FLOAT Vol_Current = pInstance->Volume; /* Actual volume setting */
- LVM_FLOAT Vol_Target = pInstance->Target; /* Target volume setting */
- LVM_FLOAT Vol_TC = pInstance->VolumeTC; /* Time constant */
-
- /*
- * Process on a sample by sample basis
- */
- for (i = 0; i < NumSamples; i++) /* For each sample */
- {
- /*
- * Get the short scalers
- */
- AGC_Mult = (LVM_FLOAT)(AGC_Gain); /* Get the short AGC gain */
- Vol_Mult = (LVM_FLOAT)(Vol_Current); /* Get the short volume gain */
-
- /*
- * Get the input samples
- */
- Left = *pStSrc++; /* Get the left sample */
- Right = *pStSrc++; /* Get the right sample */
- Mono = *pMonoSrc++; /* Get the mono sample */
-
- /*
- * Apply the AGC gain to the mono input and mix with the stereo signal
- */
- Left += (Mono * AGC_Mult); /* Mix in the mono signal */
- Right += (Mono * AGC_Mult);
-
- /*
- * Apply the volume and write to the output stream
- */
- Left = Left * Vol_Mult;
- Right = Right * Vol_Mult;
- *pDst++ = Left; /* Save the results */
- *pDst++ = Right;
-
- /*
- * Update the AGC gain
- */
- AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
- if (AbsPeak > AGC_Target) {
- /*
- * The signal is too large so decrease the gain
- */
- AGC_Gain = AGC_Gain * AGC_Attack;
- } else {
- /*
- * The signal is too small so increase the gain
- */
- if (AGC_Gain > AGC_MaxGain) {
- AGC_Gain -= (AGC_Decay);
- } else {
- AGC_Gain += (AGC_Decay);
- }
- }
-
- /*
- * Update the gain
- */
- Vol_Current += (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
- }
-
- /*
- * Update the parameters
- */
- pInstance->Volume = Vol_Current; /* Actual volume setting */
- pInstance->AGC_Gain = AGC_Gain;
-
- return;
-}
-/****************************************************************************************/
-/* */
/* FUNCTION: AGC_MIX_VOL_Mc1Mon_D32_WRA */
/* */
/* DESCRIPTION: */
@@ -255,7 +125,7 @@
*/
SampleVal = SampleVal * Vol_Mult;
- *pDst++ = SampleVal; /* Save the results */
+ *pDst++ = LVM_Clamp(SampleVal); /* Save the results */
/*
* Update the AGC gain
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp b/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
deleted file mode 100644
index 3e37d89..0000000
--- a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*######################################################################################*/
-/* Include files */
-/*######################################################################################*/
-
-#include "ScalarArithmetic.h"
-
-/****************************************************************************************
- * Name : Abs_32()
- * Input : Signed 32-bit integer
- * Output :
- * Returns : Absolute value
- * Description : Absolute value with maximum negative value corner case
- * Remarks :
- ****************************************************************************************/
-
-LVM_INT32 Abs_32(LVM_INT32 input) {
- if (input < 0) {
- if (input == (LVM_INT32)(0x80000000U)) {
- /* The corner case, so set to the maximum positive value */
- input = (LVM_INT32)0x7fffffff;
- } else {
- /* Negative input, so invert */
- input = (LVM_INT32)(-input);
- }
- }
- return input;
-}
-LVM_FLOAT Abs_Float(LVM_FLOAT input) {
- if (input < 0) {
- /* Negative input, so invert */
- input = (LVM_FLOAT)(-input);
- }
- return input;
-}
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
deleted file mode 100644
index be20521..0000000
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION ADD2_SAT_16X16
-***********************************************************************************/
-
-void Add2_Sat_16x16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT32 Temp;
- LVM_INT16 ii;
- for (ii = n; ii != 0; ii--) {
- Temp = ((LVM_INT32)*src) + ((LVM_INT32)*dst);
- src++;
-
- if (Temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (Temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)Temp;
- }
- dst++;
- }
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
index 420f93e..1981edd 100644
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
@@ -18,53 +18,15 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include "ScalarArithmetic.h"
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION ADD2_SAT_32X32
-***********************************************************************************/
-
-void Add2_Sat_32x32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT32 a, b, c;
- LVM_INT16 ii;
- for (ii = n; ii != 0; ii--) {
- a = *src;
- src++;
-
- b = *dst;
- c = a + b;
- if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
- {
- if (a < 0) {
- c = 0x80000000L;
- } else {
- c = 0x7FFFFFFFL;
- }
- }
-
- *dst = c;
- dst++;
- }
- return;
-}
-
void Add2_Sat_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_FLOAT Temp;
LVM_INT16 ii;
for (ii = n; ii != 0; ii--) {
- Temp = ((LVM_FLOAT)*src) + ((LVM_FLOAT)*dst);
- src++;
-
- if (Temp > 1.000000f) {
- *dst = 1.000000f;
- } else if (Temp < -1.000000f) {
- *dst = -1.000000f;
- } else {
- *dst = Temp;
- }
- dst++;
+ Temp = *src++ + *dst;
+ *dst++ = LVM_Clamp(Temp);
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
deleted file mode 100644
index 198a6a1..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q0 format
- pBiquadState->pDelays[3] is y(n-2)L in Q0 format
-***************************************************************************/
-void BP_1I_D16F16C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples)
-
-{
- LVM_FLOAT ynL;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL= (A0 * (x(n)L - x(n-2)L ) )
- ynL = pBiquadState->coefs[0] * ((*pDataIn) - pBiquadState->pDelays[1]);
-
- // ynL+= ((-B2 * y(n-2)L ) )
- ynL += pBiquadState->coefs[1] * pBiquadState->pDelays[3];
-
- // ynL+= ((-B1 * y(n-1)L ) )
- ynL += pBiquadState->coefs[2] * pBiquadState->pDelays[2];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = ynL; // Write Left output
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
deleted file mode 100644
index 6d36302..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BP_1I_D16F16Css_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BP_1I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps,
- BP_FLOAT_Coefs_t* pCoef) {
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- pBiquadState->coefs[0] = pCoef->A0;
- pBiquadState->coefs[1] = pCoef->B2;
- pBiquadState->coefs[2] = pCoef->B1;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
deleted file mode 100644
index a41c855..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-#define _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[3]; /* pointer to the filter coefficients */
-} Filter_State_FLOAT;
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-#endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
deleted file mode 100644
index d4d4eb1..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q30 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q16 format
- pBiquadState->pDelays[3] is y(n-2)L in Q16 format
-***************************************************************************/
-void BP_1I_D16F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, templ;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL= (A0 * (x(n)L - x(n-2)L ))
- templ = (LVM_FLOAT)*pDataIn - pBiquadState->pDelays[1];
- ynL = pBiquadState->coefs[0] * templ;
-
- // ynL+= ((-B2 * y(n-2)L ) )
- templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
- ynL += templ;
-
- // ynL+= ((-B1 * y(n-1)L ))
- templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
- ynL += templ;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[2] = ynL; // Update y(n-1)L in Q16
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L in Q0
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (ynL); // Write Left output
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
deleted file mode 100644
index d322a8e..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BP_1I_D16F32Cll_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a Band pass filter (BIQUAD) */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* */
-/* The coefficients are modified in the init() function such that lower */
-/* half word is right shifted by one and most significant bit of the lower */
-/* word is made to be zero. */
-/* */
-/* Reason: For MIPS effciency,we are using DSP 32*16 multiplication */
-/* instruction. But we have 32*32 multiplication. This can be realized by two 32*16 */
-/* multiplication. But 16th bit in the 32 bit word is not a sign bit. So this is done */
-/* by putting 16th bit to zero and lossing one bit precision by division of lower */
-/* half word by 2. */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BP_1I_D16F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps,
- BP_FLOAT_Coefs_t* pCoef) {
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- pBiquadState->coefs[0] = pCoef->A0;
- pBiquadState->coefs[1] = pCoef->B2;
- pBiquadState->coefs[2] = pCoef->B1;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
deleted file mode 100644
index 0603256..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
-#define _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[3]; /* pointer to the filter coefficients */
-} Filter_State_Float;
-typedef Filter_State_Float* PFilter_State_FLOAT;
-#endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
deleted file mode 100644
index 0670334..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q30 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q0 format
- pBiquadState->pDelays[3] is y(n-2)L in Q0 format
-***************************************************************************/
-void BP_1I_D32F32C30_TRC_WRA_02(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, templ;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL= (A0 * (x(n)L - x(n-2)L ) )
- templ = (*pDataIn) - pBiquadState->pDelays[1];
- ynL = pBiquadState->coefs[0] * templ;
-
- // ynL+= ((-B2 * y(n-2)L ) )
- templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
- ynL += templ;
-
- // ynL+= ((-B1 * y(n-1)L ) )
- templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
- ynL += templ;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = ynL; // Write Left output in Q0
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
deleted file mode 100644
index 146cc63..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BP_1I_D32F32Cll_TRC_WRA_02_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BP_1I_D32F32Cll_TRC_WRA_02_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps,
- BP_FLOAT_Coefs_t* pCoef) {
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- pBiquadState->coefs[0] = pCoef->A0;
-
- pBiquadState->coefs[1] = pCoef->B2;
-
- pBiquadState->coefs[2] = pCoef->B1;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
deleted file mode 100644
index ea83c0b..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
-#define _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[3]; /* pointer to the filter coefficients */
-} Filter_State_Float;
-typedef Filter_State_Float* PFilter_State_FLOAT;
-
-#endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
deleted file mode 100644
index a46b1ef..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q0 format
- pBiquadState->pDelays[3] is y(n-2)L in Q0 format
-***************************************************************************/
-void BQ_1I_D16F16C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL=A2 * x(n-2)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
-
- // ynL+=A1 * x(n-1)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- // ynL+= (-B2 * y(n-2)L )
- ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[3];
-
- // ynL+= (-B1 * y(n-1)L )
- ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[2];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
deleted file mode 100644
index e8bfcd8..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BQ_1I_D16F16Css_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BQ_1I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps,
- BQ_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
- temp = pCoef->A2;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A1;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[2] = temp;
- temp = pCoef->B2;
- pBiquadState->coefs[3] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[4] = temp;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
deleted file mode 100644
index ac2819e..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-#define _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[5]; /* pointer to the filter coefficients */
-
-} Filter_State_FLOAT;
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-#endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
deleted file mode 100644
index c60dcf8..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q16 format
- pBiquadState->pDelays[3] is y(n-2)L in Q16 format
-***************************************************************************/
-void BQ_1I_D16F32C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL=A2 * x(n-2)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
-
- // ynL+=A1 * x(n-1)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- // ynL+= ( (-B2 * y(n-2)L )
- ynL += pBiquadState->pDelays[3] * pBiquadState->coefs[3];
-
- // ynL+= -B1 * y(n-1)L
- ynL += pBiquadState->pDelays[2] * pBiquadState->coefs[4];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (LVM_FLOAT)(ynL); // Write Left output
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
deleted file mode 100644
index af0efc8..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
-#define _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[5]; /* pointer to the filter coefficients */
-
-} Filter_State_FLOAT;
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-#endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
deleted file mode 100644
index ecf44ca..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BQ_1I_D16F32Css_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BQ_1I_D16F32Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order2_FLOAT_Taps_t* pTaps,
- BQ_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- temp = pCoef->A2;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A1;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[2] = temp;
- temp = pCoef->B2;
- pBiquadState->coefs[3] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[4] = temp;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
deleted file mode 100644
index d047e91..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-void BQ_2I_D16F16C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL=A2 * x(n-2)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- // ynL+=A1 * x(n-1)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- // ynL+= ( -B2 * y(n-2)L )
- ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
-
- // ynL+=( -B1 * y(n-1)L )
- ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- // ynR=A2 * x(n-2)R
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
- // ynR+=A1 * x(n-1)R
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
- // ynR+=A0 * x(n)R
- ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn + 1));
-
- // ynR+= ( -B2 * y(n-2)R )
- ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
-
- // ynR+=( -B1 * y(n-1)R )
- ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; // y(n-2)R=y(n-1)R
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; // x(n-2)R=x(n-1)R
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[5] = ynR; // Update y(n-1)R
- pBiquadState->pDelays[4] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
- pBiquadState->pDelays[1] = (*pDataIn++); // Update x(n-1)R
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
- *pDataOut++ = (LVM_FLOAT)ynR; // Write Right output
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
deleted file mode 100644
index 399b5ec..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-void BQ_2I_D16F16C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL=A2 * x(n-2)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- // ynL+=A1 * x(n-1)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- // ynL+= ( -B2 * y(n-2)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
-
- // ynL+=( -B1 * y(n-1)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- // ynR=A2 * x(n-2)R
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
- // ynR+=A1 * x(n-1)R
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
- // ynR+=A0 * x(n)R
- ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn + 1));
-
- // ynR+= ( -B2 * y(n-2)R )
- ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
-
- // ynR+=( -B1 * y(n-1)R )
- ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; // y(n-2)R=y(n-1)R
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; // y(n-2)L=y(n-1)L
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; // x(n-2)R=x(n-1)R
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
- pBiquadState->pDelays[5] = ynR; // Update y(n-1)R
- pBiquadState->pDelays[4] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
- pBiquadState->pDelays[1] = (*pDataIn++); // Update x(n-1)R
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
- *pDataOut++ = (LVM_FLOAT)ynR; // Write Right output
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
deleted file mode 100644
index e0cd934..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BQ_2I_D16F16Css_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BQ_2I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
- BQ_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- temp = pCoef->A2;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A1;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[2] = temp;
- temp = pCoef->B2;
- pBiquadState->coefs[3] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[4] = temp;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
deleted file mode 100644
index 94cc794..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-#define _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[5]; /* pointer to the filter coefficients */
-
-} Filter_State_FLOAT;
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-
-#endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
deleted file mode 100644
index 3b7eb5e..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q13 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q16 format
- pBiquadState->pDelays[5] is y(n-1)R in Q16 format
- pBiquadState->pDelays[6] is y(n-2)L in Q16 format
- pBiquadState->pDelays[7] is y(n-2)R in Q16 format
-***************************************************************************/
-void BQ_2I_D16F32C13_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- /* ynL=A2 * x(n-2)L */
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- /* ynL+=A1* x(n-1)L */
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- /* ynL+=A0* x(n)L */
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- /* ynL+=-B2*y(n-2)L */
- ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
-
- /* ynL+=-B1*y(n-1)L */
- ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- /* ynR=A2 * x(n-2)R */
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
- /* ynR+=A1* x(n-1)R */
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
- /* ynR+=A0* x(n)R */
- ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn + 1));
-
- /* ynR+=-B2 * y(n-2)R */
- ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
-
- /* ynR+=-B1 * y(n-1)R */
- ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
- pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
- pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
- pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
- pDataIn++;
- pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
- pDataOut++;
- *pDataOut = (LVM_FLOAT)(ynR); /* Write Right output */
- pDataOut++;
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
deleted file mode 100644
index 8c43430..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q16 format
- pBiquadState->pDelays[5] is y(n-1)R in Q16 format
- pBiquadState->pDelays[6] is y(n-2)L in Q16 format
- pBiquadState->pDelays[7] is y(n-2)R in Q16 format
-***************************************************************************/
-void BQ_2I_D16F32C14_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- /* ynL=A2 * x(n-2)L */
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- /* ynL+=A1 * x(n-1)L */
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- /* ynL+=A0 * x(n)L */
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- /* ynL+= ( (-B2 * y(n-2)L ))*/
- ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
-
- /* ynL+=( (-B1 * y(n-1)L )) */
- ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- /* ynR=A2 * x(n-2)R */
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
- /* ynR+=A1 * x(n-1)R */
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
- /* ynR+=A0 * x(n)R */
- ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn + 1));
-
- /* ynR+= ( (-B2 * y(n-2)R ))*/
- ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
-
- /* ynR+=( (-B1 * y(n-1)R )) */
- ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
- pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
- pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
- pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
- pDataIn++;
- pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
- pDataOut++;
- *pDataOut = (LVM_FLOAT)(ynR); /* Write Right output */
- pDataOut++;
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
deleted file mode 100644
index 84fbadf..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q16 format
- pBiquadState->pDelays[5] is y(n-1)R in Q16 format
- pBiquadState->pDelays[6] is y(n-2)L in Q16 format
- pBiquadState->pDelays[7] is y(n-2)R in Q16 format
-***************************************************************************/
-void BQ_2I_D16F32C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- /* ynL=A2 * x(n-2)L */
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- /* ynL+=A1 * x(n-1)L */
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
- /* ynL+=A0 * x(n)L */
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
- /* ynL+= ( (-B2 * y(n-2)L ) */
- ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
-
- /* ynL+=( (-B1 * y(n-1)L )) */
- ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- /* ynR=A2 * x(n-2)R */
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
- /* ynR+=A1 * x(n-1)R */
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
- /* ynR+=A0 * x(n)R */
- ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn + 1));
-
- /* ynR+= ( (-B2 * y(n-2)R ) */
- ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
-
- /* ynR+=( (-B1 * y(n-1)R )) in Q15 */
- ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
- pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R*/
- pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L*/
- pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L*/
- pDataIn++;
- pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R*/
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output*/
- pDataOut++;
- *pDataOut = (LVM_FLOAT)(ynR); /* Write Right output*/
- pDataOut++;
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
deleted file mode 100644
index 1cc7618..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
-#define _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples \
- (data of 32 bits) */
- LVM_FLOAT coefs[5]; /* pointer to the filter coefficients */
-} Filter_State_FLOAT;
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-
-#endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
deleted file mode 100644
index 6817d9f..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BQ_2I_D16F32Css_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BQ_2I_D16F32Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
- BQ_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
- temp = pCoef->A2;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A1;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[2] = temp;
- temp = pCoef->B2;
- pBiquadState->coefs[3] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[4] = temp;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
deleted file mode 100644
index 4eeaaa8..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q30 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-void BQ_2I_D32F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples)
-
-{
- LVM_FLOAT ynL, ynR, templ, tempd;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- /* ynL= ( A2 * x(n-2)L ) */
- ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- /* ynL+= ( A1 * x(n-1)L )*/
- templ = pBiquadState->coefs[1] * pBiquadState->pDelays[0];
- ynL += templ;
-
- /* ynL+= ( A0 * x(n)L ) */
- templ = pBiquadState->coefs[2] * (*pDataIn);
- ynL += templ;
-
- /* ynL+= (-B2 * y(n-2)L ) */
- templ = pBiquadState->coefs[3] * pBiquadState->pDelays[6];
- ynL += templ;
-
- /* ynL+= (-B1 * y(n-1)L )*/
- templ = pBiquadState->coefs[4] * pBiquadState->pDelays[4];
- ynL += templ;
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- /* ynR= ( A2 * x(n-2)R ) */
- ynR = pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
- /* ynR+= ( A1 * x(n-1)R ) */
- templ = pBiquadState->coefs[1] * pBiquadState->pDelays[1];
- ynR += templ;
-
- /* ynR+= ( A0 * x(n)R ) */
- tempd = *(pDataIn + 1);
- templ = pBiquadState->coefs[2] * tempd;
- ynR += templ;
-
- /* ynR+= (-B2 * y(n-2)R ) */
- templ = pBiquadState->coefs[3] * pBiquadState->pDelays[7];
- ynR += templ;
-
- /* ynR+= (-B1 * y(n-1)R ) */
- templ = pBiquadState->coefs[4] * pBiquadState->pDelays[5];
- ynR += templ;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
- pBiquadState->pDelays[5] = (LVM_FLOAT)ynR; /* Update y(n-1)R */
- pBiquadState->pDelays[4] = (LVM_FLOAT)ynL; /* Update y(n-1)L */
- pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
- pDataIn++;
- pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = (LVM_FLOAT)ynL; /* Write Left output */
- pDataOut++;
- *pDataOut = (LVM_FLOAT)ynR; /* Write Right output */
- pDataOut++;
- }
-}
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1
-
- DELAYS-
- pBiquadState->pDelays[0] to
- pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
-
- pBiquadState->pDelays[NrChannels] to
- pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
-
- pBiquadState->pDelays[2*NrChannels] to
- pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
-
- pBiquadState->pDelays[3*NrChannels] to
- pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
-***************************************************************************/
-void BQ_MC_D32F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels)
-
-{
- LVM_FLOAT yn, temp;
- LVM_INT16 ii, jj;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrFrames; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING CHANNEL-WISE
- ***************************************************************************/
- for (jj = 0; jj < NrChannels; jj++) {
- /* yn= (A2 * x(n-2)) */
- yn = pBiquadState->coefs[0] * pBiquadState->pDelays[NrChannels + jj];
-
- /* yn+= (A1 * x(n-1)) */
- temp = pBiquadState->coefs[1] * pBiquadState->pDelays[jj];
- yn += temp;
-
- /* yn+= (A0 * x(n)) */
- temp = pBiquadState->coefs[2] * (*pDataIn);
- yn += temp;
-
- /* yn+= (-B2 * y(n-2)) */
- temp = pBiquadState->coefs[3] * pBiquadState->pDelays[NrChannels * 3 + jj];
- yn += temp;
-
- /* yn+= (-B1 * y(n-1)) */
- temp = pBiquadState->coefs[4] * pBiquadState->pDelays[NrChannels * 2 + jj];
- yn += temp;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[NrChannels * 3 + jj] =
- pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
- pBiquadState->pDelays[NrChannels * 1 + jj] =
- pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
- pBiquadState->pDelays[NrChannels * 2 + jj] = (LVM_FLOAT)yn; /* Update y(n-1)*/
- pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
- pDataIn++;
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = (LVM_FLOAT)yn; /* Write jj Channel output */
- pDataOut++;
- }
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
deleted file mode 100644
index 1e27391..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* BQ_2I_D32F32Cll_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void BQ_2I_D32F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
- BQ_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
- temp = pCoef->A2;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A1;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[2] = temp;
- temp = pCoef->B2;
- pBiquadState->coefs[3] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[4] = temp;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
deleted file mode 100644
index 4a2149d..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
-#define _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples \
- (data of 32 bits) */
- LVM_FLOAT coefs[5]; /* pointer to the filter coefficients */
-} Filter_State_FLOAT;
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-
-#endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
index 8887890..1fe7470 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
@@ -18,53 +18,11 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include <string.h>
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION COPY_16
-***********************************************************************************/
-
-void Copy_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- if (src > dst) {
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst++;
- src++;
- }
- } else {
- src += n - 1;
- dst += n - 1;
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
- src--;
- }
- }
-
- return;
-}
void Copy_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- if (src > dst) {
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst++;
- src++;
- }
- } else {
- src += n - 1;
- dst += n - 1;
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
- src--;
- }
- }
-
+ memmove(dst, src, n * sizeof(LVM_FLOAT));
return;
}
// Extract out the stereo channel pair from multichannel source.
@@ -93,25 +51,32 @@
}
// Merge a multichannel source with stereo contained in StereoOut, to dst.
-void Copy_Float_Stereo_Mc(const LVM_FLOAT* src, LVM_FLOAT* StereoOut, LVM_FLOAT* dst,
+void Copy_Float_Stereo_Mc(const LVM_FLOAT* src, const LVM_FLOAT* StereoOut, LVM_FLOAT* dst,
LVM_INT16 NrFrames, /* Number of frames*/
LVM_INT32 NrChannels) {
LVM_INT16 ii, jj;
- // pack dst with stereo information of StereoOut
- // together with the upper channels of src.
- StereoOut += 2 * (NrFrames - 1);
- dst += NrChannels * (NrFrames - 1);
- src += NrChannels * (NrFrames - 1);
- for (ii = NrFrames; ii != 0; ii--) {
- dst[1] = StereoOut[1];
- dst[0] = StereoOut[0]; // copy 1 before 0 is required for NrChannels == 3.
- for (jj = 2; jj < NrChannels; jj++) {
- dst[jj] = src[jj];
+ if (NrChannels >= FCC_2) {
+ // pack dst with stereo information of StereoOut
+ // together with the upper channels of src.
+ StereoOut += 2 * (NrFrames - 1);
+ dst += NrChannels * (NrFrames - 1);
+ src += NrChannels * (NrFrames - 1);
+
+ for (ii = NrFrames; ii != 0; ii--) {
+ dst[1] = StereoOut[1];
+ dst[0] = StereoOut[0]; // copy 1 before 0 is required for NrChannels == 3.
+ for (jj = FCC_2; jj < NrChannels; jj++) {
+ dst[jj] = src[jj];
+ }
+ dst -= NrChannels;
+ src -= NrChannels;
+ StereoOut -= 2;
}
- dst -= NrChannels;
- src -= NrChannels;
- StereoOut -= 2;
+ } else {
+ Copy_Float((const LVM_FLOAT*)StereoOut, /* Source */
+ (LVM_FLOAT*)dst, /* Destination */
+ (LVM_INT16)NrFrames); /* Number of frames */
}
}
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
index be9e49b..b7f4b55 100644
--- a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
@@ -18,9 +18,9 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "Mixer_private.h"
#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
/**********************************************************************************
FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
@@ -52,14 +52,7 @@
Temp2 = *dst;
Temp3 = Temp1 * (pInstance->Current);
- Temp1 = Temp2 + Temp3;
-
- if (Temp1 > 1.0f)
- Temp1 = 1.0f;
- else if (Temp1 < -1.0f)
- Temp1 = -1.0f;
-
- *dst++ = Temp1;
+ *dst++ = LVM_Clamp(Temp2 + Temp3);
}
}
@@ -72,13 +65,7 @@
Temp2 = *dst;
Temp3 = Temp1 * (pInstance->Current);
- Temp1 = Temp2 + Temp3;
-
- if (Temp1 > 1.0f)
- Temp1 = 1.0f;
- else if (Temp1 < -1.0f)
- Temp1 = -1.0f;
- *dst++ = Temp1;
+ *dst++ = LVM_Clamp(Temp2 + Temp3);
}
}
}
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
index 2861be6..6e859f4 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
@@ -14,51 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "BIQUAD.h"
#include "DC_2I_D16_TRC_WRA_01_Private.h"
#include "LVM_Macros.h"
-void DC_2I_D16_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT LeftDC, RightDC;
- LVM_FLOAT Diff;
- LVM_INT32 j;
- PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State)pInstance;
-
- LeftDC = pBiquadState->LeftDC;
- RightDC = pBiquadState->RightDC;
- for (j = NrSamples - 1; j >= 0; j--) {
- /* Subtract DC and saturate */
- Diff = *(pDataIn++) - (LeftDC);
- if (Diff > 1.0f) {
- Diff = 1.0f;
- } else if (Diff < -1.0f) {
- Diff = -1.0f;
- }
- *(pDataOut++) = (LVM_FLOAT)Diff;
- if (Diff < 0) {
- LeftDC -= DC_FLOAT_STEP;
- } else {
- LeftDC += DC_FLOAT_STEP;
- }
-
- /* Subtract DC an saturate */
- Diff = *(pDataIn++) - (RightDC);
- if (Diff > 1.0f) {
- Diff = 1.0f;
- } else if (Diff < -1.0f) {
- Diff = -1.0f;
- }
- *(pDataOut++) = (LVM_FLOAT)Diff;
- if (Diff < 0) {
- RightDC -= DC_FLOAT_STEP;
- } else {
- RightDC += DC_FLOAT_STEP;
- }
- }
- pBiquadState->LeftDC = LeftDC;
- pBiquadState->RightDC = RightDC;
-}
+#include "ScalarArithmetic.h"
/*
* FUNCTION: DC_Mc_D16_TRC_WRA_01
*
@@ -89,12 +48,7 @@
/* Subtract DC and saturate */
for (i = NrChannels - 1; i >= 0; i--) {
Diff = *(pDataIn++) - (ChDC[i]);
- if (Diff > 1.0f) {
- Diff = 1.0f;
- } else if (Diff < -1.0f) {
- Diff = -1.0f;
- }
- *(pDataOut++) = (LVM_FLOAT)Diff;
+ *(pDataOut++) = LVM_Clamp(Diff);
if (Diff < 0) {
ChDC[i] -= DC_FLOAT_STEP;
} else {
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
index 2828cb3..c16718c 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
@@ -17,11 +17,6 @@
#include "BIQUAD.h"
#include "DC_2I_D16_TRC_WRA_01_Private.h"
-void DC_2I_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance) {
- PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State)pInstance;
- pBiquadState->LeftDC = 0.0f;
- pBiquadState->RightDC = 0.0f;
-}
void DC_Mc_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance) {
PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc)pInstance;
LVM_INT32 i;
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
deleted file mode 100644
index 5daef59..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION DelayAllPass_32x32
-***********************************************************************************/
-
-void DelayAllPass_Sat_32x16To32(LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_INT16 coeff, /* All pass filter coefficient */
- LVM_UINT16 DelayOffset, /* Simple delay offset */
- LVM_UINT16* pAllPassOffset, /* All pass filter delay offset */
- LVM_INT32* dst, /* Source/destination */
- LVM_INT16 n) /* Number of samples */
-{
- LVM_INT16 i;
- LVM_UINT16 AllPassOffset = *pAllPassOffset;
- LVM_INT32 temp;
- LVM_INT32 a, b, c;
-
- for (i = 0; i < n; i++) {
- MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15) a = temp;
- b = delay[DelayOffset];
- DelayOffset++;
-
- c = a + b;
- if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
- {
- if (a < 0) {
- c = 0x80000000L;
- } else {
- c = 0x7FFFFFFFL;
- }
- }
- *dst = c;
- dst++;
-
- MUL32x16INTO32(c, -coeff, temp, 15) a = temp;
- b = delay[AllPassOffset];
- c = a + b;
- if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
- {
- if (a < 0) {
- c = 0x80000000L;
- } else {
- c = 0x7FFFFFFFL;
- }
- }
- delay[AllPassOffset] = c;
- AllPassOffset++;
-
- /* Make the delay buffer a circular buffer */
- if (DelayOffset >= size) {
- DelayOffset = 0;
- }
-
- if (AllPassOffset >= size) {
- AllPassOffset = 0;
- }
- }
-
- /* Update the offset */
- *pAllPassOffset = AllPassOffset;
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
index da75982..a346636 100644
--- a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
@@ -21,84 +21,55 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayMix_16x16(const LVM_INT16* src, /* Source 1, to be delayed */
- LVM_INT16* delay, /* Delay buffer */
- LVM_INT16 size, /* Delay size */
- LVM_INT16* dst, /* Source/destination */
- LVM_INT16* pOffset, /* Delay offset */
- LVM_INT16 n) /* Number of stereo samples */
-{
- LVM_INT16 i;
- LVM_INT16 Offset = *pOffset;
- LVM_INT16 temp;
-
- for (i = 0; i < n; i++) {
- /* Left channel */
- temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
- *dst = temp;
- dst++;
-
- delay[Offset] = *src;
- Offset++;
- src++;
-
- /* Right channel */
- temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
- *dst = temp;
- dst++;
-
- delay[Offset] = *src;
- Offset++;
- src++;
-
- /* Make the reverb delay buffer a circular buffer */
- if (Offset >= size) {
- Offset = 0;
- }
- }
-
- /* Update the offset */
- *pOffset = Offset;
-
- return;
-}
void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
LVM_FLOAT* delay, /* Delay buffer */
LVM_INT16 size, /* Delay size */
LVM_FLOAT* dst, /* Source/destination */
LVM_INT16* pOffset, /* Delay offset */
- LVM_INT16 n) /* Number of stereo samples */
+ LVM_INT16 n, /* Number of samples */
+ LVM_INT32 NrChannels) /* Number of channels */
{
LVM_INT16 i;
LVM_INT16 Offset = *pOffset;
LVM_FLOAT temp;
for (i = 0; i < n; i++) {
- /* Left channel */
- temp = (LVM_FLOAT)((LVM_FLOAT)(*dst + (LVM_FLOAT)delay[Offset]) / 2.0f);
- *dst = temp;
- dst++;
+ if (NrChannels == FCC_1) {
+ temp = (LVM_FLOAT)(*dst + (LVM_FLOAT)delay[Offset]) / 2.0f;
+ *dst = temp;
+ dst++;
- delay[Offset] = *src;
- Offset++;
- src++;
+ delay[Offset] = *src;
+ Offset++;
+ src++;
- /* Right channel */
- temp = (LVM_FLOAT)((LVM_FLOAT)(*dst - (LVM_FLOAT)delay[Offset]) / 2.0f);
- *dst = temp;
- dst++;
+ /* Make the reverb delay buffer a circular buffer */
+ if (Offset >= size) {
+ Offset = 0;
+ }
+ } else {
+ /* Left channel */
+ temp = (LVM_FLOAT)(*dst + (LVM_FLOAT)delay[Offset]) / 2.0f;
+ *dst = temp;
+ dst++;
- delay[Offset] = *src;
- Offset++;
- src++;
+ delay[Offset] = *src;
+ Offset++;
+ src++;
- /* Make the reverb delay buffer a circular buffer */
- if (Offset >= size) {
- Offset = 0;
+ /* Right channel */
+ temp = (LVM_FLOAT)(*dst - (LVM_FLOAT)delay[Offset]) / 2.0f;
+ *dst = temp;
+ dst++;
+
+ delay[Offset] = *src;
+ Offset++;
+ src++;
+
+ /* Make the reverb delay buffer a circular buffer */
+ if (Offset >= size) {
+ Offset = 0;
+ }
}
}
@@ -107,4 +78,3 @@
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
deleted file mode 100644
index 47cffbf..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayWrite_32(const LVM_INT32* src, /* Source 1, to be delayed */
- LVM_INT32* delay, /* Delay buffer */
- LVM_UINT16 size, /* Delay size */
- LVM_UINT16* pOffset, /* Delay offset */
- LVM_INT16 n) /* Number of samples */
-{
- LVM_INT16 i;
- LVM_INT16 Offset = (LVM_INT16)*pOffset;
-
- for (i = 0; i < n; i++) {
- delay[Offset] = *src;
- Offset++;
- src++;
-
- /* Make the delay buffer a circular buffer */
- if (Offset >= size) {
- Offset = 0;
- }
- }
-
- /* Update the offset */
- *pOffset = (LVM_UINT16)Offset;
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
deleted file mode 100644
index df8fadc..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A1,
- pBiquadState->coefs[1] is A0,
- pBiquadState->coefs[2] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is y(n-1)L in Q0 format
-***************************************************************************/
-
-void FO_1I_D16F16C15_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL=A1 * x(n-1)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
-
- // ynL+= (-B1 * y(n-1)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[2] * pBiquadState->pDelays[1];
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
deleted file mode 100644
index 10604bf..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* FO_1I_D16F16Css_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void FO_1I_D16F16Css_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order1_FLOAT_Taps_t* pTaps,
- FO_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
- temp = pCoef->A1;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[2] = temp;
-}
-/*------------------------------------------------*/
-/* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
deleted file mode 100644
index d1819fc..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-#define _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT16 coefs[3]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples \
- (data of 32 bits) */
- LVM_FLOAT coefs[3]; /* pointer to the filter coefficients */
-} Filter_State_FLOAT;
-
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-#endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
deleted file mode 100644
index 4c75e04..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A1,
- pBiquadState->coefs[1] is A0,
- pBiquadState->coefs[2] is -B1, these are in Q31 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is y(n-1)L in Q0 format
-***************************************************************************/
-void FO_1I_D32F32C31_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, templ;
- LVM_INT16 ii;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- // ynL=A1 * x(n-1)L
- ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[0];
-
- // ynL+=A0 * x(n)L
- templ = pBiquadState->coefs[1] * (*pDataIn);
- ynL += templ;
-
- // ynL+= (-B1 * y(n-1)L
- templ = pBiquadState->coefs[2] * pBiquadState->pDelays[1];
- ynL += templ;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
deleted file mode 100644
index bf2e5e1..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* FO_1I_D32F32Cll_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void FO_1I_D32F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_1I_Order1_FLOAT_Taps_t* pTaps,
- FO_FLOAT_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- temp = pCoef->A1;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[2] = temp;
-}
-/*------------------------------------------------*/
-/* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
deleted file mode 100644
index 8645593..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
-#define _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-typedef struct _Filter_State_FLOAT_ {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[3]; /* pointer to the filter coefficients */
-} Filter_State_FLOAT;
-
-typedef Filter_State_FLOAT* PFilter_State_FLOAT;
-#endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
deleted file mode 100644
index dad070b..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
-ASSUMPTIONS:
-COEFS-
-pBiquadState->coefs[0] is A1,
-pBiquadState->coefs[1] is A0,
-pBiquadState->coefs[2] is -B1, these are in Q15 format
-pBiquadState->Shift is Shift value
-DELAYS-
-pBiquadState->pDelays[0] is x(n-1)L in Q15 format
-pBiquadState->pDelays[1] is y(n-1)L in Q30 format
-pBiquadState->pDelays[2] is x(n-1)R in Q15 format
-pBiquadState->pDelays[3] is y(n-1)R in Q30 format
-***************************************************************************/
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR;
- LVM_FLOAT Temp;
- LVM_FLOAT NegSatValue;
- LVM_INT16 ii;
-
- PFilter_Float_State pBiquadState = (PFilter_Float_State)pInstance;
-
- NegSatValue = -1.0f;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
-
- // ynL =A1 * x(n-1)L
- ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
- // ynR =A1 * x(n-1)R
- ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
- // ynL+=A0 * x(n)L
- ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
- // ynR+=A0 * x(n)L
- ynR += (LVM_FLOAT)pBiquadState->coefs[1] * (*(pDataIn + 1));
-
- // ynL += (-B1 * y(n-1)L )
- Temp = pBiquadState->pDelays[1] * pBiquadState->coefs[2];
- ynL += Temp;
- // ynR += (-B1 * y(n-1)R ) )
- Temp = pBiquadState->pDelays[3] * pBiquadState->coefs[2];
- ynR += Temp;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
- pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
- pBiquadState->pDelays[3] = ynR; // Update y(n-1)R
- pBiquadState->pDelays[2] = (*pDataIn++); // Update x(n-1)R
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
-
- /*Saturate results*/
- if (ynL > 1.0f) {
- ynL = 1.0f;
- } else {
- if (ynL < NegSatValue) {
- ynL = NegSatValue;
- }
- }
-
- if (ynR > 1.0f) {
- ynR = 1.0f;
- } else {
- if (ynR < NegSatValue) {
- ynR = NegSatValue;
- }
- }
-
- *pDataOut++ = (LVM_FLOAT)ynL;
- *pDataOut++ = (LVM_FLOAT)ynR;
- }
-}
-/**************************************************************************
-ASSUMPTIONS:
-COEFS-
-pBiquadState->coefs[0] is A1,
-pBiquadState->coefs[1] is A0,
-pBiquadState->coefs[2] is -B1,
-DELAYS-
-pBiquadState->pDelays[2*ch + 0] is x(n-1) of the 'ch' - channel
-pBiquadState->pDelays[2*ch + 1] is y(n-1) of the 'ch' - channel
-The index 'ch' runs from 0 to (NrChannels - 1)
-
-PARAMETERS:
- pInstance Pointer Instance
- pDataIn Input/Source
- pDataOut Output/Destination
- NrFrames Number of frames
- NrChannels Number of channels
-
-RETURNS:
- void
-***************************************************************************/
-void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrFrames,
- LVM_INT16 NrChannels) {
- LVM_FLOAT yn;
- LVM_FLOAT Temp;
- LVM_INT16 ii;
- LVM_INT16 ch;
- PFilter_Float_State pBiquadState = (PFilter_Float_State)pInstance;
-
- LVM_FLOAT* pDelays = pBiquadState->pDelays;
- LVM_FLOAT* pCoefs = &pBiquadState->coefs[0];
- LVM_FLOAT A0 = pCoefs[1];
- LVM_FLOAT A1 = pCoefs[0];
- LVM_FLOAT B1 = pCoefs[2];
-
- for (ii = NrFrames; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE CHANNELS
- ***************************************************************************/
- for (ch = 0; ch < NrChannels; ch++) {
- // yn =A1 * x(n-1)
- yn = (LVM_FLOAT)A1 * pDelays[0];
-
- // yn+=A0 * x(n)
- yn += (LVM_FLOAT)A0 * (*pDataIn);
-
- // yn += (-B1 * y(n-1))
- Temp = B1 * pDelays[1];
- yn += Temp;
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pDelays[1] = yn; // Update y(n-1)
- pDelays[0] = (*pDataIn++); // Update x(n-1)
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
-
- /*Saturate results*/
- if (yn > 1.0f) {
- yn = 1.0f;
- } else if (yn < -1.0f) {
- yn = -1.0f;
- }
-
- *pDataOut++ = (LVM_FLOAT)yn;
- pDelays += 2;
- }
- pDelays -= NrChannels * 2;
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
deleted file mode 100644
index 552aeda..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*-------------------------------------------------------------------------*/
-#include "BIQUAD.h"
-#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION: */
-/* FO_2I_D16F32Css_LShx_TRC_WRA_01_Init */
-/* */
-/* DESCRIPTION: */
-/* These functions initializes a BIQUAD filter defined as a cascade of */
-/* biquadratic Filter Sections. */
-/* */
-/* PARAMETERS: */
-/* pInstance - output, returns the pointer to the State Variable */
-/* This state pointer must be passed to any subsequent */
-/* call to "Biquad" functions. */
-/* pTaps - input, pointer to the taps memory */
-/* pCoef - input, pointer to the coefficient structure */
-/* N - M coefficient factor of QM.N */
-/* RETURNS: */
-/* void return code */
-/*-------------------------------------------------------------------------*/
-void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order1_FLOAT_Taps_t* pTaps,
- FO_FLOAT_LShx_Coefs_t* pCoef) {
- LVM_FLOAT temp;
- PFilter_Float_State pBiquadState = (PFilter_Float_State)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- temp = pCoef->A1;
- pBiquadState->coefs[0] = temp;
- temp = pCoef->A0;
- pBiquadState->coefs[1] = temp;
- temp = pCoef->B1;
- pBiquadState->coefs[2] = temp;
-}
-/*-------------------------------------------------------------------------*/
-/* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
deleted file mode 100644
index 0103328..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
-#define _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[3]; /* pointer to the filter coefficients */
-} Filter_Float_State;
-
-typedef Filter_Float_State* PFilter_Float_State;
-#endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
index b050267..e2f8c67 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
@@ -21,33 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION From2iToMS_16x16
-***********************************************************************************/
-
-void From2iToMS_16x16(const LVM_INT16* src, LVM_INT16* dstM, LVM_INT16* dstS, LVM_INT16 n) {
- LVM_INT32 temp1, left, right;
- LVM_INT16 ii;
- for (ii = n; ii != 0; ii--) {
- left = (LVM_INT32)*src;
- src++;
-
- right = (LVM_INT32)*src;
- src++;
-
- /* Compute M signal*/
- temp1 = (left + right) >> 1;
- *dstM = (LVM_INT16)temp1;
- dstM++;
-
- /* Compute S signal*/
- temp1 = (left - right) >> 1;
- *dstS = (LVM_INT16)temp1;
- dstS++;
- }
-
- return;
-}
void From2iToMS_Float(const LVM_FLOAT* src, LVM_FLOAT* dstM, LVM_FLOAT* dstS, LVM_INT16 n) {
LVM_FLOAT temp1, left, right;
LVM_INT16 ii;
@@ -71,4 +44,3 @@
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
deleted file mode 100644
index 9a54ee4..0000000
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION From2iToMono_16
-***********************************************************************************/
-
-void From2iToMono_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 Temp;
- for (ii = n; ii != 0; ii--) {
- Temp = (LVM_INT32)*src;
- src++;
-
- Temp += (LVM_INT32)*src;
- src++;
-
- *dst = (LVM_INT16)(Temp >> 1);
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
index 6ede958..039ee14 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
@@ -21,27 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION From2iToMono_32
-***********************************************************************************/
-
-void From2iToMono_32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 Temp;
-
- for (ii = n; ii != 0; ii--) {
- Temp = (*src >> 1);
- src++;
-
- Temp += (*src >> 1);
- src++;
-
- *dst = Temp;
- dst++;
- }
-
- return;
-}
void From2iToMono_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
LVM_FLOAT Temp;
@@ -93,5 +72,3 @@
return;
}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.cpp b/media/libeffects/lvm/lib/Common/src/InstAlloc.cpp
deleted file mode 100644
index 2cfe056..0000000
--- a/media/libeffects/lvm/lib/Common/src/InstAlloc.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "InstAlloc.h"
-
-/****************************************************************************************
- * Name : InstAlloc_Init()
- * Input : pms - Pointer to the INST_ALLOC instance
- StartAddr - Base address of the instance memory
- * Returns : Error code
- * Description : Initializes the instance distribution and memory size calculation function
- * Remarks :
- ****************************************************************************************/
-
-void InstAlloc_Init(INST_ALLOC* pms, void* StartAddr) {
- pms->TotalSize = 3;
- pms->pNextMember = (((uintptr_t)StartAddr + 3) & (uintptr_t)~3);
-}
-
-/****************************************************************************************
- * Name : InstAlloc_AddMember()
- * Input : pms - Pointer to the INST_ALLOC instance
- Size - The size in bytes of the new added member
- * Returns : A pointer to the new added member
- * Description : Allocates space for a new member in the instance memory and returns
- a pointer to this new member. The start address of all members will
- be 32 bit alligned.
- * Remarks :
- ****************************************************************************************/
-
-void* InstAlloc_AddMember(INST_ALLOC* pms, LVM_UINT32 Size) {
- void* NewMemberAddress; /* Variable to temporarily store the return value */
- NewMemberAddress = (void*)pms->pNextMember;
-
- Size = ((Size + 3) & (LVM_UINT32)~3); /* Ceil the size to a multiple of four */
-
- pms->TotalSize += Size;
- pms->pNextMember += Size;
-
- return (NewMemberAddress);
-}
-
-/****************************************************************************************
- * Name : InstAlloc_GetTotal()
- * Input : pms - Pointer to the INST_ALLOC instance
- * Returns : The instance memory size
- * Description : This functions returns the calculated instance memory size
- * Remarks :
- ****************************************************************************************/
-
-LVM_UINT32 InstAlloc_GetTotal(INST_ALLOC* pms) {
- if (pms->TotalSize > 3) {
- return (pms->TotalSize);
- } else {
- return 0; /* No memory added */
- }
-}
-
-void InstAlloc_InitAll(INST_ALLOC* pms, LVM_MemoryTable_st* pMemoryTable) {
- uintptr_t StartAddr;
-
- StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
-
- pms[0].TotalSize = 3;
- pms[0].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
- StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
-
- pms[1].TotalSize = 3;
- pms[1].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
- StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
-
- pms[2].TotalSize = 3;
- pms[2].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
- StartAddr = (uintptr_t)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
-
- pms[3].TotalSize = 3;
- pms[3].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-}
-
-/****************************************************************************************
- * Name : InstAlloc_InitAll_NULL()
- * Input : pms - Pointer to array of four INST_ALLOC instances
- * Returns : Nothing
- * Description : This function reserves Size of 3 bytes for all memory regions and
- * intializes pNextMember for all regions to 0
- * Remarks :
- ****************************************************************************************/
-
-void InstAlloc_InitAll_NULL(INST_ALLOC* pms) {
- pms[0].TotalSize = 3;
- pms[0].pNextMember = 0;
-
- pms[1].TotalSize = 3;
- pms[1].pNextMember = 0;
-
- pms[2].TotalSize = 3;
- pms[2].pNextMember = 0;
-
- pms[3].TotalSize = 3;
- pms[3].pNextMember = 0;
-}
-
-void* InstAlloc_AddMemberAll(INST_ALLOC* pms, LVM_UINT32 Size[], LVM_MemoryTable_st* pMemoryTable) {
- void* NewMemberAddress; /* Variable to temporarily store the return value */
-
- /* coverity[returned_pointer] Ignore coverity warning that ptr is not used */
- NewMemberAddress =
- InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
-
- pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size =
- InstAlloc_GetTotal(&pms[LVM_PERSISTENT_SLOW_DATA]);
- pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type = LVM_PERSISTENT_SLOW_DATA;
- pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
-
- NewMemberAddress =
- InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
-
- pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size =
- InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_DATA]);
- pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type = LVM_PERSISTENT_FAST_DATA;
- pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
-
- NewMemberAddress =
- InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
-
- pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size =
- InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_COEF]);
- pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
- pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
-
- NewMemberAddress = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
-
- pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&pms[LVM_TEMPORARY_FAST]);
- pMemoryTable->Region[LVM_TEMPORARY_FAST].Type = LVM_TEMPORARY_FAST;
- pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
-
- return (NewMemberAddress);
-}
-
-void* InstAlloc_AddMemberAllRet(INST_ALLOC* pms, LVM_UINT32 Size[], void** ptr) {
- ptr[0] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
- ptr[1] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
- ptr[2] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
- ptr[3] = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
-
- return (ptr[0]);
-}
diff --git a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
deleted file mode 100644
index 9ddcbe4..0000000
--- a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION INT16LSHIFTTOINT32_16X32
-***********************************************************************************/
-
-void Int16LShiftToInt32_16x32(const LVM_INT16* src, LVM_INT32* dst, LVM_INT16 n, LVM_INT16 shift) {
- LVM_INT16 ii;
-
- src += n - 1;
- dst += n - 1;
-
- for (ii = n; ii != 0; ii--) {
- *dst = (((LVM_INT32)*src) << shift);
- src--;
- dst--;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
deleted file mode 100644
index 2584117..0000000
--- a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION INT32RSHIFTTOINT16_SAT_32X16
-***********************************************************************************/
-
-void Int32RShiftToInt16_Sat_32x16(const LVM_INT32* src, LVM_INT16* dst, LVM_INT16 n,
- LVM_INT16 shift) {
- LVM_INT32 temp;
- LVM_INT16 ii;
-
- for (ii = n; ii != 0; ii--) {
- temp = *src >> shift;
- src++;
-
- if (temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)temp;
- }
-
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
index 0721b76..6c7c8ae 100644
--- a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
@@ -21,29 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION JoinTo2i_32x32
-***********************************************************************************/
-
-void JoinTo2i_32x32(const LVM_INT32* srcL, const LVM_INT32* srcR, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- srcL += n - 1;
- srcR += n - 1;
- dst += ((2 * n) - 1);
-
- for (ii = n; ii != 0; ii--) {
- *dst = *srcR;
- dst--;
- srcR--;
-
- *dst = *srcL;
- dst--;
- srcL--;
- }
-
- return;
-}
void JoinTo2i_Float(const LVM_FLOAT* srcL, const LVM_FLOAT* srcR, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
index 8b00925..d670b3d 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
@@ -18,39 +18,10 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
#include "LVM_Macros.h"
#include "ScalarArithmetic.h"
-/**********************************************************************************
- FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
-***********************************************************************************/
-void LVC_Core_MixHard_1St_2i_D16C31_SAT(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_FLOAT Temp;
- LVM_INT16 ii;
- Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
- Mix_Private_FLOAT_st* pInstance2 = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
- for (ii = n; ii != 0; ii--) {
- Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance1->Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
-
- Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance2->Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
- }
-}
void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
LVM_FLOAT Temp;
@@ -58,14 +29,8 @@
for (ii = NrFrames; ii != 0; ii--) {
for (jj = 0; jj < NrChannels; jj++) {
Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance[jj]);
- Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance1->Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *src++ * pInstance1->Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
index 31cd805..417c1f0 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
@@ -18,8 +18,8 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
+#include "ScalarArithmetic.h"
/**********************************************************************************
FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
@@ -34,18 +34,12 @@
Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
Mix_Private_FLOAT_st* pInstance2 = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
- Current1 = (pInstance1->Current);
- Current2 = (pInstance2->Current);
+ Current1 = pInstance1->Current;
+ Current2 = pInstance2->Current;
for (ii = n; ii != 0; ii--) {
- Temp = (((LVM_FLOAT) * (src1++) * (LVM_FLOAT)Current1)) +
- (((LVM_FLOAT) * (src2++) * (LVM_FLOAT)Current2));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *src1++ * Current1 + *src2++ * Current2;
+ *dst++ = LVM_Clamp(Temp);
}
}
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
index b7865d9..d8c25c9 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
@@ -18,9 +18,9 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
/**********************************************************************************
FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
@@ -46,13 +46,8 @@
if (Current > Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -62,13 +57,8 @@
if (Current > Target) Current = Target;
for (jj = 4; jj != 0; jj--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
} else {
@@ -77,13 +67,8 @@
if (Current < Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -92,13 +77,8 @@
if (Current < Target) Current = Target;
for (jj = 4; jj != 0; jj--) {
- Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = (LVM_FLOAT)Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
}
@@ -148,13 +128,8 @@
if (Current > Target) Current = Target;
for (ii = OutLoop * NrChannels; ii != 0; ii--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -164,21 +139,11 @@
if (Current > Target) Current = Target;
for (jj = NrChannels; jj != 0; jj--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
} else {
@@ -187,13 +152,8 @@
if (Current < Target) Current = Target;
for (ii = OutLoop * NrChannels; ii != 0; ii--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
@@ -202,21 +162,11 @@
if (Current < Target) Current = Target;
for (jj = NrChannels; jj != 0; jj--) {
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
- Temp = (*dst) + (*(src++) * Current);
- if (Temp > 1.0f)
- *dst++ = 1.0f;
- else if (Temp < -1.0f)
- *dst++ = -1.0f;
- else
- *dst++ = Temp;
+ Temp = *dst + *src++ * Current;
+ *dst++ = LVM_Clamp(Temp);
}
}
}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
index d45845a..0968cf8 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
@@ -18,107 +18,16 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
-#include "ScalarArithmetic.h"
#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
-/**********************************************************************************
- FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
-***********************************************************************************/
-static LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a, LVM_FLOAT b, LVM_FLOAT c) {
- LVM_FLOAT temp;
- temp = a + b;
- if (temp < -1.0f)
- c = -1.0f;
- else if (temp > 1.0f)
- c = 1.0f;
- else
- c = temp;
- return c;
-}
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_INT16 OutLoop;
- LVM_INT16 InLoop;
- LVM_INT32 ii;
- Mix_Private_FLOAT_st* pInstanceL = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
- Mix_Private_FLOAT_st* pInstanceR = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
-
- LVM_FLOAT DeltaL = pInstanceL->Delta;
- LVM_FLOAT CurrentL = pInstanceL->Current;
- LVM_FLOAT TargetL = pInstanceL->Target;
-
- LVM_FLOAT DeltaR = pInstanceR->Delta;
- LVM_FLOAT CurrentR = pInstanceR->Current;
- LVM_FLOAT TargetR = pInstanceR->Target;
-
- LVM_FLOAT Temp = 0;
-
- InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
- OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
- if (OutLoop) {
- if (CurrentL < TargetL) {
- ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
- CurrentL = Temp;
- if (CurrentL > TargetL) CurrentL = TargetL;
- } else {
- CurrentL -= DeltaL;
- if (CurrentL < TargetL) CurrentL = TargetL;
- }
-
- if (CurrentR < TargetR) {
- ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
- CurrentR = Temp;
- if (CurrentR > TargetR) CurrentR = TargetR;
- } else {
- CurrentR -= DeltaR;
- if (CurrentR < TargetR) CurrentR = TargetR;
- }
-
- for (ii = OutLoop * 2; ii != 0; ii -= 2) {
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- }
- }
-
- for (ii = InLoop * 2; ii != 0; ii -= 2) {
- if (CurrentL < TargetL) {
- ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
- CurrentL = Temp;
- if (CurrentL > TargetL) CurrentL = TargetL;
- } else {
- CurrentL -= DeltaL;
- if (CurrentL < TargetL) CurrentL = TargetL;
- }
-
- if (CurrentR < TargetR) {
- ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
- CurrentR = Temp;
- if (CurrentR > TargetR) CurrentR = TargetR;
- } else {
- CurrentR -= DeltaR;
- if (CurrentR < TargetR) CurrentR = TargetR;
- }
-
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
- *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
- }
- pInstanceL->Current = CurrentL;
- pInstanceR->Current = CurrentR;
+static inline LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a, LVM_FLOAT b) {
+ return LVM_Clamp(a + b);
}
void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
LVM_INT32 ii, ch;
- LVM_FLOAT Temp = 0.0f;
LVM_FLOAT tempCurrent[NrChannels];
for (ch = 0; ch < NrChannels; ch++) {
tempCurrent[ch] = ptrInstance[ch]->Current;
@@ -130,8 +39,7 @@
LVM_FLOAT Current = tempCurrent[ch];
const LVM_FLOAT Target = pInstance->Target;
if (Current < Target) {
- ADD2_SAT_FLOAT(Current, Delta, Temp);
- Current = Temp;
+ Current = ADD2_SAT_FLOAT(Current, Delta);
if (Current > Target) Current = Target;
} else {
Current -= Delta;
@@ -145,4 +53,3 @@
ptrInstance[ch]->Current = tempCurrent[ch];
}
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
index f8c0a9d..fc464e6 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
@@ -18,7 +18,6 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
#include "LVC_Mixer_Private.h"
#include "LVM_Macros.h"
#include "ScalarArithmetic.h"
@@ -35,20 +34,13 @@
LVM_FLOAT Delta = (LVM_FLOAT)pInstance->Delta;
LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
LVM_FLOAT Target = (LVM_FLOAT)pInstance->Target;
- LVM_FLOAT Temp;
InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
OutLoop = (LVM_INT16)(n - (InLoop << 2));
if (Current < Target) {
if (OutLoop) {
- Temp = Current + Delta;
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
+ Current = LVM_Clamp(Current + Delta);
if (Current > Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
@@ -57,14 +49,8 @@
}
for (ii = InLoop; ii != 0; ii--) {
- Temp = Current + Delta;
+ Current = LVM_Clamp(Current + Delta);
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
if (Current > Target) Current = Target;
*(dst++) = (((LVM_FLOAT) * (src++) * Current));
@@ -121,7 +107,6 @@
LVM_FLOAT Delta = (LVM_FLOAT)pInstance->Delta;
LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
LVM_FLOAT Target = (LVM_FLOAT)pInstance->Target;
- LVM_FLOAT Temp;
/*
* Same operation is performed on consecutive frames.
@@ -134,13 +119,7 @@
if (Current < Target) {
if (OutLoop) {
- Temp = Current + Delta;
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
+ Current = LVM_Clamp(Current + Delta);
if (Current > Target) Current = Target;
for (ii = OutLoop; ii != 0; ii--) {
@@ -151,14 +130,7 @@
}
for (ii = InLoop; ii != 0; ii--) {
- Temp = Current + Delta;
-
- if (Temp > 1.0f)
- Temp = 1.0f;
- else if (Temp < -1.0f)
- Temp = -1.0f;
-
- Current = Temp;
+ Current = LVM_Clamp(Current + Delta);
if (Current > Target) Current = Target;
for (jj = NrChannels; jj != 0; jj--) {
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
index c74c8c6..b0aa172 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
@@ -35,7 +35,7 @@
#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(*(a))))
/**********************************************************************************
- FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
+ FUNCTION LVC_MixSoft_1St_MC_float_SAT
***********************************************************************************/
/* This threshold is used to decide on the processing to be applied on
* front center and back center channels
@@ -56,10 +56,11 @@
Mix_Private_FLOAT_st* pInstance[NrChannels];
if (audio_channel_mask_get_representation(ChMask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
- for (int i = 0; i < 2; i++) {
+ int loopLimit = (NrChannels == FCC_1) ? NrChannels : FCC_2;
+ for (int i = 0; i < loopLimit; i++) {
pInstance[i] = pMixPrivInst[i];
}
- for (int i = 2; i < NrChannels; i++) {
+ for (int i = loopLimit; i < NrChannels; i++) {
pInstance[i] = pMixPrivInst[2];
}
} else {
@@ -192,106 +193,3 @@
}
}
}
-void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st* ptrInstance, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n) {
- char HardMixing = TRUE;
- LVM_FLOAT TargetGain;
- Mix_Private_FLOAT_st* pInstance1 =
- (Mix_Private_FLOAT_st*)(ptrInstance->MixerStream[0].PrivateParams);
- Mix_Private_FLOAT_st* pInstance2 =
- (Mix_Private_FLOAT_st*)(ptrInstance->MixerStream[1].PrivateParams);
-
- if (n <= 0) return;
-
- /******************************************************************************
- SOFT MIXING
- *******************************************************************************/
- if ((pInstance1->Current != pInstance1->Target) ||
- (pInstance2->Current != pInstance2->Target)) {
- if (pInstance1->Delta == 1.0f) {
- pInstance1->Current = pInstance1->Target;
- TargetGain = pInstance1->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
- } else if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta) {
- pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
- Make them equal. */
- TargetGain = pInstance1->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
- } else {
- /* Soft mixing has to be applied */
- HardMixing = FALSE;
- }
-
- if (HardMixing == TRUE) {
- if (pInstance2->Delta == 1.0f) {
- pInstance2->Current = pInstance2->Target;
- TargetGain = pInstance2->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
- } else if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta) {
- pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
- \ Make them equal. */
- TargetGain = pInstance2->Target;
- LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
- } else {
- /* Soft mixing has to be applied */
- HardMixing = FALSE;
- }
- }
-
- if (HardMixing == FALSE) {
- LVC_Core_MixSoft_1St_2i_D16C31_WRA(&(ptrInstance->MixerStream[0]),
- &(ptrInstance->MixerStream[1]), src, dst, n);
- }
- }
-
- /******************************************************************************
- HARD MIXING
- *******************************************************************************/
-
- if (HardMixing) {
- if ((pInstance1->Target == 1.0f) && (pInstance2->Target == 1.0f)) {
- if (src != dst) {
- Copy_Float(src, dst, n);
- }
- } else {
- LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),
- &(ptrInstance->MixerStream[1]), src, dst, n);
- }
- }
-
- /******************************************************************************
- CALL BACK
- *******************************************************************************/
-
- if (ptrInstance->MixerStream[0].CallbackSet) {
- if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta) {
- pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
- Make them equal. */
- TargetGain = pInstance1->Target;
- LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
- ptrInstance->MixerStream[0].CallbackSet = FALSE;
- if (ptrInstance->MixerStream[0].pCallBack != 0) {
- (*ptrInstance->MixerStream[0].pCallBack)(
- ptrInstance->MixerStream[0].pCallbackHandle,
- ptrInstance->MixerStream[0].pGeneralPurpose,
- ptrInstance->MixerStream[0].CallbackParam);
- }
- }
- }
- if (ptrInstance->MixerStream[1].CallbackSet) {
- if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta) {
- pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
- Make them equal. */
- TargetGain = pInstance2->Target;
- LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
- ptrInstance->MixerStream[1].CallbackSet = FALSE;
- if (ptrInstance->MixerStream[1].pCallBack != 0) {
- (*ptrInstance->MixerStream[1].pCallBack)(
- ptrInstance->MixerStream[1].pCallbackHandle,
- ptrInstance->MixerStream[1].pGeneralPurpose,
- ptrInstance->MixerStream[1].CallbackParam);
- }
- }
- }
-}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index 55255a6..1eb2dea 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -101,9 +101,6 @@
void LVC_MixSoft_1St_MC_float_SAT(LVMixer3_2St_FLOAT_st* pInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, /* dst can be equal to src */
LVM_INT16 NrFrames, LVM_INT32 NrChannels, LVM_INT32 ChMask);
-void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st* pInstance, const LVM_FLOAT* src,
- LVM_FLOAT* dst, /* dst can be equal to src */
- LVM_INT16 n); /* Number of stereo samples */
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index 5f22d77..9206fae 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -65,9 +65,6 @@
/**********************************************************************************/
void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n);
/**********************************************************************************/
/* For applying different gains to Left and right chennals */
@@ -77,11 +74,5 @@
/**********************************************************************************/
void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-void LVC_Core_MixHard_1St_2i_D16C31_SAT(LVMixer3_FLOAT_st* ptrInstance1,
- LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
- LVM_FLOAT* dst, LVM_INT16 n);
-
-/*** 32 bit functions *************************************************************/
-/**********************************************************************************/
#endif //#ifndef __LVC_MIXER_PRIVATE_H__
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp b/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
deleted file mode 100644
index a39fa2f..0000000
--- a/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION LoadConst_16
-***********************************************************************************/
-
-void LoadConst_16(const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- for (ii = n; ii != 0; ii--) {
- *dst = val;
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
index a19e66f..e5c6f15 100644
--- a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
@@ -18,49 +18,9 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include "ScalarArithmetic.h"
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION MSTO2I_SAT_16X16
-***********************************************************************************/
-
-void MSTo2i_Sat_16x16(const LVM_INT16* srcM, const LVM_INT16* srcS, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT32 temp, mVal, sVal;
- LVM_INT16 ii;
-
- for (ii = n; ii != 0; ii--) {
- mVal = (LVM_INT32)*srcM;
- srcM++;
-
- sVal = (LVM_INT32)*srcS;
- srcS++;
-
- temp = mVal + sVal;
-
- if (temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)temp;
- }
- dst++;
-
- temp = mVal - sVal;
-
- if (temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)temp;
- }
- dst++;
- }
-
- return;
-}
void MSTo2i_Sat_Float(const LVM_FLOAT* srcM, const LVM_FLOAT* srcS, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_FLOAT temp, mVal, sVal;
LVM_INT16 ii;
@@ -73,28 +33,11 @@
srcS++;
temp = mVal + sVal;
-
- if (temp > 1.0f) {
- *dst = 1.0f;
- } else if (temp < -1.0f) {
- *dst = -1.0f;
- } else {
- *dst = (LVM_FLOAT)temp;
- }
- dst++;
+ *dst++ = LVM_Clamp(temp);
temp = mVal - sVal;
-
- if (temp > 1.0f) {
- *dst = 1.0f;
- } else if (temp < -1.0f) {
- *dst = -1.0f;
- } else {
- *dst = (LVM_FLOAT)temp;
- }
- dst++;
+ *dst++ = LVM_Clamp(temp);
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
deleted file mode 100644
index 1d450b0..0000000
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
-
- %created_by: sra % (CM/S)
- %name: Mac3s_Sat_16x16.c % (CM/S)
- %version: 1 % (CM/S)
- %date_created: Fri Nov 13 12:07:13 2009 % (CM/S)
-
-***********************************************************************************/
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
- FUNCTION Mac3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_16x16(const LVM_INT16* src, const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT16 srcval;
- LVM_INT32 Temp, dInVal;
-
- for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
-
- Temp = (srcval * val) >> 15;
-
- dInVal = (LVM_INT32)*dst;
-
- Temp = Temp + dInVal;
-
- if (Temp > 0x00007FFF) {
- *dst = 0x7FFF;
- } else if (Temp < -0x00008000) {
- *dst = -0x8000;
- } else {
- *dst = (LVM_INT16)Temp;
- }
-
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
index 0fe9fef..24bdf3e 100644
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
@@ -18,66 +18,19 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include "ScalarArithmetic.h"
#include "VectorArithmetic.h"
#include "LVM_Macros.h"
-/**********************************************************************************
- FUNCTION MAC3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 srcval, temp, dInVal, dOutVal;
-
- for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
-
- MUL32x16INTO32(srcval, val, temp, 15)
-
- dInVal = *dst;
- dOutVal = temp + dInVal;
-
- if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31) != 0) /* overflow / underflow */
- {
- if (temp < 0) {
- dOutVal = 0x80000000L;
- } else {
- dOutVal = 0x7FFFFFFFL;
- }
- }
-
- *dst = dOutVal;
- dst++;
- }
-
- return;
-}
void Mac3s_Sat_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
- LVM_FLOAT srcval;
- LVM_FLOAT Temp, dInVal;
for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
+ LVM_FLOAT Temp = *src++ * val;
+ Temp += *dst;
- Temp = srcval * val;
-
- dInVal = (LVM_FLOAT)*dst;
- Temp = Temp + dInVal;
-
- if (Temp > 1.000000f) {
- *dst = 1.000000f;
- } else if (Temp < -1.000000f) {
- *dst = -1.000000f;
- } else {
- *dst = Temp;
- }
- dst++;
+ *dst++ = LVM_Clamp(Temp);
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
deleted file mode 100644
index 7ab5d49..0000000
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION MonoTo2I_16
-***********************************************************************************/
-
-void MonoTo2I_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- src += (n - 1);
- dst += ((n * 2) - 1);
-
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
-
- *dst = *src;
- dst--;
- src--;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
index 1ba669f..ef3e633 100644
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
@@ -21,26 +21,6 @@
#include "VectorArithmetic.h"
-/**********************************************************************************
- FUNCTION MonoTo2I_32
-***********************************************************************************/
-
-void MonoTo2I_32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- src += (n - 1);
- dst += ((n * 2) - 1);
-
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
-
- *dst = *src;
- dst--;
- src--;
- }
-
- return;
-}
void MonoTo2I_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
src += (n - 1);
@@ -57,4 +37,3 @@
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
index 4589703..babfef3 100644
--- a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
@@ -22,26 +22,6 @@
#include "VectorArithmetic.h"
#include "LVM_Macros.h"
-/**********************************************************************************
-FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 srcval, temp;
-
- for (ii = n; ii != 0; ii--) {
- srcval = *src;
- src++;
-
- MUL32x16INTO32(srcval, val, temp, 15)
-
- * dst = temp;
- dst++;
- }
-
- return;
-}
void Mult3s_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n) {
LVM_INT16 ii;
LVM_FLOAT temp;
@@ -54,4 +34,3 @@
}
return;
}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
index fba0666..f3a1a67 100644
--- a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
@@ -61,43 +61,6 @@
/* */
/****************************************************************************************/
-void NonLinComp_D16(LVM_INT16 Gain, LVM_INT16* pDataIn, LVM_INT16* pDataOut,
- LVM_INT32 BlockLength) {
- LVM_INT16 Sample; /* Input samples */
- LVM_INT32 SampleNo; /* Sample index */
- LVM_INT16 Temp;
-
- /*
- * Process a block of samples
- */
- for (SampleNo = 0; SampleNo < BlockLength; SampleNo++) {
- /*
- * Read the input
- */
- Sample = *pDataIn;
- pDataIn++;
-
- /*
- * Apply the compander, this compresses the signal at the expense of
- * harmonic distortion. The amount of compression is control by the
- * gain factor
- */
- if ((LVM_INT32)Sample != -32768) {
- Temp = (LVM_INT16)((Sample * Sample) >> 15);
- if (Sample > 0) {
- Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
- } else {
- Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
- }
- }
-
- /*
- * Save the output
- */
- *pDataOut = Sample;
- pDataOut++;
- }
-}
void NonLinComp_Float(LVM_FLOAT Gain, LVM_FLOAT* pDataIn, LVM_FLOAT* pDataOut,
LVM_INT32 BlockLength) {
LVM_FLOAT Sample; /* Input samples */
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
deleted file mode 100644
index 0afaad2..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q14 format
- pBiquadState->coefs[3] is Gain, in Q11 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-void PK_2I_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
- LVM_FLOAT ynL, ynR, ynLO, ynRO, templ;
- LVM_INT16 ii;
- PFilter_State_Float pBiquadState = (PFilter_State_Float)pInstance;
-
- for (ii = NrSamples; ii != 0; ii--) {
- /**************************************************************************
- PROCESSING OF THE LEFT CHANNEL
- ***************************************************************************/
- /* ynL= (A0 * (x(n)L - x(n-2)L ) )*/
- templ = (*pDataIn) - pBiquadState->pDelays[2];
- ynL = templ * pBiquadState->coefs[0];
-
- /* ynL+= ((-B2 * y(n-2)L )) */
- templ = pBiquadState->pDelays[6] * pBiquadState->coefs[1];
- ynL += templ;
-
- /* ynL+= ((-B1 * y(n-1)L ) ) */
- templ = pBiquadState->pDelays[4] * pBiquadState->coefs[2];
- ynL += templ;
-
- /* ynLO= ((Gain * ynL )) */
- ynLO = ynL * pBiquadState->coefs[3];
-
- /* ynLO=( ynLO + x(n)L )*/
- ynLO += (*pDataIn);
-
- /**************************************************************************
- PROCESSING OF THE RIGHT CHANNEL
- ***************************************************************************/
- /* ynR= (A0 * (x(n)R - x(n-2)R ) ) */
- templ = (*(pDataIn + 1)) - pBiquadState->pDelays[3];
- ynR = templ * pBiquadState->coefs[0];
-
- /* ynR+= ((-B2 * y(n-2)R ) ) */
- templ = pBiquadState->pDelays[7] * pBiquadState->coefs[1];
- ynR += templ;
-
- /* ynR+= ((-B1 * y(n-1)R ) ) */
- templ = pBiquadState->pDelays[5] * pBiquadState->coefs[2];
- ynR += templ;
-
- /* ynRO= ((Gain * ynR )) */
- ynRO = ynR * pBiquadState->coefs[3];
-
- /* ynRO=( ynRO + x(n)R )*/
- ynRO += (*(pDataIn + 1));
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
- pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
- pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
- pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
- pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
- pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
- pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
- pDataIn++;
- pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = ynLO; /* Write Left output*/
- pDataOut++;
- *pDataOut = ynRO; /* Write Right output*/
- pDataOut++;
- }
-}
-
-/**************************************************************************
-DELAYS-
-pBiquadState->pDelays[0] to
-pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
-
-pBiquadState->pDelays[NrChannels] to
-pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
-
-pBiquadState->pDelays[2*NrChannels] to
-pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
-
-pBiquadState->pDelays[3*NrChannels] to
-pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
-***************************************************************************/
-
-void PK_Mc_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
- LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
- LVM_FLOAT yn, ynO, temp;
- LVM_INT16 ii, jj;
- PFilter_State_Float pBiquadState = (PFilter_State_Float)pInstance;
-
- for (ii = NrFrames; ii != 0; ii--) {
- for (jj = 0; jj < NrChannels; jj++) {
- /**************************************************************************
- PROCESSING OF THE jj CHANNEL
- ***************************************************************************/
- /* yn= (A0 * (x(n) - x(n-2)))*/
- temp = (*pDataIn) - pBiquadState->pDelays[NrChannels + jj];
- yn = temp * pBiquadState->coefs[0];
-
- /* yn+= ((-B2 * y(n-2))) */
- temp = pBiquadState->pDelays[NrChannels * 3 + jj] * pBiquadState->coefs[1];
- yn += temp;
-
- /* yn+= ((-B1 * y(n-1))) */
- temp = pBiquadState->pDelays[NrChannels * 2 + jj] * pBiquadState->coefs[2];
- yn += temp;
-
- /* ynO= ((Gain * yn)) */
- ynO = yn * pBiquadState->coefs[3];
-
- /* ynO=(ynO + x(n))*/
- ynO += (*pDataIn);
-
- /**************************************************************************
- UPDATING THE DELAYS
- ***************************************************************************/
- pBiquadState->pDelays[NrChannels * 3 + jj] =
- pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
- pBiquadState->pDelays[NrChannels * 1 + jj] =
- pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
- pBiquadState->pDelays[NrChannels * 2 + jj] = yn; /* Update y(n-1) */
- pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
- pDataIn++;
-
- /**************************************************************************
- WRITING THE OUTPUT
- ***************************************************************************/
- *pDataOut = ynO; /* Write output*/
- pDataOut++;
- }
- }
-}
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp
deleted file mode 100644
index 41de1de..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q30 format
- pBiquadState->coefs[3] is Gain, in Q11 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
deleted file mode 100644
index 3f5d332..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
-#define _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-#endif /* _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
deleted file mode 100644
index 178d766..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BIQUAD.h"
-#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
-void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
- Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
- PK_FLOAT_Coefs_t* pCoef) {
- PFilter_State_Float pBiquadState = (PFilter_State_Float)pInstance;
- pBiquadState->pDelays = (LVM_FLOAT*)pTaps;
-
- pBiquadState->coefs[0] = pCoef->A0;
-
- pBiquadState->coefs[1] = pCoef->B2;
-
- pBiquadState->coefs[2] = pCoef->B1;
-
- pBiquadState->coefs[3] = pCoef->G;
-}
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
deleted file mode 100644
index 57a1c16..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
-#define _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
-
-/* The internal state variables are implemented in a (for the user) hidden structure */
-/* In this (private) file, the internal structure is declared fro private use. */
-
-typedef struct _Filter_State_Float_ {
- LVM_FLOAT* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_FLOAT coefs[5]; /* pointer to the filter coefficients */
-} Filter_State_Float;
-
-typedef Filter_State_Float* PFilter_State_Float;
-typedef struct _Filter_State_ {
- LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
- LVM_INT32 coefs[5]; /* pointer to the filter coefficients */
-} Filter_State;
-
-typedef Filter_State* PFilter_State;
-
-#endif /* _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
deleted file mode 100644
index 66f9132..0000000
--- a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**********************************************************************************
- INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
- FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_16x16(const LVM_INT16* src, const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
- LVM_INT16 ii;
- LVM_INT32 temp;
-
- for (ii = n; ii != 0; ii--) {
- temp = (LVM_INT32)(*src) * (LVM_INT32)val;
- src++;
-
- *dst = (LVM_INT16)(temp >> 15);
- dst++;
- }
-
- return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
index bccbe86..7e5caed 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
@@ -21,6 +21,7 @@
/* */
/****************************************************************************************/
+#include <system/audio.h>
#include "LVEQNB.h"
#include "LVEQNB_Private.h"
#include "VectorArithmetic.h"
@@ -179,6 +180,7 @@
LVM_UINT16 i; /* Filter band index */
LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
+ pInstance->gain.resize(pInstance->Params.NBands);
/*
* Set the coefficients for each band by the init function
*/
@@ -198,8 +200,14 @@
/*
* Set the coefficients
*/
- PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
- &pInstance->pEQNB_Taps_Float[i], &Coefficients);
+ pInstance->gain[i] = Coefficients.G;
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInstance->eqBiquad[i]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
break;
}
default:
@@ -220,18 +228,8 @@
/* */
/************************************************************************************/
void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t* pInstance) {
- LVM_FLOAT* pTapAddress;
- LVM_INT16 NumTaps;
-
- pTapAddress = (LVM_FLOAT*)pInstance->pEQNB_Taps_Float;
- NumTaps =
- (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) /
- sizeof(LVM_FLOAT));
-
- if (NumTaps != 0) {
- LoadConst_Float(0, /* Clear the history, value 0 */
- pTapAddress, /* Destination */
- NumTaps); /* Number of words */
+ for (size_t i = 0; i < pInstance->eqBiquad.size(); i++) {
+ pInstance->eqBiquad[i].clear();
}
}
/****************************************************************************************/
@@ -310,6 +308,13 @@
(OperatingModeSave == LVEQNB_ON && pInstance->bInOperatingModeTransition &&
LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
+ /*
+ * Create biquad instance
+ */
+ pInstance->eqBiquad.resize(pParams->NBands,
+ android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels));
+ LVEQNB_ClearFilterHistory(pInstance);
+
if (bChange || modeChange) {
/*
* If the sample rate has changed clear the history
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
index 1d2a5f5..3473262 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
@@ -24,7 +24,6 @@
#include <stdlib.h>
#include "LVEQNB.h"
#include "LVEQNB_Private.h"
-#include "InstAlloc.h"
#include <string.h> /* For memset */
/****************************************************************************************/
@@ -52,29 +51,14 @@
LVEQNB_Capabilities_t* pCapabilities, void* pScratch) {
LVEQNB_Instance_t* pInstance;
- *phInstance = calloc(1, sizeof(*pInstance));
- if (phInstance == LVM_NULL) {
- return LVEQNB_NULLADDRESS;
- }
+ *phInstance = new LVEQNB_Instance_t{};
pInstance = (LVEQNB_Instance_t*)*phInstance;
pInstance->Capabilities = *pCapabilities;
pInstance->pScratch = pScratch;
/* Equaliser Biquad Instance */
- LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pEQNB_FilterState_Float));
- pInstance->pEQNB_FilterState_Float = (Biquad_FLOAT_Instance_t*)calloc(1, MemSize);
- if (pInstance->pEQNB_FilterState_Float == LVM_NULL) {
- return LVEQNB_NULLADDRESS;
- }
-
- MemSize = (pCapabilities->MaxBands * sizeof(*(pInstance->pEQNB_Taps_Float)));
- pInstance->pEQNB_Taps_Float = (Biquad_2I_Order2_FLOAT_Taps_t*)calloc(1, MemSize);
- if (pInstance->pEQNB_Taps_Float == LVM_NULL) {
- return LVEQNB_NULLADDRESS;
- }
-
- MemSize = (pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions)));
+ LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions));
pInstance->pBandDefinitions = (LVEQNB_BandDef_t*)calloc(1, MemSize);
if (pInstance->pBandDefinitions == LVM_NULL) {
return LVEQNB_NULLADDRESS;
@@ -106,10 +90,6 @@
LVEQNB_SetFilters(pInstance, /* Set the filter types */
&pInstance->Params);
- LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */
-
- LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */
-
/*
* Initialise the bypass variables
*/
@@ -154,15 +134,6 @@
}
pInstance = (LVEQNB_Instance_t*)*phInstance;
- /* Equaliser Biquad Instance */
- if (pInstance->pEQNB_FilterState_Float != LVM_NULL) {
- free(pInstance->pEQNB_FilterState_Float);
- pInstance->pEQNB_FilterState_Float = LVM_NULL;
- }
- if (pInstance->pEQNB_Taps_Float != LVM_NULL) {
- free(pInstance->pEQNB_Taps_Float);
- pInstance->pEQNB_Taps_Float = LVM_NULL;
- }
if (pInstance->pBandDefinitions != LVM_NULL) {
free(pInstance->pBandDefinitions);
pInstance->pBandDefinitions = LVM_NULL;
@@ -171,6 +142,6 @@
free(pInstance->pBiquadType);
pInstance->pBiquadType = LVM_NULL;
}
- free(pInstance);
+ delete pInstance;
*phInstance = LVM_NULL;
}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index 83a3449..2225fec 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -24,6 +24,7 @@
/* */
/****************************************************************************************/
+#include <audio_utils/BiquadFilter.h>
#include "LVEQNB.h" /* Calling or Application layer definitions */
#include "BIQUAD.h"
#include "LVC_Mixer.h"
@@ -69,8 +70,9 @@
/* Aligned memory pointers */
LVM_FLOAT* pFastTemporary; /* Fast temporary data base address */
- Biquad_2I_Order2_FLOAT_Taps_t* pEQNB_Taps_Float; /* Equaliser Taps */
- Biquad_FLOAT_Instance_t* pEQNB_FilterState_Float; /* State for each filter band */
+ std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ eqBiquad; /* Biquad filter instances */
+ std::vector<LVM_FLOAT> gain; /* Gain values for all bands*/
/* Filter definitions and call back */
LVM_UINT16 NBands; /* Number of bands */
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
index d2a26db..b177dd4 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
@@ -62,10 +62,7 @@
LVEQNB_Handle_t hInstance, const LVM_FLOAT* pInData, LVM_FLOAT* pOutData,
const LVM_UINT16 NrFrames) { // updated to use samples = frames * channels.
LVEQNB_Instance_t* pInstance = (LVEQNB_Instance_t*)hInstance;
-
- // Mono passed in as stereo
- const LVM_INT32 NrChannels =
- pInstance->Params.NrChannels == 1 ? 2 : pInstance->Params.NrChannels;
+ const LVM_INT32 NrChannels = pInstance->Params.NrChannels;
const LVM_INT32 NrSamples = NrChannels * NrFrames;
/* Check for NULL pointers */
@@ -105,18 +102,16 @@
*/
if (pInstance->pBandDefinitions[i].Gain != 0) {
/*
- * Get the address of the biquad instance
- */
- Biquad_FLOAT_Instance_t* pBiquad = &pInstance->pEQNB_FilterState_Float[i];
-
- /*
* Select single or double precision as required
*/
switch (pInstance->pBiquadType[i]) {
case LVEQNB_SinglePrecision_Float: {
- PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad, pScratch, pScratch,
- (LVM_INT16)NrFrames,
- (LVM_INT16)NrChannels);
+ LVM_FLOAT* pTemp = pScratch + NrSamples;
+ pInstance->eqBiquad[i].process(pTemp, pScratch, NrFrames);
+ const auto gain = pInstance->gain[i];
+ for (unsigned j = 0; j < NrSamples; ++j) {
+ pScratch[j] += pTemp[j] * gain;
+ }
break;
}
default:
diff --git a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
index 484787a..82e94da 100644
--- a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
+++ b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
@@ -78,11 +78,6 @@
/* */
/****************************************************************************************/
-/* Memory table containing the region definitions */
-typedef struct {
- LVM_MemoryRegion_st Region[LVREV_NR_MEMORY_REGIONS]; /* One definition for each region */
-} LVREV_MemoryTable_st;
-
/* Control Parameter structure */
typedef struct {
/* General parameters */
@@ -121,46 +116,6 @@
/****************************************************************************************/
/* */
-/* FUNCTION: LVREV_GetMemoryTable */
-/* */
-/* DESCRIPTION: */
-/* This function is used to obtain the LVREV module memory requirements to support */
-/* memory allocation. It can also be used to return the memory base address provided */
-/* during memory allocation to support freeing of memory when the LVREV module is no */
-/* longer required. It is called in two ways: */
-/* */
-/* hInstance = NULL Returns the memory requirements */
-/* hInstance = Instance handle Returns the memory requirements and allocated */
-/* base addresses. */
-/* */
-/* When this function is called with hInstance = NULL the memory base address pointers */
-/* will be NULL on return. */
-/* */
-/* When the function is called for freeing memory, hInstance = Instance Handle the */
-/* memory table returns the allocated memory and base addresses used during */
-/* initialisation. */
-/* */
-/* PARAMETERS: */
-/* hInstance Instance Handle */
-/* pMemoryTable Pointer to an empty memory table */
-/* pInstanceParams Pointer to the instance parameters */
-/* */
-/* RETURNS: */
-/* LVREV_SUCCESS Succeeded */
-/* LVREV_NULLADDRESS When pMemoryTable is NULL */
-/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
-/* is NULL */
-/* */
-/* NOTES: */
-/* 1. This function may be interrupted by the LVREV_Process function */
-/* */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
- LVREV_MemoryTable_st* pMemoryTable,
- LVREV_InstanceParams_st* pInstanceParams);
-
-/****************************************************************************************/
-/* */
/* FUNCTION: LVREV_GetInstanceHandle */
/* */
/* DESCRIPTION: */
@@ -174,7 +129,6 @@
/* */
/* PARAMETERS: */
/* phInstance Pointer to the instance handle */
-/* pMemoryTable Pointer to the memory definition table */
/* pInstanceParams Pointer to the instance parameters */
/* */
/* RETURNS: */
@@ -186,11 +140,27 @@
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t* phInstance,
- LVREV_MemoryTable_st* pMemoryTable,
LVREV_InstanceParams_st* pInstanceParams);
/****************************************************************************************/
/* */
+/* FUNCTION: LVREV_FreeInstance */
+/* */
+/* DESCRIPTION: */
+/* This function is used to free the internal allocations of the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS free instance succeeded */
+/* LVREV_NULLADDRESS Instance is NULL */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_FreeInstance(LVREV_Handle_t hInstance);
+
+/****************************************************************************************/
+/* */
/* FUNCTION: LVXX_GetControlParameters */
/* */
/* DESCRIPTION: */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 737ef01..b7883f5 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -20,6 +20,8 @@
/* Includes */
/* */
/****************************************************************************************/
+
+#include <system/audio.h>
#include "LVREV_Private.h"
#include "Filter.h"
@@ -71,10 +73,10 @@
Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
LVM_FO_HPF(Omega, &Coeffs);
- FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps,
- &Coeffs);
- LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->HPTaps,
- sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->pRevHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
}
/*
@@ -99,10 +101,10 @@
LVM_FO_LPF(Omega, &Coeffs);
}
}
- FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps,
- &Coeffs);
- LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->LPTaps,
- sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->pRevLPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
}
/*
@@ -130,10 +132,6 @@
LVM_INT16 i;
LVM_FLOAT ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
- LVM_INT16 MaxT_Delay[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY,
- LVREV_MAX_T3_DELAY};
- LVM_INT16 MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY,
- LVREV_MAX_AP3_DELAY};
/*
* For each delay line
@@ -153,7 +151,7 @@
* Set the fixed delay
*/
- Temp = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
+ Temp = (LVREV_MAX_T_DELAY[i] - LVREV_MAX_AP_DELAY[i]) * Fs / 192000;
pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
/*
@@ -231,8 +229,10 @@
Coeffs.A1 = 0;
Coeffs.B1 = 0;
}
- FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
- &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->revLPFBiquad[i].reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
}
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 5c83ce5..d4b321f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -56,31 +56,11 @@
* Clear all filter tap data, delay-lines and other signal related data
*/
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->HPTaps, 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->LPTaps, 2);
- if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4) {
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
- }
-
- if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2) {
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
- }
-
- if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1) {
- LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+ pLVREV_Private->pRevHPFBiquad->clear();
+ pLVREV_Private->pRevLPFBiquad->clear();
+ for (size_t i = 0; i < pLVREV_Private->InstanceParams.NumDelays; i++) {
+ pLVREV_Private->revLPFBiquad[i]->clear();
+ LoadConst_Float(0, pLVREV_Private->pDelay_T[i], LVREV_MAX_T_DELAY[i]);
}
return LVREV_SUCCESS;
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
index b5db23b..3a63698 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
@@ -21,7 +21,6 @@
/* */
/****************************************************************************************/
#include "LVREV_Private.h"
-#include "InstAlloc.h"
/****************************************************************************************/
/* */
@@ -34,7 +33,6 @@
/* */
/* PARAMETERS: */
/* phInstance pointer to the instance handle */
-/* pMemoryTable Pointer to the memory definition table */
/* pInstanceParams Pointer to the instance parameters */
/* */
/* RETURNS: */
@@ -46,12 +44,7 @@
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t* phInstance,
- LVREV_MemoryTable_st* pMemoryTable,
LVREV_InstanceParams_st* pInstanceParams) {
- INST_ALLOC SlowData;
- INST_ALLOC FastData;
- INST_ALLOC FastCoef;
- INST_ALLOC Temporary;
LVREV_Instance_st* pLVREV_Private;
LVM_INT16 i;
LVM_UINT16 MaxBlockSize;
@@ -60,18 +53,9 @@
* Check for error conditions
*/
/* Check for NULL pointers */
- if ((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstanceParams == LVM_NULL)) {
+ if ((phInstance == LVM_NULL) || (pInstanceParams == LVM_NULL)) {
return LVREV_NULLADDRESS;
}
- /* Check the memory table for NULL pointers */
- for (i = 0; i < LVREV_NR_MEMORY_REGIONS; i++) {
- if (pMemoryTable->Region[i].Size != 0) {
- if (pMemoryTable->Region[i].pBaseAddress == LVM_NULL) {
- return (LVREV_NULLADDRESS);
- }
- }
- }
-
/*
* Check all instance parameters are in range
*/
@@ -88,43 +72,19 @@
}
/*
- * Initialise the InstAlloc instances
- */
- InstAlloc_Init(&SlowData, pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress);
- InstAlloc_Init(&FastData, pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress);
- InstAlloc_Init(&FastCoef, pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress);
- InstAlloc_Init(&Temporary, pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress);
-
- /*
- * Zero all memory regions
- */
- LoadConst_Float(
- 0, (LVM_FLOAT*)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress,
- (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size) / sizeof(LVM_FLOAT)));
- LoadConst_Float(
- 0, (LVM_FLOAT*)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress,
- (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size) / sizeof(LVM_FLOAT)));
- LoadConst_Float(
- 0, (LVM_FLOAT*)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress,
- (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size) / sizeof(LVM_FLOAT)));
- LoadConst_Float(
- 0, (LVM_FLOAT*)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress,
- (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size) / sizeof(LVM_FLOAT)));
- /*
* Set the instance handle if not already initialised
*/
if (*phInstance == LVM_NULL) {
- *phInstance = InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+ *phInstance = new LVREV_Instance_st{};
}
pLVREV_Private = (LVREV_Instance_st*)*phInstance;
- pLVREV_Private->MemoryTable = *pMemoryTable;
if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[3];
} else if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[1];
} else {
- MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ MaxBlockSize = LVREV_MAX_AP_DELAY[0];
}
if (MaxBlockSize > pInstanceParams->MaxBlockSize) {
@@ -134,76 +94,21 @@
/*
* Set the data, coefficient and temporary memory pointers
*/
- /* Fast data memory base address */
- pLVREV_Private->pFastData =
- (LVREV_FastData_st*)InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- pLVREV_Private->pDelay_T[3] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[2] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[1] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[0] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
- for (i = 0; i < 4; i++) {
- /* Scratch for each delay line output */
- pLVREV_Private->pScratchDelayLine[i] =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- pLVREV_Private->pDelay_T[1] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- pLVREV_Private->pDelay_T[0] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
- for (i = 0; i < 2; i++) {
- /* Scratch for each delay line output */
- pLVREV_Private->pScratchDelayLine[i] =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
- pLVREV_Private->pDelay_T[0] =
- (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
- for (i = 0; i < 1; i++) {
- /* Scratch for each delay line output */
- pLVREV_Private->pScratchDelayLine[i] =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
-
- LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+ for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+ pLVREV_Private->pDelay_T[i] = (LVM_FLOAT*)calloc(LVREV_MAX_T_DELAY[i], sizeof(LVM_FLOAT));
+ /* Scratch for each delay line output */
+ pLVREV_Private->pScratchDelayLine[i] = (LVM_FLOAT*)calloc(MaxBlockSize, sizeof(LVM_FLOAT));
}
/* All-pass delay buffer addresses and sizes */
- pLVREV_Private->T[0] = LVREV_MAX_T0_DELAY;
- pLVREV_Private->T[1] = LVREV_MAX_T1_DELAY;
- pLVREV_Private->T[2] = LVREV_MAX_T2_DELAY;
- pLVREV_Private->T[3] = LVREV_MAX_T3_DELAY;
+ for (size_t i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->T[i] = LVREV_MAX_T_DELAY[i];
+ }
pLVREV_Private->AB_Selection = 1; /* Select smoothing A to B */
- /* Fast coefficient memory base address */
- pLVREV_Private->pFastCoef =
- (LVREV_FastCoef_st*)InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
/* General purpose scratch */
- pLVREV_Private->pScratch =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+ pLVREV_Private->pScratch = (LVM_FLOAT*)calloc(MaxBlockSize, sizeof(LVM_FLOAT));
/* Mono->stereo input save for end mix */
- pLVREV_Private->pInputSave =
- (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
- LoadConst_Float(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize * 2));
+ pLVREV_Private->pInputSave = (LVM_FLOAT*)calloc(FCC_2 * MaxBlockSize, sizeof(LVM_FLOAT));
/*
* Save the instance parameters in the instance structure
@@ -299,18 +204,67 @@
pLVREV_Private->FeedbackMixer[i].Target = 0;
}
/* Delay tap index */
- pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
- pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
- pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
- pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
- pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
- pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
- pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
- pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+ for (size_t i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->A_DelaySize[i] = LVREV_MAX_AP_DELAY[i];
+ pLVREV_Private->B_DelaySize[i] = LVREV_MAX_AP_DELAY[i];
+ }
+
+ pLVREV_Private->pRevHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ pLVREV_Private->pRevLPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ for (int i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->revLPFBiquad[i].reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ }
LVREV_ClearAudioBuffers(*phInstance);
return LVREV_SUCCESS;
}
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_FreeInstance */
+/* */
+/* DESCRIPTION: */
+/* This function is used to free the internal allocations of the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS free instance succeeded */
+/* LVREV_NULLADDRESS Instance is NULL */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_FreeInstance(LVREV_Handle_t hInstance) {
+ if (hInstance == LVM_NULL) {
+ return LVREV_NULLADDRESS;
+ }
+
+ LVREV_Instance_st* pLVREV_Private = (LVREV_Instance_st*)hInstance;
+
+ for (size_t i = 0; i < pLVREV_Private->InstanceParams.NumDelays; i++) {
+ if (pLVREV_Private->pDelay_T[i]) {
+ free(pLVREV_Private->pDelay_T[i]);
+ pLVREV_Private->pDelay_T[i] = LVM_NULL;
+ }
+ if (pLVREV_Private->pScratchDelayLine[i]) {
+ free(pLVREV_Private->pScratchDelayLine[i]);
+ pLVREV_Private->pScratchDelayLine[i] = LVM_NULL;
+ }
+ }
+ if (pLVREV_Private->pScratch) {
+ free(pLVREV_Private->pScratch);
+ pLVREV_Private->pScratch = LVM_NULL;
+ }
+ if (pLVREV_Private->pInputSave) {
+ free(pLVREV_Private->pInputSave);
+ pLVREV_Private->pInputSave = LVM_NULL;
+ }
+
+ delete pLVREV_Private;
+ return LVREV_SUCCESS;
+}
/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
deleted file mode 100644
index 2c1e04d..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/****************************************************************************************/
-/* */
-/* Includes */
-/* */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-#include "InstAlloc.h"
-
-/****************************************************************************************/
-/* */
-/* FUNCTION: LVREV_GetMemoryTable */
-/* */
-/* DESCRIPTION: */
-/* This function is used for memory allocation and free. It can be called in */
-/* two ways: */
-/* */
-/* hInstance = NULL Returns the memory requirements */
-/* hInstance = Instance handle Returns the memory requirements and allocated */
-/* base addresses. */
-/* */
-/* When this function is called for memory allocation (hInstance=NULL) the memory */
-/* base address pointers are NULL on return. */
-/* */
-/* When the function is called for free (hInstance = Instance Handle) the memory */
-/* table returns the allocated memory and base addresses used during initialisation. */
-/* */
-/* PARAMETERS: */
-/* hInstance Instance Handle */
-/* pMemoryTable Pointer to an empty memory table */
-/* pInstanceParams Pointer to the instance parameters */
-/* */
-/* RETURNS: */
-/* LVREV_Success Succeeded */
-/* LVREV_NULLADDRESS When pMemoryTable is NULL */
-/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
-/* is NULL */
-/* */
-/* NOTES: */
-/* 1. This function may be interrupted by the LVREV_Process function */
-/* */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
- LVREV_MemoryTable_st* pMemoryTable,
- LVREV_InstanceParams_st* pInstanceParams) {
- INST_ALLOC SlowData;
- INST_ALLOC FastData;
- INST_ALLOC FastCoef;
- INST_ALLOC Temporary;
- LVM_INT16 i;
- LVM_UINT16 MaxBlockSize;
-
- /*
- * Check for error conditions
- */
- /* Check for NULL pointer */
- if (pMemoryTable == LVM_NULL) {
- return (LVREV_NULLADDRESS);
- }
-
- /*
- * Check all instance parameters are in range
- */
- if (pInstanceParams != LVM_NULL) {
- /*
- * Call for memory allocation, so check the parameters
- */
- /* Check for a non-zero block size */
- if (pInstanceParams->MaxBlockSize == 0) {
- return LVREV_OUTOFRANGE;
- }
-
- /* Check for a valid number of delay lines */
- if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1) &&
- (pInstanceParams->NumDelays != LVREV_DELAYLINES_2) &&
- (pInstanceParams->NumDelays != LVREV_DELAYLINES_4)) {
- return LVREV_OUTOFRANGE;
- }
- }
-
- /*
- * Initialise the InstAlloc instances
- */
- InstAlloc_Init(&SlowData, (void*)LVM_NULL);
- InstAlloc_Init(&FastData, (void*)LVM_NULL);
- InstAlloc_Init(&FastCoef, (void*)LVM_NULL);
- InstAlloc_Init(&Temporary, (void*)LVM_NULL);
-
- /*
- * Fill in the memory table
- */
- if (hInstance == LVM_NULL) {
- /*
- * Check for null pointers
- */
- if (pInstanceParams == LVM_NULL) {
- return (LVREV_NULLADDRESS);
- }
-
- /*
- * Select the maximum internal block size
- */
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- MaxBlockSize = LVREV_MAX_AP3_DELAY;
- } else if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- MaxBlockSize = LVREV_MAX_AP1_DELAY;
- } else {
- MaxBlockSize = LVREV_MAX_AP0_DELAY;
- }
-
- if (MaxBlockSize > pInstanceParams->MaxBlockSize) {
- MaxBlockSize = pInstanceParams->MaxBlockSize;
- }
-
- /*
- * Slow data memory
- */
- InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
- pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size = InstAlloc_GetTotal(&SlowData);
- pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type = LVM_PERSISTENT_SLOW_DATA;
- pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
-
- /*
- * Persistent fast data memory
- */
- InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
- InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
- InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
- }
-
- pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&FastData);
- pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type = LVM_PERSISTENT_FAST_DATA;
- pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
-
- /*
- * Persistent fast coefficient memory
- */
- InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
- pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&FastCoef);
- pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
- pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
-
- /*
- * Temporary fast memory
- */
- /* General purpose scratch memory */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- /* Mono->stereo input saved for end mix */
- InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
- for (i = 0; i < 4; i++) {
- /* A Scratch buffer for each delay line */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
- for (i = 0; i < 2; i++) {
- /* A Scratch buffer for each delay line */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
- }
-
- if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
- for (i = 0; i < 1; i++) {
- /* A Scratch buffer for each delay line */
- InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
- }
- }
-
- pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&Temporary);
- pMemoryTable->Region[LVM_TEMPORARY_FAST].Type = LVM_TEMPORARY_FAST;
- pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
-
- } else {
- LVREV_Instance_st* pLVREV_Private = (LVREV_Instance_st*)hInstance;
-
- /*
- * Read back memory allocation table
- */
- *pMemoryTable = pLVREV_Private->MemoryTable;
- }
-
- return (LVREV_SUCCESS);
-}
-
-/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index b6edb03..9a2f9ca 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -23,6 +23,8 @@
/* Includes */
/* */
/****************************************************************************************/
+
+#include <audio_utils/BiquadFilter.h>
#include "LVREV.h"
#include "LVREV_Tables.h"
#include "BIQUAD.h"
@@ -101,25 +103,9 @@
/* */
/****************************************************************************************/
-/* Fast data structure */
-typedef struct {
- Biquad_1I_Order1_FLOAT_Taps_t HPTaps; /* High pass filter taps */
- Biquad_1I_Order1_FLOAT_Taps_t LPTaps; /* Low pass filter taps */
- Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[4]; /* Reverb low pass filters taps */
-
-} LVREV_FastData_st;
-
-/* Fast coefficient structure */
-typedef struct {
- Biquad_FLOAT_Instance_t HPCoefs; /* High pass filter coefficients */
- Biquad_FLOAT_Instance_t LPCoefs; /* Low pass filter coefficients */
- Biquad_FLOAT_Instance_t RevLPCoefs[4]; /* Reverb low pass filters coefficients */
-
-} LVREV_FastCoef_st;
typedef struct {
/* General */
LVREV_InstanceParams_st InstanceParams; /* Initialisation time instance parameters */
- LVREV_MemoryTable_st MemoryTable; /* Memory table */
LVREV_ControlParams_st CurrentParams; /* Parameters being used */
LVREV_ControlParams_st NewParams; /* New parameters from the \
calling application */
@@ -134,30 +120,34 @@
processing */
/* Aligned memory pointers */
- LVREV_FastData_st* pFastData; /* Fast data memory base address */
- LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
- LVM_FLOAT* pScratchDelayLine[4]; /* Delay line scratch memory */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevHPFBiquad; /* Biquad filter instance for HPF */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevLPFBiquad; /* Biquad filter instance for LPF */
+ std::array<std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>, LVREV_DELAYLINES_4>
+ revLPFBiquad; /* Biquad filter instance for Reverb LPF */
+ LVM_FLOAT* pScratchDelayLine[LVREV_DELAYLINES_4]; /* Delay line scratch memory */
LVM_FLOAT* pScratch; /* Multi ussge scratch */
LVM_FLOAT* pInputSave; /* Reverb block input save for dry/wet
mixing*/
/* Feedback matrix */
- Mix_1St_Cll_FLOAT_t FeedbackMixer[4]; /* Mixer for Pop and Click Suppression \
+ Mix_1St_Cll_FLOAT_t FeedbackMixer[LVREV_DELAYLINES_4]; /* Mixer for Pop and Click Suppression \
caused by feedback Gain */
/* All-Pass Filter */
- LVM_INT32 T[4]; /* Maximum delay size of buffer */
- LVM_FLOAT* pDelay_T[4]; /* Pointer to delay buffers */
- LVM_INT32 Delay_AP[4]; /* Offset to AP delay buffer start */
+ LVM_INT32 T[LVREV_DELAYLINES_4]; /* Maximum delay size of buffer */
+ LVM_FLOAT* pDelay_T[LVREV_DELAYLINES_4]; /* Pointer to delay buffers */
+ LVM_INT32 Delay_AP[LVREV_DELAYLINES_4]; /* Offset to AP delay buffer start */
LVM_INT16 AB_Selection; /* Smooth from tap A to B when 1 \
otherwise B to A */
- LVM_INT32 A_DelaySize[4]; /* A delay length in samples */
- LVM_INT32 B_DelaySize[4]; /* B delay length in samples */
- LVM_FLOAT* pOffsetA[4]; /* Offset for the A delay tap */
- LVM_FLOAT* pOffsetB[4]; /* Offset for the B delay tap */
- Mix_2St_Cll_FLOAT_t Mixer_APTaps[4]; /* Smoothed AP delay mixer */
- Mix_1St_Cll_FLOAT_t Mixer_SGFeedback[4]; /* Smoothed SAfeedback gain */
- Mix_1St_Cll_FLOAT_t Mixer_SGFeedforward[4]; /* Smoothed AP feedforward gain */
+ LVM_INT32 A_DelaySize[LVREV_DELAYLINES_4]; /* A delay length in samples */
+ LVM_INT32 B_DelaySize[LVREV_DELAYLINES_4]; /* B delay length in samples */
+ LVM_FLOAT* pOffsetA[LVREV_DELAYLINES_4]; /* Offset for the A delay tap */
+ LVM_FLOAT* pOffsetB[LVREV_DELAYLINES_4]; /* Offset for the B delay tap */
+ Mix_2St_Cll_FLOAT_t Mixer_APTaps[LVREV_DELAYLINES_4]; /* Smoothed AP delay mixer */
+ Mix_1St_Cll_FLOAT_t Mixer_SGFeedback[LVREV_DELAYLINES_4]; /* Smoothed SAfeedback gain */
+ Mix_1St_Cll_FLOAT_t Mixer_SGFeedforward[LVREV_DELAYLINES_4]; /* Smoothed AP feedforward gain */
/* Output gain */
Mix_2St_Cll_FLOAT_t BypassMixer; /* Dry/wet mixer */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
index ed3b89c..f9c3266 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
@@ -204,11 +204,12 @@
/*
* High pass filter
*/
- FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+ pPrivate->pRevHPFBiquad->process(pTemp, pTemp, NumSamples);
+
/*
* Low pass filter
*/
- FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+ pPrivate->pRevLPFBiquad->process(pTemp, pTemp, NumSamples);
/*
* Process all delay lines
@@ -253,8 +254,7 @@
/*
* Low pass filter
*/
- FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j], pDelayLine, pDelayLine,
- (LVM_INT16)NumSamples);
+ pPrivate->revLPFBiquad[j]->process(pDelayLine, pDelayLine, NumSamples);
}
/*
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
index 35a6522..bb6cf12 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
@@ -29,6 +29,11 @@
/* */
/****************************************************************************************/
+const LVM_INT16 LVREV_MAX_T_DELAY[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY,
+ LVREV_MAX_T3_DELAY};
+const LVM_INT16 LVREV_MAX_AP_DELAY[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY,
+ LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
/* Table with supported sampling rates. The table can be indexed using LVM_Fs_en */
const LVM_UINT32 LVM_FsTable[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000,
44100, 48000, 88200, 96000, 176400, 192000};
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
index 4b0dcca..723d1ff 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -35,6 +35,8 @@
extern LVM_UINT32 LVM_GetFsFromTable(LVM_Fs_en FsIndex);
extern const LVM_FLOAT LVREV_GainPolyTable[24][5];
+extern const LVM_INT16 LVREV_MAX_T_DELAY[];
+extern const LVM_INT16 LVREV_MAX_AP_DELAY[];
#endif /** _LVREV_TABLES_H_ **/
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
index 4e90a42..8e63502 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#include <system/audio.h>
#include "LVPSA.h"
#include "LVPSA_Private.h"
#include "VectorArithmetic.h"
@@ -182,6 +183,11 @@
break;
}
}
+ /*
+ * Create biquad instance
+ */
+ pInst->specBiquad.resize(pInst->nRelevantFilters,
+ android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
LVPSA_SetBPFiltersType(pInst, &Params);
LVPSA_SetBPFCoefficients(pInst, &Params);
LVPSA_SetQPFCoefficients(pInst, &Params);
@@ -302,8 +308,13 @@
/*
* Set the coefficients
*/
- BP_1I_D16F32Cll_TRC_WRA_01_Init(&pInst->pBP_Instances[ii], &pInst->pBP_Taps[ii],
- &Coefficients);
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInst->specBiquad[ii]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
break;
}
@@ -319,8 +330,13 @@
/*
* Set the coefficients
*/
- BP_1I_D16F16Css_TRC_WRA_01_Init(&pInst->pBP_Instances[ii], &pInst->pBP_Taps[ii],
- &Coefficients);
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInst->specBiquad[ii]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
break;
}
}
@@ -604,18 +620,8 @@
/* */
/************************************************************************************/
LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t* pInst) {
- LVM_INT8* pTapAddress;
- LVM_UINT32 i;
-
- /* Band Pass filters taps */
- pTapAddress = (LVM_INT8*)pInst->pBP_Taps;
- for (i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t); i++) {
- pTapAddress[i] = 0;
- }
- /* Quasi-peak filters taps */
- pTapAddress = (LVM_INT8*)pInst->pQPD_Taps;
- for (i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++) {
- pTapAddress[i] = 0;
+ for (size_t i = 0; i < pInst->specBiquad.size(); i++) {
+ pInst->specBiquad[i].clear();
}
return (LVPSA_OK);
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
index 9a2b29f..a0f28b1 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
@@ -18,7 +18,6 @@
#include <stdlib.h>
#include "LVPSA.h"
#include "LVPSA_Private.h"
-#include "InstAlloc.h"
/************************************************************************************/
/* */
@@ -49,10 +48,7 @@
LVM_UINT32 BufferLength = 0;
/* Set the instance handle if not already initialised */
- *phInstance = calloc(1, sizeof(*pLVPSA_Inst));
- if (*phInstance == LVM_NULL) {
- return LVPSA_ERROR_NULLADDRESS;
- }
+ *phInstance = new LVPSA_InstancePr_t{};
pLVPSA_Inst = (LVPSA_InstancePr_t*)*phInstance;
pLVPSA_Inst->pScratch = pScratch;
@@ -108,21 +104,11 @@
if (pLVPSA_Inst->pBPFiltersPrecision == LVM_NULL) {
return LVPSA_ERROR_NULLADDRESS;
}
- pLVPSA_Inst->pBP_Instances = (Biquad_FLOAT_Instance_t*)calloc(
- pInitParams->nBands, sizeof(*(pLVPSA_Inst->pBP_Instances)));
- if (pLVPSA_Inst->pBP_Instances == LVM_NULL) {
- return LVPSA_ERROR_NULLADDRESS;
- }
pLVPSA_Inst->pQPD_States =
(QPD_FLOAT_State_t*)calloc(pInitParams->nBands, sizeof(*(pLVPSA_Inst->pQPD_States)));
if (pLVPSA_Inst->pQPD_States == LVM_NULL) {
return LVPSA_ERROR_NULLADDRESS;
}
- pLVPSA_Inst->pBP_Taps = (Biquad_1I_Order2_FLOAT_Taps_t*)calloc(
- pInitParams->nBands, sizeof(*(pLVPSA_Inst->pBP_Taps)));
- if (pLVPSA_Inst->pBP_Taps == LVM_NULL) {
- return LVPSA_ERROR_NULLADDRESS;
- }
pLVPSA_Inst->pQPD_Taps =
(QPD_FLOAT_Taps_t*)calloc(pInitParams->nBands, sizeof(*(pLVPSA_Inst->pQPD_Taps)));
if (pLVPSA_Inst->pQPD_Taps == LVM_NULL) {
@@ -193,22 +179,14 @@
free(pLVPSA_Inst->pBPFiltersPrecision);
pLVPSA_Inst->pBPFiltersPrecision = LVM_NULL;
}
- if (pLVPSA_Inst->pBP_Instances != LVM_NULL) {
- free(pLVPSA_Inst->pBP_Instances);
- pLVPSA_Inst->pBP_Instances = LVM_NULL;
- }
if (pLVPSA_Inst->pQPD_States != LVM_NULL) {
free(pLVPSA_Inst->pQPD_States);
pLVPSA_Inst->pQPD_States = LVM_NULL;
}
- if (pLVPSA_Inst->pBP_Taps != LVM_NULL) {
- free(pLVPSA_Inst->pBP_Taps);
- pLVPSA_Inst->pBP_Taps = LVM_NULL;
- }
if (pLVPSA_Inst->pQPD_Taps != LVM_NULL) {
free(pLVPSA_Inst->pQPD_Taps);
pLVPSA_Inst->pQPD_Taps = LVM_NULL;
}
- free(pLVPSA_Inst);
+ delete pLVPSA_Inst;
*phInstance = LVM_NULL;
}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
index e00c11c..605a22e 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -18,6 +18,7 @@
#ifndef _LVPSA_PRIVATE_H_
#define _LVPSA_PRIVATE_H_
+#include <audio_utils/BiquadFilter.h>
#include "LVPSA.h"
#include "BIQUAD.h"
#include "LVPSA_QPD.h"
@@ -82,9 +83,8 @@
LVPSA_BPFilterPrecision_en* pBPFiltersPrecision; /* Points a nBands elements array that contains
the filter precision for each band */
- Biquad_FLOAT_Instance_t* pBP_Instances;
- /* Points a nBands elements array that contains the band pass filter taps for each band */
- Biquad_1I_Order2_FLOAT_Taps_t* pBP_Taps;
+ std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ specBiquad; /* Biquad filter instances */
/* Points a nBands elements array that contains the QPD filter instance for each band */
QPD_FLOAT_State_t* pQPD_States;
/* Points a nBands elements array that contains the QPD filter taps for each band */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
index 299dfd2..c89c4f6 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
@@ -96,13 +96,13 @@
for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++) {
switch (pLVPSA_Inst->pBPFiltersPrecision[ii]) {
case LVPSA_SimplePrecisionFilter:
- BP_1I_D16F16C14_TRC_WRA_01(&pLVPSA_Inst->pBP_Instances[ii], pScratch,
- pScratch + InputBlockSize, (LVM_INT16)InputBlockSize);
+ pLVPSA_Inst->specBiquad[ii].process(pScratch + InputBlockSize, pScratch,
+ (LVM_INT16)InputBlockSize);
break;
case LVPSA_DoublePrecisionFilter:
- BP_1I_D16F32C30_TRC_WRA_01(&pLVPSA_Inst->pBP_Instances[ii], pScratch,
- pScratch + InputBlockSize, (LVM_INT16)InputBlockSize);
+ pLVPSA_Inst->specBiquad[ii].process(pScratch + InputBlockSize, pScratch,
+ (LVM_INT16)InputBlockSize);
break;
default:
break;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp
index efca27d..f805fca 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp
@@ -200,6 +200,8 @@
LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_BypassMix_t* pConfig = (LVCS_BypassMix_t*)&pInstance->BypassMix;
+ LVM_UINT16 destNumSamples =
+ (pInstance->Params.NrChannels == FCC_1) ? NumSamples : FCC_2 * NumSamples;
/*
* Check if the bypass mixer is enabled
@@ -209,12 +211,12 @@
* Apply the bypass mix
*/
LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance, pProcessed, (LVM_FLOAT*)pUnprocessed,
- pOutData, (LVM_INT16)(2 * NumSamples));
+ pOutData, (LVM_INT16)destNumSamples);
/*
* Apply output gain correction shift
*/
Shift_Sat_Float((LVM_INT16)pConfig->Output_Shift, (LVM_FLOAT*)pOutData,
- (LVM_FLOAT*)pOutData, (LVM_INT16)(2 * NumSamples)); /* Left and right*/
+ (LVM_FLOAT*)pOutData, (LVM_INT16)destNumSamples);
}
return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp
index 8f88986..89f2f3b 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp
@@ -180,7 +180,9 @@
if (pInstance->bInOperatingModeTransition != LVM_TRUE) {
pInstance->bTimerDone = LVM_FALSE;
pInstance->TimerParams.TimeInMs =
- (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2) /
+ (LVM_INT16)(((pInstance->Params.NrChannels == FCC_1
+ ? pInstance->Reverberation.DelaySize << 3
+ : pInstance->Reverberation.DelaySize << 2) /
pInstance->TimerParams.SamplingRate) +
1);
LVM_Timer_Init(&pInstance->TimerInstance, &pInstance->TimerParams);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index bad9aef..2b628f1 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -21,6 +21,7 @@
/* */
/************************************************************************************/
+#include <system/audio.h>
#include "LVCS.h"
#include "LVCS_Private.h"
#include "LVCS_Equaliser.h"
@@ -56,14 +57,8 @@
LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
- LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
- LVCS_Data_t* pData;
- LVCS_Coefficient_t* pCoefficients;
- BQ_FLOAT_Coefs_t Coeffs;
const BiquadA012B12CoefsSP_t* pEqualiserCoefTable;
- pData = (LVCS_Data_t*)pInstance->pData;
- pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
/*
* If the sample rate changes re-initialise the filters
*/
@@ -75,34 +70,12 @@
Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
- /* Left and right filters */
- /* Convert incoming coefficients to the required format/ordering */
- Coeffs.A0 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A0;
- Coeffs.A1 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A1;
- Coeffs.A2 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A2;
- Coeffs.B1 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B1;
- Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
-
- LoadConst_Float((LVM_INT16)0, /* Value */
- (LVM_FLOAT*)&pData->EqualiserBiquadTaps, /* Destination */
- /* Number of words */
- (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
-
- BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
- &pData->EqualiserBiquadTaps, &Coeffs);
-
- /* Callbacks */
- switch (pEqualiserCoefTable[Offset].Scale) {
- case 13:
- pConfig->pBiquadCallBack = BQ_2I_D16F32C13_TRC_WRA_01;
- break;
- case 14:
- pConfig->pBiquadCallBack = BQ_2I_D16F32C14_TRC_WRA_01;
- break;
- case 15:
- pConfig->pBiquadCallBack = BQ_2I_D16F32C15_TRC_WRA_01;
- break;
- }
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ pEqualiserCoefTable[Offset].A0, pEqualiserCoefTable[Offset].A1,
+ pEqualiserCoefTable[Offset].A2, pEqualiserCoefTable[Offset].B1,
+ pEqualiserCoefTable[Offset].B2};
+ pInstance->pEqBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
+ (pParams->NrChannels == FCC_1) ? FCC_1 : FCC_2, coefs));
}
return (LVCS_SUCCESS);
@@ -129,19 +102,13 @@
LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance, LVM_FLOAT* pInputOutput,
LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
- LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
- LVCS_Coefficient_t* pCoefficients;
-
- pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
/*
* Check if the equaliser is required
*/
if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0) {
/* Apply filter to the left and right channels */
- (pConfig->pBiquadCallBack)(
- (Biquad_FLOAT_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
- (LVM_FLOAT*)pInputOutput, (LVM_FLOAT*)pInputOutput, (LVM_INT16)NumSamples);
+ pInstance->pEqBiquad->process(pInputOutput, pInputOutput, NumSamples);
}
return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
index c0d0950..5237344 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -23,12 +23,6 @@
/* Structures */
/* */
/************************************************************************************/
-
-/* Equaliser structure */
-typedef struct {
- void (*pBiquadCallBack)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
-} LVCS_Equaliser_t;
-
/************************************************************************************/
/* */
/* Function prototypes */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
index 5c8f1ae..dd1baf3 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
@@ -55,10 +55,7 @@
* Create the instance handle if not already initialised
*/
if (*phInstance == LVM_NULL) {
- *phInstance = calloc(1, sizeof(*pInstance));
- }
- if (*phInstance == LVM_NULL) {
- return LVCS_NULLADDRESS;
+ *phInstance = new LVCS_Instance_t{};
}
pInstance = (LVCS_Instance_t*)*phInstance;
@@ -123,15 +120,7 @@
if (pInstance == LVM_NULL) {
return;
}
- if (pInstance->pCoeff != LVM_NULL) {
- free(pInstance->pCoeff);
- pInstance->pCoeff = LVM_NULL;
- }
- if (pInstance->pData != LVM_NULL) {
- free(pInstance->pData);
- pInstance->pData = LVM_NULL;
- }
- free(pInstance);
+ delete pInstance;
*phInstance = LVM_NULL;
return;
}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index f9c23b3..58e21bd 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -33,6 +33,7 @@
/* */
/************************************************************************************/
+#include <audio_utils/BiquadFilter.h>
#include "LVCS.h" /* Calling or Application layer definitions */
#include "LVCS_StereoEnhancer.h" /* Stereo enhancer module definitions */
#include "LVCS_ReverbGenerator.h" /* Reverberation module definitions */
@@ -110,7 +111,6 @@
/* Sub-block configurations */
LVCS_StereoEnhancer_t StereoEnhancer; /* Stereo enhancer configuration */
LVCS_ReverbGenerator_t Reverberation; /* Reverberation configuration */
- LVCS_Equaliser_t Equaliser; /* Equaliser configuration */
LVCS_BypassMix_t BypassMix; /* Bypass mixer configuration */
/* Bypass variable */
@@ -120,27 +120,18 @@
LVM_INT16 bTimerDone; /* Timer completion flag */
LVM_Timer_Params_t TimerParams; /* Timer parameters */
LVM_Timer_Instance_t TimerInstance; /* Timer instance */
- void* pCoeff; /* pointer to buffer for equaliser filter coeffs */
- void* pData; /* pointer to buffer for equaliser filter states */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pEqBiquad; /* Biquad filter instance for Equaliser */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevBiquad; /* Biquad filter instance for Reverberation */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pSEMidBiquad; /* Biquad filter instance for Stereo enhancement mid */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pSESideBiquad; /* Biquad filter instance for Stereo enhancement side */
void* pScratch; /* Pointer to bundle scratch buffer */
} LVCS_Instance_t;
-/* Coefficient Structure */
-typedef struct {
- Biquad_FLOAT_Instance_t EqualiserBiquadInstance;
- Biquad_FLOAT_Instance_t ReverbBiquadInstance;
- Biquad_FLOAT_Instance_t SEBiquadInstanceMid;
- Biquad_FLOAT_Instance_t SEBiquadInstanceSide;
-} LVCS_Coefficient_t;
-
-/* Data Structure */
-typedef struct {
- Biquad_2I_Order2_FLOAT_Taps_t EqualiserBiquadTaps;
- Biquad_2I_Order2_FLOAT_Taps_t ReverbBiquadTaps;
- Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
- Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
-} LVCS_Data_t;
void LVCS_TimerCallBack(void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp
index d18f2c3..6af0f75 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp
@@ -75,16 +75,6 @@
LVM_INT32 channels = pInstance->Params.NrChannels;
#define NrFrames NumSamples // alias for clarity
- /*In case of mono processing, stereo input is created from mono
- *and stored in pInData before applying any of the effects.
- *However we do not update the value pInstance->Params.NrChannels
- *at this point.
- *So to treat the pInData as stereo we are setting channels to 2
- */
- if (channels == 1) {
- channels = 2;
- }
-
pScratch = (LVM_FLOAT*)pInstance->pScratch;
/*
@@ -97,11 +87,16 @@
*/
pInput = pScratch + (2 * NrFrames);
pStIn = pScratch + ((LVCS_SCRATCHBUFFERS - 2) * NrFrames);
- /* The first two channel data is extracted from the input data and
- * copied into pInput buffer
- */
- Copy_Float_Mc_Stereo((LVM_FLOAT*)pInData, (LVM_FLOAT*)pInput, NrFrames, channels);
- Copy_Float((LVM_FLOAT*)pInput, (LVM_FLOAT*)pStIn, (LVM_INT16)(2 * NrFrames));
+ if (channels == FCC_1) {
+ Copy_Float((LVM_FLOAT*)pInData, (LVM_FLOAT*)pInput, (LVM_INT16)NrFrames);
+ Copy_Float((LVM_FLOAT*)pInput, (LVM_FLOAT*)pStIn, (LVM_INT16)NrFrames);
+ } else {
+ /* The first two channel data is extracted from the input data and
+ * copied into pInput buffer
+ */
+ Copy_Float_Mc_Stereo((LVM_FLOAT*)pInData, (LVM_FLOAT*)pInput, NrFrames, channels);
+ Copy_Float((LVM_FLOAT*)pInput, (LVM_FLOAT*)pStIn, (LVM_INT16)(FCC_2 * NrFrames));
+ }
/*
* Call the stereo enhancer
*/
@@ -172,10 +167,10 @@
LVCS_ReturnStatus_en err;
/*Extract number of Channels info*/
LVM_INT32 channels = pInstance->Params.NrChannels;
+ LVM_UINT16 destNumSamples = (channels == FCC_1) ? NumSamples : FCC_2 * NumSamples;
+ LVM_INT32 compGainInterval =
+ (channels == FCC_1) ? LVCS_COMPGAINFRAME : FCC_2 * LVCS_COMPGAINFRAME;
#define NrFrames NumSamples // alias for clarity
- if (channels == 1) {
- channels = 2;
- }
/*
* Check the number of samples is not too large
*/
@@ -227,7 +222,7 @@
if (NumSamples < LVCS_COMPGAINFRAME) {
NonLinComp_Float(Gain, /* Compressor gain setting */
- pStereoOut, pStereoOut, (LVM_INT32)(2 * NrFrames));
+ pStereoOut, pStereoOut, (LVM_INT32)destNumSamples);
} else {
LVM_FLOAT GainStep;
LVM_FLOAT FinalGain;
@@ -266,12 +261,15 @@
if (SampleToProcess > LVCS_COMPGAINFRAME) {
NonLinComp_Float(Gain, /* Compressor gain setting */
- pOutPtr, pOutPtr, (LVM_INT32)(2 * LVCS_COMPGAINFRAME));
- pOutPtr += (2 * LVCS_COMPGAINFRAME);
+ pOutPtr, pOutPtr, compGainInterval);
+ pOutPtr += compGainInterval;
SampleToProcess = (LVM_INT16)(SampleToProcess - LVCS_COMPGAINFRAME);
} else {
NonLinComp_Float(Gain, /* Compressor gain setting */
- pOutPtr, pOutPtr, (LVM_INT32)(2 * SampleToProcess));
+ pOutPtr, pOutPtr,
+ (channels == FCC_1)
+ ? (LVM_INT32)(SampleToProcess)
+ : (LVM_INT32)(FCC_2 * SampleToProcess));
SampleToProcess = 0;
}
}
@@ -297,7 +295,7 @@
LVM_Timer(&pInstance->TimerInstance, (LVM_INT16)NumSamples);
}
}
- Copy_Float_Stereo_Mc(pInData, pStereoOut, pOutData, NrFrames, channels);
+ Copy_Float_Stereo_Mc(pInData, (const LVM_FLOAT*)pStereoOut, pOutData, NrFrames, channels);
} else {
if (pInData != pOutData) {
/*
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index f6d2453..c5b6598 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -20,6 +20,7 @@
/* Includes */
/* */
/************************************************************************************/
+#include <system/audio.h>
#include <stdlib.h>
#include "LVCS.h"
#include "LVCS_Private.h"
@@ -62,28 +63,8 @@
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
- LVCS_Data_t* pData;
- LVCS_Coefficient_t* pCoefficients;
- BQ_FLOAT_Coefs_t Coeffs;
const BiquadA012B12CoefsSP_t* pReverbCoefTable;
- if (pInstance->pData == LVM_NULL) {
- pInstance->pData = pData = (LVCS_Data_t*)calloc(1, sizeof(*pData));
- if (pData == LVM_NULL) {
- return LVCS_NULLADDRESS;
- }
- } else {
- pData = (LVCS_Data_t*)pInstance->pData;
- }
- if (pInstance->pCoeff == LVM_NULL) {
- pInstance->pCoeff = pCoefficients = (LVCS_Coefficient_t*)calloc(1, sizeof(*pCoefficients));
- if (pCoefficients == LVM_NULL) {
- return LVCS_NULLADDRESS;
- }
- } else {
- pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
- }
-
/*
* Initialise the delay and filters if:
* - the sample rate has changed
@@ -97,7 +78,8 @@
*/
Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
- pConfig->DelaySize = (LVM_INT16)(2 * Delay);
+ pConfig->DelaySize =
+ (pParams->NrChannels == FCC_1) ? (LVM_INT16)Delay : (LVM_INT16)(FCC_2 * Delay);
pConfig->DelayOffset = 0;
LoadConst_Float(0, /* Value */
(LVM_FLOAT*)&pConfig->StereoSamples[0], /* Destination */
@@ -109,30 +91,12 @@
Offset = (LVM_UINT16)pParams->SampleRate;
pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
- /* Convert incoming coefficients to the required format/ordering */
- Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
- Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
- Coeffs.A2 = (LVM_FLOAT)pReverbCoefTable[Offset].A2;
- Coeffs.B1 = (LVM_FLOAT)-pReverbCoefTable[Offset].B1;
- Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
-
- LoadConst_Float(0, /* Value */
- (LVM_FLOAT*)&pData->ReverbBiquadTaps, /* Destination */
- /* Number of words */
- (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
-
- BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
- &pData->ReverbBiquadTaps, &Coeffs);
-
- /* Callbacks */
- switch (pReverbCoefTable[Offset].Scale) {
- case 14:
- pConfig->pBiquadCallBack = BQ_2I_D16F16C14_TRC_WRA_01;
- break;
- case 15:
- pConfig->pBiquadCallBack = BQ_2I_D16F16C15_TRC_WRA_01;
- break;
- }
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ pReverbCoefTable[Offset].A0, pReverbCoefTable[Offset].A1,
+ pReverbCoefTable[Offset].A2, pReverbCoefTable[Offset].B1,
+ pReverbCoefTable[Offset].B2};
+ pInstance->pRevBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
+ (pParams->NrChannels == FCC_1) ? FCC_1 : FCC_2, coefs));
/*
* Setup the mixer
@@ -190,10 +154,11 @@
LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
- LVCS_Coefficient_t* pCoefficients;
LVM_FLOAT* pScratch;
+ LVM_INT32 NumChannels = pInstance->Params.NrChannels;
+ LVM_UINT16 destNumSamples =
+ (pInstance->Params.NrChannels == FCC_1) ? NumSamples : FCC_2 * NumSamples;
- pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
pScratch = (LVM_FLOAT*)pInstance->pScratch;
/*
@@ -203,9 +168,9 @@
/*
* Reverb not required so just copy the data
*/
- Copy_Float((LVM_FLOAT*)pInData, /* Source */
- (LVM_FLOAT*)pOutData, /* Destination */
- (LVM_INT16)(2 * NumSamples)); /* Left and right */
+ Copy_Float((LVM_FLOAT*)pInData, /* Source */
+ (LVM_FLOAT*)pOutData, /* Destination */
+ (LVM_INT16)destNumSamples); /* Number of frames */
}
/*
@@ -226,25 +191,23 @@
/*
* Copy the input data to the scratch memory
*/
- Copy_Float((LVM_FLOAT*)pInData, /* Source */
- (LVM_FLOAT*)pScratch, /* Destination */
- (LVM_INT16)(2 * NumSamples)); /* Left and right */
+ Copy_Float((LVM_FLOAT*)pInData, /* Source */
+ (LVM_FLOAT*)pScratch, /* Destination */
+ (LVM_INT16)destNumSamples); /* Number of frames */
/*
* Filter the data
*/
- (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
- (LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch,
- (LVM_INT16)NumSamples);
+ pInstance->pRevBiquad->process(pScratch, pScratch, NumSamples);
Mult3s_Float((LVM_FLOAT*)pScratch, pConfig->ReverbLevel, (LVM_FLOAT*)pScratch,
- (LVM_INT16)(2 * NumSamples));
+ (LVM_INT16)destNumSamples); /* Number of frames */
/*
* Apply the delay mix
*/
DelayMix_Float((LVM_FLOAT*)pScratch, &pConfig->StereoSamples[0], pConfig->DelaySize,
- pOutData, &pConfig->DelayOffset, (LVM_INT16)NumSamples);
+ pOutData, &pConfig->DelayOffset, (LVM_INT16)NumSamples, NumChannels);
}
return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
index b666da3..049eef2 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -51,8 +51,6 @@
LVM_FLOAT StereoSamples[2 * LVCS_STEREODELAY_CS_MAX_VAL];
/* Reverb Level */
LVM_FLOAT ReverbLevel;
- /* Filter */
- void (*pBiquadCallBack)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
} LVCS_ReverbGenerator_t;
/************************************************************************************/
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index ffa9c9b..3ca25f9 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -21,6 +21,7 @@
/* */
/************************************************************************************/
+#include <system/audio.h>
#include "LVCS.h"
#include "LVCS_Private.h"
#include "LVCS_StereoEnhancer.h"
@@ -52,16 +53,8 @@
LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
- LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
- LVCS_Data_t* pData;
- LVCS_Coefficient_t* pCoefficient;
- FO_FLOAT_Coefs_t CoeffsMid;
- BQ_FLOAT_Coefs_t CoeffsSide;
const BiquadA012B12CoefsSP_t* pSESideCoefs;
- pData = (LVCS_Data_t*)pInstance->pData;
- pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
-
/*
* If the sample rate or speaker type has changed update the filters
*/
@@ -73,56 +66,20 @@
/* Mid filter */
Offset = (LVM_UINT16)pParams->SampleRate;
- /* Convert incoming coefficients to the required format/ordering */
- CoeffsMid.A0 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A0;
- CoeffsMid.A1 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A1;
- CoeffsMid.B1 = (LVM_FLOAT)-LVCS_SEMidCoefTable[Offset].B1;
-
- /* Clear the taps */
- LoadConst_Float(0, /* Value */
- (LVM_FLOAT*)&pData->SEBiquadTapsMid, /* Destination */
- /* Number of words */
- (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
-
- FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid, &pData->SEBiquadTapsMid,
- &CoeffsMid);
-
- /* Callbacks */
- if (LVCS_SEMidCoefTable[Offset].Scale == 15) {
- pConfig->pBiquadCallBack_Mid = FO_1I_D16F16C15_TRC_WRA_01;
- }
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVCS_SEMidCoefTable[Offset].A0, LVCS_SEMidCoefTable[Offset].A1, 0.0,
+ LVCS_SEMidCoefTable[Offset].B1, 0.0};
+ pInstance->pSEMidBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
Offset = (LVM_UINT16)(pParams->SampleRate);
pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
/* Side filter */
- /* Convert incoming coefficients to the required format/ordering */
- CoeffsSide.A0 = (LVM_FLOAT)pSESideCoefs[Offset].A0;
- CoeffsSide.A1 = (LVM_FLOAT)pSESideCoefs[Offset].A1;
- CoeffsSide.A2 = (LVM_FLOAT)pSESideCoefs[Offset].A2;
- CoeffsSide.B1 = (LVM_FLOAT)-pSESideCoefs[Offset].B1;
- CoeffsSide.B2 = (LVM_FLOAT)-pSESideCoefs[Offset].B2;
-
- /* Clear the taps */
- LoadConst_Float(0, /* Value */
- (LVM_FLOAT*)&pData->SEBiquadTapsSide, /* Destination */
- /* Number of words */
- (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
- /* Callbacks */
- switch (pSESideCoefs[Offset].Scale) {
- case 14:
- BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
- &pData->SEBiquadTapsSide, &CoeffsSide);
-
- pConfig->pBiquadCallBack_Side = BQ_1I_D16F32C14_TRC_WRA_01;
- break;
- case 15:
- BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
- &pData->SEBiquadTapsSide, &CoeffsSide);
-
- pConfig->pBiquadCallBack_Side = BQ_1I_D16F16C15_TRC_WRA_01;
- break;
- }
+ coefs = {pSESideCoefs[Offset].A0, pSESideCoefs[Offset].A1, pSESideCoefs[Offset].A2,
+ pSESideCoefs[Offset].B1, pSESideCoefs[Offset].B2};
+ pInstance->pSESideBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
}
return (LVCS_SUCCESS);
@@ -169,10 +126,10 @@
LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
- LVCS_Coefficient_t* pCoefficient;
LVM_FLOAT* pScratch;
- pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
pScratch = (LVM_FLOAT*)pInstance->pScratch;
+ LVM_INT32 NumChannels = pInstance->Params.NrChannels;
+ LVM_UINT16 destNumSamples = (NumChannels == FCC_1) ? NumSamples : FCC_2 * NumSamples;
/*
* Check if the Stereo Enhancer is enabled
*/
@@ -180,15 +137,18 @@
/*
* Convert from stereo to middle and side
*/
- From2iToMS_Float(pInData, pScratch, pScratch + NumSamples, (LVM_INT16)NumSamples);
+ if (NumChannels == 1) {
+ // Copy same input to scratch as Middle data
+ Copy_Float((LVM_FLOAT*)pInData, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
+ } else {
+ From2iToMS_Float(pInData, pScratch, pScratch + NumSamples, (LVM_INT16)NumSamples);
+ }
/*
* Apply filter to the middle signal
*/
if (pInstance->OutputDevice == LVCS_HEADPHONE) {
- (pConfig->pBiquadCallBack_Mid)(
- (Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
- (LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
+ pInstance->pSEMidBiquad->process(pScratch, pScratch, NumSamples);
} else {
Mult3s_Float(pScratch, /* Source */
(LVM_FLOAT)pConfig->MidGain, /* Gain */
@@ -201,24 +161,27 @@
* and in all modes for mobile speakers
*/
if (pInstance->Params.SourceFormat == LVCS_STEREO) {
- (pConfig->pBiquadCallBack_Side)(
- (Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
- (LVM_FLOAT*)(pScratch + NumSamples), (LVM_FLOAT*)(pScratch + NumSamples),
- (LVM_INT16)NumSamples);
+ pInstance->pSESideBiquad->process(pScratch + NumSamples, pScratch + NumSamples,
+ NumSamples);
}
- /*
- * Convert from middle and side to stereo
- */
- MSTo2i_Sat_Float(pScratch, pScratch + NumSamples, pOutData, (LVM_INT16)NumSamples);
+ if (NumChannels == 1) {
+ // Copy processed Middle data from scratch to pOutData
+ Copy_Float((LVM_FLOAT*)pScratch, (LVM_FLOAT*)pOutData, (LVM_INT16)NumSamples);
+ } else {
+ /*
+ * Convert from middle and side to stereo
+ */
+ MSTo2i_Sat_Float(pScratch, pScratch + NumSamples, pOutData, (LVM_INT16)NumSamples);
+ }
} else {
/*
* The stereo enhancer is disabled so just copy the data
*/
- Copy_Float((LVM_FLOAT*)pInData, /* Source */
- (LVM_FLOAT*)pOutData, /* Destination */
- (LVM_INT16)(2 * NumSamples)); /* Left and right */
+ Copy_Float((LVM_FLOAT*)pInData, /* Source */
+ (LVM_FLOAT*)pOutData, /* Destination */
+ (LVM_INT16)destNumSamples); /* Number of frames */
}
return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
index c92f8a5..0bed591 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -36,15 +36,6 @@
/* Stereo enhancer structure */
typedef struct {
- /*
- * Middle filter
- */
- void (*pBiquadCallBack_Mid)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
-
- /*
- * Side filter
- */
- void (*pBiquadCallBack_Side)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
LVM_FLOAT MidGain; /* Middle gain in mobile speaker mode */
} LVCS_StereoEnhancer_t;
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index d026ab6..9939ed1 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -1,5 +1,64 @@
// Build the unit tests for effects
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+ name: "EffectReverbTest",
+ vendor: true,
+ gtest: true,
+ host_supported: true,
+ srcs: [
+ "EffectReverbTest.cpp",
+ "EffectTestHelper.cpp",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libeffects/lvm/lib/Common/lib",
+ "frameworks/av/media/libeffects/lvm/wrapper/Reverb",
+ ],
+ static_libs: [
+ "libaudioutils",
+ "libreverb",
+ "libreverbwrapper",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+}
+
+cc_test {
+ name: "EffectBundleTest",
+ vendor: true,
+ gtest: true,
+ host_supported: true,
+ test_suites: ["device-tests"],
+ srcs: [
+ "EffectBundleTest.cpp",
+ "EffectTestHelper.cpp",
+ ],
+ static_libs: [
+ "libaudioutils",
+ "libbundlewrapper",
+ "libmusicbundle",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ header_libs: [
+ "libhardware_headers",
+ ],
+}
+
cc_test {
name: "lvmtest",
host_supported: false,
@@ -45,8 +104,9 @@
cc_test {
name: "reverb_test",
- host_supported: false,
+ host_supported: true,
proprietary: true,
+ gtest: false,
include_dirs: [
"frameworks/av/media/libeffects/lvm/wrapper/Reverb",
@@ -59,9 +119,12 @@
shared_libs: [
"libaudioutils",
"liblog",
- "libreverbwrapper",
],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
srcs: [
"reverb_test.cpp",
],
diff --git a/media/libeffects/lvm/tests/EffectBundleTest.cpp b/media/libeffects/lvm/tests/EffectBundleTest.cpp
new file mode 100644
index 0000000..881ffb1
--- /dev/null
+++ b/media/libeffects/lvm/tests/EffectBundleTest.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EffectTestHelper.h"
+using namespace android;
+
+// Update isBassBoost, if the order of effects is updated
+constexpr effect_uuid_t kEffectUuids[] = {
+ // NXP SW BassBoost
+ {0x8631f300, 0x72e2, 0x11df, 0xb57e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // NXP SW Virtualizer
+ {0x1d4033c0, 0x8557, 0x11df, 0x9f2d, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // NXP SW Equalizer
+ {0xce772f20, 0x847d, 0x11df, 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // NXP SW Volume
+ {0x119341a0, 0x8469, 0x11df, 0x81f9, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+};
+
+static bool isBassBoost(const effect_uuid_t* uuid) {
+ // Update this, if the order of effects in kEffectUuids is updated
+ return uuid == &kEffectUuids[0];
+}
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+typedef std::tuple<int, int, int, int, int> SingleEffectTestParam;
+class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
+ public:
+ SingleEffectTest()
+ : mChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ mChannelCount(audio_channel_count_from_out_mask(mChMask)),
+ mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
+ mFrameCount(EffectTestHelper::kFrameCounts[std::get<2>(GetParam())]),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mUuid(&kEffectUuids[std::get<4>(GetParam())]) {}
+
+ const size_t mChMask;
+ const size_t mChannelCount;
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const effect_uuid_t* mUuid;
+};
+
+// Tests applying a single effect
+TEST_P(SingleEffectTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message()
+ << "chMask: " << mChMask << " sampleRate: " << mSampleRate
+ << " frameCount: " << mFrameCount << " loopCount: " << mLoopCount);
+
+ EffectTestHelper effect(mUuid, mChMask, mChMask, mSampleRate, mFrameCount, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(effect.setConfig());
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::vector<float> input(mTotalFrameCount * mChannelCount);
+ std::vector<float> output(mTotalFrameCount * mChannelCount);
+ std::minstd_rand gen(mChMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+ ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data()));
+ ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EffectBundleTestAll, SingleEffectTest,
+ ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
+ ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
+ ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
+ ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumEffectUuids)));
+
+typedef std::tuple<int, int, int, int> SingleEffectComparisonTestParam;
+class SingleEffectComparisonTest
+ : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
+ public:
+ SingleEffectComparisonTest()
+ : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
+ mFrameCount(EffectTestHelper::kFrameCounts[std::get<1>(GetParam())]),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mUuid(&kEffectUuids[std::get<3>(GetParam())]) {}
+
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const effect_uuid_t* mUuid;
+};
+
+// Compares first two channels in multi-channel output to stereo output when same effect is applied
+TEST_P(SingleEffectComparisonTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message() << " sampleRate: " << mSampleRate << " frameCount: "
+ << mFrameCount << " loopCount: " << mLoopCount);
+
+ // Initialize mono input buffer with deterministic pseudo-random values
+ std::vector<float> monoInput(mTotalFrameCount);
+
+ std::minstd_rand gen(mSampleRate);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ for (auto& in : monoInput) {
+ in = dis(gen);
+ }
+
+ // Generate stereo by repeating mono channel data
+ std::vector<float> stereoInput(mTotalFrameCount * FCC_2);
+ adjust_channels(monoInput.data(), FCC_1, stereoInput.data(), FCC_2, sizeof(float),
+ mTotalFrameCount * sizeof(float) * FCC_1);
+
+ // Apply effect on stereo channels
+ EffectTestHelper stereoEffect(mUuid, AUDIO_CHANNEL_OUT_STEREO, AUDIO_CHANNEL_OUT_STEREO,
+ mSampleRate, mFrameCount, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.setConfig());
+
+ std::vector<float> stereoOutput(mTotalFrameCount * FCC_2);
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.process(stereoInput.data(), stereoOutput.data()));
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.releaseEffect());
+
+ // Convert stereo float data to stereo int16_t to be used as reference
+ std::vector<int16_t> stereoRefI16(mTotalFrameCount * FCC_2);
+ memcpy_to_i16_from_float(stereoRefI16.data(), stereoOutput.data(), mTotalFrameCount * FCC_2);
+
+ for (size_t chMask : EffectTestHelper::kChMasks) {
+ size_t channelCount = audio_channel_count_from_out_mask(chMask);
+ EffectTestHelper testEffect(mUuid, chMask, chMask, mSampleRate, mFrameCount, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(testEffect.setConfig());
+
+ std::vector<float> testInput(mTotalFrameCount * channelCount);
+
+ // Repeat mono channel data to all the channels
+ // adjust_channels() zero fills channels > 2, hence can't be used here
+ for (size_t i = 0; i < mTotalFrameCount; ++i) {
+ auto* fp = &testInput[i * channelCount];
+ std::fill(fp, fp + channelCount, monoInput[i]);
+ }
+
+ std::vector<float> testOutput(mTotalFrameCount * channelCount);
+ ASSERT_NO_FATAL_FAILURE(testEffect.process(testInput.data(), testOutput.data()));
+ ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
+
+ // Extract first two channels
+ std::vector<float> stereoTestOutput(mTotalFrameCount * FCC_2);
+ adjust_channels(testOutput.data(), channelCount, stereoTestOutput.data(), FCC_2,
+ sizeof(float), mTotalFrameCount * sizeof(float) * channelCount);
+
+ // Convert the test data to int16_t
+ std::vector<int16_t> stereoTestI16(mTotalFrameCount * FCC_2);
+ memcpy_to_i16_from_float(stereoTestI16.data(), stereoTestOutput.data(),
+ mTotalFrameCount * FCC_2);
+
+ if (isBassBoost(mUuid)) {
+ // SNR must be above the threshold
+ float snr = computeSnr<int16_t>(stereoRefI16.data(), stereoTestI16.data(),
+ mTotalFrameCount * FCC_2);
+ ASSERT_GT(snr, EffectTestHelper::kSNRThreshold)
+ << "SNR " << snr << "is lower than " << EffectTestHelper::kSNRThreshold;
+ } else {
+ ASSERT_EQ(0,
+ memcmp(stereoRefI16.data(), stereoTestI16.data(), mTotalFrameCount * FCC_2))
+ << "First two channels do not match with stereo output \n";
+ }
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EffectBundleTestAll, SingleEffectComparisonTest,
+ ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
+ ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
+ ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumEffectUuids)));
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ return status;
+}
diff --git a/media/libeffects/lvm/tests/EffectReverbTest.cpp b/media/libeffects/lvm/tests/EffectReverbTest.cpp
new file mode 100644
index 0000000..59453eb
--- /dev/null
+++ b/media/libeffects/lvm/tests/EffectReverbTest.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <audio_effects/effect_presetreverb.h>
+#include <VectorArithmetic.h>
+
+#include "EffectTestHelper.h"
+using namespace android;
+
+constexpr effect_uuid_t kEffectUuids[] = {
+ // NXP SW insert environmental reverb
+ {0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // NXP SW insert preset reverb
+ {0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // NXP SW auxiliary environmental reverb
+ {0x4a387fc0, 0x8ab3, 0x11df, 0x8bad, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // NXP SW auxiliary preset reverb
+ {0xf29a1400, 0xa3bb, 0x11df, 0x8ddc, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+};
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+static bool isAuxMode(const effect_uuid_t* uuid) {
+ // Update this, if the order of effects in kEffectUuids is updated
+ return (uuid == &kEffectUuids[2] || uuid == &kEffectUuids[3]);
+}
+
+constexpr int kPresets[] = {
+ REVERB_PRESET_NONE, REVERB_PRESET_SMALLROOM, REVERB_PRESET_MEDIUMROOM,
+ REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
+ REVERB_PRESET_PLATE,
+};
+
+constexpr size_t kNumPresets = std::size(kPresets);
+
+typedef std::tuple<int, int, int, int, int, int> SingleEffectTestParam;
+class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
+ public:
+ SingleEffectTest()
+ : mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
+ mFrameCount(EffectTestHelper::kFrameCounts[std::get<2>(GetParam())]),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mUuid(&kEffectUuids[std::get<4>(GetParam())]),
+ mInChMask(isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO
+ : EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
+ mOutChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
+ mPreset(kPresets[std::get<5>(GetParam())]) {}
+
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const effect_uuid_t* mUuid;
+ const size_t mInChMask;
+ const size_t mInChannelCount;
+ const size_t mOutChMask;
+ const size_t mOutChannelCount;
+ const size_t mPreset;
+};
+
+// Tests applying a single effect
+TEST_P(SingleEffectTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message() << "outChMask: " << mOutChMask << " sampleRate: " << mSampleRate
+ << " frameCount: " << mFrameCount
+ << " loopCount: " << mLoopCount << " preset: " << mPreset);
+
+ EffectTestHelper effect(mUuid, mInChMask, mOutChMask, mSampleRate, mFrameCount, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(effect.setConfig());
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(REVERB_PARAM_PRESET, mPreset));
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::vector<float> input(mTotalFrameCount * mInChannelCount);
+ std::vector<float> output(mTotalFrameCount * mOutChannelCount);
+ std::minstd_rand gen(mOutChMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+ ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data()));
+ ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EffectReverbTestAll, SingleEffectTest,
+ ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
+ ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
+ ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
+ ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumEffectUuids),
+ ::testing::Range(0, (int)kNumPresets)));
+
+typedef std::tuple<int, int, int, int, int> SingleEffectComparisonTestParam;
+class SingleEffectComparisonTest
+ : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
+ public:
+ SingleEffectComparisonTest()
+ : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
+ mFrameCount(EffectTestHelper::kFrameCounts[std::get<1>(GetParam())]),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mUuid(&kEffectUuids[std::get<3>(GetParam())]),
+ mPreset(kPresets[std::get<4>(GetParam())]) {}
+
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const effect_uuid_t* mUuid;
+ const size_t mPreset;
+};
+
+// Compares first two channels in multi-channel output to stereo output when same effect is applied
+TEST_P(SingleEffectComparisonTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message()
+ << " sampleRate: " << mSampleRate << " frameCount: " << mFrameCount
+ << " loopCount: " << mLoopCount << " preset: " << mPreset);
+
+ // Initialize mono input buffer with deterministic pseudo-random values
+ std::vector<float> monoInput(mTotalFrameCount);
+
+ std::minstd_rand gen(mSampleRate);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ for (auto& in : monoInput) {
+ in = dis(gen);
+ }
+
+ // Generate stereo by repeating mono channel data
+ std::vector<float> stereoInput(mTotalFrameCount * FCC_2);
+ adjust_channels(monoInput.data(), FCC_1, stereoInput.data(), FCC_2, sizeof(float),
+ mTotalFrameCount * sizeof(float) * FCC_1);
+
+ // Apply effect on stereo channels
+ EffectTestHelper stereoEffect(
+ mUuid, isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_CHANNEL_OUT_STEREO, mSampleRate, mFrameCount, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.setConfig());
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.setParam(REVERB_PARAM_PRESET, mPreset));
+
+ std::vector<float> stereoOutput(mTotalFrameCount * FCC_2);
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.process(
+ (isAuxMode(mUuid) ? monoInput.data() : stereoInput.data()), stereoOutput.data()));
+ ASSERT_NO_FATAL_FAILURE(stereoEffect.releaseEffect());
+
+ // Average of both channels data is stored for mono comparison
+ std::vector<float> monoOutput(mTotalFrameCount);
+ From2iToMono_Float((const float*)stereoOutput.data(), monoOutput.data(), mTotalFrameCount);
+
+ // Convert stereo float data to stereo int16_t to be used as reference
+ std::vector<int16_t> stereoRefI16(mTotalFrameCount * FCC_2);
+ memcpy_to_i16_from_float(stereoRefI16.data(), stereoOutput.data(), mTotalFrameCount * FCC_2);
+
+ // mono int16_t to be used as refernece for mono comparison
+ std::vector<int16_t> monoRefI16(mTotalFrameCount);
+ memcpy_to_i16_from_float(monoRefI16.data(), monoOutput.data(), mTotalFrameCount);
+
+ for (size_t outChMask : EffectTestHelper::kChMasks) {
+ size_t outChannelCount = audio_channel_count_from_out_mask(outChMask);
+ size_t inChMask = isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : outChMask;
+
+ EffectTestHelper testEffect(mUuid, inChMask, outChMask, mSampleRate, mFrameCount,
+ mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(testEffect.setConfig());
+ ASSERT_NO_FATAL_FAILURE(testEffect.setParam(REVERB_PARAM_PRESET, mPreset));
+
+ std::vector<float> testInput(mTotalFrameCount * outChannelCount);
+
+ // Repeat mono channel data to all the channels
+ // adjust_channels() zero fills channels > 2, hence can't be used here
+ for (size_t i = 0; i < mTotalFrameCount; ++i) {
+ auto* fp = &testInput[i * outChannelCount];
+ std::fill(fp, fp + outChannelCount, monoInput[i]);
+ }
+
+ std::vector<float> testOutput(mTotalFrameCount * outChannelCount);
+ ASSERT_NO_FATAL_FAILURE(testEffect.process(
+ (isAuxMode(mUuid) ? monoInput.data() : testInput.data()), testOutput.data()));
+ ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
+
+ if (outChannelCount == FCC_1) {
+ // Convert the test data to int16_t
+ std::vector<int16_t> monoTestI16(mTotalFrameCount);
+ memcpy_to_i16_from_float(monoTestI16.data(), testOutput.data(), mTotalFrameCount);
+
+ ASSERT_EQ(0, memcmp(monoRefI16.data(), monoTestI16.data(), mTotalFrameCount * FCC_2))
+ << "Mono channel do not match with reference output \n";
+ } else {
+ // Extract first two channels
+ std::vector<float> stereoTestOutput(mTotalFrameCount * FCC_2);
+ adjust_channels(testOutput.data(), outChannelCount, stereoTestOutput.data(), FCC_2,
+ sizeof(float), mTotalFrameCount * sizeof(float) * outChannelCount);
+
+ // Convert the test data to int16_t
+ std::vector<int16_t> stereoTestI16(mTotalFrameCount * FCC_2);
+ memcpy_to_i16_from_float(stereoTestI16.data(), stereoTestOutput.data(),
+ mTotalFrameCount * FCC_2);
+
+ ASSERT_EQ(0,
+ memcmp(stereoRefI16.data(), stereoTestI16.data(), mTotalFrameCount * FCC_2))
+ << "First two channels do not match with stereo output \n";
+ }
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EffectReverbTestAll, SingleEffectComparisonTest,
+ ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
+ ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
+ ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumEffectUuids),
+ ::testing::Range(0, (int)kNumPresets)));
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ return status;
+}
diff --git a/media/libeffects/lvm/tests/EffectTestHelper.cpp b/media/libeffects/lvm/tests/EffectTestHelper.cpp
new file mode 100644
index 0000000..625c15a
--- /dev/null
+++ b/media/libeffects/lvm/tests/EffectTestHelper.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EffectTestHelper.h"
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+
+namespace android {
+
+void EffectTestHelper::createEffect() {
+ int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(mUuid, 1, 1, &mEffectHandle);
+ ASSERT_EQ(status, 0) << "create_effect returned an error " << status;
+}
+
+void EffectTestHelper::releaseEffect() {
+ int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(mEffectHandle);
+ ASSERT_EQ(status, 0) << "release_effect returned an error " << status;
+}
+
+void EffectTestHelper::setConfig() {
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = mSampleRate;
+ config.inputCfg.channels = mInChMask;
+ config.outputCfg.channels = mOutChMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ int status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ ASSERT_EQ(status, 0) << "set_config returned an error " << status;
+ ASSERT_EQ(reply, 0) << "set_config reply non zero " << reply;
+
+ status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ ASSERT_EQ(status, 0) << "cmd_enable returned an error " << status;
+ ASSERT_EQ(reply, 0) << "cmd_enable reply non zero " << reply;
+}
+
+void EffectTestHelper::setParam(uint32_t type, uint32_t value) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {type, value};
+ auto effectParam = new effect_param_t[sizeof(effect_param_t) + sizeof(paramData)];
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ effectParam->vsize = sizeof(paramData[1]);
+ int status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + sizeof(paramData), effectParam,
+ &replySize, &reply);
+ delete[] effectParam;
+ ASSERT_EQ(status, 0) << "set_param returned an error " << status;
+ ASSERT_EQ(reply, 0) << "set_param reply non zero " << reply;
+}
+
+void EffectTestHelper::process(float* input, float* output) {
+ audio_buffer_t inBuffer = {.frameCount = mFrameCount, .f32 = input};
+ audio_buffer_t outBuffer = {.frameCount = mFrameCount, .f32 = output};
+ for (size_t i = 0; i < mLoopCount; i++) {
+ int status = (*mEffectHandle)->process(mEffectHandle, &inBuffer, &outBuffer);
+ ASSERT_EQ(status, 0) << "process returned an error " << status;
+
+ inBuffer.f32 += mFrameCount * mInChannelCount;
+ outBuffer.f32 += mFrameCount * mOutChannelCount;
+ }
+}
+} // namespace android
diff --git a/media/libeffects/lvm/tests/EffectTestHelper.h b/media/libeffects/lvm/tests/EffectTestHelper.h
new file mode 100644
index 0000000..3854d46
--- /dev/null
+++ b/media/libeffects/lvm/tests/EffectTestHelper.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <array>
+#include <audio_utils/channels.h>
+#include <audio_utils/primitives.h>
+#include <climits>
+#include <cstdlib>
+#include <gtest/gtest.h>
+#include <hardware/audio_effect.h>
+#include <log/log.h>
+#include <random>
+#include <stdint.h>
+#include <system/audio.h>
+#include <vector>
+
+namespace android {
+template <typename T>
+static float computeSnr(const T* ref, const T* tst, size_t count) {
+ double signal{};
+ double noise{};
+
+ for (size_t i = 0; i < count; ++i) {
+ const double value(ref[i]);
+ const double diff(tst[i] - value);
+ signal += value * value;
+ noise += diff * diff;
+ }
+ // Initialized to large value to handle
+ // cases where ref and tst match exactly
+ float snr = FLT_MAX;
+ if (signal > 0.0f && noise > 0.0f) {
+ snr = 10.f * log(signal / noise);
+ }
+ return snr;
+}
+
+class EffectTestHelper {
+ public:
+ EffectTestHelper(const effect_uuid_t* uuid, size_t inChMask, size_t outChMask,
+ size_t sampleRate, size_t frameCount, size_t loopCount)
+ : mUuid(uuid),
+ mInChMask(inChMask),
+ mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
+ mOutChMask(outChMask),
+ mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
+ mSampleRate(sampleRate),
+ mFrameCount(frameCount),
+ mLoopCount(loopCount) {}
+ void createEffect();
+ void releaseEffect();
+ void setConfig();
+ void setParam(uint32_t type, uint32_t val);
+ void process(float* input, float* output);
+
+ // Corresponds to SNR for 1 bit difference between two int16_t signals
+ static constexpr float kSNRThreshold = 90.308998;
+
+ static constexpr audio_channel_mask_t kChMasks[] = {
+ AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_CHANNEL_OUT_2POINT1, AUDIO_CHANNEL_OUT_2POINT0POINT2,
+ AUDIO_CHANNEL_OUT_QUAD, AUDIO_CHANNEL_OUT_QUAD_BACK,
+ AUDIO_CHANNEL_OUT_QUAD_SIDE, AUDIO_CHANNEL_OUT_SURROUND,
+ AUDIO_CHANNEL_INDEX_MASK_4, AUDIO_CHANNEL_OUT_2POINT1POINT2,
+ AUDIO_CHANNEL_OUT_3POINT0POINT2, AUDIO_CHANNEL_OUT_PENTA,
+ AUDIO_CHANNEL_INDEX_MASK_5, AUDIO_CHANNEL_OUT_3POINT1POINT2,
+ AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_5POINT1_BACK,
+ AUDIO_CHANNEL_OUT_5POINT1_SIDE, AUDIO_CHANNEL_INDEX_MASK_6,
+ AUDIO_CHANNEL_OUT_6POINT1, AUDIO_CHANNEL_INDEX_MASK_7,
+ AUDIO_CHANNEL_OUT_5POINT1POINT2, AUDIO_CHANNEL_OUT_7POINT1,
+ AUDIO_CHANNEL_INDEX_MASK_8, AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10, AUDIO_CHANNEL_INDEX_MASK_11,
+ AUDIO_CHANNEL_INDEX_MASK_12, AUDIO_CHANNEL_INDEX_MASK_13,
+ AUDIO_CHANNEL_INDEX_MASK_14, AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16, AUDIO_CHANNEL_INDEX_MASK_17,
+ AUDIO_CHANNEL_INDEX_MASK_18, AUDIO_CHANNEL_INDEX_MASK_19,
+ AUDIO_CHANNEL_INDEX_MASK_20, AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22, AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_INDEX_MASK_24,
+ };
+
+ static constexpr size_t kNumChMasks = std::size(kChMasks);
+
+ static constexpr size_t kSampleRates[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000,
+ 44100, 48000, 88200, 96000, 176400, 192000};
+
+ static constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+ static constexpr size_t kFrameCounts[] = {4, 2048};
+
+ static constexpr size_t kNumFrameCounts = std::size(kFrameCounts);
+
+ static constexpr size_t kLoopCounts[] = {1, 4};
+
+ static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
+
+ private:
+ const effect_uuid_t* mUuid;
+ const size_t mInChMask;
+ const size_t mInChannelCount;
+ const size_t mOutChMask;
+ const size_t mOutChannelCount;
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ effect_handle_t mEffectHandle{};
+};
+} // namespace android
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
index a97acc9..df7ca5a 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
@@ -23,7 +23,7 @@
echo "========================================"
echo "testing lvm"
adb shell mkdir -p $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
adb push $OUT/testcases/snr/arm64/snr $testdir
E_VAL=1
@@ -91,7 +91,7 @@
do
for fs in ${fs_arr[*]}
do
- for chMask in {0..22}
+ for chMask in {0..38}
do
adb shell $testdir/lvmtest -i:$testdir/sinesweepraw.raw \
-o:$testdir/sinesweep_$((chMask))_$((fs)).raw -chMask:$chMask -fs:$fs $flags
@@ -102,6 +102,11 @@
((++error_count))
fi
+ # Do not compare cases where -vcBal is in flags and chMask is 0 (due to
+ # stereo computation)
+ if [[ $flags == *"-vcBal:"* ]] && [[ $chMask -eq 0 ]]; then
+ continue
+ fi
# two channel files should be identical to higher channel
# computation (first 2 channels).
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
index 0c3b0b5..72b370e 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
@@ -23,7 +23,7 @@
echo "========================================"
echo "testing reverb"
adb shell mkdir -p $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
E_VAL=1
cmds="adb push $OUT/testcases/reverb_test/arm/reverb_test $testdir"
@@ -59,9 +59,9 @@
do
for fs in ${fs_arr[*]}
do
- for chMask in {0..22}
+ for chMask in {0..38}
do
- adb shell LD_LIBRARY_PATH=/system/vendor/lib/soundfx $testdir/reverb_test \
+ adb shell $testdir/reverb_test \
--input $testdir/sinesweepraw.raw \
--output $testdir/sinesweep_$((chMask))_$((fs)).raw \
--chMask $chMask $flags --fs $fs --preset $preset_val
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index 5c5f646..e484a1a 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -109,6 +109,22 @@
AUDIO_CHANNEL_OUT_5POINT1POINT2,
AUDIO_CHANNEL_OUT_7POINT1,
AUDIO_CHANNEL_INDEX_MASK_8,
+ AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10,
+ AUDIO_CHANNEL_INDEX_MASK_11,
+ AUDIO_CHANNEL_INDEX_MASK_12,
+ AUDIO_CHANNEL_INDEX_MASK_13,
+ AUDIO_CHANNEL_INDEX_MASK_14,
+ AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16,
+ AUDIO_CHANNEL_INDEX_MASK_17,
+ AUDIO_CHANNEL_INDEX_MASK_18,
+ AUDIO_CHANNEL_INDEX_MASK_19,
+ AUDIO_CHANNEL_INDEX_MASK_20,
+ AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22,
+ AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_INDEX_MASK_24,
};
void printUsage() {
@@ -394,57 +410,16 @@
params->SourceFormat = LVM_MONO;
} else if (params->NrChannels == 2) {
params->SourceFormat = LVM_STEREO;
- } else if (params->NrChannels > 2 && params->NrChannels <= 8) { // FCC_2 FCC_8
+ } else if (params->NrChannels > FCC_2 && params->NrChannels <= FCC_24) {
params->SourceFormat = LVM_MULTICHANNEL;
} else {
return -EINVAL;
}
-
- LVM_Fs_en sampleRate;
- switch (plvmConfigParams->samplingFreq) {
- case 8000:
- sampleRate = LVM_FS_8000;
- break;
- case 11025:
- sampleRate = LVM_FS_11025;
- break;
- case 12000:
- sampleRate = LVM_FS_12000;
- break;
- case 16000:
- sampleRate = LVM_FS_16000;
- break;
- case 22050:
- sampleRate = LVM_FS_22050;
- break;
- case 24000:
- sampleRate = LVM_FS_24000;
- break;
- case 32000:
- sampleRate = LVM_FS_32000;
- break;
- case 44100:
- sampleRate = LVM_FS_44100;
- break;
- case 48000:
- sampleRate = LVM_FS_48000;
- break;
- case 88200:
- sampleRate = LVM_FS_88200;
- break;
- case 96000:
- sampleRate = LVM_FS_96000;
- break;
- case 176400:
- sampleRate = LVM_FS_176400;
- break;
- case 192000:
- sampleRate = LVM_FS_192000;
- break;
- default:
- return -EINVAL;
+ params->SampleRate = lvmFsForSampleRate(plvmConfigParams->samplingFreq);
+ if (params->SampleRate == LVM_FS_INVALID) {
+ ALOGE("lvmControl invalid sampling rate %d", plvmConfigParams->samplingFreq);
+ return -EINVAL;
}
- params->SampleRate = sampleRate;
/* Concert Sound parameters */
params->VirtualizerOperatingMode = plvmConfigParams->csEnable;
@@ -514,19 +489,11 @@
const int ioChannelCount = plvmConfigParams->fChannels;
const int ioFrameSize = ioChannelCount * sizeof(short); // file load size
const int maxChannelCount = std::max(channelCount, ioChannelCount);
- /*
- * Mono input will be converted to 2 channels internally in the process call
- * by copying the same data into the second channel.
- * Hence when channelCount is 1, output buffer should be allocated for
- * 2 channels. The memAllocChCount takes care of allocation of sufficient
- * memory for the output buffer.
- */
- const int memAllocChCount = (channelCount == 1 ? 2 : channelCount);
std::vector<short> in(frameLength * maxChannelCount);
std::vector<short> out(frameLength * maxChannelCount);
std::vector<float> floatIn(frameLength * channelCount);
- std::vector<float> floatOut(frameLength * memAllocChCount);
+ std::vector<float> floatOut(frameLength * channelCount);
int frameCounter = 0;
while (fread(in.data(), ioFrameSize, frameLength, finp) == (size_t)frameLength) {
diff --git a/media/libeffects/lvm/tests/reverb_test.cpp b/media/libeffects/lvm/tests/reverb_test.cpp
index 7cbca9b..dfb6970 100644
--- a/media/libeffects/lvm/tests/reverb_test.cpp
+++ b/media/libeffects/lvm/tests/reverb_test.cpp
@@ -94,6 +94,22 @@
AUDIO_CHANNEL_OUT_5POINT1POINT2,
AUDIO_CHANNEL_OUT_7POINT1,
AUDIO_CHANNEL_INDEX_MASK_8,
+ AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10,
+ AUDIO_CHANNEL_INDEX_MASK_11,
+ AUDIO_CHANNEL_INDEX_MASK_12,
+ AUDIO_CHANNEL_INDEX_MASK_13,
+ AUDIO_CHANNEL_INDEX_MASK_14,
+ AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16,
+ AUDIO_CHANNEL_INDEX_MASK_17,
+ AUDIO_CHANNEL_INDEX_MASK_18,
+ AUDIO_CHANNEL_INDEX_MASK_19,
+ AUDIO_CHANNEL_INDEX_MASK_20,
+ AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22,
+ AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_INDEX_MASK_24,
};
constexpr int kReverbConfigChMaskCount = std::size(kReverbConfigChMask);
@@ -196,7 +212,9 @@
printUsage();
return EXIT_FAILURE;
}
-
+ for (int i = 1; i < argc; i++) {
+ printf("%s ", argv[i]);
+ }
reverbConfigParams_t revConfigParams{}; // default initialize
const char* inputFile = nullptr;
const char* outputFile = nullptr;
@@ -296,9 +314,6 @@
config.inputCfg.samplingRate = config.outputCfg.samplingRate = revConfigParams.sampleRate;
config.inputCfg.channels = config.outputCfg.channels = revConfigParams.chMask;
config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
- if (AUDIO_CHANNEL_OUT_MONO == revConfigParams.chMask) {
- config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- }
if (int status = reverbCreateEffect(&effectHandle, &config, sessionId, ioId,
revConfigParams.auxiliary);
status != 0) {
@@ -330,19 +345,11 @@
const int ioChannelCount = revConfigParams.fChannels;
const int ioFrameSize = ioChannelCount * sizeof(short);
const int maxChannelCount = std::max(channelCount, ioChannelCount);
- /*
- * Mono input will be converted to 2 channels internally in the process call
- * by copying the same data into the second channel.
- * Hence when channelCount is 1, output buffer should be allocated for
- * 2 channels. The outChannelCount takes care of allocation of sufficient
- * memory for the output buffer.
- */
- const int outChannelCount = (channelCount == 1 ? 2 : channelCount);
std::vector<short> in(frameLength * maxChannelCount);
std::vector<short> out(frameLength * maxChannelCount);
std::vector<float> floatIn(frameLength * channelCount);
- std::vector<float> floatOut(frameLength * outChannelCount);
+ std::vector<float> floatOut(frameLength * channelCount);
int frameCounter = 0;
@@ -376,11 +383,11 @@
#else
memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize);
#endif
- memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * outChannelCount);
+ memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount);
- if (ioChannelCount != outChannelCount) {
- adjust_channels(out.data(), outChannelCount, out.data(), ioChannelCount, sizeof(short),
- frameLength * outChannelCount * sizeof(short));
+ if (ioChannelCount != channelCount) {
+ adjust_channels(out.data(), channelCount, out.data(), ioChannelCount, sizeof(short),
+ frameLength * channelCount * sizeof(short));
}
(void)fwrite(out.data(), ioFrameSize, frameLength, outputFp.get());
frameCounter += frameLength;
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index be60aae..e169e3c 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -1,4 +1,23 @@
// music bundle wrapper
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_lvm_wrapper_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libeffects_lvm_wrapper_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libbundlewrapper",
@@ -9,6 +28,7 @@
},
vendor: true,
+ host_supported: true,
srcs: ["Bundle/EffectBundle.cpp"],
cppflags: [
@@ -25,7 +45,6 @@
shared_libs: [
"libaudioutils",
"libcutils",
- "libdl",
"liblog",
],
@@ -38,7 +57,7 @@
}
// reverb wrapper
-cc_library_shared {
+cc_library {
name: "libreverbwrapper",
arch: {
@@ -48,6 +67,7 @@
},
vendor: true,
+ host_supported: true,
srcs: ["Reverb/EffectReverb.cpp"],
cppflags: [
@@ -64,7 +84,6 @@
shared_libs: [
"libaudioutils",
"libcutils",
- "libdl",
"liblog",
],
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 973a164..df64676 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -166,8 +166,8 @@
/* Effect Library Interface Implementation */
-extern "C" int EffectCreate(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId __unused,
- effect_handle_t* pHandle) {
+extern "C" int EffectCreate(const effect_uuid_t* uuid, int32_t sessionId,
+ int32_t /* ioId __unused */, effect_handle_t* pHandle) {
int ret = 0;
int sessionNo = -1;
int i;
@@ -957,51 +957,12 @@
pContext->config = *pConfig;
const LVM_INT16 NrChannels = audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
- switch (pConfig->inputCfg.samplingRate) {
- case 8000:
- SampleRate = LVM_FS_8000;
- pContext->pBundledContext->SamplesPerSecond = 8000 * NrChannels;
- break;
- case 16000:
- SampleRate = LVM_FS_16000;
- pContext->pBundledContext->SamplesPerSecond = 16000 * NrChannels;
- break;
- case 22050:
- SampleRate = LVM_FS_22050;
- pContext->pBundledContext->SamplesPerSecond = 22050 * NrChannels;
- break;
- case 32000:
- SampleRate = LVM_FS_32000;
- pContext->pBundledContext->SamplesPerSecond = 32000 * NrChannels;
- break;
- case 44100:
- SampleRate = LVM_FS_44100;
- pContext->pBundledContext->SamplesPerSecond = 44100 * NrChannels;
- break;
- case 48000:
- SampleRate = LVM_FS_48000;
- pContext->pBundledContext->SamplesPerSecond = 48000 * NrChannels;
- break;
- case 88200:
- SampleRate = LVM_FS_88200;
- pContext->pBundledContext->SamplesPerSecond = 88200 * NrChannels;
- break;
- case 96000:
- SampleRate = LVM_FS_96000;
- pContext->pBundledContext->SamplesPerSecond = 96000 * NrChannels;
- break;
- case 176400:
- SampleRate = LVM_FS_176400;
- pContext->pBundledContext->SamplesPerSecond = 176400 * NrChannels;
- break;
- case 192000:
- SampleRate = LVM_FS_192000;
- pContext->pBundledContext->SamplesPerSecond = 192000 * NrChannels;
- break;
- default:
- ALOGV("\tEffect_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
- return -EINVAL;
+ SampleRate = lvmFsForSampleRate(pConfig->inputCfg.samplingRate);
+ if (SampleRate == LVM_FS_INVALID) {
+ ALOGV("Effect_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+ return -EINVAL;
}
+ pContext->pBundledContext->SamplesPerSecond = pConfig->inputCfg.samplingRate * NrChannels;
if (pContext->pBundledContext->SampleRate != SampleRate ||
pContext->pBundledContext->ChMask != pConfig->inputCfg.channels) {
@@ -1021,6 +982,16 @@
ActiveParams.NrChannels = NrChannels;
ActiveParams.ChMask = pConfig->inputCfg.channels;
+ if (NrChannels == 1) {
+ ActiveParams.SourceFormat = LVM_MONO;
+ } else if (NrChannels == 2) {
+ ActiveParams.SourceFormat = LVM_STEREO;
+ } else if (NrChannels > 2 && NrChannels <= LVM_MAX_CHANNELS) {
+ ActiveParams.SourceFormat = LVM_MULTICHANNEL;
+ } else {
+ return -EINVAL;
+ }
+
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_setConfig")
@@ -1344,7 +1315,8 @@
//
//----------------------------------------------------------------------------
void VirtualizerGetSpeakerAngles(audio_channel_mask_t channelMask,
- audio_devices_t deviceType __unused, int32_t* pSpeakerAngles) {
+ audio_devices_t /* deviceType __unused */,
+ int32_t* pSpeakerAngles) {
// the channel count is guaranteed to be 1 or 2
// the device is guaranteed to be of type headphone
// this virtualizer is always using 2 virtual speakers at -90 and 90deg of azimuth, 0deg of
@@ -1485,8 +1457,8 @@
// pLow: lower band range
// pLow: upper band range
//----------------------------------------------------------------------------
-int32_t EqualizerGetBandFreqRange(EffectContext* pContext __unused, int32_t band, uint32_t* pLow,
- uint32_t* pHi) {
+int32_t EqualizerGetBandFreqRange(EffectContext* /* pContext __unused */, int32_t band,
+ uint32_t* pLow, uint32_t* pHi) {
*pLow = bandFreqRange[band][0];
*pHi = bandFreqRange[band][1];
return 0;
@@ -1509,7 +1481,7 @@
// pLow: lower band range
// pLow: upper band range
//----------------------------------------------------------------------------
-int32_t EqualizerGetBand(EffectContext* pContext __unused, uint32_t targetFreq) {
+int32_t EqualizerGetBand(EffectContext* /* pContext __unused */, uint32_t targetFreq) {
int band = 0;
if (targetFreq < bandFreqRange[0][0]) {
@@ -3394,8 +3366,8 @@
return -EINVAL;
}
- uint32_t device = *(uint32_t*)pCmdData;
- pContext->pBundledContext->nOutputDevice = (audio_devices_t)device;
+ audio_devices_t device = *(audio_devices_t *)pCmdData;
+ pContext->pBundledContext->nOutputDevice = device;
if (pContext->EffectType == LVM_BASS_BOOST) {
if ((device == AUDIO_DEVICE_OUT_SPEAKER) ||
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 9ea70ce..290a7b1 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -33,6 +33,7 @@
#include "EffectReverb.h"
// from Reverb/lib
#include "LVREV.h"
+#include "VectorArithmetic.h"
// effect_handle_t interface implementation for reverb
extern "C" const struct effect_interface_s gReverbInterface;
@@ -190,8 +191,8 @@
/* Effect Library Interface Implementation */
-extern "C" int EffectCreate(const effect_uuid_t* uuid, int32_t sessionId __unused,
- int32_t ioId __unused, effect_handle_t* pHandle) {
+extern "C" int EffectCreate(const effect_uuid_t* uuid, int32_t /* sessionId __unused */,
+ int32_t /* ioId __unused */, effect_handle_t* pHandle) {
int ret;
int i;
int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t*);
@@ -332,6 +333,7 @@
//----------------------------------------------------------------------------
int process(effect_buffer_t* pIn, effect_buffer_t* pOut, int frameCount, ReverbContext* pContext) {
int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
+ int outChannels = audio_channel_count_from_out_mask(pContext->config.outputCfg.channels);
LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
// Reverb only effects the stereo channels in multichannel source.
@@ -454,33 +456,49 @@
}
}
- if (channels > 2) {
+ if (outChannels > 2) {
// Accumulate if required
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
for (int i = 0; i < frameCount; i++) {
- pOut[channels * i] += pContext->OutFrames[FCC_2 * i];
- pOut[channels * i + 1] += pContext->OutFrames[FCC_2 * i + 1];
+ pOut[outChannels * i] += pContext->OutFrames[FCC_2 * i];
+ pOut[outChannels * i + 1] += pContext->OutFrames[FCC_2 * i + 1];
}
} else {
for (int i = 0; i < frameCount; i++) {
- pOut[channels * i] = pContext->OutFrames[FCC_2 * i];
- pOut[channels * i + 1] = pContext->OutFrames[FCC_2 * i + 1];
+ pOut[outChannels * i] = pContext->OutFrames[FCC_2 * i];
+ pOut[outChannels * i + 1] = pContext->OutFrames[FCC_2 * i + 1];
}
}
- for (int i = 0; i < frameCount; i++) {
- for (int j = FCC_2; j < channels; j++) {
- pOut[channels * i + j] = pIn[channels * i + j];
+ if (!pContext->auxiliary) {
+ for (int i = 0; i < frameCount; i++) {
+ // channels and outChannels are expected to be same.
+ for (int j = FCC_2; j < outChannels; j++) {
+ pOut[outChannels * i + j] = pIn[outChannels * i + j];
+ }
}
}
} else {
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
- for (int i = 0; i < frameCount * FCC_2; i++) {
- pOut[i] += pContext->OutFrames[i];
+ if (outChannels == FCC_1) {
+ for (int i = 0; i < frameCount; i++) {
+ pOut[i] +=
+ ((pContext->OutFrames[i * FCC_2] + pContext->OutFrames[i * FCC_2 + 1]) *
+ 0.5f);
+ }
+ } else {
+ for (int i = 0; i < frameCount * FCC_2; i++) {
+ pOut[i] += pContext->OutFrames[i];
+ }
}
} else {
- memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
+ if (outChannels == FCC_1) {
+ From2iToMono_Float((const process_buffer_t*)pContext->OutFrames, pOut, frameCount);
+ } else {
+ memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
+ }
}
}
+
return 0;
} /* end process */
@@ -498,25 +516,9 @@
void Reverb_free(ReverbContext* pContext) {
LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
- LVREV_MemoryTable_st MemTab;
- /* Free the algorithm memory */
- LvmStatus = LVREV_GetMemoryTable(pContext->hInstance, &MemTab, LVM_NULL);
-
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "Reverb_free")
-
- for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) {
- if (MemTab.Region[i].Size != 0) {
- if (MemTab.Region[i].pBaseAddress != NULL) {
- free(MemTab.Region[i].pBaseAddress);
- } else {
- ALOGV("\tLVM_ERROR : free() - trying to free with NULL pointer %" PRIu32
- " bytes "
- "for region %u at %p ERROR\n",
- MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
- }
- }
- }
+ LvmStatus = LVREV_FreeInstance(pContext->hInstance);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_FreeInstance", "Reverb_free")
} /* end Reverb_free */
//----------------------------------------------------------------------------
@@ -546,47 +548,17 @@
CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
((!pContext->auxiliary) && (inputChannels <= LVM_MAX_CHANNELS)));
int outputChannels = audio_channel_count_from_out_mask(pConfig->outputCfg.channels);
- CHECK_ARG(outputChannels >= FCC_2 && outputChannels <= LVM_MAX_CHANNELS);
+ CHECK_ARG(outputChannels <= LVM_MAX_CHANNELS);
CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE ||
pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
CHECK_ARG(pConfig->inputCfg.format == EFFECT_BUFFER_FORMAT);
// ALOGV("\tReverb_setConfig calling memcpy");
pContext->config = *pConfig;
- switch (pConfig->inputCfg.samplingRate) {
- case 8000:
- SampleRate = LVM_FS_8000;
- break;
- case 16000:
- SampleRate = LVM_FS_16000;
- break;
- case 22050:
- SampleRate = LVM_FS_22050;
- break;
- case 32000:
- SampleRate = LVM_FS_32000;
- break;
- case 44100:
- SampleRate = LVM_FS_44100;
- break;
- case 48000:
- SampleRate = LVM_FS_48000;
- break;
- case 88200:
- SampleRate = LVM_FS_88200;
- break;
- case 96000:
- SampleRate = LVM_FS_96000;
- break;
- case 176400:
- SampleRate = LVM_FS_176400;
- break;
- case 192000:
- SampleRate = LVM_FS_192000;
- break;
- default:
- ALOGV("\rReverb_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
- return -EINVAL;
+ SampleRate = lvmFsForSampleRate(pConfig->inputCfg.samplingRate);
+ if (SampleRate == LVM_FS_INVALID) {
+ ALOGE("Reverb_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+ return -EINVAL;
}
if (pContext->SampleRate != SampleRate) {
@@ -686,65 +658,17 @@
LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
LVREV_ControlParams_st params; /* Control Parameters */
LVREV_InstanceParams_st InstParams; /* Instance parameters */
- LVREV_MemoryTable_st MemTab; /* Memory allocation table */
- bool bMallocFailure = LVM_FALSE;
/* Set the capabilities */
InstParams.MaxBlockSize = MAX_CALL_SIZE;
InstParams.SourceFormat = LVM_STEREO; // Max format, could be mono during process
InstParams.NumDelays = LVREV_DELAYLINES_4;
- /* Allocate memory, forcing alignment */
- LvmStatus = LVREV_GetMemoryTable(LVM_NULL, &MemTab, &InstParams);
-
- LVM_ERROR_CHECK(LvmStatus, "LVREV_GetMemoryTable", "Reverb_init")
- if (LvmStatus != LVREV_SUCCESS) return -EINVAL;
-
- ALOGV("\tCreateInstance Successfully called LVM_GetMemoryTable\n");
-
- /* Allocate memory */
- for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) {
- if (MemTab.Region[i].Size != 0) {
- MemTab.Region[i].pBaseAddress = calloc(1, MemTab.Region[i].Size);
-
- if (MemTab.Region[i].pBaseAddress == LVM_NULL) {
- ALOGV("\tLVREV_ERROR :Reverb_init CreateInstance Failed to allocate %" PRIu32
- " bytes for region %u\n",
- MemTab.Region[i].Size, i);
- bMallocFailure = LVM_TRUE;
- } else {
- ALOGV("\tReverb_init CreateInstance allocate %" PRIu32
- " bytes for region %u at %p\n",
- MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
- }
- }
- }
-
- /* If one or more of the memory regions failed to allocate, free the regions that were
- * succesfully allocated and return with an error
- */
- if (bMallocFailure == LVM_TRUE) {
- for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) {
- if (MemTab.Region[i].pBaseAddress == LVM_NULL) {
- ALOGV("\tLVM_ERROR :Reverb_init CreateInstance Failed to allocate %" PRIu32
- " bytes for region %u - Not freeing\n",
- MemTab.Region[i].Size, i);
- } else {
- ALOGV("\tLVM_ERROR :Reverb_init CreateInstance Failed: but allocated %" PRIu32
- " bytes for region %u at %p- free\n",
- MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
- free(MemTab.Region[i].pBaseAddress);
- }
- }
- return -EINVAL;
- }
- ALOGV("\tReverb_init CreateInstance Successfully malloc'd memory\n");
-
/* Initialise */
pContext->hInstance = LVM_NULL;
/* Init sets the instance handle */
- LvmStatus = LVREV_GetInstanceHandle(&pContext->hInstance, &MemTab, &InstParams);
+ LvmStatus = LVREV_GetInstanceHandle(&pContext->hInstance, &InstParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "Reverb_init")
if (LvmStatus != LVREV_SUCCESS) return -EINVAL;
diff --git a/media/libeffects/preprocessing/.clang-format b/media/libeffects/preprocessing/.clang-format
new file mode 120000
index 0000000..f1b4f69
--- /dev/null
+++ b/media/libeffects/preprocessing/.clang-format
@@ -0,0 +1 @@
+../../../../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index 5217cf9..c6e036a 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -1,42 +1,27 @@
// audio preprocessing wrapper
-cc_library_shared {
- name: "libaudiopreprocessing_legacy",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
- srcs: ["PreProcessing.cpp"],
-
- shared_libs: [
- "libwebrtc_audio_preprocessing",
- "libspeexresampler",
- "libutils",
- "liblog",
- ],
-
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=hidden",
- "-Wall",
- "-Werror",
- ],
-
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_preprocessing_license",
],
}
-cc_library_shared {
- name: "libaudiopreprocessing",
- vendor: true,
- relative_install_path: "soundfx",
- srcs: ["PreProcessing.cpp"],
- local_include_dirs: [
- ".",
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libeffects_preprocessing_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_defaults {
+ name: "libaudiopreprocessing-defaults",
+ vendor: true,
+ host_supported: true,
cflags: [
"-Wall",
"-Werror",
@@ -56,6 +41,20 @@
header_libs: [
"libaudioeffects",
"libhardware_headers",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+cc_library {
+ name: "libaudiopreprocessing",
+ defaults: ["libaudiopreprocessing-defaults"],
+ relative_install_path: "soundfx",
+ srcs: ["PreProcessing.cpp"],
+ header_libs: [
"libwebrtc_absl_headers",
],
}
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index d8840b2..19a8b2f 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -18,20 +18,15 @@
#include <string.h>
#define LOG_TAG "PreProcessing"
//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <hardware/audio_effect.h>
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_agc.h>
-#ifndef WEBRTC_LEGACY
+#include <hardware/audio_effect.h>
+#include <utils/Log.h>
+#include <utils/Timers.h>
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
-#include <module_common_types.h>
#include <audio_processing.h>
-#ifdef WEBRTC_LEGACY
-#include "speex/speex_resampler.h"
-#endif
+#include <module_common_types.h>
// undefine to perform multi channels API functional tests
//#define DUAL_MIC_TEST
@@ -44,29 +39,26 @@
#define PREPROC_NUM_SESSIONS 8
// types of pre processing modules
-enum preproc_id
-{
- PREPROC_AGC, // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
- PREPROC_AGC2, // Automatic Gain Control 2
-#endif
- PREPROC_AEC, // Acoustic Echo Canceler
- PREPROC_NS, // Noise Suppressor
+enum preproc_id {
+ PREPROC_AGC, // Automatic Gain Control
+ PREPROC_AGC2, // Automatic Gain Control 2
+ PREPROC_AEC, // Acoustic Echo Canceler
+ PREPROC_NS, // Noise Suppressor
PREPROC_NUM_EFFECTS
};
// Session state
enum preproc_session_state {
- PREPROC_SESSION_STATE_INIT, // initialized
- PREPROC_SESSION_STATE_CONFIG // configuration received
+ PREPROC_SESSION_STATE_INIT, // initialized
+ PREPROC_SESSION_STATE_CONFIG // configuration received
};
// Effect/Preprocessor state
enum preproc_effect_state {
- PREPROC_EFFECT_STATE_INIT, // initialized
- PREPROC_EFFECT_STATE_CREATED, // webRTC engine created
- PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled
- PREPROC_EFFECT_STATE_ACTIVE // active/enabled
+ PREPROC_EFFECT_STATE_INIT, // initialized
+ PREPROC_EFFECT_STATE_CREATED, // webRTC engine created
+ PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled
+ PREPROC_EFFECT_STATE_ACTIVE // active/enabled
};
// handle on webRTC engine
@@ -79,95 +71,66 @@
// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
// Function pointer can be null if no action required.
struct preproc_ops_s {
- int (* create)(preproc_effect_t *fx);
- int (* init)(preproc_effect_t *fx);
- int (* reset)(preproc_effect_t *fx);
- void (* enable)(preproc_effect_t *fx);
- void (* disable)(preproc_effect_t *fx);
- int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
- int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value);
- int (* set_device)(preproc_effect_t *fx, uint32_t device);
+ int (*create)(preproc_effect_t* fx);
+ int (*init)(preproc_effect_t* fx);
+ int (*reset)(preproc_effect_t* fx);
+ void (*enable)(preproc_effect_t* fx);
+ void (*disable)(preproc_effect_t* fx);
+ int (*set_parameter)(preproc_effect_t* fx, void* param, void* value);
+ int (*get_parameter)(preproc_effect_t* fx, void* param, uint32_t* size, void* value);
+ int (*set_device)(preproc_effect_t* fx, uint32_t device);
};
// Effect context
struct preproc_effect_s {
- const struct effect_interface_s *itfe;
- uint32_t procId; // type of pre processor (enum preproc_id)
- uint32_t state; // current state (enum preproc_effect_state)
- preproc_session_t *session; // session the effect is on
- const preproc_ops_t *ops; // effect ops table
- preproc_fx_handle_t engine; // handle on webRTC engine
- uint32_t type; // subtype of effect
+ const struct effect_interface_s* itfe;
+ uint32_t procId; // type of pre processor (enum preproc_id)
+ uint32_t state; // current state (enum preproc_effect_state)
+ preproc_session_t* session; // session the effect is on
+ const preproc_ops_t* ops; // effect ops table
+ preproc_fx_handle_t engine; // handle on webRTC engine
+ uint32_t type; // subtype of effect
#ifdef DUAL_MIC_TEST
- bool aux_channels_on; // support auxiliary channels
- size_t cur_channel_config; // current auciliary channel configuration
+ bool aux_channels_on; // support auxiliary channels
+ size_t cur_channel_config; // current auciliary channel configuration
#endif
};
// Session context
struct preproc_session_s {
- struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
- uint32_t state; // current state (enum preproc_session_state)
- int id; // audio session ID
- int io; // handle of input stream this session is on
- webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
-#ifndef WEBRTC_LEGACY
+ struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
+ uint32_t state; // current state (enum preproc_session_state)
+ int id; // audio session ID
+ int io; // handle of input stream this session is on
+ webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
// Audio Processing module builder
webrtc::AudioProcessingBuilder ap_builder;
-#endif
- size_t apmFrameCount; // buffer size for webRTC process (10 ms)
- uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
- size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
- uint32_t samplingRate; // sampling rate at effect process interface
- uint32_t inChannelCount; // input channel count
- uint32_t outChannelCount; // output channel count
- uint32_t createdMsk; // bit field containing IDs of crested pre processors
- uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
- uint32_t processedMsk; // bit field containing IDs of pre processors already
- // processed in current round
-#ifdef WEBRTC_LEGACY
- webrtc::AudioFrame *procFrame; // audio frame passed to webRTC AMP ProcessStream()
-#else
+ // frameCount represents the size of the buffers used for processing, and must represent 10ms.
+ size_t frameCount;
+ uint32_t samplingRate; // sampling rate at effect process interface
+ uint32_t inChannelCount; // input channel count
+ uint32_t outChannelCount; // output channel count
+ uint32_t createdMsk; // bit field containing IDs of crested pre processors
+ uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
+ uint32_t processedMsk; // bit field containing IDs of pre processors already
+ // processed in current round
// audio config strucutre
webrtc::AudioProcessing::Config config;
webrtc::StreamConfig inputConfig; // input stream configuration
webrtc::StreamConfig outputConfig; // output stream configuration
-#endif
- int16_t *inBuf; // input buffer used when resampling
- size_t inBufSize; // input buffer size in frames
- size_t framesIn; // number of frames in input buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState *inResampler; // handle on input speex resampler
-#endif
- int16_t *outBuf; // output buffer used when resampling
- size_t outBufSize; // output buffer size in frames
- size_t framesOut; // number of frames in output buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState *outResampler; // handle on output speex resampler
-#endif
- uint32_t revChannelCount; // number of channels on reverse stream
- uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
- // with reverse channel
- uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
- // channel already processed in current round
-#ifdef WEBRTC_LEGACY
- webrtc::AudioFrame *revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream()
-#else
+ uint32_t revChannelCount; // number of channels on reverse stream
+ uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
+ // with reverse channel
+ uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
+ // channel already processed in current round
webrtc::StreamConfig revConfig; // reverse stream configuration.
-#endif
- int16_t *revBuf; // reverse channel input buffer
- size_t revBufSize; // reverse channel input buffer size
- size_t framesRev; // number of frames in reverse channel input buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState *revResampler; // handle on reverse channel input speex resampler
-#endif
};
#ifdef DUAL_MIC_TEST
enum {
- PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
- PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
- PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
+ PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
+ PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
+ PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
};
enum {
@@ -180,24 +143,22 @@
};
const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
- {AUDIO_CHANNEL_IN_MONO , 0},
- {AUDIO_CHANNEL_IN_STEREO , 0},
- {AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
- {AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
-};
+ {AUDIO_CHANNEL_IN_MONO, 0},
+ {AUDIO_CHANNEL_IN_STEREO, 0},
+ {AUDIO_CHANNEL_IN_FRONT, AUDIO_CHANNEL_IN_BACK},
+ {AUDIO_CHANNEL_IN_STEREO, AUDIO_CHANNEL_IN_RIGHT}};
bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
- false, // PREPROC_AGC
+ false, // PREPROC_AGC
true, // PREPROC_AEC
true, // PREPROC_NS
};
bool gDualMicEnabled;
-FILE *gPcmDumpFh;
+FILE* gPcmDumpFh;
static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
#endif
-
//------------------------------------------------------------------------------
// Effect descriptors
//------------------------------------------------------------------------------
@@ -207,88 +168,69 @@
// Automatic Gain Control
static const effect_descriptor_t sAgcDescriptor = {
- { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
- { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+ {0x0a8abfe0, 0x654c, 0x11e0, 0xba26, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
EFFECT_CONTROL_API_VERSION,
- (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
- 0, //FIXME indicate CPU load
- 0, //FIXME indicate memory usage
+ (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
+ 0, // FIXME indicate CPU load
+ 0, // FIXME indicate memory usage
"Automatic Gain Control",
- "The Android Open Source Project"
-};
+ "The Android Open Source Project"};
-#ifndef WEBRTC_LEGACY
// Automatic Gain Control 2
static const effect_descriptor_t sAgc2Descriptor = {
- { 0xae3c653b, 0xbe18, 0x4ab8, 0x8938, { 0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac } }, // type
- { 0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, { 0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86 } }, // uuid
+ {0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
+ {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // uuid
EFFECT_CONTROL_API_VERSION,
- (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
- 0, //FIXME indicate CPU load
- 0, //FIXME indicate memory usage
+ (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
+ 0, // FIXME indicate CPU load
+ 0, // FIXME indicate memory usage
"Automatic Gain Control 2",
- "The Android Open Source Project"
-};
-#endif
+ "The Android Open Source Project"};
// Acoustic Echo Cancellation
static const effect_descriptor_t sAecDescriptor = {
- { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
- { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+ {0x7b491460, 0x8d4d, 0x11e0, 0xbd61, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
EFFECT_CONTROL_API_VERSION,
- (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
- 0, //FIXME indicate CPU load
- 0, //FIXME indicate memory usage
+ (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
+ 0, // FIXME indicate CPU load
+ 0, // FIXME indicate memory usage
"Acoustic Echo Canceler",
- "The Android Open Source Project"
-};
+ "The Android Open Source Project"};
// Noise suppression
static const effect_descriptor_t sNsDescriptor = {
- { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
- { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+ {0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
EFFECT_CONTROL_API_VERSION,
- (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
- 0, //FIXME indicate CPU load
- 0, //FIXME indicate memory usage
+ (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
+ 0, // FIXME indicate CPU load
+ 0, // FIXME indicate memory usage
"Noise Suppression",
- "The Android Open Source Project"
-};
+ "The Android Open Source Project"};
-
-static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = {
- &sAgcDescriptor,
-#ifndef WEBRTC_LEGACY
- &sAgc2Descriptor,
-#endif
- &sAecDescriptor,
- &sNsDescriptor
-};
+static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
+ &sAgc2Descriptor,
+ &sAecDescriptor,
+ &sNsDescriptor};
//------------------------------------------------------------------------------
// Helper functions
//------------------------------------------------------------------------------
-const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {
- FX_IID_AGC,
-#ifndef WEBRTC_LEGACY
- FX_IID_AGC2,
-#endif
- FX_IID_AEC,
- FX_IID_NS
-};
+const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
+ FX_IID_AGC2,
+ FX_IID_AEC, FX_IID_NS};
-
-const effect_uuid_t * ProcIdToUuid(int procId)
-{
+const effect_uuid_t* ProcIdToUuid(int procId) {
if (procId >= PREPROC_NUM_EFFECTS) {
return EFFECT_UUID_NULL;
}
return sUuidToPreProcTable[procId];
}
-uint32_t UuidToProcId(const effect_uuid_t * uuid)
-{
+uint32_t UuidToProcId(const effect_uuid_t* uuid) {
size_t i;
for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
@@ -298,15 +240,13 @@
return i;
}
-bool HasReverseStream(uint32_t procId)
-{
+bool HasReverseStream(uint32_t procId) {
if (procId == PREPROC_AEC) {
return true;
}
return false;
}
-
//------------------------------------------------------------------------------
// Automatic Gain Control (AGC)
//------------------------------------------------------------------------------
@@ -315,287 +255,215 @@
static const int kAgcDefaultCompGain = 9;
static const bool kAgcDefaultLimiter = true;
-#ifndef WEBRTC_LEGACY
-int Agc2Init (preproc_effect_t *effect)
-{
+int Agc2Init(preproc_effect_t* effect) {
ALOGV("Agc2Init");
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- effect->session->config.gain_controller2.kRms;
+ effect->session->config.gain_controller2.kRms;
effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
effect->session->apm->ApplyConfig(effect->session->config);
return 0;
}
-#endif
-int AgcInit (preproc_effect_t *effect)
-{
+int AgcInit(preproc_effect_t* effect) {
ALOGV("AgcInit");
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
- agc->set_mode(webrtc::GainControl::kFixedDigital);
- agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
- agc->set_compression_gain_db(kAgcDefaultCompGain);
- agc->enable_limiter(kAgcDefaultLimiter);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return 0;
}
-#ifndef WEBRTC_LEGACY
-int Agc2Create(preproc_effect_t *effect)
-{
+int Agc2Create(preproc_effect_t* effect) {
Agc2Init(effect);
return 0;
}
-#endif
-int AgcCreate(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl *agc = effect->session->apm->gain_control();
- ALOGV("AgcCreate got agc %p", agc);
- if (agc == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(agc);
-#endif
+int AgcCreate(preproc_effect_t* effect) {
AgcInit(effect);
return 0;
}
-#ifndef WEBRTC_LEGACY
-int Agc2GetParameter(preproc_effect_t *effect,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue)
-{
+int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
- uint32_t param = *(uint32_t *)pParam;
- agc2_settings_t *pProperties = (agc2_settings_t *)pValue;
+ uint32_t param = *(uint32_t*)pParam;
+ agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
switch (param) {
- case AGC2_PARAM_FIXED_DIGITAL_GAIN:
- if (*pValueSize < sizeof(float)) {
- *pValueSize = 0.f;
- return -EINVAL;
- }
- break;
- case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- if (*pValueSize < sizeof(int32_t)) {
- *pValueSize = 0;
- return -EINVAL;
- }
- break;
- case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
- if (*pValueSize < sizeof(float)) {
- *pValueSize = 0.f;
- return -EINVAL;
- }
- break;
- case AGC2_PARAM_PROPERTIES:
- if (*pValueSize < sizeof(agc2_settings_t)) {
- *pValueSize = 0;
- return -EINVAL;
- }
- break;
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN:
+ if (*pValueSize < sizeof(float)) {
+ *pValueSize = 0.f;
+ return -EINVAL;
+ }
+ break;
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
+ if (*pValueSize < sizeof(int32_t)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
+ if (*pValueSize < sizeof(float)) {
+ *pValueSize = 0.f;
+ return -EINVAL;
+ }
+ break;
+ case AGC2_PARAM_PROPERTIES:
+ if (*pValueSize < sizeof(agc2_settings_t)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
- default:
- ALOGW("Agc2GetParameter() unknown param %08x", param);
- status = -EINVAL;
- break;
+ default:
+ ALOGW("Agc2GetParameter() unknown param %08x", param);
+ status = -EINVAL;
+ break;
}
effect->session->config = effect->session->apm->GetConfig();
switch (param) {
- case AGC2_PARAM_FIXED_DIGITAL_GAIN:
- *(float *) pValue =
- (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
- ALOGV("Agc2GetParameter() target level %f dB", *(float *) pValue);
- break;
- case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- *(uint32_t *) pValue =
- (uint32_t)(effect->session->config.gain_controller2.adaptive_digital.
- level_estimator);
- ALOGV("Agc2GetParameter() level estimator %d",
- *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator *) pValue);
- break;
- case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
- *(float *) pValue =
- (float)(effect->session->config.gain_controller2.adaptive_digital.
- extra_saturation_margin_db);
- ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float *) pValue);
- break;
- case AGC2_PARAM_PROPERTIES:
- pProperties->fixedDigitalGain =
- (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
- pProperties->level_estimator =
- (uint32_t)(effect->session->config.gain_controller2.adaptive_digital.
- level_estimator);
- pProperties->extraSaturationMargin =
- (float)(effect->session->config.gain_controller2.adaptive_digital.
- extra_saturation_margin_db);
- break;
- default:
- ALOGW("Agc2GetParameter() unknown param %d", param);
- status = -EINVAL;
- break;
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN:
+ *(float*)pValue =
+ (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
+ ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
+ break;
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
+ *(uint32_t*)pValue = (uint32_t)(
+ effect->session->config.gain_controller2.adaptive_digital.level_estimator);
+ ALOGV("Agc2GetParameter() level estimator %d",
+ *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ break;
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
+ *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
+ .extra_saturation_margin_db);
+ ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
+ break;
+ case AGC2_PARAM_PROPERTIES:
+ pProperties->fixedDigitalGain =
+ (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
+ pProperties->level_estimator = (uint32_t)(
+ effect->session->config.gain_controller2.adaptive_digital.level_estimator);
+ pProperties->extraSaturationMargin =
+ (float)(effect->session->config.gain_controller2.adaptive_digital
+ .extra_saturation_margin_db);
+ break;
+ default:
+ ALOGW("Agc2GetParameter() unknown param %d", param);
+ status = -EINVAL;
+ break;
}
return status;
}
-#endif
-int AgcGetParameter(preproc_effect_t *effect,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue)
-{
+int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
- uint32_t param = *(uint32_t *)pParam;
- t_agc_settings *pProperties = (t_agc_settings *)pValue;
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
-#endif
+ uint32_t param = *(uint32_t*)pParam;
+ t_agc_settings* pProperties = (t_agc_settings*)pValue;
switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- case AGC_PARAM_COMP_GAIN:
- if (*pValueSize < sizeof(int16_t)) {
- *pValueSize = 0;
- return -EINVAL;
- }
- break;
- case AGC_PARAM_LIMITER_ENA:
- if (*pValueSize < sizeof(bool)) {
- *pValueSize = 0;
- return -EINVAL;
- }
- break;
- case AGC_PARAM_PROPERTIES:
- if (*pValueSize < sizeof(t_agc_settings)) {
- *pValueSize = 0;
- return -EINVAL;
- }
- break;
+ case AGC_PARAM_TARGET_LEVEL:
+ case AGC_PARAM_COMP_GAIN:
+ if (*pValueSize < sizeof(int16_t)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
+ case AGC_PARAM_LIMITER_ENA:
+ if (*pValueSize < sizeof(bool)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
+ case AGC_PARAM_PROPERTIES:
+ if (*pValueSize < sizeof(t_agc_settings)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
- default:
- ALOGW("AgcGetParameter() unknown param %08x", param);
- status = -EINVAL;
- break;
+ default:
+ ALOGW("AgcGetParameter() unknown param %08x", param);
+ status = -EINVAL;
+ break;
}
-#ifdef WEBRTC_LEGACY
- switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100);
- ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
- break;
- case AGC_PARAM_COMP_GAIN:
- *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100);
- ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
- break;
- case AGC_PARAM_LIMITER_ENA:
- *(bool *) pValue = (bool)agc->is_limiter_enabled();
- ALOGV("AgcGetParameter() limiter enabled %s",
- (*(int16_t *) pValue != 0) ? "true" : "false");
- break;
- case AGC_PARAM_PROPERTIES:
- pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
- pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
- pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
- break;
- default:
- ALOGW("AgcGetParameter() unknown param %d", param);
- status = -EINVAL;
- break;
- }
-#else
effect->session->config = effect->session->apm->GetConfig();
switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- *(int16_t *) pValue =
- (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
- ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
- break;
- case AGC_PARAM_COMP_GAIN:
- *(int16_t *) pValue =
- (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
- ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
- break;
- case AGC_PARAM_LIMITER_ENA:
- *(bool *) pValue =
- (bool)(effect->session->config.gain_controller1.enable_limiter);
- ALOGV("AgcGetParameter() limiter enabled %s",
- (*(int16_t *) pValue != 0) ? "true" : "false");
- break;
- case AGC_PARAM_PROPERTIES:
- pProperties->targetLevel =
- (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
- pProperties->compGain =
- (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
- pProperties->limiterEnabled =
- (bool)(effect->session->config.gain_controller1.enable_limiter);
- break;
- default:
- ALOGW("AgcGetParameter() unknown param %d", param);
- status = -EINVAL;
- break;
+ case AGC_PARAM_TARGET_LEVEL:
+ *(int16_t*)pValue =
+ (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
+ ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
+ break;
+ case AGC_PARAM_COMP_GAIN:
+ *(int16_t*)pValue =
+ (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
+ ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
+ break;
+ case AGC_PARAM_LIMITER_ENA:
+ *(bool*)pValue = (bool)(effect->session->config.gain_controller1.enable_limiter);
+ ALOGV("AgcGetParameter() limiter enabled %s",
+ (*(int16_t*)pValue != 0) ? "true" : "false");
+ break;
+ case AGC_PARAM_PROPERTIES:
+ pProperties->targetLevel =
+ (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
+ pProperties->compGain =
+ (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
+ pProperties->limiterEnabled =
+ (bool)(effect->session->config.gain_controller1.enable_limiter);
+ break;
+ default:
+ ALOGW("AgcGetParameter() unknown param %d", param);
+ status = -EINVAL;
+ break;
}
-#endif
return status;
}
-#ifndef WEBRTC_LEGACY
-int Agc2SetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
-{
+int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
- uint32_t param = *(uint32_t *)pParam;
+ uint32_t param = *(uint32_t*)pParam;
float valueFloat = 0.f;
- agc2_settings_t *pProperties = (agc2_settings_t *)pValue;
+ agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
effect->session->config = effect->session->apm->GetConfig();
switch (param) {
- case AGC2_PARAM_FIXED_DIGITAL_GAIN:
- valueFloat = (float)(*(int32_t *) pValue);
- ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
- effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
- break;
- case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- ALOGV("Agc2SetParameter() level estimator %d", *(webrtc::AudioProcessing::Config::
- GainController2::LevelEstimator *) pValue);
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator *) pValue);
- break;
- case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
- valueFloat = (float)(*(int32_t *) pValue);
- ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- valueFloat;
- break;
- case AGC2_PARAM_PROPERTIES:
- ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
- pProperties->fixedDigitalGain,
- pProperties->level_estimator,
- pProperties->extraSaturationMargin);
- effect->session->config.gain_controller2.fixed_digital.gain_db =
- pProperties->fixedDigitalGain;
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)pProperties->
- level_estimator;
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- pProperties->extraSaturationMargin;
- break;
- default:
- ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
- status = -EINVAL;
- break;
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN:
+ valueFloat = (float)(*(int32_t*)pValue);
+ ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
+ effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
+ break;
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
+ ALOGV("Agc2SetParameter() level estimator %d",
+ *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ effect->session->config.gain_controller2.adaptive_digital.level_estimator =
+ (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ break;
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
+ valueFloat = (float)(*(int32_t*)pValue);
+ ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
+ effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
+ valueFloat;
+ break;
+ case AGC2_PARAM_PROPERTIES:
+ ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
+ pProperties->fixedDigitalGain, pProperties->level_estimator,
+ pProperties->extraSaturationMargin);
+ effect->session->config.gain_controller2.fixed_digital.gain_db =
+ pProperties->fixedDigitalGain;
+ effect->session->config.gain_controller2.adaptive_digital.level_estimator =
+ (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
+ pProperties->level_estimator;
+ effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
+ pProperties->extraSaturationMargin;
+ break;
+ default:
+ ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
+ status = -EINVAL;
+ break;
}
effect->session->apm->ApplyConfig(effect->session->config);
@@ -603,433 +471,210 @@
return status;
}
-#endif
-int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
-{
+int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
-#ifdef WEBRTC_LEGACY
- uint32_t param = *(uint32_t *)pParam;
- t_agc_settings *pProperties = (t_agc_settings *)pValue;
- webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
-
- switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
- status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100));
- break;
- case AGC_PARAM_COMP_GAIN:
- ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
- status = agc->set_compression_gain_db(*(int16_t *)pValue / 100);
- break;
- case AGC_PARAM_LIMITER_ENA:
- ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
- status = agc->enable_limiter(*(bool *)pValue);
- break;
- case AGC_PARAM_PROPERTIES:
- ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
- pProperties->targetLevel,
- pProperties->compGain,
- pProperties->limiterEnabled);
- status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
- if (status != 0) break;
- status = agc->set_compression_gain_db(pProperties->compGain / 100);
- if (status != 0) break;
- status = agc->enable_limiter(pProperties->limiterEnabled);
- break;
- default:
- ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
- status = -EINVAL;
- break;
- }
-#else
- uint32_t param = *(uint32_t *)pParam;
- t_agc_settings *pProperties = (t_agc_settings *)pValue;
+ uint32_t param = *(uint32_t*)pParam;
+ t_agc_settings* pProperties = (t_agc_settings*)pValue;
effect->session->config = effect->session->apm->GetConfig();
switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
- effect->session->config.gain_controller1.target_level_dbfs =
- (-(*(int16_t *)pValue / 100));
- break;
- case AGC_PARAM_COMP_GAIN:
- ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
- effect->session->config.gain_controller1.compression_gain_db =
- (*(int16_t *)pValue / 100);
- break;
- case AGC_PARAM_LIMITER_ENA:
- ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
- effect->session->config.gain_controller1.enable_limiter =
- (*(bool *)pValue);
- break;
- case AGC_PARAM_PROPERTIES:
- ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
- pProperties->targetLevel,
- pProperties->compGain,
- pProperties->limiterEnabled);
- effect->session->config.gain_controller1.target_level_dbfs =
- -(pProperties->targetLevel / 100);
- effect->session->config.gain_controller1.compression_gain_db =
- pProperties->compGain / 100;
- effect->session->config.gain_controller1.enable_limiter =
- pProperties->limiterEnabled;
- break;
- default:
- ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
- status = -EINVAL;
- break;
+ case AGC_PARAM_TARGET_LEVEL:
+ ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
+ effect->session->config.gain_controller1.target_level_dbfs =
+ (-(*(int16_t*)pValue / 100));
+ break;
+ case AGC_PARAM_COMP_GAIN:
+ ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
+ effect->session->config.gain_controller1.compression_gain_db =
+ (*(int16_t*)pValue / 100);
+ break;
+ case AGC_PARAM_LIMITER_ENA:
+ ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
+ effect->session->config.gain_controller1.enable_limiter = (*(bool*)pValue);
+ break;
+ case AGC_PARAM_PROPERTIES:
+ ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
+ pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
+ effect->session->config.gain_controller1.target_level_dbfs =
+ -(pProperties->targetLevel / 100);
+ effect->session->config.gain_controller1.compression_gain_db =
+ pProperties->compGain / 100;
+ effect->session->config.gain_controller1.enable_limiter = pProperties->limiterEnabled;
+ break;
+ default:
+ ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
+ status = -EINVAL;
+ break;
}
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
ALOGV("AgcSetParameter() done status %d", status);
return status;
}
-#ifndef WEBRTC_LEGACY
-void Agc2Enable(preproc_effect_t *effect)
-{
+void Agc2Enable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
}
-#endif
-void AgcEnable(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
- ALOGV("AgcEnable agc %p", agc);
- agc->Enable(true);
-#else
+void AgcEnable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-#ifndef WEBRTC_LEGACY
-void Agc2Disable(preproc_effect_t *effect)
-{
+void Agc2Disable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
}
-#endif
-void AgcDisable(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- ALOGV("AgcDisable");
- webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
- agc->Enable(false);
-#else
+void AgcDisable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-static const preproc_ops_t sAgcOps = {
- AgcCreate,
- AgcInit,
- NULL,
- AgcEnable,
- AgcDisable,
- AgcSetParameter,
- AgcGetParameter,
- NULL
-};
+static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
+ AgcSetParameter, AgcGetParameter, NULL};
-#ifndef WEBRTC_LEGACY
-static const preproc_ops_t sAgc2Ops = {
- Agc2Create,
- Agc2Init,
- NULL,
- Agc2Enable,
- Agc2Disable,
- Agc2SetParameter,
- Agc2GetParameter,
- NULL
-};
-#endif
+static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
+ Agc2Enable, Agc2Disable, Agc2SetParameter,
+ Agc2GetParameter, NULL};
//------------------------------------------------------------------------------
// Acoustic Echo Canceler (AEC)
//------------------------------------------------------------------------------
-#ifdef WEBRTC_LEGACY
-static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
- webrtc::EchoControlMobile::kEarpiece;
-static const bool kAecDefaultComfortNoise = true;
-#endif
-int AecInit (preproc_effect_t *effect)
-{
+int AecInit(preproc_effect_t* effect) {
ALOGV("AecInit");
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
- aec->set_routing_mode(kAecDefaultMode);
- aec->enable_comfort_noise(kAecDefaultComfortNoise);
-#else
- effect->session->config =
- effect->session->apm->GetConfig() ;
+ effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.mobile_mode = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return 0;
}
-int AecCreate(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile();
- ALOGV("AecCreate got aec %p", aec);
- if (aec == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(aec);
-#endif
- AecInit (effect);
+int AecCreate(preproc_effect_t* effect) {
+ AecInit(effect);
return 0;
}
-int AecGetParameter(preproc_effect_t *effect,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue)
-{
+int AecGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
- uint32_t param = *(uint32_t *)pParam;
+ uint32_t param = *(uint32_t*)pParam;
if (*pValueSize < sizeof(uint32_t)) {
return -EINVAL;
}
switch (param) {
- case AEC_PARAM_ECHO_DELAY:
- case AEC_PARAM_PROPERTIES:
- *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms();
- ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue);
- break;
-#ifndef WEBRTC_LEGACY
- case AEC_PARAM_MOBILE_MODE:
- effect->session->config =
- effect->session->apm->GetConfig() ;
- *(uint32_t *)pValue = effect->session->config.echo_canceller.mobile_mode;
- ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t *)pValue);
- break;
-#endif
- default:
- ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
- status = -EINVAL;
- break;
+ case AEC_PARAM_ECHO_DELAY:
+ case AEC_PARAM_PROPERTIES:
+ *(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
+ ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
+ break;
+ case AEC_PARAM_MOBILE_MODE:
+ effect->session->config = effect->session->apm->GetConfig();
+ *(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
+ ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
+ break;
+ default:
+ ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
+ status = -EINVAL;
+ break;
}
return status;
}
-int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
-{
+int AecSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
- uint32_t param = *(uint32_t *)pParam;
- uint32_t value = *(uint32_t *)pValue;
+ uint32_t param = *(uint32_t*)pParam;
+ uint32_t value = *(uint32_t*)pValue;
switch (param) {
- case AEC_PARAM_ECHO_DELAY:
- case AEC_PARAM_PROPERTIES:
- status = effect->session->apm->set_stream_delay_ms(value/1000);
- ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
- break;
-#ifndef WEBRTC_LEGACY
- case AEC_PARAM_MOBILE_MODE:
- effect->session->config =
- effect->session->apm->GetConfig() ;
- effect->session->config.echo_canceller.mobile_mode = value;
- ALOGV("AecSetParameter() mobile mode %d us", value);
- effect->session->apm->ApplyConfig(effect->session->config);
- break;
-#endif
- default:
- ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
- status = -EINVAL;
- break;
+ case AEC_PARAM_ECHO_DELAY:
+ case AEC_PARAM_PROPERTIES:
+ status = effect->session->apm->set_stream_delay_ms(value / 1000);
+ ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
+ break;
+ case AEC_PARAM_MOBILE_MODE:
+ effect->session->config = effect->session->apm->GetConfig();
+ effect->session->config.echo_canceller.mobile_mode = value;
+ ALOGV("AecSetParameter() mobile mode %d us", value);
+ effect->session->apm->ApplyConfig(effect->session->config);
+ break;
+ default:
+ ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
+ status = -EINVAL;
+ break;
}
return status;
}
-void AecEnable(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
- ALOGV("AecEnable aec %p", aec);
- aec->Enable(true);
-#else
+void AecEnable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-void AecDisable(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- ALOGV("AecDisable");
- webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
- aec->Enable(false);
-#else
+void AecDisable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-int AecSetDevice(preproc_effect_t *effect, uint32_t device)
-{
+int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
ALOGV("AecSetDevice %08x", device);
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
- webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
-#endif
if (audio_is_input_device(device)) {
return 0;
}
-#ifdef WEBRTC_LEGACY
- switch(device) {
- case AUDIO_DEVICE_OUT_EARPIECE:
- mode = webrtc::EchoControlMobile::kEarpiece;
- break;
- case AUDIO_DEVICE_OUT_SPEAKER:
- mode = webrtc::EchoControlMobile::kSpeakerphone;
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- case AUDIO_DEVICE_OUT_USB_HEADSET:
- default:
- break;
- }
- aec->set_routing_mode(mode);
-#endif
return 0;
}
-static const preproc_ops_t sAecOps = {
- AecCreate,
- AecInit,
- NULL,
- AecEnable,
- AecDisable,
- AecSetParameter,
- AecGetParameter,
- AecSetDevice
-};
+static const preproc_ops_t sAecOps = {AecCreate, AecInit, NULL,
+ AecEnable, AecDisable, AecSetParameter,
+ AecGetParameter, AecSetDevice};
//------------------------------------------------------------------------------
// Noise Suppression (NS)
//------------------------------------------------------------------------------
-#ifdef WEBRTC_LEGACY
-static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
-#else
static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
- webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
-#endif
+ webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
-int NsInit (preproc_effect_t *effect)
-{
+int NsInit(preproc_effect_t* effect) {
ALOGV("NsInit");
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
- ns->set_level(kNsDefaultLevel);
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- // TODO(aluebs): Make the geometry settable.
- geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
- // The geometry needs to be set with Beamforming enabled.
- config.Set<webrtc::Beamforming>(
- new webrtc::Beamforming(true, geometry));
- effect->session->apm->SetExtraOptions(config);
- config.Set<webrtc::Beamforming>(
- new webrtc::Beamforming(false, geometry));
- effect->session->apm->SetExtraOptions(config);
-#else
- effect->session->config =
- effect->session->apm->GetConfig() ;
- effect->session->config.noise_suppression.level =
- kNsDefaultLevel;
+ effect->session->config = effect->session->apm->GetConfig();
+ effect->session->config.noise_suppression.level = kNsDefaultLevel;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
effect->type = NS_TYPE_SINGLE_CHANNEL;
return 0;
}
-int NsCreate(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
- ALOGV("NsCreate got ns %p", ns);
- if (ns == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(ns);
-#endif
- NsInit (effect);
+int NsCreate(preproc_effect_t* effect) {
+ NsInit(effect);
return 0;
}
-int NsGetParameter(preproc_effect_t *effect __unused,
- void *pParam __unused,
- uint32_t *pValueSize __unused,
- void *pValue __unused)
-{
+int NsGetParameter(preproc_effect_t* /*effect __unused*/, void* /*pParam __unused*/,
+ uint32_t* /*pValueSize __unused*/, void* /*pValue __unused*/) {
int status = 0;
return status;
}
-int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
-{
+int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
- uint32_t param = *(uint32_t *)pParam;
- uint32_t value = *(uint32_t *)pValue;
- switch(param) {
- case NS_PARAM_LEVEL:
- ns->set_level((webrtc::NoiseSuppression::Level)value);
- ALOGV("NsSetParameter() level %d", value);
- break;
- case NS_PARAM_TYPE:
- {
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- bool is_beamforming_enabled =
- value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
- config.Set<webrtc::Beamforming>(
- new webrtc::Beamforming(is_beamforming_enabled, geometry));
- effect->session->apm->SetExtraOptions(config);
- effect->type = value;
- ALOGV("NsSetParameter() type %d", value);
- break;
- }
- default:
- ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
- status = -EINVAL;
- }
-#else
- uint32_t param = *(uint32_t *)pParam;
- uint32_t value = *(uint32_t *)pValue;
- effect->session->config =
- effect->session->apm->GetConfig();
+ uint32_t param = *(uint32_t*)pParam;
+ uint32_t value = *(uint32_t*)pValue;
+ effect->session->config = effect->session->apm->GetConfig();
switch (param) {
case NS_PARAM_LEVEL:
effect->session->config.noise_suppression.level =
- (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
+ (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
ALOGV("NsSetParameter() level %d", value);
break;
default:
@@ -1037,155 +682,111 @@
status = -EINVAL;
}
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return status;
}
-void NsEnable(preproc_effect_t *effect)
-{
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
- ALOGV("NsEnable ns %p", ns);
- ns->Enable(true);
- if (effect->type == NS_TYPE_MULTI_CHANNEL) {
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
- effect->session->apm->SetExtraOptions(config);
- }
-#else
- effect->session->config =
- effect->session->apm->GetConfig();
+void NsEnable(preproc_effect_t* effect) {
+ effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-void NsDisable(preproc_effect_t *effect)
-{
+void NsDisable(preproc_effect_t* effect) {
ALOGV("NsDisable");
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
- ns->Enable(false);
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
- effect->session->apm->SetExtraOptions(config);
-#else
- effect->session->config =
- effect->session->apm->GetConfig();
+ effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-static const preproc_ops_t sNsOps = {
- NsCreate,
- NsInit,
- NULL,
- NsEnable,
- NsDisable,
- NsSetParameter,
- NsGetParameter,
- NULL
-};
+static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
+ NsDisable, NsSetParameter, NsGetParameter, NULL};
-
-
-static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
- &sAgcOps,
-#ifndef WEBRTC_LEGACY
- &sAgc2Ops,
-#endif
- &sAecOps,
- &sNsOps
-};
-
+static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
+ &sAgc2Ops,
+ &sAecOps, &sNsOps};
//------------------------------------------------------------------------------
// Effect functions
//------------------------------------------------------------------------------
-void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
+void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled);
extern "C" const struct effect_interface_s sEffectInterface;
extern "C" const struct effect_interface_s sEffectInterfaceReverse;
-#define BAD_STATE_ABORT(from, to) \
- LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
+#define BAD_STATE_ABORT(from, to) LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
-int Effect_SetState(preproc_effect_t *effect, uint32_t state)
-{
+int Effect_SetState(preproc_effect_t* effect, uint32_t state) {
int status = 0;
ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
- switch(state) {
- case PREPROC_EFFECT_STATE_INIT:
- switch(effect->state) {
- case PREPROC_EFFECT_STATE_ACTIVE:
- effect->ops->disable(effect);
- Session_SetProcEnabled(effect->session, effect->procId, false);
+ switch (state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ switch (effect->state) {
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ effect->ops->disable(effect);
+ Session_SetProcEnabled(effect->session, effect->procId, false);
+ break;
+ case PREPROC_EFFECT_STATE_CONFIG:
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_INIT:
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ break;
+ case PREPROC_EFFECT_STATE_CREATED:
+ switch (effect->state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ status = effect->ops->create(effect);
+ break;
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ case PREPROC_EFFECT_STATE_CONFIG:
+ ALOGE("Effect_SetState invalid transition");
+ status = -ENOSYS;
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
break;
case PREPROC_EFFECT_STATE_CONFIG:
- case PREPROC_EFFECT_STATE_CREATED:
- case PREPROC_EFFECT_STATE_INIT:
+ switch (effect->state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ ALOGE("Effect_SetState invalid transition");
+ status = -ENOSYS;
+ break;
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ effect->ops->disable(effect);
+ Session_SetProcEnabled(effect->session, effect->procId, false);
+ break;
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_CONFIG:
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ break;
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ switch (effect->state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ case PREPROC_EFFECT_STATE_CREATED:
+ ALOGE("Effect_SetState invalid transition");
+ status = -ENOSYS;
+ break;
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ // enabling an already enabled effect is just ignored
+ break;
+ case PREPROC_EFFECT_STATE_CONFIG:
+ effect->ops->enable(effect);
+ Session_SetProcEnabled(effect->session, effect->procId, true);
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
break;
default:
BAD_STATE_ABORT(effect->state, state);
- }
- break;
- case PREPROC_EFFECT_STATE_CREATED:
- switch(effect->state) {
- case PREPROC_EFFECT_STATE_INIT:
- status = effect->ops->create(effect);
- break;
- case PREPROC_EFFECT_STATE_CREATED:
- case PREPROC_EFFECT_STATE_ACTIVE:
- case PREPROC_EFFECT_STATE_CONFIG:
- ALOGE("Effect_SetState invalid transition");
- status = -ENOSYS;
- break;
- default:
- BAD_STATE_ABORT(effect->state, state);
- }
- break;
- case PREPROC_EFFECT_STATE_CONFIG:
- switch(effect->state) {
- case PREPROC_EFFECT_STATE_INIT:
- ALOGE("Effect_SetState invalid transition");
- status = -ENOSYS;
- break;
- case PREPROC_EFFECT_STATE_ACTIVE:
- effect->ops->disable(effect);
- Session_SetProcEnabled(effect->session, effect->procId, false);
- break;
- case PREPROC_EFFECT_STATE_CREATED:
- case PREPROC_EFFECT_STATE_CONFIG:
- break;
- default:
- BAD_STATE_ABORT(effect->state, state);
- }
- break;
- case PREPROC_EFFECT_STATE_ACTIVE:
- switch(effect->state) {
- case PREPROC_EFFECT_STATE_INIT:
- case PREPROC_EFFECT_STATE_CREATED:
- ALOGE("Effect_SetState invalid transition");
- status = -ENOSYS;
- break;
- case PREPROC_EFFECT_STATE_ACTIVE:
- // enabling an already enabled effect is just ignored
- break;
- case PREPROC_EFFECT_STATE_CONFIG:
- effect->ops->enable(effect);
- Session_SetProcEnabled(effect->session, effect->procId, true);
- break;
- default:
- BAD_STATE_ABORT(effect->state, state);
- }
- break;
- default:
- BAD_STATE_ABORT(effect->state, state);
}
if (status == 0) {
effect->state = state;
@@ -1193,8 +794,7 @@
return status;
}
-int Effect_Init(preproc_effect_t *effect, uint32_t procId)
-{
+int Effect_Init(preproc_effect_t* effect, uint32_t procId) {
if (HasReverseStream(procId)) {
effect->itfe = &sEffectInterfaceReverse;
} else {
@@ -1206,21 +806,17 @@
return 0;
}
-int Effect_Create(preproc_effect_t *effect,
- preproc_session_t *session,
- effect_handle_t *interface)
-{
+int Effect_Create(preproc_effect_t* effect, preproc_session_t* session,
+ effect_handle_t* interface) {
effect->session = session;
*interface = (effect_handle_t)&effect->itfe;
return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
}
-int Effect_Release(preproc_effect_t *effect)
-{
+int Effect_Release(preproc_effect_t* effect) {
return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
}
-
//------------------------------------------------------------------------------
// Session functions
//------------------------------------------------------------------------------
@@ -1230,8 +826,7 @@
static const int kPreprocDefaultSr = 16000;
static const int kPreProcDefaultCnl = 1;
-int Session_Init(preproc_session_t *session)
-{
+int Session_Init(preproc_session_t* session) {
size_t i;
int status = 0;
@@ -1239,167 +834,69 @@
session->id = 0;
session->io = 0;
session->createdMsk = 0;
-#ifdef WEBRTC_LEGACY
- session->apm = NULL;
-#endif
for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
status = Effect_Init(&session->effects[i], i);
}
return status;
}
-
-extern "C" int Session_CreateEffect(preproc_session_t *session,
- int32_t procId,
- effect_handle_t *interface)
-{
+extern "C" int Session_CreateEffect(preproc_session_t* session, int32_t procId,
+ effect_handle_t* interface) {
int status = -ENOMEM;
ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
- session->apm = webrtc::AudioProcessing::Create();
- if (session->apm == NULL) {
- ALOGW("Session_CreateEffect could not get apm engine");
- goto error;
- }
- const webrtc::ProcessingConfig processing_config = {
- {{kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl}}};
- session->apm->Initialize(processing_config);
- session->procFrame = new webrtc::AudioFrame();
- if (session->procFrame == NULL) {
- ALOGW("Session_CreateEffect could not allocate audio frame");
- goto error;
- }
- session->revFrame = new webrtc::AudioFrame();
- if (session->revFrame == NULL) {
- ALOGW("Session_CreateEffect could not allocate reverse audio frame");
- goto error;
- }
-#else
session->apm = session->ap_builder.Create();
if (session->apm == NULL) {
ALOGW("Session_CreateEffect could not get apm engine");
goto error;
}
-#endif
- session->apmSamplingRate = kPreprocDefaultSr;
- session->apmFrameCount = (kPreprocDefaultSr) / 100;
- session->frameCount = session->apmFrameCount;
+ session->frameCount = kPreprocDefaultSr / 100;
session->samplingRate = kPreprocDefaultSr;
session->inChannelCount = kPreProcDefaultCnl;
session->outChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
- session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
- session->procFrame->num_channels_ = kPreProcDefaultCnl;
-#else
session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->inputConfig.set_num_channels(kPreProcDefaultCnl);
session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->outputConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
session->revChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
- session->revFrame->num_channels_ = kPreProcDefaultCnl;
-#else
session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->revConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
session->enabledMsk = 0;
session->processedMsk = 0;
session->revEnabledMsk = 0;
session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
- session->inResampler = NULL;
-#endif
- session->inBuf = NULL;
- session->inBufSize = 0;
-#ifdef WEBRTC_LEGACY
- session->outResampler = NULL;
-#endif
- session->outBuf = NULL;
- session->outBufSize = 0;
-#ifdef WEBRTC_LEGACY
- session->revResampler = NULL;
-#endif
- session->revBuf = NULL;
- session->revBufSize = 0;
}
status = Effect_Create(&session->effects[procId], session, interface);
if (status < 0) {
goto error;
}
ALOGV("Session_CreateEffect OK");
- session->createdMsk |= (1<<procId);
+ session->createdMsk |= (1 << procId);
return status;
error:
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
- delete session->revFrame;
- session->revFrame = NULL;
- delete session->procFrame;
- session->procFrame = NULL;
- delete session->apm;
- session->apm = NULL; // NOLINT(clang-analyzer-cplusplus.NewDelete)
-#else
delete session->apm;
session->apm = NULL;
-#endif
}
return status;
}
-int Session_ReleaseEffect(preproc_session_t *session,
- preproc_effect_t *fx)
-{
+int Session_ReleaseEffect(preproc_session_t* session, preproc_effect_t* fx) {
ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
- session->createdMsk &= ~(1<<fx->procId);
+ session->createdMsk &= ~(1 << fx->procId);
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
delete session->apm;
session->apm = NULL;
- delete session->procFrame;
- session->procFrame = NULL;
- delete session->revFrame;
- session->revFrame = NULL;
- if (session->inResampler != NULL) {
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- }
- if (session->outResampler != NULL) {
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- }
- if (session->revResampler != NULL) {
- speex_resampler_destroy(session->revResampler);
- session->revResampler = NULL;
- }
-#else
- delete session->apm;
- session->apm = NULL;
-#endif
- delete session->inBuf;
- session->inBuf = NULL;
- delete session->outBuf;
- session->outBuf = NULL;
- delete session->revBuf;
- session->revBuf = NULL;
-
session->id = 0;
}
return 0;
}
-
-int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
-{
+int Session_SetConfig(preproc_session_t* session, effect_config_t* config) {
uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
@@ -1409,135 +906,27 @@
return -EINVAL;
}
- ALOGV("Session_SetConfig sr %d cnl %08x",
- config->inputCfg.samplingRate, config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
- int status;
-#endif
-
- // AEC implementation is limited to 16kHz
- if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
- session->apmSamplingRate = 32000;
- } else
- if (config->inputCfg.samplingRate >= 16000) {
- session->apmSamplingRate = 16000;
- } else if (config->inputCfg.samplingRate >= 8000) {
- session->apmSamplingRate = 8000;
- }
-
-#ifdef WEBRTC_LEGACY
- const webrtc::ProcessingConfig processing_config = {
- {{static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), outCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl}}};
- status = session->apm->Initialize(processing_config);
- if (status < 0) {
- return -EINVAL;
- }
-#endif
+ ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
+ config->inputCfg.channels);
session->samplingRate = config->inputCfg.samplingRate;
- session->apmFrameCount = session->apmSamplingRate / 100;
- if (session->samplingRate == session->apmSamplingRate) {
- session->frameCount = session->apmFrameCount;
- } else {
-#ifdef WEBRTC_LEGACY
- session->frameCount = (session->apmFrameCount * session->samplingRate) /
- session->apmSamplingRate + 1;
-#else
- session->frameCount = (session->apmFrameCount * session->samplingRate) /
- session->apmSamplingRate;
-#endif
- }
+ session->frameCount = session->samplingRate / 100;
session->inChannelCount = inCnl;
session->outChannelCount = outCnl;
-#ifdef WEBRTC_LEGACY
- session->procFrame->num_channels_ = inCnl;
- session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
session->inputConfig.set_sample_rate_hz(session->samplingRate);
session->inputConfig.set_num_channels(inCnl);
session->outputConfig.set_sample_rate_hz(session->samplingRate);
session->outputConfig.set_num_channels(inCnl);
-#endif
session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->num_channels_ = inCnl;
- session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
session->revConfig.set_sample_rate_hz(session->samplingRate);
session->revConfig.set_num_channels(inCnl);
-#endif
-
- // force process buffer reallocation
- session->inBufSize = 0;
- session->outBufSize = 0;
- session->framesIn = 0;
- session->framesOut = 0;
-
-
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- }
- if (session->outResampler != NULL) {
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- }
- if (session->revResampler != NULL) {
- speex_resampler_destroy(session->revResampler);
- session->revResampler = NULL;
- }
- if (session->samplingRate != session->apmSamplingRate) {
- int error;
- session->inResampler = speex_resampler_init(session->inChannelCount,
- session->samplingRate,
- session->apmSamplingRate,
- RESAMPLER_QUALITY,
- &error);
- if (session->inResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- return -EINVAL;
- }
- session->outResampler = speex_resampler_init(session->outChannelCount,
- session->apmSamplingRate,
- session->samplingRate,
- RESAMPLER_QUALITY,
- &error);
- if (session->outResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- return -EINVAL;
- }
- session->revResampler = speex_resampler_init(session->inChannelCount,
- session->samplingRate,
- session->apmSamplingRate,
- RESAMPLER_QUALITY,
- &error);
- if (session->revResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- return -EINVAL;
- }
- }
-#endif
session->state = PREPROC_SESSION_STATE_CONFIG;
return 0;
}
-void Session_GetConfig(preproc_session_t *session, effect_config_t *config)
-{
+void Session_GetConfig(preproc_session_t* session, effect_config_t* config) {
memset(config, 0, sizeof(effect_config_t));
config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -1548,50 +937,30 @@
(EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
}
-int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
-{
+int Session_SetReverseConfig(preproc_session_t* session, effect_config_t* config) {
if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
- config->inputCfg.format != config->outputCfg.format ||
- config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ config->inputCfg.format != config->outputCfg.format ||
+ config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
return -EINVAL;
}
- ALOGV("Session_SetReverseConfig sr %d cnl %08x",
- config->inputCfg.samplingRate, config->inputCfg.channels);
+ ALOGV("Session_SetReverseConfig sr %d cnl %08x", config->inputCfg.samplingRate,
+ config->inputCfg.channels);
if (session->state < PREPROC_SESSION_STATE_CONFIG) {
return -ENOSYS;
}
if (config->inputCfg.samplingRate != session->samplingRate ||
- config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
return -EINVAL;
}
uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
- const webrtc::ProcessingConfig processing_config = {
- {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
- {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
- {static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl}}};
- int status = session->apm->Initialize(processing_config);
- if (status < 0) {
- return -EINVAL;
- }
-#endif
session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->num_channels_ = inCnl;
- session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#endif
- // force process buffer reallocation
- session->revBufSize = 0;
- session->framesRev = 0;
return 0;
}
-void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config)
-{
+void Session_GetReverseConfig(preproc_session_t* session, effect_config_t* config) {
memset(config, 0, sizeof(effect_config_t));
config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -1601,29 +970,10 @@
(EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
}
-void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
-{
+void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled) {
if (enabled) {
- if(session->enabledMsk == 0) {
- session->framesIn = 0;
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- speex_resampler_reset_mem(session->inResampler);
- }
- session->framesOut = 0;
- if (session->outResampler != NULL) {
- speex_resampler_reset_mem(session->outResampler);
- }
-#endif
- }
session->enabledMsk |= (1 << procId);
if (HasReverseStream(procId)) {
- session->framesRev = 0;
-#ifdef WEBRTC_LEGACY
- if (session->revResampler != NULL) {
- speex_resampler_reset_mem(session->revResampler);
- }
-#endif
session->revEnabledMsk |= (1 << procId);
}
} else {
@@ -1632,8 +982,8 @@
session->revEnabledMsk &= ~(1 << procId);
}
}
- ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
- procId, enabled, session->enabledMsk, session->revEnabledMsk);
+ ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", procId,
+ enabled, session->enabledMsk, session->revEnabledMsk);
session->processedMsk = 0;
if (HasReverseStream(procId)) {
session->revProcessedMsk = 0;
@@ -1647,8 +997,7 @@
static int sInitStatus = 1;
static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
-preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId)
-{
+preproc_session_t* PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) {
size_t i;
for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
if (sSessions[i].id == sessionId) {
@@ -1668,7 +1017,6 @@
return NULL;
}
-
int PreProc_Init() {
size_t i;
int status = 0;
@@ -1683,8 +1031,7 @@
return sInitStatus;
}
-const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid)
-{
+const effect_descriptor_t* PreProc_GetDescriptor(const effect_uuid_t* uuid) {
size_t i;
for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
@@ -1694,261 +1041,86 @@
return NULL;
}
-
extern "C" {
//------------------------------------------------------------------------------
// Effect Control Interface Implementation
//------------------------------------------------------------------------------
-int PreProcessingFx_Process(effect_handle_t self,
- audio_buffer_t *inBuffer,
- audio_buffer_t *outBuffer)
-{
- preproc_effect_t * effect = (preproc_effect_t *)self;
+int PreProcessingFx_Process(effect_handle_t self, audio_buffer_t* inBuffer,
+ audio_buffer_t* outBuffer) {
+ preproc_effect_t* effect = (preproc_effect_t*)self;
- if (effect == NULL){
+ if (effect == NULL) {
ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
return -EINVAL;
}
- preproc_session_t * session = (preproc_session_t *)effect->session;
+ preproc_session_t* session = (preproc_session_t*)effect->session;
- if (inBuffer == NULL || inBuffer->raw == NULL ||
- outBuffer == NULL || outBuffer->raw == NULL){
+ if (inBuffer == NULL || inBuffer->raw == NULL || outBuffer == NULL || outBuffer->raw == NULL) {
ALOGW("PreProcessingFx_Process() ERROR bad pointer");
return -EINVAL;
}
- session->processedMsk |= (1<<effect->procId);
+ if (inBuffer->frameCount != outBuffer->frameCount) {
+ ALOGW("inBuffer->frameCount %zu is not equal to outBuffer->frameCount %zu",
+ inBuffer->frameCount, outBuffer->frameCount);
+ return -EINVAL;
+ }
-// ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
-// inBuffer->frameCount, session->enabledMsk, session->processedMsk);
+ if (inBuffer->frameCount != session->frameCount) {
+ ALOGW("inBuffer->frameCount %zu != %zu representing 10ms at sampling rate %d",
+ inBuffer->frameCount, session->frameCount, session->samplingRate);
+ return -EINVAL;
+ }
+ session->processedMsk |= (1 << effect->procId);
+
+ // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
+ // inBuffer->frameCount, session->enabledMsk, session->processedMsk);
if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
effect->session->processedMsk = 0;
- size_t framesRq = outBuffer->frameCount;
- size_t framesWr = 0;
- if (session->framesOut) {
- size_t fr = session->framesOut;
- if (outBuffer->frameCount < fr) {
- fr = outBuffer->frameCount;
- }
- memcpy(outBuffer->s16,
- session->outBuf,
- fr * session->outChannelCount * sizeof(int16_t));
- memmove(session->outBuf,
- session->outBuf + fr * session->outChannelCount,
- (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
- session->framesOut -= fr;
- framesWr += fr;
- }
- outBuffer->frameCount = framesWr;
- if (framesWr == framesRq) {
- inBuffer->frameCount = 0;
- return 0;
- }
-
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- if (session->inBufSize < session->framesIn + fr) {
- int16_t *buf;
- session->inBufSize = session->framesIn + fr;
- buf = (int16_t *)realloc(session->inBuf,
- session->inBufSize * session->inChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesIn = 0;
- free(session->inBuf);
- session->inBuf = NULL;
- return -ENOMEM;
- }
- session->inBuf = buf;
- }
- memcpy(session->inBuf + session->framesIn * session->inChannelCount,
- inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-#ifdef DUAL_MIC_TEST
- pthread_mutex_lock(&gPcmDumpLock);
- if (gPcmDumpFh != NULL) {
- fwrite(inBuffer->raw,
- fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
- }
- pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- spx_uint32_t frIn = session->framesIn;
- spx_uint32_t frOut = session->apmFrameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->inResampler,
- 0,
- session->inBuf,
- &frIn,
- session->procFrame->data_,
- &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->inResampler,
- session->inBuf,
- &frIn,
- session->procFrame->data_,
- &frOut);
- }
- memmove(session->inBuf,
- session->inBuf + frIn * session->inChannelCount,
- (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
- session->framesIn -= frIn;
- } else {
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
- inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-
-#ifdef DUAL_MIC_TEST
- pthread_mutex_lock(&gPcmDumpLock);
- if (gPcmDumpFh != NULL) {
- fwrite(inBuffer->raw,
- fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
- }
- pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- session->framesIn = 0;
- }
- session->procFrame->samples_per_channel_ = session->apmFrameCount;
-
- effect->session->apm->ProcessStream(session->procFrame);
-#else
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- session->framesIn = 0;
if (int status = effect->session->apm->ProcessStream(
- (const int16_t* const)inBuffer->s16,
- (const webrtc::StreamConfig)effect->session->inputConfig,
- (const webrtc::StreamConfig)effect->session->outputConfig,
- (int16_t* const)outBuffer->s16);
- status != 0) {
+ (const int16_t* const)inBuffer->s16,
+ (const webrtc::StreamConfig)effect->session->inputConfig,
+ (const webrtc::StreamConfig)effect->session->outputConfig,
+ (int16_t* const)outBuffer->s16);
+ status != 0) {
ALOGE("Process Stream failed with error %d\n", status);
return status;
}
- outBuffer->frameCount = inBuffer->frameCount;
-#endif
-
- if (session->outBufSize < session->framesOut + session->frameCount) {
- int16_t *buf;
- session->outBufSize = session->framesOut + session->frameCount;
- buf = (int16_t *)realloc(session->outBuf,
- session->outBufSize * session->outChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesOut = 0;
- free(session->outBuf);
- session->outBuf = NULL;
- return -ENOMEM;
- }
- session->outBuf = buf;
- }
-
-#ifdef WEBRTC_LEGACY
- if (session->outResampler != NULL) {
- spx_uint32_t frIn = session->apmFrameCount;
- spx_uint32_t frOut = session->frameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->outResampler,
- 0,
- session->procFrame->data_,
- &frIn,
- session->outBuf + session->framesOut * session->outChannelCount,
- &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->outResampler,
- session->procFrame->data_,
- &frIn,
- session->outBuf + session->framesOut * session->outChannelCount,
- &frOut);
- }
- session->framesOut += frOut;
- } else {
- memcpy(session->outBuf + session->framesOut * session->outChannelCount,
- session->procFrame->data_,
- session->frameCount * session->outChannelCount * sizeof(int16_t));
- session->framesOut += session->frameCount;
- }
- size_t fr = session->framesOut;
-#else
- fr = session->framesOut;
-#endif
- if (framesRq - framesWr < fr) {
- fr = framesRq - framesWr;
- }
- memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
- session->outBuf,
- fr * session->outChannelCount * sizeof(int16_t));
- memmove(session->outBuf,
- session->outBuf + fr * session->outChannelCount,
- (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
- session->framesOut -= fr;
- outBuffer->frameCount += fr;
-
return 0;
} else {
return -ENODATA;
}
}
-int PreProcessingFx_Command(effect_handle_t self,
- uint32_t cmdCode,
- uint32_t cmdSize,
- void *pCmdData,
- uint32_t *replySize,
- void *pReplyData)
-{
- preproc_effect_t * effect = (preproc_effect_t *) self;
+int PreProcessingFx_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
+ void* pCmdData, uint32_t* replySize, void* pReplyData) {
+ preproc_effect_t* effect = (preproc_effect_t*)self;
- if (effect == NULL){
+ if (effect == NULL) {
return -EINVAL;
}
- //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
+ // ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
- switch (cmdCode){
+ switch (cmdCode) {
case EFFECT_CMD_INIT:
- if (pReplyData == NULL || *replySize != sizeof(int)){
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
return -EINVAL;
}
if (effect->ops->init) {
effect->ops->init(effect);
}
- *(int *)pReplyData = 0;
+ *(int*)pReplyData = 0;
break;
case EFFECT_CMD_SET_CONFIG: {
- if (pCmdData == NULL||
- cmdSize != sizeof(effect_config_t)||
- pReplyData == NULL||
- *replySize != sizeof(int)){
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
+ *replySize != sizeof(int)) {
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_SET_CONFIG: ERROR");
+ "EFFECT_CMD_SET_CONFIG: ERROR");
return -EINVAL;
}
#ifdef DUAL_MIC_TEST
@@ -1959,55 +1131,51 @@
effect->session->enabledMsk = 0;
}
#endif
- *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
+ *(int*)pReplyData = Session_SetConfig(effect->session, (effect_config_t*)pCmdData);
#ifdef DUAL_MIC_TEST
if (gDualMicEnabled) {
effect->session->enabledMsk = enabledMsk;
}
#endif
- if (*(int *)pReplyData != 0) {
+ if (*(int*)pReplyData != 0) {
break;
}
if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
- *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
+ *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
}
- } break;
+ } break;
case EFFECT_CMD_GET_CONFIG:
- if (pReplyData == NULL ||
- *replySize != sizeof(effect_config_t)) {
+ if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_GET_CONFIG: ERROR");
+ "EFFECT_CMD_GET_CONFIG: ERROR");
return -EINVAL;
}
- Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
+ Session_GetConfig(effect->session, (effect_config_t*)pReplyData);
break;
case EFFECT_CMD_SET_CONFIG_REVERSE:
- if (pCmdData == NULL ||
- cmdSize != sizeof(effect_config_t) ||
- pReplyData == NULL ||
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
*replySize != sizeof(int)) {
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
+ "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
return -EINVAL;
}
- *(int *)pReplyData = Session_SetReverseConfig(effect->session,
- (effect_config_t *)pCmdData);
- if (*(int *)pReplyData != 0) {
+ *(int*)pReplyData =
+ Session_SetReverseConfig(effect->session, (effect_config_t*)pCmdData);
+ if (*(int*)pReplyData != 0) {
break;
}
break;
case EFFECT_CMD_GET_CONFIG_REVERSE:
- if (pReplyData == NULL ||
- *replySize != sizeof(effect_config_t)){
+ if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
+ "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
return -EINVAL;
}
- Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
+ Session_GetReverseConfig(effect->session, (effect_config_t*)pCmdData);
break;
case EFFECT_CMD_RESET:
@@ -2017,80 +1185,74 @@
break;
case EFFECT_CMD_GET_PARAM: {
- effect_param_t *p = (effect_param_t *)pCmdData;
+ effect_param_t* p = (effect_param_t*)pCmdData;
if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
- cmdSize < (sizeof(effect_param_t) + p->psize) ||
- pReplyData == NULL || replySize == NULL ||
- *replySize < (sizeof(effect_param_t) + p->psize)){
+ cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL ||
+ replySize == NULL || *replySize < (sizeof(effect_param_t) + p->psize)) {
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_GET_PARAM: ERROR");
+ "EFFECT_CMD_GET_PARAM: ERROR");
return -EINVAL;
}
memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
- p = (effect_param_t *)pReplyData;
+ p = (effect_param_t*)pReplyData;
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
if (effect->ops->get_parameter) {
- p->status = effect->ops->get_parameter(effect, p->data,
- &p->vsize,
- p->data + voffset);
+ p->status =
+ effect->ops->get_parameter(effect, p->data, &p->vsize, p->data + voffset);
*replySize = sizeof(effect_param_t) + voffset + p->vsize;
}
} break;
- case EFFECT_CMD_SET_PARAM:{
- if (pCmdData == NULL||
- cmdSize < sizeof(effect_param_t) ||
- pReplyData == NULL || replySize == NULL ||
- *replySize != sizeof(int32_t)){
+ case EFFECT_CMD_SET_PARAM: {
+ if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || pReplyData == NULL ||
+ replySize == NULL || *replySize != sizeof(int32_t)) {
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_SET_PARAM: ERROR");
+ "EFFECT_CMD_SET_PARAM: ERROR");
return -EINVAL;
}
- effect_param_t *p = (effect_param_t *) pCmdData;
+ effect_param_t* p = (effect_param_t*)pCmdData;
- if (p->psize != sizeof(int32_t)){
+ if (p->psize != sizeof(int32_t)) {
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
return -EINVAL;
}
if (effect->ops->set_parameter) {
- *(int *)pReplyData = effect->ops->set_parameter(effect,
- (void *)p->data,
- p->data + p->psize);
+ *(int*)pReplyData =
+ effect->ops->set_parameter(effect, (void*)p->data, p->data + p->psize);
}
} break;
case EFFECT_CMD_ENABLE:
- if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
+ if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
return -EINVAL;
}
- *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
+ *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
break;
case EFFECT_CMD_DISABLE:
- if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
+ if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
return -EINVAL;
}
- *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
+ *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
break;
case EFFECT_CMD_SET_DEVICE:
case EFFECT_CMD_SET_INPUT_DEVICE:
- if (pCmdData == NULL ||
- cmdSize != sizeof(uint32_t)) {
+ if (pCmdData == NULL || cmdSize != sizeof(uint32_t)) {
ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
return -EINVAL;
}
if (effect->ops->set_device) {
- effect->ops->set_device(effect, *(uint32_t *)pCmdData);
+ effect->ops->set_device(effect, *(uint32_t*)pCmdData);
}
break;
@@ -2101,30 +1263,30 @@
#ifdef DUAL_MIC_TEST
///// test commands start
case PREPROC_CMD_DUAL_MIC_ENABLE: {
- if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
- pReplyData == NULL || replySize == NULL) {
+ if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
+ replySize == NULL) {
ALOGE("PreProcessingFx_Command cmdCode Case: "
- "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
+ "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
*replySize = 0;
return -EINVAL;
}
- gDualMicEnabled = *(bool *)pCmdData;
+ gDualMicEnabled = *(bool*)pCmdData;
if (gDualMicEnabled) {
effect->aux_channels_on = sHasAuxChannels[effect->procId];
} else {
effect->aux_channels_on = false;
}
- effect->cur_channel_config = (effect->session->inChannelCount == 1) ?
- CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
+ effect->cur_channel_config =
+ (effect->session->inChannelCount == 1) ? CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
*replySize = sizeof(int);
- *(int *)pReplyData = 0;
- } break;
+ *(int*)pReplyData = 0;
+ } break;
case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
- if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) {
+ if (pCmdData == NULL || pReplyData == NULL || replySize == NULL) {
ALOGE("PreProcessingFx_Command cmdCode Case: "
- "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
+ "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
*replySize = 0;
return -EINVAL;
}
@@ -2133,20 +1295,19 @@
fclose(gPcmDumpFh);
gPcmDumpFh = NULL;
}
- char *path = strndup((char *)pCmdData, cmdSize);
- gPcmDumpFh = fopen((char *)path, "wb");
+ char* path = strndup((char*)pCmdData, cmdSize);
+ gPcmDumpFh = fopen((char*)path, "wb");
pthread_mutex_unlock(&gPcmDumpLock);
- ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p",
- path, gPcmDumpFh);
+ ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", path, gPcmDumpFh);
ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
free(path);
*replySize = sizeof(int);
- *(int *)pReplyData = 0;
- } break;
+ *(int*)pReplyData = 0;
+ } break;
case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
if (pReplyData == NULL || replySize == NULL) {
ALOGE("PreProcessingFx_Command cmdCode Case: "
- "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
+ "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
*replySize = 0;
return -EINVAL;
}
@@ -2158,118 +1319,116 @@
pthread_mutex_unlock(&gPcmDumpLock);
ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
*replySize = sizeof(int);
- *(int *)pReplyData = 0;
- } break;
- ///// test commands end
+ *(int*)pReplyData = 0;
+ } break;
+ ///// test commands end
case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
- if(!gDualMicEnabled) {
+ if (!gDualMicEnabled) {
return -EINVAL;
}
- if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) ||
- pReplyData == NULL || replySize == NULL) {
+ if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) || pReplyData == NULL ||
+ replySize == NULL) {
ALOGE("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
+ "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
*replySize = 0;
return -EINVAL;
}
- if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS ||
- !effect->aux_channels_on) {
+ if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
- " fx %d", effect->procId);
- *(uint32_t *)pReplyData = -ENOSYS;
+ " fx %d",
+ effect->procId);
+ *(uint32_t*)pReplyData = -ENOSYS;
*replySize = sizeof(uint32_t);
break;
}
- size_t num_configs = *((uint32_t *)pCmdData + 1);
- if (*replySize < (2 * sizeof(uint32_t) +
- num_configs * sizeof(channel_config_t))) {
+ size_t num_configs = *((uint32_t*)pCmdData + 1);
+ if (*replySize < (2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t))) {
*replySize = 0;
return -EINVAL;
}
- *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT;
+ *((uint32_t*)pReplyData + 1) = CHANNEL_CFG_CNT;
if (num_configs < CHANNEL_CFG_CNT ||
- *replySize < (2 * sizeof(uint32_t) +
- CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
- *(uint32_t *)pReplyData = -ENOMEM;
+ *replySize < (2 * sizeof(uint32_t) + CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
+ *(uint32_t*)pReplyData = -ENOMEM;
} else {
num_configs = CHANNEL_CFG_CNT;
- *(uint32_t *)pReplyData = 0;
+ *(uint32_t*)pReplyData = 0;
}
ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
num_configs);
*replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
- *((uint32_t *)pReplyData + 1) = num_configs;
- memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t));
- } break;
+ *((uint32_t*)pReplyData + 1) = num_configs;
+ memcpy((uint32_t*)pReplyData + 2, &sDualMicConfigs,
+ num_configs * sizeof(channel_config_t));
+ } break;
case EFFECT_CMD_GET_FEATURE_CONFIG:
- if(!gDualMicEnabled) {
+ if (!gDualMicEnabled) {
return -EINVAL;
}
- if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
- pReplyData == NULL || replySize == NULL ||
- *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
+ if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
+ replySize == NULL || *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
ALOGE("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
+ "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
return -EINVAL;
}
- if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
- *(uint32_t *)pReplyData = -ENOSYS;
+ if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
+ *(uint32_t*)pReplyData = -ENOSYS;
*replySize = sizeof(uint32_t);
break;
}
ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
- *(uint32_t *)pReplyData = 0;
+ *(uint32_t*)pReplyData = 0;
*replySize = sizeof(uint32_t) + sizeof(channel_config_t);
- memcpy((uint32_t *)pReplyData + 1,
- &sDualMicConfigs[effect->cur_channel_config],
+ memcpy((uint32_t*)pReplyData + 1, &sDualMicConfigs[effect->cur_channel_config],
sizeof(channel_config_t));
break;
case EFFECT_CMD_SET_FEATURE_CONFIG: {
ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
- "gDualMicEnabled %d effect->aux_channels_on %d",
+ "gDualMicEnabled %d effect->aux_channels_on %d",
gDualMicEnabled, effect->aux_channels_on);
- if(!gDualMicEnabled) {
+ if (!gDualMicEnabled) {
return -EINVAL;
}
- if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
- pReplyData == NULL || replySize == NULL ||
- *replySize < sizeof(uint32_t)) {
+ if (pCmdData == NULL || cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
+ pReplyData == NULL || replySize == NULL || *replySize < sizeof(uint32_t)) {
ALOGE("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
- "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
- pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
+ "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
+ "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
+ pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
return -EINVAL;
}
*replySize = sizeof(uint32_t);
- if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
- *(uint32_t *)pReplyData = -ENOSYS;
+ if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
+ *(uint32_t*)pReplyData = -ENOSYS;
ALOGV("PreProcessingFx_Command cmdCode Case: "
- "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
- "CmdData %d effect->aux_channels_on %d",
- *(uint32_t *)pCmdData, effect->aux_channels_on);
+ "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
+ "CmdData %d effect->aux_channels_on %d",
+ *(uint32_t*)pCmdData, effect->aux_channels_on);
break;
}
size_t i;
- for (i = 0; i < CHANNEL_CFG_CNT;i++) {
- if (memcmp((uint32_t *)pCmdData + 1,
- &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) {
+ for (i = 0; i < CHANNEL_CFG_CNT; i++) {
+ if (memcmp((uint32_t*)pCmdData + 1, &sDualMicConfigs[i],
+ sizeof(channel_config_t)) == 0) {
break;
}
}
if (i == CHANNEL_CFG_CNT) {
- *(uint32_t *)pReplyData = -EINVAL;
+ *(uint32_t*)pReplyData = -EINVAL;
ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
- "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2));
+ "[%08x].[%08x]",
+ *((uint32_t*)pCmdData + 1), *((uint32_t*)pCmdData + 2));
} else {
effect->cur_channel_config = i;
- *(uint32_t *)pReplyData = 0;
+ *(uint32_t*)pReplyData = 0;
ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
- "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
+ "[%08x].[%08x]",
+ sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
}
- } break;
+ } break;
#endif
default:
return -EINVAL;
@@ -2277,11 +1436,8 @@
return 0;
}
-
-int PreProcessingFx_GetDescriptor(effect_handle_t self,
- effect_descriptor_t *pDescriptor)
-{
- preproc_effect_t * effect = (preproc_effect_t *) self;
+int PreProcessingFx_GetDescriptor(effect_handle_t self, effect_descriptor_t* pDescriptor) {
+ preproc_effect_t* effect = (preproc_effect_t*)self;
if (effect == NULL || pDescriptor == NULL) {
return -EINVAL;
@@ -2292,159 +1448,81 @@
return 0;
}
-int PreProcessingFx_ProcessReverse(effect_handle_t self,
- audio_buffer_t *inBuffer,
- audio_buffer_t *outBuffer __unused)
-{
- preproc_effect_t * effect = (preproc_effect_t *)self;
+int PreProcessingFx_ProcessReverse(effect_handle_t self, audio_buffer_t* inBuffer,
+ audio_buffer_t* outBuffer) {
+ preproc_effect_t* effect = (preproc_effect_t*)self;
- if (effect == NULL){
+ if (effect == NULL) {
ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
return -EINVAL;
}
- preproc_session_t * session = (preproc_session_t *)effect->session;
+ preproc_session_t* session = (preproc_session_t*)effect->session;
- if (inBuffer == NULL || inBuffer->raw == NULL){
+ if (inBuffer == NULL || inBuffer->raw == NULL) {
ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
return -EINVAL;
}
- session->revProcessedMsk |= (1<<effect->procId);
+ if (inBuffer->frameCount != outBuffer->frameCount) {
+ ALOGW("inBuffer->frameCount %zu is not equal to outBuffer->frameCount %zu",
+ inBuffer->frameCount, outBuffer->frameCount);
+ return -EINVAL;
+ }
-// ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
-// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
+ if (inBuffer->frameCount != session->frameCount) {
+ ALOGW("inBuffer->frameCount %zu != %zu representing 10ms at sampling rate %d",
+ inBuffer->frameCount, session->frameCount, session->samplingRate);
+ return -EINVAL;
+ }
+ session->revProcessedMsk |= (1 << effect->procId);
+
+ // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk
+ // %08x",
+ // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
effect->session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
- if (session->revResampler != NULL) {
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- if (session->revBufSize < session->framesRev + fr) {
- int16_t *buf;
- session->revBufSize = session->framesRev + fr;
- buf = (int16_t *)realloc(session->revBuf,
- session->revBufSize * session->inChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesRev = 0;
- free(session->revBuf);
- session->revBuf = NULL;
- return -ENOMEM;
- }
- session->revBuf = buf;
- }
- memcpy(session->revBuf + session->framesRev * session->inChannelCount,
- inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- spx_uint32_t frIn = session->framesRev;
- spx_uint32_t frOut = session->apmFrameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->revResampler,
- 0,
- session->revBuf,
- &frIn,
- session->revFrame->data_,
- &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->revResampler,
- session->revBuf,
- &frIn,
- session->revFrame->data_,
- &frOut);
- }
- memmove(session->revBuf,
- session->revBuf + frIn * session->inChannelCount,
- (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
- session->framesRev -= frIn;
- } else {
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
- inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- session->framesRev = 0;
- }
- session->revFrame->samples_per_channel_ = session->apmFrameCount;
- effect->session->apm->AnalyzeReverseStream(session->revFrame);
-#else
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- session->framesRev = 0;
if (int status = effect->session->apm->ProcessReverseStream(
- (const int16_t* const)inBuffer->s16,
- (const webrtc::StreamConfig)effect->session->revConfig,
- (const webrtc::StreamConfig)effect->session->revConfig,
- (int16_t* const)outBuffer->s16);
- status != 0) {
+ (const int16_t* const)inBuffer->s16,
+ (const webrtc::StreamConfig)effect->session->revConfig,
+ (const webrtc::StreamConfig)effect->session->revConfig,
+ (int16_t* const)outBuffer->s16);
+ status != 0) {
ALOGE("Process Reverse Stream failed with error %d\n", status);
return status;
}
-#endif
return 0;
} else {
return -ENODATA;
}
}
-
// effect_handle_t interface implementation for effect
const struct effect_interface_s sEffectInterface = {
- PreProcessingFx_Process,
- PreProcessingFx_Command,
- PreProcessingFx_GetDescriptor,
- NULL
-};
+ PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor, NULL};
const struct effect_interface_s sEffectInterfaceReverse = {
- PreProcessingFx_Process,
- PreProcessingFx_Command,
- PreProcessingFx_GetDescriptor,
- PreProcessingFx_ProcessReverse
-};
+ PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor,
+ PreProcessingFx_ProcessReverse};
//------------------------------------------------------------------------------
// Effect Library Interface Implementation
//------------------------------------------------------------------------------
-int PreProcessingLib_Create(const effect_uuid_t *uuid,
- int32_t sessionId,
- int32_t ioId,
- effect_handle_t *pInterface)
-{
+int PreProcessingLib_Create(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId,
+ effect_handle_t* pInterface) {
ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
int status;
- const effect_descriptor_t *desc;
- preproc_session_t *session;
+ const effect_descriptor_t* desc;
+ preproc_session_t* session;
uint32_t procId;
if (PreProc_Init() != 0) {
return sInitStatus;
}
- desc = PreProc_GetDescriptor(uuid);
+ desc = PreProc_GetDescriptor(uuid);
if (desc == NULL) {
ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
return -EINVAL;
@@ -2465,14 +1543,13 @@
return status;
}
-int PreProcessingLib_Release(effect_handle_t interface)
-{
+int PreProcessingLib_Release(effect_handle_t interface) {
ALOGV("EffectRelease start %p", interface);
if (PreProc_Init() != 0) {
return sInitStatus;
}
- preproc_effect_t *fx = (preproc_effect_t *)interface;
+ preproc_effect_t* fx = (preproc_effect_t*)interface;
if (fx->session->id == 0) {
return -EINVAL;
@@ -2480,17 +1557,15 @@
return Session_ReleaseEffect(fx->session, fx);
}
-int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,
- effect_descriptor_t *pDescriptor) {
-
- if (pDescriptor == NULL || uuid == NULL){
+int PreProcessingLib_GetDescriptor(const effect_uuid_t* uuid, effect_descriptor_t* pDescriptor) {
+ if (pDescriptor == NULL || uuid == NULL) {
return -EINVAL;
}
- const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
+ const effect_descriptor_t* desc = PreProc_GetDescriptor(uuid);
if (desc == NULL) {
ALOGV("PreProcessingLib_GetDescriptor() not found");
- return -EINVAL;
+ return -EINVAL;
}
ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
@@ -2500,15 +1575,13 @@
}
// This is the only symbol that needs to be exported
-__attribute__ ((visibility ("default")))
-audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
- .tag = AUDIO_EFFECT_LIBRARY_TAG,
- .version = EFFECT_LIBRARY_API_VERSION,
- .name = "Audio Preprocessing Library",
- .implementor = "The Android Open Source Project",
- .create_effect = PreProcessingLib_Create,
- .release_effect = PreProcessingLib_Release,
- .get_descriptor = PreProcessingLib_GetDescriptor
-};
+__attribute__((visibility("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ .tag = AUDIO_EFFECT_LIBRARY_TAG,
+ .version = EFFECT_LIBRARY_API_VERSION,
+ .name = "Audio Preprocessing Library",
+ .implementor = "The Android Open Source Project",
+ .create_effect = PreProcessingLib_Create,
+ .release_effect = PreProcessingLib_Release,
+ .get_descriptor = PreProcessingLib_GetDescriptor};
-}; // extern "C"
+}; // extern "C"
diff --git a/media/libeffects/preprocessing/README.md b/media/libeffects/preprocessing/README.md
new file mode 100644
index 0000000..af46376
--- /dev/null
+++ b/media/libeffects/preprocessing/README.md
@@ -0,0 +1,7 @@
+# Preprocessing effects
+
+## Limitations
+- Preprocessing effects currently work on 10ms worth of data and do not support
+ arbitrary frame counts. This limiation comes from the underlying effects in
+ webrtc modules
+- There is currently no api to communicate this requirement
diff --git a/media/libeffects/preprocessing/benchmarks/Android.bp b/media/libeffects/preprocessing/benchmarks/Android.bp
index 2808293..fbbcab4 100644
--- a/media/libeffects/preprocessing/benchmarks/Android.bp
+++ b/media/libeffects/preprocessing/benchmarks/Android.bp
@@ -1,51 +1,20 @@
-cc_benchmark {
- name: "preprocessing_legacy_benchmark",
- vendor: true,
- relative_install_path: "soundfx",
- srcs: ["preprocessing_benchmark.cpp"],
- shared_libs: [
- "libaudiopreprocessing_legacy",
- "libaudioutils",
- "liblog",
- "libutils",
- "libwebrtc_audio_preprocessing",
- ],
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- "libwebrtc_absl_headers",
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libeffects_preprocessing_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_preprocessing_license",
],
}
cc_benchmark {
name: "preprocessing_benchmark",
- vendor: true,
- relative_install_path: "soundfx",
+ defaults: ["libaudiopreprocessing-defaults"],
srcs: ["preprocessing_benchmark.cpp"],
- shared_libs: [
+ static_libs: [
"libaudiopreprocessing",
"libaudioutils",
- "liblog",
- "libutils",
- ],
- cflags: [
- "-DWEBRTC_POSIX",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- "libwebrtc_absl_headers",
],
}
diff --git a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
index d4df371..9501d4d 100644
--- a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
+++ b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
@@ -25,38 +25,112 @@
* ---------------------------------------------------------------
* Benchmark Time CPU Iterations
* ---------------------------------------------------------------
- * BM_PREPROCESSING/1/0 59836 ns 59655 ns 11732
- * BM_PREPROCESSING/1/1 66848 ns 66642 ns 10554
- * BM_PREPROCESSING/1/2 20726 ns 20655 ns 33822
- * BM_PREPROCESSING/1/3 5093 ns 5076 ns 137897
- * BM_PREPROCESSING/2/0 117040 ns 116670 ns 5996
- * BM_PREPROCESSING/2/1 120600 ns 120225 ns 5845
- * BM_PREPROCESSING/2/2 38460 ns 38330 ns 18190
- * BM_PREPROCESSING/2/3 6294 ns 6274 ns 111488
- * BM_PREPROCESSING/3/0 232272 ns 231528 ns 3025
- * BM_PREPROCESSING/3/1 226346 ns 225628 ns 3117
- * BM_PREPROCESSING/3/2 75442 ns 75227 ns 9104
- * BM_PREPROCESSING/3/3 9782 ns 9750 ns 71805
- * BM_PREPROCESSING/4/0 290388 ns 289426 ns 2389
- * BM_PREPROCESSING/4/1 279394 ns 278498 ns 2522
- * BM_PREPROCESSING/4/2 94029 ns 93759 ns 7307
- * BM_PREPROCESSING/4/3 11487 ns 11450 ns 61129
- * BM_PREPROCESSING/5/0 347736 ns 346580 ns 2020
- * BM_PREPROCESSING/5/1 331853 ns 330788 ns 2122
- * BM_PREPROCESSING/5/2 112594 ns 112268 ns 6105
- * BM_PREPROCESSING/5/3 13254 ns 13212 ns 52972
+ * BM_PREPROCESSING/1/0 48179 ns 48041 ns 12349
+ * BM_PREPROCESSING/1/1 57559 ns 57403 ns 12270
+ * BM_PREPROCESSING/1/2 17524 ns 17466 ns 39982
+ * BM_PREPROCESSING/1/3 2608 ns 2599 ns 268399
+ * BM_PREPROCESSING/2/0 94198 ns 93926 ns 7470
+ * BM_PREPROCESSING/2/1 109196 ns 108899 ns 6459
+ * BM_PREPROCESSING/2/2 34098 ns 33986 ns 20576
+ * BM_PREPROCESSING/2/3 3231 ns 3221 ns 216606
+ * BM_PREPROCESSING/3/0 141532 ns 141132 ns 5030
+ * BM_PREPROCESSING/3/1 161199 ns 160745 ns 4387
+ * BM_PREPROCESSING/3/2 50663 ns 50535 ns 13619
+ * BM_PREPROCESSING/3/3 3967 ns 3955 ns 177005
+ * BM_PREPROCESSING/4/0 187032 ns 186486 ns 3706
+ * BM_PREPROCESSING/4/1 212872 ns 212264 ns 3304
+ * BM_PREPROCESSING/4/2 67649 ns 67476 ns 10128
+ * BM_PREPROCESSING/4/3 4728 ns 4713 ns 148547
+ * BM_PREPROCESSING/5/0 233874 ns 233188 ns 2954
+ * BM_PREPROCESSING/5/1 262798 ns 262052 ns 2680
+ * BM_PREPROCESSING/5/2 84592 ns 84368 ns 8203
+ * BM_PREPROCESSING/5/3 5472 ns 5455 ns 127784
+ * BM_PREPROCESSING/6/0 284777 ns 283911 ns 2468
+ * BM_PREPROCESSING/6/1 315631 ns 314726 ns 2233
+ * BM_PREPROCESSING/6/2 101200 ns 100931 ns 6802
+ * BM_PREPROCESSING/6/3 6152 ns 6133 ns 113951
+ * BM_PREPROCESSING/7/0 327207 ns 326153 ns 2112
+ * BM_PREPROCESSING/7/1 367510 ns 366410 ns 1915
+ * BM_PREPROCESSING/7/2 118574 ns 118250 ns 5795
+ * BM_PREPROCESSING/7/3 6956 ns 6935 ns 100783
+ * BM_PREPROCESSING/8/0 372603 ns 371470 ns 1880
+ * BM_PREPROCESSING/8/1 418882 ns 417625 ns 1685
+ * BM_PREPROCESSING/8/2 136155 ns 135777 ns 4986
+ * BM_PREPROCESSING/8/3 7734 ns 7711 ns 91581
+ * BM_PREPROCESSING/9/0 424795 ns 423464 ns 1657
+ * BM_PREPROCESSING/9/1 469073 ns 467687 ns 1506
+ * BM_PREPROCESSING/9/2 153170 ns 152737 ns 4519
+ * BM_PREPROCESSING/9/3 8393 ns 8363 ns 83603
+ * BM_PREPROCESSING/10/0 472440 ns 470926 ns 1489
+ * BM_PREPROCESSING/10/1 516984 ns 515480 ns 1000
+ * BM_PREPROCESSING/10/2 168802 ns 168348 ns 4097
+ * BM_PREPROCESSING/10/3 9127 ns 9100 ns 76913
+ * BM_PREPROCESSING/11/0 509690 ns 508113 ns 1360
+ * BM_PREPROCESSING/11/1 569076 ns 567390 ns 1310
+ * BM_PREPROCESSING/11/2 185678 ns 185165 ns 3729
+ * BM_PREPROCESSING/11/3 9789 ns 9760 ns 71342
+ * BM_PREPROCESSING/12/0 563858 ns 562108 ns 1270
+ * BM_PREPROCESSING/12/1 619656 ns 617791 ns 1198
+ * BM_PREPROCESSING/12/2 202882 ns 202316 ns 3406
+ * BM_PREPROCESSING/12/3 10610 ns 10579 ns 66287
+ * BM_PREPROCESSING/13/0 602944 ns 601094 ns 1167
+ * BM_PREPROCESSING/13/1 675401 ns 673293 ns 1107
+ * BM_PREPROCESSING/13/2 220677 ns 220051 ns 3131
+ * BM_PREPROCESSING/13/3 11301 ns 11265 ns 62022
+ * BM_PREPROCESSING/14/0 659495 ns 657375 ns 1071
+ * BM_PREPROCESSING/14/1 726551 ns 724295 ns 1024
+ * BM_PREPROCESSING/14/2 238595 ns 237922 ns 2901
+ * BM_PREPROCESSING/14/3 11941 ns 11906 ns 58788
+ * BM_PREPROCESSING/15/0 698377 ns 696134 ns 1014
+ * BM_PREPROCESSING/15/1 772532 ns 770217 ns 960
+ * BM_PREPROCESSING/15/2 253219 ns 252505 ns 2736
+ * BM_PREPROCESSING/15/3 12669 ns 12632 ns 55452
+ * BM_PREPROCESSING/16/0 742054 ns 739708 ns 936
+ * BM_PREPROCESSING/16/1 828029 ns 825484 ns 902
+ * BM_PREPROCESSING/16/2 272419 ns 271658 ns 2545
+ * BM_PREPROCESSING/16/3 13473 ns 13431 ns 52088
+ * BM_PREPROCESSING/17/0 794444 ns 791916 ns 891
+ * BM_PREPROCESSING/17/1 879429 ns 876704 ns 841
+ * BM_PREPROCESSING/17/2 290059 ns 289216 ns 2391
+ * BM_PREPROCESSING/17/3 14257 ns 14210 ns 49425
+ * BM_PREPROCESSING/18/0 852221 ns 849430 ns 839
+ * BM_PREPROCESSING/18/1 931121 ns 928308 ns 799
+ * BM_PREPROCESSING/18/2 307995 ns 307104 ns 2253
+ * BM_PREPROCESSING/18/3 14947 ns 14900 ns 46872
+ * BM_PREPROCESSING/19/0 888752 ns 885893 ns 781
+ * BM_PREPROCESSING/19/1 983398 ns 980285 ns 756
+ * BM_PREPROCESSING/19/2 325669 ns 324705 ns 2132
+ * BM_PREPROCESSING/19/3 15677 ns 15629 ns 44693
+ * BM_PREPROCESSING/20/0 933651 ns 930697 ns 746
+ * BM_PREPROCESSING/20/1 1033396 ns 1030235 ns 713
+ * BM_PREPROCESSING/20/2 342081 ns 341077 ns 2031
+ * BM_PREPROCESSING/20/3 16422 ns 16370 ns 42622
+ * BM_PREPROCESSING/21/0 982521 ns 979388 ns 706
+ * BM_PREPROCESSING/21/1 1085340 ns 1081926 ns 682
+ * BM_PREPROCESSING/21/2 360862 ns 359810 ns 1926
+ * BM_PREPROCESSING/21/3 17161 ns 17107 ns 40885
+ * BM_PREPROCESSING/22/0 1043560 ns 1040219 ns 678
+ * BM_PREPROCESSING/22/1 1137203 ns 1133687 ns 653
+ * BM_PREPROCESSING/22/2 377421 ns 376315 ns 1841
+ * BM_PREPROCESSING/22/3 17903 ns 17847 ns 38984
+ * BM_PREPROCESSING/23/0 1090097 ns 1086523 ns 650
+ * BM_PREPROCESSING/23/1 1199267 ns 1194231 ns 619
+ * BM_PREPROCESSING/23/2 395429 ns 394263 ns 1759
+ * BM_PREPROCESSING/23/3 18879 ns 18818 ns 37242
+ * BM_PREPROCESSING/24/0 1128638 ns 1125076 ns 629
+ * BM_PREPROCESSING/24/1 1239909 ns 1236019 ns 598
+ * BM_PREPROCESSING/24/2 414294 ns 413055 ns 1680
+ * BM_PREPROCESSING/24/3 19583 ns 19521 ns 35771
*******************************************************************/
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
#include <array>
#include <climits>
#include <cstdlib>
#include <random>
#include <vector>
-#include <audio_effects/effect_aec.h>
-#include <audio_effects/effect_agc.h>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <benchmark/benchmark.h>
#include <hardware/audio_effect.h>
@@ -70,190 +144,177 @@
constexpr float kTenMilliSecVal = 0.01;
constexpr unsigned int kStreamDelayMs = 0;
constexpr effect_uuid_t kEffectUuids[] = {
- // agc uuid
- {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
- // aec uuid
- {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
- // ns uuid
- {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
-#ifndef WEBRTC_LEGACY
- // agc2 uuid
- {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},
-#endif
+ // agc uuid
+ {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // aec uuid
+ {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // ns uuid
+ {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ // agc2 uuid
+ {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},
};
constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
constexpr audio_channel_mask_t kChMasks[] = {
- AUDIO_CHANNEL_IN_MONO,
- AUDIO_CHANNEL_IN_STEREO,
- AUDIO_CHANNEL_IN_2POINT0POINT2,
- AUDIO_CHANNEL_IN_2POINT1POINT2,
- AUDIO_CHANNEL_IN_6,
+ AUDIO_CHANNEL_INDEX_MASK_1, AUDIO_CHANNEL_INDEX_MASK_2, AUDIO_CHANNEL_INDEX_MASK_3,
+ AUDIO_CHANNEL_INDEX_MASK_4, AUDIO_CHANNEL_INDEX_MASK_5, AUDIO_CHANNEL_INDEX_MASK_6,
+ AUDIO_CHANNEL_INDEX_MASK_7, AUDIO_CHANNEL_INDEX_MASK_8, AUDIO_CHANNEL_INDEX_MASK_9,
+ AUDIO_CHANNEL_INDEX_MASK_10, AUDIO_CHANNEL_INDEX_MASK_11, AUDIO_CHANNEL_INDEX_MASK_12,
+ AUDIO_CHANNEL_INDEX_MASK_13, AUDIO_CHANNEL_INDEX_MASK_14, AUDIO_CHANNEL_INDEX_MASK_15,
+ AUDIO_CHANNEL_INDEX_MASK_16, AUDIO_CHANNEL_INDEX_MASK_17, AUDIO_CHANNEL_INDEX_MASK_18,
+ AUDIO_CHANNEL_INDEX_MASK_19, AUDIO_CHANNEL_INDEX_MASK_20, AUDIO_CHANNEL_INDEX_MASK_21,
+ AUDIO_CHANNEL_INDEX_MASK_22, AUDIO_CHANNEL_INDEX_MASK_23, AUDIO_CHANNEL_INDEX_MASK_24,
};
constexpr size_t kNumChMasks = std::size(kChMasks);
// types of pre processing modules
enum PreProcId {
- PREPROC_AGC, // Automatic Gain Control
- PREPROC_AEC, // Acoustic Echo Canceler
- PREPROC_NS, // Noise Suppressor
-#ifndef WEBRTC_LEGACY
- PREPROC_AGC2, // Automatic Gain Control 2
-#endif
- PREPROC_NUM_EFFECTS
+ PREPROC_AGC, // Automatic Gain Control
+ PREPROC_AEC, // Acoustic Echo Canceler
+ PREPROC_NS, // Noise Suppressor
+ PREPROC_AGC2, // Automatic Gain Control 2
+ PREPROC_NUM_EFFECTS
};
-int preProcCreateEffect(effect_handle_t *pEffectHandle, uint32_t effectType,
- effect_config_t *pConfig, int sessionId, int ioId) {
- if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(
- &kEffectUuids[effectType], sessionId, ioId, pEffectHandle);
- status != 0) {
- ALOGE("Audio Preprocessing create returned an error = %d\n", status);
- return EXIT_FAILURE;
- }
- int reply = 0;
- uint32_t replySize = sizeof(reply);
- if (effectType == PREPROC_AEC) {
- if (int status =
- (**pEffectHandle)
- ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE,
- sizeof(effect_config_t), pConfig, &replySize, &reply);
+int preProcCreateEffect(effect_handle_t* pEffectHandle, uint32_t effectType,
+ effect_config_t* pConfig, int sessionId, int ioId) {
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kEffectUuids[effectType],
+ sessionId, ioId, pEffectHandle);
status != 0) {
- ALOGE("Set config reverse command returned an error = %d\n", status);
- return EXIT_FAILURE;
+ ALOGE("Audio Preprocessing create returned an error = %d\n", status);
+ return EXIT_FAILURE;
}
- }
- if (int status =
- (**pEffectHandle)
- ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG,
- sizeof(effect_config_t), pConfig, &replySize, &reply);
- status != 0) {
- ALOGE("Set config command returned an error = %d\n", status);
- return EXIT_FAILURE;
- }
- return reply;
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (effectType == PREPROC_AEC) {
+ if (int status = (**pEffectHandle)
+ ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE,
+ sizeof(effect_config_t), pConfig, &replySize, &reply);
+ status != 0) {
+ ALOGE("Set config reverse command returned an error = %d\n", status);
+ return EXIT_FAILURE;
+ }
+ }
+ if (int status = (**pEffectHandle)
+ ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t), pConfig, &replySize, &reply);
+ status != 0) {
+ ALOGE("Set config command returned an error = %d\n", status);
+ return EXIT_FAILURE;
+ }
+ return reply;
}
-int preProcSetConfigParam(effect_handle_t effectHandle, uint32_t paramType,
- uint32_t paramValue) {
- int reply = 0;
- uint32_t replySize = sizeof(reply);
- uint32_t paramData[2] = {paramType, paramValue};
- effect_param_t *effectParam =
- (effect_param_t *)malloc(sizeof(*effectParam) + sizeof(paramData));
- memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
- effectParam->psize = sizeof(paramData[0]);
- (*effectHandle)
- ->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t),
- effectParam, &replySize, &reply);
- free(effectParam);
- return reply;
+int preProcSetConfigParam(effect_handle_t effectHandle, uint32_t paramType, uint32_t paramValue) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {paramType, paramValue};
+ effect_param_t* effectParam = (effect_param_t*)malloc(sizeof(*effectParam) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ return reply;
}
short preProcGetShortVal(float paramValue) {
- return static_cast<short>(paramValue * std::numeric_limits<short>::max());
+ return static_cast<short>(paramValue * std::numeric_limits<short>::max());
}
-static void BM_PREPROCESSING(benchmark::State &state) {
- const size_t chMask = kChMasks[state.range(0) - 1];
- const size_t channelCount = audio_channel_count_from_in_mask(chMask);
+static void BM_PREPROCESSING(benchmark::State& state) {
+ const size_t chMask = kChMasks[state.range(0) - 1];
+ const size_t channelCount = audio_channel_count_from_in_mask(chMask);
- PreProcId effectType = (PreProcId)state.range(1);
+ PreProcId effectType = (PreProcId)state.range(1);
- int32_t sessionId = 1;
- int32_t ioId = 1;
- effect_handle_t effectHandle = nullptr;
- effect_config_t config{};
- config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
- config.inputCfg.channels = config.outputCfg.channels = chMask;
- config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ int32_t sessionId = 1;
+ int32_t ioId = 1;
+ effect_handle_t effectHandle = nullptr;
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
+ config.inputCfg.channels = config.outputCfg.channels = chMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
- if (int status = preProcCreateEffect(&effectHandle, state.range(1), &config,
- sessionId, ioId);
- status != 0) {
- ALOGE("Create effect call returned error %i", status);
- return;
- }
-
- int reply = 0;
- uint32_t replySize = sizeof(reply);
- if (int status = (*effectHandle)
- ->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr,
- &replySize, &reply);
- status != 0) {
- ALOGE("Command enable call returned error %d\n", reply);
- return;
- }
-
- // Initialize input buffer with deterministic pseudo-random values
- const int frameLength = (int)(kSampleRate * kTenMilliSecVal);
- std::minstd_rand gen(chMask);
- std::uniform_real_distribution<> dis(-1.0f, 1.0f);
- std::vector<short> in(frameLength * channelCount);
- for (auto &i : in) {
- i = preProcGetShortVal(dis(gen));
- }
- std::vector<short> farIn(frameLength * channelCount);
- for (auto &i : farIn) {
- i = preProcGetShortVal(dis(gen));
- }
- std::vector<short> out(frameLength * channelCount);
-
- // Run the test
- for (auto _ : state) {
- benchmark::DoNotOptimize(in.data());
- benchmark::DoNotOptimize(out.data());
- benchmark::DoNotOptimize(farIn.data());
-
- audio_buffer_t inBuffer = {.frameCount = (size_t)frameLength,
- .s16 = in.data()};
- audio_buffer_t outBuffer = {.frameCount = (size_t)frameLength,
- .s16 = out.data()};
- audio_buffer_t farInBuffer = {.frameCount = (size_t)frameLength,
- .s16 = farIn.data()};
-
- if (PREPROC_AEC == effectType) {
- if (int status = preProcSetConfigParam(effectHandle, AEC_PARAM_ECHO_DELAY,
- kStreamDelayMs);
- status != 0) {
- ALOGE("preProcSetConfigParam returned Error %d\n", status);
- return;
- }
- }
- if (int status =
- (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+ if (int status = preProcCreateEffect(&effectHandle, state.range(1), &config, sessionId, ioId);
status != 0) {
- ALOGE("\nError: Process i = %d returned with error %d\n",
- (int)state.range(1), status);
- return;
- }
- if (PREPROC_AEC == effectType) {
- if (int status =
- (*effectHandle)
- ->process_reverse(effectHandle, &farInBuffer, &outBuffer);
- status != 0) {
- ALOGE("\nError: Process reverse i = %d returned with error %d\n",
- (int)state.range(1), status);
+ ALOGE("Create effect call returned error %i", status);
return;
- }
}
- }
- benchmark::ClobberMemory();
- state.SetComplexityN(state.range(0));
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (int status =
+ (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ status != 0) {
+ ALOGE("Command enable call returned error %d\n", reply);
+ return;
+ }
- if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle);
- status != 0) {
- ALOGE("release_effect returned an error = %d\n", status);
- return;
- }
+ // Initialize input buffer with deterministic pseudo-random values
+ const int frameLength = (int)(kSampleRate * kTenMilliSecVal);
+ std::minstd_rand gen(chMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ std::vector<short> in(frameLength * channelCount);
+ for (auto& i : in) {
+ i = preProcGetShortVal(dis(gen));
+ }
+ std::vector<short> farIn(frameLength * channelCount);
+ for (auto& i : farIn) {
+ i = preProcGetShortVal(dis(gen));
+ }
+ std::vector<short> out(frameLength * channelCount);
+
+ // Run the test
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(in.data());
+ benchmark::DoNotOptimize(out.data());
+ benchmark::DoNotOptimize(farIn.data());
+
+ audio_buffer_t inBuffer = {.frameCount = (size_t)frameLength, .s16 = in.data()};
+ audio_buffer_t outBuffer = {.frameCount = (size_t)frameLength, .s16 = out.data()};
+ audio_buffer_t farInBuffer = {.frameCount = (size_t)frameLength, .s16 = farIn.data()};
+
+ if (PREPROC_AEC == effectType) {
+ if (int status =
+ preProcSetConfigParam(effectHandle, AEC_PARAM_ECHO_DELAY, kStreamDelayMs);
+ status != 0) {
+ ALOGE("preProcSetConfigParam returned Error %d\n", status);
+ return;
+ }
+ }
+ if (int status = (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+ status != 0) {
+ ALOGE("\nError: Process i = %d returned with error %d\n", (int)state.range(1), status);
+ return;
+ }
+ if (PREPROC_AEC == effectType) {
+ if (int status =
+ (*effectHandle)->process_reverse(effectHandle, &farInBuffer, &outBuffer);
+ status != 0) {
+ ALOGE("\nError: Process reverse i = %d returned with error %d\n",
+ (int)state.range(1), status);
+ return;
+ }
+ }
+ }
+ benchmark::ClobberMemory();
+
+ state.SetComplexityN(state.range(0));
+
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
+ ALOGE("release_effect returned an error = %d\n", status);
+ return;
+ }
}
-static void preprocessingArgs(benchmark::internal::Benchmark *b) {
- for (int i = 1; i <= (int)kNumChMasks; i++) {
- for (int j = 0; j < (int)kNumEffectUuids; ++j) {
- b->Args({i, j});
+static void preprocessingArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 1; i <= (int)kNumChMasks; i++) {
+ for (int j = 0; j < (int)kNumEffectUuids; ++j) {
+ b->Args({i, j});
+ }
}
- }
}
BENCHMARK(BM_PREPROCESSING)->Apply(preprocessingArgs);
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index 045b0d3..d80b135 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -1,53 +1,49 @@
// audio preprocessing unit test
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libeffects_preprocessing_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libeffects_preprocessing_license",
+ ],
+}
+
cc_test {
- name: "AudioPreProcessingLegacyTest",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
- srcs: ["PreProcessingTest.cpp"],
-
- shared_libs: [
- "libaudiopreprocessing_legacy",
+ name: "EffectPreprocessingTest",
+ defaults: ["libaudiopreprocessing-defaults"],
+ gtest: true,
+ test_suites: ["device-tests"],
+ srcs: [
+ "EffectPreprocessingTest.cpp",
+ "EffectTestHelper.cpp",
+ ],
+ static_libs: [
+ "libaudiopreprocessing",
"libaudioutils",
- "liblog",
- "libutils",
- "libwebrtc_audio_preprocessing",
- ],
-
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
-
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
],
}
cc_test {
name: "AudioPreProcessingTest",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
+ defaults: ["libaudiopreprocessing-defaults"],
+ gtest: false,
srcs: ["PreProcessingTest.cpp"],
-
- shared_libs: [
+ static_libs: [
"libaudiopreprocessing",
"libaudioutils",
- "liblog",
- "libutils",
],
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
+}
+
+cc_test {
+ name: "correlation",
+ host_supported: true,
+ srcs: ["correlation.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
],
+ gtest: false,
}
diff --git a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
new file mode 100644
index 0000000..07006a1
--- /dev/null
+++ b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EffectTestHelper.h"
+
+#include <getopt.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <tuple>
+#include <vector>
+
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
+#include <audio_effects/effect_agc2.h>
+#include <audio_effects/effect_ns.h>
+#include <log/log.h>
+
+constexpr effect_uuid_t kAGCUuid = {
+ 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+constexpr effect_uuid_t kAGC2Uuid = {
+ 0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}};
+constexpr effect_uuid_t kAECUuid = {
+ 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+constexpr effect_uuid_t kNSUuid = {
+ 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+static bool isAGCEffect(const effect_uuid_t* uuid) {
+ return uuid == &kAGCUuid;
+}
+static bool isAGC2Effect(const effect_uuid_t* uuid) {
+ return uuid == &kAGC2Uuid;
+}
+static bool isAECEffect(const effect_uuid_t* uuid) {
+ return uuid == &kAECUuid;
+}
+static bool isNSEffect(const effect_uuid_t* uuid) {
+ return uuid == &kNSUuid;
+}
+
+constexpr int kAGCTargetLevels[] = {0, -300, -500, -1000, -3100};
+
+constexpr int kAGCCompLevels[] = {0, -300, -500, -1000, -9000};
+
+constexpr size_t kAGC2FixedDigitalGains[] = {0, 3, 10, 20, 49};
+
+constexpr size_t kAGC2AdaptGigitalLevelEstimators[] = {0, 1};
+
+constexpr size_t kAGC2ExtraSaturationMargins[] = {0, 3, 10, 20, 100};
+
+constexpr size_t kAECEchoDelays[] = {0, 250, 500};
+
+constexpr size_t kNSLevels[] = {0, 1, 2, 3};
+
+struct AGCParams {
+ int targetLevel;
+ int compLevel;
+};
+
+struct AGC2Params {
+ size_t fixedDigitalGain;
+ size_t adaptDigiLevelEstimator;
+ size_t extraSaturationMargin;
+};
+
+struct AECParams {
+ size_t echoDelay;
+};
+
+struct NSParams {
+ size_t level;
+};
+
+struct PreProcParams {
+ const effect_uuid_t* uuid;
+ union {
+ AGCParams agcParams;
+ AGC2Params agc2Params;
+ AECParams aecParams;
+ NSParams nsParams;
+ };
+};
+
+// Create a list of pre-processing parameters to be used for testing
+static const std::vector<PreProcParams> kPreProcParams = [] {
+ std::vector<PreProcParams> result;
+
+ for (const auto targetLevel : kAGCTargetLevels) {
+ for (const auto compLevel : kAGCCompLevels) {
+ AGCParams agcParams = {.targetLevel = targetLevel, .compLevel = compLevel};
+ PreProcParams params = {.uuid = &kAGCUuid, .agcParams = agcParams};
+ result.push_back(params);
+ }
+ }
+
+ for (const auto fixedDigitalGain : kAGC2FixedDigitalGains) {
+ for (const auto adaptDigiLevelEstimator : kAGC2AdaptGigitalLevelEstimators) {
+ for (const auto extraSaturationMargin : kAGC2ExtraSaturationMargins) {
+ AGC2Params agc2Params = {.fixedDigitalGain = fixedDigitalGain,
+ .adaptDigiLevelEstimator = adaptDigiLevelEstimator,
+ .extraSaturationMargin = extraSaturationMargin};
+ PreProcParams params = {.uuid = &kAGC2Uuid, .agc2Params = agc2Params};
+ result.push_back(params);
+ }
+ }
+ }
+
+ for (const auto echoDelay : kAECEchoDelays) {
+ AECParams aecParams = {.echoDelay = echoDelay};
+ PreProcParams params = {.uuid = &kAECUuid, .aecParams = aecParams};
+ result.push_back(params);
+ }
+
+ for (const auto level : kNSLevels) {
+ NSParams nsParams = {.level = level};
+ PreProcParams params = {.uuid = &kNSUuid, .nsParams = nsParams};
+ result.push_back(params);
+ }
+ return result;
+}();
+
+static const size_t kNumPreProcParams = std::size(kPreProcParams);
+
+void setPreProcParams(const effect_uuid_t* uuid, EffectTestHelper& effect, size_t paramIdx) {
+ const PreProcParams* params = &kPreProcParams[paramIdx];
+ if (isAGCEffect(uuid)) {
+ const AGCParams* agcParams = ¶ms->agcParams;
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC_PARAM_TARGET_LEVEL, agcParams->targetLevel));
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC_PARAM_COMP_GAIN, agcParams->compLevel));
+ } else if (isAGC2Effect(uuid)) {
+ const AGC2Params* agc2Params = ¶ms->agc2Params;
+ ASSERT_NO_FATAL_FAILURE(
+ effect.setParam(AGC2_PARAM_FIXED_DIGITAL_GAIN, agc2Params->fixedDigitalGain));
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
+ agc2Params->adaptDigiLevelEstimator));
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
+ agc2Params->extraSaturationMargin));
+ } else if (isAECEffect(uuid)) {
+ const AECParams* aecParams = ¶ms->aecParams;
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(AEC_PARAM_ECHO_DELAY, aecParams->echoDelay));
+ } else if (isNSEffect(uuid)) {
+ const NSParams* nsParams = ¶ms->nsParams;
+ ASSERT_NO_FATAL_FAILURE(effect.setParam(NS_PARAM_LEVEL, nsParams->level));
+ }
+}
+
+typedef std::tuple<int, int, int, int> SingleEffectTestParam;
+class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
+ public:
+ SingleEffectTest()
+ : mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
+ mFrameCount(mSampleRate * EffectTestHelper::kTenMilliSecVal),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ mChannelCount(audio_channel_count_from_in_mask(mChMask)),
+ mParamIdx(std::get<3>(GetParam())),
+ mUuid(kPreProcParams[mParamIdx].uuid){};
+
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const size_t mChMask;
+ const size_t mChannelCount;
+ const size_t mParamIdx;
+ const effect_uuid_t* mUuid;
+};
+
+// Tests applying a single effect
+TEST_P(SingleEffectTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message() << " chMask: " << mChMask << " sampleRate: " << mSampleRate
+ << " loopCount: " << mLoopCount << " paramIdx " << mParamIdx);
+
+ EffectTestHelper effect(mUuid, mChMask, mSampleRate, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(effect.setConfig(isAECEffect(mUuid)));
+ ASSERT_NO_FATAL_FAILURE(setPreProcParams(mUuid, effect, mParamIdx));
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::vector<int16_t> input(mTotalFrameCount * mChannelCount);
+ std::vector<int16_t> output(mTotalFrameCount * mChannelCount);
+ std::vector<int16_t> farInput(mTotalFrameCount * mChannelCount);
+ std::minstd_rand gen(mChMask);
+ std::uniform_int_distribution<int16_t> dis(INT16_MIN, INT16_MAX);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+ if (isAECEffect(mUuid)) {
+ for (auto& farIn : farInput) {
+ farIn = dis(gen);
+ }
+ }
+ ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data(), isAECEffect(mUuid)));
+ if (isAECEffect(mUuid)) {
+ ASSERT_NO_FATAL_FAILURE(effect.process_reverse(farInput.data(), output.data()));
+ }
+ ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PreProcTestAll, SingleEffectTest,
+ ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
+ ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
+ ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumPreProcParams)));
+
+typedef std::tuple<int, int, int> SingleEffectComparisonTestParam;
+class SingleEffectComparisonTest
+ : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
+ public:
+ SingleEffectComparisonTest()
+ : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
+ mFrameCount(mSampleRate * EffectTestHelper::kTenMilliSecVal),
+ mLoopCount(EffectTestHelper::kLoopCounts[std::get<1>(GetParam())]),
+ mTotalFrameCount(mFrameCount * mLoopCount),
+ mParamIdx(std::get<2>(GetParam())),
+ mUuid(kPreProcParams[mParamIdx].uuid){};
+
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ const size_t mTotalFrameCount;
+ const size_t mParamIdx;
+ const effect_uuid_t* mUuid;
+};
+
+// Compares first channel in multi-channel output to mono output when same effect is applied
+TEST_P(SingleEffectComparisonTest, SimpleProcess) {
+ SCOPED_TRACE(testing::Message() << " sampleRate: " << mSampleRate
+ << " loopCount: " << mLoopCount << " paramIdx " << mParamIdx);
+
+ // Initialize mono input buffer with deterministic pseudo-random values
+ std::vector<int16_t> monoInput(mTotalFrameCount);
+ std::vector<int16_t> monoFarInput(mTotalFrameCount);
+
+ std::minstd_rand gen(mSampleRate);
+ std::uniform_int_distribution<int16_t> dis(INT16_MIN, INT16_MAX);
+ for (auto& in : monoInput) {
+ in = dis(gen);
+ }
+ if (isAECEffect(mUuid)) {
+ for (auto& farIn : monoFarInput) {
+ farIn = dis(gen);
+ }
+ }
+
+ // Apply effect on mono channel
+ EffectTestHelper monoEffect(mUuid, AUDIO_CHANNEL_INDEX_MASK_1, mSampleRate, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(monoEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(monoEffect.setConfig(isAECEffect(mUuid)));
+ ASSERT_NO_FATAL_FAILURE(setPreProcParams(mUuid, monoEffect, mParamIdx));
+
+ std::vector<int16_t> monoOutput(mTotalFrameCount);
+ ASSERT_NO_FATAL_FAILURE(
+ monoEffect.process(monoInput.data(), monoOutput.data(), isAECEffect(mUuid)));
+ if (isAECEffect(mUuid)) {
+ ASSERT_NO_FATAL_FAILURE(monoEffect.process_reverse(monoFarInput.data(), monoOutput.data()));
+ }
+ ASSERT_NO_FATAL_FAILURE(monoEffect.releaseEffect());
+
+ for (size_t chMask : EffectTestHelper::kChMasks) {
+ size_t channelCount = audio_channel_count_from_in_mask(chMask);
+
+ EffectTestHelper testEffect(mUuid, chMask, mSampleRate, mLoopCount);
+
+ ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
+ ASSERT_NO_FATAL_FAILURE(testEffect.setConfig(isAECEffect(mUuid)));
+ ASSERT_NO_FATAL_FAILURE(setPreProcParams(mUuid, testEffect, mParamIdx));
+
+ std::vector<int16_t> testInput(mTotalFrameCount * channelCount);
+ std::vector<int16_t> testFarInput(mTotalFrameCount * channelCount);
+
+ // Repeat mono channel data to all the channels
+ // adjust_channels() zero fills channels > 2, hence can't be used here
+ for (size_t i = 0; i < mTotalFrameCount; ++i) {
+ auto* fpInput = &testInput[i * channelCount];
+ std::fill(fpInput, fpInput + channelCount, monoInput[i]);
+ }
+ if (isAECEffect(mUuid)) {
+ for (size_t i = 0; i < mTotalFrameCount; ++i) {
+ auto* fpFarInput = &testFarInput[i * channelCount];
+ std::fill(fpFarInput, fpFarInput + channelCount, monoFarInput[i]);
+ }
+ }
+
+ std::vector<int16_t> testOutput(mTotalFrameCount * channelCount);
+ ASSERT_NO_FATAL_FAILURE(
+ testEffect.process(testInput.data(), testOutput.data(), isAECEffect(mUuid)));
+ if (isAECEffect(mUuid)) {
+ ASSERT_NO_FATAL_FAILURE(
+ testEffect.process_reverse(testFarInput.data(), testOutput.data()));
+ }
+ ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
+
+ // Adjust the test output to mono channel
+ std::vector<int16_t> monoTestOutput(mTotalFrameCount);
+ adjust_channels(testOutput.data(), channelCount, monoTestOutput.data(), FCC_1,
+ sizeof(int16_t), mTotalFrameCount * sizeof(int16_t) * channelCount);
+
+ ASSERT_EQ(0, memcmp(monoOutput.data(), monoTestOutput.data(),
+ mTotalFrameCount * sizeof(int16_t)))
+ << "Mono channel output does not match with reference output \n";
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PreProcTestAll, SingleEffectComparisonTest,
+ ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
+ ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Range(0, (int)kNumPreProcParams)));
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d", status);
+ return status;
+}
diff --git a/media/libeffects/preprocessing/tests/EffectTestHelper.cpp b/media/libeffects/preprocessing/tests/EffectTestHelper.cpp
new file mode 100644
index 0000000..79200b6
--- /dev/null
+++ b/media/libeffects/preprocessing/tests/EffectTestHelper.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EffectTestHelper.h"
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+
+void EffectTestHelper::createEffect() {
+ int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(mUuid, 1, 1, &mEffectHandle);
+ ASSERT_EQ(status, 0) << "create_effect returned an error " << status;
+}
+
+void EffectTestHelper::releaseEffect() {
+ int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(mEffectHandle);
+ ASSERT_EQ(status, 0) << "release_effect returned an error " << status;
+}
+
+void EffectTestHelper::setConfig(bool configReverse) {
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = mSampleRate;
+ config.inputCfg.channels = config.outputCfg.channels = mChMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+
+ int status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ ASSERT_EQ(status, 0) << "set_config returned an error " << status;
+ ASSERT_EQ(reply, 0) << "set_config reply non zero " << reply;
+
+ if (configReverse) {
+ int status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE,
+ sizeof(effect_config_t), &config, &replySize, &reply);
+ ASSERT_EQ(status, 0) << "set_config_reverse returned an error " << status;
+ ASSERT_EQ(reply, 0) << "set_config_reverse reply non zero " << reply;
+ }
+
+ status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ ASSERT_EQ(status, 0) << "cmd_enable returned an error " << status;
+ ASSERT_EQ(reply, 0) << "cmd_enable reply non zero " << reply;
+}
+
+void EffectTestHelper::setParam(uint32_t type, uint32_t value) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {type, value};
+ auto effectParam = (effect_param_t*)malloc(sizeof(effect_param_t) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ effectParam->vsize = sizeof(paramData[1]);
+ int status = (*mEffectHandle)
+ ->command(mEffectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + sizeof(paramData), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ ASSERT_EQ(status, 0) << "set_param returned an error " << status;
+ ASSERT_EQ(reply, 0) << "set_param reply non zero " << reply;
+}
+
+void EffectTestHelper::process(int16_t* input, int16_t* output, bool setAecEchoDelay) {
+ audio_buffer_t inBuffer = {.frameCount = mFrameCount, .s16 = input};
+ audio_buffer_t outBuffer = {.frameCount = mFrameCount, .s16 = output};
+ for (size_t i = 0; i < mLoopCount; i++) {
+ if (setAecEchoDelay) ASSERT_NO_FATAL_FAILURE(setParam(AEC_PARAM_ECHO_DELAY, kAECDelay));
+ int status = (*mEffectHandle)->process(mEffectHandle, &inBuffer, &outBuffer);
+ ASSERT_EQ(status, 0) << "process returned an error " << status;
+
+ inBuffer.s16 += mFrameCount * mChannelCount;
+ outBuffer.s16 += mFrameCount * mChannelCount;
+ }
+}
+
+void EffectTestHelper::process_reverse(int16_t* farInput, int16_t* output) {
+ audio_buffer_t farInBuffer = {.frameCount = mFrameCount, .s16 = farInput};
+ audio_buffer_t outBuffer = {.frameCount = mFrameCount, .s16 = output};
+ for (size_t i = 0; i < mLoopCount; i++) {
+ int status = (*mEffectHandle)->process_reverse(mEffectHandle, &farInBuffer, &outBuffer);
+ ASSERT_EQ(status, 0) << "process returned an error " << status;
+
+ farInBuffer.s16 += mFrameCount * mChannelCount;
+ outBuffer.s16 += mFrameCount * mChannelCount;
+ }
+}
diff --git a/media/libeffects/preprocessing/tests/EffectTestHelper.h b/media/libeffects/preprocessing/tests/EffectTestHelper.h
new file mode 100644
index 0000000..117cf7b
--- /dev/null
+++ b/media/libeffects/preprocessing/tests/EffectTestHelper.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <array>
+#include <audio_effects/effect_aec.h>
+#include <audio_utils/channels.h>
+#include <audio_utils/primitives.h>
+#include <climits>
+#include <cstdlib>
+#include <gtest/gtest.h>
+#include <hardware/audio_effect.h>
+#include <log/log.h>
+#include <random>
+#include <stdint.h>
+#include <system/audio.h>
+#include <vector>
+
+template <typename T>
+static float computeSnr(const T* ref, const T* tst, size_t count) {
+ double signal{};
+ double noise{};
+
+ for (size_t i = 0; i < count; ++i) {
+ const double value(ref[i]);
+ const double diff(tst[i] - value);
+ signal += value * value;
+ noise += diff * diff;
+ }
+ // Initialized to large value to handle
+ // cases where ref and tst match exactly
+ float snr = FLT_MAX;
+ if (signal > 0.0f && noise > 0.0f) {
+ snr = 10.f * log(signal / noise);
+ }
+ return snr;
+}
+
+class EffectTestHelper {
+ public:
+ EffectTestHelper(const effect_uuid_t* uuid, size_t chMask, size_t sampleRate, size_t loopCount)
+ : mUuid(uuid),
+ mChMask(chMask),
+ mChannelCount(audio_channel_count_from_in_mask(mChMask)),
+ mSampleRate(sampleRate),
+ mFrameCount(mSampleRate * kTenMilliSecVal),
+ mLoopCount(loopCount) {}
+ void createEffect();
+ void releaseEffect();
+ void setConfig(bool configReverse);
+ void setParam(uint32_t type, uint32_t val);
+ void process(int16_t* input, int16_t* output, bool setAecEchoDelay);
+ void process_reverse(int16_t* farInput, int16_t* output);
+
+ // Corresponds to SNR for 1 bit difference between two int16_t signals
+ static constexpr float kSNRThreshold = 90.308998;
+
+ static constexpr audio_channel_mask_t kChMasks[] = {
+ AUDIO_CHANNEL_IN_MONO,
+ AUDIO_CHANNEL_IN_STEREO,
+ AUDIO_CHANNEL_IN_FRONT_BACK,
+ AUDIO_CHANNEL_IN_6,
+ AUDIO_CHANNEL_IN_2POINT0POINT2,
+ AUDIO_CHANNEL_IN_2POINT1POINT2,
+ AUDIO_CHANNEL_IN_3POINT0POINT2,
+ AUDIO_CHANNEL_IN_3POINT1POINT2,
+ AUDIO_CHANNEL_IN_5POINT1,
+ AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO,
+ AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO,
+ AUDIO_CHANNEL_IN_VOICE_CALL_MONO,
+ };
+
+ static constexpr float kTenMilliSecVal = 0.01;
+
+ static constexpr size_t kNumChMasks = std::size(kChMasks);
+
+ static constexpr size_t kSampleRates[] = {8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000};
+
+ static constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+ static constexpr size_t kLoopCounts[] = {1, 4};
+
+ static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
+
+ static constexpr size_t kAECDelay = 0;
+
+ private:
+ const effect_uuid_t* mUuid;
+ const size_t mChMask;
+ const size_t mChannelCount;
+ const size_t mSampleRate;
+ const size_t mFrameCount;
+ const size_t mLoopCount;
+ effect_handle_t mEffectHandle{};
+};
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 3e8ea76..3bd93f8 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -22,10 +22,9 @@
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_agc.h>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
+#include <audio_utils/channels.h>
#include <log/log.h>
// This is the only symbol that needs to be imported
@@ -37,464 +36,497 @@
// types of pre processing modules
enum PreProcId {
- PREPROC_AGC, // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
- PREPROC_AGC2, // Automatic Gain Control 2
-#endif
- PREPROC_AEC, // Acoustic Echo Canceler
- PREPROC_NS, // Noise Suppressor
- PREPROC_NUM_EFFECTS
+ PREPROC_AGC, // Automatic Gain Control
+ PREPROC_AGC2, // Automatic Gain Control 2
+ PREPROC_AEC, // Acoustic Echo Canceler
+ PREPROC_NS, // Noise Suppressor
+ PREPROC_NUM_EFFECTS
};
enum PreProcParams {
- ARG_HELP = 1,
- ARG_INPUT,
- ARG_OUTPUT,
- ARG_FAR,
- ARG_FS,
- ARG_CH_MASK,
- ARG_AGC_TGT_LVL,
- ARG_AGC_COMP_LVL,
- ARG_AEC_DELAY,
- ARG_NS_LVL,
-#ifndef WEBRTC_LEGACY
- ARG_AGC2_GAIN,
- ARG_AGC2_LVL,
- ARG_AGC2_SAT_MGN
-#endif
+ ARG_HELP = 1,
+ ARG_INPUT,
+ ARG_OUTPUT,
+ ARG_FAR,
+ ARG_FS,
+ ARG_CH_MASK,
+ ARG_AGC_TGT_LVL,
+ ARG_AGC_COMP_LVL,
+ ARG_AEC_DELAY,
+ ARG_NS_LVL,
+ ARG_AGC2_GAIN,
+ ARG_AGC2_LVL,
+ ARG_AGC2_SAT_MGN,
+ ARG_FILE_CHANNELS,
+ ARG_MONO_MODE
};
struct preProcConfigParams_t {
- int samplingFreq = 16000;
- audio_channel_mask_t chMask = AUDIO_CHANNEL_IN_MONO;
- int nsLevel = 0; // a value between 0-3
- int agcTargetLevel = 3; // in dB
- int agcCompLevel = 9; // in dB
-#ifndef WEBRTC_LEGACY
- float agc2Gain = 0.f; // in dB
- float agc2SaturationMargin = 2.f; // in dB
- int agc2Level = 0; // either kRms(0) or kPeak(1)
-#endif
- int aecDelay = 0; // in ms
+ int samplingFreq = 16000;
+ audio_channel_mask_t chMask = AUDIO_CHANNEL_IN_MONO;
+ int nsLevel = 0; // a value between 0-3
+ int agcTargetLevel = 3; // in dB
+ int agcCompLevel = 9; // in dB
+ float agc2Gain = 0.f; // in dB
+ float agc2SaturationMargin = 2.f; // in dB
+ int agc2Level = 0; // either kRms(0) or kPeak(1)
+ int aecDelay = 0; // in ms
+ int fileChannels = 1;
+ int monoMode = 0;
};
const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
- {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // agc uuid
-#ifndef WEBRTC_LEGACY
- {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // agc2 uuid
-#endif
- {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // aec uuid
- {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // ns uuid
+ {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // agc uuid
+ {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // agc2 uuid
+ {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // aec uuid
+ {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // ns uuid
};
constexpr audio_channel_mask_t kPreProcConfigChMask[] = {
- AUDIO_CHANNEL_IN_MONO,
- AUDIO_CHANNEL_IN_STEREO,
- AUDIO_CHANNEL_IN_FRONT_BACK,
- AUDIO_CHANNEL_IN_6,
- AUDIO_CHANNEL_IN_2POINT0POINT2,
- AUDIO_CHANNEL_IN_2POINT1POINT2,
- AUDIO_CHANNEL_IN_3POINT0POINT2,
- AUDIO_CHANNEL_IN_3POINT1POINT2,
- AUDIO_CHANNEL_IN_5POINT1,
- AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO,
- AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO,
- AUDIO_CHANNEL_IN_VOICE_CALL_MONO,
+ AUDIO_CHANNEL_IN_MONO,
+ AUDIO_CHANNEL_IN_STEREO,
+ AUDIO_CHANNEL_IN_FRONT_BACK,
+ AUDIO_CHANNEL_IN_6,
+ AUDIO_CHANNEL_IN_2POINT0POINT2,
+ AUDIO_CHANNEL_IN_2POINT1POINT2,
+ AUDIO_CHANNEL_IN_3POINT0POINT2,
+ AUDIO_CHANNEL_IN_3POINT1POINT2,
+ AUDIO_CHANNEL_IN_5POINT1,
+ AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO,
+ AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO,
+ AUDIO_CHANNEL_IN_VOICE_CALL_MONO,
};
constexpr int kPreProcConfigChMaskCount = std::size(kPreProcConfigChMask);
void printUsage() {
- printf("\nUsage: ");
- printf("\n <executable> [options]\n");
- printf("\nwhere options are, ");
- printf("\n --input <inputfile>");
- printf("\n path to the input file");
- printf("\n --output <outputfile>");
- printf("\n path to the output file");
- printf("\n --help");
- printf("\n Prints this usage information");
- printf("\n --fs <sampling_freq>");
- printf("\n Sampling frequency in Hz, default 16000.");
- printf("\n -ch_mask <channel_mask>\n");
- printf("\n 0 - AUDIO_CHANNEL_IN_MONO");
- printf("\n 1 - AUDIO_CHANNEL_IN_STEREO");
- printf("\n 2 - AUDIO_CHANNEL_IN_FRONT_BACK");
- printf("\n 3 - AUDIO_CHANNEL_IN_6");
- printf("\n 4 - AUDIO_CHANNEL_IN_2POINT0POINT2");
- printf("\n 5 - AUDIO_CHANNEL_IN_2POINT1POINT2");
- printf("\n 6 - AUDIO_CHANNEL_IN_3POINT0POINT2");
- printf("\n 7 - AUDIO_CHANNEL_IN_3POINT1POINT2");
- printf("\n 8 - AUDIO_CHANNEL_IN_5POINT1");
- printf("\n 9 - AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO");
- printf("\n 10 - AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO ");
- printf("\n 11 - AUDIO_CHANNEL_IN_VOICE_CALL_MONO ");
- printf("\n default 0");
- printf("\n --far <farend_file>");
- printf("\n Path to far-end file needed for echo cancellation");
- printf("\n --aec");
- printf("\n Enable Echo Cancellation, default disabled");
- printf("\n --ns");
- printf("\n Enable Noise Suppression, default disabled");
- printf("\n --agc");
- printf("\n Enable Gain Control, default disabled");
-#ifndef WEBRTC_LEGACY
- printf("\n --agc2");
- printf("\n Enable Gain Controller 2, default disabled");
-#endif
- printf("\n --ns_lvl <ns_level>");
- printf("\n Noise Suppression level in dB, default value 0dB");
- printf("\n --agc_tgt_lvl <target_level>");
- printf("\n AGC Target Level in dB, default value 3dB");
- printf("\n --agc_comp_lvl <comp_level>");
- printf("\n AGC Comp Level in dB, default value 9dB");
-#ifndef WEBRTC_LEGACY
- printf("\n --agc2_gain <fixed_digital_gain>");
- printf("\n AGC Fixed Digital Gain in dB, default value 0dB");
- printf("\n --agc2_lvl <level_estimator>");
- printf("\n AGC Adaptive Digital Level Estimator, default value kRms");
- printf("\n --agc2_sat_mgn <saturation_margin>");
- printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
-#endif
- printf("\n --aec_delay <delay>");
- printf("\n AEC delay value in ms, default value 0ms");
- printf("\n");
+ printf("\nUsage: ");
+ printf("\n <executable> [options]\n");
+ printf("\nwhere options are, ");
+ printf("\n --input <inputfile>");
+ printf("\n path to the input file");
+ printf("\n --output <outputfile>");
+ printf("\n path to the output file");
+ printf("\n --help");
+ printf("\n Prints this usage information");
+ printf("\n --fs <sampling_freq>");
+ printf("\n Sampling frequency in Hz, default 16000.");
+ printf("\n --ch_mask <channel_mask>\n");
+ printf("\n 0 - AUDIO_CHANNEL_IN_MONO");
+ printf("\n 1 - AUDIO_CHANNEL_IN_STEREO");
+ printf("\n 2 - AUDIO_CHANNEL_IN_FRONT_BACK");
+ printf("\n 3 - AUDIO_CHANNEL_IN_6");
+ printf("\n 4 - AUDIO_CHANNEL_IN_2POINT0POINT2");
+ printf("\n 5 - AUDIO_CHANNEL_IN_2POINT1POINT2");
+ printf("\n 6 - AUDIO_CHANNEL_IN_3POINT0POINT2");
+ printf("\n 7 - AUDIO_CHANNEL_IN_3POINT1POINT2");
+ printf("\n 8 - AUDIO_CHANNEL_IN_5POINT1");
+ printf("\n 9 - AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO");
+ printf("\n 10 - AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO ");
+ printf("\n 11 - AUDIO_CHANNEL_IN_VOICE_CALL_MONO ");
+ printf("\n default 0");
+ printf("\n --far <farend_file>");
+ printf("\n Path to far-end file needed for echo cancellation");
+ printf("\n --aec");
+ printf("\n Enable Echo Cancellation, default disabled");
+ printf("\n --ns");
+ printf("\n Enable Noise Suppression, default disabled");
+ printf("\n --agc");
+ printf("\n Enable Gain Control, default disabled");
+ printf("\n --agc2");
+ printf("\n Enable Gain Controller 2, default disabled");
+ printf("\n --ns_lvl <ns_level>");
+ printf("\n Noise Suppression level in dB, default value 0dB");
+ printf("\n --agc_tgt_lvl <target_level>");
+ printf("\n AGC Target Level in dB, default value 3dB");
+ printf("\n --agc_comp_lvl <comp_level>");
+ printf("\n AGC Comp Level in dB, default value 9dB");
+ printf("\n --agc2_gain <fixed_digital_gain>");
+ printf("\n AGC Fixed Digital Gain in dB, default value 0dB");
+ printf("\n --agc2_lvl <level_estimator>");
+ printf("\n AGC Adaptive Digital Level Estimator, default value kRms");
+ printf("\n --agc2_sat_mgn <saturation_margin>");
+ printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
+ printf("\n --aec_delay <delay>");
+ printf("\n AEC delay value in ms, default value 0ms");
+ printf("\n --fch <fileChannels>");
+ printf("\n number of channels in the input file");
+ printf("\n --mono <Mono Mode>");
+ printf("\n Mode to make data of all channels the same as first channel");
+ printf("\n");
}
constexpr float kTenMilliSecVal = 0.01;
-int preProcCreateEffect(effect_handle_t *pEffectHandle, uint32_t effectType,
- effect_config_t *pConfig, int sessionId, int ioId) {
- if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kPreProcUuids[effectType],
- sessionId, ioId, pEffectHandle);
- status != 0) {
- ALOGE("Audio Preprocessing create returned an error = %d\n", status);
- return EXIT_FAILURE;
- }
- int reply = 0;
- uint32_t replySize = sizeof(reply);
- if (effectType == PREPROC_AEC) {
+int preProcCreateEffect(effect_handle_t* pEffectHandle, uint32_t effectType,
+ effect_config_t* pConfig, int sessionId, int ioId) {
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kPreProcUuids[effectType],
+ sessionId, ioId, pEffectHandle);
+ status != 0) {
+ ALOGE("Audio Preprocessing create returned an error = %d\n", status);
+ return EXIT_FAILURE;
+ }
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (effectType == PREPROC_AEC) {
+ (**pEffectHandle)
+ ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE, sizeof(effect_config_t),
+ pConfig, &replySize, &reply);
+ }
(**pEffectHandle)
- ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE, sizeof(effect_config_t), pConfig,
- &replySize, &reply);
- }
- (**pEffectHandle)
- ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t), pConfig,
- &replySize, &reply);
- return reply;
+ ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t), pConfig,
+ &replySize, &reply);
+ return reply;
}
int preProcSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
- int reply = 0;
- uint32_t replySize = sizeof(reply);
- uint32_t paramData[2] = {paramType, paramValue};
- effect_param_t *effectParam =
- (effect_param_t *)malloc(sizeof(*effectParam) + sizeof(paramData));
- memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
- effectParam->psize = sizeof(paramData[0]);
- (*effectHandle)
- ->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t), effectParam,
- &replySize, &reply);
- free(effectParam);
- return reply;
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {paramType, paramValue};
+ effect_param_t* effectParam = (effect_param_t*)malloc(sizeof(*effectParam) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ return reply;
}
-int main(int argc, const char *argv[]) {
- if (argc == 1) {
- printUsage();
- return EXIT_FAILURE;
- }
- const char *inputFile = nullptr;
- const char *outputFile = nullptr;
- const char *farFile = nullptr;
- int effectEn[PREPROC_NUM_EFFECTS] = {0};
-
- const option long_opts[] = {
- {"help", no_argument, nullptr, ARG_HELP},
- {"input", required_argument, nullptr, ARG_INPUT},
- {"output", required_argument, nullptr, ARG_OUTPUT},
- {"far", required_argument, nullptr, ARG_FAR},
- {"fs", required_argument, nullptr, ARG_FS},
- {"ch_mask", required_argument, nullptr, ARG_CH_MASK},
- {"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
- {"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
-#ifndef WEBRTC_LEGACY
- {"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
- {"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
- {"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
-#endif
- {"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
- {"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
- {"aec", no_argument, &effectEn[PREPROC_AEC], 1},
- {"agc", no_argument, &effectEn[PREPROC_AGC], 1},
-#ifndef WEBRTC_LEGACY
- {"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
-#endif
- {"ns", no_argument, &effectEn[PREPROC_NS], 1},
- {nullptr, 0, nullptr, 0},
- };
- struct preProcConfigParams_t preProcCfgParams {};
-
- while (true) {
- const int opt = getopt_long(argc, (char *const *)argv, "i:o:", long_opts, nullptr);
- if (opt == -1) {
- break;
- }
- switch (opt) {
- case ARG_HELP:
+int main(int argc, const char* argv[]) {
+ if (argc == 1) {
printUsage();
- return 0;
- case ARG_INPUT: {
- inputFile = (char *)optarg;
- break;
- }
- case ARG_OUTPUT: {
- outputFile = (char *)optarg;
- break;
- }
- case ARG_FAR: {
- farFile = (char *)optarg;
- break;
- }
- case ARG_FS: {
- preProcCfgParams.samplingFreq = atoi(optarg);
- break;
- }
- case ARG_CH_MASK: {
- int chMaskIdx = atoi(optarg);
- if (chMaskIdx < 0 or chMaskIdx > kPreProcConfigChMaskCount) {
- ALOGE("Channel Mask index not in correct range\n");
- printUsage();
- return EXIT_FAILURE;
- }
- preProcCfgParams.chMask = kPreProcConfigChMask[chMaskIdx];
- break;
- }
- case ARG_AGC_TGT_LVL: {
- preProcCfgParams.agcTargetLevel = atoi(optarg);
- break;
- }
- case ARG_AGC_COMP_LVL: {
- preProcCfgParams.agcCompLevel = atoi(optarg);
- break;
- }
-#ifndef WEBRTC_LEGACY
- case ARG_AGC2_GAIN: {
- preProcCfgParams.agc2Gain = atof(optarg);
- break;
- }
- case ARG_AGC2_LVL: {
- preProcCfgParams.agc2Level = atoi(optarg);
- break;
- }
- case ARG_AGC2_SAT_MGN: {
- preProcCfgParams.agc2SaturationMargin = atof(optarg);
- break;
- }
-#endif
- case ARG_AEC_DELAY: {
- preProcCfgParams.aecDelay = atoi(optarg);
- break;
- }
- case ARG_NS_LVL: {
- preProcCfgParams.nsLevel = atoi(optarg);
- break;
- }
- default:
- break;
- }
- }
-
- if (inputFile == nullptr) {
- ALOGE("Error: missing input file\n");
- printUsage();
- return EXIT_FAILURE;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> inputFp(fopen(inputFile, "rb"), &fclose);
- if (inputFp == nullptr) {
- ALOGE("Cannot open input file %s\n", inputFile);
- return EXIT_FAILURE;
- }
-
- std::unique_ptr<FILE, decltype(&fclose)> farFp(fopen(farFile, "rb"), &fclose);
- std::unique_ptr<FILE, decltype(&fclose)> outputFp(fopen(outputFile, "wb"), &fclose);
- if (effectEn[PREPROC_AEC]) {
- if (farFile == nullptr) {
- ALOGE("Far end signal file required for echo cancellation \n");
- return EXIT_FAILURE;
- }
- if (farFp == nullptr) {
- ALOGE("Cannot open far end stream file %s\n", farFile);
- return EXIT_FAILURE;
- }
- struct stat statInput, statFar;
- (void)fstat(fileno(inputFp.get()), &statInput);
- (void)fstat(fileno(farFp.get()), &statFar);
- if (statInput.st_size != statFar.st_size) {
- ALOGE("Near and far end signals are of different sizes");
- return EXIT_FAILURE;
- }
- }
- if (outputFile != nullptr && outputFp == nullptr) {
- ALOGE("Cannot open output file %s\n", outputFile);
- return EXIT_FAILURE;
- }
-
- int32_t sessionId = 1;
- int32_t ioId = 1;
- effect_handle_t effectHandle[PREPROC_NUM_EFFECTS] = {nullptr};
- effect_config_t config;
- config.inputCfg.samplingRate = config.outputCfg.samplingRate = preProcCfgParams.samplingFreq;
- config.inputCfg.channels = config.outputCfg.channels = preProcCfgParams.chMask;
- config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
-
- // Create all the effect handles
- for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
- if (int status = preProcCreateEffect(&effectHandle[i], i, &config, sessionId, ioId);
- status != 0) {
- ALOGE("Create effect call returned error %i", status);
- return EXIT_FAILURE;
- }
- }
-
- for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
- if (effectEn[i] == 1) {
- int reply = 0;
- uint32_t replySize = sizeof(reply);
- (*effectHandle[i])
- ->command(effectHandle[i], EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
- if (reply != 0) {
- ALOGE("Command enable call returned error %d\n", reply);
return EXIT_FAILURE;
- }
}
- }
- // Set Config Params of the effects
- if (effectEn[PREPROC_AGC]) {
- if (int status = preProcSetConfigParam(AGC_PARAM_TARGET_LEVEL,
- (uint32_t)preProcCfgParams.agcTargetLevel,
- effectHandle[PREPROC_AGC]);
- status != 0) {
- ALOGE("Invalid AGC Target Level. Error %d\n", status);
- return EXIT_FAILURE;
+ // Print the arguments passed
+ for (int i = 1; i < argc; i++) {
+ printf("%s ", argv[i]);
}
- if (int status =
- preProcSetConfigParam(AGC_PARAM_COMP_GAIN, (uint32_t)preProcCfgParams.agcCompLevel,
- effectHandle[PREPROC_AGC]);
- status != 0) {
- ALOGE("Invalid AGC Comp Gain. Error %d\n", status);
- return EXIT_FAILURE;
- }
- }
-#ifndef WEBRTC_LEGACY
- if (effectEn[PREPROC_AGC2]) {
- if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
- (float)preProcCfgParams.agc2Gain,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
- return EXIT_FAILURE;
- }
- if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
- (uint32_t)preProcCfgParams.agc2Level,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
- return EXIT_FAILURE;
- }
- if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
- (float)preProcCfgParams.agc2SaturationMargin,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
- return EXIT_FAILURE;
- }
- }
-#endif
- if (effectEn[PREPROC_NS]) {
- if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
- effectHandle[PREPROC_NS]);
- status != 0) {
- ALOGE("Invalid Noise Suppression level Error %d\n", status);
- return EXIT_FAILURE;
- }
- }
- // Process Call
- const int frameLength = (int)(preProcCfgParams.samplingFreq * kTenMilliSecVal);
- const int ioChannelCount = audio_channel_count_from_in_mask(preProcCfgParams.chMask);
- const int ioFrameSize = ioChannelCount * sizeof(short);
- int frameCounter = 0;
- while (true) {
- std::vector<short> in(frameLength * ioChannelCount);
- std::vector<short> out(frameLength * ioChannelCount);
- std::vector<short> farIn(frameLength * ioChannelCount);
- size_t samplesRead = fread(in.data(), ioFrameSize, frameLength, inputFp.get());
- if (samplesRead == 0) {
- break;
- }
- audio_buffer_t inputBuffer, outputBuffer;
- audio_buffer_t farInBuffer{};
- inputBuffer.frameCount = samplesRead;
- outputBuffer.frameCount = samplesRead;
- inputBuffer.s16 = in.data();
- outputBuffer.s16 = out.data();
+ const char* inputFile = nullptr;
+ const char* outputFile = nullptr;
+ const char* farFile = nullptr;
+ int effectEn[PREPROC_NUM_EFFECTS] = {0};
+ struct preProcConfigParams_t preProcCfgParams {};
- if (farFp != nullptr) {
- samplesRead = fread(farIn.data(), ioFrameSize, frameLength, farFp.get());
- if (samplesRead == 0) {
- break;
- }
- farInBuffer.frameCount = samplesRead;
- farInBuffer.s16 = farIn.data();
+ const option long_opts[] = {
+ {"help", no_argument, nullptr, ARG_HELP},
+ {"input", required_argument, nullptr, ARG_INPUT},
+ {"output", required_argument, nullptr, ARG_OUTPUT},
+ {"far", required_argument, nullptr, ARG_FAR},
+ {"fs", required_argument, nullptr, ARG_FS},
+ {"ch_mask", required_argument, nullptr, ARG_CH_MASK},
+ {"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
+ {"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
+ {"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
+ {"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
+ {"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
+ {"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
+ {"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
+ {"aec", no_argument, &effectEn[PREPROC_AEC], 1},
+ {"agc", no_argument, &effectEn[PREPROC_AGC], 1},
+ {"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
+ {"ns", no_argument, &effectEn[PREPROC_NS], 1},
+ {"fch", required_argument, nullptr, ARG_FILE_CHANNELS},
+ {"mono", no_argument, &preProcCfgParams.monoMode, 1},
+ {nullptr, 0, nullptr, 0},
+ };
+
+ while (true) {
+ const int opt = getopt_long(argc, (char* const*)argv, "i:o:", long_opts, nullptr);
+ if (opt == -1) {
+ break;
+ }
+ switch (opt) {
+ case ARG_HELP:
+ printUsage();
+ return 0;
+ case ARG_INPUT: {
+ inputFile = (char*)optarg;
+ break;
+ }
+ case ARG_OUTPUT: {
+ outputFile = (char*)optarg;
+ break;
+ }
+ case ARG_FAR: {
+ farFile = (char*)optarg;
+ break;
+ }
+ case ARG_FS: {
+ preProcCfgParams.samplingFreq = atoi(optarg);
+ break;
+ }
+ case ARG_CH_MASK: {
+ int chMaskIdx = atoi(optarg);
+ if (chMaskIdx < 0 or chMaskIdx > kPreProcConfigChMaskCount) {
+ ALOGE("Channel Mask index not in correct range\n");
+ printUsage();
+ return EXIT_FAILURE;
+ }
+ preProcCfgParams.chMask = kPreProcConfigChMask[chMaskIdx];
+ break;
+ }
+ case ARG_AGC_TGT_LVL: {
+ preProcCfgParams.agcTargetLevel = atoi(optarg);
+ break;
+ }
+ case ARG_AGC_COMP_LVL: {
+ preProcCfgParams.agcCompLevel = atoi(optarg);
+ break;
+ }
+ case ARG_AGC2_GAIN: {
+ preProcCfgParams.agc2Gain = atof(optarg);
+ break;
+ }
+ case ARG_AGC2_LVL: {
+ preProcCfgParams.agc2Level = atoi(optarg);
+ break;
+ }
+ case ARG_AGC2_SAT_MGN: {
+ preProcCfgParams.agc2SaturationMargin = atof(optarg);
+ break;
+ }
+ case ARG_AEC_DELAY: {
+ preProcCfgParams.aecDelay = atoi(optarg);
+ break;
+ }
+ case ARG_NS_LVL: {
+ preProcCfgParams.nsLevel = atoi(optarg);
+ break;
+ }
+ case ARG_FILE_CHANNELS: {
+ preProcCfgParams.fileChannels = atoi(optarg);
+ break;
+ }
+ case ARG_MONO_MODE: {
+ preProcCfgParams.monoMode = 1;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (inputFile == nullptr) {
+ ALOGE("Error: missing input file\n");
+ printUsage();
+ return EXIT_FAILURE;
+ }
+
+ std::unique_ptr<FILE, decltype(&fclose)> inputFp(fopen(inputFile, "rb"), &fclose);
+ if (inputFp == nullptr) {
+ ALOGE("Cannot open input file %s\n", inputFile);
+ return EXIT_FAILURE;
+ }
+
+ std::unique_ptr<FILE, decltype(&fclose)> farFp(fopen(farFile, "rb"), &fclose);
+ std::unique_ptr<FILE, decltype(&fclose)> outputFp(fopen(outputFile, "wb"), &fclose);
+ if (effectEn[PREPROC_AEC]) {
+ if (farFile == nullptr) {
+ ALOGE("Far end signal file required for echo cancellation \n");
+ return EXIT_FAILURE;
+ }
+ if (farFp == nullptr) {
+ ALOGE("Cannot open far end stream file %s\n", farFile);
+ return EXIT_FAILURE;
+ }
+ struct stat statInput, statFar;
+ (void)fstat(fileno(inputFp.get()), &statInput);
+ (void)fstat(fileno(farFp.get()), &statFar);
+ if (statInput.st_size != statFar.st_size) {
+ ALOGE("Near and far end signals are of different sizes");
+ return EXIT_FAILURE;
+ }
+ }
+ if (outputFile != nullptr && outputFp == nullptr) {
+ ALOGE("Cannot open output file %s\n", outputFile);
+ return EXIT_FAILURE;
+ }
+
+ int32_t sessionId = 1;
+ int32_t ioId = 1;
+ effect_handle_t effectHandle[PREPROC_NUM_EFFECTS] = {nullptr};
+ effect_config_t config;
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = preProcCfgParams.samplingFreq;
+ config.inputCfg.channels = config.outputCfg.channels = preProcCfgParams.chMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+
+ // Create all the effect handles
+ for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+ if (int status = preProcCreateEffect(&effectHandle[i], i, &config, sessionId, ioId);
+ status != 0) {
+ ALOGE("Create effect call returned error %i", status);
+ return EXIT_FAILURE;
+ }
}
for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
- if (effectEn[i] == 1) {
- if (i == PREPROC_AEC) {
- if (int status =
- preProcSetConfigParam(AEC_PARAM_ECHO_DELAY, (uint32_t)preProcCfgParams.aecDelay,
- effectHandle[PREPROC_AEC]);
- status != 0) {
- ALOGE("preProcSetConfigParam returned Error %d\n", status);
- return EXIT_FAILURE;
- }
+ if (effectEn[i] == 1) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ (*effectHandle[i])
+ ->command(effectHandle[i], EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ if (reply != 0) {
+ ALOGE("Command enable call returned error %d\n", reply);
+ return EXIT_FAILURE;
+ }
}
- if (int status =
- (*effectHandle[i])->process(effectHandle[i], &inputBuffer, &outputBuffer);
+ }
+
+ // Set Config Params of the effects
+ if (effectEn[PREPROC_AGC]) {
+ if (int status = preProcSetConfigParam(AGC_PARAM_TARGET_LEVEL,
+ (uint32_t)preProcCfgParams.agcTargetLevel,
+ effectHandle[PREPROC_AGC]);
status != 0) {
- ALOGE("\nError: Process i = %d returned with error %d\n", i, status);
- return EXIT_FAILURE;
- }
- if (i == PREPROC_AEC) {
- if (int status = (*effectHandle[i])
- ->process_reverse(effectHandle[i], &farInBuffer, &outputBuffer);
- status != 0) {
- ALOGE("\nError: Process reverse i = %d returned with error %d\n", i, status);
+ ALOGE("Invalid AGC Target Level. Error %d\n", status);
return EXIT_FAILURE;
- }
}
- }
+ if (int status = preProcSetConfigParam(AGC_PARAM_COMP_GAIN,
+ (uint32_t)preProcCfgParams.agcCompLevel,
+ effectHandle[PREPROC_AGC]);
+ status != 0) {
+ ALOGE("Invalid AGC Comp Gain. Error %d\n", status);
+ return EXIT_FAILURE;
+ }
}
- if (outputFp != nullptr) {
- size_t samplesWritten =
- fwrite(out.data(), ioFrameSize, outputBuffer.frameCount, outputFp.get());
- if (samplesWritten != outputBuffer.frameCount) {
- ALOGE("\nError: Output file writing failed");
- break;
- }
+ if (effectEn[PREPROC_AGC2]) {
+ if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
+ (float)preProcCfgParams.agc2Gain,
+ effectHandle[PREPROC_AGC2]);
+ status != 0) {
+ ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
+ return EXIT_FAILURE;
+ }
+ if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
+ (uint32_t)preProcCfgParams.agc2Level,
+ effectHandle[PREPROC_AGC2]);
+ status != 0) {
+ ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
+ return EXIT_FAILURE;
+ }
+ if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
+ (float)preProcCfgParams.agc2SaturationMargin,
+ effectHandle[PREPROC_AGC2]);
+ status != 0) {
+ ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
+ return EXIT_FAILURE;
+ }
}
- frameCounter += frameLength;
- }
- // Release all the effect handles created
- for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
- if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle[i]);
- status != 0) {
- ALOGE("Audio Preprocessing release returned an error = %d\n", status);
- return EXIT_FAILURE;
+ if (effectEn[PREPROC_NS]) {
+ if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
+ effectHandle[PREPROC_NS]);
+ status != 0) {
+ ALOGE("Invalid Noise Suppression level Error %d\n", status);
+ return EXIT_FAILURE;
+ }
}
- }
- return EXIT_SUCCESS;
+
+ // Process Call
+ const int frameLength = (int)(preProcCfgParams.samplingFreq * kTenMilliSecVal);
+ const int ioChannelCount = audio_channel_count_from_in_mask(preProcCfgParams.chMask);
+ const int fileChannelCount = preProcCfgParams.fileChannels;
+ const int ioFrameSize = ioChannelCount * sizeof(short);
+ const int inFrameSize = fileChannelCount * sizeof(short);
+ int frameCounter = 0;
+ while (true) {
+ std::vector<short> in(frameLength * ioChannelCount);
+ std::vector<short> out(frameLength * ioChannelCount);
+ std::vector<short> farIn(frameLength * ioChannelCount);
+ size_t samplesRead = fread(in.data(), inFrameSize, frameLength, inputFp.get());
+ if (samplesRead == 0) {
+ break;
+ }
+ if (fileChannelCount != ioChannelCount) {
+ adjust_channels(in.data(), fileChannelCount, in.data(), ioChannelCount, sizeof(short),
+ frameLength * inFrameSize);
+ if (preProcCfgParams.monoMode == 1) {
+ for (int i = 0; i < frameLength; ++i) {
+ auto* fp = &in[i * ioChannelCount];
+ std::fill(fp + 1, fp + ioChannelCount, *fp); // replicate ch 0
+ }
+ }
+ }
+ audio_buffer_t inputBuffer, outputBuffer;
+ audio_buffer_t farInBuffer{};
+ inputBuffer.frameCount = frameLength;
+ outputBuffer.frameCount = frameLength;
+ inputBuffer.s16 = in.data();
+ outputBuffer.s16 = out.data();
+
+ if (farFp != nullptr) {
+ samplesRead = fread(farIn.data(), inFrameSize, frameLength, farFp.get());
+ if (samplesRead == 0) {
+ break;
+ }
+ if (fileChannelCount != ioChannelCount) {
+ adjust_channels(farIn.data(), fileChannelCount, farIn.data(), ioChannelCount,
+ sizeof(short), frameLength * inFrameSize);
+ if (preProcCfgParams.monoMode == 1) {
+ for (int i = 0; i < frameLength; ++i) {
+ auto* fp = &farIn[i * ioChannelCount];
+ std::fill(fp + 1, fp + ioChannelCount, *fp); // replicate ch 0
+ }
+ }
+ }
+
+ farInBuffer.frameCount = frameLength;
+ farInBuffer.s16 = farIn.data();
+ }
+
+ for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+ if (effectEn[i] == 1) {
+ if (i == PREPROC_AEC) {
+ if (int status = preProcSetConfigParam(AEC_PARAM_ECHO_DELAY,
+ (uint32_t)preProcCfgParams.aecDelay,
+ effectHandle[PREPROC_AEC]);
+ status != 0) {
+ ALOGE("preProcSetConfigParam returned Error %d\n", status);
+ return EXIT_FAILURE;
+ }
+ }
+ if (int status = (*effectHandle[i])
+ ->process(effectHandle[i], &inputBuffer, &outputBuffer);
+ status != 0) {
+ ALOGE("\nError: Process i = %d returned with error %d\n", i, status);
+ return EXIT_FAILURE;
+ }
+ if (i == PREPROC_AEC) {
+ if (int status = (*effectHandle[i])
+ ->process_reverse(effectHandle[i], &farInBuffer,
+ &outputBuffer);
+ status != 0) {
+ ALOGE("\nError: Process reverse i = %d returned with error %d\n", i,
+ status);
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ }
+ if (outputFp != nullptr) {
+ if (fileChannelCount != ioChannelCount) {
+ adjust_channels(out.data(), ioChannelCount, out.data(), fileChannelCount,
+ sizeof(short), frameLength * ioFrameSize);
+ }
+ size_t samplesWritten =
+ fwrite(out.data(), inFrameSize, outputBuffer.frameCount, outputFp.get());
+ if (samplesWritten != outputBuffer.frameCount) {
+ ALOGE("\nError: Output file writing failed");
+ break;
+ }
+ }
+ frameCounter += frameLength;
+ }
+ printf("frameCounter: [%d]\n", frameCounter);
+ // Release all the effect handles created
+ for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle[i]);
+ status != 0) {
+ ALOGE("Audio Preprocessing release returned an error = %d\n", status);
+ return EXIT_FAILURE;
+ }
+ }
+ return EXIT_SUCCESS;
}
diff --git a/media/libeffects/preprocessing/tests/build_and_run_all_unit_tests.sh b/media/libeffects/preprocessing/tests/build_and_run_all_unit_tests.sh
new file mode 100755
index 0000000..35da13e
--- /dev/null
+++ b/media/libeffects/preprocessing/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,119 @@
+#!/bin/bash
+#
+# Run tests in this directory.
+#
+
+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
+
+mm -j
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount
+
+# location of test files
+testdir="/data/local/tmp/AudioPreProcessingTest"
+
+echo "========================================"
+echo "testing PreProcessing modules"
+adb shell mkdir -p $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
+adb push $OUT/testcases/snr/arm64/snr $testdir
+
+E_VAL=1
+if [ -z "$1" ]
+then
+ cmds=("adb push $OUT/testcases/AudioPreProcessingTest/arm64/AudioPreProcessingTest $testdir"
+ "adb push $OUT/testcases/AudioPreProcessingTest/arm/AudioPreProcessingTest $testdir"
+)
+elif [ "$1" == "32" ]
+then
+ cmds="adb push $OUT/testcases/AudioPreProcessingTest/arm/AudioPreProcessingTest $testdir"
+elif [ "$1" == "64" ]
+then
+ cmds="adb push $OUT/testcases/AudioPreProcessingTest/arm64/AudioPreProcessingTest $testdir"
+else
+ echo ""
+ echo "Invalid \"val\""
+ echo "Usage:"
+ echo " "$0" [val]"
+ echo " where, val can be either 32 or 64."
+ echo ""
+ echo " If val is not specified then both 32 bit and 64 bit binaries"
+ echo " are tested."
+ exit $E_VAL
+fi
+
+flags_arr=(
+ "--agc --mono"
+ "--ns --mono"
+ "--agc2 --mono"
+ "--aec --mono"
+)
+
+fs_arr=(
+ 8000
+ 11025
+ 12000
+ 16000
+ 22050
+ 24000
+ 32000
+ 44100
+ 48000
+)
+
+# run multichannel effects at different configs, saving only the mono channel
+error_count=0
+test_count=0
+for cmd in "${cmds[@]}"
+do
+ $cmd
+ for flags in "${flags_arr[@]}"
+ do
+ for fs in ${fs_arr[*]}
+ do
+ for chMask in {0..7}
+ do
+ adb shell $testdir/AudioPreProcessingTest $flags \
+ --i $testdir/sinesweepraw.raw --far $testdir/sinesweepraw.raw \
+ --output $testdir/sinesweep_$((chMask))_$((fs)).raw --ch_mask $chMask \
+ --fs $fs --fch 1
+
+ shell_ret=$?
+ if [ $shell_ret -ne 0 ]; then
+ echo "error shell_ret here is zero: $shell_ret"
+ ((++error_count))
+ fi
+
+
+ # single channel files should be identical to higher channel
+ # computation (first channel).
+ if [[ "$chMask" -gt 1 ]]
+ then
+ adb shell cmp $testdir/sinesweep_1_$((fs)).raw \
+ $testdir/sinesweep_$((chMask))_$((fs)).raw
+ fi
+
+ # cmp return EXIT_FAILURE on mismatch.
+ shell_ret=$?
+ if [ $shell_ret -ne 0 ]; then
+ echo "error: $shell_ret"
+ ((++error_count))
+ fi
+ ((++test_count))
+ done
+ done
+ done
+done
+
+adb shell rm -r $testdir
+echo "$test_count tests performed"
+echo "$error_count errors"
+exit $error_count
diff --git a/media/libeffects/preprocessing/tests/correlation.cpp b/media/libeffects/preprocessing/tests/correlation.cpp
new file mode 100644
index 0000000..eb56fc3
--- /dev/null
+++ b/media/libeffects/preprocessing/tests/correlation.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <iostream>
+#include <vector>
+
+constexpr int kMinLoopLimitValue = 1;
+constexpr int kNumPeaks = 3;
+
+/*!
+ \brief Compute the length normalized correlation of two signals
+
+ \sigX Pointer to signal 1
+ \sigY Pointer to signal 2
+ \len Length of signals
+ \enableCrossCorr Flag to be set to 1 if cross-correlation is needed
+
+ \return First value is vector of correlation peak indices
+ Second value is vector of correlation peak values
+*/
+
+static std::pair<std::vector<int>, std::vector<float>> correlation(const int16_t* sigX,
+ const int16_t* sigY, int len,
+ int16_t enableCrossCorr) {
+ float maxCorrVal = 0.f, prevCorrVal = 0.f;
+ int delay = 0, peakIndex = 0, flag = 0;
+ int loopLim = (1 == enableCrossCorr) ? len : kMinLoopLimitValue;
+ std::vector<int> peakIndexVect(kNumPeaks, 0);
+ std::vector<float> peakValueVect(kNumPeaks, 0.f);
+ for (int i = 0; i < loopLim; i++) {
+ float corrVal = 0.f;
+ for (int j = i; j < len; j++) {
+ corrVal += (float)(sigX[j] * sigY[j - i]);
+ }
+ corrVal /= len - i;
+ if (corrVal > maxCorrVal) {
+ delay = i;
+ maxCorrVal = corrVal;
+ }
+ // Correlation peaks are expected to be observed at equal intervals. The interval length is
+ // expected to match with wave period.
+ // The following block of code saves the first kNumPeaks number of peaks and the index at
+ // which they occur.
+ if (peakIndex < kNumPeaks) {
+ if (corrVal > prevCorrVal) {
+ peakIndexVect[peakIndex] = i;
+ peakValueVect[peakIndex] = corrVal;
+ flag = 0;
+ } else if (0 == flag) {
+ peakIndex++;
+ flag = 1;
+ }
+ }
+ if (peakIndex == kNumPeaks) break;
+ prevCorrVal = corrVal;
+ }
+ return {peakIndexVect, peakValueVect};
+}
+
+void printUsage() {
+ printf("\nUsage: ");
+ printf("\n correlation <firstFile> <secondFile> [enableCrossCorr]\n");
+ printf("\nwhere, \n <firstFile> is the first file name");
+ printf("\n <secondFile> is the second file name");
+ printf("\n [enableCrossCorr] is flag to set for cross-correlation (Default 1)\n\n");
+}
+
+int main(int argc, const char* argv[]) {
+ if (argc < 3) {
+ printUsage();
+ return EXIT_FAILURE;
+ }
+
+ std::unique_ptr<FILE, decltype(&fclose)> fInput1(fopen(argv[1], "rb"), &fclose);
+ if (fInput1.get() == NULL) {
+ printf("\nError: missing file %s\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+ std::unique_ptr<FILE, decltype(&fclose)> fInput2(fopen(argv[2], "rb"), &fclose);
+ if (fInput2.get() == NULL) {
+ printf("\nError: missing file %s\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+ int16_t enableCrossCorr = (4 == argc) ? atoi(argv[3]) : 1;
+
+ fseek(fInput1.get(), 0L, SEEK_END);
+ unsigned int fileSize1 = ftell(fInput1.get());
+ rewind(fInput1.get());
+ fseek(fInput2.get(), 0L, SEEK_END);
+ unsigned int fileSize2 = ftell(fInput2.get());
+ rewind(fInput2.get());
+ if (fileSize1 != fileSize2) {
+ printf("\nError: File sizes different\n");
+ return EXIT_FAILURE;
+ }
+
+ size_t numFrames = fileSize1 / sizeof(int16_t);
+ std::unique_ptr<int16_t[]> inBuffer1(new int16_t[numFrames]());
+ std::unique_ptr<int16_t[]> inBuffer2(new int16_t[numFrames]());
+
+ if (numFrames != fread(inBuffer1.get(), sizeof(int16_t), numFrames, fInput1.get())) {
+ printf("\nError: Unable to read %zu samples from file %s\n", numFrames, argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ if (numFrames != fread(inBuffer2.get(), sizeof(int16_t), numFrames, fInput2.get())) {
+ printf("\nError: Unable to read %zu samples from file %s\n", numFrames, argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ auto pairAutoCorr1 = correlation(inBuffer1.get(), inBuffer1.get(), numFrames, enableCrossCorr);
+ auto pairAutoCorr2 = correlation(inBuffer2.get(), inBuffer2.get(), numFrames, enableCrossCorr);
+
+ // Following code block checks pitch period difference between two input signals. They must
+ // match as AGC applies only gain, no frequency related computation is done.
+ bool pitchMatch = false;
+ for (unsigned i = 0; i < pairAutoCorr1.first.size() - 1; i++) {
+ if (pairAutoCorr1.first[i + 1] - pairAutoCorr1.first[i] !=
+ pairAutoCorr2.first[i + 1] - pairAutoCorr2.first[i]) {
+ pitchMatch = false;
+ break;
+ }
+ pitchMatch = true;
+ }
+ if (pitchMatch) {
+ printf("Auto-correlation : Pitch matched\n");
+ } else {
+ printf("Auto-correlation : Pitch mismatch\n");
+ return EXIT_FAILURE;
+ }
+
+ if (enableCrossCorr) {
+ auto pairCrossCorr =
+ correlation(inBuffer1.get(), inBuffer2.get(), numFrames, enableCrossCorr);
+
+ // Since AGC applies only gain, the pitch information obtained from cross correlation data
+ // of input and output is expected to be same as the input signal's pitch information.
+ pitchMatch = false;
+ for (unsigned i = 0; i < pairCrossCorr.first.size() - 1; i++) {
+ if (pairAutoCorr1.first[i + 1] - pairAutoCorr1.first[i] !=
+ pairCrossCorr.first[i + 1] - pairCrossCorr.first[i]) {
+ pitchMatch = false;
+ break;
+ }
+ pitchMatch = true;
+ }
+ if (pitchMatch) {
+ printf("Cross-correlation : Pitch matched for AGC\n");
+ if (pairAutoCorr1.second[0]) {
+ printf("Expected gain : (maxCrossCorr / maxAutoCorr1) = %f\n",
+ pairCrossCorr.second[0] / pairAutoCorr1.second[0]);
+ }
+ } else {
+ printf("Cross-correlation : Pitch mismatch\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/media/libeffects/proxy/Android.bp b/media/libeffects/proxy/Android.bp
index c6abb9e..6256eda 100644
--- a/media/libeffects/proxy/Android.bp
+++ b/media/libeffects/proxy/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libeffectproxy",
relative_install_path: "soundfx",
diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp
index c010d68..be9f8c0 100644
--- a/media/libeffects/proxy/EffectProxy.cpp
+++ b/media/libeffects/proxy/EffectProxy.cpp
@@ -116,6 +116,16 @@
pContext->sube[SUB_FX_OFFLOAD] = sube[1];
pContext->desc[SUB_FX_OFFLOAD] = desc[1];
pContext->aeli[SUB_FX_OFFLOAD] = aeli[1];
+ } else {
+ ALOGE("Both effects have (or don't have) EFFECT_FLAG_HW_ACC_TUNNEL flag");
+ delete[] sube;
+ delete[] desc;
+ delete[] aeli;
+ delete[] pContext->sube;
+ delete[] pContext->desc;
+ delete[] pContext->aeli;
+ delete pContext;
+ return -EINVAL;
}
delete[] desc;
delete[] aeli;
diff --git a/media/libeffects/res/raw/sinesweepraw.raw b/media/libeffects/res/raw/sinesweepraw.raw
new file mode 100644
index 0000000..c0d48ce
--- /dev/null
+++ b/media/libeffects/res/raw/sinesweepraw.raw
Binary files differ
diff --git a/media/libeffects/testlibs/EffectsMath.h b/media/libeffects/testlibs/EffectsMath.h
index 2a44399..dd43b49 100644
--- a/media/libeffects/testlibs/EffectsMath.h
+++ b/media/libeffects/testlibs/EffectsMath.h
@@ -251,22 +251,6 @@
*/
/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */
-#if 0
-#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */
-
-#define DOUBLE_LFO_GAIN_TO_CENTS (double) \
- ( \
- (DOUBLE_LOG2_10) * \
- 1200.0 / \
- 20.0 \
- )
-
-#define LFO_GAIN_TO_CENTS (int32_t) \
- ( \
- DOUBLE_LFO_GAIN_TO_CENTS * \
- (0x1L << NUM_EG1_FRAC_BITS) \
- )
-#endif
#define LFO_GAIN_TO_CENTS (int32_t) (1671981156L >> (23 - NUM_EG1_FRAC_BITS))
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index 35e2f3d..68c7cf2 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -18,6 +18,9 @@
LOCAL_MODULE_RELATIVE_PATH := soundfx
LOCAL_MODULE:= libvisualizer
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
LOCAL_C_INCLUDES := \
$(call include-path-for, audio-effects) \
diff --git a/media/libheif/Android.bp b/media/libheif/Android.bp
index 7d5a4eb..6a3427e 100644
--- a/media/libheif/Android.bp
+++ b/media/libheif/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libheif",
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1caee04..48b5391 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_libmedia_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libmedia_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libmedia_headers",
vendor_available: true,
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 5c6b981..64ba977 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -268,7 +268,7 @@
ucnv_convertEx(mUtf8Conv, conv, &target, target + targetLength,
&source, source + strlen(source),
- NULL, NULL, NULL, NULL, TRUE, TRUE, &status);
+ NULL, NULL, NULL, NULL, true, true, &status);
if (U_FAILURE(status)) {
ALOGE("ucnv_convertEx failed: %d", status);
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 39caf53..7ed76d8 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -38,7 +38,8 @@
FLAGS,
SETMEDIACAS,
NAME,
- GETMETRICS
+ GETMETRICS,
+ SETENTRYPOINT
};
class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -142,6 +143,13 @@
}
return nm;
}
+
+ virtual status_t setEntryPoint(EntryPoint entryPoint) {
+ Parcel data, reply;
+ data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(entryPoint));
+ return remote()->transact(SETENTRYPOINT, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -232,6 +240,16 @@
reply->writeString8(nm);
return NO_ERROR;
}
+ case SETENTRYPOINT: {
+ ALOGV("setEntryPoint");
+ CHECK_INTERFACE(IMediaExtractor, data, reply);
+ int32_t entryPoint;
+ status_t err = data.readInt32(&entryPoint);
+ if (err == OK) {
+ setEntryPoint(EntryPoint(entryPoint));
+ }
+ return err;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 4c76fd2..8a4b17c 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -40,6 +40,7 @@
SET_DATA_SOURCE_FD,
SET_DATA_SOURCE_STREAM,
SET_DATA_SOURCE_CALLBACK,
+ SET_DATA_SOURCE_RTP,
SET_BUFFERING_SETTINGS,
GET_BUFFERING_SETTINGS,
PREPARE_ASYNC,
@@ -161,6 +162,15 @@
return reply.readInt32();
}
+ status_t setDataSource(const String8& rtpParams) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeString8(rtpParams);
+ remote()->transact(SET_DATA_SOURCE_RTP, data, &reply);
+
+ return reply.readInt32();
+ }
+
// pass the buffered IGraphicBufferProducer to the media player service
status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer)
{
@@ -685,6 +695,12 @@
}
return NO_ERROR;
}
+ case SET_DATA_SOURCE_RTP: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ String8 rtpParams = data.readString8();
+ reply->writeInt32(setDataSource(rtpParams));
+ return NO_ERROR;
+ }
case SET_VIDEO_SURFACETEXTURE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<IGraphicBufferProducer> bufferProducer =
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index bd18a40..11005c6 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -62,11 +62,13 @@
}
virtual sp<IMediaPlayer> create(
- const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
+ const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId,
+ const std::string opPackageName) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(client));
data.writeInt32(audioSessionId);
+ data.writeCString(opPackageName.c_str());
remote()->transact(CREATE, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
@@ -127,7 +129,12 @@
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
audio_session_t audioSessionId = (audio_session_t) data.readInt32();
- sp<IMediaPlayer> player = create(client, audioSessionId);
+ const char* opPackageName = data.readCString();
+ if (opPackageName == nullptr) {
+ return FAILED_TRANSACTION;
+ }
+ std::string opPackageNameStr(opPackageName);
+ sp<IMediaPlayer> player = create(client, audioSessionId, opPackageNameStr);
reply->writeStrongBinder(IInterface::asBinder(player));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index ac86f72..154988d 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -66,6 +66,7 @@
ENABLE_AUDIO_DEVICE_CALLBACK,
GET_ACTIVE_MICROPHONES,
GET_PORT_ID,
+ GET_RTP_DATA_USAGE,
SET_PREFERRED_MICROPHONE_DIRECTION,
SET_PREFERRED_MICROPHONE_FIELD_DIMENSION,
SET_PRIVACY_SENSITIVE,
@@ -476,6 +477,23 @@
*portId = (audio_port_handle_t)reply.readInt32();
return NO_ERROR;
}
+
+ status_t getRtpDataUsage(uint64_t *bytes)
+ {
+ ALOGV("getRtpDataUsage");
+ if (bytes == nullptr) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_RTP_DATA_USAGE, data, &reply);
+ if (status != OK
+ || (status = (status_t)reply.readInt32()) != NO_ERROR) {
+ *bytes = 0;
+ return status;
+ }
+ return reply.readUint64(bytes);
+ }
};
IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
@@ -759,6 +777,17 @@
}
return NO_ERROR;
}
+ case GET_RTP_DATA_USAGE: {
+ ALOGV("GET_RTP_DATA_USAGE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ uint64_t bytes;
+ status_t status = getRtpDataUsage(&bytes);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeUint64(bytes);
+ }
+ return NO_ERROR;
+ }
case SET_PREFERRED_MICROPHONE_DIRECTION: {
ALOGV("SET_PREFERRED_MICROPHONE_DIRECTION");
CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index da272e3..f682b6e 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -21,6 +21,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <algorithm>
#include <media/MidiIoWrapper.h>
#include <media/MediaExtractorPluginApi.h>
@@ -33,6 +34,8 @@
}
namespace android {
+int MidiIoWrapper::sCacheBufferSize = 0;
+Mutex MidiIoWrapper::mCacheLock;
MidiIoWrapper::MidiIoWrapper(const char *path) {
ALOGV("MidiIoWrapper(%s)", path);
@@ -40,6 +43,8 @@
mBase = 0;
mLength = lseek(mFd, 0, SEEK_END);
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::MidiIoWrapper(int fd, off64_t offset, int64_t size) {
@@ -48,6 +53,8 @@
mBase = offset;
mLength = size;
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
class MidiIoWrapper::DataSourceUnwrapper {
@@ -97,6 +104,8 @@
} else {
mLength = 0;
}
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::~MidiIoWrapper() {
@@ -105,11 +114,80 @@
close(mFd);
}
delete mDataSource;
+
+ if (NULL != mCacheBuffer) {
+ delete [] mCacheBuffer;
+ mCacheBuffer = NULL;
+ {
+ Mutex::Autolock _l(mCacheLock);
+ sCacheBufferSize -= mLength;
+ }
+ }
}
int MidiIoWrapper::readAt(void *buffer, int offset, int size) {
ALOGV("readAt(%p, %d, %d)", buffer, offset, size);
+ if (offset < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (offset + size > mLength) {
+ size = mLength - offset;
+ }
+
+ if (mCacheBuffer == NULL) {
+ Mutex::Autolock _l(mCacheLock);
+ if (sCacheBufferSize + mLength <= kTotalCacheSize) {
+ mCacheBuffer = new (std::nothrow) unsigned char[mLength];
+ if (NULL != mCacheBuffer) {
+ sCacheBufferSize += mLength;
+ ALOGV("sCacheBufferSize : %d", sCacheBufferSize);
+ } else {
+ ALOGE("failed to allocate memory for mCacheBuffer");
+ }
+ } else {
+ ALOGV("not allocate memory for mCacheBuffer");
+ }
+ }
+
+ if (mCacheBuffer != NULL) {
+ if (mCacheBufRangeLength > 0 && mCacheBufRangeLength >= (offset + size)) {
+ /* Use buffered data */
+ memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+ return size;
+ } else {
+ /* Buffer new data */
+ int64_t beyondCacheBufRangeLength = (offset + size) - mCacheBufRangeLength;
+ int64_t numRequiredBytesToCache =
+ std::max((int64_t)kSingleCacheSize, beyondCacheBufRangeLength);
+ int64_t availableReadLength = mLength - mCacheBufRangeLength;
+ int64_t readSize = std::min(availableReadLength, numRequiredBytesToCache);
+ int actualNumBytesRead =
+ unbufferedReadAt(mCacheBuffer + mCacheBufRangeLength,
+ mCacheBufRangeLength, readSize);
+ if(actualNumBytesRead > 0) {
+ mCacheBufRangeLength += actualNumBytesRead;
+ if (offset >= mCacheBufRangeLength) {
+ return 0;
+ } else if (offset + size >= mCacheBufRangeLength) {
+ memcpy(buffer, (void*)(mCacheBuffer + offset), mCacheBufRangeLength - offset);
+ return mCacheBufRangeLength - offset;
+ } else {
+ memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+ return size;
+ }
+ } else {
+ return actualNumBytesRead;
+ }
+ }
+ } else {
+ return unbufferedReadAt(buffer, offset, size);
+ }
+}
+
+int MidiIoWrapper::unbufferedReadAt(void *buffer, int offset, int size) {
+ ALOGV("unbufferedReadAt(%p, %d, %d)", buffer, offset, size);
if (mDataSource != NULL) {
return mDataSource->readAt(offset, buffer, size);
}
diff --git a/media/libmedia/include/android/IMediaExtractor.h b/media/libmedia/include/android/IMediaExtractor.h
index 3e035ad..f9cafde 100644
--- a/media/libmedia/include/android/IMediaExtractor.h
+++ b/media/libmedia/include/android/IMediaExtractor.h
@@ -63,6 +63,15 @@
virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
virtual String8 name() = 0;
+
+ enum class EntryPoint {
+ SDK = 1,
+ NDK_WITH_JVM = 2,
+ NDK_NO_JVM = 3,
+ OTHER = 4,
+ };
+
+ virtual status_t setEntryPoint(EntryPoint entryPoint) = 0;
};
diff --git a/media/libmedia/include/media/IMediaPlayer.h b/media/libmedia/include/media/IMediaPlayer.h
index a4c0ec6..3548a1e 100644
--- a/media/libmedia/include/media/IMediaPlayer.h
+++ b/media/libmedia/include/media/IMediaPlayer.h
@@ -59,6 +59,7 @@
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setDataSource(const sp<IStreamSource>& source) = 0;
virtual status_t setDataSource(const sp<IDataSource>& source) = 0;
+ virtual status_t setDataSource(const String8& rtpParams) = 0;
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
virtual status_t getBufferingSettings(
diff --git a/media/libmedia/include/media/IMediaPlayerService.h b/media/libmedia/include/media/IMediaPlayerService.h
index f2e2060..a4207eb 100644
--- a/media/libmedia/include/media/IMediaPlayerService.h
+++ b/media/libmedia/include/media/IMediaPlayerService.h
@@ -28,6 +28,8 @@
#include <media/IMediaPlayerClient.h>
#include <media/IMediaMetadataRetriever.h>
+#include <string>
+
namespace android {
class IMediaPlayer;
@@ -47,7 +49,8 @@
virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) = 0;
virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
- audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) = 0;
+ audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE,
+ const std::string opPackage = "") = 0;
virtual sp<IMediaCodecList> getCodecList() const = 0;
// Connects to a remote display.
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 651bd5e..6e69782 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -78,6 +78,7 @@
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) = 0;
+ virtual status_t getRtpDataUsage(uint64_t *bytes) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 8493f64..d9a7efb 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -77,6 +77,7 @@
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) const = 0;
+ virtual status_t getRtpDataUsage(uint64_t *bytes) = 0;
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 0cdd4ad..5fa745c 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -18,6 +18,7 @@
#define MIDI_IO_WRAPPER_H_
#include <libsonivox/eas_types.h>
+#include <utils/Mutex.h>
namespace android {
@@ -32,17 +33,27 @@
~MidiIoWrapper();
int readAt(void *buffer, int offset, int size);
+ int unbufferedReadAt(void *buffer, int offset, int size);
int size();
EAS_FILE_LOCATOR getLocator();
private:
+ enum {
+ kTotalCacheSize = 1024 * 1024 + 512 * 1024,
+ kSingleCacheSize = 65536,
+ };
+
int mFd;
off64_t mBase;
int64_t mLength;
class DataSourceUnwrapper;
DataSourceUnwrapper *mDataSource;
EAS_FILE mEasFile;
+ unsigned char *mCacheBuffer;
+ int64_t mCacheBufRangeLength;
+ static int sCacheBufferSize;
+ static Mutex mCacheLock;
};
diff --git a/media/libmedia/include/media/mediaplayer.h b/media/libmedia/include/media/mediaplayer.h
index 2335c5a..71c0bc5 100644
--- a/media/libmedia/include/media/mediaplayer.h
+++ b/media/libmedia/include/media/mediaplayer.h
@@ -33,6 +33,8 @@
#include <utils/KeyedVector.h>
#include <utils/String8.h>
+#include <string>
+
struct ANativeWindow;
namespace android {
@@ -60,6 +62,7 @@
MEDIA_META_DATA = 202,
MEDIA_DRM_INFO = 210,
MEDIA_TIME_DISCONTINUITY = 211,
+ MEDIA_IMS_RX_NOTICE = 300,
MEDIA_AUDIO_ROUTING_CHANGED = 10000,
};
@@ -177,7 +180,10 @@
KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300, // set only
// Set a Parcel containing the value of a parcelled Java AudioAttribute instance
- KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400 // set only
+ KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400, // set only
+
+ // Set a Parcel containing the values of RTP attribute
+ KEY_PARAMETER_RTP_ATTRIBUTES = 2000 // set only
};
// Keep INVOKE_ID_* in sync with MediaPlayer.java.
@@ -205,7 +211,7 @@
public virtual IMediaDeathNotifier
{
public:
- MediaPlayer();
+ MediaPlayer(const std::string opPackageName = "");
~MediaPlayer();
void died();
void disconnect();
@@ -217,6 +223,7 @@
status_t setDataSource(int fd, int64_t offset, int64_t length);
status_t setDataSource(const sp<IDataSource> &source);
+ status_t setDataSource(const String8& rtpParams);
status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer);
status_t setListener(const sp<MediaPlayerListener>& listener);
@@ -308,6 +315,7 @@
float mSendLevel;
struct sockaddr_in mRetransmitEndpoint;
bool mRetransmitEndpointValid;
+ const std::string mOpPackageName;
};
}; // namespace android
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index 6e2d94d..84c92f6 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -270,6 +270,7 @@
status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const;
+ status_t getRtpDataUsage(uint64_t *bytes);
private:
void doCleanUp();
@@ -291,6 +292,8 @@
bool mIsOutputFileSet;
Mutex mLock;
Mutex mNotifyLock;
+
+ output_format mOutputFormat;
};
}; // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 1fadc94..1554920 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -41,7 +41,7 @@
using media::VolumeShaper;
-MediaPlayer::MediaPlayer()
+MediaPlayer::MediaPlayer(const std::string opPackageName) : mOpPackageName(opPackageName)
{
ALOGV("constructor");
mListener = NULL;
@@ -152,7 +152,7 @@
if (url != NULL) {
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+ sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(httpService, url, headers))) {
player.clear();
@@ -169,7 +169,7 @@
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+ sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(fd, offset, length))) {
player.clear();
@@ -185,7 +185,7 @@
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+ sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(source))) {
player.clear();
@@ -195,6 +195,22 @@
return err;
}
+status_t MediaPlayer::setDataSource(const String8& rtpParams)
+{
+ ALOGV("setDataSource(rtpParams)");
+ status_t err = UNKNOWN_ERROR;
+ const sp<IMediaPlayerService> service(getMediaPlayerService());
+ if (service != 0) {
+ sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+ if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
+ (NO_ERROR != player->setDataSource(rtpParams))) {
+ player.clear();
+ }
+ err = attachNewPlayer(player);
+ }
+ return err;
+}
+
status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
{
Mutex::Autolock _l(mLock);
@@ -943,6 +959,9 @@
case MEDIA_META_DATA:
ALOGV("Received timed metadata message");
break;
+ case MEDIA_IMS_RX_NOTICE:
+ ALOGV("Received IMS Rx notice message");
+ break;
default:
ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
break;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 70655d5..e3cd9d8 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -244,6 +244,7 @@
mCurrentState = MEDIA_RECORDER_ERROR;
return ret;
}
+ mOutputFormat = (output_format)of;
mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
return ret;
}
@@ -479,6 +480,13 @@
(MEDIA_RECORDER_PREPARED |
MEDIA_RECORDER_RECORDING |
MEDIA_RECORDER_ERROR));
+
+ // For RTP video, parameter should be set dynamically.
+ if (isInvalidState) {
+ if (mCurrentState == MEDIA_RECORDER_RECORDING &&
+ mOutputFormat == OUTPUT_FORMAT_RTP_AVP)
+ isInvalidState = false;
+ }
if (isInvalidState) {
ALOGE("setParameters is called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
@@ -737,6 +745,7 @@
mIsAudioEncoderSet = false;
mIsVideoEncoderSet = false;
mIsOutputFileSet = false;
+ mOutputFormat = OUTPUT_FORMAT_DEFAULT;
}
// Release should be OK in any state
@@ -904,4 +913,14 @@
return mMediaRecorder->getPortId(portId);
}
+status_t MediaRecorder::getRtpDataUsage(uint64_t *bytes)
+{
+ ALOGV("getRtpDataUsage");
+
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ return mMediaRecorder->getRtpDataUsage(bytes);
+}
} // namespace android
diff --git a/media/libmedia/tests/codeclist/Android.bp b/media/libmedia/tests/codeclist/Android.bp
index b9c1bdb..89dddc4 100644
--- a/media/libmedia/tests/codeclist/Android.bp
+++ b/media/libmedia/tests/codeclist/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libmedia_license"],
+}
+
cc_test {
name: "CodecListTest",
gtest: true,
diff --git a/media/libmedia/tests/fuzzer/Android.bp b/media/libmedia/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..c03b5b1
--- /dev/null
+++ b/media/libmedia/tests/fuzzer/Android.bp
@@ -0,0 +1,19 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libmedia_license"],
+}
+
+cc_fuzz {
+ name: "libmedia_metadata_fuzzer",
+ srcs: [
+ "libmedia_metadata_fuzzer.cpp",
+ ],
+ shared_libs: [
+ "libmedia",
+ "libbinder",
+ ],
+}
diff --git a/media/libmedia/tests/fuzzer/libmedia_metadata_fuzzer.cpp b/media/libmedia/tests/fuzzer/libmedia_metadata_fuzzer.cpp
new file mode 100644
index 0000000..058e4e5
--- /dev/null
+++ b/media/libmedia/tests/fuzzer/libmedia_metadata_fuzzer.cpp
@@ -0,0 +1,52 @@
+//This program fuzzes Metadata.cpp
+
+#include <stddef.h>
+#include <stdint.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/Metadata.h>
+#include <binder/Parcel.h>
+
+using namespace android;
+using namespace media;
+
+static const float want_prob = 0.5;
+
+bool bytesRemain(FuzzedDataProvider *fdp);
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ Parcel p;
+ Metadata md = Metadata(&p);
+
+ md.appendHeader();
+ while (bytesRemain(&fdp)) {
+
+ float got_prob = fdp.ConsumeProbability<float>();
+ if (!bytesRemain(&fdp)) {
+ break;
+ }
+
+ if (got_prob < want_prob) {
+ int32_t key_bool = fdp.ConsumeIntegral<int32_t>();
+ if (!bytesRemain(&fdp)) {
+ break;
+ }
+ bool val_bool = fdp.ConsumeBool();
+ md.appendBool(key_bool, val_bool);
+ } else {
+ int32_t key_int32 = fdp.ConsumeIntegral<int32_t>();
+ if (!bytesRemain(&fdp)) {
+ break;
+ }
+ bool val_int32 = fdp.ConsumeIntegral<int32_t>();
+ md.appendInt32(key_int32, val_int32);
+ }
+ md.updateLength();
+ }
+ md.resetParcel();
+ return 0;
+}
+
+bool bytesRemain(FuzzedDataProvider *fdp){
+ return fdp -> remaining_bytes() > 0;
+}
\ No newline at end of file
diff --git a/media/libmedia/xsd/Android.bp b/media/libmedia/xsd/Android.bp
index 1635f70..36e2808 100644
--- a/media/libmedia/xsd/Android.bp
+++ b/media/libmedia/xsd/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libmedia_license"],
+}
+
xsd_config {
name: "media_profiles",
srcs: ["media_profiles.xsd"],
diff --git a/media/libmedia/xsd/vts/Android.bp b/media/libmedia/xsd/vts/Android.bp
index 598e41b..83ab977 100644
--- a/media/libmedia/xsd/vts/Android.bp
+++ b/media/libmedia/xsd/vts/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libmedia_license"],
+}
+
cc_test {
name: "vts_mediaProfiles_validate_test",
srcs: [
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index b46c98a..64ec91b 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libmedia_helper_headers",
vendor_available: true,
@@ -18,7 +27,10 @@
enabled: true,
},
double_loadable: true,
- srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
+ srcs: [
+ "AudioParameter.cpp",
+ "TypeConverter.cpp",
+ ],
cflags: [
"-Werror",
"-Wextra",
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index fc8306c..73c1e41 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -57,6 +57,10 @@
// AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES;
// const char * const AudioParameter::keyDeviceSupportedEncapsulationMetadataTypes =
// AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES;
+// const char * const AudioParameter::keyAdditionalOutputDeviceDelay =
+// AUDIO_PARAMETER_DEVICE_ADDITIONAL_OUTPUT_DELAY;
+// const char * const AudioParameter::keyMaxAdditionalOutputDeviceDelay =
+// AUDIO_PARAMETER_DEVICE_MAX_ADDITIONAL_OUTPUT_DELAY;
AudioParameter::AudioParameter(const String8& keyValuePairs)
{
diff --git a/media/libmediahelper/TEST_MAPPING b/media/libmediahelper/TEST_MAPPING
new file mode 100644
index 0000000..f9594bd
--- /dev/null
+++ b/media/libmediahelper/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libmedia_helper_tests"
+ }
+ ]
+}
diff --git a/media/libmediahelper/TypeConverter.cpp b/media/libmediahelper/TypeConverter.cpp
index 705959a..d3a517f 100644
--- a/media/libmediahelper/TypeConverter.cpp
+++ b/media/libmediahelper/TypeConverter.cpp
@@ -18,310 +18,9 @@
namespace android {
-#define MAKE_STRING_FROM_ENUM(string) { #string, string }
+#define MAKE_STRING_FROM_ENUM(enumval) { #enumval, enumval }
#define TERMINATOR { .literal = nullptr }
-template <>
-const OutputDeviceConverter::Table OutputDeviceConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_NONE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_LINE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPDIF),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_PROXY),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HEARING_AID),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ECHO_CANCELLER),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLE_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLE_SPEAKER),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DEFAULT),
- // STUB must be after DEFAULT, so the latter is picked up by toString first.
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_STUB),
- TERMINATOR
-};
-
-template <>
-const InputDeviceConverter::Table InputDeviceConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_NONE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_COMMUNICATION),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI_ARC),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_USB),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ECHO_REFERENCE),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLE_HEADSET),
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
- // STUB must be after DEFAULT, so the latter is picked up by toString first.
- MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
- TERMINATOR
-};
-
-
-template <>
-const OutputFlagConverter::Table OutputFlagConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NONE),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_FAST),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_TTS),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_RAW),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
- MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
- TERMINATOR
-};
-
-
-template <>
-const InputFlagConverter::Table InputFlagConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_NONE),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_FAST),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_RAW),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_SYNC),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_MMAP_NOIRQ),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_VOIP_TX),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_AV_SYNC),
- MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_DIRECT),
- TERMINATOR
-};
-
-
-template <>
-const FormatConverter::Table FormatConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_16_BIT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_BIT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_32_BIT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_FLOAT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP3),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_NB),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_WB),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_MAIN),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SSR),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LTP),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V1),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ERLC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V2),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ELD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_XHE),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_MAIN),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_SSR),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LTP),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_SCALABLE),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_ERLC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_ELD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_XHE),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_VORBIS),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V1),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V2),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_OPUS),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC3),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS_HD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_IEC61937),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCB),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCWB),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCNW),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADIF),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_WMA),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_WMA_PRO),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP2),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_QCELP),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DSD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_FLAC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_ALAC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APE),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_SBC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_HD),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC4),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LDAC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3_JOC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_1_0),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_2_0),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_2_1),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_LC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V1),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V2),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_CELT),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_ADAPTIVE),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC_LL),
- MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_TWSP),
- TERMINATOR
-};
-
-
-template <>
-const OutputChannelConverter::Table OutputChannelConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT0POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT1POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_TRI),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_TRI_BACK),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT1),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT0POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT1POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD_BACK),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_PENTA),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1_BACK),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1POINT4),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT4),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_A),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_A),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_AB),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB),
- TERMINATOR
-};
-
-
-template <>
-const InputChannelConverter::Table InputChannelConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_MONO),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_STEREO),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_6),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_2POINT0POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_2POINT1POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_3POINT0POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_3POINT1POINT2),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_5POINT1),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO),
- MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_CALL_MONO),
- TERMINATOR
-};
-
-template <>
-const ChannelIndexConverter::Table ChannelIndexConverter::mTable[] = {
- {"AUDIO_CHANNEL_INDEX_MASK_1", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_1)},
- {"AUDIO_CHANNEL_INDEX_MASK_2", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_2)},
- {"AUDIO_CHANNEL_INDEX_MASK_3", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_3)},
- {"AUDIO_CHANNEL_INDEX_MASK_4", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_4)},
- {"AUDIO_CHANNEL_INDEX_MASK_5", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_5)},
- {"AUDIO_CHANNEL_INDEX_MASK_6", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_6)},
- {"AUDIO_CHANNEL_INDEX_MASK_7", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_7)},
- {"AUDIO_CHANNEL_INDEX_MASK_8", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_8)},
- TERMINATOR
-};
-
-
-template <>
-const GainModeConverter::Table GainModeConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_JOINT),
- MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_CHANNELS),
- MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_RAMP),
- TERMINATOR
-};
-
-
-template <>
-const StreamTypeConverter::Table StreamTypeConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DEFAULT),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_VOICE_CALL),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_SYSTEM),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_RING),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_MUSIC),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ALARM),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_NOTIFICATION),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_BLUETOOTH_SCO ),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ENFORCED_AUDIBLE),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DTMF),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_TTS),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ACCESSIBILITY),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ASSISTANT),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_REROUTING),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_PATCH),
- MAKE_STRING_FROM_ENUM(AUDIO_STREAM_CALL_ASSISTANT),
- TERMINATOR
-};
-
template<>
const AudioModeConverter::Table AudioModeConverter::mTable[] = {
MAKE_STRING_FROM_ENUM(AUDIO_MODE_INVALID),
@@ -334,62 +33,6 @@
TERMINATOR
};
-template<>
-const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_UNKNOWN),
- MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_SPEECH),
- MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_MUSIC),
- MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_MOVIE),
- MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_SONIFICATION),
- TERMINATOR
-};
-
-template <>
-const UsageTypeConverter::Table UsageTypeConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_UNKNOWN),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_MEDIA),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VOICE_COMMUNICATION),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ALARM),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_EVENT),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_SONIFICATION),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_GAME),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VIRTUAL_SOURCE),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANT),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_CALL_ASSISTANT),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_EMERGENCY),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_SAFETY),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VEHICLE_STATUS),
- MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ANNOUNCEMENT),
- TERMINATOR
-};
-
-template <>
-const SourceTypeConverter::Table SourceTypeConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_DEFAULT),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_MIC),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_UPLINK),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_DOWNLINK),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_CALL),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_CAMCORDER),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_RECOGNITION),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_COMMUNICATION),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_REMOTE_SUBMIX),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_UNPROCESSED),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_PERFORMANCE),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_ECHO_REFERENCE),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_FM_TUNER),
- MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_HOTWORD),
- TERMINATOR
-};
-
template <>
const AudioFlagConverter::Table AudioFlagConverter::mTable[] = {
MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NONE),
@@ -412,6 +55,7 @@
template class TypeConverter<OutputDeviceTraits>;
template class TypeConverter<InputDeviceTraits>;
+template class TypeConverter<DeviceTraits>;
template class TypeConverter<OutputFlagTraits>;
template class TypeConverter<InputFlagTraits>;
template class TypeConverter<FormatTraits>;
@@ -425,11 +69,6 @@
template class TypeConverter<SourceTraits>;
template class TypeConverter<AudioFlagTraits>;
-bool deviceFromString(const std::string& literalDevice, audio_devices_t& device) {
- return InputDeviceConverter::fromString(literalDevice, device) ||
- OutputDeviceConverter::fromString(literalDevice, device);
-}
-
SampleRateTraits::Collection samplingRatesFromString(
const std::string &samplingRates, const char *del)
{
@@ -449,21 +88,20 @@
audio_format_t formatFromString(const std::string &literalFormat, audio_format_t defaultFormat)
{
audio_format_t format;
- if (literalFormat.empty()) {
- return defaultFormat;
+ if (!literalFormat.empty() && FormatConverter::fromString(literalFormat, format)) {
+ return format;
}
- FormatConverter::fromString(literalFormat, format);
- return format;
+ return defaultFormat;
}
audio_channel_mask_t channelMaskFromString(const std::string &literalChannels)
{
audio_channel_mask_t channels;
- if (!OutputChannelConverter::fromString(literalChannels, channels) &&
- !InputChannelConverter::fromString(literalChannels, channels)) {
- return AUDIO_CHANNEL_INVALID;
+ if (!literalChannels.empty() &&
+ audio_channel_mask_from_string(literalChannels.c_str(), &channels)) {
+ return channels;
}
- return channels;
+ return AUDIO_CHANNEL_INVALID;
}
ChannelTraits::Collection channelMasksFromString(
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 66d8dfb..b72d0d5 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -104,6 +104,9 @@
// static const char * const keyDeviceSupportedEncapsulationModes;
// static const char * const keyDeviceSupportedEncapsulationMetadataTypes;
+ // static const char * const keyAdditionalOutputDeviceDelay;
+ // static const char * const keyMaxAdditionalOutputDeviceDelay;
+
String8 toString() const { return toStringImpl(true); }
String8 keysToString() const { return toStringImpl(false); }
diff --git a/media/libmediahelper/include/media/TypeConverter.h b/media/libmediahelper/include/media/TypeConverter.h
index 011498a..42ccb5f 100644
--- a/media/libmediahelper/include/media/TypeConverter.h
+++ b/media/libmediahelper/include/media/TypeConverter.h
@@ -24,8 +24,6 @@
#include <system/audio.h>
#include <utils/Log.h>
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
#include <media/AudioParameter.h>
#include "convert.h"
@@ -43,16 +41,6 @@
}
};
template <typename T>
-struct SortedVectorTraits
-{
- typedef T Type;
- typedef SortedVector<Type> Collection;
- static void add(Collection &collection, Type value)
- {
- collection.add(value);
- }
-};
-template <typename T>
struct SetTraits
{
typedef T Type;
@@ -108,13 +96,20 @@
typename Traits::Collection &collection,
const char *del = AudioParameter::valueListSeparator);
- static uint32_t maskFromString(
+ static typename Traits::Type maskFromString(
const std::string &str, const char *del = AudioParameter::valueListSeparator);
static void maskToString(
- uint32_t mask, std::string &str, const char *del = AudioParameter::valueListSeparator);
+ typename Traits::Type mask, std::string &str,
+ const char *del = AudioParameter::valueListSeparator);
protected:
+ // Default implementations use mTable for to/from string conversions
+ // of each individual enum value.
+ // These functions may be specialized to use external converters instead.
+ static bool toStringImpl(const typename Traits::Type &value, std::string &str);
+ static bool fromStringImpl(const std::string &str, typename Traits::Type &result);
+
struct Table {
const char *literal;
typename Traits::Type value;
@@ -124,26 +119,22 @@
};
template <class Traits>
-inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
-{
+inline bool TypeConverter<Traits>::toStringImpl(
+ const typename Traits::Type &value, std::string &str) {
for (size_t i = 0; mTable[i].literal; i++) {
if (mTable[i].value == value) {
str = mTable[i].literal;
return true;
}
}
- char result[64];
- snprintf(result, sizeof(result), "Unknown enum value %d", value);
- str = result;
return false;
}
template <class Traits>
-inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
-{
+inline bool TypeConverter<Traits>::fromStringImpl(
+ const std::string &str, typename Traits::Type &result) {
for (size_t i = 0; mTable[i].literal; i++) {
if (strcmp(mTable[i].literal, str.c_str()) == 0) {
- ALOGV("stringToEnum() found %s", mTable[i].literal);
result = mTable[i].value;
return true;
}
@@ -152,6 +143,26 @@
}
template <class Traits>
+inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
+{
+ const bool success = toStringImpl(value, str);
+ if (!success) {
+ char result[64];
+ snprintf(result, sizeof(result), "Unknown enum value %d", value);
+ str = result;
+ }
+ return success;
+}
+
+template <class Traits>
+inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
+{
+ const bool success = fromStringImpl(str, result);
+ ALOGV_IF(success, "stringToEnum() found %s", str.c_str());
+ return success;
+}
+
+template <class Traits>
inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
typename Traits::Collection &collection,
const char *del)
@@ -168,7 +179,8 @@
}
template <class Traits>
-inline uint32_t TypeConverter<Traits>::maskFromString(const std::string &str, const char *del)
+inline typename Traits::Type TypeConverter<Traits>::maskFromString(
+ const std::string &str, const char *del)
{
char *literal = strdup(str.c_str());
uint32_t value = 0;
@@ -179,20 +191,24 @@
}
}
free(literal);
- return value;
+ return static_cast<typename Traits::Type>(value);
}
template <class Traits>
-inline void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
+inline void TypeConverter<Traits>::maskToString(
+ typename Traits::Type mask, std::string &str, const char *del)
{
if (mask != 0) {
bool first_flag = true;
- for (size_t i = 0; mTable[i].literal; i++) {
- uint32_t value = static_cast<uint32_t>(mTable[i].value);
- if (mTable[i].value != 0 && ((mask & value) == value)) {
- if (!first_flag) str += del;
- first_flag = false;
- str += mTable[i].literal;
+ for (size_t bit = 0; bit < sizeof(uint32_t) * 8; ++bit) {
+ uint32_t flag = 1u << bit;
+ if ((flag & mask) == flag) {
+ std::string flag_str;
+ if (toString(static_cast<typename Traits::Type>(flag), flag_str)) {
+ if (!first_flag) str += del;
+ first_flag = false;
+ str += flag_str;
+ }
}
}
} else {
@@ -200,6 +216,7 @@
}
}
+typedef TypeConverter<DeviceTraits> DeviceConverter;
typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
@@ -216,23 +233,227 @@
typedef TypeConverter<SourceTraits> SourceTypeConverter;
typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
-template<> const OutputDeviceConverter::Table OutputDeviceConverter::mTable[];
-template<> const InputDeviceConverter::Table InputDeviceConverter::mTable[];
-template<> const OutputFlagConverter::Table OutputFlagConverter::mTable[];
-template<> const InputFlagConverter::Table InputFlagConverter::mTable[];
-template<> const FormatConverter::Table FormatConverter::mTable[];
-template<> const OutputChannelConverter::Table OutputChannelConverter::mTable[];
-template<> const InputChannelConverter::Table InputChannelConverter::mTable[];
-template<> const ChannelIndexConverter::Table ChannelIndexConverter::mTable[];
-template<> const GainModeConverter::Table GainModeConverter::mTable[];
-template<> const StreamTypeConverter::Table StreamTypeConverter::mTable[];
template<> const AudioModeConverter::Table AudioModeConverter::mTable[];
-template<> const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[];
-template<> const UsageTypeConverter::Table UsageTypeConverter::mTable[];
-template<> const SourceTypeConverter::Table SourceTypeConverter::mTable[];
template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
-bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
+template <>
+inline bool TypeConverter<DeviceTraits>::toStringImpl(
+ const DeviceTraits::Type &value, std::string &str) {
+ str = audio_device_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<DeviceTraits>::fromStringImpl(
+ const std::string &str, DeviceTraits::Type &result) {
+ return audio_device_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<OutputDeviceTraits>::toStringImpl(
+ const OutputDeviceTraits::Type &value, std::string &str) {
+ if (audio_is_output_device(value)) {
+ str = audio_device_to_string(value);
+ return !str.empty();
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<OutputDeviceTraits>::fromStringImpl(
+ const std::string &str, OutputDeviceTraits::Type &result) {
+ OutputDeviceTraits::Type temp;
+ if (audio_device_from_string(str.c_str(), &temp) &&
+ audio_is_output_device(temp)) {
+ result = temp;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<InputDeviceTraits>::toStringImpl(
+ const InputDeviceTraits::Type &value, std::string &str) {
+ if (audio_is_input_device(value)) {
+ str = audio_device_to_string(value);
+ return !str.empty();
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<InputDeviceTraits>::fromStringImpl(
+ const std::string &str, InputDeviceTraits::Type &result) {
+ InputDeviceTraits::Type temp;
+ if (audio_device_from_string(str.c_str(), &temp) &&
+ audio_is_input_device(temp)) {
+ result = temp;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<InputFlagTraits>::toStringImpl(
+ const audio_input_flags_t &value, std::string &str) {
+ str = audio_input_flag_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<InputFlagTraits>::fromStringImpl(
+ const std::string &str, audio_input_flags_t &result) {
+ return audio_input_flag_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<OutputFlagTraits>::toStringImpl(
+ const audio_output_flags_t &value, std::string &str) {
+ str = audio_output_flag_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<OutputFlagTraits>::fromStringImpl(
+ const std::string &str, audio_output_flags_t &result) {
+ return audio_output_flag_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<FormatTraits>::toStringImpl(
+ const audio_format_t &value, std::string &str) {
+ str = audio_format_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<FormatTraits>::fromStringImpl(
+ const std::string &str, audio_format_t &result) {
+ return audio_format_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<OutputChannelTraits>::toStringImpl(
+ const audio_channel_mask_t &value, std::string &str) {
+ str = audio_channel_out_mask_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<OutputChannelTraits>::fromStringImpl(
+ const std::string &str, audio_channel_mask_t &result) {
+ OutputChannelTraits::Type temp;
+ if (audio_channel_mask_from_string(str.c_str(), &temp) &&
+ audio_is_output_channel(temp)) {
+ result = temp;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<InputChannelTraits>::toStringImpl(
+ const audio_channel_mask_t &value, std::string &str) {
+ str = audio_channel_in_mask_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<InputChannelTraits>::fromStringImpl(
+ const std::string &str, audio_channel_mask_t &result) {
+ InputChannelTraits::Type temp;
+ if (audio_channel_mask_from_string(str.c_str(), &temp) &&
+ audio_is_input_channel(temp)) {
+ result = temp;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<ChannelIndexTraits>::toStringImpl(
+ const audio_channel_mask_t &value, std::string &str) {
+ str = audio_channel_index_mask_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<ChannelIndexTraits>::fromStringImpl(
+ const std::string &str, audio_channel_mask_t &result) {
+ ChannelIndexTraits::Type temp;
+ if (audio_channel_mask_from_string(str.c_str(), &temp) &&
+ audio_channel_mask_get_representation(temp) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ result = temp;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool TypeConverter<StreamTraits>::toStringImpl(
+ const audio_stream_type_t &value, std::string &str) {
+ str = audio_stream_type_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<StreamTraits>::fromStringImpl(
+ const std::string &str, audio_stream_type_t &result)
+{
+ return audio_stream_type_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<GainModeTraits>::toStringImpl(
+ const audio_gain_mode_t &value, std::string &str) {
+ str = audio_gain_mode_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<GainModeTraits>::fromStringImpl(
+ const std::string &str, audio_gain_mode_t &result) {
+ return audio_gain_mode_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<AudioContentTraits>::toStringImpl(
+ const audio_content_type_t &value, std::string &str) {
+ str = audio_content_type_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<AudioContentTraits>::fromStringImpl(
+ const std::string &str, audio_content_type_t &result) {
+ return audio_content_type_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<UsageTraits>::toStringImpl(const audio_usage_t &value, std::string &str)
+{
+ str = audio_usage_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<UsageTraits>::fromStringImpl(
+ const std::string &str, audio_usage_t &result) {
+ return audio_usage_from_string(str.c_str(), &result);
+}
+
+template <>
+inline bool TypeConverter<SourceTraits>::toStringImpl(const audio_source_t &value, std::string &str)
+{
+ str = audio_source_to_string(value);
+ return !str.empty();
+}
+
+template <>
+inline bool TypeConverter<SourceTraits>::fromStringImpl(
+ const std::string &str, audio_source_t &result) {
+ return audio_source_from_string(str.c_str(), &result);
+}
SampleRateTraits::Collection samplingRatesFromString(
const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
@@ -256,6 +477,7 @@
// counting enumerations
template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::value
+ || std::is_same<T, audio_devices_t>::value
|| std::is_same<T, audio_mode_t>::value
|| std::is_same<T, audio_source_t>::value
|| std::is_same<T, audio_stream_type_t>::value
@@ -282,17 +504,6 @@
return result;
}
-static inline std::string toString(const audio_devices_t& devices)
-{
- std::string result;
- if ((devices & AUDIO_DEVICE_BIT_IN) != 0) {
- InputDeviceConverter::maskToString(devices, result);
- } else {
- OutputDeviceConverter::maskToString(devices, result);
- }
- return result;
-}
-
static inline std::string toString(const audio_attributes_t& attributes)
{
std::ostringstream result;
diff --git a/media/libmediahelper/tests/Android.bp b/media/libmediahelper/tests/Android.bp
new file mode 100644
index 0000000..a5f2819
--- /dev/null
+++ b/media/libmediahelper/tests/Android.bp
@@ -0,0 +1,31 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+ name: "libmedia_helper_tests",
+
+ generated_headers: ["audio_policy_configuration_V7_0"],
+ generated_sources: ["audio_policy_configuration_V7_0"],
+ header_libs: ["libxsdc-utils"],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libmedia_helper",
+ "libxml2",
+ ],
+
+ srcs: ["typeconverter_tests.cpp"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/media/libmediahelper/tests/typeconverter_tests.cpp b/media/libmediahelper/tests/typeconverter_tests.cpp
new file mode 100644
index 0000000..181d636
--- /dev/null
+++ b/media/libmediahelper/tests/typeconverter_tests.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "TypeConverter_Test"
+#include <log/log.h>
+
+#include <android_audio_policy_configuration_V7_0.h>
+#include <media/TypeConverter.h>
+#include <system/audio.h>
+#include <xsdc/XsdcSupport.h>
+
+using namespace android;
+namespace xsd {
+using namespace android::audio::policy::configuration::V7_0;
+}
+
+TEST(TypeConverter, ParseChannelMasks) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioChannelMask>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_channel_mask_t channelMask = channelMaskFromString(stringVal);
+ EXPECT_EQ(enumVal != xsd::AudioChannelMask::AUDIO_CHANNEL_NONE,
+ audio_channel_mask_is_valid(channelMask))
+ << "Validity of \"" << stringVal << "\" is not as expected";
+ }
+}
+
+TEST(TypeConverter, ParseInputOutputIndexChannelMask) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioChannelMask>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_channel_mask_t channelMask, channelMaskBack;
+ std::string stringValBack;
+ if (stringVal.find("_CHANNEL_IN_") != std::string::npos) {
+ EXPECT_TRUE(InputChannelConverter::fromString(stringVal, channelMask))
+ << "Conversion of \"" << stringVal << "\" failed (as input channel mask)";
+ EXPECT_TRUE(InputChannelConverter::toString(channelMask, stringValBack))
+ << "Conversion of input channel mask " << channelMask << " failed";
+ // Due to aliased values, the result of 'toString' might not be the same
+ // as 'stringVal', thus we need to compare the results of parsing instead.
+ EXPECT_TRUE(InputChannelConverter::fromString(stringValBack, channelMaskBack))
+ << "Conversion of \"" << stringValBack << "\" failed (as input channel mask)";
+ EXPECT_EQ(channelMask, channelMaskBack);
+ } else if (stringVal.find("_CHANNEL_OUT_") != std::string::npos) {
+ EXPECT_TRUE(OutputChannelConverter::fromString(stringVal, channelMask))
+ << "Conversion of \"" << stringVal << "\" failed (as output channel mask)";
+ EXPECT_TRUE(OutputChannelConverter::toString(channelMask, stringValBack))
+ << "Conversion of output channel mask " << channelMask << " failed";
+ EXPECT_TRUE(OutputChannelConverter::fromString(stringValBack, channelMaskBack))
+ << "Conversion of \"" << stringValBack << "\" failed (as output channel mask)";
+ EXPECT_EQ(channelMask, channelMaskBack);
+ } else if (stringVal.find("_CHANNEL_INDEX_") != std::string::npos) {
+ EXPECT_TRUE(ChannelIndexConverter::fromString(stringVal, channelMask))
+ << "Conversion of \"" << stringVal << "\" failed (as indexed channel mask)";
+ EXPECT_TRUE(ChannelIndexConverter::toString(channelMask, stringValBack))
+ << "Conversion of indexed channel mask " << channelMask << " failed";
+ EXPECT_EQ(stringVal, stringValBack);
+ } else if (stringVal == toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE)) {
+ EXPECT_FALSE(InputChannelConverter::fromString(stringVal, channelMask))
+ << "Conversion of \"" << stringVal << "\" succeeded (as input channel mask)";
+ EXPECT_FALSE(OutputChannelConverter::fromString(stringVal, channelMask))
+ << "Conversion of \"" << stringVal << "\" succeeded (as output channel mask)";
+ EXPECT_FALSE(ChannelIndexConverter::fromString(stringVal, channelMask))
+ << "Conversion of \"" << stringVal << "\" succeeded (as index channel mask)";
+ // None of Converters could parse this because 'NONE' isn't a 'valid' channel mask.
+ channelMask = AUDIO_CHANNEL_NONE;
+ // However they all must succeed in converting it back.
+ EXPECT_TRUE(InputChannelConverter::toString(channelMask, stringValBack))
+ << "Conversion of input channel mask " << channelMask << " failed";
+ EXPECT_EQ(stringVal, stringValBack);
+ EXPECT_TRUE(OutputChannelConverter::toString(channelMask, stringValBack))
+ << "Conversion of output channel mask " << channelMask << " failed";
+ EXPECT_EQ(stringVal, stringValBack);
+ EXPECT_TRUE(ChannelIndexConverter::toString(channelMask, stringValBack))
+ << "Conversion of indexed channel mask " << channelMask << " failed";
+ EXPECT_EQ(stringVal, stringValBack);
+ } else {
+ FAIL() << "Unrecognized channel mask \"" << stringVal << "\"";
+ }
+ }
+}
+
+TEST(TypeConverter, ParseContentTypes) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioContentType>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_content_type_t contentType;
+ EXPECT_TRUE(AudioContentTypeConverter::fromString(stringVal, contentType))
+ << "Conversion of \"" << stringVal << "\" failed";
+ EXPECT_EQ(stringVal, toString(contentType));
+ }
+}
+
+TEST(TypeConverter, ParseDevices) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioDevice>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_devices_t device, deviceBack;
+ std::string stringValBack;
+ EXPECT_TRUE(DeviceConverter::fromString(stringVal, device))
+ << "Conversion of \"" << stringVal << "\" failed";
+ if (enumVal != xsd::AudioDevice::AUDIO_DEVICE_NONE) {
+ EXPECT_TRUE(audio_is_input_device(device) || audio_is_output_device(device))
+ << "Device \"" << stringVal << "\" is neither input, nor output device";
+ } else {
+ EXPECT_FALSE(audio_is_input_device(device));
+ EXPECT_FALSE(audio_is_output_device(device));
+ }
+ // Due to aliased values, the result of 'toString' might not be the same
+ // as 'stringVal', thus we need to compare the results of parsing instead.
+ stringValBack = toString(device);
+ EXPECT_TRUE(DeviceConverter::fromString(stringValBack, deviceBack))
+ << "Conversion of \"" << stringValBack << "\" failed";
+ EXPECT_EQ(device, deviceBack);
+ }
+}
+
+TEST(TypeConverter, ParseInOutDevices) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioDevice>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_devices_t device, deviceBack;
+ std::string stringValBack;
+ if (stringVal.find("_DEVICE_IN_") != std::string::npos) {
+ EXPECT_TRUE(InputDeviceConverter::fromString(stringVal, device))
+ << "Conversion of \"" << stringVal << "\" failed (as input device)";
+ // Due to aliased values, the result of 'toString' might not be the same
+ // as 'stringVal', thus we need to compare the results of parsing instead.
+ stringValBack = toString(device);
+ EXPECT_TRUE(InputDeviceConverter::fromString(stringValBack, deviceBack))
+ << "Conversion of \"" << stringValBack << "\" failed";
+ EXPECT_EQ(device, deviceBack);
+ } else if (stringVal.find("_DEVICE_OUT_") != std::string::npos) {
+ EXPECT_TRUE(OutputDeviceConverter::fromString(stringVal, device))
+ << "Conversion of \"" << stringVal << "\" failed (as output device)";
+ stringValBack = toString(device);
+ EXPECT_TRUE(OutputDeviceConverter::fromString(stringValBack, deviceBack))
+ << "Conversion of \"" << stringValBack << "\" failed";
+ EXPECT_EQ(device, deviceBack);
+ } else if (stringVal == toString(xsd::AudioDevice::AUDIO_DEVICE_NONE)) {
+ EXPECT_FALSE(InputDeviceConverter::fromString(stringVal, device))
+ << "Conversion of \"" << stringVal << "\" succeeded (as input device)";
+ EXPECT_FALSE(OutputDeviceConverter::fromString(stringVal, device))
+ << "Conversion of \"" << stringVal << "\" succeeded (as output device)";
+ EXPECT_EQ(stringVal, toString(device));
+ } else {
+ FAIL() << "Unrecognized audio device \"" << stringVal << "\"";
+ }
+ }
+}
+
+TEST(TypeConverter, ParseInOutFlags) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioInOutFlag>{}) {
+ const std::string stringVal = toString(enumVal);
+ if (stringVal.find("_INPUT_FLAG_") != std::string::npos) {
+ audio_input_flags_t flag;
+ EXPECT_TRUE(InputFlagConverter::fromString(stringVal, flag))
+ << "Conversion of \"" << stringVal << "\" failed (as input flag)";
+ EXPECT_EQ(stringVal, toString(flag));
+ } else {
+ audio_output_flags_t flag;
+ EXPECT_TRUE(OutputFlagConverter::fromString(stringVal, flag))
+ << "Conversion of \"" << stringVal << "\" failed (as output flag)";
+ EXPECT_EQ(stringVal, toString(flag));
+ }
+ }
+}
+
+TEST(TypeConverter, ParseFormats) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioFormat>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_format_t format;
+ EXPECT_TRUE(FormatConverter::fromString(stringVal, format))
+ << "Conversion of \"" << stringVal << "\" failed";
+ EXPECT_EQ(enumVal != xsd::AudioFormat::AUDIO_FORMAT_DEFAULT,
+ audio_is_valid_format(format))
+ << "Validity of \"" << stringVal << "\" is not as expected";
+ EXPECT_EQ(stringVal, toString(format));
+ }
+}
+
+TEST(TypeConverter, ParseGainModes) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioGainMode>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_gain_mode_t gainMode;
+ EXPECT_TRUE(GainModeConverter::fromString(stringVal, gainMode))
+ << "Conversion of \"" << stringVal << "\" failed";
+ EXPECT_EQ(stringVal, toString(gainMode));
+ }
+}
+
+TEST(TypeConverter, ParseSources) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioSource>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_source_t source;
+ EXPECT_TRUE(SourceTypeConverter::fromString(stringVal, source))
+ << "Conversion of \"" << stringVal << "\" failed";
+ EXPECT_EQ(source != AUDIO_SOURCE_DEFAULT, audio_is_valid_audio_source(source))
+ << "Validity of \"" << stringVal << "\" is not as expected";
+ EXPECT_EQ(stringVal, toString(source));
+ }
+}
+
+TEST(TypeConverter, ParseStreamTypes) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioStreamType>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_stream_type_t streamType;
+ EXPECT_TRUE(StreamTypeConverter::fromString(stringVal, streamType))
+ << "Conversion of \"" << stringVal << "\" failed";
+ EXPECT_EQ(stringVal, toString(streamType));
+ }
+}
+
+TEST(TypeConverter, ParseUsages) {
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioUsage>{}) {
+ const std::string stringVal = toString(enumVal);
+ audio_usage_t usage;
+ EXPECT_TRUE(UsageTypeConverter::fromString(stringVal, usage))
+ << "Conversion of \"" << stringVal << "\" failed";
+ EXPECT_EQ(stringVal, toString(usage));
+ }
+}
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index ba84761..3843e70 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libmediametrics_headers",
export_include_dirs: ["include"],
@@ -53,6 +62,7 @@
visibility: [
"//cts/tests/tests/nativemedia/mediametrics",
"//frameworks/av:__subpackages__",
+ "//frameworks/base/apex/media/framework",
"//frameworks/base/core/jni",
"//frameworks/base/media/jni",
],
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 84388c9..674df17 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -139,6 +139,7 @@
#define AMEDIAMETRICS_PROP_SESSIONID "sessionId" // int32
#define AMEDIAMETRICS_PROP_SHARINGMODE "sharingMode" // string value, "exclusive", shared"
#define AMEDIAMETRICS_PROP_SOURCE "source" // string (AudioAttributes)
+#define AMEDIAMETRICS_PROP_STARTTHRESHOLDFRAMES "startThresholdFrames" // int32 (AudioTrack)
#define AMEDIAMETRICS_PROP_STARTUPMS "startupMs" // double value
// State is "ACTIVE" or "STOPPED" for AudioRecord
#define AMEDIAMETRICS_PROP_STATE "state" // string
@@ -181,6 +182,7 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE "setMode" // AudioFlinger
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETBUFFERSIZE "setBufferSize" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETPLAYBACKPARAM "setPlaybackParam" // AudioTrack
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETSTARTTHRESHOLD "setStartThreshold" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME "setVoiceVolume" // AudioFlinger
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOLUME "setVolume" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_START "start" // AudioTrack, AudioRecord
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 5301f5c..9ab117a 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -1,4 +1,23 @@
-cc_library_shared {
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libmediaplayerservice_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libmediaplayerservice_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_library {
srcs: [
"ActivityManager.cpp",
@@ -16,6 +35,7 @@
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
"libbase",
+ "libandroid_net",
"libaudioclient",
"libbinder",
"libcamera_client",
@@ -76,4 +96,3 @@
},
}
-
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c0da0ce..7cda2fb 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -480,14 +480,14 @@
}
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
- audio_session_t audioSessionId)
+ audio_session_t audioSessionId, std::string opPackageName)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(
this, pid, connId, client, audioSessionId,
- IPCThreadState::self()->getCallingUid());
+ IPCThreadState::self()->getCallingUid(), opPackageName);
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());
@@ -733,7 +733,8 @@
MediaPlayerService::Client::Client(
const sp<MediaPlayerService>& service, pid_t pid,
int32_t connId, const sp<IMediaPlayerClient>& client,
- audio_session_t audioSessionId, uid_t uid)
+ audio_session_t audioSessionId, uid_t uid, const std::string& opPackageName)
+ : mOpPackageName(opPackageName)
{
ALOGV("Client(%d) constructor", connId);
mPid = pid;
@@ -922,7 +923,7 @@
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
- mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
+ mPid, mAudioAttributes, mAudioDeviceUpdatedListener, mOpPackageName);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@@ -1062,6 +1063,17 @@
return mStatus = setDataSource_post(p, p->setDataSource(dataSource));
}
+status_t MediaPlayerService::Client::setDataSource(
+ const String8& rtpParams) {
+ player_type playerType = NU_PLAYER;
+ sp<MediaPlayerBase> p = setDataSource_pre(playerType);
+ if (p == NULL) {
+ return NO_INIT;
+ }
+ // now set data source
+ return mStatus = setDataSource_post(p, p->setDataSource(rtpParams));
+}
+
void MediaPlayerService::Client::disconnectNativeWindow_l() {
if (mConnectedWindow != NULL) {
status_t err = nativeWindowDisconnect(
@@ -1761,7 +1773,8 @@
#undef LOG_TAG
#define LOG_TAG "AudioSink"
MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
- const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
+ const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback,
+ const std::string& opPackageName)
: mCallback(NULL),
mCallbackCookie(NULL),
mCallbackData(NULL),
@@ -1782,7 +1795,8 @@
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
mDeviceCallbackEnabled(false),
- mDeviceCallback(deviceCallback)
+ mDeviceCallback(deviceCallback),
+ mOpPackageName(opPackageName)
{
ALOGV("AudioOutput(%d)", sessionId);
if (attr != NULL) {
@@ -1808,8 +1822,7 @@
//static
void MediaPlayerService::AudioOutput::setMinBufferCount()
{
- char value[PROPERTY_VALUE_MAX];
- if (property_get("ro.kernel.qemu", value, 0)) {
+ if (property_get_bool("ro.boot.qemu", false)) {
mIsOnEmulator = true;
mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
}
@@ -2176,7 +2189,8 @@
mAttributes,
doNotReconnect,
1.0f, // default value for maxRequiredSpeed
- mSelectedDeviceId);
+ mSelectedDeviceId,
+ mOpPackageName);
} else {
// TODO: Due to buffer memory concerns, we use a max target playback speed
// based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
@@ -2204,7 +2218,8 @@
mAttributes,
doNotReconnect,
targetSpeed,
- mSelectedDeviceId);
+ mSelectedDeviceId,
+ mOpPackageName);
}
// Set caller name so it can be logged in destructor.
// MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 6431ca1..b2f1b9b 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -19,6 +19,7 @@
#define ANDROID_MEDIAPLAYERSERVICE_H
#include <arpa/inet.h>
+#include <string>
#include <utils/threads.h>
#include <utils/Errors.h>
@@ -81,7 +82,8 @@
uid_t uid,
int pid,
const audio_attributes_t * attr,
- const sp<AudioSystem::AudioDeviceCallback>& deviceCallback);
+ const sp<AudioSystem::AudioDeviceCallback>& deviceCallback,
+ const std::string& opPackageName);
virtual ~AudioOutput();
virtual bool ready() const { return mTrack != 0; }
@@ -178,6 +180,7 @@
bool mDeviceCallbackEnabled;
wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
mutable Mutex mLock;
+ const std::string mOpPackageName;
// static variables below not protected by mutex
static bool mIsOnEmulator;
@@ -235,7 +238,8 @@
virtual sp<IMediaMetadataRetriever> createMetadataRetriever();
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
- audio_session_t audioSessionId);
+ audio_session_t audioSessionId,
+ const std::string opPackageName);
virtual sp<IMediaCodecList> getCodecList() const;
@@ -368,6 +372,7 @@
virtual status_t setDataSource(const sp<IStreamSource> &source);
virtual status_t setDataSource(const sp<IDataSource> &source);
+ virtual status_t setDataSource(const String8& rtpParams);
sp<MediaPlayerBase> setDataSource_pre(player_type playerType);
@@ -410,7 +415,8 @@
int32_t connId,
const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId,
- uid_t uid);
+ uid_t uid,
+ const std::string& opPackageName);
Client();
virtual ~Client();
@@ -467,6 +473,7 @@
bool mRetransmitEndpointValid;
sp<Client> mNextClient;
sp<MediaPlayerBase::Listener> mListener;
+ const std::string mOpPackageName;
// Metadata filters.
media::Metadata::Filter mMetadataAllow; // protected by mLock
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 9b1974b..9f16a22 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -28,6 +28,7 @@
#include <binder/IServiceManager.h>
#include <binder/MemoryHeapBase.h>
#include <binder/MemoryBase.h>
+#include <camera/CameraUtils.h>
#include <codec2/hidl/client.h>
#include <cutils/atomic.h>
#include <cutils/properties.h> // for property_get
@@ -423,30 +424,35 @@
sp<IServiceManager> sm = defaultServiceManager();
- // WORKAROUND: We don't know if camera exists here and getService might block for 5 seconds.
- // Use checkService for camera if we don't know it exists.
- static std::atomic<bool> sCameraChecked(false); // once true never becomes false.
- static std::atomic<bool> sCameraVerified(false); // once true never becomes false.
- sp<IBinder> binder = (sCameraVerified || !sCameraChecked)
- ? sm->getService(String16("media.camera")) : sm->checkService(String16("media.camera"));
- // If the device does not have a camera, do not create a death listener for it.
- if (binder != NULL) {
- sCameraVerified = true;
- mDeathNotifiers.emplace_back(
- binder, [l = wp<IMediaRecorderClient>(listener)](){
- sp<IMediaRecorderClient> listener = l.promote();
- if (listener) {
- ALOGV("media.camera service died. "
- "Sending death notification.");
- listener->notify(
- MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
- MediaPlayerService::CAMERA_PROCESS_DEATH);
- } else {
- ALOGW("media.camera service died without a death handler.");
- }
- });
+ static const bool sCameraDisabled = CameraUtils::isCameraServiceDisabled();
+
+ if (!sCameraDisabled) {
+ // WORKAROUND: We don't know if camera exists here and getService might block for 5 seconds.
+ // Use checkService for camera if we don't know it exists.
+ static std::atomic<bool> sCameraChecked(false); // once true never becomes false.
+ static std::atomic<bool> sCameraVerified(false); // once true never becomes false.
+
+ sp<IBinder> binder = (sCameraVerified || !sCameraChecked)
+ ? sm->getService(String16("media.camera")) : sm->checkService(String16("media.camera"));
+ // If the device does not have a camera, do not create a death listener for it.
+ if (binder != NULL) {
+ sCameraVerified = true;
+ mDeathNotifiers.emplace_back(
+ binder, [l = wp<IMediaRecorderClient>(listener)](){
+ sp<IMediaRecorderClient> listener = l.promote();
+ if (listener) {
+ ALOGV("media.camera service died. "
+ "Sending death notification.");
+ listener->notify(
+ MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
+ MediaPlayerService::CAMERA_PROCESS_DEATH);
+ } else {
+ ALOGW("media.camera service died without a death handler.");
+ }
+ });
+ }
+ sCameraChecked = true;
}
- sCameraChecked = true;
{
using ::android::hidl::base::V1_0::IBase;
@@ -585,4 +591,13 @@
}
return NO_INIT;
}
+
+status_t MediaRecorderClient::getRtpDataUsage(uint64_t *bytes) {
+ ALOGV("getRtpDataUsage");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder != NULL) {
+ return mRecorder->getRtpDataUsage(bytes);
+ }
+ return NO_INIT;
+}
}; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 12257e5..e041855 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -86,6 +86,7 @@
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) override;
+ virtual status_t getRtpDataUsage(uint64_t *bytes);
private:
friend class MediaPlayerService; // for accessing private constructor
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 7897959..ecbdf61 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -17,6 +17,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "StagefrightRecorder"
#include <inttypes.h>
+// TODO/workaround: including base logging now as it conflicts with ADebug.h
+// and it must be included first.
+#include <android-base/logging.h>
#include <utils/Log.h>
#include "WebmWriter.h"
@@ -44,6 +47,7 @@
#include <media/stagefright/CameraSourceTimeLapse.h>
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaCodecSource.h>
@@ -117,6 +121,11 @@
mAudioSource((audio_source_t)AUDIO_SOURCE_CNT), // initialize with invalid value
mPrivacySensitive(PRIVACY_SENSITIVE_DEFAULT),
mVideoSource(VIDEO_SOURCE_LIST_END),
+ mRTPCVOExtMap(-1),
+ mRTPCVODegrees(0),
+ mRTPSockDscp(0),
+ mRTPSockNetwork(0),
+ mLastSeqNo(0),
mStarted(false),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
mDeviceCallbackEnabled(false),
@@ -125,6 +134,7 @@
ALOGV("Constructor");
+ mMetricsItem = NULL;
mAnalyticsDirty = false;
reset();
}
@@ -199,10 +209,12 @@
void StagefrightRecorder::flushAndResetMetrics(bool reinitialize) {
ALOGV("flushAndResetMetrics");
// flush anything we have, maybe setup a new record
- if (mAnalyticsDirty && mMetricsItem != NULL) {
- updateMetrics();
- if (mMetricsItem->count() > 0) {
- mMetricsItem->selfrecord();
+ if (mMetricsItem != NULL) {
+ if (mAnalyticsDirty) {
+ updateMetrics();
+ if (mMetricsItem->count() > 0) {
+ mMetricsItem->selfrecord();
+ }
}
delete mMetricsItem;
mMetricsItem = NULL;
@@ -567,6 +579,32 @@
// range that a specific encoder supports. The mismatch between the
// the target and requested bit rate will NOT be treated as an error.
mVideoBitRate = bitRate;
+
+ // A new bitrate(TMMBR) should be applied on runtime as well if OutputFormat is RTP_AVP
+ if (mOutputFormat == OUTPUT_FORMAT_RTP_AVP) {
+ // Regular I frames may overload the network so we reduce the bitrate to allow
+ // margins for the I frame overruns.
+ // Still send requested bitrate (TMMBR) in the reply (TMMBN).
+ const float coefficient = 0.8f;
+ mVideoBitRate = (bitRate * coefficient) / 1000 * 1000;
+ }
+ if (mOutputFormat == OUTPUT_FORMAT_RTP_AVP && mStarted && mPauseStartTimeUs == 0) {
+ mVideoEncoderSource->setEncodingBitrate(mVideoBitRate);
+ ARTPWriter* rtpWriter = static_cast<ARTPWriter*>(mWriter.get());
+ rtpWriter->setTMMBNInfo(mOpponentID, bitRate);
+ }
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoBitRateMode(int32_t bitRateMode) {
+ ALOGV("setParamVideoBitRateMode: %d", bitRateMode);
+ // TODO: clarify what bitrate mode of -1 is as these start from 0
+ if (bitRateMode < -1) {
+ ALOGE("Unsupported video bitrate mode: %d", bitRateMode);
+ return BAD_VALUE;
+ }
+ mVideoBitRateMode = bitRateMode;
return OK;
}
@@ -776,6 +814,105 @@
return OK;
}
+status_t StagefrightRecorder::setParamRtpLocalIp(const String8 &localIp) {
+ ALOGV("setParamVideoLocalIp: %s", localIp.string());
+
+ mLocalIp.setTo(localIp.string());
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamRtpLocalPort(int32_t localPort) {
+ ALOGV("setParamVideoLocalPort: %d", localPort);
+
+ mLocalPort = localPort;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamRtpRemoteIp(const String8 &remoteIp) {
+ ALOGV("setParamVideoRemoteIp: %s", remoteIp.string());
+
+ mRemoteIp.setTo(remoteIp.string());
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamRtpRemotePort(int32_t remotePort) {
+ ALOGV("setParamVideoRemotePort: %d", remotePort);
+
+ mRemotePort = remotePort;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamSelfID(int32_t selfID) {
+ ALOGV("setParamSelfID: %x", selfID);
+
+ mSelfID = selfID;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoOpponentID(int32_t opponentID) {
+ mOpponentID = opponentID;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamPayloadType(int32_t payloadType) {
+ ALOGV("setParamPayloadType: %d", payloadType);
+
+ mPayloadType = payloadType;
+
+ if (mStarted && mOutputFormat == OUTPUT_FORMAT_RTP_AVP) {
+ mWriter->updatePayloadType(mPayloadType);
+ }
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setRTPCVOExtMap(int32_t extmap) {
+ ALOGV("setRtpCvoExtMap: %d", extmap);
+
+ mRTPCVOExtMap = extmap;
+ return OK;
+}
+
+status_t StagefrightRecorder::setRTPCVODegrees(int32_t cvoDegrees) {
+ Mutex::Autolock autolock(mLock);
+ ALOGV("setRtpCvoDegrees: %d", cvoDegrees);
+
+ mRTPCVODegrees = cvoDegrees;
+
+ if (mStarted && mOutputFormat == OUTPUT_FORMAT_RTP_AVP) {
+ mWriter->updateCVODegrees(mRTPCVODegrees);
+ }
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamRtpDscp(int32_t dscp) {
+ ALOGV("setParamRtpDscp: %d", dscp);
+
+ mRTPSockDscp = dscp;
+ return OK;
+}
+
+status_t StagefrightRecorder::setSocketNetwork(int64_t networkHandle) {
+ ALOGV("setSocketNetwork: %llu", (unsigned long long) networkHandle);
+
+ mRTPSockNetwork = networkHandle;
+ if (mStarted && mOutputFormat == OUTPUT_FORMAT_RTP_AVP) {
+ mWriter->updateSocketNetwork(mRTPSockNetwork);
+ }
+ return OK;
+}
+
+status_t StagefrightRecorder::requestIDRFrame() {
+ status_t ret = BAD_VALUE;
+ if (mVideoEncoderSource != NULL) {
+ ret = mVideoEncoderSource->requestIDRFrame();
+ } else {
+ ALOGV("requestIDRFrame: Encoder not ready");
+ }
+ return ret;
+}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -844,6 +981,11 @@
if (safe_strtoi32(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitRate(video_bitrate);
}
+ } else if (key == "video-param-bitrate-mode") {
+ int32_t video_bitrate_mode;
+ if (safe_strtoi32(value.string(), &video_bitrate_mode)) {
+ return setParamVideoBitRateMode(video_bitrate_mode);
+ }
} else if (key == "video-param-rotation-angle-degrees") {
int32_t degrees;
if (safe_strtoi32(value.string(), °rees)) {
@@ -884,6 +1026,61 @@
if (safe_strtod(value.string(), &fps)) {
return setParamCaptureFps(fps);
}
+ } else if (key == "rtp-param-local-ip") {
+ return setParamRtpLocalIp(value);
+ } else if (key == "rtp-param-local-port") {
+ int32_t localPort;
+ if (safe_strtoi32(value.string(), &localPort)) {
+ return setParamRtpLocalPort(localPort);
+ }
+ } else if (key == "rtp-param-remote-ip") {
+ return setParamRtpRemoteIp(value);
+ } else if (key == "rtp-param-remote-port") {
+ int32_t remotePort;
+ if (safe_strtoi32(value.string(), &remotePort)) {
+ return setParamRtpRemotePort(remotePort);
+ }
+ } else if (key == "rtp-param-self-id") {
+ int32_t selfID;
+ int64_t temp;
+ if (safe_strtoi64(value.string(), &temp)) {
+ selfID = static_cast<int32_t>(temp);
+ return setParamSelfID(selfID);
+ }
+ } else if (key == "rtp-param-opponent-id") {
+ int32_t opnId;
+ int64_t temp;
+ if (safe_strtoi64(value.string(), &temp)) {
+ opnId = static_cast<int32_t>(temp);
+ return setParamVideoOpponentID(opnId);
+ }
+ } else if (key == "rtp-param-payload-type") {
+ int32_t payloadType;
+ if (safe_strtoi32(value.string(), &payloadType)) {
+ return setParamPayloadType(payloadType);
+ }
+ } else if (key == "rtp-param-ext-cvo-extmap") {
+ int32_t extmap;
+ if (safe_strtoi32(value.string(), &extmap)) {
+ return setRTPCVOExtMap(extmap);
+ }
+ } else if (key == "rtp-param-ext-cvo-degrees") {
+ int32_t degrees;
+ if (safe_strtoi32(value.string(), °rees)) {
+ return setRTPCVODegrees(degrees);
+ }
+ } else if (key == "video-param-request-i-frame") {
+ return requestIDRFrame();
+ } else if (key == "rtp-param-set-socket-dscp") {
+ int32_t dscp;
+ if (safe_strtoi32(value.string(), &dscp)) {
+ return setParamRtpDscp(dscp);
+ }
+ } else if (key == "rtp-param-set-socket-network") {
+ int64_t networkHandle;
+ if (safe_strtoi64(value.string(), &networkHandle)) {
+ return setSocketNetwork(networkHandle);
+ }
} else {
ALOGE("setParameter: failed to find key %s", key.string());
}
@@ -1050,6 +1247,17 @@
sp<MetaData> meta = new MetaData;
int64_t startTimeUs = systemTime() / 1000;
meta->setInt64(kKeyTime, startTimeUs);
+ meta->setInt32(kKeySelfID, mSelfID);
+ meta->setInt32(kKeyPayloadType, mPayloadType);
+ meta->setInt64(kKeySocketNetwork, mRTPSockNetwork);
+ if (mRTPCVOExtMap > 0) {
+ meta->setInt32(kKeyRtpExtMap, mRTPCVOExtMap);
+ meta->setInt32(kKeyRtpCvoDegrees, mRTPCVODegrees);
+ }
+ if (mRTPSockDscp > 0) {
+ meta->setInt32(kKeyRtpDscp, mRTPSockDscp);
+ }
+
status = mWriter->start(meta.get());
break;
}
@@ -1113,7 +1321,7 @@
if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
if (attr.source == AUDIO_SOURCE_VOICE_COMMUNICATION
|| attr.source == AUDIO_SOURCE_CAMCORDER) {
- attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+ attr.flags = static_cast<audio_flags_mask_t>(attr.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
mPrivacySensitive = PRIVACY_SENSITIVE_ENABLED;
} else {
mPrivacySensitive = PRIVACY_SENSITIVE_DISABLED;
@@ -1129,7 +1337,7 @@
return NULL;
}
if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
- attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+ attr.flags = static_cast<audio_flags_mask_t>(attr.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
}
}
@@ -1330,7 +1538,7 @@
mVideoEncoderSource = source;
}
- mWriter = new ARTPWriter(mOutputFd);
+ mWriter = new ARTPWriter(mOutputFd, mLocalIp, mLocalPort, mRemoteIp, mRemotePort, mLastSeqNo);
mWriter->addSource(source);
mWriter->setListener(mListener);
@@ -1784,7 +1992,13 @@
}
}
+ if (mOutputFormat == OUTPUT_FORMAT_RTP_AVP) {
+ // This indicates that a raw image provided to encoder needs to be rotated.
+ format->setInt32("rotation-degrees", mRotationDegrees);
+ }
+
format->setInt32("bitrate", mVideoBitRate);
+ format->setInt32("bitrate-mode", mVideoBitRateMode);
format->setInt32("frame-rate", mFrameRate);
format->setInt32("i-frame-interval", mIFramesIntervalSec);
@@ -2130,6 +2344,7 @@
if (mWriter != NULL) {
err = mWriter->stop();
+ mLastSeqNo = mWriter->getSequenceNum();
mWriter.clear();
}
@@ -2206,6 +2421,8 @@
mVideoHeight = 144;
mFrameRate = -1;
mVideoBitRate = 192000;
+ // Following MediaCodec's default
+ mVideoBitRateMode = BITRATE_MODE_VBR;
mSampleRate = 8000;
mAudioChannels = 1;
mAudioBitRate = 12200;
@@ -2351,6 +2568,14 @@
return NO_INIT;
}
+status_t StagefrightRecorder::getRtpDataUsage(uint64_t *bytes) {
+ if (mWriter != 0) {
+ *bytes = mWriter->getAccumulativeBytes();
+ return OK;
+ }
+ return NO_INIT;
+}
+
status_t StagefrightRecorder::dump(
int fd, const Vector<String16>& args) const {
ALOGV("dump");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index a725bee..4bba869 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -82,6 +82,7 @@
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const override;
+ virtual status_t getRtpDataUsage(uint64_t *bytes);
private:
@@ -119,6 +120,7 @@
int32_t mVideoWidth, mVideoHeight;
int32_t mFrameRate;
int32_t mVideoBitRate;
+ int32_t mVideoBitRateMode;
int32_t mAudioBitRate;
int32_t mAudioChannels;
int32_t mSampleRate;
@@ -138,6 +140,18 @@
int32_t mLongitudex10000;
int32_t mStartTimeOffsetMs;
int32_t mTotalBitRate;
+ String8 mLocalIp;
+ String8 mRemoteIp;
+ int32_t mLocalPort;
+ int32_t mRemotePort;
+ int32_t mSelfID;
+ int32_t mOpponentID;
+ int32_t mPayloadType;
+ int32_t mRTPCVOExtMap;
+ int32_t mRTPCVODegrees;
+ int32_t mRTPSockDscp;
+ int64_t mRTPSockNetwork;
+ uint32_t mLastSeqNo;
int64_t mDurationRecordedUs;
int64_t mStartedRecordingUs;
@@ -205,6 +219,7 @@
status_t setParamCaptureFpsEnable(int32_t timeLapseEnable);
status_t setParamCaptureFps(double fps);
status_t setParamVideoEncodingBitRate(int32_t bitRate);
+ status_t setParamVideoBitRateMode(int32_t bitRateMode);
status_t setParamVideoIFramesInterval(int32_t seconds);
status_t setParamVideoEncoderProfile(int32_t profile);
status_t setParamVideoEncoderLevel(int32_t level);
@@ -219,6 +234,18 @@
status_t setParamMovieTimeScale(int32_t timeScale);
status_t setParamGeoDataLongitude(int64_t longitudex10000);
status_t setParamGeoDataLatitude(int64_t latitudex10000);
+ status_t setParamRtpLocalIp(const String8 &localIp);
+ status_t setParamRtpLocalPort(int32_t localPort);
+ status_t setParamRtpRemoteIp(const String8 &remoteIp);
+ status_t setParamRtpRemotePort(int32_t remotePort);
+ status_t setParamSelfID(int32_t selfID);
+ status_t setParamVideoOpponentID(int32_t opponentID);
+ status_t setParamPayloadType(int32_t payloadType);
+ status_t setRTPCVOExtMap(int32_t extmap);
+ status_t setRTPCVODegrees(int32_t cvoDegrees);
+ status_t setParamRtpDscp(int32_t dscp);
+ status_t setSocketNetwork(int64_t networkHandle);
+ status_t requestIDRFrame();
void clipVideoBitRate();
void clipVideoFrameRate();
void clipVideoFrameWidth();
diff --git a/media/libmediaplayerservice/datasource/Android.bp b/media/libmediaplayerservice/datasource/Android.bp
index 71fa50b..19fc172 100644
--- a/media/libmediaplayerservice/datasource/Android.bp
+++ b/media/libmediaplayerservice/datasource/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmediaplayerservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libmediaplayerservice_license",
+ ],
+}
+
cc_library_static {
name: "libplayerservice_datasource",
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index 436cb31..8d94698 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -60,7 +60,7 @@
#define DEFAULT_AUDIOSINK_SAMPLERATE 44100
// when the channel mask isn't known, use the channel count to derive a mask in AudioSink::open()
-#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
+#define CHANNEL_MASK_USE_CHANNEL_ORDER AUDIO_CHANNEL_NONE
// duration below which we do not allow deep audio buffering
#define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
@@ -183,6 +183,10 @@
return INVALID_OPERATION;
}
+ virtual status_t setDataSource(const String8& /* rtpParams */) {
+ return INVALID_OPERATION;
+ }
+
// pass the buffered IGraphicBufferProducer to the media player service
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 32c97cf..6d338db 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libmediaplayerservice_nuplayer_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libmediaplayerservice_nuplayer_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
srcs: [
@@ -14,6 +33,7 @@
"NuPlayerRenderer.cpp",
"NuPlayerStreamListener.cpp",
"RTSPSource.cpp",
+ "RTPSource.cpp",
"StreamingSource.cpp",
],
@@ -30,6 +50,7 @@
"frameworks/av/media/libstagefright/mpeg2ts",
"frameworks/av/media/libstagefright/rtsp",
"frameworks/av/media/libstagefright/timedtext",
+ "frameworks/native/include/android",
],
cflags: [
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index c1c4b55..389249e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -31,6 +31,7 @@
#include "NuPlayerDriver.h"
#include "NuPlayerRenderer.h"
#include "NuPlayerSource.h"
+#include "RTPSource.h"
#include "RTSPSource.h"
#include "StreamingSource.h"
#include "GenericSource.h"
@@ -368,6 +369,18 @@
return err;
}
+void NuPlayer::setDataSourceAsync(const String8& rtpParams) {
+ ALOGD("setDataSourceAsync for RTP = %s", rtpParams.string());
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
+
+ sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
+ sp<Source> source = new RTPSource(notify, rtpParams);
+
+ msg->setObject("source", source);
+ msg->post();
+ mDataSourceType = DATA_SOURCE_TYPE_RTP;
+}
+
void NuPlayer::prepareAsync() {
ALOGV("prepareAsync");
@@ -1689,6 +1702,12 @@
updateRebufferingTimer(false /* stopping */, false /* exiting */);
}
+void NuPlayer::setTargetBitrate(int bitrate) {
+ if (mSource != NULL) {
+ mSource->setTargetBitrate(bitrate);
+ }
+}
+
void NuPlayer::onPause() {
updatePlaybackTimer(true /* stopping */, "onPause");
@@ -1915,6 +1934,11 @@
format->setInt32("priority", 0 /* realtime */);
+ if (mDataSourceType == DATA_SOURCE_TYPE_RTP) {
+ ALOGV("instantiateDecoder: set decoder error free on stream corrupt.");
+ format->setInt32("corrupt-free", true);
+ }
+
if (!audio) {
AString mime;
CHECK(format->findString("mime", &mime));
@@ -2715,6 +2739,14 @@
break;
}
+ case Source::kWhatIMSRxNotice:
+ {
+ sp<AMessage> IMSRxNotice;
+ CHECK(msg->findMessage("message", &IMSRxNotice));
+ sendIMSRxNotice(IMSRxNotice);
+ break;
+ }
+
default:
TRESPASS();
}
@@ -2817,11 +2849,75 @@
}
}
+void NuPlayer::sendIMSRxNotice(const sp<AMessage> &msg) {
+ int32_t payloadType;
+
+ CHECK(msg->findInt32("payload-type", &payloadType));
+
+ Parcel in;
+ in.writeInt32(payloadType);
+
+ switch (payloadType) {
+ case ARTPSource::RTCP_TSFB: // RTCP TSFB
+ case ARTPSource::RTCP_PSFB: // RTCP PSFB
+ case ARTPSource::RTP_AUTODOWN:
+ {
+ int32_t feedbackType, id;
+ CHECK(msg->findInt32("feedback-type", &feedbackType));
+ CHECK(msg->findInt32("sender", &id));
+ in.writeInt32(feedbackType);
+ in.writeInt32(id);
+ if (payloadType == ARTPSource::RTCP_TSFB) {
+ int32_t bitrate;
+ CHECK(msg->findInt32("bit-rate", &bitrate));
+ in.writeInt32(bitrate);
+ }
+ break;
+ }
+ case ARTPSource::RTP_QUALITY:
+ case ARTPSource::RTP_QUALITY_EMC:
+ {
+ int32_t feedbackType, bitrate;
+ int32_t highestSeqNum, baseSeqNum, prevExpected;
+ int32_t numBufRecv, prevNumBufRecv;
+ CHECK(msg->findInt32("feedback-type", &feedbackType));
+ CHECK(msg->findInt32("bit-rate", &bitrate));
+ CHECK(msg->findInt32("highest-seq-num", &highestSeqNum));
+ CHECK(msg->findInt32("base-seq-num", &baseSeqNum));
+ CHECK(msg->findInt32("prev-expected", &prevExpected));
+ CHECK(msg->findInt32("num-buf-recv", &numBufRecv));
+ CHECK(msg->findInt32("prev-num-buf-recv", &prevNumBufRecv));
+ in.writeInt32(feedbackType);
+ in.writeInt32(bitrate);
+ in.writeInt32(highestSeqNum);
+ in.writeInt32(baseSeqNum);
+ in.writeInt32(prevExpected);
+ in.writeInt32(numBufRecv);
+ in.writeInt32(prevNumBufRecv);
+ break;
+ }
+ case ARTPSource::RTP_CVO:
+ {
+ int32_t cvo;
+ CHECK(msg->findInt32("cvo", &cvo));
+ in.writeInt32(cvo);
+ break;
+ }
+ default:
+ break;
+ }
+
+ notifyListener(MEDIA_IMS_RX_NOTICE, 0, 0, &in);
+}
+
const char *NuPlayer::getDataSourceType() {
switch (mDataSourceType) {
case DATA_SOURCE_TYPE_HTTP_LIVE:
return "HTTPLive";
+ case DATA_SOURCE_TYPE_RTP:
+ return "RTP";
+
case DATA_SOURCE_TYPE_RTSP:
return "RTSP";
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index ef4354c..adb7075 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -51,6 +51,8 @@
void setDataSourceAsync(const sp<DataSource> &source);
+ void setDataSourceAsync(const String8& rtpParams);
+
status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
status_t setBufferingSettings(const BufferingSettings& buffering);
@@ -100,6 +102,8 @@
void updateInternalTimers();
+ void setTargetBitrate(int bitrate /* bps */);
+
protected:
virtual ~NuPlayer();
@@ -117,6 +121,7 @@
struct GenericSource;
struct HTTPLiveSource;
struct Renderer;
+ struct RTPSource;
struct RTSPSource;
struct StreamingSource;
struct Action;
@@ -257,6 +262,7 @@
typedef enum {
DATA_SOURCE_TYPE_NONE,
DATA_SOURCE_TYPE_HTTP_LIVE,
+ DATA_SOURCE_TYPE_RTP,
DATA_SOURCE_TYPE_RTSP,
DATA_SOURCE_TYPE_GENERIC_URL,
DATA_SOURCE_TYPE_GENERIC_FD,
@@ -334,6 +340,7 @@
void sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex);
void sendTimedMetaData(const sp<ABuffer> &buffer);
void sendTimedTextData(const sp<ABuffer> &buffer);
+ void sendIMSRxNotice(const sp<AMessage> &msg);
void writeTrackInfo(Parcel* reply, const sp<AMessage>& format) const;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index f734439..5b60bbf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -746,9 +746,15 @@
mOutputBuffers.editItemAt(index) = buffer;
+ int64_t frameIndex;
+ bool frameIndexFound = buffer->meta()->findInt64("frameIndex", &frameIndex);
+
buffer->setRange(offset, size);
buffer->meta()->clear();
buffer->meta()->setInt64("timeUs", timeUs);
+ if (frameIndexFound) {
+ buffer->meta()->setInt64("frameIndex", frameIndex);
+ }
bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
// we do not expect CODECCONFIG or SYNCFRAME for decoder
@@ -1050,7 +1056,7 @@
uint32_t flags = 0;
CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
- int32_t eos, csd;
+ int32_t eos, csd, cvo;
// we do not expect SYNCFRAME for decoder
if (buffer->meta()->findInt32("eos", &eos) && eos) {
flags |= MediaCodec::BUFFER_FLAG_EOS;
@@ -1058,6 +1064,24 @@
flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
}
+ if (buffer->meta()->findInt32("cvo", (int32_t*)&cvo)) {
+ ALOGV("[%s] cvo(%d) found at %lld us", mComponentName.c_str(), cvo, (long long)timeUs);
+ switch (cvo) {
+ case 0:
+ codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_0);
+ break;
+ case 1:
+ codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_90);
+ break;
+ case 2:
+ codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_180);
+ break;
+ case 3:
+ codecBuffer->meta()->setInt32("cvo", MediaCodec::CVO_DEGREE_270);
+ break;
+ }
+ }
+
// Modular DRM
MediaBufferBase *mediaBuf = NULL;
NuPlayerDrm::CryptoInfo *cryptInfo = NULL;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index dc144b2..2a50fc2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -218,6 +218,26 @@
return mAsyncResult;
}
+status_t NuPlayerDriver::setDataSource(const String8& rtpParams) {
+ ALOGV("setDataSource(%p) rtp source", this);
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != STATE_IDLE) {
+ return INVALID_OPERATION;
+ }
+
+ mState = STATE_SET_DATASOURCE_PENDING;
+
+ mPlayer->setDataSourceAsync(rtpParams);
+
+ while (mState == STATE_SET_DATASOURCE_PENDING) {
+ mCondition.wait(mLock);
+ }
+
+ return mAsyncResult;
+}
+
+
status_t NuPlayerDriver::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer> &bufferProducer) {
ALOGV("setVideoSurfaceTexture(%p)", this);
@@ -797,7 +817,11 @@
}
status_t NuPlayerDriver::setParameter(
- int /* key */, const Parcel & /* request */) {
+ int key, const Parcel &request ) {
+ if (key == KEY_PARAMETER_RTP_ATTRIBUTES) {
+ mPlayer->setTargetBitrate(request.readInt32());
+ return OK;
+ }
return INVALID_OPERATION;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index f4b1968..55a0fad 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -43,6 +43,8 @@
virtual status_t setDataSource(const sp<DataSource>& dataSource);
+ virtual status_t setDataSource(const String8& rtpParams);
+
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer> &bufferProducer);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 7e8fe45..6a8c708 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1933,11 +1933,12 @@
int32_t numChannels;
CHECK(format->findInt32("channel-count", &numChannels));
- int32_t channelMask;
- if (!format->findInt32("channel-mask", &channelMask)) {
- // signal to the AudioSink to derive the mask from count.
- channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
- }
+ int32_t rawChannelMask;
+ audio_channel_mask_t channelMask =
+ format->findInt32("channel-mask", &rawChannelMask) ?
+ static_cast<audio_channel_mask_t>(rawChannelMask)
+ // signal to the AudioSink to derive the mask from count.
+ : CHANNEL_MASK_USE_CHANNEL_ORDER;
int32_t sampleRate;
CHECK(format->findInt32("sample-rate", &sampleRate));
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index f137c52..bf6b539 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -58,6 +58,7 @@
kWhatInstantiateSecureDecoders,
// Modular DRM
kWhatDrmInfo,
+ kWhatIMSRxNotice,
};
// The provides message is used to notify the player about various
@@ -131,6 +132,8 @@
virtual void setOffloadAudio(bool /* offload */) {}
+ virtual void setTargetBitrate(int32_t) {}
+
// Modular DRM
virtual status_t prepareDrm(
const uint8_t /*uuid*/[16], const Vector<uint8_t> &/*drmSessionId*/,
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
new file mode 100644
index 0000000..b43df38
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -0,0 +1,801 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "RTPSource"
+#include <utils/Log.h>
+
+#include "RTPSource.h"
+
+
+
+
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <string.h>
+
+namespace android {
+
+const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
+static int32_t kMaxAllowedStaleAccessUnits = 20;
+
+NuPlayer::RTPSource::RTPSource(
+ const sp<AMessage> ¬ify,
+ const String8& rtpParams)
+ : Source(notify),
+ mRTPParams(rtpParams),
+ mFlags(0),
+ mState(DISCONNECTED),
+ mFinalResult(OK),
+ mBuffering(false),
+ mInPreparationPhase(true),
+ mRTPConn(new ARTPConnection(ARTPConnection::kViLTEConnection)),
+ mEOSTimeoutAudio(0),
+ mEOSTimeoutVideo(0),
+ mFirstAccessUnit(true),
+ mAllTracksHaveTime(false),
+ mNTPAnchorUs(-1),
+ mMediaAnchorUs(-1),
+ mLastMediaTimeUs(-1),
+ mNumAccessUnitsReceived(0),
+ mLastCVOUpdated(-1),
+ mReceivedFirstRTCPPacket(false),
+ mReceivedFirstRTPPacket(false),
+ mPausing(false),
+ mPauseGeneration(0) {
+ ALOGD("RTPSource initialized with rtpParams=%s", rtpParams.string());
+}
+
+NuPlayer::RTPSource::~RTPSource() {
+ if (mLooper != NULL) {
+ mLooper->unregisterHandler(id());
+ mLooper->unregisterHandler(mRTPConn->id());
+ mLooper->stop();
+ }
+}
+
+status_t NuPlayer::RTPSource::getBufferingSettings(
+ BufferingSettings* buffering /* nonnull */) {
+ Mutex::Autolock _l(mBufferingSettingsLock);
+ *buffering = mBufferingSettings;
+ return OK;
+}
+
+status_t NuPlayer::RTPSource::setBufferingSettings(const BufferingSettings& buffering) {
+ Mutex::Autolock _l(mBufferingSettingsLock);
+ mBufferingSettings = buffering;
+ return OK;
+}
+
+void NuPlayer::RTPSource::prepareAsync() {
+ if (mLooper == NULL) {
+ mLooper = new ALooper;
+ mLooper->setName("rtp");
+ mLooper->start();
+
+ mLooper->registerHandler(this);
+ mLooper->registerHandler(mRTPConn);
+ }
+
+ CHECK_EQ(mState, (int)DISCONNECTED);
+ mState = CONNECTING;
+
+ setParameters(mRTPParams);
+
+ TrackInfo *info = NULL;
+ unsigned i;
+ for (i = 0; i < mTracks.size(); i++) {
+ info = &mTracks.editItemAt(i);
+
+ if (info == NULL)
+ break;
+
+ AString sdp;
+ ASessionDescription::SDPStringFactory(sdp, info->mLocalIp,
+ info->mIsAudio, info->mLocalPort, info->mPayloadType, info->mAS, info->mCodecName,
+ NULL, info->mWidth, info->mHeight, info->mCVOExtMap);
+ ALOGD("RTPSource SDP =>\n%s", sdp.c_str());
+
+ sp<ASessionDescription> desc = new ASessionDescription;
+ bool isValidSdp = desc->setTo(sdp.c_str(), sdp.size());
+ ALOGV("RTPSource isValidSdp => %d", isValidSdp);
+
+ int sockRtp, sockRtcp;
+ ARTPConnection::MakeRTPSocketPair(&sockRtp, &sockRtcp, info->mLocalIp, info->mRemoteIp,
+ info->mLocalPort, info->mRemotePort, info->mSocketNetwork);
+
+ sp<AMessage> notify = new AMessage('accu', this);
+
+ ALOGV("RTPSource addStream. track-index=%d", i);
+ notify->setSize("trackIndex", i);
+ // index(i) should be started from 1. 0 is reserved for [root]
+ mRTPConn->addStream(sockRtp, sockRtcp, desc, i + 1, notify, false);
+ mRTPConn->setSelfID(info->mSelfID);
+ mRTPConn->setJbTime(
+ (info->mJbTimeMs <= 3000 && info->mJbTimeMs >= 40) ? info->mJbTimeMs : 300);
+
+ info->mRTPSocket = sockRtp;
+ info->mRTCPSocket = sockRtcp;
+ info->mFirstSeqNumInSegment = 0;
+ info->mNewSegment = true;
+ info->mAllowedStaleAccessUnits = kMaxAllowedStaleAccessUnits;
+ info->mRTPAnchor = 0;
+ info->mNTPAnchorUs = -1;
+ info->mNormalPlayTimeRTP = 0;
+ info->mNormalPlayTimeUs = 0ll;
+
+ // index(i) should be started from 1. 0 is reserved for [root]
+ info->mPacketSource = new APacketSource(desc, i + 1);
+
+ int32_t timeScale;
+ sp<MetaData> format = getTrackFormat(i, &timeScale);
+ sp<AnotherPacketSource> source = new AnotherPacketSource(format);
+
+ if (info->mIsAudio) {
+ mAudioTrack = source;
+ info->mTimeScale = 16000;
+ } else {
+ mVideoTrack = source;
+ info->mTimeScale = 90000;
+ }
+
+ info->mSource = source;
+ info->mRTPTime = 0;
+ info->mNormalPlaytimeUs = 0;
+ info->mNPTMappingValid = false;
+ }
+
+ if (mInPreparationPhase) {
+ mInPreparationPhase = false;
+ notifyPrepared();
+ }
+}
+
+void NuPlayer::RTPSource::start() {
+}
+
+void NuPlayer::RTPSource::pause() {
+ mState = PAUSED;
+}
+
+void NuPlayer::RTPSource::resume() {
+ mState = CONNECTING;
+}
+
+void NuPlayer::RTPSource::stop() {
+ if (mLooper == NULL) {
+ return;
+ }
+ sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
+
+ sp<AMessage> dummy;
+ msg->postAndAwaitResponse(&dummy);
+}
+
+status_t NuPlayer::RTPSource::feedMoreTSData() {
+ Mutex::Autolock _l(mBufferingLock);
+ return mFinalResult;
+}
+
+sp<MetaData> NuPlayer::RTPSource::getFormatMeta(bool audio) {
+ sp<AnotherPacketSource> source = getSource(audio);
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+bool NuPlayer::RTPSource::haveSufficientDataOnAllTracks() {
+ // We're going to buffer at least 2 secs worth data on all tracks before
+ // starting playback (both at startup and after a seek).
+
+ static const int64_t kMinDurationUs = 2000000ll;
+
+ int64_t mediaDurationUs = 0;
+ getDuration(&mediaDurationUs);
+ if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
+ || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
+ return true;
+ }
+
+ status_t err;
+ int64_t durationUs;
+ if (mAudioTrack != NULL
+ && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
+ < kMinDurationUs
+ && err == OK) {
+ ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
+ durationUs / 1E6);
+ return false;
+ }
+
+ if (mVideoTrack != NULL
+ && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
+ < kMinDurationUs
+ && err == OK) {
+ ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
+ durationUs / 1E6);
+ return false;
+ }
+
+ return true;
+}
+
+status_t NuPlayer::RTPSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+
+ sp<AnotherPacketSource> source = getSource(audio);
+
+ if (mState == PAUSED) {
+ ALOGV("-EWOULDBLOCK");
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!source->hasBufferAvailable(&finalResult)) {
+ if (finalResult == OK) {
+ int64_t mediaDurationUs = 0;
+ getDuration(&mediaDurationUs);
+ sp<AnotherPacketSource> otherSource = getSource(!audio);
+ status_t otherFinalResult;
+
+ // If other source already signaled EOS, this source should also signal EOS
+ if (otherSource != NULL &&
+ !otherSource->hasBufferAvailable(&otherFinalResult) &&
+ otherFinalResult == ERROR_END_OF_STREAM) {
+ source->signalEOS(ERROR_END_OF_STREAM);
+ return ERROR_END_OF_STREAM;
+ }
+
+ // If this source has detected near end, give it some time to retrieve more
+ // data before signaling EOS
+ if (source->isFinished(mediaDurationUs)) {
+ int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
+ if (eosTimeout == 0) {
+ setEOSTimeout(audio, ALooper::GetNowUs());
+ } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
+ setEOSTimeout(audio, 0);
+ source->signalEOS(ERROR_END_OF_STREAM);
+ return ERROR_END_OF_STREAM;
+ }
+ return -EWOULDBLOCK;
+ }
+
+ if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
+ // We should not enter buffering mode
+ // if any of the sources already have detected EOS.
+ // TODO: needs to be checked whether below line is needed or not.
+ // startBufferingIfNecessary();
+ }
+
+ return -EWOULDBLOCK;
+ }
+ return finalResult;
+ }
+
+ setEOSTimeout(audio, 0);
+
+ finalResult = source->dequeueAccessUnit(accessUnit);
+ if (finalResult != OK) {
+ return finalResult;
+ }
+
+ int32_t cvo;
+ if ((*accessUnit) != NULL && (*accessUnit)->meta()->findInt32("cvo", &cvo) &&
+ cvo != mLastCVOUpdated) {
+ sp<AMessage> msg = new AMessage();
+ msg->setInt32("payload-type", ARTPSource::RTP_CVO);
+ msg->setInt32("cvo", cvo);
+
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatIMSRxNotice);
+ notify->setMessage("message", msg);
+ notify->post();
+
+ ALOGV("notify cvo updated (%d)->(%d) to upper layer", mLastCVOUpdated, cvo);
+ mLastCVOUpdated = cvo;
+ }
+
+ return finalResult;
+}
+
+sp<AnotherPacketSource> NuPlayer::RTPSource::getSource(bool audio) {
+ return audio ? mAudioTrack : mVideoTrack;
+}
+
+void NuPlayer::RTPSource::setEOSTimeout(bool audio, int64_t timeout) {
+ if (audio) {
+ mEOSTimeoutAudio = timeout;
+ } else {
+ mEOSTimeoutVideo = timeout;
+ }
+}
+
+status_t NuPlayer::RTPSource::getDuration(int64_t *durationUs) {
+ *durationUs = 0ll;
+
+ int64_t audioDurationUs;
+ if (mAudioTrack != NULL
+ && mAudioTrack->getFormat()->findInt64(
+ kKeyDuration, &audioDurationUs)
+ && audioDurationUs > *durationUs) {
+ *durationUs = audioDurationUs;
+ }
+
+ int64_t videoDurationUs;
+ if (mVideoTrack != NULL
+ && mVideoTrack->getFormat()->findInt64(
+ kKeyDuration, &videoDurationUs)
+ && videoDurationUs > *durationUs) {
+ *durationUs = videoDurationUs;
+ }
+
+ return OK;
+}
+
+status_t NuPlayer::RTPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
+ ALOGV("RTPSource::seekTo=%d, mode=%d", (int)seekTimeUs, mode);
+ return OK;
+}
+
+void NuPlayer::RTPSource::schedulePollBuffering() {
+ sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
+ msg->post(kBufferingPollIntervalUs); // 1 second intervals
+}
+
+void NuPlayer::RTPSource::onPollBuffering() {
+ schedulePollBuffering();
+}
+
+bool NuPlayer::RTPSource::isRealTime() const {
+ ALOGD("RTPSource::isRealTime=%d", true);
+ return true;
+}
+
+void NuPlayer::RTPSource::onMessageReceived(const sp<AMessage> &msg) {
+ ALOGV("onMessageReceived =%d", msg->what());
+
+ switch (msg->what()) {
+ case kWhatAccessUnitComplete:
+ {
+ if (mState == CONNECTING) {
+ mState = CONNECTED;
+ }
+
+ int32_t timeUpdate;
+ //"time-update" raised from ARTPConnection::parseSR()
+ if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
+ size_t trackIndex;
+ CHECK(msg->findSize("trackIndex", &trackIndex));
+
+ uint32_t rtpTime;
+ uint64_t ntpTime;
+ CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime));
+ CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime));
+
+ onTimeUpdate(trackIndex, rtpTime, ntpTime);
+ break;
+ }
+
+ int32_t firstRTCP;
+ if (msg->findInt32("first-rtcp", &firstRTCP)) {
+ // There won't be an access unit here, it's just a notification
+ // that the data communication worked since we got the first
+ // rtcp packet.
+ ALOGV("first-rtcp");
+ break;
+ }
+
+ int32_t IMSRxNotice;
+ if (msg->findInt32("rtcp-event", &IMSRxNotice)) {
+ int32_t payloadType, feedbackType;
+ CHECK(msg->findInt32("payload-type", &payloadType));
+ CHECK(msg->findInt32("feedback-type", &feedbackType));
+
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatIMSRxNotice);
+ notify->setMessage("message", msg);
+ notify->post();
+
+ ALOGV("IMSRxNotice \t\t payload : %d feedback : %d",
+ payloadType, feedbackType);
+ break;
+ }
+
+ size_t trackIndex;
+ CHECK(msg->findSize("trackIndex", &trackIndex));
+
+ sp<ABuffer> accessUnit;
+ if (msg->findBuffer("access-unit", &accessUnit) == false) {
+ break;
+ }
+
+ int32_t damaged;
+ if (accessUnit->meta()->findInt32("damaged", &damaged)
+ && damaged) {
+ ALOGD("dropping damaged access unit.");
+ break;
+ }
+
+ // Implicitly assert on valid trackIndex here, which we ensure by
+ // never removing tracks.
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+ sp<AnotherPacketSource> source = info->mSource;
+ if (source != NULL) {
+ uint32_t rtpTime;
+ CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ /* AnotherPacketSource make an assertion if there is no ntp provided
+ RTPSource should provide ntpUs all the times.
+ if (!info->mNPTMappingValid) {
+ // This is a live stream, we didn't receive any normal
+ // playtime mapping. We won't map to npt time.
+ source->queueAccessUnit(accessUnit);
+ break;
+ }
+
+ int64_t nptUs =
+ ((double)rtpTime - (double)info->mRTPTime)
+ / info->mTimeScale
+ * 1000000ll
+ + info->mNormalPlaytimeUs;
+
+ */
+ accessUnit->meta()->setInt64("timeUs", ALooper::GetNowUs());
+
+ source->queueAccessUnit(accessUnit);
+ }
+
+ break;
+ }
+ case kWhatDisconnect:
+ {
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ if (info->mIsAudio) {
+ mAudioTrack->signalEOS(ERROR_END_OF_STREAM);
+ mAudioTrack = NULL;
+ ALOGV("mAudioTrack disconnected");
+ } else {
+ mVideoTrack->signalEOS(ERROR_END_OF_STREAM);
+ mVideoTrack = NULL;
+ ALOGV("mVideoTrack disconnected");
+ }
+
+ mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket);
+ close(info->mRTPSocket);
+ close(info->mRTCPSocket);
+ }
+
+ mTracks.clear();
+ mFirstAccessUnit = true;
+ mAllTracksHaveTime = false;
+ mNTPAnchorUs = -1;
+ mMediaAnchorUs = -1;
+ mLastMediaTimeUs = -1;
+ mNumAccessUnitsReceived = 0;
+ mReceivedFirstRTCPPacket = false;
+ mReceivedFirstRTPPacket = false;
+ mPausing = false;
+ mPauseGeneration = 0;
+
+ (new AMessage)->postReply(replyID);
+
+ break;
+ }
+ case kWhatPollBuffering:
+ break;
+ default:
+ TRESPASS();
+ }
+}
+
+void NuPlayer::RTPSource::setTargetBitrate(int32_t bitrate) {
+ mRTPConn->setTargetBitrate(bitrate);
+}
+
+void NuPlayer::RTPSource::onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
+ ALOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = %#016llx",
+ trackIndex, rtpTime, (long long)ntpTime);
+
+ // convert ntpTime in Q32 seconds to microseconds. Note: this will not lose precision
+ // because ntpTimeUs is at most 52 bits (double holds 53 bits)
+ int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ track->mRTPAnchor = rtpTime;
+ track->mNTPAnchorUs = ntpTimeUs;
+
+ if (mNTPAnchorUs < 0) {
+ mNTPAnchorUs = ntpTimeUs;
+ mMediaAnchorUs = mLastMediaTimeUs;
+ }
+
+ if (!mAllTracksHaveTime) {
+ bool allTracksHaveTime = (mTracks.size() > 0);
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *track = &mTracks.editItemAt(i);
+ if (track->mNTPAnchorUs < 0) {
+ allTracksHaveTime = false;
+ break;
+ }
+ }
+ if (allTracksHaveTime) {
+ mAllTracksHaveTime = true;
+ ALOGI("Time now established for all tracks.");
+ }
+ }
+ if (mAllTracksHaveTime && dataReceivedOnAllChannels()) {
+ // Time is now established, lets start timestamping immediately
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *trackInfo = &mTracks.editItemAt(i);
+ while (!trackInfo->mPackets.empty()) {
+ sp<ABuffer> accessUnit = *trackInfo->mPackets.begin();
+ trackInfo->mPackets.erase(trackInfo->mPackets.begin());
+
+ if (addMediaTimestamp(i, trackInfo, accessUnit)) {
+ postQueueAccessUnit(i, accessUnit);
+ }
+ }
+ }
+ }
+}
+
+bool NuPlayer::RTPSource::addMediaTimestamp(
+ int32_t trackIndex, const TrackInfo *track,
+ const sp<ABuffer> &accessUnit) {
+
+ uint32_t rtpTime;
+ CHECK(accessUnit->meta()->findInt32(
+ "rtp-time", (int32_t *)&rtpTime));
+
+ int64_t relRtpTimeUs =
+ (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll)
+ / track->mTimeScale;
+
+ int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs;
+
+ int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs;
+
+ if (mediaTimeUs > mLastMediaTimeUs) {
+ mLastMediaTimeUs = mediaTimeUs;
+ }
+
+ if (mediaTimeUs < 0) {
+ ALOGV("dropping early accessUnit.");
+ return false;
+ }
+
+ ALOGV("track %d rtpTime=%u mediaTimeUs = %lld us (%.2f secs)",
+ trackIndex, rtpTime, (long long)mediaTimeUs, mediaTimeUs / 1E6);
+
+ accessUnit->meta()->setInt64("timeUs", mediaTimeUs);
+
+ return true;
+}
+
+bool NuPlayer::RTPSource::dataReceivedOnAllChannels() {
+ TrackInfo *track;
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ track = &mTracks.editItemAt(i);
+ if (track->mPackets.empty()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void NuPlayer::RTPSource::postQueueAccessUnit(
+ size_t trackIndex, const sp<ABuffer> &accessUnit) {
+ sp<AMessage> msg = new AMessage(kWhatAccessUnit, this);
+ msg->setInt32("what", kWhatAccessUnit);
+ msg->setSize("trackIndex", trackIndex);
+ msg->setBuffer("accessUnit", accessUnit);
+ msg->post();
+}
+
+void NuPlayer::RTPSource::postQueueEOS(size_t trackIndex, status_t finalResult) {
+ sp<AMessage> msg = new AMessage(kWhatEOS, this);
+ msg->setInt32("what", kWhatEOS);
+ msg->setSize("trackIndex", trackIndex);
+ msg->setInt32("finalResult", finalResult);
+ msg->post();
+}
+
+sp<MetaData> NuPlayer::RTPSource::getTrackFormat(size_t index, int32_t *timeScale) {
+ CHECK_GE(index, 0u);
+ CHECK_LT(index, mTracks.size());
+
+ const TrackInfo &info = mTracks.itemAt(index);
+
+ *timeScale = info.mTimeScale;
+
+ return info.mPacketSource->getFormat();
+}
+
+void NuPlayer::RTPSource::onConnected() {
+ ALOGV("onConnected");
+ mState = CONNECTED;
+}
+
+void NuPlayer::RTPSource::onDisconnected(const sp<AMessage> &msg) {
+ if (mState == DISCONNECTED) {
+ return;
+ }
+
+ status_t err;
+ CHECK(msg->findInt32("result", &err));
+ CHECK_NE(err, (status_t)OK);
+
+// mLooper->unregisterHandler(mHandler->id());
+// mHandler.clear();
+
+ if (mState == CONNECTING) {
+ // We're still in the preparation phase, signal that it
+ // failed.
+ notifyPrepared(err);
+ }
+
+ mState = DISCONNECTED;
+// setError(err);
+
+}
+
+status_t NuPlayer::RTPSource::setParameter(const String8 &key, const String8 &value) {
+ ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+
+ bool isAudioKey = key.contains("audio");
+ TrackInfo *info = NULL;
+ for (unsigned i = 0; i < mTracks.size(); ++i) {
+ info = &mTracks.editItemAt(i);
+ if (info != NULL && info->mIsAudio == isAudioKey) {
+ ALOGV("setParameter: %s track (%d) found", isAudioKey ? "audio" : "video" , i);
+ break;
+ }
+ }
+
+ if (info == NULL) {
+ TrackInfo newTrackInfo;
+ newTrackInfo.mIsAudio = isAudioKey;
+ mTracks.push(newTrackInfo);
+ info = &mTracks.editTop();
+ info->mJbTimeMs = 300;
+ }
+
+ if (key == "rtp-param-mime-type") {
+ info->mMimeType = value;
+
+ const char *mime = value.string();
+ const char *delimiter = strchr(mime, '/');
+ info->mCodecName = delimiter ? (delimiter + 1) : "<none>";
+
+ ALOGV("rtp-param-mime-type: mMimeType (%s) => mCodecName (%s)",
+ info->mMimeType.string(), info->mCodecName.string());
+ } else if (key == "video-param-decoder-profile") {
+ info->mCodecProfile = atoi(value);
+ } else if (key == "video-param-decoder-level") {
+ info->mCodecLevel = atoi(value);
+ } else if (key == "video-param-width") {
+ info->mWidth = atoi(value);
+ } else if (key == "video-param-height") {
+ info->mHeight = atoi(value);
+ } else if (key == "rtp-param-local-ip") {
+ info->mLocalIp = value;
+ } else if (key == "rtp-param-local-port") {
+ info->mLocalPort = atoi(value);
+ } else if (key == "rtp-param-remote-ip") {
+ info->mRemoteIp = value;
+ } else if (key == "rtp-param-remote-port") {
+ info->mRemotePort = atoi(value);
+ } else if (key == "rtp-param-payload-type") {
+ info->mPayloadType = atoi(value);
+ } else if (key == "rtp-param-as") {
+ //AS means guaranteed bit rate that negotiated from sdp.
+ info->mAS = atoi(value);
+ } else if (key == "rtp-param-rtp-timeout") {
+ } else if (key == "rtp-param-rtcp-timeout") {
+ } else if (key == "rtp-param-time-scale") {
+ } else if (key == "rtp-param-self-id") {
+ info->mSelfID = atoi(value);
+ } else if (key == "rtp-param-ext-cvo-extmap") {
+ info->mCVOExtMap = atoi(value);
+ } else if (key == "rtp-param-set-socket-network") {
+ int64_t networkHandle = atoll(value);
+ setSocketNetwork(networkHandle);
+ } else if (key == "rtp-param-jitter-buffer-time") {
+ info->mJbTimeMs = atoi(value);
+ }
+
+ return OK;
+}
+
+status_t NuPlayer::RTPSource::setParameters(const String8 ¶ms) {
+ ALOGV("setParameters: %s", params.string());
+ const char *cparams = params.string();
+ const char *key_start = cparams;
+ for (;;) {
+ const char *equal_pos = strchr(key_start, '=');
+ if (equal_pos == NULL) {
+ ALOGE("Parameters %s miss a value", cparams);
+ return BAD_VALUE;
+ }
+ String8 key(key_start, equal_pos - key_start);
+ TrimString(&key);
+ if (key.length() == 0) {
+ ALOGE("Parameters %s contains an empty key", cparams);
+ return BAD_VALUE;
+ }
+ const char *value_start = equal_pos + 1;
+ const char *semicolon_pos = strchr(value_start, ';');
+ String8 value;
+ if (semicolon_pos == NULL) {
+ value.setTo(value_start);
+ } else {
+ value.setTo(value_start, semicolon_pos - value_start);
+ }
+ if (setParameter(key, value) != OK) {
+ return BAD_VALUE;
+ }
+ if (semicolon_pos == NULL) {
+ break; // Reaches the end
+ }
+ key_start = semicolon_pos + 1;
+ }
+ return OK;
+}
+
+void NuPlayer::RTPSource::setSocketNetwork(int64_t networkHandle) {
+ ALOGV("setSocketNetwork: %llu", (unsigned long long)networkHandle);
+
+ TrackInfo *info = NULL;
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ info = &mTracks.editItemAt(i);
+
+ if (info == NULL)
+ break;
+
+ info->mSocketNetwork = networkHandle;
+ }
+}
+
+// Trim both leading and trailing whitespace from the given string.
+//static
+void NuPlayer::RTPSource::TrimString(String8 *s) {
+ size_t num_bytes = s->bytes();
+ const char *data = s->string();
+
+ size_t leading_space = 0;
+ while (leading_space < num_bytes && isspace(data[leading_space])) {
+ ++leading_space;
+ }
+
+ size_t i = num_bytes;
+ while (i > leading_space && isspace(data[i - 1])) {
+ --i;
+ }
+
+ s->setTo(String8(&data[leading_space], i - leading_space));
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.h b/media/libmediaplayerservice/nuplayer/RTPSource.h
new file mode 100644
index 0000000..3b4f9e9
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RTP_SOURCE_H_
+
+#define RTP_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/Utils.h>
+#include <media/BufferingSettings.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+
+#include "AnotherPacketSource.h"
+#include "APacketSource.h"
+#include "ARTPConnection.h"
+#include "ARTPSource.h"
+#include "ASessionDescription.h"
+#include "NuPlayerSource.h"
+
+
+
+
+
+
+namespace android {
+
+struct ALooper;
+struct AnotherPacketSource;
+
+struct NuPlayer::RTPSource : public NuPlayer::Source {
+ RTPSource(
+ const sp<AMessage> ¬ify,
+ const String8& rtpParams);
+
+ virtual status_t getBufferingSettings(
+ BufferingSettings* buffering /* nonnull */) override;
+ virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
+
+ virtual void prepareAsync();
+ virtual void start();
+ virtual void stop();
+ virtual void pause();
+ virtual void resume();
+
+ virtual status_t feedMoreTSData();
+
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+ virtual status_t getDuration(int64_t *durationUs);
+ virtual status_t seekTo(
+ int64_t seekTimeUs,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) override;
+
+ virtual bool isRealTime() const;
+
+ void onMessageReceived(const sp<AMessage> &msg);
+
+ virtual void setTargetBitrate(int32_t bitrate) override;
+
+protected:
+ virtual ~RTPSource();
+
+ virtual sp<MetaData> getFormatMeta(bool audio);
+
+private:
+ enum {
+ kWhatAccessUnit = 'accU',
+ kWhatAccessUnitComplete = 'accu',
+ kWhatDisconnect = 'disc',
+ kWhatEOS = 'eos!',
+ kWhatPollBuffering = 'poll',
+ kWhatSetBufferingSettings = 'sBuS',
+ };
+
+ const int64_t kBufferingPollIntervalUs = 1000000ll;
+
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ PAUSED,
+ };
+
+ struct TrackInfo {
+
+ /* SDP of track */
+ bool mIsAudio;
+ int32_t mPayloadType;
+ String8 mMimeType;
+ String8 mCodecName;
+ int32_t mCodecProfile;
+ int32_t mCodecLevel;
+ int32_t mWidth;
+ int32_t mHeight;
+ String8 mLocalIp;
+ String8 mRemoteIp;
+ int32_t mLocalPort;
+ int32_t mRemotePort;
+ int64_t mSocketNetwork;
+ int32_t mTimeScale;
+ int32_t mAS;
+
+ /* RTP jitter buffer time in milliseconds */
+ uint32_t mJbTimeMs;
+ /* Unique ID indicates itself */
+ uint32_t mSelfID;
+ /* extmap:<value> for CVO will be set to here */
+ int32_t mCVOExtMap;
+
+ /* a copy of TrackInfo in RTSPSource */
+ sp<AnotherPacketSource> mSource;
+ uint32_t mRTPTime;
+ int64_t mNormalPlaytimeUs;
+ bool mNPTMappingValid;
+
+ /* a copy of TrackInfo in MyHandler.h */
+ int mRTPSocket;
+ int mRTCPSocket;
+ uint32_t mFirstSeqNumInSegment;
+ bool mNewSegment;
+ int32_t mAllowedStaleAccessUnits;
+ uint32_t mRTPAnchor;
+ int64_t mNTPAnchorUs;
+ bool mEOSReceived;
+ uint32_t mNormalPlayTimeRTP;
+ int64_t mNormalPlayTimeUs;
+ sp<APacketSource> mPacketSource;
+ List<sp<ABuffer>> mPackets;
+ };
+
+ const String8 mRTPParams;
+ uint32_t mFlags;
+ State mState;
+ status_t mFinalResult;
+
+ // below 3 parameters need to be checked whether it needed or not.
+ Mutex mBufferingLock;
+ bool mBuffering;
+ bool mInPreparationPhase;
+ Mutex mBufferingSettingsLock;
+ BufferingSettings mBufferingSettings;
+
+ sp<ALooper> mLooper;
+
+ sp<ARTPConnection> mRTPConn;
+
+ Vector<TrackInfo> mTracks;
+ sp<AnotherPacketSource> mAudioTrack;
+ sp<AnotherPacketSource> mVideoTrack;
+
+ int64_t mEOSTimeoutAudio;
+ int64_t mEOSTimeoutVideo;
+
+ /* MyHandler.h */
+ bool mFirstAccessUnit;
+ bool mAllTracksHaveTime;
+ int64_t mNTPAnchorUs;
+ int64_t mMediaAnchorUs;
+ int64_t mLastMediaTimeUs;
+ int64_t mNumAccessUnitsReceived;
+ int32_t mLastCVOUpdated;
+ bool mReceivedFirstRTCPPacket;
+ bool mReceivedFirstRTPPacket;
+ bool mPausing;
+ int32_t mPauseGeneration;
+
+ sp<AnotherPacketSource> getSource(bool audio);
+
+ /* MyHandler.h */
+ void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime);
+ bool addMediaTimestamp(int32_t trackIndex, const TrackInfo *track,
+ const sp<ABuffer> &accessUnit);
+ bool dataReceivedOnAllChannels();
+ void postQueueAccessUnit(size_t trackIndex, const sp<ABuffer> &accessUnit);
+ void postQueueEOS(size_t trackIndex, status_t finalResult);
+ sp<MetaData> getTrackFormat(size_t index, int32_t *timeScale);
+ void onConnected();
+ void onDisconnected(const sp<AMessage> &msg);
+
+ void schedulePollBuffering();
+ void onPollBuffering();
+
+ bool haveSufficientDataOnAllTracks();
+
+ void setEOSTimeout(bool audio, int64_t timeout);
+
+ status_t setParameters(const String8 ¶ms);
+ status_t setParameter(const String8 &key, const String8 &value);
+ void setSocketNetwork(int64_t networkHandle);
+ static void TrimString(String8 *s);
+
+ DISALLOW_EVIL_CONSTRUCTORS(RTPSource);
+};
+
+} // namespace android
+
+#endif // RTP_SOURCE_H_
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index e845c33..98626fd 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmediaplayerservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libmediaplayerservice_license",
+ ],
+}
+
cc_test {
name: "DrmSessionManager_test",
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
index 5a52ea5..b84d64b 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmediaplayerservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libmediaplayerservice_license",
+ ],
+}
+
cc_test {
name: "StagefrightRecorderTest",
gtest: true,
@@ -23,26 +34,47 @@
],
include_dirs: [
- "system/media/audio/include",
- "frameworks/av/include",
- "frameworks/av/camera/include",
"frameworks/av/media/libmediaplayerservice",
- "frameworks/av/media/libmediametrics/include",
- "frameworks/av/media/ndk/include",
+ ],
+
+ static_libs: [
+ "libmediaplayerservice",
+ "libstagefright_httplive",
+ "libstagefright_rtsp",
],
shared_libs: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.omx@1.0",
+ "libbase",
+ "libandroid_net",
+ "libaudioclient",
+ "libbinder",
+ "libcamera_client",
+ "libcodec2_client",
+ "libcrypto",
+ "libcutils",
+ "libdatasource",
+ "libdl",
+ "libdrmframework",
+ "libgui",
+ "libhidlbase",
"liblog",
"libmedia",
- "libbinder",
- "libutils",
- "libmediaplayerservice",
- "libstagefright",
+ "libmedia_codeclist",
+ "libmedia_omx",
+ "libmediadrm",
"libmediandk",
+ "libmediametrics",
+ "libmediautils",
+ "libmemunreachable",
+ "libnetd_client",
+ "libpowermanager",
+ "libstagefright",
+ "libstagefright_foundation",
+ "libutils",
],
- compile_multilib: "32",
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/AndroidTest.xml b/media/libmediaplayerservice/tests/stagefrightRecorder/AndroidTest.xml
new file mode 100644
index 0000000..427026d
--- /dev/null
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Test module config for StagefrightRecorder unit tests">
+ <option name="test-suite-tag" value="StagefrightRecorderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ <option name="force-root" value="true" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push"
+ value="StagefrightRecorderTest->/data/local/tmp/StagefrightRecorderTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="StagefrightRecorderTest" />
+ </test>
+</configuration>
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
index ac17ef3..5751631 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
@@ -29,7 +29,7 @@
#include <MediaPlayerService.h>
#include <media/NdkMediaExtractor.h>
#include <media/stagefright/MediaCodec.h>
-#include <system/audio-base.h>
+#include <system/audio.h>
#include "StagefrightRecorder.h"
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
index f948bd8..9375e4e 100644
--- a/media/libmediatranscoding/Android.bp
+++ b/media/libmediatranscoding/Android.bp
@@ -15,6 +15,15 @@
*/
// AIDL interfaces of MediaTranscoding.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
aidl_interface {
name: "mediatranscoding_aidl_interface",
unstable: true,
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index 8191b00..17a43df 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests for libmediatranscoding.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libmediatranscoding_test_defaults",
@@ -45,4 +54,4 @@
defaults: ["libmediatranscoding_test_defaults"],
srcs: ["AdjustableMaxPriorityQueue_tests.cpp"],
-}
\ No newline at end of file
+}
diff --git a/media/libnbaio/Android.bp b/media/libnbaio/Android.bp
index 04ddcff..e9422cc 100644
--- a/media/libnbaio/Android.bp
+++ b/media/libnbaio/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libnbaio_mono_defaults",
srcs: [
diff --git a/media/libnblog/Android.bp b/media/libnblog/Android.bp
index 1188320..8cfece6 100644
--- a/media/libnblog/Android.bp
+++ b/media/libnblog/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libnblog",
diff --git a/media/libnblog/ReportPerformance.cpp b/media/libnblog/ReportPerformance.cpp
index aa678ba..4c78b01 100644
--- a/media/libnblog/ReportPerformance.cpp
+++ b/media/libnblog/ReportPerformance.cpp
@@ -92,8 +92,8 @@
(*dataJson)["threadNum"] = item.first;
root.append(*dataJson);
}
- Json::StyledWriter writer;
- std::string rootStr = writer.write(root);
+ Json::StreamWriterBuilder factory;
+ std::string rootStr = Json::writeString(factory, root);
write(fd, rootStr.c_str(), rootStr.size());
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ffe3052..224ec8b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -564,6 +564,7 @@
mShutdownInProgress(false),
mExplicitShutdown(false),
mIsLegacyVP9Decoder(false),
+ mIsStreamCorruptFree(false),
mIsLowLatency(false),
mEncoderDelay(0),
mEncoderPadding(0),
@@ -2339,6 +2340,12 @@
mChannelMaskPresent = false;
}
+ int32_t isCorruptFree = 0;
+ if (msg->findInt32("corrupt-free", &isCorruptFree)) {
+ mIsStreamCorruptFree = isCorruptFree == 1 ? true : false;
+ ALOGV("corrupt-free=[%d]", mIsStreamCorruptFree);
+ }
+
int32_t maxInputSize;
if (msg->findInt32("max-input-size", &maxInputSize)) {
err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
@@ -4164,6 +4171,29 @@
ALOGI("setupVideoEncoder succeeded");
}
+ // Video should be encoded as stand straight because RTP protocol
+ // can provide rotation information only if CVO is supported.
+ // This needs to be added to support non-CVO case for video streaming scenario.
+ int32_t rotation = 0;
+ if (msg->findInt32("rotation-degrees", &rotation)) {
+ OMX_CONFIG_ROTATIONTYPE config;
+ InitOMXParams(&config);
+ config.nPortIndex = kPortIndexOutput;
+ status_t err = mOMXNode->getConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigCommonRotate, &config, sizeof(config));
+ if (err != OK) {
+ ALOGW("Failed to getConfig of OMX_IndexConfigCommonRotate(err %d)", err);
+ }
+ config.nRotation = rotation;
+ err = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigCommonRotate, &config, sizeof(config));
+
+ ALOGD("Applying encoder-rotation=[%d] to video encoder.", config.nRotation);
+ if (err != OK) {
+ ALOGW("Failed to setConfig of OMX_IndexConfigCommonRotate(err %d)", err);
+ }
+ }
+
return err;
}
@@ -5320,6 +5350,34 @@
if (mChannelMaskPresent) {
notify->setInt32("channel-mask", mChannelMask);
}
+
+ if (!mIsEncoder && portIndex == kPortIndexOutput) {
+ AString mime;
+ if (mConfigFormat->findString("mime", &mime)
+ && !strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime.c_str())) {
+
+ OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE presentation;
+ InitOMXParams(&presentation);
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
+ &presentation, sizeof(presentation));
+ if (err != OK) {
+ return err;
+ }
+ notify->setInt32("aac-encoded-target-level",
+ presentation.nEncodedTargetLevel);
+ notify->setInt32("aac-drc-cut-level", presentation.nDrcCut);
+ notify->setInt32("aac-drc-boost-level", presentation.nDrcBoost);
+ notify->setInt32("aac-drc-heavy-compression",
+ presentation.nHeavyCompression);
+ notify->setInt32("aac-target-ref-level",
+ presentation.nTargetReferenceLevel);
+ notify->setInt32("aac-drc-effect-type", presentation.nDrcEffectType);
+ notify->setInt32("aac-drc-album-mode", presentation.nDrcAlbumMode);
+ notify->setInt32("aac-drc-output-loudness",
+ presentation.nDrcOutputLoudness);
+ }
+ }
break;
}
@@ -5625,15 +5683,18 @@
int32_t range, standard, transfer;
convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
+ int32_t dsRange, dsStandard, dsTransfer;
+ getColorConfigFromDataSpace(dataSpace, &dsRange, &dsStandard, &dsTransfer);
+
// if some aspects are unspecified, use dataspace fields
if (range == 0) {
- range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
+ range = dsRange;
}
if (standard == 0) {
- standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
+ standard = dsStandard;
}
if (transfer == 0) {
- transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
+ transfer = dsTransfer;
}
mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event
@@ -6029,6 +6090,12 @@
return false;
}
+ if (mCodec->mIsStreamCorruptFree && data1 == (OMX_U32)OMX_ErrorStreamCorrupt) {
+ ALOGV("[%s] handle OMX_ErrorStreamCorrupt as a normal operation",
+ mCodec->mComponentName.c_str());
+ return true;
+ }
+
ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
// verify OMX component sends back an error we expect.
@@ -6136,6 +6203,13 @@
return;
}
+ int32_t cvo;
+ if (mCodec->mNativeWindow != NULL && buffer != NULL &&
+ buffer->meta()->findInt32("cvo", &cvo)) {
+ ALOGV("cvo(%d) found in buffer #%u", cvo, bufferID);
+ setNativeWindowRotation(mCodec->mNativeWindow.get(), cvo);
+ }
+
info->mStatus = BufferInfo::OWNED_BY_US;
info->mData = buffer;
@@ -6789,6 +6863,7 @@
ALOGV("onAllocateComponent");
CHECK(mCodec->mOMXNode == NULL);
+ mCodec->mFatalError = false;
sp<AMessage> notify = new AMessage(kWhatOMXMessageList, mCodec);
notify->setInt32("generation", mCodec->mNodeGeneration + 1);
@@ -7007,10 +7082,9 @@
return err;
}
- using hardware::media::omx::V1_0::utils::TWOmxNode;
err = statusFromBinderStatus(
mCodec->mGraphicBufferSource->configure(
- new TWOmxNode(mCodec->mOMXNode),
+ mCodec->mOMXNode->getHalInterface<IOmxNode>(),
static_cast<hardware::graphics::common::V1_0::Dataspace>(dataSpace)));
if (err != OK) {
ALOGE("[%s] Unable to configure for node (err %d)",
@@ -7767,6 +7841,58 @@
// Ignore errors as failure is expected for codecs that aren't video encoders.
(void)configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
+ AString mime;
+ if (!mIsEncoder
+ && (mConfigFormat->findString("mime", &mime))
+ && !strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime.c_str())) {
+ OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE presentation;
+ InitOMXParams(&presentation);
+ mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
+ &presentation, sizeof(presentation));
+ int32_t value32 = 0;
+ bool updated = false;
+ if (params->findInt32("aac-pcm-limiter-enable", &value32)) {
+ presentation.nPCMLimiterEnable = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-encoded-target-level", &value32)) {
+ presentation.nEncodedTargetLevel = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-drc-cut-level", &value32)) {
+ presentation.nDrcCut = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-drc-boost-level", &value32)) {
+ presentation.nDrcBoost = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-drc-heavy-compression", &value32)) {
+ presentation.nHeavyCompression = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-target-ref-level", &value32)) {
+ presentation.nTargetReferenceLevel = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-drc-effect-type", &value32)) {
+ presentation.nDrcEffectType = value32;
+ updated = true;
+ }
+ if (params->findInt32("aac-drc-album-mode", &value32)) {
+ presentation.nDrcAlbumMode = value32;
+ updated = true;
+ }
+ if (!params->findInt32("aac-drc-output-loudness", &value32)) {
+ presentation.nDrcOutputLoudness = value32;
+ updated = true;
+ }
+ if (updated) {
+ mOMXNode->setParameter((OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
+ &presentation, sizeof(presentation));
+ }
+ }
return setVendorParameters(params);
}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index c180edf..5d959cb 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libstagefright_headers",
export_include_dirs: ["include"],
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 9b3f420..4e34a26 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -797,7 +797,7 @@
mStartTimeUs = 0;
mNumInputBuffers = 0;
mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- mEncoderDataSpace = HAL_DATASPACE_V0_BT709;
+ mEncoderDataSpace = mBufferDataSpace = HAL_DATASPACE_V0_BT709;
if (meta) {
int64_t startTimeUs;
@@ -817,6 +817,7 @@
}
if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) {
ALOGI("Using encoder data space: %#x", mEncoderDataSpace);
+ mBufferDataSpace = mEncoderDataSpace;
}
}
@@ -1114,6 +1115,11 @@
(*buffer)->setObserver(this);
(*buffer)->add_ref();
(*buffer)->meta_data().setInt64(kKeyTime, frameTime);
+ if (mBufferDataSpace != mEncoderDataSpace) {
+ ALOGD("Data space updated to %x", mBufferDataSpace);
+ (*buffer)->meta_data().setInt32(kKeyColorSpace, mBufferDataSpace);
+ mEncoderDataSpace = mBufferDataSpace;
+ }
}
return OK;
}
@@ -1391,6 +1397,7 @@
// Find a available memory slot to store the buffer as VideoNativeMetadata.
sp<IMemory> data = *mMemoryBases.begin();
mMemoryBases.erase(mMemoryBases.begin());
+ mBufferDataSpace = buffer.mDataSpace;
ssize_t offset;
size_t size;
diff --git a/media/libstagefright/FrameCaptureProcessor.cpp b/media/libstagefright/FrameCaptureProcessor.cpp
index 96c1195..63238bc 100644
--- a/media/libstagefright/FrameCaptureProcessor.cpp
+++ b/media/libstagefright/FrameCaptureProcessor.cpp
@@ -171,6 +171,8 @@
if (err != OK) {
ALOGW("wait for fence returned err %d", err);
}
+
+ mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
return OK;
}
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 734f5bb..4ba85ba 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -43,7 +43,7 @@
namespace android {
static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
-static const size_t kRetryCount = 50; // must be >0
+static const size_t kRetryCount = 100; // must be >0
static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms
sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
index 0e4eae2..e4794dd 100644
--- a/media/libstagefright/HevcUtils.cpp
+++ b/media/libstagefright/HevcUtils.cpp
@@ -377,6 +377,54 @@
return reader.overRead() ? ERROR_MALFORMED : OK;
}
+void HevcParameterSets::FindHEVCDimensions(const sp<ABuffer> &SpsBuffer, int32_t *width, int32_t *height)
+{
+ ALOGD("FindHEVCDimensions");
+ // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.2 for reference
+ ABitReader reader(SpsBuffer->data() + 1, SpsBuffer->size() - 1);
+ // Skip sps_video_parameter_set_id
+ reader.skipBits(4);
+ uint8_t maxSubLayersMinus1 = reader.getBitsWithFallback(3, 0);
+ // Skip sps_temporal_id_nesting_flag;
+ reader.skipBits(1);
+ // Skip general profile
+ reader.skipBits(96);
+ if (maxSubLayersMinus1 > 0) {
+ bool subLayerProfilePresentFlag[8];
+ bool subLayerLevelPresentFlag[8];
+ for (int i = 0; i < maxSubLayersMinus1; ++i) {
+ subLayerProfilePresentFlag[i] = reader.getBitsWithFallback(1, 0);
+ subLayerLevelPresentFlag[i] = reader.getBitsWithFallback(1, 0);
+ }
+ // Skip reserved
+ reader.skipBits(2 * (8 - maxSubLayersMinus1));
+ for (int i = 0; i < maxSubLayersMinus1; ++i) {
+ if (subLayerProfilePresentFlag[i]) {
+ // Skip profile
+ reader.skipBits(88);
+ }
+ if (subLayerLevelPresentFlag[i]) {
+ // Skip sub_layer_level_idc[i]
+ reader.skipBits(8);
+ }
+ }
+ }
+ // Skip sps_seq_parameter_set_id
+ skipUE(&reader);
+ uint8_t chromaFormatIdc = parseUEWithFallback(&reader, 0);
+ if (chromaFormatIdc == 3) {
+ // Skip separate_colour_plane_flag
+ reader.skipBits(1);
+ }
+ skipUE(&reader);
+ skipUE(&reader);
+
+ // pic_width_in_luma_samples
+ *width = parseUEWithFallback(&reader, 0);
+ // pic_height_in_luma_samples
+ *height = parseUEWithFallback(&reader, 0);
+}
+
status_t HevcParameterSets::parsePps(
const uint8_t* data UNUSED_PARAM, size_t size UNUSED_PARAM) {
return OK;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 8f7d4bf..b2fae96 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2774,7 +2774,7 @@
// even if the file is well-formed and the primary picture is correct.
// Reserve item ids for samples + grid
- size_t numItemsToReserve = mNumTiles + (mNumTiles > 1);
+ size_t numItemsToReserve = mNumTiles + (mNumTiles > 0);
status_t err = mOwner->reserveItemId_l(numItemsToReserve, &mItemIdBase);
if (err != OK) {
return err;
@@ -4217,13 +4217,20 @@
void MPEG4Writer::Track::writeColrBox() {
ColorAspects aspects;
memset(&aspects, 0, sizeof(aspects));
+ // Color metadata may have changed.
+ sp<MetaData> meta = mSource->getFormat();
// TRICKY: using | instead of || because we want to execute all findInt32-s
- if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
- | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
- | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
- | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
+ if (meta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
+ | meta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
+ | meta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
+ | meta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
int32_t primaries, transfer, coeffs;
bool fullRange;
+ ALOGV("primaries=%s transfer=%s matrix=%s range=%s",
+ asString(aspects.mPrimaries),
+ asString(aspects.mTransfer),
+ asString(aspects.mMatrixCoeffs),
+ asString(aspects.mRange));
ColorUtils::convertCodecColorAspectsToIsoAspects(
aspects, &primaries, &transfer, &coeffs, &fullRange);
mOwner->beginBox("colr");
@@ -4233,6 +4240,8 @@
mOwner->writeInt16(coeffs);
mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
mOwner->endBox(); // colr
+ } else {
+ ALOGV("no color information");
}
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index a3a4aba..8e721d4 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -317,17 +317,31 @@
class MediaCodec::ReleaseSurface {
public:
- ReleaseSurface() {
+ explicit ReleaseSurface(uint64_t usage) {
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mSurface = new Surface(mProducer, false /* controlledByApp */);
struct ConsumerListener : public BnConsumerListener {
- void onFrameAvailable(const BufferItem&) override {}
+ ConsumerListener(const sp<IGraphicBufferConsumer> &consumer) {
+ mConsumer = consumer;
+ }
+ void onFrameAvailable(const BufferItem&) override {
+ BufferItem buffer;
+ // consume buffer
+ sp<IGraphicBufferConsumer> consumer = mConsumer.promote();
+ if (consumer != nullptr && consumer->acquireBuffer(&buffer, 0) == NO_ERROR) {
+ consumer->releaseBuffer(buffer.mSlot, buffer.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, buffer.mFence);
+ }
+ }
+
+ wp<IGraphicBufferConsumer> mConsumer;
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
};
- sp<ConsumerListener> listener{new ConsumerListener};
+ sp<ConsumerListener> listener{new ConsumerListener(mConsumer)};
mConsumer->consumerConnect(listener, false);
mConsumer->setConsumerName(String8{"MediaCodec.release"});
+ mConsumer->setConsumerUsageBits(usage);
}
const sp<Surface> &getSurface() {
@@ -1310,6 +1324,8 @@
// save msg for reset
mConfigureMsg = msg;
+ sp<AMessage> callback = mCallback;
+
status_t err;
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
@@ -1334,7 +1350,18 @@
// the configure failure is due to wrong state.
ALOGE("configure failed with err 0x%08x, resetting...", err);
- reset();
+ status_t err2 = reset();
+ if (err2 != OK) {
+ ALOGE("retrying configure: failed to reset codec (%08x)", err2);
+ break;
+ }
+ if (callback != nullptr) {
+ err2 = setCallback(callback);
+ if (err2 != OK) {
+ ALOGE("retrying configure: failed to set callback (%08x)", err2);
+ break;
+ }
+ }
}
if (!isResourceError(err)) {
break;
@@ -1443,6 +1470,8 @@
status_t MediaCodec::start() {
sp<AMessage> msg = new AMessage(kWhatStart, this);
+ sp<AMessage> callback;
+
status_t err;
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
@@ -1467,6 +1496,20 @@
ALOGE("retrying start: failed to configure codec");
break;
}
+ if (callback != nullptr) {
+ err = setCallback(callback);
+ if (err != OK) {
+ ALOGE("retrying start: failed to set callback");
+ break;
+ }
+ ALOGD("succeed to set callback for reclaim");
+ }
+ }
+
+ // Keep callback message after the first iteration if necessary.
+ if (i == 0 && mCallback != nullptr && mFlags & kFlagIsAsync) {
+ callback = mCallback;
+ ALOGD("keep callback message for reclaim");
}
sp<AMessage> response;
@@ -1938,6 +1981,22 @@
return OK;
}
+status_t MediaCodec::querySupportedVendorParameters(std::vector<std::string> *names) {
+ return mCodec->querySupportedParameters(names);
+}
+
+status_t MediaCodec::describeParameter(const std::string &name, CodecParameterDescriptor *desc) {
+ return mCodec->describeParameter(name, desc);
+}
+
+status_t MediaCodec::subscribeToVendorParameters(const std::vector<std::string> &names) {
+ return mCodec->subscribeToParameters(names);
+}
+
+status_t MediaCodec::unsubscribeFromVendorParameters(const std::vector<std::string> &names) {
+ return mCodec->unsubscribeFromParameters(names);
+}
+
void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) {
sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
msg->setMessage("notify", notify);
@@ -2201,6 +2260,8 @@
}
postPendingRepliesAndDeferredMessages(origin + ":dead");
sendErrorResponse = false;
+ } else if (!mReplyID) {
+ sendErrorResponse = false;
}
break;
}
@@ -3086,16 +3147,21 @@
break;
}
- // If we're flushing, stopping, configuring or starting but
+ // If we're flushing, configuring or starting but
// received a release request, post the reply for the pending call
// first, and consider it done. The reply token will be replaced
// after this, and we'll no longer be able to reply.
- if (mState == FLUSHING || mState == STOPPING
- || mState == CONFIGURING || mState == STARTING) {
+ if (mState == FLUSHING || mState == CONFIGURING || mState == STARTING) {
// mReply is always set if in these states.
postPendingRepliesAndDeferredMessages(
std::string("kWhatRelease:") + stateString(mState));
}
+ // If we're stopping but received a release request, post the reply
+ // for the pending call if necessary. Note that the reply may have been
+ // already posted due to an error.
+ if (mState == STOPPING && mReplyID) {
+ postPendingRepliesAndDeferredMessages("kWhatRelease:STOPPING");
+ }
if (mFlags & kFlagSawMediaServerDie) {
// It's dead, Jim. Don't expect initiateShutdown to yield
@@ -3122,7 +3188,11 @@
if (asyncNotify != nullptr) {
if (mSurface != NULL) {
if (!mReleaseSurface) {
- mReleaseSurface.reset(new ReleaseSurface);
+ uint64_t usage = 0;
+ if (mSurface->getConsumerUsage(&usage) != OK) {
+ usage = 0;
+ }
+ mReleaseSurface.reset(new ReleaseSurface(usage));
}
if (mSurface != mReleaseSurface->getSurface()) {
status_t err = connectToSurface(mReleaseSurface->getSurface());
@@ -4083,7 +4153,15 @@
}
}
}
- mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+ status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+
+ if (err == NO_INIT) {
+ ALOGE("rendering to non-initilized(obsolete) surface");
+ return err;
+ }
+ if (err != OK) {
+ ALOGI("rendring output error %d", err);
+ }
} else {
mBufferChannel->discardBuffer(buffer);
}
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index ac54fa1..799ca0d 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -209,9 +209,12 @@
ALOGD("ignored a null builder");
continue;
}
- mInitCheck = builder->buildMediaCodecList(&writer);
- if (mInitCheck != OK) {
- break;
+ auto currentCheck = builder->buildMediaCodecList(&writer);
+ if (currentCheck != OK) {
+ ALOGD("ignored failed builder");
+ continue;
+ } else {
+ mInitCheck = currentCheck;
}
}
writer.writeGlobalSettings(mGlobalSettings);
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 1395c27..876d06c 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecConstants.h>
@@ -435,6 +436,30 @@
buffer->release();
}
+status_t MediaCodecSource::setEncodingBitrate(int32_t bitRate) {
+ ALOGV("setEncodingBitrate (%d)", bitRate);
+
+ if (mEncoder == NULL) {
+ ALOGW("setEncodingBitrate (%d) : mEncoder is null", bitRate);
+ return BAD_VALUE;
+ }
+
+ sp<AMessage> params = new AMessage;
+ params->setInt32("video-bitrate", bitRate);
+
+ return mEncoder->setParameters(params);
+}
+
+status_t MediaCodecSource::requestIDRFrame() {
+ if (mEncoder == NULL) {
+ ALOGW("requestIDRFrame : mEncoder is null");
+ return BAD_VALUE;
+ } else {
+ mEncoder->requestIDRFrame();
+ return OK;
+ }
+}
+
MediaCodecSource::MediaCodecSource(
const sp<ALooper> &looper,
const sp<AMessage> &outputFormat,
@@ -744,6 +769,23 @@
memcpy(inbuf->data(), mbuf->data(), size);
if (mIsVideo) {
+ int32_t ds = 0;
+ if (mbuf->meta_data().findInt32(kKeyColorSpace, &ds)
+ && ds != HAL_DATASPACE_UNKNOWN) {
+ android_dataspace dataspace = static_cast<android_dataspace>(ds);
+ ColorUtils::convertDataSpaceToV0(dataspace);
+ ALOGD("Updating dataspace to %x", dataspace);
+ int32_t standard, transfer, range;
+ ColorUtils::getColorConfigFromDataSpace(
+ dataspace, &range, &standard, &transfer);
+ sp<AMessage> msg = new AMessage;
+ msg->setInt32(KEY_COLOR_STANDARD, standard);
+ msg->setInt32(KEY_COLOR_TRANSFER, transfer);
+ msg->setInt32(KEY_COLOR_RANGE, range);
+ msg->setInt32("android._dataspace", dataspace);
+ mEncoder->setParameters(msg);
+ }
+
// video encoder will release MediaBuffer when done
// with underlying data.
inbuf->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mbuf));
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index cab4ebd..8d9bc06 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -92,7 +92,9 @@
}
sp<MetaData> trackMeta = new MetaData;
- convertMessageToMetaData(format, trackMeta);
+ if (convertMessageToMetaData(format, trackMeta) != OK) {
+ return BAD_VALUE;
+ }
sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta);
status_t result = mWriter->addSource(newTrack);
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 050d7c2..c638507 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -50,8 +50,9 @@
mSampleTimeUs(timeUs) {
}
-NuMediaExtractor::NuMediaExtractor()
- : mTotalBitrate(-1LL),
+NuMediaExtractor::NuMediaExtractor(EntryPoint entryPoint)
+ : mEntryPoint(entryPoint),
+ mTotalBitrate(-1LL),
mDurationUs(-1LL) {
}
@@ -93,6 +94,7 @@
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
+ setEntryPointToRemoteMediaExtractor();
status_t err = OK;
if (!mCasToken.empty()) {
@@ -134,6 +136,7 @@
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
+ setEntryPointToRemoteMediaExtractor();
if (!mCasToken.empty()) {
err = mImpl->setMediaCas(mCasToken);
@@ -168,6 +171,7 @@
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
+ setEntryPointToRemoteMediaExtractor();
if (!mCasToken.empty()) {
err = mImpl->setMediaCas(mCasToken);
@@ -468,6 +472,16 @@
}
}
+void NuMediaExtractor::setEntryPointToRemoteMediaExtractor() {
+ if (mImpl == NULL) {
+ return;
+ }
+ status_t err = mImpl->setEntryPoint(mEntryPoint);
+ if (err != OK) {
+ ALOGW("Failed to set entry point with error %d.", err);
+ }
+}
+
ssize_t NuMediaExtractor::fetchAllTrackSamples(
int64_t seekTimeUs, MediaSource::ReadOptions::SeekMode mode) {
TrackInfo *minInfo = NULL;
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 25e43c2..381eb1a 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -39,6 +39,12 @@
static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
static const char *kExtractorMime = "android.media.mediaextractor.mime";
static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
+static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
+
+static const char *kEntryPointSdk = "sdk";
+static const char *kEntryPointWithJvm = "ndk-with-jvm";
+static const char *kEntryPointNoJvm = "ndk-no-jvm";
+static const char *kEntryPointOther = "other";
RemoteMediaExtractor::RemoteMediaExtractor(
MediaExtractor *extractor,
@@ -74,6 +80,9 @@
}
// what else is interesting and not already available?
}
+ // By default, we set the entry point to be "other". Clients of this
+ // class will override this value by calling setEntryPoint.
+ mMetricsItem->setCString(kExtractorEntryPoint, kEntryPointOther);
}
}
@@ -143,6 +152,28 @@
return String8(mExtractor->name());
}
+status_t RemoteMediaExtractor::setEntryPoint(EntryPoint entryPoint) {
+ const char* entryPointString;
+ switch (entryPoint) {
+ case EntryPoint::SDK:
+ entryPointString = kEntryPointSdk;
+ break;
+ case EntryPoint::NDK_WITH_JVM:
+ entryPointString = kEntryPointWithJvm;
+ break;
+ case EntryPoint::NDK_NO_JVM:
+ entryPointString = kEntryPointNoJvm;
+ break;
+ case EntryPoint::OTHER:
+ entryPointString = kEntryPointOther;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ mMetricsItem->setCString(kExtractorEntryPoint, entryPointString);
+ return OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
// static
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index c284ef7..1f569ef 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -175,6 +175,22 @@
}
}
+status_t setNativeWindowRotation(
+ ANativeWindow *nativeWindow /* nonnull */, int rotation) {
+
+ int transform = 0;
+ if ((rotation % 90) == 0) {
+ switch ((rotation / 90) & 3) {
+ case 1: transform = HAL_TRANSFORM_ROT_90; break;
+ case 2: transform = HAL_TRANSFORM_ROT_180; break;
+ case 3: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+ }
+
+ return native_window_set_buffers_transform(nativeWindow, transform);
+}
+
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) {
status_t err = NO_ERROR;
ANativeWindowBuffer* anb = NULL;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index d67874f..1c4f5ac 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1663,13 +1663,16 @@
meta->setInt32(kKeyColorMatrix, colorAspects.mMatrixCoeffs);
}
}
-
-void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
+/* Converts key and value pairs in AMessage format to MetaData format.
+ * Also checks for the presence of required keys.
+ */
+status_t convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
AString mime;
if (msg->findString("mime", &mime)) {
meta->setCString(kKeyMIMEType, mime.c_str());
} else {
- ALOGW("did not find mime type");
+ ALOGE("did not find mime type");
+ return BAD_VALUE;
}
convertMessageToMetaDataFromMappings(msg, meta);
@@ -1718,7 +1721,8 @@
meta->setInt32(kKeyWidth, width);
meta->setInt32(kKeyHeight, height);
} else {
- ALOGV("did not find width and/or height");
+ ALOGE("did not find width and/or height");
+ return BAD_VALUE;
}
int32_t sarWidth, sarHeight;
@@ -1803,14 +1807,14 @@
}
}
} else if (mime.startsWith("audio/")) {
- int32_t numChannels;
- if (msg->findInt32("channel-count", &numChannels)) {
- meta->setInt32(kKeyChannelCount, numChannels);
+ int32_t numChannels, sampleRate;
+ if (!msg->findInt32("channel-count", &numChannels) ||
+ !msg->findInt32("sample-rate", &sampleRate)) {
+ ALOGE("did not find channel-count and/or sample-rate");
+ return BAD_VALUE;
}
- int32_t sampleRate;
- if (msg->findInt32("sample-rate", &sampleRate)) {
- meta->setInt32(kKeySampleRate, sampleRate);
- }
+ meta->setInt32(kKeyChannelCount, numChannels);
+ meta->setInt32(kKeySampleRate, sampleRate);
int32_t bitsPerSample;
if (msg->findInt32("bits-per-sample", &bitsPerSample)) {
meta->setInt32(kKeyBitsPerSample, bitsPerSample);
@@ -1925,7 +1929,8 @@
}
}
} else {
- ALOGW("We need csd-2!!. %s", msg->debugString().c_str());
+ ALOGE("We need csd-2!!. %s", msg->debugString().c_str());
+ return BAD_VALUE;
}
} else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
@@ -1991,6 +1996,7 @@
ALOGI("converted %s to:", msg->debugString(0).c_str());
meta->dumpToLog();
#endif
+ return OK;
}
status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink,
@@ -2136,8 +2142,10 @@
}
info->sample_rate = srate;
- int32_t cmask = 0;
- if (!meta->findInt32(kKeyChannelMask, &cmask) || cmask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
+ int32_t rawChannelMask;
+ audio_channel_mask_t cmask = meta->findInt32(kKeyChannelMask, &rawChannelMask) ?
+ static_cast<audio_channel_mask_t>(rawChannelMask) : CHANNEL_MASK_USE_CHANNEL_ORDER;
+ if (cmask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
ALOGV("track of type '%s' does not publish channel mask", mime);
// Try a channel count instead
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 8698d33..e4fc128 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_defaults {
name: "libstagefright_bufferqueue-defaults",
double_loadable: true,
diff --git a/media/libstagefright/bqhelper/tests/Android.bp b/media/libstagefright/bqhelper/tests/Android.bp
index 2fbc3d6..86ab62a 100644
--- a/media/libstagefright/bqhelper/tests/Android.bp
+++ b/media/libstagefright/bqhelper/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_test {
name: "FrameDropper_test",
diff --git a/media/libstagefright/codecs/aacdec/Android.bp b/media/libstagefright/codecs/aacdec/Android.bp
index 46b3b8f..5ab49a7 100644
--- a/media/libstagefright/codecs/aacdec/Android.bp
+++ b/media/libstagefright/codecs/aacdec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_aacdec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_aacdec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_aacdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 2aeddd7..92ec94f 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -38,6 +38,7 @@
#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* switch for heavy compression for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */
#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0 /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS -1 /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
#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
@@ -230,6 +231,15 @@
// For seven and eight channel input streams, enable 6.1 and 7.1 channel output
aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
+ mDrcCompressMode = DRC_DEFAULT_MOBILE_DRC_HEAVY;
+ mDrcTargetRefLevel = DRC_DEFAULT_MOBILE_REF_LEVEL;
+ mDrcEncTargetLevel = DRC_DEFAULT_MOBILE_ENC_LEVEL;
+ mDrcBoostFactor = DRC_DEFAULT_MOBILE_DRC_BOOST;
+ mDrcAttenuationFactor = DRC_DEFAULT_MOBILE_DRC_CUT;
+ mDrcEffectType = DRC_DEFAULT_MOBILE_DRC_EFFECT;
+ mDrcAlbumMode = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+ mDrcOutputLoudness = DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS;
+
return status;
}
@@ -358,6 +368,27 @@
return OMX_ErrorNone;
}
+ case OMX_IndexParamAudioAndroidAacDrcPresentation:
+ {
+ OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *aacPresParams =
+ (OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *)params;
+
+ ALOGD("get OMX_IndexParamAudioAndroidAacDrcPresentation");
+
+ if (!isValidOMXParam(aacPresParams)) {
+ return OMX_ErrorBadParameter;
+ }
+ aacPresParams->nDrcEffectType = mDrcEffectType;
+ aacPresParams->nDrcAlbumMode = mDrcAlbumMode;
+ aacPresParams->nDrcBoost = mDrcBoostFactor;
+ aacPresParams->nDrcCut = mDrcAttenuationFactor;
+ aacPresParams->nHeavyCompression = mDrcCompressMode;
+ aacPresParams->nTargetReferenceLevel = mDrcTargetRefLevel;
+ aacPresParams->nEncodedTargetLevel = mDrcEncTargetLevel;
+ aacPresParams ->nDrcOutputLoudness = mDrcOutputLoudness;
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalGetParameter(index, params);
}
@@ -464,11 +495,13 @@
if (aacPresParams->nDrcEffectType >= -1) {
ALOGV("set nDrcEffectType=%d", aacPresParams->nDrcEffectType);
aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, aacPresParams->nDrcEffectType);
+ mDrcEffectType = aacPresParams->nDrcEffectType;
}
if (aacPresParams->nDrcAlbumMode >= -1) {
ALOGV("set nDrcAlbumMode=%d", aacPresParams->nDrcAlbumMode);
aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE,
aacPresParams->nDrcAlbumMode);
+ mDrcAlbumMode = aacPresParams->nDrcAlbumMode;
}
bool updateDrcWrapper = false;
if (aacPresParams->nDrcBoost >= 0) {
@@ -476,34 +509,42 @@
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR,
aacPresParams->nDrcBoost);
updateDrcWrapper = true;
+ mDrcBoostFactor = aacPresParams->nDrcBoost;
}
if (aacPresParams->nDrcCut >= 0) {
ALOGV("set nDrcCut=%d", aacPresParams->nDrcCut);
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, aacPresParams->nDrcCut);
updateDrcWrapper = true;
+ mDrcAttenuationFactor = aacPresParams->nDrcCut;
}
if (aacPresParams->nHeavyCompression >= 0) {
ALOGV("set nHeavyCompression=%d", aacPresParams->nHeavyCompression);
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY,
aacPresParams->nHeavyCompression);
updateDrcWrapper = true;
+ mDrcCompressMode = aacPresParams->nHeavyCompression;
}
if (aacPresParams->nTargetReferenceLevel >= -1) {
ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
aacPresParams->nTargetReferenceLevel);
updateDrcWrapper = true;
+ mDrcTargetRefLevel = aacPresParams->nTargetReferenceLevel;
}
if (aacPresParams->nEncodedTargetLevel >= 0) {
ALOGV("set nEncodedTargetLevel=%d", aacPresParams->nEncodedTargetLevel);
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET,
aacPresParams->nEncodedTargetLevel);
updateDrcWrapper = true;
+ mDrcEncTargetLevel = aacPresParams->nEncodedTargetLevel;
}
if (aacPresParams->nPCMLimiterEnable >= 0) {
aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE,
(aacPresParams->nPCMLimiterEnable != 0));
}
+ if (aacPresParams ->nDrcOutputLoudness != DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS) {
+ mDrcOutputLoudness = aacPresParams ->nDrcOutputLoudness;
+ }
if (updateDrcWrapper) {
mDrcWrap.update();
}
@@ -854,6 +895,11 @@
// fall through
}
+ if ( mDrcOutputLoudness != mStreamInfo->outputLoudness) {
+ ALOGD("update Loudness, before = %d, now = %d", mDrcOutputLoudness, mStreamInfo->outputLoudness);
+ mDrcOutputLoudness = mStreamInfo->outputLoudness;
+ }
+
/*
* AAC+/eAAC+ streams can be signalled in two ways: either explicitly
* or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
@@ -1201,6 +1247,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index 5bee710..9f98aa1 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -85,6 +85,17 @@
int32_t mOutputDelayRingBufferWritePos;
int32_t mOutputDelayRingBufferReadPos;
int32_t mOutputDelayRingBufferFilled;
+
+ //drc
+ int32_t mDrcCompressMode;
+ int32_t mDrcTargetRefLevel;
+ int32_t mDrcEncTargetLevel;
+ int32_t mDrcBoostFactor;
+ int32_t mDrcAttenuationFactor;
+ int32_t mDrcEffectType;
+ int32_t mDrcAlbumMode;
+ int32_t mDrcOutputLoudness;
+
bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
int32_t outputDelayRingBufferSamplesAvailable();
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index bf789c4..793125f 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_aacenc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_aacenc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_aacenc",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 6e437cf..90421b9 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -732,6 +732,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index b8e00b3..2c0954d 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -1,86 +1,20 @@
-cc_library_static {
- name: "libstagefright_amrnbdec",
- vendor_available: true,
- host_supported: true,
- min_sdk_version: "29",
-
- srcs: [
- "src/a_refl.cpp",
- "src/agc.cpp",
- "src/amrdecode.cpp",
- "src/b_cn_cod.cpp",
- "src/bgnscd.cpp",
- "src/c_g_aver.cpp",
- "src/d1035pf.cpp",
- "src/d2_11pf.cpp",
- "src/d2_9pf.cpp",
- "src/d3_14pf.cpp",
- "src/d4_17pf.cpp",
- "src/d8_31pf.cpp",
- "src/d_gain_c.cpp",
- "src/d_gain_p.cpp",
- "src/d_plsf.cpp",
- "src/d_plsf_3.cpp",
- "src/d_plsf_5.cpp",
- "src/dec_amr.cpp",
- "src/dec_gain.cpp",
- "src/dec_input_format_tab.cpp",
- "src/dec_lag3.cpp",
- "src/dec_lag6.cpp",
- "src/dtx_dec.cpp",
- "src/ec_gains.cpp",
- "src/ex_ctrl.cpp",
- "src/if2_to_ets.cpp",
- "src/int_lsf.cpp",
- "src/lsp_avg.cpp",
- "src/ph_disp.cpp",
- "src/post_pro.cpp",
- "src/preemph.cpp",
- "src/pstfilt.cpp",
- "src/qgain475_tab.cpp",
- "src/sp_dec.cpp",
- "src/wmf_to_ets.cpp",
- ],
-
- export_include_dirs: ["src"],
-
- cflags: [
- "-DOSCL_UNUSED_ARG(x)=(void)(x)",
- "-DOSCL_IMPORT_REF=",
-
- "-Werror",
- ],
-
- version_script: "exports.lds",
-
- //sanitize: {
- // misc_undefined: [
- // "signed-integer-overflow",
- // ],
- //},
-
- shared_libs: [
- "libstagefright_amrnb_common",
- "liblog",
- ],
-
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
//###############################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_amrdec",
defaults: ["libstagefright_softomx-defaults"],
srcs: ["SoftAMR.cpp"],
- local_include_dirs: ["src"],
-
cflags: [
"-DOSCL_IMPORT_REF=",
],
@@ -103,39 +37,3 @@
"libstagefright_amrnb_common",
],
}
-
-//###############################################################################
-cc_test {
- name: "libstagefright_amrnbdec_test",
- gtest: false,
- host_supported: true,
-
- srcs: ["test/amrnbdec_test.cpp"],
-
- cflags: ["-Wall", "-Werror"],
-
- local_include_dirs: ["src"],
-
- static_libs: [
- "libstagefright_amrnbdec",
- "libsndfile",
- ],
-
- shared_libs: [
- "libstagefright_amrnb_common",
- "libaudioutils",
- "liblog",
- ],
-
- target: {
- darwin: {
- enabled: false,
- },
- },
-
- //sanitize: {
- // misc_undefined: [
- // "signed-integer-overflow",
- // ],
- //},
-}
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index cdfc03a..01da3f8 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -576,6 +576,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index ff9a720..6bf2d39 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -1,105 +1,21 @@
-cc_library_static {
- name: "libstagefright_amrnbenc",
- vendor_available: true,
- min_sdk_version: "29",
-
- srcs: [
- "src/amrencode.cpp",
- "src/autocorr.cpp",
- "src/c1035pf.cpp",
- "src/c2_11pf.cpp",
- "src/c2_9pf.cpp",
- "src/c3_14pf.cpp",
- "src/c4_17pf.cpp",
- "src/c8_31pf.cpp",
- "src/calc_cor.cpp",
- "src/calc_en.cpp",
- "src/cbsearch.cpp",
- "src/cl_ltp.cpp",
- "src/cod_amr.cpp",
- "src/convolve.cpp",
- "src/cor_h.cpp",
- "src/cor_h_x.cpp",
- "src/cor_h_x2.cpp",
- "src/corrwght_tab.cpp",
- "src/dtx_enc.cpp",
- "src/enc_lag3.cpp",
- "src/enc_lag6.cpp",
- "src/enc_output_format_tab.cpp",
- "src/ets_to_if2.cpp",
- "src/ets_to_wmf.cpp",
- "src/g_adapt.cpp",
- "src/g_code.cpp",
- "src/g_pitch.cpp",
- "src/gain_q.cpp",
- "src/hp_max.cpp",
- "src/inter_36.cpp",
- "src/inter_36_tab.cpp",
- "src/l_comp.cpp",
- "src/l_extract.cpp",
- "src/l_negate.cpp",
- "src/lag_wind.cpp",
- "src/lag_wind_tab.cpp",
- "src/levinson.cpp",
- "src/lpc.cpp",
- "src/ol_ltp.cpp",
- "src/p_ol_wgh.cpp",
- "src/pitch_fr.cpp",
- "src/pitch_ol.cpp",
- "src/pre_big.cpp",
- "src/pre_proc.cpp",
- "src/prm2bits.cpp",
- "src/q_gain_c.cpp",
- "src/q_gain_p.cpp",
- "src/qgain475.cpp",
- "src/qgain795.cpp",
- "src/qua_gain.cpp",
- "src/s10_8pf.cpp",
- "src/set_sign.cpp",
- "src/sid_sync.cpp",
- "src/sp_enc.cpp",
- "src/spreproc.cpp",
- "src/spstproc.cpp",
- "src/ton_stab.cpp",
- ],
-
- header_libs: ["libstagefright_headers"],
- export_include_dirs: ["src"],
-
- cflags: [
- "-DOSCL_UNUSED_ARG(x)=(void)(x)",
- "-Werror",
- ],
-
- version_script: "exports.lds",
-
- //addressing b/25409744
- //sanitize: {
- // misc_undefined: [
- // "signed-integer-overflow",
- // ],
- //},
-
- shared_libs: ["libstagefright_amrnb_common"],
-
- host_supported: true,
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
//###############################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_amrnbenc",
defaults: ["libstagefright_softomx-defaults"],
srcs: ["SoftAMRNBEncoder.cpp"],
- local_include_dirs: ["src"],
-
//addressing b/25409744
//sanitize: {
// misc_undefined: [
@@ -113,27 +29,3 @@
"libstagefright_amrnb_common",
],
}
-
-//###############################################################################
-
-cc_test {
- name: "libstagefright_amrnbenc_test",
- gtest: false,
-
- srcs: ["test/amrnb_enc_test.cpp"],
-
- cflags: ["-Wall", "-Werror"],
-
- local_include_dirs: ["src"],
-
- static_libs: ["libstagefright_amrnbenc"],
-
- shared_libs: ["libstagefright_amrnb_common"],
-
- //addressing b/25409744
- //sanitize: {
- // misc_undefined: [
- // "signed-integer-overflow",
- // ],
- //},
-}
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index 85ab64e..a1f6686 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -421,6 +421,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrwb/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrwb/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/media/libstagefright/codecs/amrwb/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/media/libstagefright/codecs/amrwb/NOTICE b/media/libstagefright/codecs/amrwb/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/media/libstagefright/codecs/amrwb/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/media/libstagefright/codecs/amrwb/patent_disclaimer.txt b/media/libstagefright/codecs/amrwb/patent_disclaimer.txt
deleted file mode 100644
index b4bf11d..0000000
--- a/media/libstagefright/codecs/amrwb/patent_disclaimer.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-THIS IS NOT A GRANT OF PATENT RIGHTS.
-
-Google makes no representation or warranty that the codecs for which
-source code is made available hereunder are unencumbered by
-third-party patents. Those intending to use this source code in
-hardware or software products are advised that implementations of
-these codecs, including in open source software or shareware, may
-require patent licenses from the relevant patent holders.
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index 70c672d..00e7bc9 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -1,153 +1,13 @@
-cc_library_static {
- name: "libstagefright_amrwbenc",
- vendor_available: true,
- min_sdk_version: "29",
- srcs: [
- "src/autocorr.c",
- "src/az_isp.c",
- "src/bits.c",
- "src/c2t64fx.c",
- "src/c4t64fx.c",
- "src/convolve.c",
- "src/cor_h_x.c",
- "src/decim54.c",
- "src/deemph.c",
- "src/dtx.c",
- "src/g_pitch.c",
- "src/gpclip.c",
- "src/homing.c",
- "src/hp400.c",
- "src/hp50.c",
- "src/hp6k.c",
- "src/hp_wsp.c",
- "src/int_lpc.c",
- "src/isp_az.c",
- "src/isp_isf.c",
- "src/lag_wind.c",
- "src/levinson.c",
- "src/log2.c",
- "src/lp_dec2.c",
- "src/math_op.c",
- "src/oper_32b.c",
- "src/p_med_ol.c",
- "src/pit_shrp.c",
- "src/pitch_f4.c",
- "src/pred_lt4.c",
- "src/preemph.c",
- "src/q_gain2.c",
- "src/q_pulse.c",
- "src/qisf_ns.c",
- "src/qpisf_2s.c",
- "src/random.c",
- "src/residu.c",
- "src/scale.c",
- "src/stream.c",
- "src/syn_filt.c",
- "src/updt_tar.c",
- "src/util.c",
- "src/voAMRWBEnc.c",
- "src/voicefac.c",
- "src/wb_vad.c",
- "src/weight_a.c",
- "src/mem_align.c",
- ],
-
- arch: {
- arm: {
- srcs: [
- "src/asm/ARMV5E/convolve_opt.s",
- "src/asm/ARMV5E/cor_h_vec_opt.s",
- "src/asm/ARMV5E/Deemph_32_opt.s",
- "src/asm/ARMV5E/Dot_p_opt.s",
- "src/asm/ARMV5E/Filt_6k_7k_opt.s",
- "src/asm/ARMV5E/Norm_Corr_opt.s",
- "src/asm/ARMV5E/pred_lt4_1_opt.s",
- "src/asm/ARMV5E/residu_asm_opt.s",
- "src/asm/ARMV5E/scale_sig_opt.s",
- "src/asm/ARMV5E/Syn_filt_32_opt.s",
- "src/asm/ARMV5E/syn_filt_opt.s",
- ],
-
- cflags: [
- "-DARM",
- "-DASM_OPT",
- ],
- local_include_dirs: ["src/asm/ARMV5E"],
-
- instruction_set: "arm",
-
- neon: {
- exclude_srcs: [
- "src/asm/ARMV5E/convolve_opt.s",
- "src/asm/ARMV5E/cor_h_vec_opt.s",
- "src/asm/ARMV5E/Deemph_32_opt.s",
- "src/asm/ARMV5E/Dot_p_opt.s",
- "src/asm/ARMV5E/Filt_6k_7k_opt.s",
- "src/asm/ARMV5E/Norm_Corr_opt.s",
- "src/asm/ARMV5E/pred_lt4_1_opt.s",
- "src/asm/ARMV5E/residu_asm_opt.s",
- "src/asm/ARMV5E/scale_sig_opt.s",
- "src/asm/ARMV5E/Syn_filt_32_opt.s",
- "src/asm/ARMV5E/syn_filt_opt.s",
- ],
-
- srcs: [
- "src/asm/ARMV7/convolve_neon.s",
- "src/asm/ARMV7/cor_h_vec_neon.s",
- "src/asm/ARMV7/Deemph_32_neon.s",
- "src/asm/ARMV7/Dot_p_neon.s",
- "src/asm/ARMV7/Filt_6k_7k_neon.s",
- "src/asm/ARMV7/Norm_Corr_neon.s",
- "src/asm/ARMV7/pred_lt4_1_neon.s",
- "src/asm/ARMV7/residu_asm_neon.s",
- "src/asm/ARMV7/scale_sig_neon.s",
- "src/asm/ARMV7/Syn_filt_32_neon.s",
- "src/asm/ARMV7/syn_filt_neon.s",
- ],
-
- // don't actually generate neon instructions, see bug 26932980
- cflags: [
- "-DARMV7",
- "-mfpu=vfpv3",
- ],
- local_include_dirs: [
- "src/asm/ARMV5E",
- "src/asm/ARMV7",
- ],
- },
-
- },
- },
-
- include_dirs: [
- "frameworks/av/include",
- "frameworks/av/media/libstagefright/include",
- ],
-
- local_include_dirs: ["src"],
- export_include_dirs: ["inc"],
-
- shared_libs: [
- "libstagefright_enc_common",
- "liblog",
- ],
-
- cflags: ["-Werror"],
- sanitize: {
- cfi: true,
- },
-
- host_supported: true,
- target: {
- darwin: {
- enabled: false,
- },
- },
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
}
-//###############################################################################
-
cc_library_shared {
name: "libstagefright_soft_amrwbenc",
defaults: ["libstagefright_softomx-defaults"],
@@ -169,4 +29,3 @@
"libstagefright_enc_common",
],
}
-
diff --git a/media/libstagefright/codecs/amrwbenc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrwbenc/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/media/libstagefright/codecs/amrwbenc/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/media/libstagefright/codecs/amrwbenc/NOTICE b/media/libstagefright/codecs/amrwbenc/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/media/libstagefright/codecs/amrwbenc/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
deleted file mode 100644
index 9442fc4..0000000
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-cc_test {
- name: "AMRWBEncTest",
- gtest: false,
-
- srcs: ["AMRWB_E_SAMPLE.c"],
-
- cflags: ["-Wall", "-Werror"],
-
- arch: {
- arm: {
- instruction_set: "arm",
- },
- },
-
- shared_libs: [
- "libdl",
- "liblog",
- ],
-
- static_libs: [
- "libstagefright_amrwbenc",
- "libstagefright_enc_common",
- ],
-
- sanitize: {
- cfi: true,
- },
-}
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 7fb8a4c..657a5ce 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -476,6 +476,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 0bb6bb0..1c2f9be 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_avcdec",
defaults: ["libstagefright_softomx-defaults"],
@@ -16,6 +25,9 @@
"signed-integer-overflow",
],
cfi: true,
+ config: {
+ cfi_assembly_support: true,
+ },
},
ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 5a4b2f8..3891f23 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -724,6 +724,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index 980261c..586088c 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_avcenc",
defaults: ["libstagefright_softomx-defaults"],
@@ -10,6 +19,9 @@
"signed-integer-overflow",
],
cfi: true,
+ config: {
+ cfi_assembly_support: true,
+ },
},
cflags: [
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 9db6465..01174c9 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -1507,6 +1507,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/common/Android.bp b/media/libstagefright/codecs/common/Android.bp
index 2290722..08691e7 100644
--- a/media/libstagefright/codecs/common/Android.bp
+++ b/media/libstagefright/codecs/common/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_common_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_common_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libstagefright_enc_common",
vendor_available: true,
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 4064751..d06e0b7 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_flac_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_flac_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_flacdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 842a7ce..d6448d3 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -491,6 +491,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index f35bce1..59a4675 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_flac_enc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_flac_enc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_flacenc",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 078c8e3..24216a2 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -592,6 +592,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/g711/dec/Android.bp b/media/libstagefright/codecs/g711/dec/Android.bp
index f5357f4..1dc34c3 100644
--- a/media/libstagefright/codecs/g711/dec/Android.bp
+++ b/media/libstagefright/codecs/g711/dec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_g711_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_g711_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_g711dec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 877cb5a..fe91510 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -382,6 +382,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/gsm/dec/Android.bp b/media/libstagefright/codecs/gsm/dec/Android.bp
index 5672d89..efa2f83 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.bp
+++ b/media/libstagefright/codecs/gsm/dec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_gsm_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_gsm_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_gsmdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index d777229..330cb8a 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -354,6 +354,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/hevcdec/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index ec436ce..2c4091b 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_hevcdec",
defaults: ["libstagefright_softomx-defaults"],
@@ -17,6 +26,9 @@
"signed-integer-overflow",
],
cfi: true,
+ config: {
+ cfi_assembly_support: true,
+ },
},
// We need this because the current asm generates the following link error:
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index f6ae1f4..176da47 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -713,6 +713,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(const char *name,
const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index 7a33c54..725c79c 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -1,73 +1,19 @@
-cc_library_static {
- name: "libstagefright_m4vh263dec",
- vendor_available: true,
- apex_available: [
- "//apex_available:platform",
- "com.android.media.swcodec",
- ],
- min_sdk_version: "29",
- host_supported: true,
- shared_libs: ["liblog"],
- srcs: [
- "src/bitstream.cpp",
- "src/block_idct.cpp",
- "src/cal_dc_scaler.cpp",
- "src/combined_decode.cpp",
- "src/conceal.cpp",
- "src/datapart_decode.cpp",
- "src/dcac_prediction.cpp",
- "src/dec_pred_intra_dc.cpp",
- "src/get_pred_adv_b_add.cpp",
- "src/get_pred_outside.cpp",
- "src/idct.cpp",
- "src/idct_vca.cpp",
- "src/mb_motion_comp.cpp",
- "src/mb_utils.cpp",
- "src/packet_util.cpp",
- "src/post_filter.cpp",
- "src/pvdec_api.cpp",
- "src/scaling_tab.cpp",
- "src/vlc_decode.cpp",
- "src/vlc_dequant.cpp",
- "src/vlc_tab.cpp",
- "src/vop.cpp",
- "src/zigzag_tab.cpp",
- ],
-
- local_include_dirs: ["src"],
- export_include_dirs: ["include"],
-
- cflags: [
- "-Werror",
- ],
-
- version_script: "exports.lds",
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-
- target: {
- darwin: {
- enabled: false,
- },
- },
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
}
-//###############################################################################
-
cc_library_shared {
name: "libstagefright_soft_mpeg4dec",
defaults: ["libstagefright_softomx-defaults"],
srcs: ["SoftMPEG4.cpp"],
- local_include_dirs: ["src"],
-
cflags: [
],
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 60750d9..a4b3e2f 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -412,6 +412,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
index 13d310d..d10e40d 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
@@ -1,65 +1,20 @@
-cc_library_static {
- name: "libstagefright_m4vh263enc",
- vendor_available: true,
- apex_available: [
- "//apex_available:platform",
- "com.android.media.swcodec",
- ],
- min_sdk_version: "29",
- host_supported: true,
- target: {
- darwin: {
- enabled: false,
- },
- },
-
- srcs: [
- "src/bitstream_io.cpp",
- "src/combined_encode.cpp", "src/datapart_encode.cpp",
- "src/dct.cpp",
- "src/findhalfpel.cpp",
- "src/fastcodemb.cpp",
- "src/fastidct.cpp",
- "src/fastquant.cpp",
- "src/me_utils.cpp",
- "src/mp4enc_api.cpp",
- "src/rate_control.cpp",
- "src/motion_est.cpp",
- "src/motion_comp.cpp",
- "src/sad.cpp",
- "src/sad_halfpel.cpp",
- "src/vlc_encode.cpp",
- "src/vop.cpp",
- ],
-
- cflags: [
- "-DBX_RC",
- "-Werror",
- ],
-
- version_script: "exports.lds",
-
- local_include_dirs: ["src"],
- export_include_dirs: ["include"],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-}
-
//###############################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_mpeg4enc",
defaults: ["libstagefright_softomx-defaults"],
srcs: ["SoftMPEG4Encoder.cpp"],
- local_include_dirs: ["src"],
-
cflags: [
"-DBX_RC",
],
@@ -73,29 +28,3 @@
cfi: true,
},
}
-
-//###############################################################################
-
-cc_test {
- name: "libstagefright_m4vh263enc_test",
- gtest: false,
-
- srcs: ["test/m4v_h263_enc_test.cpp"],
-
- local_include_dirs: ["src"],
-
- cflags: [
- "-DBX_RC",
- "-Wall",
- "-Werror",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-
- static_libs: ["libstagefright_m4vh263enc"],
-}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index fa7db81..fb6c4e2 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -528,6 +528,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index 316d63c..b669c84 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -1,100 +1,19 @@
-cc_library_static {
- name: "libstagefright_mp3dec",
- vendor_available: true,
- min_sdk_version: "29",
- host_supported:true,
- srcs: [
- "src/pvmp3_normalize.cpp",
- "src/pvmp3_alias_reduction.cpp",
- "src/pvmp3_crc.cpp",
- "src/pvmp3_decode_header.cpp",
- "src/pvmp3_decode_huff_cw.cpp",
- "src/pvmp3_getbits.cpp",
- "src/pvmp3_dequantize_sample.cpp",
- "src/pvmp3_framedecoder.cpp",
- "src/pvmp3_get_main_data_size.cpp",
- "src/pvmp3_get_side_info.cpp",
- "src/pvmp3_get_scale_factors.cpp",
- "src/pvmp3_mpeg2_get_scale_data.cpp",
- "src/pvmp3_mpeg2_get_scale_factors.cpp",
- "src/pvmp3_mpeg2_stereo_proc.cpp",
- "src/pvmp3_huffman_decoding.cpp",
- "src/pvmp3_huffman_parsing.cpp",
- "src/pvmp3_tables.cpp",
- "src/pvmp3_imdct_synth.cpp",
- "src/pvmp3_mdct_6.cpp",
- "src/pvmp3_dct_6.cpp",
- "src/pvmp3_poly_phase_synthesis.cpp",
- "src/pvmp3_equalizer.cpp",
- "src/pvmp3_seek_synch.cpp",
- "src/pvmp3_stereo_proc.cpp",
- "src/pvmp3_reorder.cpp",
-
- "src/pvmp3_polyphase_filter_window.cpp",
- "src/pvmp3_mdct_18.cpp",
- "src/pvmp3_dct_9.cpp",
- "src/pvmp3_dct_16.cpp",
- ],
-
- arch: {
- arm: {
- exclude_srcs: [
- "src/pvmp3_polyphase_filter_window.cpp",
- "src/pvmp3_mdct_18.cpp",
- "src/pvmp3_dct_9.cpp",
- "src/pvmp3_dct_16.cpp",
- ],
- srcs: [
- "src/asm/pvmp3_polyphase_filter_window_gcc.s",
- "src/asm/pvmp3_mdct_18_gcc.s",
- "src/asm/pvmp3_dct_9_gcc.s",
- "src/asm/pvmp3_dct_16_gcc.s",
- ],
-
- instruction_set: "arm",
- },
- },
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-
- include_dirs: ["frameworks/av/media/libstagefright/include"],
-
- export_include_dirs: [
- "include",
- "src",
- ],
-
- cflags: [
- "-DOSCL_UNUSED_ARG(x)=(void)(x)",
- "-Werror",
- ],
-
- target: {
- darwin: {
- enabled: false,
- },
- },
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
}
-//###############################################################################
-
cc_library_shared {
name: "libstagefright_soft_mp3dec",
defaults: ["libstagefright_softomx-defaults"],
srcs: ["SoftMP3.cpp"],
- local_include_dirs: [
- "src",
- "include",
- ],
-
version_script: "exports.lds",
sanitize: {
@@ -106,35 +25,3 @@
static_libs: ["libstagefright_mp3dec"],
}
-
-//###############################################################################
-cc_test {
- name: "libstagefright_mp3dec_test",
- gtest: false,
-
- srcs: [
- "test/mp3dec_test.cpp",
- "test/mp3reader.cpp",
- ],
-
- cflags: ["-Wall", "-Werror"],
-
- local_include_dirs: [
- "src",
- "include",
- ],
-
- sanitize: {
- misc_undefined: [
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-
- static_libs: [
- "libstagefright_mp3dec",
- "libsndfile",
- ],
-
- shared_libs: ["libaudioutils"],
-}
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index b5d32ed..07bb45a 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -23,7 +23,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
-#include "include/pvmp3decoder_api.h"
+#include <pvmp3decoder_api.h>
namespace android {
@@ -498,6 +498,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.bp b/media/libstagefright/codecs/mpeg2dec/Android.bp
index e849410..abd1379 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.bp
+++ b/media/libstagefright/codecs/mpeg2dec/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_mpeg2dec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 9d5f342..9f8001f 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -864,6 +864,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/on2/dec/Android.bp b/media/libstagefright/codecs/on2/dec/Android.bp
index 82bb8d1..ba6dc2a 100644
--- a/media/libstagefright/codecs/on2/dec/Android.bp
+++ b/media/libstagefright/codecs/on2/dec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_on2_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_on2_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_vpxdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 0f2ff17..bffc23a 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -355,6 +355,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/on2/enc/Android.bp b/media/libstagefright/codecs/on2/enc/Android.bp
index 705e554..e85ff98 100644
--- a/media/libstagefright/codecs/on2/enc/Android.bp
+++ b/media/libstagefright/codecs/on2/enc/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_on2_enc_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_on2_enc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_vpxenc",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index d0cb071..e9b4341 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -775,6 +775,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/opus/dec/Android.bp b/media/libstagefright/codecs/opus/dec/Android.bp
index 71a2a0d..3d8af69 100644
--- a/media/libstagefright/codecs/opus/dec/Android.bp
+++ b/media/libstagefright/codecs/opus/dec/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_opusdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 5bb1879..dcd8dda 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -666,6 +666,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/raw/Android.bp b/media/libstagefright/codecs/raw/Android.bp
index fcc7a0a..3673786 100644
--- a/media/libstagefright/codecs/raw/Android.bp
+++ b/media/libstagefright/codecs/raw/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_raw_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_raw_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_rawdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index 0e31804..82dd171 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -273,6 +273,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.bp b/media/libstagefright/codecs/vorbis/dec/Android.bp
index 3efb952..7764294 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.bp
+++ b/media/libstagefright/codecs/vorbis/dec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_codecs_vorbis_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_codecs_vorbis_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_soft_vorbisdec",
defaults: ["libstagefright_softomx-defaults"],
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 08e20cc..3daed10 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -636,6 +636,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/xaacdec/Android.bp b/media/libstagefright/codecs/xaacdec/Android.bp
index 5385dbc..1d03c16 100644
--- a/media/libstagefright/codecs/xaacdec/Android.bp
+++ b/media/libstagefright/codecs/xaacdec/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_soft_xaacdec",
defaults: ["libstagefright_softomx-defaults"],
@@ -14,6 +23,9 @@
// integer_overflow: true,
misc_undefined: [ "signed-integer-overflow", "unsigned-integer-overflow", ],
cfi: true,
+ config: {
+ cfi_assembly_support: true,
+ },
},
static_libs: ["libxaacdec"],
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index 87e8fd4..a478642 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -1693,6 +1693,7 @@
} // namespace android
+__attribute__((cfi_canonical_jump_table))
android::SoftOMXComponent* createSoftOMXComponent(const char* name,
const OMX_CALLBACKTYPE* callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE** component) {
diff --git a/media/libstagefright/colorconversion/Android.bp b/media/libstagefright/colorconversion/Android.bp
index 6b08b08..06cebd3 100644
--- a/media/libstagefright/colorconversion/Android.bp
+++ b/media/libstagefright/colorconversion/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_colorconversion_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_colorconversion_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libstagefright_color_conversion",
diff --git a/media/libstagefright/data/Android.bp b/media/libstagefright/data/Android.bp
index 616b4b3..6da2ccb 100644
--- a/media/libstagefright/data/Android.bp
+++ b/media/libstagefright/data/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
prebuilt_etc {
name: "mediaswcodec.xml",
src: "media_codecs_sw.xml",
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index 88f30c4..acc9e87 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_static {
name: "libstagefright_mediafilter",
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index b63353c..225c930 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_flac_dec_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_flac_dec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libstagefright_flacdec",
vendor_available: true,
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/libstagefright/flac/dec/test/Android.bp
index 70ca80a..a4c2735 100644
--- a/media/libstagefright/flac/dec/test/Android.bp
+++ b/media/libstagefright/flac/dec/test/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_flac_dec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_flac_dec_license",
+ ],
+}
+
cc_test {
name: "FlacDecoderTest",
gtest: true,
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index ebf1035..407f609 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_foundation_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_foundation_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libstagefright_foundation_headers",
export_include_dirs: ["include"],
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/libstagefright/foundation/ColorUtils.cpp
index 070e325..3812afe 100644
--- a/media/libstagefright/foundation/ColorUtils.cpp
+++ b/media/libstagefright/foundation/ColorUtils.cpp
@@ -613,6 +613,35 @@
}
// static
+void ColorUtils::getColorConfigFromDataSpace(
+ const android_dataspace &dataspace, int32_t *range, int32_t *standard, int32_t *transfer) {
+ uint32_t gfxRange =
+ (dataspace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
+ uint32_t gfxStandard =
+ (dataspace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
+ uint32_t gfxTransfer =
+ (dataspace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
+
+ // assume 1-to-1 mapping to HAL values (to deal with potential vendor extensions)
+ CU::ColorRange cuRange = CU::kColorRangeUnspecified;
+ CU::ColorStandard cuStandard = CU::kColorStandardUnspecified;
+ CU::ColorTransfer cuTransfer = CU::kColorTransferUnspecified;
+ // TRICKY: use & to ensure all three mappings are completed
+ if (!(sGfxRanges.map(gfxRange, &cuRange) & sGfxStandards.map(gfxStandard, &cuStandard)
+ & sGfxTransfers.map(gfxTransfer, &cuTransfer))) {
+ ALOGW("could not safely map graphics dataspace (R:%u S:%u T:%u) to "
+ "platform color aspects (R:%u(%s) S:%u(%s) T:%u(%s)",
+ gfxRange, gfxStandard, gfxTransfer,
+ cuRange, asString(cuRange),
+ cuStandard, asString(cuStandard),
+ cuTransfer, asString(cuTransfer));
+ }
+ *range = cuRange;
+ *standard = cuStandard;
+ *transfer = cuTransfer;
+}
+
+// static
void ColorUtils::getColorConfigFromFormat(
const sp<AMessage> &format, int32_t *range, int32_t *standard, int32_t *transfer) {
if (!format->findInt32("color-range", range)) {
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h b/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
index cd0af2b..9e3f718 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
@@ -156,6 +156,10 @@
// suited to blending. This requires implicit color space conversion on part of the device.
static android_dataspace getDataSpaceForColorAspects(ColorAspects &aspects, bool mayExpand);
+ // it returns the platform color configs from given |dataspace|.
+ static void getColorConfigFromDataSpace(
+ const android_dataspace &dataspace, int *range, int *standard, int *transfer);
+
// converts |dataSpace| to a V0 enum, and returns true if dataSpace is an aspect-only value
static bool convertDataSpaceToV0(android_dataspace &dataSpace);
diff --git a/media/libstagefright/foundation/tests/AVCUtils/Android.bp b/media/libstagefright/foundation/tests/AVCUtils/Android.bp
index 5d0e481..594da56 100644
--- a/media/libstagefright/foundation/tests/AVCUtils/Android.bp
+++ b/media/libstagefright/foundation/tests/AVCUtils/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_foundation_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_foundation_license",
+ ],
+}
+
cc_test {
name: "AVCUtilsUnitTest",
gtest: true,
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
index 45e81e8..801e216 100644
--- a/media/libstagefright/foundation/tests/Android.bp
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_foundation_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_foundation_license",
+ ],
+}
+
cc_test {
name: "sf_foundation_test",
test_suites: ["device-tests"],
diff --git a/media/libstagefright/foundation/tests/OpusHeader/Android.bp b/media/libstagefright/foundation/tests/OpusHeader/Android.bp
index c1251a8..6c64ef3 100644
--- a/media/libstagefright/foundation/tests/OpusHeader/Android.bp
+++ b/media/libstagefright/foundation/tests/OpusHeader/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_foundation_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_foundation_license",
+ ],
+}
+
cc_test {
name: "OpusHeaderTest",
gtest: true,
diff --git a/media/libstagefright/foundation/tests/colorutils/Android.bp b/media/libstagefright/foundation/tests/colorutils/Android.bp
index d77f405..5a17e4b 100644
--- a/media/libstagefright/foundation/tests/colorutils/Android.bp
+++ b/media/libstagefright/foundation/tests/colorutils/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_foundation_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_foundation_license",
+ ],
+}
+
cc_test {
name: "ColorUtilsTest",
gtest: true,
diff --git a/media/libstagefright/http/Android.bp b/media/libstagefright/http/Android.bp
index 8655caf..f4d6d99 100644
--- a/media/libstagefright/http/Android.bp
+++ b/media/libstagefright/http/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_shared {
name: "libstagefright_http_support",
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index 12e7ca6..0b0acbf 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_httplive_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_httplive_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library {
name: "libstagefright_httplive",
diff --git a/media/libstagefright/id3/Android.bp b/media/libstagefright/id3/Android.bp
index e34504d..3f5ba47 100644
--- a/media/libstagefright/id3/Android.bp
+++ b/media/libstagefright/id3/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_id3_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_id3_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libstagefright_id3",
min_sdk_version: "29",
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 5509512..e97f6eb 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -813,6 +813,10 @@
baseSize = U32_AT(&mParent.mData[mOffset + 4]);
}
+ if (baseSize == 0) {
+ return;
+ }
+
// Prevent integer overflow when adding
if (SIZE_MAX - 10 <= baseSize) {
return;
diff --git a/media/libstagefright/id3/test/Android.bp b/media/libstagefright/id3/test/Android.bp
index 9d26eec..3cd8565 100644
--- a/media/libstagefright/id3/test/Android.bp
+++ b/media/libstagefright/id3/test/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_id3_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_id3_license",
+ ],
+}
+
cc_test {
name: "ID3Test",
gtest: true,
diff --git a/media/libstagefright/include/HevcUtils.h b/media/libstagefright/include/HevcUtils.h
index 0f59631..335de2f 100644
--- a/media/libstagefright/include/HevcUtils.h
+++ b/media/libstagefright/include/HevcUtils.h
@@ -90,6 +90,8 @@
// Note that this method does not write the start code.
bool write(size_t index, uint8_t* dest, size_t size);
status_t makeHvcc(uint8_t *hvcc, size_t *hvccSize, size_t nalSizeLength);
+ void FindHEVCDimensions(
+ const sp<ABuffer> &SpsBuffer, int32_t *width, int32_t *height);
Info getInfo() const { return mInfo; }
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 8ef9278..4c97b4d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -273,6 +273,7 @@
bool mShutdownInProgress;
bool mExplicitShutdown;
bool mIsLegacyVP9Decoder;
+ bool mIsStreamCorruptFree;
bool mIsLowLatency;
// If "mKeepComponentAllocated" we only transition back to Loaded state
diff --git a/media/libstagefright/include/media/stagefright/CameraSource.h b/media/libstagefright/include/media/stagefright/CameraSource.h
index 6f0d3b5..efdfa02 100644
--- a/media/libstagefright/include/media/stagefright/CameraSource.h
+++ b/media/libstagefright/include/media/stagefright/CameraSource.h
@@ -192,6 +192,7 @@
int32_t mColorFormat;
int32_t mEncoderFormat;
int32_t mEncoderDataSpace;
+ int32_t mBufferDataSpace;
status_t mInitCheck;
sp<Camera> mCamera;
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index dd6df90..2e98fec 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -61,6 +61,11 @@
using hardware::cas::native::V1_0::IDescrambler;
+struct CodecParameterDescriptor {
+ std::string name;
+ AMessage::Type type;
+};
+
struct CodecBase : public AHandler, /* static */ ColorUtils {
/**
* This interface defines events firing from CodecBase back to MediaCodec.
@@ -233,6 +238,64 @@
virtual void signalSetParameters(const sp<AMessage> &msg) = 0;
virtual void signalEndOfInputStream() = 0;
+ /**
+ * Query supported parameters from this instance, and fill |names| with the
+ * names of the parameters.
+ *
+ * \param names string vector to fill with supported parameters.
+ * \return OK if successful;
+ * BAD_VALUE if |names| is null;
+ * INVALID_OPERATION if already released;
+ * ERROR_UNSUPPORTED if not supported.
+ */
+ virtual status_t querySupportedParameters([[maybe_unused]] std::vector<std::string> *names) {
+ return ERROR_UNSUPPORTED;
+ }
+ /**
+ * Fill |desc| with description of the parameter with |name|.
+ *
+ * \param name name of the parameter to describe
+ * \param desc pointer to CodecParameterDescriptor to be filled
+ * \return OK if successful;
+ * BAD_VALUE if |desc| is null;
+ * NAME_NOT_FOUND if |name| is not recognized by the component;
+ * INVALID_OPERATION if already released;
+ * ERROR_UNSUPPORTED if not supported.
+ */
+ virtual status_t describeParameter(
+ [[maybe_unused]] const std::string &name,
+ [[maybe_unused]] CodecParameterDescriptor *desc) {
+ return ERROR_UNSUPPORTED;
+ }
+ /**
+ * Subscribe to parameters in |names| and get output format change event
+ * when they change.
+ * Unrecognized / already subscribed parameters are ignored.
+ *
+ * \param names names of parameters to subscribe
+ * \return OK if successful;
+ * INVALID_OPERATION if already released;
+ * ERROR_UNSUPPORTED if not supported.
+ */
+ virtual status_t subscribeToParameters(
+ [[maybe_unused]] const std::vector<std::string> &names) {
+ return ERROR_UNSUPPORTED;
+ }
+ /**
+ * Unsubscribe from parameters in |names| and no longer get
+ * output format change event when they change.
+ * Unrecognized / already unsubscribed parameters are ignored.
+ *
+ * \param names names of parameters to unsubscribe
+ * \return OK if successful;
+ * INVALID_OPERATION if already released;
+ * ERROR_UNSUPPORTED if not supported.
+ */
+ virtual status_t unsubscribeFromParameters(
+ [[maybe_unused]] const std::vector<std::string> &names) {
+ return ERROR_UNSUPPORTED;
+ }
+
typedef CodecBase *(*CreateCodecFunc)(void);
typedef PersistentSurface *(*CreateInputSurfaceFunc)(void);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 5ff4e12..8952376 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -50,6 +50,7 @@
struct BatteryChecker;
class BufferChannelBase;
struct CodecBase;
+struct CodecParameterDescriptor;
class IBatteryStats;
struct ICrypto;
class MediaCodecBuffer;
@@ -81,6 +82,13 @@
BUFFER_FLAG_MUXER_DATA = 16,
};
+ enum CVODegree {
+ CVO_DEGREE_0 = 0,
+ CVO_DEGREE_90 = 90,
+ CVO_DEGREE_180 = 180,
+ CVO_DEGREE_270 = 270,
+ };
+
enum {
CB_INPUT_AVAILABLE = 1,
CB_OUTPUT_AVAILABLE = 2,
@@ -239,6 +247,11 @@
status_t setParameters(const sp<AMessage> ¶ms);
+ status_t querySupportedVendorParameters(std::vector<std::string> *names);
+ status_t describeParameter(const std::string &name, CodecParameterDescriptor *desc);
+ status_t subscribeToVendorParameters(const std::vector<std::string> &names);
+ status_t unsubscribeFromVendorParameters(const std::vector<std::string> &names);
+
// Create a MediaCodec notification message from a list of rendered or dropped render infos
// by adding rendered frame information to a base notification message. Returns the number
// of frames that were rendered.
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 178d334..9793b89 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -619,6 +619,7 @@
constexpr int32_t COLOR_FormatYUV422SemiPlanar = 24;
constexpr int32_t COLOR_FormatYUV444Flexible = 0x7F444888;
constexpr int32_t COLOR_FormatYUV444Interleaved = 29;
+constexpr int32_t COLOR_FormatYUVP010 = 54;
constexpr int32_t COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00;
constexpr int32_t COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
@@ -792,7 +793,7 @@
constexpr char KEY_PCM_ENCODING[] = "pcm-encoding";
constexpr char KEY_PIXEL_ASPECT_RATIO_HEIGHT[] = "sar-height";
constexpr char KEY_PIXEL_ASPECT_RATIO_WIDTH[] = "sar-width";
-constexpr char KEY_PREPEND_HEADERS_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames";
+constexpr char KEY_PREPEND_HEADER_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames";
constexpr char KEY_PRIORITY[] = "priority";
constexpr char KEY_PROFILE[] = "profile";
constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index e681d25..78d1005 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -88,7 +88,7 @@
static sp<IMediaCodecList> sCodecList;
static sp<IMediaCodecList> sRemoteList;
- status_t mInitCheck;
+ status_t mInitCheck{NO_INIT};
sp<AMessage> mGlobalSettings;
std::vector<sp<MediaCodecInfo> > mCodecInfos;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecSource.h b/media/libstagefright/include/media/stagefright/MediaCodecSource.h
index 2f98af1..0f7b535 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecSource.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecSource.h
@@ -64,12 +64,15 @@
// MediaBufferObserver
virtual void signalBufferReturned(MediaBufferBase *buffer);
+ virtual status_t setEncodingBitrate(int32_t bitRate /* bps */);
// for AHandlerReflector
void onMessageReceived(const sp<AMessage> &msg);
+ status_t requestIDRFrame();
+
protected:
virtual ~MediaCodecSource();
diff --git a/media/libstagefright/include/media/stagefright/MediaWriter.h b/media/libstagefright/include/media/stagefright/MediaWriter.h
index 1f4fbcb..9f20185 100644
--- a/media/libstagefright/include/media/stagefright/MediaWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaWriter.h
@@ -54,6 +54,11 @@
virtual void setStartTimeOffsetMs(int /*ms*/) {}
virtual int32_t getStartTimeOffsetMs() const { return 0; }
virtual status_t setNextFd(int /*fd*/) { return INVALID_OPERATION; }
+ virtual void updateCVODegrees(int32_t /*cvoDegrees*/) {}
+ virtual void updatePayloadType(int32_t /*payloadType*/) {}
+ virtual void updateSocketNetwork(int64_t /*socketNetwork*/) {}
+ virtual uint32_t getSequenceNum() { return 0; }
+ virtual uint64_t getAccumulativeBytes() { return 0; }
protected:
virtual ~MediaWriter() {}
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 64eb8b4..6f21a80 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -247,6 +247,15 @@
// Treat empty track as malformed for MediaRecorder.
kKeyEmptyTrackMalFormed = 'nemt', // bool (int32_t)
+ kKeyVps = 'sVps', // int32_t, indicates that a buffer has vps.
+ kKeySps = 'sSps', // int32_t, indicates that a buffer has sps.
+ kKeyPps = 'sPps', // int32_t, indicates that a buffer has pps.
+ kKeySelfID = 'sfid', // int32_t, source ID to identify itself on RTP protocol.
+ kKeyPayloadType = 'pTyp', // int32_t, SDP negotiated payload type.
+ kKeyRtpExtMap = 'extm', // int32_t, rtp extension ID for cvo on RTP protocol.
+ kKeyRtpCvoDegrees = 'cvod', // int32_t, rtp cvo degrees as per 3GPP 26.114.
+ kKeyRtpDscp = 'dscp', // int32_t, DSCP(Differentiated services codepoint) of RFC 2474.
+ kKeySocketNetwork = 'sNet', // int64_t, socket will be bound to network handle.
};
enum {
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 227cead..d8f2b00 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -47,12 +47,14 @@
SAMPLE_FLAG_ENCRYPTED = 2,
};
+ typedef IMediaExtractor::EntryPoint EntryPoint;
+
// identical to IMediaExtractor::GetTrackMetaDataFlags
enum GetTrackFormatFlags {
kIncludeExtensiveMetaData = 1, // reads sample table and possibly stream headers
};
- NuMediaExtractor();
+ explicit NuMediaExtractor(EntryPoint entryPoint);
status_t setDataSource(
const sp<MediaHTTPService> &httpService,
@@ -128,6 +130,8 @@
uint32_t mTrackFlags; // bitmask of "TrackFlags"
};
+ const EntryPoint mEntryPoint;
+
mutable Mutex mLock;
sp<DataSource> mDataSource;
@@ -139,6 +143,8 @@
int64_t mTotalBitrate; // in bits/sec
int64_t mDurationUs;
+ void setEntryPointToRemoteMediaExtractor();
+
ssize_t fetchAllTrackSamples(
int64_t seekTimeUs = -1ll,
MediaSource::ReadOptions::SeekMode mode =
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 2ce7bc7..25125f2 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -42,6 +42,7 @@
virtual uint32_t flags() const;
virtual status_t setMediaCas(const HInterfaceToken &casToken);
virtual String8 name();
+ virtual status_t setEntryPoint(EntryPoint entryPoint);
private:
MediaExtractor *mExtractor;
diff --git a/media/libstagefright/include/media/stagefright/SurfaceUtils.h b/media/libstagefright/include/media/stagefright/SurfaceUtils.h
index ae55c65..35b3fa2 100644
--- a/media/libstagefright/include/media/stagefright/SurfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/SurfaceUtils.h
@@ -38,6 +38,8 @@
int width, int height, int format, int rotation, int usage, bool reconnect);
void setNativeWindowHdrMetadata(
ANativeWindow *nativeWindow /* nonnull */, HDRStaticInfo *info /* nonnull */);
+status_t setNativeWindowRotation(
+ ANativeWindow *nativeWindow /* nonnull */, int rotation);
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */);
status_t nativeWindowConnect(ANativeWindow *surface, const char *reason);
status_t nativeWindowDisconnect(ANativeWindow *surface, const char *reason);
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index 2b9b759..1673120 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -33,7 +33,7 @@
const MetaDataBase *meta, sp<AMessage> *format);
status_t convertMetaDataToMessage(
const sp<MetaData> &meta, sp<AMessage> *format);
-void convertMessageToMetaData(
+status_t convertMessageToMetaData(
const sp<AMessage> &format, sp<MetaData> &meta);
// Returns a pointer to the next NAL start code in buffer of size |length| starting at |data|, or
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index 5d697f7..a970224 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_mpeg2ts_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_mpeg2ts_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "libstagefright_mpeg2support_defaults",
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 801dba1..192ba77 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1430,7 +1430,13 @@
if (mSampleDecryptor != NULL && (nalType == 1 || nalType == 5)) {
uint8_t *nalData = mBuffer->data() + pos.nalOffset;
size_t newSize = mSampleDecryptor->processNal(nalData, pos.nalSize);
- // Note: the data can shrink due to unescaping
+ // Note: the data can shrink due to unescaping, but it can never grow
+ if (newSize > pos.nalSize) {
+ // don't log unless verbose, since this can get called a lot if
+ // the caller is trying to resynchronize
+ ALOGV("expected sample size < %u, got %zu", pos.nalSize, newSize);
+ return NULL;
+ }
memcpy(accessUnit->data() + dstOffset + 4,
nalData,
newSize);
diff --git a/media/libstagefright/mpeg2ts/test/Android.bp b/media/libstagefright/mpeg2ts/test/Android.bp
index 4e4832a..db2794f 100644
--- a/media/libstagefright/mpeg2ts/test/Android.bp
+++ b/media/libstagefright/mpeg2ts/test/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_mpeg2ts_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_mpeg2ts_license",
+ ],
+}
+
cc_test{
name: "Mpeg2tsUnitTest",
gtest: true,
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 7c372cd..54c5697 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_omx_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_omx_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libstagefright_omx",
vendor_available: true,
@@ -227,4 +246,3 @@
},
cflags: ["-Wall", "-Werror"],
}
-
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index ddb459f..44415aa 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -17,6 +17,10 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SimpleSoftOMXComponent"
#include <utils/Log.h>
+#include <OMX_Core.h>
+#include <OMX_Audio.h>
+#include <OMX_IndexExt.h>
+#include <OMX_AudioExt.h>
#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -74,7 +78,7 @@
OMX_U32 portIndex;
- switch (index) {
+ switch ((int)index) {
case OMX_IndexParamPortDefinition:
{
const OMX_PARAM_PORTDEFINITIONTYPE *portDefs =
@@ -108,6 +112,19 @@
break;
}
+ case OMX_IndexParamAudioAndroidAacDrcPresentation:
+ {
+ if (mState == OMX_StateInvalid) {
+ return false;
+ }
+ const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *aacPresParams =
+ (const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *)params;
+ if (!isValidOMXParam(aacPresParams)) {
+ return false;
+ }
+ return true;
+ }
+
default:
return false;
}
diff --git a/media/libstagefright/omx/tests/Android.bp b/media/libstagefright/omx/tests/Android.bp
index fefb3bb..83cc80e 100644
--- a/media/libstagefright/omx/tests/Android.bp
+++ b/media/libstagefright/omx/tests/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_omx_tests_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_omx_tests_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_test {
name: "omx_tests",
gtest: false,
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 4bc67e8..2f93d5d 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -25,8 +25,11 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <android-base/properties.h>
+
#include <stdint.h>
namespace android {
@@ -37,36 +40,142 @@
mAccessUnitRTPTime(0),
mNextExpectedSeqNoValid(false),
mNextExpectedSeqNo(0),
- mAccessUnitDamaged(false) {
+ mAccessUnitDamaged(false),
+ mFirstIFrameProvided(false),
+ mLastIFrameProvidedAtMs(0),
+ mWidth(0),
+ mHeight(0) {
}
AAVCAssembler::~AAVCAssembler() {
}
+int32_t AAVCAssembler::addNack(
+ const sp<ARTPSource> &source) {
+ List<sp<ABuffer>> *queue = source->queue();
+ int32_t nackCount = 0;
+
+ List<sp<ABuffer> >::iterator it = queue->begin();
+
+ if (it == queue->end()) {
+ return nackCount /* 0 */;
+ }
+
+ uint16_t queueHeadSeqNum = (*it)->int32Data();
+
+ // move to the packet after which RTCP:NACK was sent.
+ for (; it != queue->end(); ++it) {
+ int32_t seqNum = (*it)->int32Data();
+ if (seqNum >= source->mHighestNackNumber) {
+ break;
+ }
+ }
+
+ int32_t nackStartAt = -1;
+
+ while (it != queue->end()) {
+ int32_t seqBeforeLast = (*it)->int32Data();
+ // increase iterator.
+ if ((++it) == queue->end()) {
+ break;
+ }
+ int32_t seqLast = (*it)->int32Data();
+
+ if ((seqLast - seqBeforeLast) < 0) {
+ ALOGD("addNack: found end of seqNum from(%d) to(%d)", seqBeforeLast, seqLast);
+ source->mHighestNackNumber = 0;
+ }
+
+ // missed packet found
+ if (seqLast > (seqBeforeLast + 1) &&
+ // we didn't send RTCP:NACK for this packet yet.
+ (seqLast - 1) > source->mHighestNackNumber) {
+ source->mHighestNackNumber = seqLast - 1;
+ nackStartAt = seqBeforeLast + 1;
+ break;
+ }
+
+ }
+
+ if (nackStartAt != -1) {
+ nackCount = source->mHighestNackNumber - nackStartAt + 1;
+ ALOGD("addNack: nackCount=%d, nackFrom=%d, nackTo=%d", nackCount,
+ nackStartAt, source->mHighestNackNumber);
+
+ uint16_t mask = (uint16_t)(0xffff) >> (16 - nackCount + 1);
+ source->setSeqNumToNACK(nackStartAt, mask, queueHeadSeqNum);
+ }
+
+ return nackCount;
+}
+
ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
const sp<ARTPSource> &source) {
List<sp<ABuffer> > *queue = source->queue();
+ const uint32_t firstRTPTime = source->mFirstRtpTime;
if (queue->empty()) {
return NOT_ENOUGH_DATA;
}
+ sp<ABuffer> buffer = *queue->begin();
+ buffer->meta()->setObject("source", source);
+
+ int64_t rtpTime = findRTPTime(firstRTPTime, buffer);
+
+ int64_t startTime = source->mFirstSysTime / 1000;
+ int64_t nowTime = ALooper::GetNowUs() / 1000;
+ int64_t playedTime = nowTime - startTime;
+
+ int64_t playedTimeRtp = source->mFirstRtpTime + playedTime * (int64_t)source->mClockRate / 1000;
+ const int64_t jitterTime = source->mJbTimeMs * (int64_t)source->mClockRate / 1000;
+
+ int64_t expiredTimeInJb = rtpTime + jitterTime;
+ bool isExpired = expiredTimeInJb <= (playedTimeRtp);
+ bool isTooLate200 = expiredTimeInJb < (playedTimeRtp - jitterTime);
+ bool isTooLate300 = expiredTimeInJb < (playedTimeRtp - (jitterTime * 3 / 2));
+
+ if (mShowQueue && mShowQueueCnt < 20) {
+ showCurrentQueue(queue);
+ printNowTimeUs(startTime, nowTime, playedTime);
+ printRTPTime(rtpTime, playedTimeRtp, expiredTimeInJb, isExpired);
+ mShowQueueCnt++;
+ }
+
+ AAVCAssembler::addNack(source);
+
+ if (!isExpired) {
+ ALOGV("buffering in jitter buffer.");
+ return NOT_ENOUGH_DATA;
+ }
+
+ if (isTooLate200) {
+ ALOGW("=== WARNING === buffer arrived 200ms late. === WARNING === ");
+ }
+
+ if (isTooLate300) {
+ ALOGW("buffer arrived after 300ms ... \t Diff in Jb=%lld \t Seq# %d",
+ (long long)(playedTimeRtp - expiredTimeInJb), buffer->int32Data());
+ printNowTimeUs(startTime, nowTime, playedTime);
+ printRTPTime(rtpTime, playedTimeRtp, expiredTimeInJb, isExpired);
+
+ mNextExpectedSeqNo = pickProperSeq(queue, firstRTPTime, playedTimeRtp, jitterTime);
+ }
+
if (mNextExpectedSeqNoValid) {
- List<sp<ABuffer> >::iterator it = queue->begin();
- while (it != queue->end()) {
- if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
- break;
- }
+ int32_t size = queue->size();
+ int32_t cntRemove = deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
- it = queue->erase(it);
+ if (cntRemove > 0) {
+ source->noticeAbandonBuffer(cntRemove);
+ ALOGW("delete %d of %d buffers", cntRemove, size);
}
-
if (queue->empty()) {
return NOT_ENOUGH_DATA;
}
}
- sp<ABuffer> buffer = *queue->begin();
+ buffer = *queue->begin();
if (!mNextExpectedSeqNoValid) {
mNextExpectedSeqNoValid = true;
@@ -123,15 +232,72 @@
}
}
+void AAVCAssembler::checkSpsUpdated(const sp<ABuffer> &buffer) {
+ const uint8_t *data = buffer->data();
+ unsigned nalType = data[0] & 0x1f;
+ if (nalType == 0x7) {
+ int32_t width = 0, height = 0;
+ FindAVCDimensions(buffer, &width, &height);
+ if (width != mWidth || height != mHeight) {
+ mFirstIFrameProvided = false;
+ mWidth = width;
+ mHeight = height;
+ ALOGD("found a new resolution (%u x %u)", mWidth, mHeight);
+ }
+ }
+}
+
+void AAVCAssembler::checkIFrameProvided(const sp<ABuffer> &buffer) {
+ if (buffer->size() == 0) {
+ return;
+ }
+ const uint8_t *data = buffer->data();
+ unsigned nalType = data[0] & 0x1f;
+ if (nalType == 0x5) {
+ mLastIFrameProvidedAtMs = ALooper::GetNowUs() / 1000;
+ if (!mFirstIFrameProvided) {
+ mFirstIFrameProvided = true;
+
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ ALOGD("got First I-frame to be decoded. rtpTime=%d, size=%zu", rtpTime, buffer->size());
+ }
+ }
+}
+
+bool AAVCAssembler::dropFramesUntilIframe(const sp<ABuffer> &buffer) {
+ const uint8_t *data = buffer->data();
+ unsigned nalType = data[0] & 0x1f;
+ if (!mFirstIFrameProvided && nalType < 0x5) {
+ return true;
+ }
+
+ return false;
+}
+
void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
ALOGV("addSingleNALUnit of size %zu", buffer->size());
#if !LOG_NDEBUG
hexdump(buffer->data(), buffer->size());
#endif
+ checkSpsUpdated(buffer);
+ checkIFrameProvided(buffer);
+
uint32_t rtpTime;
CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ if (dropFramesUntilIframe(buffer)) {
+ sp<ARTPSource> source = nullptr;
+ buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
+ if (source != nullptr) {
+ ALOGD("Issued FIR to get the I-frame");
+ source->onIssueFIRByAssembler();
+ }
+ ALOGV("Dropping P-frame till I-frame provided. rtpTime %u", rtpTime);
+ return;
+ }
+
if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
submitAccessUnit();
}
@@ -216,6 +382,11 @@
size_t totalCount = 1;
bool complete = false;
+ uint32_t rtpTimeStartAt;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTimeStartAt));
+ uint32_t startSeqNo = buffer->int32Data();
+ bool pFrame = nalType == 0x1;
+
if (data[1] & 0x40) {
// Huh? End bit also set on the first buffer.
@@ -224,6 +395,8 @@
complete = true;
} else {
List<sp<ABuffer> >::iterator it = ++queue->begin();
+ int32_t connected = 1;
+ bool snapped = false;
while (it != queue->end()) {
ALOGV("sequence length %zu", totalCount);
@@ -233,26 +406,32 @@
size_t size = buffer->size();
if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
- ALOGV("sequence not complete, expected seqNo %d, got %d",
- expectedSeqNo, (uint32_t)buffer->int32Data());
+ ALOGD("sequence not complete, expected seqNo %u, got %u, nalType %u",
+ expectedSeqNo, (unsigned)buffer->int32Data(), nalType);
+ snapped = true;
- return WRONG_SEQUENCE_NUMBER;
+ if (!pFrame) {
+ return WRONG_SEQUENCE_NUMBER;
+ }
}
+ if (!snapped) {
+ connected++;
+ }
+
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
if (size < 2
|| data[0] != indicator
|| (data[1] & 0x1f) != nalType
- || (data[1] & 0x80)) {
+ || (data[1] & 0x80)
+ || rtpTime != rtpTimeStartAt) {
ALOGV("Ignoring malformed FU buffer.");
// Delete the whole start of the FU.
- it = queue->begin();
- for (size_t i = 0; i <= totalCount; ++i) {
- it = queue->erase(it);
- }
-
mNextExpectedSeqNo = expectedSeqNo + 1;
+ deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
return MALFORMED_PACKET;
}
@@ -260,9 +439,17 @@
totalSize += size - 2;
++totalCount;
- expectedSeqNo = expectedSeqNo + 1;
+ expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
if (data[1] & 0x40) {
+ if (pFrame && !recycleUnit(startSeqNo, expectedSeqNo,
+ connected, totalCount, 0.5f)) {
+ mNextExpectedSeqNo = expectedSeqNo;
+ deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
+
+ return MALFORMED_PACKET;
+ }
+
// This is the last fragment.
complete = true;
break;
@@ -290,6 +477,8 @@
unit->data()[0] = (nri << 5) | nalType;
size_t offset = 1;
+ int32_t cvo = -1;
+ sp<ARTPSource> source = nullptr;
List<sp<ABuffer> >::iterator it = queue->begin();
for (size_t i = 0; i < totalCount; ++i) {
const sp<ABuffer> &buffer = *it;
@@ -300,6 +489,9 @@
#endif
memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
+
+ buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
+ buffer->meta()->findInt32("cvo", &cvo);
offset += buffer->size() - 2;
it = queue->erase(it);
@@ -307,6 +499,13 @@
unit->setRange(0, totalSize);
+ if (cvo >= 0) {
+ unit->meta()->setInt32("cvo", cvo);
+ }
+ if (source != nullptr) {
+ unit->meta()->setObject("source", source);
+ }
+
addSingleNALUnit(unit);
ALOGV("successfully assembled a NAL unit from fragments.");
@@ -317,7 +516,11 @@
void AAVCAssembler::submitAccessUnit() {
CHECK(!mNALUnits.empty());
- ALOGV("Access unit complete (%zu nal units)", mNALUnits.size());
+ if(android::base::GetBoolProperty("debug.stagefright.fps", false)) {
+ ALOGD("Access unit complete (%zu nal units)", mNALUnits.size());
+ } else {
+ ALOGV("Access unit complete (%zu nal units)", mNALUnits.size());
+ }
size_t totalSize = 0;
for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
@@ -327,6 +530,7 @@
sp<ABuffer> accessUnit = new ABuffer(totalSize);
size_t offset = 0;
+ int32_t cvo = -1;
for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
it != mNALUnits.end(); ++it) {
memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
@@ -335,6 +539,8 @@
sp<ABuffer> nal = *it;
memcpy(accessUnit->data() + offset, nal->data(), nal->size());
offset += nal->size();
+
+ nal->meta()->findInt32("cvo", &cvo);
}
CopyTimes(accessUnit, *mNALUnits.begin());
@@ -343,6 +549,9 @@
printf(mAccessUnitDamaged ? "X" : ".");
fflush(stdout);
#endif
+ if (cvo >= 0) {
+ accessUnit->meta()->setInt32("cvo", cvo);
+ }
if (mAccessUnitDamaged) {
accessUnit->meta()->setInt32("damaged", true);
@@ -356,22 +565,89 @@
msg->post();
}
+inline int64_t AAVCAssembler::findRTPTime(
+ const uint32_t& firstRTPTime, const sp<ABuffer>& buffer) {
+ /* If you want to +, -, * rtpTime, recommend to declare rtpTime as int64_t.
+ Because rtpTime can be near UINT32_MAX. Beware the overflow. */
+ int64_t rtpTime = 0;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ // If the first overs 2^31 and rtp unders 2^31, the rtp value is overflowed one.
+ int64_t overflowMask = (firstRTPTime & 0x80000000 & ~rtpTime) << 1;
+ return rtpTime | overflowMask;
+}
+
+int32_t AAVCAssembler::pickProperSeq(const Queue *queue,
+ uint32_t first, int64_t play, int64_t jit) {
+ sp<ABuffer> buffer = *(queue->begin());
+ int32_t nextSeqNo = buffer->int32Data();
+
+ Queue::const_iterator it = queue->begin();
+ while (it != queue->end()) {
+ int64_t rtpTime = findRTPTime(first, *it);
+ // if pkt in time exists, that should be the next pivot
+ if (rtpTime + jit >= play) {
+ nextSeqNo = (*it)->int32Data();
+ break;
+ }
+ it++;
+ }
+ return nextSeqNo;
+}
+
+bool AAVCAssembler::recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
+ size_t avail, float goodRatio) {
+ float total = end - start;
+ float valid = connected;
+ float exist = avail;
+ bool isRecycle = (valid / total) >= goodRatio;
+
+ ALOGV("checking p-frame losses.. recvBufs %f valid %f diff %f recycle? %d",
+ exist, valid, total, isRecycle);
+
+ return isRecycle;
+}
+
+int32_t AAVCAssembler::deleteUnitUnderSeq(Queue *queue, uint32_t seq) {
+ int32_t initSize = queue->size();
+ Queue::iterator it = queue->begin();
+ while (it != queue->end()) {
+ if ((uint32_t)(*it)->int32Data() >= seq) {
+ break;
+ }
+ it++;
+ }
+ queue->erase(queue->begin(), it);
+ return initSize - queue->size();
+}
+
+inline void AAVCAssembler::printNowTimeUs(int64_t start, int64_t now, int64_t play) {
+ ALOGD("start=%lld, now=%lld, played=%lld",
+ (long long)start, (long long)now, (long long)play);
+}
+
+inline void AAVCAssembler::printRTPTime(int64_t rtp, int64_t play, int64_t exp, bool isExp) {
+ ALOGD("rtp-time(JB)=%lld, played-rtp-time(JB)=%lld, expired-rtp-time(JB)=%lld expired=%d",
+ (long long)rtp, (long long)play, (long long)exp, isExp);
+}
+
ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
const sp<ARTPSource> &source) {
AssemblyStatus status = addNALUnit(source);
if (status == MALFORMED_PACKET) {
- mAccessUnitDamaged = true;
+ uint64_t msecsSinceLastIFrame = (ALooper::GetNowUs() / 1000) - mLastIFrameProvidedAtMs;
+ if (msecsSinceLastIFrame > 1000) {
+ ALOGV("request FIR to get a new I-Frame, time since "
+ "last I-Frame %llu ms", (unsigned long long)msecsSinceLastIFrame);
+ source->onIssueFIRByAssembler();
+ }
}
return status;
}
void AAVCAssembler::packetLost() {
CHECK(mNextExpectedSeqNoValid);
- ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
-
+ ALOGD("packetLost (expected %u)", mNextExpectedSeqNo);
++mNextExpectedSeqNo;
-
- mAccessUnitDamaged = true;
}
void AAVCAssembler::onByeReceived() {
diff --git a/media/libstagefright/rtsp/AAVCAssembler.h b/media/libstagefright/rtsp/AAVCAssembler.h
index e19480c..9d71e2f 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.h
+++ b/media/libstagefright/rtsp/AAVCAssembler.h
@@ -31,6 +31,7 @@
struct AAVCAssembler : public ARTPAssembler {
explicit AAVCAssembler(const sp<AMessage> ¬ify);
+ typedef List<sp<ABuffer> > Queue;
protected:
virtual ~AAVCAssembler();
@@ -45,8 +46,16 @@
bool mNextExpectedSeqNoValid;
uint32_t mNextExpectedSeqNo;
bool mAccessUnitDamaged;
+ bool mFirstIFrameProvided;
+ uint64_t mLastIFrameProvidedAtMs;
+ int32_t mWidth;
+ int32_t mHeight;
List<sp<ABuffer> > mNALUnits;
+ int32_t addNack(const sp<ARTPSource> &source);
+ void checkSpsUpdated(const sp<ABuffer> &buffer);
+ void checkIFrameProvided(const sp<ABuffer> &buffer);
+ bool dropFramesUntilIframe(const sp<ABuffer> &buffer);
AssemblyStatus addNALUnit(const sp<ARTPSource> &source);
void addSingleNALUnit(const sp<ABuffer> &buffer);
AssemblyStatus addFragmentedNALUnit(List<sp<ABuffer> > *queue);
@@ -54,6 +63,14 @@
void submitAccessUnit();
+ inline int64_t findRTPTime(const uint32_t& firstRTPTime, const sp<ABuffer>& buffer);
+ int32_t pickProperSeq(const Queue *q, uint32_t first, int64_t play, int64_t jit);
+ bool recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
+ size_t avail, float goodRatio);
+ int32_t deleteUnitUnderSeq(Queue *q, uint32_t seq);
+ void printNowTimeUs(int64_t start, int64_t now, int64_t play);
+ void printRTPTime(int64_t rtp, int64_t play, int64_t exp, bool isExp);
+
DISALLOW_EVIL_CONSTRUCTORS(AAVCAssembler);
};
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.cpp b/media/libstagefright/rtsp/AHEVCAssembler.cpp
new file mode 100644
index 0000000..553ea08
--- /dev/null
+++ b/media/libstagefright/rtsp/AHEVCAssembler.cpp
@@ -0,0 +1,673 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AHEVCAssembler"
+#include <utils/Log.h>
+
+#include "AHEVCAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <include/HevcUtils.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#include <stdint.h>
+
+#define H265_NALU_MASK 0x3F
+#define H265_NALU_VPS 0x20
+#define H265_NALU_SPS 0x21
+#define H265_NALU_PPS 0x22
+#define H265_NALU_AP 0x30
+#define H265_NALU_FU 0x31
+#define H265_NALU_PACI 0x32
+
+
+namespace android {
+
+// static
+AHEVCAssembler::AHEVCAssembler(const sp<AMessage> ¬ify)
+ : mNotifyMsg(notify),
+ mAccessUnitRTPTime(0),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0),
+ mAccessUnitDamaged(false),
+ mFirstIFrameProvided(false),
+ mLastIFrameProvidedAtMs(0),
+ mWidth(0),
+ mHeight(0) {
+
+ ALOGV("Constructor");
+}
+
+AHEVCAssembler::~AHEVCAssembler() {
+}
+
+int32_t AHEVCAssembler::addNack(
+ const sp<ARTPSource> &source) {
+ List<sp<ABuffer>> *queue = source->queue();
+ int32_t nackCount = 0;
+
+ List<sp<ABuffer> >::iterator it = queue->begin();
+
+ if (it == queue->end()) {
+ return nackCount /* 0 */;
+ }
+
+ uint16_t queueHeadSeqNum = (*it)->int32Data();
+
+ // move to the packet after which RTCP:NACK was sent.
+ for (; it != queue->end(); ++it) {
+ int32_t seqNum = (*it)->int32Data();
+ if (seqNum >= source->mHighestNackNumber) {
+ break;
+ }
+ }
+
+ int32_t nackStartAt = -1;
+
+ while (it != queue->end()) {
+ int32_t seqBeforeLast = (*it)->int32Data();
+ // increase iterator.
+ if ((++it) == queue->end()) {
+ break;
+ }
+
+ int32_t seqLast = (*it)->int32Data();
+
+ if ((seqLast - seqBeforeLast) < 0) {
+ ALOGD("addNack: found end of seqNum from(%d) to(%d)", seqBeforeLast, seqLast);
+ source->mHighestNackNumber = 0;
+ }
+
+ // missed packet found
+ if (seqLast > (seqBeforeLast + 1) &&
+ // we didn't send RTCP:NACK for this packet yet.
+ (seqLast - 1) > source->mHighestNackNumber) {
+ source->mHighestNackNumber = seqLast -1;
+ nackStartAt = seqBeforeLast + 1;
+ break;
+ }
+
+ }
+
+ if (nackStartAt != -1) {
+ nackCount = source->mHighestNackNumber - nackStartAt + 1;
+ ALOGD("addNack: nackCount=%d, nackFrom=%d, nackTo=%d", nackCount,
+ nackStartAt, source->mHighestNackNumber);
+
+ uint16_t mask = (uint16_t)(0xffff) >> (16 - nackCount + 1);
+ source->setSeqNumToNACK(nackStartAt, mask, queueHeadSeqNum);
+ }
+
+ return nackCount;
+}
+
+ARTPAssembler::AssemblyStatus AHEVCAssembler::addNALUnit(
+ const sp<ARTPSource> &source) {
+ List<sp<ABuffer> > *queue = source->queue();
+ const uint32_t firstRTPTime = source->mFirstRtpTime;
+
+ if (queue->empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+
+ sp<ABuffer> buffer = *queue->begin();
+ buffer->meta()->setObject("source", source);
+ int64_t rtpTime = findRTPTime(firstRTPTime, buffer);
+
+ int64_t startTime = source->mFirstSysTime / 1000;
+ int64_t nowTime = ALooper::GetNowUs() / 1000;
+ int64_t playedTime = nowTime - startTime;
+ int64_t playedTimeRtp = source->mFirstRtpTime + playedTime * (int64_t)source->mClockRate / 1000;
+ const int64_t jitterTime = source->mJbTimeMs * (int64_t)source->mClockRate / 1000;
+
+ int64_t expiredTimeInJb = rtpTime + jitterTime;
+ bool isExpired = expiredTimeInJb <= (playedTimeRtp);
+ bool isTooLate200 = expiredTimeInJb < (playedTimeRtp - jitterTime);
+ bool isTooLate300 = expiredTimeInJb < (playedTimeRtp - (jitterTime * 3 / 2));
+
+ if (mShowQueueCnt < 20) {
+ showCurrentQueue(queue);
+ printNowTimeUs(startTime, nowTime, playedTime);
+ printRTPTime(rtpTime, playedTimeRtp, expiredTimeInJb, isExpired);
+ mShowQueueCnt++;
+ }
+
+ AHEVCAssembler::addNack(source);
+
+ if (!isExpired) {
+ ALOGV("buffering in jitter buffer.");
+ return NOT_ENOUGH_DATA;
+ }
+
+ if (isTooLate200) {
+ ALOGW("=== WARNING === buffer arrived 200ms late. === WARNING === ");
+ }
+
+ if (isTooLate300) {
+ ALOGW("buffer arrived after 300ms ... \t Diff in Jb=%lld \t Seq# %d",
+ (long long)(playedTimeRtp - expiredTimeInJb), buffer->int32Data());
+ printNowTimeUs(startTime, nowTime, playedTime);
+ printRTPTime(rtpTime, playedTimeRtp, expiredTimeInJb, isExpired);
+
+ mNextExpectedSeqNo = pickProperSeq(queue, firstRTPTime, playedTimeRtp, jitterTime);
+ }
+
+ if (mNextExpectedSeqNoValid) {
+ int32_t size = queue->size();
+ int32_t cntRemove = deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
+
+ if (cntRemove > 0) {
+ source->noticeAbandonBuffer(cntRemove);
+ ALOGW("delete %d of %d buffers", cntRemove, size);
+ }
+
+ if (queue->empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+ }
+
+ buffer = *queue->begin();
+
+ if (!mNextExpectedSeqNoValid) {
+ mNextExpectedSeqNoValid = true;
+ mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
+ } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
+ ALOGV("Not the sequence number I expected");
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if (size < 1 || (data[0] & 0x80)) {
+ // Corrupt.
+
+ ALOGV("Ignoring corrupt buffer.");
+ queue->erase(queue->begin());
+
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ unsigned nalType = (data[0] >> 1) & H265_NALU_MASK;
+ if (nalType > 0 && nalType < H265_NALU_AP) {
+ addSingleNALUnit(buffer);
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return OK;
+ } else if (nalType == H265_NALU_FU) {
+ // FU-A
+ return addFragmentedNALUnit(queue);
+ } else if (nalType == H265_NALU_AP) {
+ // STAP-A
+ bool success = addSingleTimeAggregationPacket(buffer);
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return success ? OK : MALFORMED_PACKET;
+ } else if (nalType == 0) {
+ ALOGV("Ignoring undefined nal type.");
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return OK;
+ } else {
+ ALOGV("Ignoring unsupported buffer (nalType=%d)", nalType);
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return MALFORMED_PACKET;
+ }
+}
+
+void AHEVCAssembler::checkSpsUpdated(const sp<ABuffer> &buffer) {
+ if (buffer->size() == 0) {
+ return;
+ }
+ const uint8_t *data = buffer->data();
+ HevcParameterSets paramSets;
+ unsigned nalType = (data[0] >> 1) & H265_NALU_MASK;
+ if (nalType == H265_NALU_SPS) {
+ int32_t width = 0, height = 0;
+ paramSets.FindHEVCDimensions(buffer, &width, &height);
+ ALOGV("existing resolution (%u x %u)", mWidth, mHeight);
+ if (width != mWidth || height != mHeight) {
+ mFirstIFrameProvided = false;
+ mWidth = width;
+ mHeight = height;
+ ALOGD("found a new resolution (%u x %u)", mWidth, mHeight);
+ }
+ }
+}
+
+void AHEVCAssembler::checkIFrameProvided(const sp<ABuffer> &buffer) {
+ if (buffer->size() == 0) {
+ return;
+ }
+ const uint8_t *data = buffer->data();
+ unsigned nalType = (data[0] >> 1) & H265_NALU_MASK;
+ if (nalType > 0x0F && nalType < 0x18) {
+ mLastIFrameProvidedAtMs = ALooper::GetNowUs() / 1000;
+ if (!mFirstIFrameProvided) {
+ mFirstIFrameProvided = true;
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ ALOGD("got First I-frame to be decoded. rtpTime=%d, size=%zu", rtpTime, buffer->size());
+ }
+ }
+}
+
+bool AHEVCAssembler::dropFramesUntilIframe(const sp<ABuffer> &buffer) {
+ if (buffer->size() == 0) {
+ return false;
+ }
+ const uint8_t *data = buffer->data();
+ unsigned nalType = (data[0] >> 1) & H265_NALU_MASK;
+ return !mFirstIFrameProvided && nalType < 0x10;
+}
+
+void AHEVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
+ ALOGV("addSingleNALUnit of size %zu", buffer->size());
+#if !LOG_NDEBUG
+ hexdump(buffer->data(), buffer->size());
+#endif
+ checkSpsUpdated(buffer);
+ checkIFrameProvided(buffer);
+
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ if (dropFramesUntilIframe(buffer)) {
+ sp<ARTPSource> source = nullptr;
+ buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
+ if (source != nullptr) {
+ ALOGD("Issued FIR to get the I-frame");
+ source->onIssueFIRByAssembler();
+ }
+ ALOGD("drop P-frames till an I-frame provided. rtpTime %u", rtpTime);
+ return;
+ }
+
+ if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
+ submitAccessUnit();
+ }
+ mAccessUnitRTPTime = rtpTime;
+
+ mNALUnits.push_back(buffer);
+}
+
+bool AHEVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if (size < 3) {
+ ALOGV("Discarding too small STAP-A packet.");
+ return false;
+ }
+
+ ++data;
+ --size;
+ while (size >= 2) {
+ size_t nalSize = (data[0] << 8) | data[1];
+
+ if (size < nalSize + 2) {
+ ALOGV("Discarding malformed STAP-A packet.");
+ return false;
+ }
+
+ sp<ABuffer> unit = new ABuffer(nalSize);
+ memcpy(unit->data(), &data[2], nalSize);
+
+ CopyTimes(unit, buffer);
+
+ addSingleNALUnit(unit);
+
+ data += 2 + nalSize;
+ size -= 2 + nalSize;
+ }
+
+ if (size != 0) {
+ ALOGV("Unexpected padding at end of STAP-A packet.");
+ }
+
+ return true;
+}
+
+ARTPAssembler::AssemblyStatus AHEVCAssembler::addFragmentedNALUnit(
+ List<sp<ABuffer> > *queue) {
+ CHECK(!queue->empty());
+
+ sp<ABuffer> buffer = *queue->begin();
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ CHECK(size > 0);
+ /* H265 payload header is 16 bit
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |F| Type | Layer ID | TID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ unsigned indicator = (data[0] >> 1);
+
+ CHECK((indicator & H265_NALU_MASK) == H265_NALU_FU);
+
+ if (size < 3) {
+ ALOGV("Ignoring malformed FU buffer (size = %zu)", size);
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ if (!(data[2] & 0x80)) {
+ // Start bit not set on the first buffer.
+
+ ALOGV("Start bit not set on first buffer");
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ /* FU INDICATOR HDR
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |S|E| Type |
+ +-+-+-+-+-+-+-+-+
+ */
+ uint32_t nalType = data[2] & H265_NALU_MASK;
+ uint32_t tid = data[1] & 0x7;
+ ALOGV("nalType =%u, tid =%u", nalType, tid);
+
+ uint32_t expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
+ size_t totalSize = size - 3;
+ size_t totalCount = 1;
+ bool complete = false;
+
+ uint32_t rtpTimeStartAt;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTimeStartAt));
+ uint32_t startSeqNo = buffer->int32Data();
+ bool pFrame = (nalType < 0x10);
+
+ if (data[2] & 0x40) {
+ // Huh? End bit also set on the first buffer.
+
+ ALOGV("Grrr. This isn't fragmented at all.");
+
+ complete = true;
+ } else {
+ List<sp<ABuffer> >::iterator it = ++queue->begin();
+ int32_t connected = 1;
+ bool snapped = false;
+ while (it != queue->end()) {
+ ALOGV("sequence length %zu", totalCount);
+
+ const sp<ABuffer> &buffer = *it;
+
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
+ ALOGV("sequence not complete, expected seqNo %u, got %u, nalType %u",
+ expectedSeqNo, (uint32_t)buffer->int32Data(), nalType);
+ snapped = true;
+
+ if (!pFrame) {
+ return WRONG_SEQUENCE_NUMBER;
+ }
+ }
+
+ if (!snapped) {
+ connected++;
+ }
+
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ if (size < 3
+ || ((data[0] >> 1) & H265_NALU_MASK) != indicator
+ || (data[2] & H265_NALU_MASK) != nalType
+ || (data[2] & 0x80)
+ || rtpTime != rtpTimeStartAt) {
+ ALOGV("Ignoring malformed FU buffer.");
+
+ // Delete the whole start of the FU.
+
+ mNextExpectedSeqNo = expectedSeqNo + 1;
+ deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
+
+ return MALFORMED_PACKET;
+ }
+
+ totalSize += size - 3;
+ ++totalCount;
+
+ expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
+
+ if (data[2] & 0x40) {
+ if (pFrame && !recycleUnit(startSeqNo, expectedSeqNo,
+ connected, totalCount, 0.5f)) {
+ mNextExpectedSeqNo = expectedSeqNo;
+ deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
+
+ return MALFORMED_PACKET;
+ }
+ // This is the last fragment.
+ complete = true;
+ break;
+ }
+
+ ++it;
+ }
+ }
+
+ if (!complete) {
+ return NOT_ENOUGH_DATA;
+ }
+
+ mNextExpectedSeqNo = expectedSeqNo;
+
+ // We found all the fragments that make up the complete NAL unit.
+
+ // Leave room for the header. So far totalSize did not include the
+ // header byte.
+ totalSize += 2;
+
+ sp<ABuffer> unit = new ABuffer(totalSize);
+ CopyTimes(unit, *queue->begin());
+
+ unit->data()[0] = (nalType << 1);
+ unit->data()[1] = tid;
+
+ size_t offset = 2;
+ int32_t cvo = -1;
+ List<sp<ABuffer> >::iterator it = queue->begin();
+ for (size_t i = 0; i < totalCount; ++i) {
+ const sp<ABuffer> &buffer = *it;
+
+ ALOGV("piece #%zu/%zu", i + 1, totalCount);
+#if !LOG_NDEBUG
+ hexdump(buffer->data(), buffer->size());
+#endif
+
+ memcpy(unit->data() + offset, buffer->data() + 3, buffer->size() - 3);
+ buffer->meta()->findInt32("cvo", &cvo);
+ offset += buffer->size() - 3;
+
+ it = queue->erase(it);
+ }
+
+ unit->setRange(0, totalSize);
+
+ if (cvo >= 0) {
+ unit->meta()->setInt32("cvo", cvo);
+ }
+
+ addSingleNALUnit(unit);
+
+ ALOGV("successfully assembled a NAL unit from fragments.");
+
+ return OK;
+}
+
+void AHEVCAssembler::submitAccessUnit() {
+ CHECK(!mNALUnits.empty());
+
+ ALOGV("Access unit complete (%zu nal units)", mNALUnits.size());
+
+ size_t totalSize = 0;
+ for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
+ it != mNALUnits.end(); ++it) {
+ totalSize += 4 + (*it)->size();
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ size_t offset = 0;
+ int32_t cvo = -1;
+ for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
+ it != mNALUnits.end(); ++it) {
+ memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
+ offset += 4;
+
+ sp<ABuffer> nal = *it;
+ memcpy(accessUnit->data() + offset, nal->data(), nal->size());
+ offset += nal->size();
+ nal->meta()->findInt32("cvo", &cvo);
+ }
+
+ CopyTimes(accessUnit, *mNALUnits.begin());
+
+#if 0
+ printf(mAccessUnitDamaged ? "X" : ".");
+ fflush(stdout);
+#endif
+ if (cvo >= 0) {
+ accessUnit->meta()->setInt32("cvo", cvo);
+ }
+
+ if (mAccessUnitDamaged) {
+ accessUnit->meta()->setInt32("damaged", true);
+ }
+
+ mNALUnits.clear();
+ mAccessUnitDamaged = false;
+
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setBuffer("access-unit", accessUnit);
+ msg->post();
+}
+
+inline int64_t AHEVCAssembler::findRTPTime(
+ const uint32_t& firstRTPTime, const sp<ABuffer>& buffer) {
+ /* If you want to +, -, * rtpTime, recommend to declare rtpTime as int64_t.
+ Because rtpTime can be near UINT32_MAX. Beware the overflow. */
+ int64_t rtpTime = 0;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ // If the first overs 2^31 and rtp unders 2^31, the rtp value is overflowed one.
+ int64_t overflowMask = (firstRTPTime & 0x80000000 & ~rtpTime) << 1;
+ return rtpTime | overflowMask;
+}
+
+int32_t AHEVCAssembler::pickProperSeq(const Queue *queue,
+ uint32_t first, int64_t play, int64_t jit) {
+ sp<ABuffer> buffer = *(queue->begin());
+ int32_t nextSeqNo = buffer->int32Data();
+
+ Queue::const_iterator it = queue->begin();
+ while (it != queue->end()) {
+ int64_t rtpTime = findRTPTime(first, *it);
+ // if pkt in time exists, that should be the next pivot
+ if (rtpTime + jit >= play) {
+ nextSeqNo = (*it)->int32Data();
+ break;
+ }
+ it++;
+ }
+ return nextSeqNo;
+}
+
+bool AHEVCAssembler::recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
+ size_t avail, float goodRatio) {
+ float total = end - start;
+ float valid = connected;
+ float exist = avail;
+ bool isRecycle = (valid / total) >= goodRatio;
+
+ ALOGV("checking p-frame losses.. recvBufs %f valid %f diff %f recycle? %d",
+ exist, valid, total, isRecycle);
+
+ return isRecycle;
+}
+
+int32_t AHEVCAssembler::deleteUnitUnderSeq(Queue *queue, uint32_t seq) {
+ int32_t initSize = queue->size();
+ Queue::iterator it = queue->begin();
+ while (it != queue->end()) {
+ if ((uint32_t)(*it)->int32Data() >= seq) {
+ break;
+ }
+ it++;
+ }
+ queue->erase(queue->begin(), it);
+ return initSize - queue->size();
+}
+
+inline void AHEVCAssembler::printNowTimeUs(int64_t start, int64_t now, int64_t play) {
+ ALOGD("start=%lld, now=%lld, played=%lld",
+ (long long)start, (long long)now, (long long)play);
+}
+
+inline void AHEVCAssembler::printRTPTime(int64_t rtp, int64_t play, int64_t exp, bool isExp) {
+ ALOGD("rtp-time(JB)=%lld, played-rtp-time(JB)=%lld, expired-rtp-time(JB)=%lld expired=%d",
+ (long long)rtp, (long long)play, (long long)exp, isExp);
+}
+
+ARTPAssembler::AssemblyStatus AHEVCAssembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ AssemblyStatus status = addNALUnit(source);
+ if (status == MALFORMED_PACKET) {
+ uint64_t msecsSinceLastIFrame = (ALooper::GetNowUs() / 1000) - mLastIFrameProvidedAtMs;
+ if (msecsSinceLastIFrame > 1000) {
+ ALOGV("request FIR to get a new I-Frame, time after "
+ "last I-Frame in %llu ms", (unsigned long long)msecsSinceLastIFrame);
+ source->onIssueFIRByAssembler();
+ }
+ }
+ return status;
+}
+
+void AHEVCAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ALOGD("packetLost (expected %u)", mNextExpectedSeqNo);
+
+ ++mNextExpectedSeqNo;
+}
+
+void AHEVCAssembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.h b/media/libstagefright/rtsp/AHEVCAssembler.h
new file mode 100644
index 0000000..bf1cded
--- /dev/null
+++ b/media/libstagefright/rtsp/AHEVCAssembler.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_HEVC_ASSEMBLER_H_
+
+#define A_HEVC_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+
+struct AHEVCAssembler : public ARTPAssembler {
+ AHEVCAssembler(const sp<AMessage> ¬ify);
+
+ typedef List<sp<ABuffer> > Queue;
+
+protected:
+ virtual ~AHEVCAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void onByeReceived();
+ virtual void packetLost();
+
+private:
+ sp<AMessage> mNotifyMsg;
+
+ uint32_t mAccessUnitRTPTime;
+ bool mNextExpectedSeqNoValid;
+ uint32_t mNextExpectedSeqNo;
+ bool mAccessUnitDamaged;
+ bool mFirstIFrameProvided;
+ uint64_t mLastIFrameProvidedAtMs;
+ int32_t mWidth;
+ int32_t mHeight;
+ List<sp<ABuffer> > mNALUnits;
+
+ int32_t addNack(const sp<ARTPSource> &source);
+ void checkSpsUpdated(const sp<ABuffer> &buffer);
+ void checkIFrameProvided(const sp<ABuffer> &buffer);
+ bool dropFramesUntilIframe(const sp<ABuffer> &buffer);
+ AssemblyStatus addNALUnit(const sp<ARTPSource> &source);
+ void addSingleNALUnit(const sp<ABuffer> &buffer);
+ AssemblyStatus addFragmentedNALUnit(List<sp<ABuffer> > *queue);
+ bool addSingleTimeAggregationPacket(const sp<ABuffer> &buffer);
+
+ void submitAccessUnit();
+
+ inline int64_t findRTPTime(const uint32_t& firstRTPTime, const sp<ABuffer>& buffer);
+ int32_t pickProperSeq(const Queue *q, uint32_t first, int64_t play, int64_t jit);
+ bool recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
+ size_t avail, float goodRatio);
+ int32_t deleteUnitUnderSeq(Queue *queue, uint32_t seq);
+ void printNowTimeUs(int64_t start, int64_t now, int64_t play);
+ void printRTPTime(int64_t rtp, int64_t play, int64_t exp, bool isExp);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AHEVCAssembler);
+};
+
+} // namespace android
+
+#endif // A_HEVC_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 574bd7a..8f4df8e 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -454,6 +454,17 @@
mFormat->setInt32(kKeyWidth, width);
mFormat->setInt32(kKeyHeight, height);
+ } else if (!strncmp(desc.c_str(), "H265/", 5)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+
+ int32_t width, height;
+ if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
+ width = -1;
+ height = -1;
+ }
+
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
} else if (!strncmp(desc.c_str(), "H263-2000/", 10)
|| !strncmp(desc.c_str(), "H263-1998/", 10)) {
mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
index befc226..52aa3a0 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.cpp
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_TAG "ARTPAssembler"
#include "ARTPAssembler.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -21,12 +22,16 @@
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <android-base/properties.h>
+
#include <stdint.h>
namespace android {
ARTPAssembler::ARTPAssembler()
- : mFirstFailureTimeUs(-1) {
+ : mShowQueueCnt(0),
+ mFirstFailureTimeUs(-1) {
+ mShowQueue = android::base::GetBoolProperty("debug.stagefright.rtp", false);
}
void ARTPAssembler::onPacketReceived(const sp<ARTPSource> &source) {
@@ -141,4 +146,15 @@
return accessUnit;
}
+void ARTPAssembler::showCurrentQueue(List<sp<ABuffer> > *queue) {
+ AString temp("Queue elem size : ");
+ List<sp<ABuffer> >::iterator it = queue->begin();
+ while (it != queue->end()) {
+ temp.append((*it)->size());
+ temp.append(" \t");
+ it++;
+ }
+ ALOGD("%s",temp.c_str());
+};
+
} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h
index 4082d4c..191f08e 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.h
+++ b/media/libstagefright/rtsp/ARTPAssembler.h
@@ -56,6 +56,11 @@
static sp<ABuffer> MakeCompoundFromPackets(
const List<sp<ABuffer> > &frames);
+ void showCurrentQueue(List<sp<ABuffer> > *queue);
+
+ bool mShowQueue;
+ int32_t mShowQueueCnt;
+
private:
int64_t mFirstFailureTimeUs;
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 6a4706d..61c06d1 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -30,6 +30,8 @@
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <android/multinetwork.h>
+
#include <arpa/inet.h>
#include <sys/socket.h>
@@ -53,6 +55,7 @@
const int64_t ARTPConnection::kSelectTimeoutUs = 1000LL;
struct ARTPConnection::StreamInfo {
+ bool isIPv6;
int mRTPSocket;
int mRTCPSocket;
sp<ASessionDescription> mSessionDesc;
@@ -63,14 +66,21 @@
int64_t mNumRTCPPacketsReceived;
int64_t mNumRTPPacketsReceived;
struct sockaddr_in mRemoteRTCPAddr;
+ struct sockaddr_in6 mRemoteRTCPAddr6;
bool mIsInjected;
+
+ // RTCP Extension for CVO
+ int mCVOExtMap; // will be set to 0 if cvo is not negotiated in sdp
};
ARTPConnection::ARTPConnection(uint32_t flags)
: mFlags(flags),
mPollEventPending(false),
- mLastReceiverReportTimeUs(-1) {
+ mLastReceiverReportTimeUs(-1),
+ mLastBitrateReportTimeUs(-1),
+ mTargetBitrate(-1),
+ mJbTimeMs(300) {
}
ARTPConnection::~ARTPConnection() {
@@ -121,7 +131,7 @@
unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
start &= ~1;
- for (unsigned port = start; port < 65536; port += 2) {
+ for (unsigned port = start; port < 65535; port += 2) {
struct sockaddr_in addr;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
addr.sin_family = AF_INET;
@@ -139,12 +149,130 @@
(const struct sockaddr *)&addr, sizeof(addr)) == 0) {
*rtpPort = port;
return;
+ } else {
+ // we should recreate a RTP socket to avoid bind other port in same RTP socket
+ close(*rtpSocket);
+
+ *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(*rtpSocket, 0);
+ bumpSocketBufferSize(*rtpSocket);
}
}
TRESPASS();
}
+// static
+void ARTPConnection::MakeRTPSocketPair(
+ int *rtpSocket, int *rtcpSocket, const char *localIp, const char *remoteIp,
+ unsigned localPort, unsigned remotePort, int64_t socketNetwork) {
+ bool isIPv6 = false;
+ if (strchr(localIp, ':') != NULL)
+ isIPv6 = true;
+
+ *rtpSocket = socket(isIPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(*rtpSocket, 0);
+
+ bumpSocketBufferSize(*rtpSocket);
+
+ *rtcpSocket = socket(isIPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(*rtcpSocket, 0);
+
+ if (socketNetwork != 0) {
+ ALOGD("trying to bind rtp socket(%d) to network(%llu).",
+ *rtpSocket, (unsigned long long)socketNetwork);
+
+ int result = android_setsocknetwork((net_handle_t)socketNetwork, *rtpSocket);
+ if (result != 0) {
+ ALOGW("failed(%d) to bind rtp socket(%d) to network(%llu)",
+ result, *rtpSocket, (unsigned long long)socketNetwork);
+ }
+ result = android_setsocknetwork((net_handle_t)socketNetwork, *rtcpSocket);
+ if (result != 0) {
+ ALOGW("failed(%d) to bind rtcp socket(%d) to network(%llu)",
+ result, *rtcpSocket, (unsigned long long)socketNetwork);
+ }
+ }
+
+ bumpSocketBufferSize(*rtcpSocket);
+
+ struct sockaddr *addr;
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+
+ if (isIPv6) {
+ addr = (struct sockaddr *)&addr6;
+ memset(&addr6, 0, sizeof(addr6));
+ addr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, localIp, &addr6.sin6_addr);
+ addr6.sin6_port = htons((uint16_t)localPort);
+ } else {
+ addr = (struct sockaddr *)&addr4;
+ memset(&addr4, 0, sizeof(addr4));
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = inet_addr(localIp);
+ addr4.sin_port = htons((uint16_t)localPort);
+ }
+
+ int sockopt = 1;
+ setsockopt(*rtpSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
+ setsockopt(*rtcpSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
+
+ int sizeSockSt = isIPv6 ? sizeof(addr6) : sizeof(addr4);
+
+ if (bind(*rtpSocket, addr, sizeSockSt) == 0) {
+ ALOGI("rtp socket successfully binded. addr=%s:%d", localIp, localPort);
+ } else {
+ ALOGE("failed to bind rtp socket addr=%s:%d err=%s", localIp, localPort, strerror(errno));
+ return;
+ }
+
+ if (isIPv6)
+ addr6.sin6_port = htons(localPort + 1);
+ else
+ addr4.sin_port = htons(localPort + 1);
+
+ if (bind(*rtcpSocket, addr, sizeSockSt) == 0) {
+ ALOGI("rtcp socket successfully binded. addr=%s:%d", localIp, localPort + 1);
+ } else {
+ ALOGE("failed to bind rtcp socket addr=%s:%d err=%s", localIp,
+ localPort + 1, strerror(errno));
+ }
+
+ // Re uses addr variable as remote addr.
+ if (isIPv6) {
+ memset(&addr6, 0, sizeof(addr6));
+ addr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, remoteIp, &addr6.sin6_addr);
+ addr6.sin6_port = htons((uint16_t)remotePort);
+ } else {
+ memset(&addr4, 0, sizeof(addr4));
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = inet_addr(remoteIp);
+ addr4.sin_port = htons((uint16_t)remotePort);
+ }
+ if (connect(*rtpSocket, addr, sizeSockSt) == 0) {
+ ALOGI("rtp socket successfully connected to remote=%s:%d", remoteIp, remotePort);
+ } else {
+ ALOGE("failed to connect rtp socket to remote addr=%s:%d err=%s", remoteIp,
+ remotePort, strerror(errno));
+ return;
+ }
+
+ if (isIPv6)
+ addr6.sin6_port = htons(remotePort + 1);
+ else
+ addr4.sin_port = htons(remotePort + 1);
+
+ if (connect(*rtcpSocket, addr, sizeSockSt) == 0) {
+ ALOGI("rtcp socket successfully connected to remote=%s:%d", remoteIp, remotePort + 1);
+ } else {
+ ALOGE("failed to connect rtcp socket addr=%s:%d err=%s", remoteIp,
+ remotePort + 1, strerror(errno));
+ return;
+ }
+}
+
void ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatAddStream:
@@ -204,6 +332,19 @@
info->mNumRTCPPacketsReceived = 0;
info->mNumRTPPacketsReceived = 0;
memset(&info->mRemoteRTCPAddr, 0, sizeof(info->mRemoteRTCPAddr));
+ memset(&info->mRemoteRTCPAddr6, 0, sizeof(info->mRemoteRTCPAddr6));
+
+ sp<ASessionDescription> sessionDesc = info->mSessionDesc;
+ info->mCVOExtMap = 0;
+ for (size_t i = 1; i < sessionDesc->countTracks(); ++i) {
+ int32_t cvoExtMap;
+ if (sessionDesc->getCvoExtMap(i, &cvoExtMap)) {
+ info->mCVOExtMap = cvoExtMap;
+ ALOGI("urn:3gpp:video-orientation(cvo) found as extmap:%d", info->mCVOExtMap);
+ } else {
+ ALOGI("urn:3gpp:video-orientation(cvo) not found :%d", info->mCVOExtMap);
+ }
+ }
if (!injected) {
postPollEvent();
@@ -295,17 +436,59 @@
if (err == -ECONNRESET) {
// socket failure, this stream is dead, Jim.
+ sp<AMessage> notify = it->mNotifyMsg->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", 400);
+ notify->setInt32("feedback-type", 1);
+ notify->setInt32("sender", it->mSources.valueAt(0)->getSelfID());
+ notify->post();
ALOGW("failed to receive RTP/RTCP datagram.");
it = mStreams.erase(it);
continue;
}
+ // add NACK and FIR that needs to be sent immediately.
+ sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
+ for (size_t i = 0; i < it->mSources.size(); ++i) {
+ buffer->setRange(0, 0);
+ int cnt = it->mSources.valueAt(i)->addNACK(buffer);
+ if (cnt > 0) {
+ ALOGV("Send NACK for lost %d Packets", cnt);
+ send(&*it, buffer);
+ }
+
+ buffer->setRange(0, 0);
+ it->mSources.valueAt(i)->addFIR(buffer);
+ if (buffer->size() > 0) {
+ ALOGD("Send FIR immediately for lost Packets");
+ send(&*it, buffer);
+ }
+
+ buffer->setRange(0, 0);
+ it->mSources.valueAt(i)->addTMMBR(buffer, mTargetBitrate);
+ mTargetBitrate = -1;
+ if (buffer->size() > 0) {
+ ALOGV("Sending TMMBR...");
+ ssize_t n = send(&*it, buffer);
+
+ if (n != (ssize_t)buffer->size()) {
+ ALOGW("failed to send RTCP TMMBR (%s).",
+ n >= 0 ? "connection gone" : strerror(errno));
+
+ it = mStreams.erase(it);
+ continue;
+ }
+ }
+ }
+
++it;
}
}
int64_t nowUs = ALooper::GetNowUs();
+ checkRxBitrate(nowUs);
+
if (mLastReceiverReportTimeUs <= 0
|| mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
@@ -340,24 +523,16 @@
if (buffer->size() > 0) {
ALOGV("Sending RR...");
- ssize_t n;
- do {
- n = sendto(
- s->mRTCPSocket, buffer->data(), buffer->size(), 0,
- (const struct sockaddr *)&s->mRemoteRTCPAddr,
- sizeof(s->mRemoteRTCPAddr));
- } while (n < 0 && errno == EINTR);
+ ssize_t n = send(s, buffer);
- if (n <= 0) {
+ if (n != (ssize_t)buffer->size()) {
ALOGW("failed to send RTCP receiver report (%s).",
- n == 0 ? "connection gone" : strerror(errno));
+ n >= 0 ? "connection gone" : strerror(errno));
it = mStreams.erase(it);
continue;
}
- CHECK_EQ(n, (ssize_t)buffer->size());
-
mLastReceiverReportTimeUs = nowUs;
}
@@ -377,9 +552,22 @@
sp<ABuffer> buffer = new ABuffer(65536);
+ struct sockaddr *pRemoteRTCPAddr;
+ int sizeSockSt;
+ if (s->isIPv6) {
+ pRemoteRTCPAddr = (struct sockaddr *)&s->mRemoteRTCPAddr6;
+ sizeSockSt = sizeof(struct sockaddr_in6);
+ } else {
+ pRemoteRTCPAddr = (struct sockaddr *)&s->mRemoteRTCPAddr;
+ sizeSockSt = sizeof(struct sockaddr_in);
+ }
socklen_t remoteAddrLen =
(!receiveRTP && s->mNumRTCPPacketsReceived == 0)
- ? sizeof(s->mRemoteRTCPAddr) : 0;
+ ? sizeSockSt : 0;
+
+ if (mFlags & kViLTEConnection) {
+ remoteAddrLen = 0;
+ }
ssize_t nbytes;
do {
@@ -388,8 +576,9 @@
buffer->data(),
buffer->capacity(),
0,
- remoteAddrLen > 0 ? (struct sockaddr *)&s->mRemoteRTCPAddr : NULL,
+ remoteAddrLen > 0 ? pRemoteRTCPAddr : NULL,
remoteAddrLen > 0 ? &remoteAddrLen : NULL);
+ mCumulativeBytes += nbytes;
} while (nbytes < 0 && errno == EINTR);
if (nbytes <= 0) {
@@ -410,6 +599,36 @@
return err;
}
+ssize_t ARTPConnection::send(const StreamInfo *info, const sp<ABuffer> buffer) {
+ struct sockaddr* pRemoteRTCPAddr;
+ int sizeSockSt;
+
+ /* It seems this isIPv6 variable is useless.
+ * We should remove it to prevent confusion */
+ if (info->isIPv6) {
+ pRemoteRTCPAddr = (struct sockaddr *)&info->mRemoteRTCPAddr6;
+ sizeSockSt = sizeof(struct sockaddr_in6);
+ } else {
+ pRemoteRTCPAddr = (struct sockaddr *)&info->mRemoteRTCPAddr;
+ sizeSockSt = sizeof(struct sockaddr_in);
+ }
+
+ if (mFlags & kViLTEConnection) {
+ ALOGV("ViLTE RTCP");
+ pRemoteRTCPAddr = NULL;
+ sizeSockSt = 0;
+ }
+
+ ssize_t n;
+ do {
+ n = sendto(
+ info->mRTCPSocket, buffer->data(), buffer->size(), 0,
+ pRemoteRTCPAddr, sizeSockSt);
+ } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
if (s->mNumRTPPacketsReceived++ == 0) {
sp<AMessage> notify = s->mNotifyMsg->dup();
@@ -431,6 +650,11 @@
return -1;
}
+ if ((data[1] & 0x7f) == 20 /* decimal */) {
+ // Unassigned payload type
+ return -1;
+ }
+
if (data[0] & 0x20) {
// Padding present.
@@ -454,6 +678,7 @@
return -1;
}
+ int32_t cvoDegrees = -1;
if (data[0] & 0x10) {
// Header eXtension present.
@@ -467,13 +692,14 @@
const uint8_t *extensionData = &data[payloadOffset];
size_t extensionLength =
- 4 * (extensionData[2] << 8 | extensionData[3]);
+ (4 * (extensionData[2] << 8 | extensionData[3])) + 4;
- if (size < payloadOffset + 4 + extensionLength) {
+ if (size < payloadOffset + extensionLength) {
return -1;
}
- payloadOffset += 4 + extensionLength;
+ parseRTPExt(s, (const uint8_t *)extensionData, extensionLength, &cvoDegrees);
+ payloadOffset += extensionLength;
}
uint32_t srcId = u32at(&data[8]);
@@ -487,6 +713,9 @@
meta->setInt32("rtp-time", rtpTime);
meta->setInt32("PT", data[1] & 0x7f);
meta->setInt32("M", data[1] >> 7);
+ if (cvoDegrees >= 0) {
+ meta->setInt32("cvo", cvoDegrees);
+ }
buffer->setInt32Data(u16at(&data[2]));
buffer->setRange(payloadOffset, size - payloadOffset);
@@ -496,11 +725,65 @@
return OK;
}
+status_t ARTPConnection::parseRTPExt(StreamInfo *s,
+ const uint8_t *extHeader, size_t extLen, int32_t *cvoDegrees) {
+ if (extLen < 4)
+ return -1;
+
+ uint16_t header = (extHeader[0] << 8) | (extHeader[1]);
+ bool isOnebyteHeader = false;
+
+ if (header == 0xBEDE) {
+ isOnebyteHeader = true;
+ } else if (header == 0x1000) {
+ ALOGW("parseRTPExt: two-byte header is not implemented yet");
+ return -1;
+ } else {
+ ALOGW("parseRTPExt: can not recognize header");
+ return -1;
+ }
+
+ const uint8_t *extPayload = extHeader + 4;
+ extLen -= 4;
+ size_t offset = 0; //start from first payload of rtp extension.
+ // one-byte header parser
+ while (isOnebyteHeader && offset < extLen) {
+ uint8_t extmapId = extPayload[offset] >> 4;
+ uint8_t length = (extPayload[offset] & 0xF) + 1;
+ offset++;
+
+ // padding case
+ if (extmapId == 0)
+ continue;
+
+ uint8_t data[16]; // maximum length value
+ for (uint8_t j = 0; offset + j <= extLen && j < length; j++) {
+ data[j] = extPayload[offset + j];
+ }
+
+ offset += length;
+
+ if (extmapId == s->mCVOExtMap) {
+ *cvoDegrees = (int32_t)data[0];
+ return OK;
+ }
+ }
+
+ return BAD_VALUE;
+}
+
status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
if (s->mNumRTCPPacketsReceived++ == 0) {
sp<AMessage> notify = s->mNotifyMsg->dup();
notify->setInt32("first-rtcp", true);
notify->post();
+
+ ALOGI("send first-rtcp event to upper layer as ImsRxNotice");
+ sp<AMessage> imsNotify = s->mNotifyMsg->dup();
+ imsNotify->setInt32("rtcp-event", 1);
+ imsNotify->setInt32("payload-type", 101);
+ imsNotify->setInt32("feedback-type", 0);
+ imsNotify->post();
}
const uint8_t *data = buffer->data();
@@ -551,8 +834,12 @@
break;
case 205: // TSFB (transport layer specific feedback)
+ parseTSFB(s, data, headerLength);
+ break;
case 206: // PSFB (payload specific feedback)
// hexdump(data, headerLength);
+ parsePSFB(s, data, headerLength);
+ ALOGI("RTCP packet type %u of size %zu", (unsigned)data[1], headerLength);
break;
case 203:
@@ -589,6 +876,12 @@
sp<ARTPSource> source = findSource(s, id);
+ // Report a final stastics to be used for rtp data usage.
+ int64_t nowUs = ALooper::GetNowUs();
+ int32_t timeDiff = (nowUs - mLastBitrateReportTimeUs) / 1000000ll;
+ int32_t bitrate = mCumulativeBytes * 8 / timeDiff;
+ source->notifyPktInfo(bitrate, true /* isRegular */);
+
source->byeReceived();
return OK;
@@ -621,6 +914,144 @@
return 0;
}
+status_t ARTPConnection::parseTSFB(
+ StreamInfo *s, const uint8_t *data, size_t size) {
+ if (size < 12) {
+ // broken packet
+ return -1;
+ }
+
+ uint8_t msgType = data[0] & 0x1f;
+ uint32_t id = u32at(&data[4]);
+
+ const uint8_t *ptr = &data[12];
+ size -= 12;
+
+ using namespace std;
+ size_t FCISize;
+ switch(msgType) {
+ case 1: // Generic NACK
+ {
+ FCISize = 4;
+ while (size >= FCISize) {
+ uint16_t PID = u16at(&ptr[0]); // lost packet RTP number
+ uint16_t BLP = u16at(&ptr[2]); // Bitmask of following Lost Packets
+
+ size -= FCISize;
+ ptr += FCISize;
+
+ AString list_of_losts;
+ list_of_losts.append(PID);
+ for (int i=0 ; i<16 ; i++) {
+ bool is_lost = BLP & (0x1 << i);
+ if (is_lost) {
+ list_of_losts.append(", ");
+ list_of_losts.append(PID + i);
+ }
+ }
+ ALOGI("Opponent losts packet of RTP %s", list_of_losts.c_str());
+ }
+ break;
+ }
+ case 3: // TMMBR
+ case 4: // TMMBN
+ {
+ FCISize = 8;
+ while (size >= FCISize) {
+ uint32_t MxTBR = u32at(&ptr[4]);
+ uint32_t MxTBRExp = MxTBR >> 26;
+ uint32_t MxTBRMantissa = (MxTBR >> 9) & 0x01FFFF;
+ uint32_t overhead = MxTBR & 0x01FF;
+
+ size -= FCISize;
+ ptr += FCISize;
+
+ uint32_t bitRate = (1 << MxTBRExp) * MxTBRMantissa;
+
+ if (msgType == 3)
+ ALOGI("Op -> UE Req Tx bitrate : %d X 2^%d = %d",
+ MxTBRMantissa, MxTBRExp, bitRate);
+ else if (msgType == 4)
+ ALOGI("OP -> UE Noti Rx bitrate : %d X 2^%d = %d",
+ MxTBRMantissa, MxTBRExp, bitRate);
+
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", 205);
+ notify->setInt32("feedback-type", msgType);
+ notify->setInt32("sender", id);
+ notify->setInt32("bit-rate", bitRate);
+ notify->post();
+ ALOGI("overhead : %d", overhead);
+ }
+ break;
+ }
+ default:
+ {
+ ALOGI("Not supported TSFB type %d", msgType);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+status_t ARTPConnection::parsePSFB(
+ StreamInfo *s, const uint8_t *data, size_t size) {
+ if (size < 12) {
+ // broken packet
+ return -1;
+ }
+
+ uint8_t msgType = data[0] & 0x1f;
+ uint32_t id = u32at(&data[4]);
+
+ const uint8_t *ptr = &data[12];
+ size -= 12;
+
+ using namespace std;
+ switch(msgType) {
+ case 1: // Picture Loss Indication (PLI)
+ {
+ if (size > 0) {
+ // PLI does not need parameters
+ break;
+ };
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", 206);
+ notify->setInt32("feedback-type", msgType);
+ notify->setInt32("sender", id);
+ notify->post();
+ ALOGI("PLI detected.");
+ break;
+ }
+ case 4: // Full Intra Request (FIR)
+ {
+ if (size < 4) {
+ break;
+ }
+ uint32_t requestedId = u32at(&ptr[0]);
+ if (requestedId == (uint32_t)mSelfID) {
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", 206);
+ notify->setInt32("feedback-type", msgType);
+ notify->setInt32("sender", id);
+ notify->post();
+ ALOGI("FIR detected.");
+ }
+ break;
+ }
+ default:
+ {
+ ALOGI("Not supported PSFB type %d", msgType);
+ break;
+ }
+ }
+
+ return 0;
+}
sp<ARTPSource> ARTPConnection::findSource(StreamInfo *info, uint32_t srcId) {
sp<ARTPSource> source;
ssize_t index = info->mSources.indexOfKey(srcId);
@@ -630,6 +1061,12 @@
source = new ARTPSource(
srcId, info->mSessionDesc, info->mIndex, info->mNotifyMsg);
+ if (mFlags & kViLTEConnection) {
+ source->setPeriodicFIR(false);
+ }
+
+ source->setSelfID(mSelfID);
+ source->setJbTime(mJbTimeMs > 0 ? mJbTimeMs : 300);
info->mSources.add(srcId, source);
} else {
source = info->mSources.valueAt(index);
@@ -645,6 +1082,78 @@
msg->post();
}
+void ARTPConnection::setSelfID(const uint32_t selfID) {
+ mSelfID = selfID;
+}
+
+void ARTPConnection::setJbTime(const uint32_t jbTimeMs) {
+ mJbTimeMs = jbTimeMs;
+}
+
+void ARTPConnection::setTargetBitrate(int32_t targetBitrate) {
+ mTargetBitrate = targetBitrate;
+}
+
+void ARTPConnection::checkRxBitrate(int64_t nowUs) {
+ if (mLastBitrateReportTimeUs <= 0) {
+ mCumulativeBytes = 0;
+ mLastBitrateReportTimeUs = nowUs;
+ }
+ else if (mLastEarlyNotifyTimeUs + 100000ll <= nowUs) {
+ int32_t timeDiff = (nowUs - mLastBitrateReportTimeUs) / 1000000ll;
+ int32_t bitrate = mCumulativeBytes * 8 / timeDiff;
+ mLastEarlyNotifyTimeUs = nowUs;
+
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()) {
+ StreamInfo *s = &*it;
+ if (s->mIsInjected) {
+ ++it;
+ continue;
+ }
+ for (size_t i = 0; i < s->mSources.size(); ++i) {
+ sp<ARTPSource> source = s->mSources.valueAt(i);
+ if (source->isNeedToEarlyNotify()) {
+ source->notifyPktInfo(bitrate, false /* isRegular */);
+ mLastEarlyNotifyTimeUs = nowUs + (1000000ll * 3600 * 24); // after 1 day
+ }
+ }
+ ++it;
+ }
+ }
+ else if (mLastBitrateReportTimeUs + 1000000ll <= nowUs) {
+ int32_t timeDiff = (nowUs - mLastBitrateReportTimeUs) / 1000000ll;
+ int32_t bitrate = mCumulativeBytes * 8 / timeDiff;
+ ALOGI("Actual Rx bitrate : %d bits/sec", bitrate);
+
+ sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()) {
+ StreamInfo *s = &*it;
+ if (s->mIsInjected) {
+ ++it;
+ continue;
+ }
+
+ if (s->mNumRTCPPacketsReceived == 0) {
+ // We have never received any RTCP packets on this stream,
+ // we don't even know where to send a report.
+ ++it;
+ continue;
+ }
+
+ buffer->setRange(0, 0);
+ for (size_t i = 0; i < s->mSources.size(); ++i) {
+ sp<ARTPSource> source = s->mSources.valueAt(i);
+ source->notifyPktInfo(bitrate, true /* isRegular */);
+ }
+ ++it;
+ }
+ mCumulativeBytes = 0;
+ mLastBitrateReportTimeUs = nowUs;
+ mLastEarlyNotifyTimeUs = nowUs;
+ }
+}
void ARTPConnection::onInjectPacket(const sp<AMessage> &msg) {
int32_t index;
CHECK(msg->findInt32("index", &index));
@@ -672,4 +1181,3 @@
}
} // namespace android
-
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index d5f7c2e..a37ac0e 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -30,6 +30,7 @@
struct ARTPConnection : public AHandler {
enum Flags {
kRegularlyRequestFIR = 2,
+ kViLTEConnection = 4,
};
explicit ARTPConnection(uint32_t flags = 0);
@@ -44,11 +45,22 @@
void injectPacket(int index, const sp<ABuffer> &buffer);
+ void setSelfID(const uint32_t selfID);
+ void setJbTime(const uint32_t jbTimeMs);
+ void setTargetBitrate(int32_t targetBitrate);
+
// Creates a pair of UDP datagram sockets bound to adjacent ports
// (the rtpSocket is bound to an even port, the rtcpSocket to the
// next higher port).
static void MakePortPair(
int *rtpSocket, int *rtcpSocket, unsigned *rtpPort);
+ // Creates a pair of UDP datagram sockets bound to assigned ip and
+ // ports (the rtpSocket is bound to an even port, the rtcpSocket
+ // to the next higher port).
+ static void MakeRTPSocketPair(
+ int *rtpSocket, int *rtcpSocket,
+ const char *localIp, const char *remoteIp,
+ unsigned localPort, unsigned remotePort, int64_t socketNetwork = 0);
protected:
virtual ~ARTPConnection();
@@ -71,18 +83,32 @@
bool mPollEventPending;
int64_t mLastReceiverReportTimeUs;
+ int64_t mLastBitrateReportTimeUs;
+ int64_t mLastEarlyNotifyTimeUs;
+
+ int32_t mSelfID;
+ int32_t mTargetBitrate;
+
+ uint32_t mJbTimeMs;
+
+ int32_t mCumulativeBytes;
void onAddStream(const sp<AMessage> &msg);
void onRemoveStream(const sp<AMessage> &msg);
void onPollStreams();
void onInjectPacket(const sp<AMessage> &msg);
void onSendReceiverReports();
+ void checkRxBitrate(int64_t nowUs);
status_t receive(StreamInfo *info, bool receiveRTP);
+ ssize_t send(const StreamInfo *info, const sp<ABuffer> buffer);
status_t parseRTP(StreamInfo *info, const sp<ABuffer> &buffer);
+ status_t parseRTPExt(StreamInfo *s, const uint8_t *extData, size_t extLen, int32_t *cvoDegrees);
status_t parseRTCP(StreamInfo *info, const sp<ABuffer> &buffer);
status_t parseSR(StreamInfo *info, const uint8_t *data, size_t size);
+ status_t parseTSFB(StreamInfo *info, const uint8_t *data, size_t size);
+ status_t parsePSFB(StreamInfo *info, const uint8_t *data, size_t size);
status_t parseBYE(StreamInfo *info, const uint8_t *data, size_t size);
sp<ARTPSource> findSource(StreamInfo *info, uint32_t id);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index f5f8128..3fdf8e4 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -22,6 +22,7 @@
#include "AAMRAssembler.h"
#include "AAVCAssembler.h"
+#include "AHEVCAssembler.h"
#include "AH263Assembler.h"
#include "AMPEG2TSAssembler.h"
#include "AMPEG4AudioAssembler.h"
@@ -33,23 +34,35 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <strings.h>
+
namespace android {
-static const uint32_t kSourceID = 0xdeadbeef;
+static uint32_t kSourceID = 0xdeadbeef;
ARTPSource::ARTPSource(
uint32_t id,
const sp<ASessionDescription> &sessionDesc, size_t index,
const sp<AMessage> ¬ify)
- : mID(id),
+ : mFirstSeqNumber(0),
+ mFirstRtpTime(0),
+ mFirstSysTime(0),
+ mClockRate(0),
+ mJbTimeMs(300), // default jitter buffer time is 300ms.
+ mFirstSsrc(0),
+ mHighestNackNumber(0),
+ mID(id),
mHighestSeqNumber(0),
mPrevExpected(0),
mBaseSeqNumber(0),
mNumBuffersReceived(0),
mPrevNumBuffersReceived(0),
+ mPrevExpectedForRR(0),
+ mPrevNumBuffersReceivedForRR(0),
mLastNTPTime(0),
mLastNTPTimeUpdateUs(0),
mIssueFIRRequests(false),
+ mIssueFIRByAssembler(false),
mLastFIRRequestUs(-1),
mNextFIRSeqNo((rand() * 256.0) / RAND_MAX),
mNotify(notify) {
@@ -61,6 +74,9 @@
if (!strncmp(desc.c_str(), "H264/", 5)) {
mAssembler = new AAVCAssembler(notify);
mIssueFIRRequests = true;
+ } else if (!strncmp(desc.c_str(), "H265/", 5)) {
+ mAssembler = new AHEVCAssembler(notify);
+ mIssueFIRRequests = true;
} else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
mAssembler = new AMPEG4AudioAssembler(notify, params);
} else if (!strncmp(desc.c_str(), "H263-1998/", 10)
@@ -112,13 +128,29 @@
bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
uint32_t seqNum = (uint32_t)buffer->int32Data();
- if (mNumBuffersReceived++ == 0) {
+ int32_t ssrc = 0;
+ buffer->meta()->findInt32("ssrc", &ssrc);
+
+ if (mNumBuffersReceived++ == 0 && mFirstSysTime == 0) {
+ uint32_t firstRtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&firstRtpTime));
+ mFirstSysTime = ALooper::GetNowUs();
mHighestSeqNumber = seqNum;
mBaseSeqNumber = seqNum;
+ mFirstRtpTime = firstRtpTime;
+ mFirstSsrc = ssrc;
+ ALOGD("first-rtp arrived: first-rtp-time=%d, sys-time=%lld, seq-num=%u, ssrc=%d",
+ mFirstRtpTime, (long long)mFirstSysTime, mHighestSeqNumber, mFirstSsrc);
+ mClockRate = 90000;
mQueue.push_back(buffer);
return true;
}
+ if (mFirstSsrc != ssrc) {
+ ALOGW("Discarding a buffer due to unexpected ssrc");
+ return false;
+ }
+
// Only the lower 16-bit of the sequence numbers are transmitted,
// derive the high-order bits by choosing the candidate closest
// to the highest sequence number (extended to 32 bits) received so far.
@@ -181,20 +213,34 @@
}
void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
- if (!mIssueFIRRequests) {
+ if (!mIssueFIRRequests && !mIssueFIRByAssembler) {
return;
}
+ bool send = false;
int64_t nowUs = ALooper::GetNowUs();
- if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000LL > nowUs) {
- // Send FIR requests at most every 5 secs.
+ int64_t usecsSinceLastFIR = nowUs - mLastFIRRequestUs;
+ if (mLastFIRRequestUs < 0) {
+ // A first FIR, just send it.
+ send = true;
+ } else if (mIssueFIRByAssembler && (usecsSinceLastFIR > 1000000)) {
+ // A FIR issued by Assembler.
+ // Send it if last FIR is not sent within a sec.
+ send = true;
+ } else if (mIssueFIRRequests && (usecsSinceLastFIR > 5000000)) {
+ // A FIR issued periodically regardless packet loss.
+ // Send it if last FIR is not sent within 5 secs.
+ send = true;
+ }
+
+ if (!send) {
return;
}
mLastFIRRequestUs = nowUs;
if (buffer->size() + 20 > buffer->capacity()) {
- ALOGW("RTCP buffer too small to accomodate FIR.");
+ ALOGW("RTCP buffer too small to accommodate FIR.");
return;
}
@@ -203,7 +249,7 @@
data[0] = 0x80 | 4;
data[1] = 206; // PSFB
data[2] = 0;
- data[3] = 4;
+ data[3] = 4; // total (4+1) * sizeof(int32_t) = 20 bytes
data[4] = kSourceID >> 24;
data[5] = (kSourceID >> 16) & 0xff;
data[6] = (kSourceID >> 8) & 0xff;
@@ -225,14 +271,16 @@
data[18] = 0x00;
data[19] = 0x00;
- buffer->setRange(buffer->offset(), buffer->size() + 20);
+ buffer->setRange(buffer->offset(), buffer->size() + (data[3] + 1) * sizeof(int32_t));
+
+ mIssueFIRByAssembler = false;
ALOGV("Added FIR request.");
}
void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) {
if (buffer->size() + 32 > buffer->capacity()) {
- ALOGW("RTCP buffer too small to accomodate RR.");
+ ALOGW("RTCP buffer too small to accommodate RR.");
return;
}
@@ -240,16 +288,16 @@
// According to appendix A.3 in RFC 3550
uint32_t expected = mHighestSeqNumber - mBaseSeqNumber + 1;
- int64_t intervalExpected = expected - mPrevExpected;
- int64_t intervalReceived = mNumBuffersReceived - mPrevNumBuffersReceived;
+ int64_t intervalExpected = expected - mPrevExpectedForRR;
+ int64_t intervalReceived = mNumBuffersReceived - mPrevNumBuffersReceivedForRR;
int64_t intervalPacketLost = intervalExpected - intervalReceived;
if (intervalExpected > 0 && intervalPacketLost > 0) {
fraction = (intervalPacketLost << 8) / intervalExpected;
}
- mPrevExpected = expected;
- mPrevNumBuffersReceived = mNumBuffersReceived;
+ mPrevExpectedForRR = expected;
+ mPrevNumBuffersReceivedForRR = mNumBuffersReceived;
int32_t cumulativePacketLost = (int32_t)expected - mNumBuffersReceived;
uint8_t *data = buffer->data() + buffer->size();
@@ -257,7 +305,7 @@
data[0] = 0x80 | 1;
data[1] = 201; // RR
data[2] = 0;
- data[3] = 7;
+ data[3] = 7; // total (7+1) * sizeof(int32_t) = 32 bytes
data[4] = kSourceID >> 24;
data[5] = (kSourceID >> 16) & 0xff;
data[6] = (kSourceID >> 8) & 0xff;
@@ -303,9 +351,210 @@
data[30] = (DLSR >> 8) & 0xff;
data[31] = DLSR & 0xff;
- buffer->setRange(buffer->offset(), buffer->size() + 32);
+ buffer->setRange(buffer->offset(), buffer->size() + (data[3] + 1) * sizeof(int32_t));
}
+void ARTPSource::addTMMBR(const sp<ABuffer> &buffer, int32_t targetBitrate) {
+ if (buffer->size() + 20 > buffer->capacity()) {
+ ALOGW("RTCP buffer too small to accommodate RR.");
+ return;
+ }
+
+ if (targetBitrate <= 0) {
+ return;
+ }
+
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 3; // TMMBR
+ data[1] = 205; // TSFB
+ data[2] = 0;
+ data[3] = 4; // total (4+1) * sizeof(int32_t) = 20 bytes
+ data[4] = kSourceID >> 24;
+ data[5] = (kSourceID >> 16) & 0xff;
+ data[6] = (kSourceID >> 8) & 0xff;
+ data[7] = kSourceID & 0xff;
+
+ *(int32_t*)(&data[8]) = 0; // 4 bytes blank
+
+ data[12] = mID >> 24;
+ data[13] = (mID >> 16) & 0xff;
+ data[14] = (mID >> 8) & 0xff;
+ data[15] = mID & 0xff;
+
+ // Find the first bit '1' from left & right side of the value.
+ int32_t leftEnd = 31 - __builtin_clz(targetBitrate);
+ int32_t rightEnd = ffs(targetBitrate) - 1;
+
+ // Mantissa have only 17bit space by RTCP specification.
+ if ((leftEnd - rightEnd) > 16) {
+ rightEnd = leftEnd - 16;
+ }
+ int32_t mantissa = targetBitrate >> rightEnd;
+
+ data[16] = ((rightEnd << 2) & 0xfc) | ((mantissa & 0x18000) >> 15);
+ data[17] = (mantissa & 0x07f80) >> 7;
+ data[18] = (mantissa & 0x0007f) << 1;
+ data[19] = 40; // 40 bytes overhead;
+
+ buffer->setRange(buffer->offset(), buffer->size() + (data[3] + 1) * sizeof(int32_t));
+
+ ALOGI("UE -> Op Req Rx bitrate : %d ", mantissa << rightEnd);
+}
+
+int ARTPSource::addNACK(const sp<ABuffer> &buffer) {
+ constexpr size_t kMaxFCIs = 10; // max number of FCIs
+ if (buffer->size() + (3 + kMaxFCIs) * sizeof(int32_t) > buffer->capacity()) {
+ ALOGW("RTCP buffer too small to accommodate NACK.");
+ return -1;
+ }
+
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 1; // Generic NACK
+ data[1] = 205; // TSFB
+ data[2] = 0;
+ data[3] = 0; // will be decided later
+ data[4] = kSourceID >> 24;
+ data[5] = (kSourceID >> 16) & 0xff;
+ data[6] = (kSourceID >> 8) & 0xff;
+ data[7] = kSourceID & 0xff;
+
+ data[8] = mID >> 24;
+ data[9] = (mID >> 16) & 0xff;
+ data[10] = (mID >> 8) & 0xff;
+ data[11] = mID & 0xff;
+
+ List<int> list;
+ List<int>::iterator it;
+ getSeqNumToNACK(list, kMaxFCIs);
+ size_t cnt = 0;
+
+ int *FCI = (int *)(data + 12);
+ for (it = list.begin(); it != list.end() && cnt < kMaxFCIs; it++) {
+ *(FCI + cnt) = *it;
+ cnt++;
+ }
+
+ data[3] = (3 + cnt) - 1; // total (3 + #ofFCI) * sizeof(int32_t) byte
+
+ buffer->setRange(buffer->offset(), buffer->size() + (data[3] + 1) * sizeof(int32_t));
+
+ return cnt;
+}
+
+int ARTPSource::getSeqNumToNACK(List<int>& list, int size) {
+ AutoMutex _l(mMapLock);
+ int cnt = 0;
+
+ std::map<uint16_t, infoNACK>::iterator it;
+ for(it = mNACKMap.begin(); it != mNACKMap.end() && cnt < size; it++) {
+ infoNACK &info_it = it->second;
+ if (info_it.needToNACK) {
+ info_it.needToNACK = false;
+ // switch LSB to MSB for sending N/W
+ uint32_t FCI;
+ uint8_t *temp = (uint8_t *)&FCI;
+ temp[0] = (info_it.seqNum >> 8) & 0xff;
+ temp[1] = (info_it.seqNum) & 0xff;
+ temp[2] = (info_it.mask >> 8) & 0xff;
+ temp[3] = (info_it.mask) & 0xff;
+
+ list.push_back(FCI);
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+
+void ARTPSource::setSeqNumToNACK(uint16_t seqNum, uint16_t mask, uint16_t nowJitterHeadSeqNum) {
+ AutoMutex _l(mMapLock);
+ infoNACK info = {seqNum, mask, nowJitterHeadSeqNum, true};
+ std::map<uint16_t, infoNACK>::iterator it;
+
+ it = mNACKMap.find(seqNum);
+ if (it != mNACKMap.end()) {
+ infoNACK &info_it = it->second;
+ // renew if (mask or head seq) is changed
+ if ((info_it.mask != mask) || (info_it.nowJitterHeadSeqNum != nowJitterHeadSeqNum)) {
+ info_it = info;
+ }
+ } else {
+ mNACKMap[seqNum] = info;
+ }
+
+ // delete all NACK far from current Jitter's first sequence number
+ it = mNACKMap.begin();
+ while (it != mNACKMap.end()) {
+ infoNACK &info_it = it->second;
+
+ int diff = nowJitterHeadSeqNum - info_it.nowJitterHeadSeqNum;
+ if (diff > 100) {
+ ALOGV("Delete %d pkt from NACK map ", info_it.seqNum);
+ it = mNACKMap.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+}
+
+uint32_t ARTPSource::getSelfID() {
+ return kSourceID;
+}
+
+void ARTPSource::setSelfID(const uint32_t selfID) {
+ kSourceID = selfID;
+}
+
+void ARTPSource::setJbTime(const uint32_t jbTimeMs) {
+ mJbTimeMs = jbTimeMs;
+}
+
+void ARTPSource::setPeriodicFIR(bool enable) {
+ ALOGD("setPeriodicFIR %d", enable);
+ mIssueFIRRequests = enable;
+}
+
+bool ARTPSource::isNeedToEarlyNotify() {
+ uint32_t expected = mHighestSeqNumber - mBaseSeqNumber + 1;
+ int32_t intervalExpectedInNow = expected - mPrevExpected;
+ int32_t intervalReceivedInNow = mNumBuffersReceived - mPrevNumBuffersReceived;
+
+ if (intervalExpectedInNow - intervalReceivedInNow > 5)
+ return true;
+ return false;
+}
+
+void ARTPSource::notifyPktInfo(int32_t bitrate, bool isRegular) {
+ int32_t payloadType = isRegular ? RTP_QUALITY : RTP_QUALITY_EMC;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", payloadType);
+ notify->setInt32("feedback-type", 0);
+ // sending target bitrate up to application to share rtp quality.
+ notify->setInt32("bit-rate", bitrate);
+ notify->setInt32("highest-seq-num", mHighestSeqNumber);
+ notify->setInt32("base-seq-num", mBaseSeqNumber);
+ notify->setInt32("prev-expected", mPrevExpected);
+ notify->setInt32("num-buf-recv", mNumBuffersReceived);
+ notify->setInt32("prev-num-buf-recv", mPrevNumBuffersReceived);
+ notify->post();
+
+ if (isRegular) {
+ uint32_t expected = mHighestSeqNumber - mBaseSeqNumber + 1;
+ mPrevExpected = expected;
+ mPrevNumBuffersReceived = mNumBuffersReceived;
+ }
+}
+
+void ARTPSource::onIssueFIRByAssembler() {
+ mIssueFIRByAssembler = true;
+}
+
+void ARTPSource::noticeAbandonBuffer(int cnt) {
+ mNumBuffersReceived -= cnt;
+}
} // namespace android
-
-
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index f44e83f..c51fd8a 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -23,6 +23,9 @@
#include <media/stagefright/foundation/ABase.h>
#include <utils/List.h>
#include <utils/RefBase.h>
+#include <utils/Thread.h>
+
+#include <map>
namespace android {
@@ -37,6 +40,17 @@
const sp<ASessionDescription> &sessionDesc, size_t index,
const sp<AMessage> ¬ify);
+ enum {
+ RTP_FIRST_PACKET = 100,
+ RTCP_FIRST_PACKET = 101,
+ RTP_QUALITY = 102,
+ RTP_QUALITY_EMC = 103,
+ RTCP_TSFB = 205,
+ RTCP_PSFB = 206,
+ RTP_CVO = 300,
+ RTP_AUTODOWN = 400,
+ };
+
void processRTPPacket(const sp<ABuffer> &buffer);
void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
void byeReceived();
@@ -45,22 +59,59 @@
void addReceiverReport(const sp<ABuffer> &buffer);
void addFIR(const sp<ABuffer> &buffer);
+ void addTMMBR(const sp<ABuffer> &buffer, int32_t targetBitrate);
+ int addNACK(const sp<ABuffer> &buffer);
+ void setSeqNumToNACK(uint16_t seqNum, uint16_t mask, uint16_t nowJitterHeadSeqNum);
+ uint32_t getSelfID();
+ void setSelfID(const uint32_t selfID);
+ void setJbTime(const uint32_t jbTimeMs);
+ void setPeriodicFIR(bool enable);
+ bool isNeedToEarlyNotify();
+ void notifyPktInfo(int32_t bitrate, bool isRegular);
+ // FIR needs to be sent by missing packet or broken video image.
+ void onIssueFIRByAssembler();
+
+ void noticeAbandonBuffer(int cnt=1);
+
+ int32_t mFirstSeqNumber;
+ uint32_t mFirstRtpTime;
+ int64_t mFirstSysTime;
+ int32_t mClockRate;
+
+ uint32_t mJbTimeMs;
+ int32_t mFirstSsrc;
+ int32_t mHighestNackNumber;
private:
+
uint32_t mID;
uint32_t mHighestSeqNumber;
uint32_t mPrevExpected;
uint32_t mBaseSeqNumber;
int32_t mNumBuffersReceived;
int32_t mPrevNumBuffersReceived;
+ uint32_t mPrevExpectedForRR;
+ int32_t mPrevNumBuffersReceivedForRR;
List<sp<ABuffer> > mQueue;
sp<ARTPAssembler> mAssembler;
+ typedef struct infoNACK {
+ uint16_t seqNum;
+ uint16_t mask;
+ uint16_t nowJitterHeadSeqNum;
+ bool needToNACK;
+ } infoNACK;
+
+ Mutex mMapLock;
+ std::map<uint16_t, infoNACK> mNACKMap;
+ int getSeqNumToNACK(List<int>& list, int size);
+
uint64_t mLastNTPTime;
int64_t mLastNTPTimeUpdateUs;
bool mIssueFIRRequests;
+ bool mIssueFIRByAssembler;
int64_t mLastFIRRequestUs;
uint8_t mNextFIRSeqNo;
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 58d6086..ec70952 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -20,8 +20,6 @@
#include "ARTPWriter.h"
-#include <fcntl.h>
-
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -32,13 +30,43 @@
#include <media/stagefright/MetaData.h>
#include <utils/ByteOrder.h>
+#include <fcntl.h>
+#include <strings.h>
+
#define PT 97
#define PT_STR "97"
+#define H264_NALU_MASK 0x1F
+#define H264_NALU_SPS 0x7
+#define H264_NALU_PPS 0x8
+#define H264_NALU_IFRAME 0x5
+#define H264_NALU_PFRAME 0x1
+
+#define H265_NALU_MASK 0x3F
+#define H265_NALU_VPS 0x20
+#define H265_NALU_SPS 0x21
+#define H265_NALU_PPS 0x22
+
+#define IPV4_HEADER_SIZE 20
+#define IPV6_HEADER_SIZE 40
+#define UDP_HEADER_SIZE 8
+#define TCPIPV4_HEADER_SIZE (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
+#define TCPIPV6_HEADER_SIZE (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
+#define TCPIP_HEADER_SIZE TCPIPV4_HEADER_SIZE
+#define RTP_HEADER_SIZE 12
+#define RTP_HEADER_EXT_SIZE 8
+#define RTP_FU_HEADER_SIZE 2
+#define RTP_PAYLOAD_ROOM_SIZE 100 // ROOM size for IPv6 header, ESP and etc.
+
+
namespace android {
// static const size_t kMaxPacketSize = 65507; // maximum payload in UDP over IP
-static const size_t kMaxPacketSize = 1500;
+static const size_t kMaxPacketSize = 1280;
+static char kCNAME[255] = "someone@somewhere";
+
+static const size_t kTrafficRecorderMaxEntries = 128;
+static const size_t kTrafficRecorderMaxTimeSpanMs = 2000;
static int UniformRand(int limit) {
return ((double)rand() * limit) / RAND_MAX;
@@ -48,15 +76,20 @@
: mFlags(0),
mFd(dup(fd)),
mLooper(new ALooper),
- mReflector(new AHandlerReflector<ARTPWriter>(this)) {
+ mReflector(new AHandlerReflector<ARTPWriter>(this)),
+ mTrafficRec(new TrafficRecorder<uint32_t /* Time */, Bytes>(
+ kTrafficRecorderMaxEntries, kTrafficRecorderMaxTimeSpanMs)) {
CHECK_GE(fd, 0);
+ mIsIPv6 = false;
mLooper->setName("rtp writer");
mLooper->registerHandler(mReflector);
mLooper->start();
- mSocket = socket(AF_INET, SOCK_DGRAM, 0);
- CHECK_GE(mSocket, 0);
+ mRTPSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(mRTPSocket, 0);
+ mRTCPSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(mRTCPSocket, 0);
memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
mRTPAddr.sin_family = AF_INET;
@@ -72,6 +105,46 @@
mRTCPAddr = mRTPAddr;
mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
+ mSPSBuf = NULL;
+ mPPSBuf = NULL;
+
+#if LOG_TO_FILES
+ mRTPFd = open(
+ "/data/misc/rtpout.bin",
+ O_WRONLY | O_CREAT | O_TRUNC,
+ 0644);
+ CHECK_GE(mRTPFd, 0);
+
+ mRTCPFd = open(
+ "/data/misc/rtcpout.bin",
+ O_WRONLY | O_CREAT | O_TRUNC,
+ 0644);
+ CHECK_GE(mRTCPFd, 0);
+#endif
+}
+
+ARTPWriter::ARTPWriter(int fd, String8& localIp, int localPort, String8& remoteIp,
+ int remotePort, uint32_t seqNo)
+ : mFlags(0),
+ mFd(dup(fd)),
+ mLooper(new ALooper),
+ mReflector(new AHandlerReflector<ARTPWriter>(this)),
+ mTrafficRec(new TrafficRecorder<uint32_t /* Time */, Bytes>(
+ kTrafficRecorderMaxEntries, kTrafficRecorderMaxTimeSpanMs)) {
+ CHECK_GE(fd, 0);
+ mIsIPv6 = false;
+
+ mLooper->setName("rtp writer");
+ mLooper->registerHandler(mReflector);
+ mLooper->start();
+
+ makeSocketPairAndBind(localIp, localPort, remoteIp , remotePort);
+ mVPSBuf = NULL;
+ mSPSBuf = NULL;
+ mPPSBuf = NULL;
+
+ initState();
+ mSeqNo = seqNo; // Must use explicit # of seq for RTP continuity
#if LOG_TO_FILES
mRTPFd = open(
@@ -89,6 +162,21 @@
}
ARTPWriter::~ARTPWriter() {
+ if (mVPSBuf != NULL) {
+ mVPSBuf->release();
+ mVPSBuf = NULL;
+ }
+
+ if (mSPSBuf != NULL) {
+ mSPSBuf->release();
+ mSPSBuf = NULL;
+ }
+
+ if (mPPSBuf != NULL) {
+ mPPSBuf->release();
+ mPPSBuf = NULL;
+ }
+
#if LOG_TO_FILES
close(mRTCPFd);
mRTCPFd = -1;
@@ -97,13 +185,39 @@
mRTPFd = -1;
#endif
- close(mSocket);
- mSocket = -1;
+ close(mRTPSocket);
+ mRTPSocket = -1;
+
+ close(mRTCPSocket);
+ mRTCPSocket = -1;
close(mFd);
mFd = -1;
}
+void ARTPWriter::initState() {
+ if (mSourceID == 0)
+ mSourceID = rand();
+ mPayloadType = 0;
+ if (mSeqNo == 0)
+ mSeqNo = UniformRand(65536);
+ mRTPTimeBase = 0;
+ mNumRTPSent = 0;
+ mNumRTPOctetsSent = 0;
+ mLastRTPTime = 0;
+ mLastNTPTime = 0;
+
+ mOpponentID = 0;
+ mBitrate = 192000;
+
+ mNumSRsSent = 0;
+ mRTPCVOExtMap = -1;
+ mRTPCVODegrees = 0;
+ mRTPSockNetwork = 0;
+
+ mMode = INVALID;
+}
+
status_t ARTPWriter::addSource(const sp<MediaSource> &source) {
mSource = source;
return OK;
@@ -114,28 +228,46 @@
return (mFlags & kFlagEOS) != 0;
}
-status_t ARTPWriter::start(MetaData * /* params */) {
+status_t ARTPWriter::start(MetaData * params) {
Mutex::Autolock autoLock(mLock);
if (mFlags & kFlagStarted) {
return INVALID_OPERATION;
}
mFlags &= ~kFlagEOS;
- mSourceID = rand();
- mSeqNo = UniformRand(65536);
- mRTPTimeBase = rand();
- mNumRTPSent = 0;
- mNumRTPOctetsSent = 0;
- mLastRTPTime = 0;
- mLastNTPTime = 0;
- mNumSRsSent = 0;
+ initState();
const char *mime;
CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
- mMode = INVALID;
+ int32_t selfID = 0;
+ if (params->findInt32(kKeySelfID, &selfID))
+ mSourceID = selfID;
+
+ int32_t payloadType = 0;
+ if (params->findInt32(kKeyPayloadType, &payloadType))
+ mPayloadType = payloadType;
+
+ int32_t rtpExtMap = 0;
+ if (params->findInt32(kKeyRtpExtMap, &rtpExtMap))
+ mRTPCVOExtMap = rtpExtMap;
+
+ int32_t rtpCVODegrees = 0;
+ if (params->findInt32(kKeyRtpCvoDegrees, &rtpCVODegrees))
+ mRTPCVODegrees = rtpCVODegrees;
+
+ int32_t dscp = 0;
+ if (params->findInt32(kKeyRtpDscp, &dscp))
+ updateSocketDscp(dscp);
+
+ int64_t sockNetwork = 0;
+ if (params->findInt64(kKeySocketNetwork, &sockNetwork))
+ updateSocketNetwork(sockNetwork);
+
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
mMode = H264;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
+ mMode = H265;
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
mMode = H263;
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
@@ -187,11 +319,137 @@
}
}
+static const uint8_t SPCSize = 4; // Start Prefix Code Size
+static const uint8_t startPrefixCode[SPCSize] = {0, 0, 0, 1};
+static const uint8_t spcKMPidx[SPCSize] = {0, 0, 2, 0};
+static void SpsPpsParser(MediaBufferBase *buffer,
+ MediaBufferBase **spsBuffer, MediaBufferBase **ppsBuffer) {
+
+ while (buffer->range_length() > 0) {
+ const uint8_t *NALPtr = (const uint8_t *)buffer->data() + buffer->range_offset();
+
+ MediaBufferBase **targetPtr = NULL;
+ if ((*NALPtr & H264_NALU_MASK) == H264_NALU_SPS) {
+ targetPtr = spsBuffer;
+ } else if ((*NALPtr & H264_NALU_MASK) == H264_NALU_PPS) {
+ targetPtr = ppsBuffer;
+ } else {
+ return;
+ }
+ ALOGV("SPS(7) or PPS(8) found. Type %d", *NALPtr & H264_NALU_MASK);
+
+ uint32_t bufferSize = buffer->range_length();
+ MediaBufferBase *&target = *targetPtr;
+ uint32_t i = 0, j = 0;
+ bool isBoundFound = false;
+ for (i = 0; i < bufferSize; i++) {
+ while (j > 0 && NALPtr[i] != startPrefixCode[j]) {
+ j = spcKMPidx[j - 1];
+ }
+ if (NALPtr[i] == startPrefixCode[j]) {
+ j++;
+ if (j == SPCSize) {
+ isBoundFound = true;
+ break;
+ }
+ }
+ }
+
+ uint32_t targetSize;
+ if (target != NULL) {
+ target->release();
+ }
+ // note that targetSize is never 0 as the first byte is never part
+ // of a start prefix
+ if (isBoundFound) {
+ targetSize = i - SPCSize + 1;
+ target = MediaBufferBase::Create(targetSize);
+ memcpy(target->data(),
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ targetSize);
+ buffer->set_range(buffer->range_offset() + targetSize + SPCSize,
+ buffer->range_length() - targetSize - SPCSize);
+ } else {
+ targetSize = bufferSize;
+ target = MediaBufferBase::Create(targetSize);
+ memcpy(target->data(),
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ targetSize);
+ buffer->set_range(buffer->range_offset() + bufferSize, 0);
+ return;
+ }
+ }
+}
+
+static void VpsSpsPpsParser(MediaBufferBase *buffer,
+ MediaBufferBase **vpsBuffer, MediaBufferBase **spsBuffer, MediaBufferBase **ppsBuffer) {
+
+ while (buffer->range_length() > 0) {
+ const uint8_t *NALPtr = (const uint8_t *)buffer->data() + buffer->range_offset();
+ uint8_t nalType = ((*NALPtr) >> 1) & H265_NALU_MASK;
+
+ MediaBufferBase **targetPtr = NULL;
+ if (nalType == H265_NALU_VPS) {
+ targetPtr = vpsBuffer;
+ } else if (nalType == H265_NALU_SPS) {
+ targetPtr = spsBuffer;
+ } else if (nalType == H265_NALU_PPS) {
+ targetPtr = ppsBuffer;
+ } else {
+ return;
+ }
+ ALOGV("VPS(32) SPS(33) or PPS(34) found. Type %d", nalType);
+
+ uint32_t bufferSize = buffer->range_length();
+ MediaBufferBase *&target = *targetPtr;
+ uint32_t i = 0, j = 0;
+ bool isBoundFound = false;
+ for (i = 0; i < bufferSize; i++) {
+ while (j > 0 && NALPtr[i] != startPrefixCode[j]) {
+ j = spcKMPidx[j - 1];
+ }
+ if (NALPtr[i] == startPrefixCode[j]) {
+ j++;
+ if (j == SPCSize) {
+ isBoundFound = true;
+ break;
+ }
+ }
+ }
+
+ if (target != NULL) {
+ target->release();
+ }
+ uint32_t targetSize;
+ // note that targetSize is never 0 as the first byte is never part
+ // of a start prefix
+ if (isBoundFound) {
+ targetSize = i - SPCSize + 1;
+ target = MediaBufferBase::Create(j);
+ memcpy(target->data(),
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ j);
+ buffer->set_range(buffer->range_offset() + targetSize + SPCSize,
+ buffer->range_length() - targetSize - SPCSize);
+ } else {
+ targetSize = bufferSize;
+ target = MediaBufferBase::Create(targetSize);
+ memcpy(target->data(),
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ targetSize);
+ buffer->set_range(buffer->range_offset() + bufferSize, 0);
+ return;
+ }
+ }
+}
+
void ARTPWriter::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatStart:
{
- CHECK_EQ(mSource->start(), (status_t)OK);
+ sp<MetaData> meta = new MetaData();
+ meta->setInt64(kKeyTime, 10ll);
+ CHECK_EQ(mSource->start(meta.get()), (status_t)OK);
#if 0
if (mMode == H264) {
@@ -264,6 +522,18 @@
}
}
+void ARTPWriter::setTMMBNInfo(uint32_t opponentID, uint32_t bitrate) {
+ mOpponentID = opponentID;
+ mBitrate = bitrate;
+
+ sp<ABuffer> buffer = new ABuffer(65536);
+ buffer->setRange(0, 0);
+
+ addTMMBN(buffer);
+
+ send(buffer, true /* isRTCP */);
+}
+
void ARTPWriter::onRead(const sp<AMessage> &msg) {
MediaBufferBase *mediaBuf;
status_t err = mSource->read(&mediaBuf);
@@ -281,7 +551,16 @@
if (mMode == H264) {
StripStartcode(mediaBuf);
- sendAVCData(mediaBuf);
+ SpsPpsParser(mediaBuf, &mSPSBuf, &mPPSBuf);
+ if (mediaBuf->range_length() > 0) {
+ sendAVCData(mediaBuf);
+ }
+ } else if (mMode == H265) {
+ StripStartcode(mediaBuf);
+ VpsSpsPpsParser(mediaBuf, &mVPSBuf, &mSPSBuf, &mPPSBuf);
+ if (mediaBuf->range_length() > 0) {
+ sendHEVCData(mediaBuf);
+ }
} else if (mMode == H263) {
sendH263Data(mediaBuf);
} else if (mMode == AMR_NB || mMode == AMR_WB) {
@@ -309,12 +588,39 @@
}
void ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) {
- ssize_t n = sendto(
- mSocket, buffer->data(), buffer->size(), 0,
- (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr),
- sizeof(mRTCPAddr));
+ int sizeSockSt;
+ struct sockaddr *remAddr;
- CHECK_EQ(n, (ssize_t)buffer->size());
+ if (mIsIPv6) {
+ sizeSockSt = sizeof(struct sockaddr_in6);
+ if (isRTCP)
+ remAddr = (struct sockaddr *)&mRTCPAddr6;
+ else
+ remAddr = (struct sockaddr *)&mRTPAddr6;
+ } else {
+ sizeSockSt = sizeof(struct sockaddr_in);
+ if (isRTCP)
+ remAddr = (struct sockaddr *)&mRTCPAddr;
+ else
+ remAddr = (struct sockaddr *)&mRTPAddr;
+ }
+
+ // Unseal code if moderator is needed (prevent overflow of instant bandwidth)
+ // Set limit bits per period through the moderator.
+ // ex) 6KByte/10ms = 48KBit/10ms = 4.8MBit/s instant limit
+ // ModerateInstantTraffic(10, 6 * 1024);
+
+ ssize_t n = sendto(isRTCP ? mRTCPSocket : mRTPSocket,
+ buffer->data(), buffer->size(), 0, remAddr, sizeSockSt);
+
+ if (n != (ssize_t)buffer->size()) {
+ ALOGW("packets can not be sent. ret=%d, buf=%d", (int)n, (int)buffer->size());
+ } else {
+ // Record current traffic & Print bits while last 1sec (1000ms)
+ mTrafficRec->writeBytes(buffer->size() +
+ (mIsIPv6 ? TCPIPV6_HEADER_SIZE : TCPIPV4_HEADER_SIZE));
+ mTrafficRec->printAccuBitsForLastPeriod(1000, 1000);
+ }
#if LOG_TO_FILES
int fd = isRTCP ? mRTCPFd : mRTPFd;
@@ -379,7 +685,6 @@
data[offset++] = 1; // CNAME
- static const char *kCNAME = "someone@somewhere";
data[offset++] = strlen(kCNAME);
memcpy(&data[offset], kCNAME, strlen(kCNAME));
@@ -416,9 +721,55 @@
buffer->setRange(buffer->offset(), buffer->size() + offset);
}
+void ARTPWriter::addTMMBN(const sp<ABuffer> &buffer) {
+ if (buffer->size() + 20 > buffer->capacity()) {
+ ALOGW("RTCP buffer too small to accommodate SR.");
+ return;
+ }
+ if (mOpponentID == 0)
+ return;
+
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 4; // TMMBN
+ data[1] = 205; // TSFB
+ data[2] = 0;
+ data[3] = 4; // total (4+1) * sizeof(int32_t) = 20 bytes
+ data[4] = mSourceID >> 24;
+ data[5] = (mSourceID >> 16) & 0xff;
+ data[6] = (mSourceID >> 8) & 0xff;
+ data[7] = mSourceID & 0xff;
+
+ *(int32_t*)(&data[8]) = 0; // 4 bytes blank
+
+ data[12] = mOpponentID >> 24;
+ data[13] = (mOpponentID >> 16) & 0xff;
+ data[14] = (mOpponentID >> 8) & 0xff;
+ data[15] = mOpponentID & 0xff;
+
+ // Find the first bit '1' from left & right side of the value.
+ int32_t leftEnd = 31 - __builtin_clz(mBitrate);
+ int32_t rightEnd = ffs(mBitrate) - 1;
+
+ // Mantissa have only 17bit space by RTCP specification.
+ if ((leftEnd - rightEnd) > 16) {
+ rightEnd = leftEnd - 16;
+ }
+ int32_t mantissa = mBitrate >> rightEnd;
+
+ data[16] = ((rightEnd << 2) & 0xfc) | ((mantissa & 0x18000) >> 15);
+ data[17] = (mantissa & 0x07f80) >> 7;
+ data[18] = (mantissa & 0x0007f) << 1;
+ data[19] = 40; // 40 bytes overhead;
+
+ buffer->setRange(buffer->offset(), buffer->size() + 20);
+
+ ALOGI("UE -> Op Noti Tx bitrate : %d ", mantissa << rightEnd);
+}
+
// static
uint64_t ARTPWriter::GetNowNTP() {
- uint64_t nowUs = ALooper::GetNowUs();
+ uint64_t nowUs = systemTime(SYSTEM_TIME_REALTIME) / 1000ll;
nowUs += ((70LL * 365 + 17) * 24) * 60 * 60 * 1000000LL;
@@ -463,7 +814,7 @@
sdp.append("m=audio ");
}
- sdp.append(AStringPrintf("%d", ntohs(mRTPAddr.sin_port)));
+ sdp.append(AStringPrintf("%d", mIsIPv6 ? ntohs(mRTPAddr6.sin6_port) : ntohs(mRTPAddr.sin_port)));
sdp.append(
" RTP/AVP " PT_STR "\r\n"
"b=AS 320000\r\n"
@@ -569,24 +920,91 @@
send(buffer, true /* isRTCP */);
}
-void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
+void ARTPWriter::sendSPSPPSIfIFrame(MediaBufferBase *mediaBuf, int64_t timeUs) {
+ CHECK(mediaBuf->range_length() > 0);
+ const uint8_t *mediaData =
+ (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+ if ((mediaData[0] & H264_NALU_MASK) != H264_NALU_IFRAME) {
+ return;
+ }
+
+ if (mSPSBuf != NULL) {
+ mSPSBuf->meta_data().setInt64(kKeyTime, timeUs);
+ mSPSBuf->meta_data().setInt32(kKeySps, 1);
+ sendAVCData(mSPSBuf);
+ }
+
+ if (mPPSBuf != NULL) {
+ mPPSBuf->meta_data().setInt64(kKeyTime, timeUs);
+ mPPSBuf->meta_data().setInt32(kKeyPps, 1);
+ sendAVCData(mPPSBuf);
+ }
+}
+
+void ARTPWriter::sendVPSSPSPPSIfIFrame(MediaBufferBase *mediaBuf, int64_t timeUs) {
+ CHECK(mediaBuf->range_length() > 0);
+ const uint8_t *mediaData =
+ (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+ int nalType = ((mediaData[0] >> 1) & H265_NALU_MASK);
+ if (!(nalType >= 16 && nalType <= 21) /*H265_NALU_IFRAME*/) {
+ return;
+ }
+
+ if (mVPSBuf != NULL) {
+ mVPSBuf->meta_data().setInt64(kKeyTime, timeUs);
+ mVPSBuf->meta_data().setInt32(kKeyVps, 1);
+ sendHEVCData(mVPSBuf);
+ }
+
+ if (mSPSBuf != NULL) {
+ mSPSBuf->meta_data().setInt64(kKeyTime, timeUs);
+ mSPSBuf->meta_data().setInt32(kKeySps, 1);
+ sendHEVCData(mSPSBuf);
+ }
+
+ if (mPPSBuf != NULL) {
+ mPPSBuf->meta_data().setInt64(kKeyTime, timeUs);
+ mPPSBuf->meta_data().setInt32(kKeyPps, 1);
+ sendHEVCData(mPPSBuf);
+ }
+}
+
+void ARTPWriter::sendHEVCData(MediaBufferBase *mediaBuf) {
// 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
CHECK_GE(kMaxPacketSize, 12u + 2u);
int64_t timeUs;
CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
- uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
+ sendVPSSPSPPSIfIFrame(mediaBuf, timeUs);
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+
+ CHECK(mediaBuf->range_length() > 0);
const uint8_t *mediaData =
(const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+ int32_t isNonVCL = 0;
+ if (mediaBuf->meta_data().findInt32(kKeyVps, &isNonVCL) ||
+ mediaBuf->meta_data().findInt32(kKeySps, &isNonVCL) ||
+ mediaBuf->meta_data().findInt32(kKeyPps, &isNonVCL)) {
+ isNonVCL = 1;
+ }
+
sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
- if (mediaBuf->range_length() + 12 <= buffer->capacity()) {
+
+ if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
+ + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
// The data fits into a single packet
uint8_t *data = buffer->data();
data[0] = 0x80;
- data[1] = (1 << 7) | PT; // M-bit
+ if (isNonVCL) {
+ data[1] = mPayloadType; // Marker bit should not be set in case of Non-VCL
+ } else {
+ data[1] = (1 << 7) | mPayloadType; // M-bit
+ }
data[2] = (mSeqNo >> 8) & 0xff;
data[3] = mSeqNo & 0xff;
data[4] = rtpTime >> 24;
@@ -611,21 +1029,24 @@
} else {
// FU-A
- unsigned nalType = mediaData[0];
- size_t offset = 1;
+ unsigned nalType = (mediaData[0] >> 1) & H265_NALU_MASK;
+ ALOGV("H265 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
+ size_t offset = 2; //H265 payload header is 16 bit.
bool firstPacket = true;
while (offset < mediaBuf->range_length()) {
size_t size = mediaBuf->range_length() - offset;
bool lastPacket = true;
- if (size + 12 + 2 > buffer->capacity()) {
+ if (size + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE +
+ RTP_FU_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
lastPacket = false;
- size = buffer->capacity() - 12 - 2;
+ size = buffer->capacity() - TCPIP_HEADER_SIZE - RTP_HEADER_SIZE -
+ RTP_HEADER_EXT_SIZE - RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
}
uint8_t *data = buffer->data();
data[0] = 0x80;
- data[1] = (lastPacket ? (1 << 7) : 0x00) | PT; // M-bit
+ data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType; // M-bit
data[2] = (mSeqNo >> 8) & 0xff;
data[3] = mSeqNo & 0xff;
data[4] = rtpTime >> 24;
@@ -637,18 +1058,39 @@
data[10] = (mSourceID >> 8) & 0xff;
data[11] = mSourceID & 0xff;
- data[12] = 28 | (nalType & 0xe0);
+ /* H265 payload header is 16 bit
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |F| Type | Layer ID | TID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ ALOGV("H265 payload header 0x%x %x", mediaData[0], mediaData[1]);
+ // excludes Type from 1st byte of H265 payload header.
+ data[12] = mediaData[0] & 0x81;
+ // fills Type as FU (49 == 0x31)
+ data[12] = data[12] | (0x31 << 1);
+ data[13] = mediaData[1];
+
+ ALOGV("H265 FU header 0x%x %x", data[12], data[13]);
CHECK(!firstPacket || !lastPacket);
+ /*
+ FU INDICATOR HDR
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+
+ |S|E| Type |
+ +-+-+-+-+-+-+-+
+ */
- data[13] =
+ data[14] =
(firstPacket ? 0x80 : 0x00)
| (lastPacket ? 0x40 : 0x00)
- | (nalType & 0x1f);
+ | (nalType & H265_NALU_MASK);
+ ALOGV("H265 FU indicator 0x%x", data[14]);
- memcpy(&data[14], &mediaData[offset], size);
+ memcpy(&data[15], &mediaData[offset], size);
- buffer->setRange(0, 14 + size);
+ buffer->setRange(0, 15 + size);
send(buffer, false /* isRTCP */);
@@ -663,6 +1105,172 @@
mLastRTPTime = rtpTime;
mLastNTPTime = GetNowNTP();
+
+}
+
+void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
+ // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
+ CHECK_GE(kMaxPacketSize, 12u + 2u);
+
+ int64_t timeUs;
+ CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
+
+ sendSPSPPSIfIFrame(mediaBuf, timeUs);
+
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
+
+ CHECK(mediaBuf->range_length() > 0);
+ const uint8_t *mediaData =
+ (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+ int32_t sps, pps;
+ bool isSpsPps = false;
+ if (mediaBuf->meta_data().findInt32(kKeySps, &sps) ||
+ mediaBuf->meta_data().findInt32(kKeyPps, &pps)) {
+ isSpsPps = true;
+ }
+
+ mTrafficRec->updateClock(ALooper::GetNowUs() / 1000);
+ sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
+ if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
+ + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
+ // The data fits into a single packet
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ if (mRTPCVOExtMap > 0)
+ data[0] |= 0x10;
+ if (isSpsPps)
+ data[1] = mPayloadType; // Marker bit should not be set in case of sps/pps
+ else
+ data[1] = (1 << 7) | mPayloadType;
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ int rtpExtIndex = 0;
+ if (mRTPCVOExtMap > 0) {
+ /*
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xBE | 0xDE | length=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | ID | L=0 | data | ID | L=1 | data...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ...data | 0 (pad) | 0 (pad) | ID | L=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | data |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ In the one-byte header form of extensions, the 16-bit value required
+ by the RTP specification for a header extension, labeled in the RTP
+ specification as "defined by profile", takes the fixed bit pattern
+ 0xBEDE (the first version of this specification was written on the
+ feast day of the Venerable Bede).
+ */
+ data[12] = 0xBE;
+ data[13] = 0xDE;
+ // put a length of RTP Extension.
+ data[14] = 0x00;
+ data[15] = 0x01;
+ // put extmap of RTP assigned for CVO.
+ data[16] = (mRTPCVOExtMap << 4) | 0x0;
+ // put image degrees as per CVO specification.
+ data[17] = mRTPCVODegrees;
+ data[18] = 0x0;
+ data[19] = 0x0;
+ rtpExtIndex = 8;
+ }
+
+ memcpy(&data[12 + rtpExtIndex],
+ mediaData, mediaBuf->range_length());
+
+ buffer->setRange(0, mediaBuf->range_length() + (12 + rtpExtIndex));
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
+ } else {
+ // FU-A
+
+ unsigned nalType = mediaData[0];
+ size_t offset = 1;
+
+ bool firstPacket = true;
+ while (offset < mediaBuf->range_length()) {
+ size_t size = mediaBuf->range_length() - offset;
+ bool lastPacket = true;
+ if (size + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE +
+ RTP_FU_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
+ lastPacket = false;
+ size = buffer->capacity() - TCPIP_HEADER_SIZE - RTP_HEADER_SIZE -
+ RTP_HEADER_EXT_SIZE - RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
+ }
+
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ if (lastPacket && mRTPCVOExtMap > 0)
+ data[0] |= 0x10;
+ data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType; // M-bit
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ int rtpExtIndex = 0;
+ if (lastPacket && mRTPCVOExtMap > 0) {
+ data[12] = 0xBE;
+ data[13] = 0xDE;
+ data[14] = 0x00;
+ data[15] = 0x01;
+ data[16] = (mRTPCVOExtMap << 4) | 0x0;
+ data[17] = mRTPCVODegrees;
+ data[18] = 0x0;
+ data[19] = 0x0;
+ rtpExtIndex = 8;
+ }
+
+ data[12 + rtpExtIndex] = 28 | (nalType & 0xe0);
+
+ CHECK(!firstPacket || !lastPacket);
+
+ data[13 + rtpExtIndex] =
+ (firstPacket ? 0x80 : 0x00)
+ | (lastPacket ? 0x40 : 0x00)
+ | (nalType & 0x1f);
+
+ memcpy(&data[14 + rtpExtIndex], &mediaData[offset], size);
+
+ buffer->setRange(0, 14 + rtpExtIndex + size);
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
+
+ firstPacket = false;
+ offset += size;
+ }
+ }
+
+ mLastRTPTime = rtpTime;
+ mLastNTPTime = GetNowNTP();
}
void ARTPWriter::sendH263Data(MediaBufferBase *mediaBuf) {
@@ -696,7 +1304,7 @@
uint8_t *data = buffer->data();
data[0] = 0x80;
- data[1] = (lastPacket ? 0x80 : 0x00) | PT; // M-bit
+ data[1] = (lastPacket ? 0x80 : 0x00) | mPayloadType; // M-bit
data[2] = (mSeqNo >> 8) & 0xff;
data[3] = mSeqNo & 0xff;
data[4] = rtpTime >> 24;
@@ -727,6 +1335,58 @@
mLastNTPTime = GetNowNTP();
}
+void ARTPWriter::updateCVODegrees(int32_t cvoDegrees) {
+ Mutex::Autolock autoLock(mLock);
+ mRTPCVODegrees = cvoDegrees;
+}
+
+void ARTPWriter::updatePayloadType(int32_t payloadType) {
+ Mutex::Autolock autoLock(mLock);
+ mPayloadType = payloadType;
+}
+
+void ARTPWriter::updateSocketDscp(int32_t dscp) {
+ mRtpLayer3Dscp = dscp << 2;
+
+ /* mRtpLayer3Dscp will be mapped to WMM(Wifi) as per operator's requirement */
+ if (setsockopt(mRTPSocket, IPPROTO_IP, IP_TOS,
+ (int *)&mRtpLayer3Dscp, sizeof(mRtpLayer3Dscp)) < 0) {
+ ALOGE("failed to set dscp on rtpsock. err=%s", strerror(errno));
+ } else {
+ ALOGD("successfully set dscp on rtpsock. opt=%d", mRtpLayer3Dscp);
+ setsockopt(mRTCPSocket, IPPROTO_IP, IP_TOS,
+ (int *)&mRtpLayer3Dscp, sizeof(mRtpLayer3Dscp));
+ ALOGD("successfully set dscp on rtcpsock. opt=%d", mRtpLayer3Dscp);
+ }
+}
+
+void ARTPWriter::updateSocketNetwork(int64_t socketNetwork) {
+ mRTPSockNetwork = (net_handle_t)socketNetwork;
+ ALOGI("trying to bind rtp socket(%d) to network(%llu).",
+ mRTPSocket, (unsigned long long)mRTPSockNetwork);
+
+ int result = android_setsocknetwork(mRTPSockNetwork, mRTPSocket);
+ if (result != 0) {
+ ALOGW("failed(%d) to bind rtp socket(%d) to network(%llu)",
+ result, mRTPSocket, (unsigned long long)mRTPSockNetwork);
+ }
+ result = android_setsocknetwork(mRTPSockNetwork, mRTCPSocket);
+ if (result != 0) {
+ ALOGW("failed(%d) to bind rtcp socket(%d) to network(%llu)",
+ result, mRTCPSocket, (unsigned long long)mRTPSockNetwork);
+ }
+ ALOGI("done. bind rtp socket(%d) to network(%llu)",
+ mRTPSocket, (unsigned long long)mRTPSockNetwork);
+}
+
+uint32_t ARTPWriter::getSequenceNum() {
+ return mSeqNo;
+}
+
+uint64_t ARTPWriter::getAccumulativeBytes() {
+ return mTrafficRec->readBytesForTotal();
+}
+
static size_t getFrameSize(bool isWide, unsigned FT) {
static const size_t kFrameSizeNB[8] = {
95, 103, 118, 134, 148, 159, 204, 244
@@ -778,7 +1438,7 @@
// The data fits into a single packet
uint8_t *data = buffer->data();
data[0] = 0x80;
- data[1] = PT;
+ data[1] = mPayloadType;
if (mNumRTPSent == 0) {
// Signal start of talk-spurt.
data[1] |= 0x80; // M-bit
@@ -834,5 +1494,91 @@
mLastNTPTime = GetNowNTP();
}
-} // namespace android
+void ARTPWriter::makeSocketPairAndBind(String8& localIp, int localPort,
+ String8& remoteIp, int remotePort) {
+ static char kSomeone[16] = "someone@";
+ int nameLength = strlen(kSomeone);
+ memcpy(kCNAME, kSomeone, nameLength);
+ memcpy(kCNAME + nameLength, localIp.c_str(), localIp.length() + 1);
+ if (localIp.contains(":"))
+ mIsIPv6 = true;
+ else
+ mIsIPv6 = false;
+
+ mRTPSocket = socket(mIsIPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(mRTPSocket, 0);
+ mRTCPSocket = socket(mIsIPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(mRTCPSocket, 0);
+
+ int sockopt = 1;
+ setsockopt(mRTPSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
+ setsockopt(mRTCPSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
+
+ if (mIsIPv6) {
+ memset(&mLocalAddr6, 0, sizeof(mLocalAddr6));
+ memset(&mRTPAddr6, 0, sizeof(mRTPAddr6));
+ memset(&mRTCPAddr6, 0, sizeof(mRTCPAddr6));
+
+ mLocalAddr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, localIp.string(), &mLocalAddr6.sin6_addr);
+ mLocalAddr6.sin6_port = htons((uint16_t)localPort);
+
+ mRTPAddr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, remoteIp.string(), &mRTPAddr6.sin6_addr);
+ mRTPAddr6.sin6_port = htons((uint16_t)remotePort);
+
+ mRTCPAddr6 = mRTPAddr6;
+ mRTCPAddr6.sin6_port = htons((uint16_t)(remotePort + 1));
+ } else {
+ memset(&mLocalAddr, 0, sizeof(mLocalAddr));
+ memset(&mRTPAddr, 0, sizeof(mRTPAddr));
+ memset(&mRTCPAddr, 0, sizeof(mRTCPAddr));
+
+ mLocalAddr.sin_family = AF_INET;
+ mLocalAddr.sin_addr.s_addr = inet_addr(localIp.string());
+ mLocalAddr.sin_port = htons((uint16_t)localPort);
+
+ mRTPAddr.sin_family = AF_INET;
+ mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.string());
+ mRTPAddr.sin_port = htons((uint16_t)remotePort);
+
+ mRTCPAddr = mRTPAddr;
+ mRTCPAddr.sin_port = htons((uint16_t)(remotePort + 1));
+ }
+
+ struct sockaddr *localAddr = mIsIPv6 ?
+ (struct sockaddr*)&mLocalAddr6 : (struct sockaddr*)&mLocalAddr;
+
+ int sizeSockSt = mIsIPv6 ? sizeof(mLocalAddr6) : sizeof(mLocalAddr);
+
+ if (bind(mRTPSocket, localAddr, sizeSockSt) == -1) {
+ ALOGE("failed to bind rtp %s:%d err=%s", localIp.string(), localPort, strerror(errno));
+ } else {
+ ALOGD("succeed to bind rtp %s:%d", localIp.string(), localPort);
+ }
+
+ if (mIsIPv6)
+ mLocalAddr6.sin6_port = htons((uint16_t)(localPort + 1));
+ else
+ mLocalAddr.sin_port = htons((uint16_t)(localPort + 1));
+
+ if (bind(mRTCPSocket, localAddr, sizeSockSt) == -1) {
+ ALOGE("failed to bind rtcp %s:%d err=%s", localIp.string(), localPort + 1, strerror(errno));
+ } else {
+ ALOGD("succeed to bind rtcp %s:%d", localIp.string(), localPort + 1);
+ }
+}
+
+// TODO : Develop more advanced moderator based on AS & TMMBR value
+void ARTPWriter::ModerateInstantTraffic(uint32_t samplePeriod, uint32_t limitBytes) {
+ unsigned int bytes = mTrafficRec->readBytesForLastPeriod(samplePeriod);
+ if (bytes > limitBytes) {
+ ALOGI("Nuclear moderator. #seq = %d \t\t %d bits / 10ms",
+ mSeqNo, bytes * 8);
+ usleep(4000);
+ mTrafficRec->updateClock(ALooper::GetNowUs() / 1000);
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/ARTPWriter.h
index 2f13486..28d6ec5 100644
--- a/media/libstagefright/rtsp/ARTPWriter.h
+++ b/media/libstagefright/rtsp/ARTPWriter.h
@@ -27,6 +27,9 @@
#include <arpa/inet.h>
#include <sys/socket.h>
+#include <android/multinetwork.h>
+#include "TrafficRecorder.h"
+
#define LOG_TO_FILES 0
namespace android {
@@ -36,14 +39,24 @@
struct ARTPWriter : public MediaWriter {
explicit ARTPWriter(int fd);
+ explicit ARTPWriter(int fd, String8& localIp, int localPort,
+ String8& remoteIp, int remotePort,
+ uint32_t seqNo);
virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS();
virtual status_t start(MetaData *params);
virtual status_t stop();
virtual status_t pause();
+ void updateCVODegrees(int32_t cvoDegrees);
+ void updatePayloadType(int32_t payloadType);
+ void updateSocketDscp(int32_t dscp);
+ void updateSocketNetwork(int64_t socketNetwork);
+ uint32_t getSequenceNum();
+ virtual uint64_t getAccumulativeBytes() override;
virtual void onMessageReceived(const sp<AMessage> &msg);
+ virtual void setTMMBNInfo(uint32_t opponentID, uint32_t bitrate);
protected:
virtual ~ARTPWriter();
@@ -76,15 +89,27 @@
sp<ALooper> mLooper;
sp<AHandlerReflector<ARTPWriter> > mReflector;
- int mSocket;
+ bool mIsIPv6;
+ int mRTPSocket, mRTCPSocket;
+ struct sockaddr_in mLocalAddr;
struct sockaddr_in mRTPAddr;
struct sockaddr_in mRTCPAddr;
+ struct sockaddr_in6 mLocalAddr6;
+ struct sockaddr_in6 mRTPAddr6;
+ struct sockaddr_in6 mRTCPAddr6;
+ int32_t mRtpLayer3Dscp;
+ net_handle_t mRTPSockNetwork;
AString mProfileLevel;
AString mSeqParamSet;
AString mPicParamSet;
+ MediaBufferBase *mVPSBuf;
+ MediaBufferBase *mSPSBuf;
+ MediaBufferBase *mPPSBuf;
+
uint32_t mSourceID;
+ uint32_t mPayloadType;
uint32_t mSeqNo;
uint32_t mRTPTimeBase;
uint32_t mNumRTPSent;
@@ -92,10 +117,18 @@
uint32_t mLastRTPTime;
uint64_t mLastNTPTime;
+ uint32_t mOpponentID;
+ uint32_t mBitrate;
+ typedef uint64_t Bytes;
+ sp<TrafficRecorder<uint32_t /* Time */, Bytes> > mTrafficRec;
+
int32_t mNumSRsSent;
+ int32_t mRTPCVOExtMap;
+ int32_t mRTPCVODegrees;
enum {
INVALID,
+ H265,
H264,
H263,
AMR_NB,
@@ -104,22 +137,29 @@
static uint64_t GetNowNTP();
+ void initState();
void onRead(const sp<AMessage> &msg);
void onSendSR(const sp<AMessage> &msg);
void addSR(const sp<ABuffer> &buffer);
void addSDES(const sp<ABuffer> &buffer);
+ void addTMMBN(const sp<ABuffer> &buffer);
void makeH264SPropParamSets(MediaBufferBase *buffer);
void dumpSessionDesc();
void sendBye();
+ void sendVPSSPSPPSIfIFrame(MediaBufferBase *mediaBuf, int64_t timeUs);
+ void sendSPSPPSIfIFrame(MediaBufferBase *mediaBuf, int64_t timeUs);
+ void sendHEVCData(MediaBufferBase *mediaBuf);
void sendAVCData(MediaBufferBase *mediaBuf);
void sendH263Data(MediaBufferBase *mediaBuf);
void sendAMRData(MediaBufferBase *mediaBuf);
void send(const sp<ABuffer> &buffer, bool isRTCP);
+ void makeSocketPairAndBind(String8& localIp, int localPort, String8& remoteIp, int remotePort);
+ void ModerateInstantTraffic(uint32_t samplePeriod, uint32_t limitBytes);
DISALLOW_EVIL_CONSTRUCTORS(ARTPWriter);
};
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 2b42040..5b5b4b1 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -27,6 +27,8 @@
namespace android {
+constexpr unsigned kDefaultAs = 960; // kbps?
+
ASessionDescription::ASessionDescription()
: mIsValid(false) {
}
@@ -103,7 +105,7 @@
key.setTo(line, 0, colonPos);
if (key == "a=fmtp" || key == "a=rtpmap"
- || key == "a=framesize") {
+ || key == "a=framesize" || key == "a=extmap") {
ssize_t spacePos = line.find(" ", colonPos + 1);
if (spacePos < 0) {
return false;
@@ -201,6 +203,33 @@
return true;
}
+bool ASessionDescription::getCvoExtMap(
+ size_t index, int32_t *cvoExtMap) const {
+ CHECK_GE(index, 0u);
+ CHECK_LT(index, mTracks.size());
+
+ AString key, value;
+ *cvoExtMap = 0;
+
+ const Attribs &track = mTracks.itemAt(index);
+ for (size_t i = 0; i < track.size(); i++) {
+ value = track.valueAt(i);
+ if (value.size() > 0 && strcmp(value.c_str(), "urn:3gpp:video-orientation") == 0) {
+ key = track.keyAt(i);
+ break;
+ }
+ }
+
+ if (key.size() > 0) {
+ const char *colonPos = strrchr(key.c_str(), ':');
+ colonPos++;
+ *cvoExtMap = atoi(colonPos);
+ return true;
+ }
+
+ return false;
+}
+
void ASessionDescription::getFormatType(
size_t index, unsigned long *PT,
AString *desc, AString *params) const {
@@ -345,5 +374,74 @@
return *npt2 > *npt1;
}
+// static
+void ASessionDescription::SDPStringFactory(AString &sdp,
+ const char *ip, bool isAudio, unsigned port, unsigned payloadType,
+ unsigned as, const char *codec, const char *fmtp,
+ int32_t width, int32_t height, int32_t cvoExtMap)
+{
+ bool isIPv4 = (AString(ip).find("::") == -1) ? true : false;
+ sdp.clear();
+ sdp.append("v=0\r\n");
+
+ sdp.append("a=range:npt=now-\r\n");
+
+ sdp.append("m=");
+ sdp.append(isAudio ? "audio " : "video ");
+ sdp.append(port);
+ sdp.append(" RTP/AVP ");
+ sdp.append(payloadType);
+ sdp.append("\r\n");
+
+ sdp.append("c= IN IP");
+ if (isIPv4) {
+ sdp.append("4 ");
+ } else {
+ sdp.append("6 ");
+ }
+ sdp.append(ip);
+ sdp.append("\r\n");
+
+ sdp.append("b=AS:");
+ sdp.append(as > 0 ? as : kDefaultAs);
+ sdp.append("\r\n");
+
+ sdp.append("a=rtpmap:");
+ sdp.append(payloadType);
+ sdp.append(" ");
+ sdp.append(codec);
+ sdp.append("/");
+ sdp.append(isAudio ? "8000" : "90000");
+ sdp.append("\r\n");
+
+ if (fmtp != NULL) {
+ sdp.append("a=fmtp:");
+ sdp.append(payloadType);
+ sdp.append(" ");
+ sdp.append(fmtp);
+ sdp.append("\r\n");
+ }
+
+ if (!isAudio && width > 0 && height > 0) {
+ sdp.append("a=framesize:");
+ sdp.append(payloadType);
+ sdp.append(" ");
+ sdp.append(width);
+ sdp.append("-");
+ sdp.append(height);
+ sdp.append("\r\n");
+ }
+
+ if (cvoExtMap > 0) {
+ sdp.append("a=extmap:");
+ sdp.append(cvoExtMap);
+ sdp.append(" ");
+ sdp.append("urn:3gpp:video-orientation");
+ sdp.append("\r\n");
+ }
+
+ ALOGV("SDPStringFactory => %s", sdp.c_str());
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
index b462983..91f5442 100644
--- a/media/libstagefright/rtsp/ASessionDescription.h
+++ b/media/libstagefright/rtsp/ASessionDescription.h
@@ -40,6 +40,8 @@
size_t countTracks() const;
void getFormat(size_t index, AString *value) const;
+ bool getCvoExtMap(size_t index, int32_t *cvoExtMap) const;
+
void getFormatType(
size_t index, unsigned long *PT,
AString *desc, AString *params) const;
@@ -63,6 +65,9 @@
// i.e. we have a fixed duration, otherwise this is live streaming.
static bool parseNTPRange(const char *s, float *npt1, float *npt2);
+ static void SDPStringFactory(AString &sdp, const char *ip, bool isAudio, unsigned port,
+ unsigned payloadType, unsigned as, const char *codec, const char *fmtp = NULL,
+ int32_t width = 0, int32_t height = 0, int32_t cvoExtMap = 0);
protected:
virtual ~ASessionDescription();
diff --git a/media/libstagefright/rtsp/Android.bp b/media/libstagefright/rtsp/Android.bp
index a5a895e..dcadbaf 100644
--- a/media/libstagefright/rtsp/Android.bp
+++ b/media/libstagefright/rtsp/Android.bp
@@ -1,9 +1,29 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_rtsp_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_rtsp_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "libstagefright_rtsp_defaults",
srcs: [
"AAMRAssembler.cpp",
"AAVCAssembler.cpp",
+ "AHEVCAssembler.cpp",
"AH263Assembler.cpp",
"AMPEG2TSAssembler.cpp",
"AMPEG4AudioAssembler.cpp",
@@ -20,6 +40,7 @@
],
shared_libs: [
+ "libandroid_net",
"libcrypto",
"libdatasource",
"libmedia",
@@ -28,6 +49,7 @@
include_dirs: [
"frameworks/av/media/libstagefright",
"frameworks/native/include/media/openmax",
+ "frameworks/native/include/android",
],
arch: {
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 7f025a5..0fdf431 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1032,6 +1032,11 @@
break;
}
+ int32_t rtcpEvent;
+ if (msg->findInt32("rtcp-event", &rtcpEvent)) {
+ break;
+ }
+
++mNumAccessUnitsReceived;
postAccessUnitTimeoutCheck();
diff --git a/media/libstagefright/rtsp/QualManager.cpp b/media/libstagefright/rtsp/QualManager.cpp
new file mode 100644
index 0000000..37aa326
--- /dev/null
+++ b/media/libstagefright/rtsp/QualManager.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 "QualManager"
+
+#include <algorithm>
+
+#include <sys/prctl.h>
+#include <utils/Log.h>
+
+#include "QualManager.h"
+
+namespace android {
+
+QualManager::Watcher::Watcher(int32_t timeLimit)
+ : Thread(false), mWatching(false), mSwitch(false),
+ mTimeLimit(timeLimit * 1000000LL) // timeLimit ms
+{
+}
+
+bool QualManager::Watcher::isExpired() const
+{
+ return mSwitch;
+}
+
+void QualManager::Watcher::setup() {
+ AutoMutex _l(mMyLock);
+ if (mWatching == false) {
+ mWatching = true;
+ mMyCond.signal();
+ }
+}
+
+void QualManager::Watcher::release() {
+ AutoMutex _l(mMyLock);
+ if (mSwitch) {
+ ALOGW("%s DISARMED", name);
+ mSwitch = false;
+ }
+ if (mWatching == true) {
+ ALOGW("%s DISARMED", name);
+ mWatching = false;
+ mMyCond.signal();
+ }
+}
+
+void QualManager::Watcher::exit() {
+ AutoMutex _l(mMyLock);
+ // The order is important to avoid dead lock.
+ Thread::requestExit();
+ mMyCond.signal();
+}
+
+QualManager::Watcher::~Watcher() {
+ ALOGI("%s thread dead", name);
+}
+
+bool QualManager::Watcher::threadLoop() {
+ AutoMutex _l(mMyLock);
+#if defined(__linux__)
+ prctl(PR_GET_NAME, name, 0, 0, 0);
+#endif
+ while (!exitPending()) {
+ ALOGW("%s Timer init", name);
+ mMyCond.wait(mMyLock); // waits as non-watching state
+ if (exitPending())
+ return false;
+ ALOGW("%s timer BOOM after %d msec", name, (int)(mTimeLimit / 1000000LL));
+ mMyCond.waitRelative(mMyLock, mTimeLimit); // waits as watching satte
+ if (mWatching == true) {
+ mSwitch = true;
+ ALOGW("%s BOOM!!!!", name);
+ }
+ mWatching = false;
+ }
+ return false;
+}
+
+
+QualManager::QualManager()
+ : mMinBitrate(-1), mMaxBitrate(-1),
+ mTargetBitrate(512000), mLastTargetBitrate(-1),
+ mLastSetBitrateTime(0), mIsNewTargetBitrate(false)
+{
+ VFPWatcher = new Watcher(3000); //Very Few Packet Watcher
+ VFPWatcher->run("VeryFewPtk");
+ LBRWatcher = new Watcher(10000); //Low Bit Rate Watcher
+ LBRWatcher->run("LowBitRate");
+}
+
+QualManager::~QualManager() {
+ VFPWatcher->exit();
+ LBRWatcher->exit();
+}
+
+int32_t QualManager::getTargetBitrate() {
+ if (mIsNewTargetBitrate) {
+ mIsNewTargetBitrate = false;
+ mLastTargetBitrate = clampingBitrate(mTargetBitrate);
+ mTargetBitrate = mLastTargetBitrate;
+ return mTargetBitrate;
+ } else {
+ return -1;
+ }
+}
+
+bool QualManager::isNeedToDowngrade() {
+ return LBRWatcher->isExpired();
+}
+
+void QualManager::setTargetBitrate(uint8_t fraction, int64_t nowUs, bool isTooLowPkts) {
+ /* Too Low Packet. Maybe opponent is switching camera.
+ * If this condition goes longer, we should down bitrate.
+ */
+ if (isTooLowPkts) {
+ VFPWatcher->setup();
+ } else {
+ VFPWatcher->release();
+ }
+
+ if ((fraction > (256 * 5 / 100) && !isTooLowPkts) || VFPWatcher->isExpired()) {
+ // loss more than 5% or VFPWatcher BOOMED
+ mTargetBitrate -= mBitrateStep * 3;
+ } else if (fraction <= (256 * 2 /100)) {
+ // loss less than 2%
+ mTargetBitrate += mBitrateStep;
+ }
+
+ if (mTargetBitrate > mMaxBitrate) {
+ mTargetBitrate = mMaxBitrate + mBitrateStep;
+ } else if (mTargetBitrate < mMinBitrate) {
+ LBRWatcher->setup();
+ mTargetBitrate = mMinBitrate - mBitrateStep;
+ }
+
+ if (mLastTargetBitrate != clampingBitrate(mTargetBitrate) ||
+ nowUs - mLastSetBitrateTime > 5000000ll) {
+ mIsNewTargetBitrate = true;
+ mLastSetBitrateTime = nowUs;
+ }
+}
+
+void QualManager::setMinMaxBitrate(int32_t min, int32_t max) {
+ mMinBitrate = min;
+ mMaxBitrate = max;
+ mBitrateStep = (max - min) / 8;
+}
+
+void QualManager::setBitrateData(int32_t bitrate, int64_t /*now*/) {
+ // A bitrate that is considered packetloss also should be good.
+ if (bitrate >= mMinBitrate && mTargetBitrate >= mMinBitrate) {
+ LBRWatcher->release();
+ } else if (bitrate < mMinBitrate){
+ LBRWatcher->setup();
+ }
+}
+
+int32_t QualManager::clampingBitrate(int32_t bitrate) {
+ return std::min(std::max(mMinBitrate, bitrate), mMaxBitrate);
+}
+} // namespace android
diff --git a/media/libstagefright/rtsp/QualManager.h b/media/libstagefright/rtsp/QualManager.h
new file mode 100644
index 0000000..a7dc921
--- /dev/null
+++ b/media/libstagefright/rtsp/QualManager.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef QUAL_MANAGER_H_
+
+#define QUAL_MANAGER_H_
+
+#include <stdint.h>
+#include <utils/Thread.h>
+
+namespace android {
+class QualManager {
+public:
+ QualManager();
+ ~QualManager();
+
+ int32_t getTargetBitrate();
+ bool isNeedToDowngrade();
+
+ void setTargetBitrate(uint8_t fraction, int64_t nowUs, bool isTooLowPkts);
+ void setMinMaxBitrate(int32_t min, int32_t max);
+ void setBitrateData(int32_t bitrate, int64_t now);
+private:
+ class Watcher : public Thread
+ {
+ public:
+ Watcher(int32_t timeLimit);
+
+ void setup();
+ void release();
+ void exit();
+ bool isExpired() const;
+ private:
+ virtual ~Watcher();
+ virtual bool threadLoop();
+
+ char name[32] = {0,};
+
+ Condition mMyCond;
+ Mutex mMyLock;
+
+ bool mWatching;
+ bool mSwitch;
+ const nsecs_t mTimeLimit;
+ };
+ sp<Watcher> VFPWatcher;
+ sp<Watcher> LBRWatcher;
+ int32_t mMinBitrate;
+ int32_t mMaxBitrate;
+ int32_t mBitrateStep;
+
+ int32_t mTargetBitrate;
+ int32_t mLastTargetBitrate;
+ int64_t mLastSetBitrateTime;
+
+ bool mIsNewTargetBitrate;
+
+ int32_t clampingBitrate(int32_t bitrate);
+};
+} //namespace android
+
+#endif // QUAL_MANAGER_H_
diff --git a/media/libstagefright/rtsp/TrafficRecorder.h b/media/libstagefright/rtsp/TrafficRecorder.h
new file mode 100644
index 0000000..8ba8f90
--- /dev/null
+++ b/media/libstagefright/rtsp/TrafficRecorder.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_TRAFFIC_RECORDER_H_
+
+#define A_TRAFFIC_RECORDER_H_
+
+#include <android-base/logging.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Circular array to save recent amount of bytes
+template <class Time, class Bytes>
+class TrafficRecorder : public RefBase {
+private:
+ constexpr static size_t kMinNumEntries = 4;
+ constexpr static size_t kMaxNumEntries = 1024;
+
+ size_t mSize;
+ size_t mSizeMask;
+ Time *mTimeArray = NULL;
+ Bytes *mBytesArray = NULL;
+ size_t mHeadIdx;
+ size_t mTailIdx;
+
+ int mLastReadIdx;
+
+ const Time mRecordLimit;
+ Time mClock;
+ Time mLastTimeOfPrint;
+ Bytes mAccuBytes;
+
+public:
+ TrafficRecorder(size_t size, Time accuTimeLimit);
+ virtual ~TrafficRecorder();
+
+ void init();
+ void updateClock(Time now);
+ Bytes readBytesForTotal();
+ Bytes readBytesForLastPeriod(Time period);
+ void writeBytes(Bytes bytes);
+ void printAccuBitsForLastPeriod(Time period, Time unit);
+};
+
+template <class Time, class Bytes>
+TrafficRecorder<Time, Bytes>::TrafficRecorder(size_t size, Time recordLimit)
+ : mRecordLimit(recordLimit) {
+ if (size > kMaxNumEntries) {
+ LOG(VERBOSE) << "Limiting TrafficRecorder size to " << kMaxNumEntries;
+ size = kMaxNumEntries;
+ } else if (size < kMinNumEntries) {
+ LOG(VERBOSE) << "Limiting TrafficRecorder size to " << kMaxNumEntries;
+ size = kMinNumEntries;
+ }
+
+ size_t exp = ((sizeof(size_t) == 8) ?
+ 64 - __builtin_clzl(size - 1) :
+ 32 - __builtin_clz(size - 1));
+ mSize = (1ul << exp); // size = 2^exp
+ mSizeMask = mSize - 1;
+
+ LOG(VERBOSE) << "TrafficRecorder Init size " << mSize;
+ mTimeArray = new Time[mSize];
+ mBytesArray = new Bytes[mSize];
+
+ init();
+}
+
+template <class Time, class Bytes>
+TrafficRecorder<Time, Bytes>::~TrafficRecorder() {
+ delete[] mTimeArray;
+ delete[] mBytesArray;
+}
+
+template <class Time, class Bytes>
+void TrafficRecorder<Time, Bytes>::init() {
+ mHeadIdx = 0;
+ mTailIdx = mSizeMask;
+ for (int i = 0 ; i < mSize ; i++) {
+ mTimeArray[i] = 0;
+ mBytesArray[i] = 0;
+ }
+ mClock = 0;
+ mLastReadIdx = 0;
+ mLastTimeOfPrint = 0;
+ mAccuBytes = 0;
+}
+
+template <class Time, class Bytes>
+void TrafficRecorder<Time, Bytes>::updateClock(Time now) {
+ mClock = now;
+}
+
+template <class Time, class Bytes>
+Bytes TrafficRecorder<Time, Bytes>::readBytesForTotal() {
+ return mAccuBytes;
+}
+
+template <class Time, class Bytes>
+Bytes TrafficRecorder<Time, Bytes>::readBytesForLastPeriod(Time period) {
+ // Not enough data
+ if (period > mClock)
+ return 0;
+
+ Bytes bytes = 0;
+ int i = mHeadIdx;
+ while (i != mTailIdx) {
+ LOG(VERBOSE) << "READ " << i << " time " << mTimeArray[i]
+ << " \t EndOfPeriod " << mClock - period
+ << "\t\t Bytes:" << mBytesArray[i] << "\t\t Accu: " << bytes;
+ if (mTimeArray[i] < mClock - period) {
+ break;
+ }
+ bytes += mBytesArray[i];
+ i = (i - 1) & mSizeMask;
+ }
+ mLastReadIdx = (i + 1) & mSizeMask;
+
+ return bytes;
+}
+
+template <class Time, class Bytes>
+void TrafficRecorder<Time, Bytes>::writeBytes(Bytes bytes) {
+ int writeIdx;
+ if (mClock == mTimeArray[mHeadIdx]) {
+ writeIdx = mHeadIdx;
+ mBytesArray[writeIdx] += bytes;
+ } else {
+ writeIdx = (mHeadIdx + 1) & mSizeMask;
+ mTimeArray[writeIdx] = mClock;
+ mBytesArray[writeIdx] = bytes;
+ }
+
+ LOG(VERBOSE) << "WRITE " << writeIdx << " time " << mClock;
+ if (writeIdx == mTailIdx) {
+ mTailIdx = (mTailIdx + 1) & mSizeMask;
+ }
+
+ mHeadIdx = writeIdx;
+ mAccuBytes += bytes;
+}
+
+template <class Time, class Bytes>
+void TrafficRecorder<Time, Bytes>::printAccuBitsForLastPeriod(Time period, Time unit) {
+ Time timeSinceLastPrint = mClock - mLastTimeOfPrint;
+ if (timeSinceLastPrint < period)
+ return;
+
+ Bytes sum = readBytesForLastPeriod(period);
+ Time readPeriod = mClock - mTimeArray[mLastReadIdx];
+
+ float numOfUnit = (float)(readPeriod) / (unit + FLT_MIN);
+ ALOGD("Actual Tx period %.3f unit \t %.0f bytes (%.0f Kbits)/Unit",
+ numOfUnit, sum / numOfUnit, sum * 8.f / numOfUnit / 1000.f);
+ mLastTimeOfPrint = mClock;
+
+ if (mClock - mTimeArray[mTailIdx] < mRecordLimit) {
+ // Size is not enough to record bytes for mRecordLimit period
+ ALOGW("Traffic recorder size is not enough. mRecordLimit %d", mRecordLimit);
+ }
+}
+
+} // namespace android
+
+#endif // A_TRAFFIC_RECORDER_H_
diff --git a/media/libstagefright/tests/Android.bp b/media/libstagefright/tests/Android.bp
index a7f94c1..a799a13 100644
--- a/media/libstagefright/tests/Android.bp
+++ b/media/libstagefright/tests/Android.bp
@@ -1,5 +1,24 @@
// Build the unit tests.
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_tests_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_test {
name: "MediaCodecListOverrides_test",
@@ -9,7 +28,6 @@
"libmedia",
"libstagefright",
"libstagefright_foundation",
- "libstagefright_omx",
"libutils",
"liblog",
],
@@ -17,11 +35,8 @@
include_dirs: [
"frameworks/av/media/libstagefright",
"frameworks/av/media/libstagefright/include",
- "frameworks/native/include/media/openmax",
],
- compile_multilib: "32",
-
cflags: [
"-Werror",
"-Wall",
@@ -44,4 +59,4 @@
"-Werror",
"-Wall",
],
-}
\ No newline at end of file
+}
diff --git a/media/libstagefright/tests/ESDS/Android.bp b/media/libstagefright/tests/ESDS/Android.bp
index 1ad1a64..04e9b29 100644
--- a/media/libstagefright/tests/ESDS/Android.bp
+++ b/media/libstagefright/tests/ESDS/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_test {
name: "ESDSTest",
gtest: true,
diff --git a/media/libstagefright/tests/HEVC/Android.bp b/media/libstagefright/tests/HEVC/Android.bp
index 7a6b959..501478c 100644
--- a/media/libstagefright/tests/HEVC/Android.bp
+++ b/media/libstagefright/tests/HEVC/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_test {
name: "HEVCUtilsUnitTest",
gtest: true,
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index e3e61d7..171755f 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_test {
name: "ExtractorFactoryTest",
gtest: true,
diff --git a/media/libstagefright/tests/fuzzers/Android.bp b/media/libstagefright/tests/fuzzers/Android.bp
index 49ff69a..65e74e6 100644
--- a/media/libstagefright/tests/fuzzers/Android.bp
+++ b/media/libstagefright/tests/fuzzers/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_defaults {
name: "libstagefright_fuzzer_defaults",
cflags: [
@@ -8,7 +19,9 @@
],
shared_libs: [
"libstagefright",
- "libstagefright_codecbase",
+ "libstagefright_codecbase",
+ "libbase",
+ "libcutils",
"libutils",
"libstagefright_foundation",
"libmedia",
@@ -16,7 +29,10 @@
"libmedia_omx",
"libgui",
"libbinder",
- "libcutils",
+ "liblog",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
],
}
@@ -51,3 +67,27 @@
],
defaults: ["libstagefright_fuzzer_defaults"],
}
+
+cc_fuzz {
+ name: "libstagefright_frameDecoder_fuzzer",
+ srcs: [
+ "FrameDecoderFuzzer.cpp",
+ ],
+ defaults: ["libstagefright_fuzzer_defaults"],
+}
+
+cc_fuzz {
+ name: "libstagefright_writer_fuzzer",
+ srcs: [
+ "FuzzerMediaUtility.cpp",
+ "WriterFuzzer.cpp",
+ ],
+ dictionary: "dictionaries/formats.dict",
+ defaults: ["libstagefright_fuzzer_defaults"],
+ static_libs: [
+ "libstagefright_webm",
+ "libdatasource",
+ "libstagefright_esds",
+ "libogg",
+ ],
+}
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
new file mode 100644
index 0000000..a628c70
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/FrameDecoder.h"
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/IMediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/AString.h>
+#include "FrameDecoderHelpers.h"
+#include "IMediaSourceFuzzImpl.h"
+
+namespace android {
+
+#define MAX_MEDIA_BUFFER_SIZE 2048
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ // Init our wrapper
+ FuzzedDataProvider fdp(data, size);
+
+ std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ AString componentName(name.c_str());
+ sp<MetaData> trackMeta = generateMetaData(&fdp);
+ sp<IMediaSource> source = new IMediaSourceFuzzImpl(&fdp, MAX_MEDIA_BUFFER_SIZE);
+
+ // Image or video Decoder?
+ sp<FrameDecoder> decoder;
+ bool isVideoDecoder = fdp.ConsumeBool();
+ if (isVideoDecoder) {
+ decoder = new VideoFrameDecoder(componentName, trackMeta, source);
+ } else {
+ decoder = new ImageDecoder(componentName, trackMeta, source);
+ }
+
+ while (fdp.remaining_bytes()) {
+ switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 3)) {
+ case 0:
+ decoder->init(/*frameTimeUs*/ fdp.ConsumeIntegral<int64_t>(),
+ /*option*/ fdp.ConsumeIntegral<int>(),
+ /*colorFormat*/ fdp.ConsumeIntegral<int>());
+ break;
+ case 1:
+ decoder->extractFrame();
+ break;
+ case 2: {
+ FrameRect rect;
+ rect.left = fdp.ConsumeIntegral<int32_t>();
+ rect.top = fdp.ConsumeIntegral<int32_t>();
+ rect.right = fdp.ConsumeIntegral<int32_t>();
+ rect.bottom = fdp.ConsumeIntegral<int32_t>();
+ decoder->extractFrame(&rect);
+ break;
+ }
+ case 3: {
+ sp<MetaData> trackMeta = generateMetaData(&fdp);
+ decoder->getMetadataOnly(trackMeta,
+ /*colorFormat*/ fdp.ConsumeIntegral<int>(),
+ /*thumbnail*/ fdp.ConsumeBool());
+ break;
+ }
+ }
+ }
+
+ generated_mime_types.clear();
+
+ return 0;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
new file mode 100644
index 0000000..228c04a
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
@@ -0,0 +1,90 @@
+
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <media/stagefright/MetaData.h>
+#include "MediaMimeTypes.h"
+
+#define MAX_METADATA_BUF_SIZE 512
+
+namespace android {
+
+std::vector<std::shared_ptr<char>> generated_mime_types;
+
+sp<MetaData> generateMetaData(FuzzedDataProvider *fdp) {
+ sp<MetaData> newMeta = new MetaData();
+
+ // random MIME Type
+ const char *mime_type;
+ size_t index = fdp->ConsumeIntegralInRange<size_t>(0, kMimeTypes.size());
+ // Let there be a chance of a true random string
+ if (index == kMimeTypes.size()) {
+ std::string mime_str = fdp->ConsumeRandomLengthString(64);
+ std::shared_ptr<char> mime_cstr(new char[mime_str.length()+1]);
+ generated_mime_types.push_back(mime_cstr);
+ strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1);
+ mime_type = mime_cstr.get();
+ } else {
+ mime_type = kMimeTypes[index];
+ }
+ newMeta->setCString(kKeyMIMEType, mime_type);
+
+ // Thumbnail time
+ newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral<int64_t>());
+
+ // Values used by allocVideoFrame
+ newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegral<int32_t>());
+ size_t profile_size =
+ fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE);
+ std::vector<uint8_t> profile_bytes =
+ fdp->ConsumeBytes<uint8_t>(profile_size);
+ newMeta->setData(kKeyIccProfile,
+ fdp->ConsumeIntegral<int32_t>(),
+ profile_bytes.empty() ? nullptr : profile_bytes.data(),
+ profile_bytes.size());
+ newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral<int32_t>());
+
+ // Values used by findThumbnailInfo
+ newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral<int32_t>());
+ size_t thumbnail_size =
+ fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE);
+ std::vector<uint8_t> thumb_bytes =
+ fdp->ConsumeBytes<uint8_t>(thumbnail_size);
+ newMeta->setData(kKeyThumbnailHVCC,
+ fdp->ConsumeIntegral<int32_t>(),
+ thumb_bytes.empty() ? nullptr : thumb_bytes.data(),
+ thumb_bytes.size());
+
+ // Values used by findGridInfo
+ newMeta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<int32_t>());
+
+ // A few functions perform a CHECK() that height/width are set
+ newMeta->setInt32(kKeyHeight, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyWidth, fdp->ConsumeIntegral<int32_t>());
+
+ return newMeta;
+}
+
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
new file mode 100644
index 0000000..810ae95
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FuzzerMediaUtility.h"
+
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OggWriter.h>
+
+#include "MediaMimeTypes.h"
+#include "webm/WebmWriter.h"
+
+namespace android {
+std::string genMimeType(FuzzedDataProvider *dataProvider) {
+ uint8_t idx = dataProvider->ConsumeIntegralInRange<uint8_t>(0, kMimeTypes.size() - 1);
+ return std::string(kMimeTypes[idx]);
+}
+
+sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, std::string mimeType,
+ uint16_t maxDataAmount) {
+ uint32_t dataBlobSize = dataProvider->ConsumeIntegralInRange<uint16_t>(0, maxDataAmount);
+ std::vector<uint8_t> data = dataProvider->ConsumeBytes<uint8_t>(dataBlobSize);
+ // data:[<mediatype>][;base64],<data>
+ std::string uri("data:");
+ uri += mimeType;
+ // Currently libstagefright only accepts base64 uris
+ uri += ";base64,";
+ android::AString out;
+ android::encodeBase64(data.data(), data.size(), &out);
+ uri += out.c_str();
+
+ sp<DataSource> source =
+ DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri.c_str());
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return MediaExtractorFactory::Create(source);
+}
+
+sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize) {
+ std::string mime = genMimeType(dataProvider);
+ sp<IMediaExtractor> extractor = genMediaExtractor(dataProvider, mime, maxMediaBlobSize);
+
+ if (extractor == NULL) {
+ return NULL;
+ }
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *trackMime;
+ if (!strcasecmp(mime.c_str(), trackMime)) {
+ sp<IMediaSource> track = extractor->getTrack(i);
+ if (track == NULL) {
+ return NULL;
+ }
+ return new CallbackMediaSource(track);
+ }
+ }
+
+ return NULL;
+}
+
+sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> fileMeta) {
+ sp<MediaWriter> writer;
+ switch (writerType) {
+ case OGG:
+ writer = new OggWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ break;
+ case AAC:
+ writer = new AACWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ break;
+ case AAC_ADTS:
+ writer = new AACWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+ break;
+ case WEBM:
+ writer = new WebmWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ break;
+ case MPEG4:
+ writer = new MPEG4Writer(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ break;
+ case AMR_NB:
+ writer = new AMRWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ break;
+ case AMR_WB:
+ writer = new AMRWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ break;
+ case MPEG2TS:
+ writer = new MPEG2TSWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ break;
+ default:
+ return nullptr;
+ }
+ if (writer != nullptr) {
+ fileMeta->setInt32(kKeyRealTimeRecording, false);
+ }
+ return writer;
+}
+} // namespace android
\ No newline at end of file
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
new file mode 100644
index 0000000..98bfb94
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <datasource/DataSourceFactory.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <android/IMediaExtractor.h>
+#include <media/IMediaHTTPService.h>
+#include <media/mediarecorder.h>
+#include <media/stagefright/CallbackMediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <media/stagefright/MediaWriter.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/base64.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+enum StandardWriters {
+ OGG,
+ AAC,
+ AAC_ADTS,
+ WEBM,
+ MPEG4,
+ AMR_NB,
+ AMR_WB,
+ MPEG2TS,
+ // Allows FuzzedDataProvider to find the end of this enum.
+ kMaxValue = MPEG2TS,
+};
+
+std::string genMimeType(FuzzedDataProvider *dataProvider);
+sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
+sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);
+
+sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> fileMeta);
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
new file mode 100644
index 0000000..e769950
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IMEDIASOURCEFUZZIMPL_H
+#define IMEDIASOURCEFUZZIMPL_H
+
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+class IMediaSourceFuzzImpl : public IMediaSource {
+ public:
+ IMediaSourceFuzzImpl(FuzzedDataProvider *_fdp, size_t _max_buffer_size) :
+ fdp(_fdp),
+ max_buffer_size(_max_buffer_size) {}
+ status_t start(MetaData*) override { return 0; }
+ status_t stop() override { return 0; }
+ sp<MetaData> getFormat() override { return nullptr; }
+ status_t read(MediaBufferBase**,
+ const MediaSource::ReadOptions*) override;
+ status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t,
+ const MediaSource::ReadOptions*) override;
+ bool supportReadMultiple() override { return true; }
+ bool supportNonblockingRead() override { return true; }
+ status_t pause() override { return 0; }
+
+ protected:
+ IBinder* onAsBinder() { return nullptr; }
+
+ private:
+ FuzzedDataProvider *fdp;
+ std::vector<std::shared_ptr<MediaBufferBase>> buffer_bases;
+ const size_t max_buffer_size;
+};
+
+// This class is simply to expose the destructor
+class MediaBufferFuzzImpl : public MediaBuffer {
+ public:
+ MediaBufferFuzzImpl(void *data, size_t size) : MediaBuffer(data, size) {}
+ ~MediaBufferFuzzImpl() {}
+};
+
+status_t IMediaSourceFuzzImpl::read(MediaBufferBase **buffer,
+ const MediaSource::ReadOptions *options) {
+ Vector<MediaBufferBase*> buffers;
+ status_t ret = readMultiple(&buffers, 1, options);
+ *buffer = buffers.empty() ? nullptr : buffers[0];
+
+ return ret;
+}
+
+status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers,
+ uint32_t maxNumBuffers, const MediaSource::ReadOptions*) {
+ uint32_t num_buffers =
+ fdp->ConsumeIntegralInRange<uint32_t>(0, maxNumBuffers);
+ for(uint32_t i = 0; i < num_buffers; i++) {
+ std::vector<uint8_t> buf = fdp->ConsumeBytes<uint8_t>(
+ fdp->ConsumeIntegralInRange<size_t>(0, max_buffer_size));
+
+ std::shared_ptr<MediaBufferBase> mbb(
+ new MediaBufferFuzzImpl(buf.data(), buf.size()));
+
+ buffer_bases.push_back(mbb);
+ buffers->push_back(mbb.get());
+ }
+
+ // STATUS_OK
+ return 0;
+}
+
+} // namespace android
+
+#endif // IMEDIASOURCEFUZZIMPL_H
+
diff --git a/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp b/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp
index e473541..9b26f0b 100644
--- a/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp
@@ -17,52 +17,53 @@
// dylan.katz@leviathansecurity.com
#include <fuzzer/FuzzedDataProvider.h>
-#include <media/stagefright/MediaClock.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaClock.h>
namespace android {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- sp<MediaClock> mClock(new MediaClock);
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ sp<MediaClock> mClock(new MediaClock);
- bool registered = false;
- while (fdp.remaining_bytes() > 0) {
- switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 5)) {
- case 0: {
- if (registered == false) {
- mClock->init();
- registered = true;
- }
- break;
+ bool registered = false;
+ while (fdp.remaining_bytes() > 0) {
+ switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 5)) {
+ case 0: {
+ if (registered == false) {
+ mClock->init();
+ registered = true;
+ }
+ break;
+ }
+ case 1: {
+ int64_t startingTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ mClock->setStartingTimeMedia(startingTimeMediaUs);
+ break;
+ }
+ case 2: {
+ mClock->clearAnchor();
+ break;
+ }
+ case 3: {
+ int64_t anchorTimeRealUs = fdp.ConsumeIntegral<int64_t>();
+ int64_t anchorTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ mClock->updateAnchor(anchorTimeMediaUs, anchorTimeRealUs,
+ maxTimeMediaUs);
+ break;
+ }
+ case 4: {
+ int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ mClock->updateMaxTimeMedia(maxTimeMediaUs);
+ break;
+ }
+ case 5: {
+ wp<AMessage> msg(new AMessage);
+ mClock->setNotificationMessage(msg.promote());
+ }
+ }
}
- case 1: {
- int64_t startingTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- mClock->setStartingTimeMedia(startingTimeMediaUs);
- break;
- }
- case 2: {
- mClock->clearAnchor();
- break;
- }
- case 3: {
- int64_t anchorTimeRealUs = fdp.ConsumeIntegral<int64_t>();
- int64_t anchorTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- mClock->updateAnchor(anchorTimeMediaUs, anchorTimeRealUs, maxTimeMediaUs);
- break;
- }
- case 4: {
- int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- mClock->updateMaxTimeMedia(maxTimeMediaUs);
- break;
- }
- case 5: {
- wp<AMessage> msg(new AMessage);
- mClock->setNotificationMessage(msg.promote());
- }
- }
- }
- return 0;
+ return 0;
}
-} // namespace android
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
new file mode 100644
index 0000000..9f337ac
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FUZZER_MEDIAMIMETYPES_H_
+#define FUZZER_MEDIAMIMETYPES_H_
+
+#include <media/stagefright/foundation/MediaDefs.h>
+
+namespace android {
+
+static const std::vector<const char*> kMimeTypes {
+ MEDIA_MIMETYPE_IMAGE_JPEG,
+ MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
+ MEDIA_MIMETYPE_VIDEO_VP8,
+ MEDIA_MIMETYPE_VIDEO_VP9,
+ MEDIA_MIMETYPE_VIDEO_AV1,
+ MEDIA_MIMETYPE_VIDEO_AVC,
+ MEDIA_MIMETYPE_VIDEO_HEVC,
+ MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263,
+ MEDIA_MIMETYPE_VIDEO_MPEG2,
+ MEDIA_MIMETYPE_VIDEO_RAW,
+ MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
+ MEDIA_MIMETYPE_VIDEO_SCRAMBLED,
+ MEDIA_MIMETYPE_VIDEO_DIVX,
+ MEDIA_MIMETYPE_VIDEO_DIVX3,
+ MEDIA_MIMETYPE_VIDEO_XVID,
+ MEDIA_MIMETYPE_VIDEO_MJPEG,
+ MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_MPEG,
+ MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
+ MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ MEDIA_MIMETYPE_AUDIO_MIDI,
+ MEDIA_MIMETYPE_AUDIO_AAC,
+ MEDIA_MIMETYPE_AUDIO_QCELP,
+ MEDIA_MIMETYPE_AUDIO_VORBIS,
+ MEDIA_MIMETYPE_AUDIO_OPUS,
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ MEDIA_MIMETYPE_AUDIO_RAW,
+ MEDIA_MIMETYPE_AUDIO_FLAC,
+ MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
+ MEDIA_MIMETYPE_AUDIO_MSGSM,
+ MEDIA_MIMETYPE_AUDIO_AC3,
+ MEDIA_MIMETYPE_AUDIO_EAC3,
+ MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+ MEDIA_MIMETYPE_AUDIO_AC4,
+ MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
+ MEDIA_MIMETYPE_AUDIO_ALAC,
+ MEDIA_MIMETYPE_AUDIO_WMA,
+ MEDIA_MIMETYPE_AUDIO_MS_ADPCM,
+ MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
+ MEDIA_MIMETYPE_CONTAINER_MPEG4,
+ MEDIA_MIMETYPE_CONTAINER_WAV,
+ MEDIA_MIMETYPE_CONTAINER_OGG,
+ MEDIA_MIMETYPE_CONTAINER_MATROSKA,
+ MEDIA_MIMETYPE_CONTAINER_MPEG2TS,
+ MEDIA_MIMETYPE_CONTAINER_AVI,
+ MEDIA_MIMETYPE_CONTAINER_MPEG2PS,
+ MEDIA_MIMETYPE_CONTAINER_HEIF,
+ MEDIA_MIMETYPE_TEXT_3GPP,
+ MEDIA_MIMETYPE_TEXT_SUBRIP,
+ MEDIA_MIMETYPE_TEXT_VTT,
+ MEDIA_MIMETYPE_TEXT_CEA_608,
+ MEDIA_MIMETYPE_TEXT_CEA_708,
+ MEDIA_MIMETYPE_DATA_TIMED_ID3
+};
+
+} // namespace android
+
+#endif // FUZZER_MEDIAMIMETYPES_H_
diff --git a/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp b/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp
index a072b7c..c50c951 100644
--- a/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp
@@ -16,7 +16,6 @@
// Authors: corbin.souffrant@leviathansecurity.com
// dylan.katz@leviathansecurity.com
-#include <cutils/ashmem.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/StagefrightMediaScanner.h>
@@ -24,59 +23,39 @@
namespace android {
class FuzzMediaScannerClient : public MediaScannerClient {
-public:
- virtual status_t scanFile(const char *, long long, long long, bool, bool) {
- return 0;
- }
+ public:
+ virtual status_t scanFile(const char*, long long, long long, bool, bool) {
+ return 0;
+ }
- virtual status_t handleStringTag(const char *, const char *) { return 0; }
+ virtual status_t handleStringTag(const char*, const char*) { return 0; }
- virtual status_t setMimeType(const char *) { return 0; }
+ virtual status_t setMimeType(const char*) { return 0; }
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- StagefrightMediaScanner mScanner = StagefrightMediaScanner();
- // Without this, the fuzzer crashes for some reason.
- mScanner.setLocale("");
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ StagefrightMediaScanner mScanner = StagefrightMediaScanner();
+ // Without this, the fuzzer crashes for some reason.
+ mScanner.setLocale("");
- size_t data_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
- int fd =
- ashmem_create_region("stagefrightmediascanner_fuzz_region", data_size);
- if (fd < 0)
+ while (fdp.remaining_bytes() > 0) {
+ switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 1)) {
+ case 0: {
+ std::string path = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ std::string mimeType =
+ fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ std::shared_ptr<MediaScannerClient> client(new FuzzMediaScannerClient());
+ mScanner.processFile(path.c_str(), mimeType.c_str(), *client);
+ break;
+ }
+ case 1: {
+ int fd = fdp.ConsumeIntegral<int>();
+ if (fd >= 0 && fd <= 2) fd = 3;
+ mScanner.extractAlbumArt(fd);
+ }
+ }
+ }
return 0;
-
- uint8_t *sh_data = static_cast<uint8_t *>(
- mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
- if (sh_data == MAP_FAILED)
- return 0;
-
- while (fdp.remaining_bytes() > 8) {
- switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 1)) {
- case 0: {
- std::string path = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
- std::string mimeType =
- fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
- std::shared_ptr<MediaScannerClient> client(new FuzzMediaScannerClient());
- mScanner.processFile(path.c_str(), mimeType.c_str(), *client);
- break;
- }
- case 1: {
- size_t to_copy = fdp.ConsumeIntegralInRange<size_t>(1, data_size);
- std::vector<uint8_t> rand_buf = fdp.ConsumeBytes<uint8_t>(to_copy);
-
- // If fdp doesn't have enough bytes left it will just make a shorter
- // vector.
- to_copy = std::min(rand_buf.size(), data_size);
-
- std::copy(sh_data, sh_data + to_copy, rand_buf.begin());
- mScanner.extractAlbumArt(fd);
- }
- }
- }
-
- munmap(sh_data, data_size);
- close(fd);
- return 0;
}
-} // namespace android
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
new file mode 100644
index 0000000..03e9b43
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Authors: corbin.souffrant@leviathansecurity.com
+// dylan.katz@leviathansecurity.com
+
+#include <android-base/file.h>
+#include <ctype.h>
+#include <media/mediarecorder.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <stdlib.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+#include <functional>
+#include <string>
+
+#include "FuzzerMediaUtility.h"
+#include "fuzzer/FuzzedDataProvider.h"
+
+static constexpr uint16_t kMaxOperations = 5000;
+static constexpr uint8_t kMaxPackageNameLen = 50;
+// For other strings in mpeg we want a higher limit.
+static constexpr uint16_t kMaxMPEGStrLen = 1000;
+static constexpr uint16_t kMaxMediaBlobSize = 1000;
+
+namespace android {
+
+std::string getFourCC(FuzzedDataProvider *fdp) {
+ std::string fourCC = fdp->ConsumeRandomLengthString(4);
+ // Replace any existing nulls
+ for (size_t pos = 0; pos < fourCC.length(); pos++) {
+ if (fourCC.at(pos) == '\0') {
+ fourCC.replace(pos, 1, "a");
+ }
+ }
+
+ // If our string is too short, fill the remainder with "a"s.
+ while (fourCC.length() < 4) {
+ fourCC += 'a';
+ }
+ return fourCC;
+}
+
+typedef std::vector<std::function<void(FuzzedDataProvider*,
+ sp<MediaWriter>, sp<MetaData>, int tmpFileFd)>> OperationVec;
+typedef std::vector<std::function<void(FuzzedDataProvider*, MPEG4Writer*)>> MPEG4OperationVec;
+static const OperationVec operations = {
+ [](FuzzedDataProvider*, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->pause();
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
+ bool valid_fd = dataProvider->ConsumeBool();
+ int fd = -1;
+ if (valid_fd) {
+ fd = tmpFd;
+ }
+ // Args don't seem to be used
+ Vector<String16> args;
+ mediaWriter->dump(fd, args);
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
+ bool valid_fd = dataProvider->ConsumeBool();
+ int fd = -1;
+ if (valid_fd) {
+ fd = tmpFd;
+ }
+ mediaWriter->setNextFd(fd);
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setCaptureRate(dataProvider->ConsumeFloatingPoint<float>());
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setStartTimeOffsetMs(dataProvider->ConsumeIntegral<int>());
+
+ // Likely won't do much, but might as well as do a quick check
+ // while we're here.
+ mediaWriter->getStartTimeOffsetMs();
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
+ },
+};
+
+static const MPEG4OperationVec mpeg4Operations = {
+ [](FuzzedDataProvider*, MPEG4Writer *mediaWriter) { mediaWriter->notifyApproachingLimit(); },
+ // Lower level write methods.
+ // High-level startBox/endBox/etc are all called elsewhere,
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint8_t val = dataProvider->ConsumeIntegral<uint8_t>();
+ mediaWriter->writeInt8(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint16_t val = dataProvider->ConsumeIntegral<uint16_t>();
+ mediaWriter->writeInt16(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint32_t val = dataProvider->ConsumeIntegral<uint32_t>();
+ mediaWriter->writeInt32(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint64_t val = dataProvider->ConsumeIntegral<uint64_t>();
+ mediaWriter->writeInt64(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ std::string strVal = dataProvider->ConsumeRandomLengthString(kMaxMPEGStrLen);
+ mediaWriter->writeCString(strVal.c_str());
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ std::string fourCC = getFourCC(dataProvider);
+ mediaWriter->writeFourcc(fourCC.c_str());
+ },
+
+ // Misc setters
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint32_t layers = dataProvider->ConsumeIntegral<uint32_t>();
+ mediaWriter->setTemporalLayerCount(layers);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint32_t duration = dataProvider->ConsumeIntegral<uint32_t>();
+ mediaWriter->setInterleaveDuration(duration);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ int lat = dataProvider->ConsumeIntegral<int>();
+ int lon = dataProvider->ConsumeIntegral<int>();
+ mediaWriter->setGeoData(lat, lon);
+ },
+};
+
+// Not all writers can always add new sources, so we'll need additional checks.
+void addSource(FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter) {
+ sp<MediaSource> mediaSource = genMediaSource(dataProvider, kMaxMediaBlobSize);
+ if (mediaSource == NULL) {
+ // There's a static check preventing NULLs in addSource.
+ return;
+ }
+ mediaWriter->addSource(mediaSource);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ TemporaryFile tf;
+ sp<MetaData> fileMeta = new MetaData;
+ StandardWriters writerType = dataProvider.ConsumeEnum<StandardWriters>();
+ sp<MediaWriter> writer = createWriter(tf.fd, writerType, fileMeta);
+
+ std::string packageName = dataProvider.ConsumeRandomLengthString(kMaxPackageNameLen);
+
+ sp<MediaRecorder> mr = new MediaRecorder(String16(packageName.c_str()));
+ writer->setListener(mr);
+
+ uint8_t baseOpLen = operations.size();
+ uint8_t totalLen = baseOpLen;
+ uint8_t maxSources;
+ // Different writers support different amounts of sources.
+ switch (writerType) {
+ case StandardWriters::AAC:
+ case StandardWriters::AAC_ADTS:
+ case StandardWriters::AMR_NB:
+ case StandardWriters::AMR_WB:
+ case StandardWriters::OGG:
+ maxSources = 1;
+ break;
+ case StandardWriters::WEBM:
+ maxSources = 2;
+ break;
+ default:
+ maxSources = UINT8_MAX;
+ break;
+ }
+ // Initialize some number of sources and add them to our writer.
+ uint8_t sourceCount = dataProvider.ConsumeIntegralInRange<uint8_t>(0, maxSources);
+ for (uint8_t i = 0; i < sourceCount; i++) {
+ addSource(&dataProvider, writer);
+ }
+
+ // Increase our range if additional operations are implemented.
+ // Currently only MPEG4 has additiona public operations on their writer.
+ if (writerType == StandardWriters::MPEG4) {
+ totalLen += mpeg4Operations.size();
+ }
+
+ // Many operations require the writer to be started.
+ writer->start(fileMeta.get());
+ for (size_t ops_run = 0; dataProvider.remaining_bytes() > 0 && ops_run < kMaxOperations - 1;
+ ops_run++) {
+ uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, totalLen - 1);
+ if (op < baseOpLen) {
+ operations[op](&dataProvider, writer, fileMeta, tf.fd);
+ } else if (writerType == StandardWriters::MPEG4) {
+ mpeg4Operations[op - baseOpLen](&dataProvider, (MPEG4Writer*)writer.get());
+ } else {
+ // Here just in case, will error out.
+ operations[op](&dataProvider, writer, fileMeta, tf.fd);
+ }
+ }
+ writer->stop();
+
+ writer.clear();
+ writer = nullptr;
+ return 0;
+}
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/dictionaries/formats.dict b/media/libstagefright/tests/fuzzers/dictionaries/formats.dict
new file mode 100644
index 0000000..4ab22de
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/dictionaries/formats.dict
@@ -0,0 +1,299 @@
+############################################################################################################
+# This file is a combination of these dictionaries: #
+# https://github.com/google/fuzzing/blob/0c48531c4d317cea9479b3ec1b0ddb9edc438c3a/dictionaries/mp4.dict #
+# https://github.com/google/fuzzing/blob/0c48531c4d317cea9479b3ec1b0ddb9edc438c3a/dictionaries/webm.dict #
+# https://github.com/google/fuzzing/blob/0c48531c4d317cea9479b3ec1b0ddb9edc438c3a/dictionaries/ogg.dict #
+# MPEG4, OGG, and WEBM are all formats used by MediaWriter. #
+############################################################################################################
+# mp4.dict
+# Taken from https://chromium.googlesource.com/chromium/src/+/master/media/test/mp4.dict
+FOURCC_NULL="\x00\x00\x00\x00"
+FOURCC_AC3 ="\x61\x63\x2d\x33"
+FOURCC_EAC3="\x65\x63\x2d\x33"
+FOURCC_AVC1="\x61\x76\x63\x31"
+FOURCC_AVC3="\x61\x76\x63\x33"
+FOURCC_AVCC="\x61\x76\x63\x43"
+FOURCC_BLOC="\x62\x6C\x6F\x63"
+FOURCC_CENC="\x63\x65\x6e\x63"
+FOURCC_CO64="\x63\x6f\x36\x34"
+FOURCC_CTTS="\x63\x74\x74\x73"
+FOURCC_DINF="\x64\x69\x6e\x66"
+FOURCC_EDTS="\x65\x64\x74\x73"
+FOURCC_EMSG="\x65\x6d\x73\x67"
+FOURCC_ELST="\x65\x6c\x73\x74"
+FOURCC_ENCA="\x65\x6e\x63\x61"
+FOURCC_ENCV="\x65\x6e\x63\x76"
+FOURCC_ESDS="\x65\x73\x64\x73"
+FOURCC_FREE="\x66\x72\x65\x65"
+FOURCC_FRMA="\x66\x72\x6d\x61"
+FOURCC_FTYP="\x66\x74\x79\x70"
+FOURCC_HDLR="\x68\x64\x6c\x72"
+FOURCC_HINT="\x68\x69\x6e\x74"
+FOURCC_HVC1="\x68\x76\x63\x31"
+FOURCC_HVCC="\x68\x76\x63\x43"
+FOURCC_IODS="\x69\x6f\x64\x73"
+FOURCC_MDAT="\x6d\x64\x61\x74"
+FOURCC_MDHD="\x6d\x64\x68\x64"
+FOURCC_MDIA="\x6d\x64\x69\x61"
+FOURCC_MECO="\x6d\x65\x63\x6f"
+FOURCC_MEHD="\x6d\x65\x68\x64"
+FOURCC_META="\x6d\x65\x74\x61"
+FOURCC_MFHD="\x6d\x66\x68\x64"
+FOURCC_MFRA="\x6d\x66\x72\x61"
+FOURCC_MINF="\x6d\x69\x6e\x66"
+FOURCC_MOOF="\x6d\x6f\x6f\x66"
+FOURCC_MOOV="\x6d\x6f\x6f\x76"
+FOURCC_MP4A="\x6d\x70\x34\x61"
+FOURCC_MP4V="\x6d\x70\x34\x76"
+FOURCC_MVEX="\x6d\x76\x65\x78"
+FOURCC_MVHD="\x6d\x76\x68\x64"
+FOURCC_PASP="\x70\x61\x73\x70"
+FOURCC_PDIN="\x70\x64\x69\x6e"
+FOURCC_PRFT="\x70\x72\x66\x74"
+FOURCC_PSSH="\x70\x73\x73\x68"
+FOURCC_SAIO="\x73\x61\x69\x6f"
+FOURCC_SAIZ="\x73\x61\x69\x7a"
+FOURCC_SBGP="\x73\x62\x67\x70"
+FOURCC_SCHI="\x73\x63\x68\x69"
+FOURCC_SCHM="\x73\x63\x68\x6d"
+FOURCC_SDTP="\x73\x64\x74\x70"
+FOURCC_SEIG="\x73\x65\x69\x67"
+FOURCC_SENC="\x73\x65\x6e\x63"
+FOURCC_SGPD="\x73\x67\x70\x64"
+FOURCC_SIDX="\x73\x69\x64\x78"
+FOURCC_SINF="\x73\x69\x6e\x66"
+FOURCC_SKIP="\x73\x6b\x69\x70"
+FOURCC_SMHD="\x73\x6d\x68\x64"
+FOURCC_SOUN="\x73\x6f\x75\x6e"
+FOURCC_SSIX="\x73\x73\x69\x78"
+FOURCC_STBL="\x73\x74\x62\x6c"
+FOURCC_STCO="\x73\x74\x63\x6f"
+FOURCC_STSC="\x73\x74\x73\x63"
+FOURCC_STSD="\x73\x74\x73\x64"
+FOURCC_STSS="\x73\x74\x73\x73"
+FOURCC_STSZ="\x73\x74\x73\x7a"
+FOURCC_STTS="\x73\x74\x74\x73"
+FOURCC_STYP="\x73\x74\x79\x70"
+FOURCC_TENC="\x74\x65\x6e\x63"
+FOURCC_TFDT="\x74\x66\x64\x74"
+FOURCC_TFHD="\x74\x66\x68\x64"
+FOURCC_TKHD="\x74\x6b\x68\x64"
+FOURCC_TRAF="\x74\x72\x61\x66"
+FOURCC_TRAK="\x74\x72\x61\x6b"
+FOURCC_TREX="\x74\x72\x65\x78"
+FOURCC_TRUN="\x74\x72\x75\x6e"
+FOURCC_UDTA="\x75\x64\x74\x61"
+FOURCC_UUID="\x75\x75\x69\x64"
+FOURCC_VIDE="\x76\x69\x64\x65"
+FOURCC_VMHD="\x76\x6d\x68\x64"
+FOURCC_WIDE="\x77\x69\x64\x65"
+
+# ogg.dict
+# https://xiph.org/vorbis/doc/Vorbis_I_spec.html
+
+header="OggS"
+
+# Codecs
+"BBCD\x00"
+"\x7fFLAC"
+"\x80theora"
+"\x01vorbis"
+"CELT "
+"CMML\x00\x00\x00\x00"
+"\x8bJNG\x0d\x0a\x1a\x0a"
+"\x80kate\x00\x00\x00"
+"OggMIDI\x00"
+"\x8aMNG\x0d\x0a\x1a\x0a"
+"PCM "
+"\x89PNG\x0d\x0a\x1a\x0a"
+"Speex "
+"YUV4MPEG"
+
+# Metadata
+"TITLE="
+"VERSION="
+"ALBUM="
+"TRACKNUMBER="
+"ARTIST="
+"PERFORMER="
+"COPYRIGHT="
+"LICENSE="
+"ORGANIZATION="
+"DESCRIPTION="
+"GENRE="
+"DATE="
+"LOCATION="
+"CONTACT="
+"ISRC="
+
+# webm.dict
+# Element IDs.
+IdAesSettingsCipherMode = "\x47\xE8"
+IdAlphaMode = "\x53\xC0"
+IdAspectRatioType = "\x54\xB3"
+IdAudio = "\xE1"
+IdBitDepth = "\x62\x64"
+IdBitsPerChannel = "\x55\xB2"
+IdBlock = "\xA1"
+IdBlockAddId = "\xEE"
+IdBlockAdditional = "\xA5"
+IdBlockAdditions = "\x75\xA1"
+IdBlockDuration = "\x9B"
+IdBlockGroup = "\xA0"
+IdBlockMore = "\xA6"
+IdBlockVirtual = "\xA2"
+IdCbSubsamplingHorz = "\x55\xB5"
+IdCbSubsamplingVert = "\x55\xB6"
+IdChannels = "\x9F"
+IdChapCountry = "\x43\x7E"
+IdChapLanguage = "\x43\x7C"
+IdChapString = "\x85"
+IdChapterAtom = "\xB6"
+IdChapterDisplay = "\x80"
+IdChapterStringUID = "\x56\x54"
+IdChapterStringUid = "\x56\x54"
+IdChapterTimeEnd = "\x92"
+IdChapterTimeStart = "\x91"
+IdChapterUID = "\x73\xC4"
+IdChapterUid = "\x73\xC4"
+IdChapters = "\x10\x43\xA7\x70"
+IdChromaSitingHorz = "\x55\xB7"
+IdChromaSitingVert = "\x55\xB8"
+IdChromaSubsamplingHorz = "\x55\xB3"
+IdChromaSubsamplingVert = "\x55\xB4"
+IdCluster = "\x1F\x43\xB6\x75"
+IdCodecDelay = "\x56\xAA"
+IdCodecID = "\x86"
+IdCodecName = "\x25\x86\x88"
+IdCodecPrivate = "\x63\xA2"
+IdColour = "\x55\xB0"
+IdContentEncAESSettings = "\x47\xE7"
+IdContentEncAesSettings = "\x47\xE7"
+IdContentEncAlgo = "\x47\xE1"
+IdContentEncKeyId = "\x47\xE2"
+IdContentEncoding = "\x62\x40"
+IdContentEncodingOrder = "\x50\x31"
+IdContentEncodingScope = "\x50\x32"
+IdContentEncodingType = "\x50\x33"
+IdContentEncodings = "\x6D\x80"
+IdContentEncryption = "\x50\x35"
+IdCueBlockNumber = "\x53\x78"
+IdCueClusterPosition = "\xF1"
+IdCueDuration = "\xB2"
+IdCuePoint = "\xBB"
+IdCueRelativePosition = "\xF0"
+IdCueTime = "\xB3"
+IdCueTrack = "\xF7"
+IdCueTrackPositions = "\xB7"
+IdCues = "\x1C\x53\xBB\x6B"
+IdDateUTC = "\x44\x61"
+IdDateUtc = "\x44\x61"
+IdDefaultDuration = "\x23\xE3\x83"
+IdDiscardPadding = "\x75\xA2"
+IdDisplayHeight = "\x54\xBA"
+IdDisplayUnit = "\x54\xB2"
+IdDisplayWidth = "\x54\xB0"
+IdDocType = "\x42\x82"
+IdDocTypeReadVersion = "\x42\x85"
+IdDocTypeVersion = "\x42\x87"
+IdDuration = "\x44\x89"
+IdEBML = "\x1A\x45\xDF\xA3"
+IdEBMLMaxIDLength = "\x42\xF2"
+IdEBMLMaxSizeLength = "\x42\xF3"
+IdEBMLReadVersion = "\x42\xF7"
+IdEBMLVersion = "\x42\x86"
+IdEbml = "\x1A\x45\xDF\xA3"
+IdEbmlMaxIdLength = "\x42\xF2"
+IdEbmlMaxSizeLength = "\x42\xF3"
+IdEbmlReadVersion = "\x42\xF7"
+IdEbmlVersion = "\x42\x86"
+IdEditionEntry = "\x45\xB9"
+IdFileUsedEndTime = "\x46\x62"
+IdFileUsedStartTime = "\x46\x61"
+IdFlagDefault = "\x88"
+IdFlagEnabled = "\xB9"
+IdFlagForced = "\x55\xAA"
+IdFlagInterlaced = "\x9A"
+IdFlagLacing = "\x9C"
+IdFrameRate = "\x23\x83\xE3"
+IdInfo = "\x15\x49\xA9\x66"
+IdLaceNumber = "\xCC"
+IdLanguage = "\x22\xB5\x9C"
+IdLuminanceMax = "\x55\xD9"
+IdLuminanceMin = "\x55\xDA"
+IdMasteringMetadata = "\x55\xD0"
+IdMatrixCoefficients = "\x55\xB1"
+IdMaxCll = "\x55\xBC"
+IdMaxFall = "\x55\xBD"
+IdMuxingApp = "\x4D\x80"
+IdName = "\x53\x6E"
+IdOutputSamplingFrequency = "\x78\xB5"
+IdPixelCropBottom = "\x54\xAA"
+IdPixelCropLeft = "\x54\xCC"
+IdPixelCropRight = "\x54\xDD"
+IdPixelCropTop = "\x54\xBB"
+IdPixelHeight = "\xBA"
+IdPixelWidth = "\xB0"
+IdPrevSize = "\xAB"
+IdPrimaries = "\x55\xBB"
+IdPrimaryBChromaticityX = "\x55\xD5"
+IdPrimaryBChromaticityY = "\x55\xD6"
+IdPrimaryGChromaticityX = "\x55\xD3"
+IdPrimaryGChromaticityY = "\x55\xD4"
+IdPrimaryRChromaticityX = "\x55\xD1"
+IdPrimaryRChromaticityY = "\x55\xD2"
+IdProjection = "\x76\x70"
+IdProjectionPosePitch = "\x76\x74"
+IdProjectionPoseRoll = "\x76\x75"
+IdProjectionPoseYaw = "\x76\x73"
+IdProjectionPrivate = "\x76\x72"
+IdProjectionType = "\x76\x71"
+IdRange = "\x55\xB9"
+IdReferenceBlock = "\xFB"
+IdSamplingFrequency = "\xB5"
+IdSeek = "\x4D\xBB"
+IdSeekHead = "\x11\x4D\x9B\x74"
+IdSeekID = "\x53\xAB"
+IdSeekPosition = "\x53\xAC"
+IdSeekPreRoll = "\x56\xBB"
+IdSegment = "\x18\x53\x80\x67"
+IdSimpleBlock = "\xA3"
+IdSimpleTag = "\x67\xC8"
+IdSliceDuration = "\xCF"
+IdSlices = "\x8E"
+IdStereoMode = "\x53\xB8"
+IdTag = "\x73\x73"
+IdTagBinary = "\x44\x85"
+IdTagDefault = "\x44\x84"
+IdTagLanguage = "\x44\x7A"
+IdTagName = "\x45\xA3"
+IdTagString = "\x44\x87"
+IdTagTrackUid = "\x63\xC5"
+IdTags = "\x12\x54\xC3\x67"
+IdTargetType = "\x63\xCA"
+IdTargetTypeValue = "\x68\xCA"
+IdTargets = "\x63\xC0"
+IdTimeSlice = "\xE8"
+IdTimecode = "\xE7"
+IdTimecodeScale = "\x2A\xD7\xB1"
+IdTitle = "\x7B\xA9"
+IdTrackEntry = "\xAE"
+IdTrackNumber = "\xD7"
+IdTrackType = "\x83"
+IdTrackUID = "\x73\xC5"
+IdTracks = "\x16\x54\xAE\x6B"
+IdTransferCharacteristics = "\x55\xBA"
+IdTrickMasterTrackSegmentUID = "\xC4"
+IdTrickMasterTrackUID = "\xC7"
+IdTrickTrackFlag = "\xC6"
+IdTrickTrackSegmentUID = "\xC1"
+IdTrickTrackUID = "\xC0"
+IdVideo = "\xE0"
+IdVoid = "\xEC"
+IdWhitePointChromaticityX = "\x55\xD7"
+IdWhitePointChromaticityY = "\x55\xD8"
+IdWritingApp = "\x57\x41"
+
+# Interesting sizes.
+SizeUnknown = "\xFF"
+
diff --git a/media/libstagefright/tests/mediacodec/Android.bp b/media/libstagefright/tests/mediacodec/Android.bp
index 0bd0639..9cdc6d4 100644
--- a/media/libstagefright/tests/mediacodec/Android.bp
+++ b/media/libstagefright/tests/mediacodec/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_test {
name: "mediacodecTest",
gtest: true,
diff --git a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
index d00a50f..06e36ad 100644
--- a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
+++ b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
@@ -285,17 +285,20 @@
// 1) Client thread calls stop(); MediaCodec looper thread calls
// initiateShutdown(); shutdown is being handled at the component thread.
// 2) Error occurred, but the shutdown operation is still being done.
- // 3) MediaCodec looper thread handles the error.
- // 4) Component thread completes shutdown and posts onStopCompleted()
+ // 3) Another error occurred during the shutdown operation.
+ // 4) MediaCodec looper thread handles the error.
+ // 5) Client releases the codec upon the error; previous shutdown is still
+ // going on.
+ // 6) Component thread completes shutdown and posts onStopCompleted();
+ // Shutdown from release also completes.
static const AString kCodecName{"test.codec"};
static const AString kCodecOwner{"nobody"};
static const AString kMediaType{"video/x-test"};
- std::promise<void> errorOccurred;
sp<MockCodec> mockCodec;
std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase =
- [&mockCodec, &errorOccurred](const AString &, const char *) {
+ [&mockCodec](const AString &, const char *) {
mockCodec = new MockCodec([](const std::shared_ptr<MockBufferChannel> &) {
// No mock setup, as we don't expect any buffer operations
// in this scenario.
@@ -314,13 +317,17 @@
mockCodec->callback()->onStartCompleted();
});
ON_CALL(*mockCodec, initiateShutdown(true))
- .WillByDefault([mockCodec, &errorOccurred](bool) {
+ .WillByDefault([mockCodec](bool) {
+ // 2)
mockCodec->callback()->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- // Mark that 1) and 2) are complete.
- errorOccurred.set_value();
+ // 3)
+ mockCodec->callback()->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
});
ON_CALL(*mockCodec, initiateShutdown(false))
.WillByDefault([mockCodec](bool) {
+ // Previous stop finished now.
+ mockCodec->callback()->onStopCompleted();
+ // Release also finished.
mockCodec->callback()->onReleaseCompleted();
});
return mockCodec;
@@ -332,19 +339,13 @@
ASSERT_NE(nullptr, codec) << "Codec must not be null";
ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";
- std::thread([mockCodec, &errorOccurred]{
- // Simulate component thread that handles stop()
- errorOccurred.get_future().wait();
- // Error occurred but shutdown request still got processed.
- mockCodec->callback()->onStopCompleted();
- }).detach();
-
codec->configure(new AMessage, nullptr, nullptr, 0);
codec->start();
- codec->stop();
- // Sleep here to give time for the MediaCodec looper thread
- // to process the messages.
+ // stop() will fail because of the error
+ EXPECT_NE(OK, codec->stop());
+ // sleep here so that the looper thread can handle all the errors.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ // upon receiving the error, client tries to release the codec.
codec->release();
looper->stop();
}
diff --git a/media/libstagefright/tests/metadatautils/Android.bp b/media/libstagefright/tests/metadatautils/Android.bp
index 69830fc..ecdf89b 100644
--- a/media/libstagefright/tests/metadatautils/Android.bp
+++ b/media/libstagefright/tests/metadatautils/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_test {
name: "MetaDataUtilsTest",
gtest: true,
diff --git a/media/libstagefright/tests/writer/Android.bp b/media/libstagefright/tests/writer/Android.bp
index b5d453e..38d5ecc 100644
--- a/media/libstagefright/tests/writer/Android.bp
+++ b/media/libstagefright/tests/writer/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_tests_license",
+ ],
+}
+
cc_test {
name: "writerTest",
gtest: true,
diff --git a/media/libstagefright/timedtext/Android.bp b/media/libstagefright/timedtext/Android.bp
index 4f4ceb1..6590ef7 100644
--- a/media/libstagefright/timedtext/Android.bp
+++ b/media/libstagefright/timedtext/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_timedtext_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_libstagefright_timedtext_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libstagefright_timedtext",
@@ -22,5 +41,3 @@
shared_libs: ["libmedia"],
}
-
-
diff --git a/media/libstagefright/timedtext/test/Android.bp b/media/libstagefright/timedtext/test/Android.bp
index 36f8891..e8ee2ee 100644
--- a/media/libstagefright/timedtext/test/Android.bp
+++ b/media/libstagefright/timedtext/test/Android.bp
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_timedtext_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_timedtext_license",
+ ],
+}
+
cc_test {
name: "TimedTextUnitTest",
gtest: true,
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 2cebe8f..68752cd 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_static {
name: "libstagefright_webm",
diff --git a/media/libstagefright/webm/tests/Android.bp b/media/libstagefright/webm/tests/Android.bp
index 5183a49..4443766 100644
--- a/media/libstagefright/webm/tests/Android.bp
+++ b/media/libstagefright/webm/tests/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_test {
name: "WebmFrameThreadUnitTest",
gtest: true,
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
new file mode 100644
index 0000000..a33b888
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
+cc_defaults {
+ name: "writer-fuzzerbase-defaults",
+ local_include_dirs: [
+ "include",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ static_libs: [
+ "liblog",
+ "libstagefright_foundation",
+ "libstagefright",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
+
+cc_defaults {
+ name: "writer-fuzzer-defaults",
+ defaults: ["writer-fuzzerbase-defaults"],
+ static_libs: [
+ "libwriterfuzzerbase",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_library_static {
+ name: "libwriterfuzzerbase",
+ defaults: ["writer-fuzzerbase-defaults"],
+ srcs: [
+ "WriterFuzzerBase.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "amrnb_writer_fuzzer",
+ defaults: ["writer-fuzzer-defaults"],
+ srcs: [
+ "amr_writer_fuzzer.cpp",
+ ],
+ cflags: [
+ "-DAMRNB",
+ ],
+}
+
+cc_fuzz {
+ name: "amrwb_writer_fuzzer",
+ defaults: ["writer-fuzzer-defaults"],
+ srcs: [
+ "amr_writer_fuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name : "mpeg4_writer_fuzzer",
+ defaults : ["writer-fuzzer-defaults"],
+ srcs : [
+ "mpeg4_writer_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_esds",
+ ],
+}
+
+cc_fuzz {
+ name : "ogg_writer_fuzzer",
+ defaults : ["writer-fuzzer-defaults"],
+ srcs : [
+ "ogg_writer_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libogg",
+ ],
+}
+
+cc_fuzz {
+ name : "webm_writer_fuzzer",
+ defaults : ["writer-fuzzer-defaults"],
+ srcs : [
+ "webm_writer_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_webm",
+ "libdatasource",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
+ ],
+}
diff --git a/media/libstagefright/writer_fuzzers/README.md b/media/libstagefright/writer_fuzzers/README.md
new file mode 100644
index 0000000..6f95ecc
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/README.md
@@ -0,0 +1,100 @@
+# Fuzzer for writers
+
+## Table of contents
++ [libwriterfuzzerbase](#WriterFuzzerBase)
++ [Amr Writer](#amrWriterFuzzer)
++ [MPEG4 Writer](#mpeg4WriterFuzzer)
++ [OGG Writer](#oggWriterFuzzer)
++ [WEBM Writer](#webmWriterFuzzer)
+
+# <a name="WriterFuzzerBase"></a> Fuzzer for libwriterfuzzerbase
+All the writers have a common API - creating a writer, adding a source for
+all the tracks, etc. These common APIs have been abstracted in a base class
+called `WriterFuzzerBase` to ensure code is reused between fuzzer plugins.
+
+## Plugin Design Considerations
+The fuzzer plugin for writers is designed based on the understanding of the
+writer and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Fuzzer for writers supports the following parameters:
+1. Track Mime (parameter name: `mime`)
+2. Channel Count (parameter name: `channel-count`)
+3. Sample Rate (parameter name: `sample-rate`)
+4. Frame Height (parameter name: `height`)
+5. Frame Width (parameter name: `width`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `mime` | 0. `audio/3gpp` 1. `audio/amr-wb` 2. `audio/vorbis` 3. `audio/opus` 4. `audio/mp4a-latm` 5. `audio/mpeg` 6. `audio/mpeg-L1` 7. `audio/mpeg-L2` 8. `audio/midi` 9. `audio/qcelp` 10. `audio/g711-alaw` 11. `audio/g711-mlaw` 12. `audio/flac` 13. `audio/aac-adts` 14. `audio/gsm` 15. `audio/ac3` 16. `audio/eac3` 17. `audio/eac3-joc` 18. `audio/ac4` 19. `audio/scrambled` 20. `audio/alac` 21. `audio/x-ms-wma` 22. `audio/x-adpcm-ms` 23. `audio/x-adpcm-dvi-ima` 24. `video/avc` 25. `video/hevc` 26. `video/mp4v-es` 27. `video/3gpp` 28. `video/x-vnd.on2.vp8` 29. `video/x-vnd.on2.vp9` 30. `video/av01` 31. `video/mpeg2` 32. `video/dolby-vision` 33. `video/scrambled` 34. `video/divx` 35. `video/divx3` 36. `video/xvid` 37. `video/x-motion-jpeg` 38. `text/3gpp-tt` 39. `application/x-subrip` 40. `text/vtt` 41. `text/cea-608` 42. `text/cea-708` 43. `application/x-id3v4` | All the bits of 2nd byte of data for first track and 11th byte of data for second track and 20th byte of data for third track(if present) modulus 44 |
+| `channel-count` | In the range `0 to INT32_MAX` | All the bits of 3rd byte to 6th bytes of data if first track is audio and 12th to 15th bytes of data if second track is audio |
+| `sample-rate` | In the range `1 to INT32_MAX` | All the bits of 7th byte to 10th bytes of data if first track is audio and 16th to 19th bytes of data if second track is audio |
+| `height` | In the range `0 to INT32_MAX` | All the bits of 3rd byte to 6th bytes of data if first track is video and 12th to 15th bytes of data if second track is video |
+| `width` | In the range `0 to INT32_MAX` | All the bits of 7th byte to 10th bytes of data if first track is video and 16th to 19th bytes of data if second track is video |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin divides the entire input data into frames based on frame markers.
+If no frame marker is found then the entire input data is treated as single frame.
+
+This ensures that the plugin tolerates any kind of input (huge,
+malformed, etc) and thereby increasing the chance of identifying vulnerabilities.
+
+# <a name="amrWriterFuzzer"></a> Fuzzer for Amr Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for AMR writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the AMR writer class.
+
+##### Other considerations
+ * Two fuzzer binaries - amrnb_writer_fuzzer and amrwb_writer_fuzzer are generated based on the presence of a flag - 'AMRNB'
+
+# <a name="mpeg4WriterFuzzer"></a> Fuzzer for MPEG4 Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for MPEG4 writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the MPEG4 writer class.
+
+# <a name="oggWriterFuzzer"></a> Fuzzer for OGG Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for OGG writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the OGG writer class.
+
+# <a name="webmWriterFuzzer"></a> Fuzzer for WEBM Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for WEBM writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the WEBM writer class.
+
+## Build
+
+This describes steps to build writer fuzzer binaries.
+
+### Android
+
+`*` = amrnb/amrwb/mpeg4/ogg/webm
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) *_writer_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some media files to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/*_writer_fuzzer/*_writer_fuzzer CORPUS_DIR
+```
+
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
new file mode 100644
index 0000000..ee7af70
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <utils/Log.h>
+
+#include "WriterFuzzerBase.h"
+
+using namespace android;
+
+/**
+ * Buffer source implementations to parse input file
+ */
+
+uint32_t WriterFuzzerBase::BufferSource::getNumTracks() {
+ uint32_t numTracks = 0;
+ if (mSize > sizeof(uint8_t)) {
+ numTracks = min(mData[0], kMaxTrackCount);
+ mReadIndex += sizeof(uint8_t);
+ }
+ return numTracks;
+}
+
+bool WriterFuzzerBase::BufferSource::searchForMarker(size_t startIndex) {
+ while (true) {
+ if (isMarker()) {
+ return true;
+ }
+ --mReadIndex;
+ if (mReadIndex < startIndex) {
+ break;
+ }
+ }
+ return false;
+}
+
+ConfigFormat WriterFuzzerBase::BufferSource::getConfigFormat(int32_t trackIndex) {
+ return mParams[trackIndex];
+}
+
+int32_t WriterFuzzerBase::BufferSource::getNumCsds(int32_t trackIndex) {
+ return mNumCsds[trackIndex];
+}
+
+vector<FrameData> &WriterFuzzerBase::BufferSource::getFrameList(int32_t trackIndex) {
+ return mFrameList[trackIndex];
+}
+
+void WriterFuzzerBase::BufferSource::getFrameInfo() {
+ size_t readIndexStart = mReadIndex;
+ if (mSize - mReadIndex > kMarkerSize + kMarkerSuffixSize) {
+ bool isFrameAvailable = true;
+ size_t bytesRemaining = mSize;
+ mReadIndex = mSize - kMarkerSize;
+ while (isFrameAvailable) {
+ isFrameAvailable = searchForMarker(readIndexStart);
+ if (isFrameAvailable) {
+ size_t location = mReadIndex + kMarkerSize;
+ if (location + kMarkerSuffixSize >= bytesRemaining) {
+ break;
+ }
+ bool isCSD = isCSDMarker(location);
+ location += kMarkerSuffixSize;
+ uint8_t *framePtr = const_cast<uint8_t *>(&mData[location]);
+ size_t frameSize = bytesRemaining - location, bufferSize = 0;
+ uint8_t trackIndex = framePtr[0] % kMaxTrackCount;
+ ++framePtr;
+ uint8_t flags = 0;
+ int64_t pts = 0;
+ if (isCSD && frameSize > 1) {
+ flags |= kCodecConfigFlag;
+ pts = 0;
+ ++mNumCsds[trackIndex];
+ bufferSize = frameSize - 1;
+ } else if (frameSize > sizeof(uint8_t) + sizeof(int64_t) + 1) {
+ flags = flagTypes[framePtr[0] % size(flagTypes)];
+ ++framePtr;
+ copy(framePtr, framePtr + sizeof(int64_t), reinterpret_cast<uint8_t *>(&pts));
+ framePtr += sizeof(int64_t);
+ bufferSize = frameSize - (sizeof(uint8_t) + sizeof(int64_t)) - 1;
+ } else {
+ break;
+ }
+ mFrameList[trackIndex].insert(mFrameList[trackIndex].begin(),
+ FrameData{bufferSize, flags, pts, framePtr});
+ bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
+ --mReadIndex;
+ }
+ }
+ }
+ if (mFrameList[0].empty() && mFrameList[1].empty()) {
+ /**
+ * Scenario where input data does not contain the custom frame markers.
+ * Hence feed the entire data as single frame.
+ */
+ mFrameList[0].emplace_back(FrameData{mSize - readIndexStart, 0, 0, mData + readIndexStart});
+ }
+}
+bool WriterFuzzerBase::BufferSource::getTrackInfo(int32_t trackIndex) {
+ if (mSize <= mReadIndex + sizeof(uint8_t)) {
+ return false;
+ }
+ size_t mimeTypeIdx = mData[mReadIndex] % kSupportedMimeTypes;
+ char *mime = (char *)supportedMimeTypes[mimeTypeIdx].c_str();
+ mParams[trackIndex].mime = mime;
+ mReadIndex += sizeof(uint8_t);
+
+ if (mSize > mReadIndex + 2 * sizeof(int32_t)) {
+ if (!strncmp(mime, "audio/", 6)) {
+ copy(mData + mReadIndex, mData + mReadIndex + sizeof(int32_t),
+ reinterpret_cast<char *>(&mParams[trackIndex].channelCount));
+ copy(mData + mReadIndex + sizeof(int32_t), mData + mReadIndex + 2 * sizeof(int32_t),
+ reinterpret_cast<char *>(&mParams[trackIndex].sampleRate));
+ } else if (!strncmp(mime, "video/", 6)) {
+ copy(mData + mReadIndex, mData + mReadIndex + sizeof(int32_t),
+ reinterpret_cast<char *>(&mParams[trackIndex].height));
+ copy(mData + mReadIndex + sizeof(int32_t), mData + mReadIndex + 2 * sizeof(int32_t),
+ reinterpret_cast<char *>(&mParams[trackIndex].width));
+ }
+ mReadIndex += 2 * sizeof(int32_t);
+ } else {
+ if (strncmp(mime, "text/", 5) && strncmp(mime, "application/", 12)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void writeHeaderBuffers(vector<FrameData> &bufferInfo, sp<AMessage> &format, int32_t numCsds) {
+ char csdName[kMaxCSDStrlen];
+ for (int csdId = 0; csdId < numCsds; ++csdId) {
+ int32_t flags = bufferInfo[csdId].flags;
+ if (flags == kCodecConfigFlag) {
+ sp<ABuffer> csdBuffer =
+ ABuffer::CreateAsCopy((void *)bufferInfo[csdId].buf, bufferInfo[csdId].size);
+ if (csdBuffer.get() == nullptr || csdBuffer->base() == nullptr) {
+ return;
+ }
+ snprintf(csdName, sizeof(csdName), "csd-%d", csdId);
+ format->setBuffer(csdName, csdBuffer);
+ }
+ }
+}
+
+bool WriterFuzzerBase::createOutputFile() {
+ mFd = memfd_create(mOutputFileName.c_str(), MFD_ALLOW_SEALING);
+ if (mFd == -1) {
+ return false;
+ }
+ return true;
+}
+
+void WriterFuzzerBase::addWriterSource(int32_t trackIndex) {
+ ConfigFormat params = mBufferSource->getConfigFormat(trackIndex);
+ sp<AMessage> format = new AMessage;
+ format->setString("mime", params.mime);
+ if (!strncmp(params.mime, "audio/", 6)) {
+ if (!strncmp(params.mime, "audio/3gpp", 10)) {
+ params.channelCount = 1;
+ params.sampleRate = 8000;
+ } else if (!strncmp(params.mime, "audio/amr-wb", 12)) {
+ params.channelCount = 1;
+ params.sampleRate = 16000;
+ } else {
+ params.sampleRate = max(1, params.sampleRate);
+ }
+ format->setInt32("channel-count", params.channelCount);
+ format->setInt32("sample-rate", params.sampleRate);
+ } else if (!strncmp(params.mime, "video/", 6)) {
+ format->setInt32("width", params.width);
+ format->setInt32("height", params.height);
+ }
+ int32_t numCsds = mBufferSource->getNumCsds(trackIndex);
+ if (numCsds) {
+ vector<FrameData> mFrames = mBufferSource->getFrameList(trackIndex);
+ writeHeaderBuffers(mFrames, format, numCsds);
+ }
+ sp<MetaData> trackMeta = new MetaData;
+ convertMessageToMetaData(format, trackMeta);
+ mCurrentTrack[trackIndex] = new MediaAdapter(trackMeta);
+ mWriter->addSource(mCurrentTrack[trackIndex]);
+}
+
+void WriterFuzzerBase::start() {
+ mFileMeta->setInt32(kKeyRealTimeRecording, false);
+ mWriter->start(mFileMeta.get());
+}
+
+void WriterFuzzerBase::sendBuffersToWriter(sp<MediaAdapter> ¤tTrack, int32_t trackIndex,
+ int32_t startFrameIndex, int32_t endFrameIndex) {
+ vector<FrameData> bufferInfo = mBufferSource->getFrameList(trackIndex);
+ for (int idx = startFrameIndex; idx < endFrameIndex; ++idx) {
+ sp<ABuffer> buffer = new ABuffer((void *)bufferInfo[idx].buf, bufferInfo[idx].size);
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
+ // Released in MediaAdapter::signalBufferReturned().
+ mediaBuffer->add_ref();
+ mediaBuffer->set_range(buffer->offset(), buffer->size());
+ MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+ sampleMetaData.setInt64(kKeyTime, bufferInfo[idx].timeUs);
+
+ // Just set the kKeyDecodingTime as the presentation time for now.
+ sampleMetaData.setInt64(kKeyDecodingTime, bufferInfo[idx].timeUs);
+ if (bufferInfo[idx].flags == SampleFlag::SYNC_FLAG) {
+ sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+ }
+
+ // This pushBuffer will wait until the mediaBuffer is consumed.
+ currentTrack->pushBuffer(mediaBuffer);
+ }
+}
+
+void WriterFuzzerBase::sendBuffersInterleave(int32_t numTracks, uint8_t numBuffersInterleave) {
+ int32_t currentFrameIndex[numTracks], remainingNumFrames[numTracks], numTrackFramesDone;
+ for (int32_t idx = 0; idx < numTracks; ++idx) {
+ currentFrameIndex[idx] = mBufferSource->getNumCsds(idx);
+ remainingNumFrames[idx] = mBufferSource->getFrameList(idx).size() - currentFrameIndex[idx];
+ }
+ do {
+ numTrackFramesDone = numTracks;
+ for (int32_t idx = 0; idx < numTracks; ++idx) {
+ if (remainingNumFrames[idx] > 0) {
+ int32_t numFramesInterleave =
+ min(remainingNumFrames[idx], static_cast<int32_t>(numBuffersInterleave));
+ sendBuffersToWriter(mCurrentTrack[idx], idx, currentFrameIndex[idx],
+ currentFrameIndex[idx] + numFramesInterleave);
+ currentFrameIndex[idx] += numFramesInterleave;
+ remainingNumFrames[idx] -= numFramesInterleave;
+ --numTrackFramesDone;
+ }
+ }
+ } while (numTrackFramesDone < numTracks);
+}
+
+void WriterFuzzerBase::initFileWriterAndProcessData(const uint8_t *data, size_t size) {
+ if (!createOutputFile()) {
+ return;
+ }
+ if (!createWriter()) {
+ return;
+ }
+
+ if (size < 1) {
+ return;
+ }
+ uint8_t numBuffersInterleave = (data[0] == 0 ? 1 : data[0]);
+ ++data;
+ --size;
+
+ mBufferSource = new BufferSource(data, size);
+ if (!mBufferSource) {
+ return;
+ }
+ mNumTracks = mBufferSource->getNumTracks();
+ if (mNumTracks > 0) {
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ if (!mBufferSource->getTrackInfo(idx)) {
+ if (idx == 0) {
+ delete mBufferSource;
+ return;
+ }
+ mNumTracks = idx;
+ break;
+ }
+ }
+ mBufferSource->getFrameInfo();
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ addWriterSource(idx);
+ }
+ start();
+ sendBuffersInterleave(mNumTracks, numBuffersInterleave);
+ for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+ if (mCurrentTrack[idx]) {
+ mCurrentTrack[idx]->stop();
+ }
+ }
+ }
+ delete mBufferSource;
+ mWriter->stop();
+}
diff --git a/media/libstagefright/writer_fuzzers/amr_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/amr_writer_fuzzer.cpp
new file mode 100644
index 0000000..bbb6f9f
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/amr_writer_fuzzer.cpp
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <media/stagefright/AMRWriter.h>
+
+using namespace android;
+
+class AmrWriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool AmrWriterFuzzer::createWriter() {
+ mWriter = new AMRWriter(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+#ifdef AMRNB
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+#else
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+#endif
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ AmrWriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
new file mode 100644
index 0000000..4315322
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
@@ -0,0 +1,211 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#ifndef __WRITER_FUZZER_BASE_H__
+#define __WRITER_FUZZER_BASE_H__
+
+#include <media/stagefright/MediaAdapter.h>
+#include <media/stagefright/MediaWriter.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <algorithm>
+#include <cstring>
+#include <vector>
+
+using namespace std;
+
+constexpr uint32_t kMimeSize = 128;
+constexpr uint8_t kMaxTrackCount = 3;
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kCodecConfigFlag = 32;
+
+namespace android {
+
+struct ConfigFormat {
+ char* mime;
+ int32_t width;
+ int32_t height;
+ int32_t sampleRate;
+ int32_t channelCount;
+};
+
+struct FrameData {
+ size_t size;
+ uint8_t flags;
+ int64_t timeUs;
+ const uint8_t* buf;
+};
+
+static string supportedMimeTypes[] = {"audio/3gpp",
+ "audio/amr-wb",
+ "audio/vorbis",
+ "audio/opus",
+ "audio/mp4a-latm",
+ "audio/mpeg",
+ "audio/mpeg-L1",
+ "audio/mpeg-L2",
+ "audio/midi",
+ "audio/qcelp",
+ "audio/g711-alaw",
+ "audio/g711-mlaw",
+ "audio/flac",
+ "audio/aac-adts",
+ "audio/gsm",
+ "audio/ac3",
+ "audio/eac3",
+ "audio/eac3-joc",
+ "audio/ac4",
+ "audio/scrambled",
+ "audio/alac",
+ "audio/x-ms-wma",
+ "audio/x-adpcm-ms",
+ "audio/x-adpcm-dvi-ima",
+ "video/avc",
+ "video/hevc",
+ "video/mp4v-es",
+ "video/3gpp",
+ "video/x-vnd.on2.vp8",
+ "video/x-vnd.on2.vp9",
+ "video/av01",
+ "video/mpeg2",
+ "video/dolby-vision",
+ "video/scrambled",
+ "video/divx",
+ "video/divx3",
+ "video/xvid",
+ "video/x-motion-jpeg",
+ "text/3gpp-tt",
+ "application/x-subrip",
+ "text/vtt",
+ "text/cea-608",
+ "text/cea-708",
+ "application/x-id3v4"};
+
+enum SampleFlag {
+ DEFAULT_FLAG = 0,
+ SYNC_FLAG = 1,
+ ENCRYPTED_FLAG = 2,
+};
+
+static uint8_t flagTypes[] = {SampleFlag::DEFAULT_FLAG, SampleFlag::SYNC_FLAG,
+ SampleFlag::ENCRYPTED_FLAG};
+
+class WriterFuzzerBase {
+ public:
+ WriterFuzzerBase() = default;
+ virtual ~WriterFuzzerBase() {
+ if (mFileMeta) {
+ mFileMeta.clear();
+ mFileMeta = nullptr;
+ }
+ if (mWriter) {
+ mWriter.clear();
+ mWriter = nullptr;
+ }
+ for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) {
+ if (mCurrentTrack[idx]) {
+ mCurrentTrack[idx]->stop();
+ mCurrentTrack[idx].clear();
+ mCurrentTrack[idx] = nullptr;
+ }
+ }
+ close(mFd);
+ };
+
+ /** Function to create the media writer component.
+ * To be implemented by the derived class.
+ */
+ virtual bool createWriter() = 0;
+
+ /** Parent class functions to be reused by derived class.
+ * These are common for all media writer components.
+ */
+ bool createOutputFile();
+
+ void addWriterSource(int32_t trackIndex);
+
+ void start();
+
+ void sendBuffersToWriter(sp<MediaAdapter>& currentTrack, int32_t trackIndex,
+ int32_t startFrameIndex, int32_t endFrameIndex);
+
+ void sendBuffersInterleave(int32_t numTracks, uint8_t numBuffersInterleave);
+
+ void initFileWriterAndProcessData(const uint8_t* data, size_t size);
+
+ protected:
+ class BufferSource {
+ public:
+ BufferSource(const uint8_t* data, size_t size) : mData(data), mSize(size), mReadIndex(0) {}
+ ~BufferSource() {
+ mData = nullptr;
+ mSize = 0;
+ mReadIndex = 0;
+ for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) {
+ mFrameList[idx].clear();
+ }
+ }
+ uint32_t getNumTracks();
+ bool getTrackInfo(int32_t trackIndex);
+ void getFrameInfo();
+ ConfigFormat getConfigFormat(int32_t trackIndex);
+ int32_t getNumCsds(int32_t trackIndex);
+ vector<FrameData>& getFrameList(int32_t trackIndex);
+
+ private:
+ bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }
+
+ bool isCSDMarker(size_t position) {
+ return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+ }
+
+ bool searchForMarker(size_t startIndex);
+
+ const uint8_t* mData = nullptr;
+ size_t mSize = 0;
+ size_t mReadIndex = 0;
+ ConfigFormat mParams[kMaxTrackCount] = {};
+ int32_t mNumCsds[kMaxTrackCount] = {0};
+ vector<FrameData> mFrameList[kMaxTrackCount];
+
+ static constexpr int kSupportedMimeTypes = size(supportedMimeTypes);
+ static constexpr uint8_t kMarker[] = "_MARK";
+ static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
+ static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
+ // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
+ static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
+ // All marker types should be 3 bytes long ('_H_', '_F_')
+ static constexpr size_t kMarkerSuffixSize = 3;
+ };
+
+ BufferSource* mBufferSource = nullptr;
+ int32_t mFd = -1;
+ uint32_t mNumTracks = 0;
+ string mOutputFileName = "writer.out";
+ sp<MediaWriter> mWriter = nullptr;
+ sp<MetaData> mFileMeta = nullptr;
+ sp<MediaAdapter> mCurrentTrack[kMaxTrackCount] = {};
+};
+
+} // namespace android
+
+#endif // __WRITER_FUZZER_BASE_H__
diff --git a/media/libstagefright/writer_fuzzers/mpeg4_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/mpeg4_writer_fuzzer.cpp
new file mode 100644
index 0000000..99bd2b6
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/mpeg4_writer_fuzzer.cpp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <media/stagefright/MPEG4Writer.h>
+
+using namespace android;
+
+class Mpeg4WriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool Mpeg4WriterFuzzer::createWriter() {
+ mWriter = new MPEG4Writer(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ Mpeg4WriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/writer_fuzzers/ogg_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/ogg_writer_fuzzer.cpp
new file mode 100644
index 0000000..ae9c94c
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/ogg_writer_fuzzer.cpp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <media/stagefright/OggWriter.h>
+
+using namespace android;
+
+class OGGWriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool OGGWriterFuzzer::createWriter() {
+ mWriter = new OggWriter(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ OGGWriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/writer_fuzzers/webm_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/webm_writer_fuzzer.cpp
new file mode 100644
index 0000000..0a91b72
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/webm_writer_fuzzer.cpp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <webm/WebmWriter.h>
+
+using namespace android;
+
+class WEBMWriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool WEBMWriterFuzzer::createWriter() {
+ mWriter = new WebmWriter(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ WEBMWriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index 7ed0e88..055dd80 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_library_headers {
name: "libstagefright_xmlparser_headers",
export_include_dirs: ["include"],
@@ -49,4 +58,3 @@
srcs: ["media_codecs.xsd"],
package_name: "media.codecs",
}
-
diff --git a/media/libstagefright/xmlparser/test/Android.bp b/media/libstagefright/xmlparser/test/Android.bp
index 6d97c96..2fd577c 100644
--- a/media/libstagefright/xmlparser/test/Android.bp
+++ b/media/libstagefright/xmlparser/test/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_test {
name: "XMLParserTest",
gtest: true,
diff --git a/media/libstagefright/xmlparser/vts/Android.bp b/media/libstagefright/xmlparser/vts/Android.bp
index 132ce82..1e36c8f 100644
--- a/media/libstagefright/xmlparser/vts/Android.bp
+++ b/media/libstagefright/xmlparser/vts/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+}
+
cc_test {
name: "vts_mediaCodecs_validate_test",
srcs: [
diff --git a/media/libwatchdog/Android.bp b/media/libwatchdog/Android.bp
index 1a87824..fe717b1 100644
--- a/media/libwatchdog/Android.bp
+++ b/media/libwatchdog/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libwatchdog",
srcs: [
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 8d5c77f..38bb791 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -1,4 +1,21 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_mediaserver_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_mediaserver_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libregistermsext",
srcs: ["register.cpp"],
diff --git a/media/mtp/Android.bp b/media/mtp/Android.bp
index e572249..97e2a22 100644
--- a/media/mtp/Android.bp
+++ b/media/mtp/Android.bp
@@ -14,6 +14,23 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["frameworks_av_media_mtp_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_mtp_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libmtp",
srcs: [
@@ -54,4 +71,3 @@
],
header_libs: ["libcutils_headers"],
}
-
diff --git a/media/mtp/tests/Android.bp b/media/mtp/tests/Android.bp
index 0750208..6ed94ac 100644
--- a/media/mtp/tests/Android.bp
+++ b/media/mtp/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_mtp_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_mtp_license"],
+}
+
cc_test {
name: "mtp_ffs_handle_test",
test_suites: ["device-tests"],
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 71e6fac..e9ea386 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -16,6 +16,37 @@
// to refer to headers in parent directories and the headers live in
// frameworks/av/include.
+package {
+ default_applicable_licenses: ["frameworks_av_media_ndk_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_media_ndk_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-Unicode-DFS",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_library {
name: "libmediandk",
symbol_file: "libmediandk.map.txt",
@@ -83,6 +114,7 @@
static_libs: [
"libgrallocusage",
+ "libnativehelper_lazy",
],
header_libs: [
@@ -111,7 +143,6 @@
"libgui",
"libui",
"libmediandk_utils",
- "libnativehelper",
],
export_header_lib_headers: ["jni_headers"],
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 1145b7b..5fdd45a 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -58,7 +58,7 @@
if (mIsClosed) {
return;
}
- if (!mReader->mIsClosed) {
+ if (mReader->mIsOpen) {
mReader->releaseImageLocked(this, releaseFenceFd);
}
// Should have been set to nullptr in releaseImageLocked
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index c0ceb3d..051466a 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -274,7 +274,7 @@
AImageReader::~AImageReader() {
Mutex::Autolock _l(mLock);
- LOG_FATAL_IF("AImageReader not closed before destruction", mIsClosed != true);
+ LOG_FATAL_IF(mIsOpen, "AImageReader not closed before destruction");
}
media_status_t
@@ -348,16 +348,16 @@
}
mHandler = new CallbackHandler(this);
mCbLooper->registerHandler(mHandler);
-
+ mIsOpen = true;
return AMEDIA_OK;
}
void AImageReader::close() {
Mutex::Autolock _l(mLock);
- if (mIsClosed) {
+ if (!mIsOpen) {
return;
}
- mIsClosed = true;
+ mIsOpen = false;
AImageReader_ImageListener nullListener = {nullptr, nullptr};
setImageListenerLocked(&nullListener);
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 0779a71..37c606e 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -166,7 +166,7 @@
native_handle_t* mWindowHandle = nullptr;
List<AImage*> mAcquiredImages;
- bool mIsClosed = false;
+ bool mIsOpen = false;
Mutex mLock;
};
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 0da0740..0c65e9e 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -22,6 +22,7 @@
#include <media/NdkMediaExtractor.h>
#include <media/NdkMediaErrorPriv.h>
#include <media/NdkMediaFormatPriv.h>
+#include "NdkJavaVMHelperPriv.h"
#include "NdkMediaDataSourcePriv.h"
@@ -63,7 +64,10 @@
AMediaExtractor* AMediaExtractor_new() {
ALOGV("ctor");
AMediaExtractor *mData = new AMediaExtractor();
- mData->mImpl = new NuMediaExtractor();
+ mData->mImpl = new NuMediaExtractor(
+ NdkJavaVMHelper::getJNIEnv() != nullptr
+ ? NuMediaExtractor::EntryPoint::NDK_WITH_JVM
+ : NuMediaExtractor::EntryPoint::NDK_NO_JVM );
return mData;
}
diff --git a/media/ndk/include/media/NdkImage.h b/media/ndk/include/media/NdkImage.h
index 62b8624..e19dd3a 100644
--- a/media/ndk/include/media/NdkImage.h
+++ b/media/ndk/include/media/NdkImage.h
@@ -559,8 +559,6 @@
int32_t bottom;
} AImageCropRect;
-#if __ANDROID_API__ >= 24
-
/**
* Return the image back the the system and delete the AImage object from memory.
*
@@ -777,10 +775,6 @@
const AImage* image, int planeIdx,
/*out*/uint8_t** data, /*out*/int* dataLength) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 26
-
/**
* Return the image back the the system and delete the AImage object from memory asynchronously.
*
@@ -829,8 +823,6 @@
*/
media_status_t AImage_getHardwareBuffer(const AImage* image, /*out*/AHardwareBuffer** buffer) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
-
__END_DECLS
#endif //_NDK_IMAGE_H
diff --git a/media/ndk/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index 600ffc9..d86f3c7 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -53,8 +53,6 @@
*/
typedef struct AImageReader AImageReader;
-#if __ANDROID_API__ >= 24
-
/**
* Create a new reader for images of the desired size and format.
*
@@ -320,10 +318,6 @@
media_status_t AImageReader_setImageListener(
AImageReader* reader, AImageReader_ImageListener* listener) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 26
-
/**
* AImageReader constructor similar to {@link AImageReader_new} that takes an additional parameter
* for the consumer usage. All other parameters and the return values are identical to those passed
@@ -510,8 +504,6 @@
AImageReader *reader, /* out */native_handle_t **handle);
#endif
-#endif /* __ANDROID_API__ >= 26 */
-
__END_DECLS
#endif //_NDK_IMAGE_READER_H
diff --git a/media/ndk/include/media/NdkMediaCodec.h b/media/ndk/include/media/NdkMediaCodec.h
index 80d5d50..60cdd32 100644
--- a/media/ndk/include/media/NdkMediaCodec.h
+++ b/media/ndk/include/media/NdkMediaCodec.h
@@ -121,8 +121,6 @@
AMediaCodecOnAsyncError onAsyncError;
} AMediaCodecOnAsyncNotifyCallback;
-#if __ANDROID_API__ >= 21
-
/**
* Create codec by name. Use this if you know the exact codec you want to use.
* When configuring, you will need to specify whether to use the codec as an
@@ -311,8 +309,6 @@
media_status_t AMediaCodec_releaseOutputBufferAtTime(
AMediaCodec *mData, size_t idx, int64_t timestampNs) __INTRODUCED_IN(21);
-#if __ANDROID_API__ >= 26
-
/**
* Creates a Surface that can be used as the input to encoder, in place of input buffers
*
@@ -393,10 +389,6 @@
*/
media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
-
-#if __ANDROID_API__ >= 28
-
/**
* Get format of the buffer. The specified buffer index must have been previously obtained from
* dequeueOutputBuffer.
@@ -482,8 +474,6 @@
*/
bool AMediaCodecActionCode_isTransient(int32_t actionCode) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
typedef enum {
AMEDIACODECRYPTOINFO_MODE_CLEAR = 0,
AMEDIACODECRYPTOINFO_MODE_AES_CTR = 1,
@@ -580,8 +570,6 @@
*/
media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo*, size_t *dst) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-
__END_DECLS
#endif //_NDK_MEDIA_CODEC_H
diff --git a/media/ndk/include/media/NdkMediaCrypto.h b/media/ndk/include/media/NdkMediaCrypto.h
index 3fa07c7..590d51d 100644
--- a/media/ndk/include/media/NdkMediaCrypto.h
+++ b/media/ndk/include/media/NdkMediaCrypto.h
@@ -47,8 +47,6 @@
typedef uint8_t AMediaUUID[16];
-#if __ANDROID_API__ >= 21
-
/**
* Available since API level 21.
*/
@@ -69,8 +67,6 @@
*/
void AMediaCrypto_delete(AMediaCrypto* crypto) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-
__END_DECLS
#endif // _NDK_MEDIA_CRYPTO_H
diff --git a/media/ndk/include/media/NdkMediaDataSource.h b/media/ndk/include/media/NdkMediaDataSource.h
index 0577df2..4158a97 100644
--- a/media/ndk/include/media/NdkMediaDataSource.h
+++ b/media/ndk/include/media/NdkMediaDataSource.h
@@ -38,8 +38,6 @@
struct AMediaDataSource;
typedef struct AMediaDataSource AMediaDataSource;
-#if __ANDROID_API__ >= 28
-
/*
* AMediaDataSource's callbacks will be invoked on an implementation-defined thread
* or thread pool. No guarantees are provided about which thread(s) will be used for
@@ -93,8 +91,6 @@
*/
AMediaDataSource* AMediaDataSource_new() __INTRODUCED_IN(28);
-#if __ANDROID_API__ >= 29
-
/**
* Called to get an estimate of the number of bytes that can be read from this data source
* starting at |offset| without blocking for I/O.
@@ -124,8 +120,6 @@
int numheaders,
const char * const *key_values) __INTRODUCED_IN(29);
-#endif /*__ANDROID_API__ >= 29 */
-
/**
* Delete a previously created media data source.
*
@@ -185,10 +179,6 @@
AMediaDataSource*,
AMediaDataSourceClose) __INTRODUCED_IN(28);
-#endif /*__ANDROID_API__ >= 28 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Close the data source, unblock reads, and release associated resources.
*
@@ -213,8 +203,6 @@
AMediaDataSource*,
AMediaDataSourceGetAvailableSize) __INTRODUCED_IN(29);
-#endif /*__ANDROID_API__ >= 29 */
-
__END_DECLS
#endif // _NDK_MEDIA_DATASOURCE_H
diff --git a/media/ndk/include/media/NdkMediaDrm.h b/media/ndk/include/media/NdkMediaDrm.h
index 31f5c7d..849a8f9 100644
--- a/media/ndk/include/media/NdkMediaDrm.h
+++ b/media/ndk/include/media/NdkMediaDrm.h
@@ -165,8 +165,6 @@
const AMediaDrmSessionId *sessionId, const AMediaDrmKeyStatus *keyStatus,
size_t numKeys, bool hasNewUsableKey);
-#if __ANDROID_API__ >= 21
-
/**
* Query if the given scheme identified by its UUID is supported on this device, and
* whether the drm plugin is able to handle the media container format specified by mimeType.
@@ -576,8 +574,6 @@
const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
const uint8_t *signature, size_t signatureSize) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-
__END_DECLS
#endif //_NDK_MEDIA_DRM_H
diff --git a/media/ndk/include/media/NdkMediaExtractor.h b/media/ndk/include/media/NdkMediaExtractor.h
index a1cd9e3..e429820 100644
--- a/media/ndk/include/media/NdkMediaExtractor.h
+++ b/media/ndk/include/media/NdkMediaExtractor.h
@@ -50,8 +50,6 @@
struct AMediaExtractor;
typedef struct AMediaExtractor AMediaExtractor;
-#if __ANDROID_API__ >= 21
-
/**
* Create new media extractor.
*
@@ -82,8 +80,6 @@
media_status_t AMediaExtractor_setDataSource(AMediaExtractor*,
const char *location) __INTRODUCED_IN(21);
-#if __ANDROID_API__ >= 28
-
/**
* Set the custom data source implementation from which the extractor will read.
*
@@ -92,8 +88,6 @@
media_status_t AMediaExtractor_setDataSourceCustom(AMediaExtractor*,
AMediaDataSource *src) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
/**
* Return the number of tracks in the previously specified media file
*
@@ -211,8 +205,6 @@
AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED = 2,
};
-#if __ANDROID_API__ >= 28
-
/**
* Returns the format of the extractor. The caller must free the returned format
* using AMediaFormat_delete(format).
@@ -266,10 +258,6 @@
media_status_t AMediaExtractor_getSampleFormat(AMediaExtractor *ex,
AMediaFormat *fmt) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
-#endif /* __ANDROID_API__ >= 21 */
-
__END_DECLS
#endif // _NDK_MEDIA_EXTRACTOR_H
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 6371de4..0ce08c1 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -40,18 +40,8 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-#ifndef __ANDROID__
-// Value copied from 'bionic/libc/include/android/api-level.h' which is not available on
-// non Android systems. It is set to 10000 which is same as __ANDROID_API_FUTURE__ value.
-#ifndef __ANDROID_API__
-#define __ANDROID_API__ 10000
-#endif
-
-// Value copied from 'bionic/libc/include/android/versioning.h' which is not available on
-// non Android systems
-#ifndef __INTRODUCED_IN
-#define __INTRODUCED_IN(api_level)
-#endif
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#include "NdkMediaError.h"
@@ -61,8 +51,6 @@
struct AMediaFormat;
typedef struct AMediaFormat AMediaFormat;
-#if __ANDROID_API__ >= 21
-
/**
* Available since API level 21.
*/
@@ -205,9 +193,7 @@
extern const char* AMEDIAFORMAT_KEY_TRACK_ID __INTRODUCED_IN(28);
extern const char* AMEDIAFORMAT_KEY_TRACK_INDEX __INTRODUCED_IN(28);
extern const char* AMEDIAFORMAT_KEY_WIDTH __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-#if __ANDROID_API__ >= 28
/**
* Available since API level 28.
*/
@@ -231,9 +217,7 @@
*/
void AMediaFormat_setRect(AMediaFormat*, const char* name,
int32_t left, int32_t top, int32_t right, int32_t bottom) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-#if __ANDROID_API__ >= 29
/**
* Remove all key/value pairs from the given AMediaFormat.
*
@@ -307,9 +291,6 @@
extern const char* AMEDIAFORMAT_KEY_VALID_SAMPLES __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
-#if __ANDROID_API__ >= 30
/**
* An optional key describing the low latency decoding mode. This is an optional parameter
* that applies only to decoders. If enabled, the decoder doesn't hold input and output
@@ -320,7 +301,6 @@
* Available since API level 30.
*/
extern const char* AMEDIAFORMAT_KEY_LOW_LATENCY __INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
__END_DECLS
diff --git a/media/ndk/include/media/NdkMediaMuxer.h b/media/ndk/include/media/NdkMediaMuxer.h
index 9de3fbf..519e249 100644
--- a/media/ndk/include/media/NdkMediaMuxer.h
+++ b/media/ndk/include/media/NdkMediaMuxer.h
@@ -54,8 +54,6 @@
AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP = 2,
} OutputFormat;
-#if __ANDROID_API__ >= 21
-
/**
* Create new media muxer.
*
@@ -140,8 +138,6 @@
size_t trackIdx, const uint8_t *data,
const AMediaCodecBufferInfo *info) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-
__END_DECLS
#endif // _NDK_MEDIA_MUXER_H
diff --git a/media/tests/SampleVideoEncoder/README.md b/media/tests/SampleVideoEncoder/README.md
new file mode 100644
index 0000000..2e275c5
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/README.md
@@ -0,0 +1,56 @@
+# B-Frames Encoding App
+
+This is a sample android application for encoding AVC/HEVC streams with B-Frames enabled. It uses MediaRecorder APIs to record B-frames enabled video from camera2 input and MediaCodec APIs to encode reference test vector using input surface.
+
+This page describes how to get started with the Encoder App and how to run the tests for it.
+
+
+# Getting Started
+
+This app uses the Gradle build system as well as Soong Build System.
+
+To build this project using Gradle build, use the "gradlew build" command or use "Import Project" in Android Studio.
+
+To build the app using Soong Build System, run the following command:
+```
+mmm frameworks/av/media/tests/SampleVideoEncoder/
+```
+
+The apk is generated at the following location:
+```
+out\target\product\sargo\testcases\SampleVideoEncoder\arm64\SampleVideoEncoder.apk
+```
+
+Command to install the apk:
+```
+adb install SampleVideoEncoder.apk
+```
+
+Command to launch the app:
+```
+adb shell am start -n "com.android.media.samplevideoencoder/com.android.media.samplevideoencoder.MainActivity"
+```
+
+After installing the app, a TextureView showing camera preview is dispalyed on one third of the screen. It also features checkboxes to select either avc/hevc and hw/sw codecs. It also has an option to select either MediaRecorder APIs or MediaCodec, along with the 'Start' button to start/stop recording.
+
+# Running Tests
+
+The app also contains a test, which will test the MediaCodec APIs for encoding avc/hevc streams with B-frames enabled. This does not require us to use application UI.
+
+## Running the tests using atest
+Note that atest command will install the SampleVideoEncoder app on the device.
+
+Command to run the tests:
+```
+atest SampleVideoEncoder
+```
+
+# Ouput
+
+The muxed ouptput video is saved in the app data at:
+```
+/storage/emulated/0/Android/data/com.android.media.samplevideoencoder/files/
+```
+
+The total number of I-frames, P-frames and B-frames after encoding has been done using MediaCodec APIs are displayed on the screen.
+The results of the tests can be obtained from the logcats of the test.
diff --git a/media/tests/SampleVideoEncoder/app/Android.bp b/media/tests/SampleVideoEncoder/app/Android.bp
new file mode 100644
index 0000000..58b219b
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+android_test {
+ name: "SampleVideoEncoder",
+
+ manifest: "src/main/AndroidManifest.xml",
+
+ srcs: ["src/**/*.java"],
+
+ sdk_version: "current",
+ min_sdk_version: "24", // N
+
+ resource_dirs: [
+ "src/main/res",
+ ],
+
+ static_libs: [
+ "androidx.annotation_annotation",
+ "androidx.appcompat_appcompat",
+ "androidx-constraintlayout_constraintlayout",
+ "junit",
+ "androidx.test.core",
+ "androidx.test.runner",
+ "hamcrest-library",
+ ],
+
+ javacflags: [
+ "-Xlint:deprecation",
+ "-Xlint:unchecked",
+ ],
+}
diff --git a/media/tests/SampleVideoEncoder/app/AndroidTest.xml b/media/tests/SampleVideoEncoder/app/AndroidTest.xml
new file mode 100644
index 0000000..91f4304
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs SampleVideoEncoder Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="cleanup-apks" value="false" />
+ <option name="test-file-name" value="SampleVideoEncoder.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="SampleVideoEncoder" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.media.samplevideoencoder" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/media/tests/SampleVideoEncoder/app/build.gradle b/media/tests/SampleVideoEncoder/app/build.gradle
new file mode 100644
index 0000000..cc54981
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/build.gradle
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.2"
+
+ defaultConfig {
+ applicationId "com.android.media.samplevideoencoder"
+ minSdkVersion 24
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.13.1'
+ androidTestImplementation 'androidx.test:runner:1.3.0'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/androidTest/java/com/android/media/samplevideoencoder/tests/SampleVideoEncoderTest.java b/media/tests/SampleVideoEncoder/app/src/androidTest/java/com/android/media/samplevideoencoder/tests/SampleVideoEncoderTest.java
new file mode 100644
index 0000000..1ef332e
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/androidTest/java/com/android/media/samplevideoencoder/tests/SampleVideoEncoderTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.media.samplevideoencoder.tests;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import android.content.Context;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import com.android.media.samplevideoencoder.MediaCodecSurfaceEncoder;
+import com.android.media.samplevideoencoder.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+
+@RunWith(Parameterized.class)
+public class SampleVideoEncoderTest {
+ private static final String TAG = SampleVideoEncoderTest.class.getSimpleName();
+ private final Context mContext;
+ private int mMaxBFrames;
+ private int mInputResId;
+ private String mMime;
+ private boolean mIsSoftwareEncoder;
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> inputFiles() {
+ return Arrays.asList(new Object[][]{
+ // Parameters: MimeType, isSoftwareEncoder, maxBFrames
+ {MediaFormat.MIMETYPE_VIDEO_AVC, false, 1},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, true, 1},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, false, 1},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, true, 1}});
+ }
+
+ public SampleVideoEncoderTest(String mimeType, boolean isSoftwareEncoder, int maxBFrames) {
+ this.mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ this.mInputResId = R.raw.crowd_1920x1080_25fps_4000kbps_h265;
+ this.mMime = mimeType;
+ this.mIsSoftwareEncoder = isSoftwareEncoder;
+ this.mMaxBFrames = maxBFrames;
+ }
+
+ private String getOutputPath() {
+ File dir = mContext.getExternalFilesDir(null);
+ if (dir == null) {
+ Log.e(TAG, "Cannot get external directory path to save output video");
+ return null;
+ }
+ String videoPath = dir.getAbsolutePath() + "/Video-" + System.currentTimeMillis() + ".mp4";
+ Log.i(TAG, "Output video is saved at: " + videoPath);
+ return videoPath;
+ }
+
+ @Test
+ public void testMediaSurfaceEncoder() throws IOException, InterruptedException {
+ String outputFilePath = getOutputPath();
+ MediaCodecSurfaceEncoder surfaceEncoder =
+ new MediaCodecSurfaceEncoder(mContext, mInputResId, mMime, mIsSoftwareEncoder,
+ outputFilePath, mMaxBFrames);
+ int encodingStatus = surfaceEncoder.startEncodingSurface();
+ assertThat(encodingStatus, is(equalTo(0)));
+ int[] frameNumArray = surfaceEncoder.getFrameTypes();
+ Log.i(TAG, "Results: I-Frames: " + frameNumArray[0] + "; P-Frames: " + frameNumArray[1] +
+ "\n " + "; B-Frames:" + frameNumArray[2]);
+ assertNotEquals("Encoder mime: " + mMime + " isSoftware: " + mIsSoftwareEncoder +
+ " failed to generate B Frames", frameNumArray[2], 0);
+ }
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/AndroidManifest.xml b/media/tests/SampleVideoEncoder/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b17541d
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.media.samplevideoencoder">
+
+ <uses-permission android:name="android.permission.CAMERA"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+
+ <application
+ android:configChanges="orientation"
+ android:screenOrientation="portrait"
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity android:name="com.android.media.samplevideoencoder.MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.media.samplevideoencoder"
+ android:label="SampleVideoEncoder Test"/>
+
+</manifest>
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/AutoFitTextureView.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/AutoFitTextureView.java
new file mode 100644
index 0000000..a3ea4c7
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/AutoFitTextureView.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.media.samplevideoencoder;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.TextureView;
+
+public class AutoFitTextureView extends TextureView {
+
+ public AutoFitTextureView(Context context) {
+ this(context, null);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setAspectRatio(int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Size cannot be negative.");
+ }
+ requestLayout();
+ }
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MainActivity.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MainActivity.java
new file mode 100644
index 0000000..a7a353c
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MainActivity.java
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.media.samplevideoencoder;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.graphics.SurfaceTexture;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.media.MediaRecorder;
+
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.view.Surface;
+import android.view.View;
+import android.view.TextureView;
+import android.widget.Button;
+import android.widget.CheckBox;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.util.Log;
+import android.util.Size;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+
+public class MainActivity extends AppCompatActivity
+ implements View.OnClickListener, ActivityCompat.OnRequestPermissionsResultCallback {
+
+ private static final String TAG = "SampleVideoEncoder";
+ private static final String[] RECORD_PERMISSIONS =
+ {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
+ private static final int REQUEST_RECORD_PERMISSIONS = 1;
+ private final Semaphore mCameraOpenCloseLock = new Semaphore(1);
+ private static final int VIDEO_BITRATE = 8000000 /* 8 Mbps */;
+ private static final int VIDEO_FRAMERATE = 30;
+
+ /**
+ * Constant values to frame types assigned here are internal to this app.
+ * These values does not correspond to the actual values defined in avc/hevc specifications.
+ */
+ public static final int FRAME_TYPE_I = 0;
+ public static final int FRAME_TYPE_P = 1;
+ public static final int FRAME_TYPE_B = 2;
+
+ private String mMime = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private String mOutputVideoPath = null;
+
+ private final boolean mIsFrontCamera = true;
+ private boolean mIsCodecSoftware = false;
+ private boolean mIsMediaRecorder = true;
+ private boolean mIsRecording;
+
+ private AutoFitTextureView mTextureView;
+ private TextView mTextView;
+ private CameraDevice mCameraDevice;
+ private CameraCaptureSession mPreviewSession;
+ private CaptureRequest.Builder mPreviewBuilder;
+ private MediaRecorder mMediaRecorder;
+ private Size mVideoSize;
+ private Size mPreviewSize;
+
+ private Handler mBackgroundHandler;
+ private HandlerThread mBackgroundThread;
+
+ private Button mStartButton;
+
+ private int[] mFrameTypeOccurrences;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ final RadioGroup radioGroup_mime = findViewById(R.id.radio_group_mime);
+ radioGroup_mime.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ if (checkedId == R.id.avc) {
+ mMime = MediaFormat.MIMETYPE_VIDEO_AVC;
+ } else {
+ mMime = MediaFormat.MIMETYPE_VIDEO_HEVC;
+ }
+ }
+ });
+
+ final RadioGroup radioGroup_codec = findViewById(R.id.radio_group_codec);
+ radioGroup_codec.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ mIsCodecSoftware = checkedId == R.id.sw;
+ }
+ });
+
+ final CheckBox checkBox_mr = findViewById(R.id.checkBox_media_recorder);
+ final CheckBox checkBox_mc = findViewById(R.id.checkBox_media_codec);
+ mTextureView = findViewById(R.id.texture);
+ mTextView = findViewById(R.id.textViewResults);
+
+ checkBox_mr.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ boolean checked = ((CheckBox) v).isChecked();
+ if (checked) {
+ checkBox_mc.setChecked(false);
+ mIsMediaRecorder = TRUE;
+ for (int i = 0; i < radioGroup_codec.getChildCount(); i++) {
+ radioGroup_codec.getChildAt(i).setEnabled(false);
+ }
+ }
+ }
+ });
+ checkBox_mc.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ boolean checked = ((CheckBox) v).isChecked();
+ if (checked) {
+ checkBox_mr.setChecked(false);
+ mIsMediaRecorder = FALSE;
+ for (int i = 0; i < radioGroup_codec.getChildCount(); i++) {
+ radioGroup_codec.getChildAt(i).setEnabled(true);
+ }
+ }
+ }
+ });
+ mStartButton = findViewById(R.id.start_button);
+ mStartButton.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.start_button) {
+ mTextView.setText(null);
+ if (mIsMediaRecorder) {
+ if (mIsRecording) {
+ stopRecordingVideo();
+ } else {
+ mStartButton.setEnabled(false);
+ startRecordingVideo();
+ }
+ } else {
+ mStartButton.setEnabled(false);
+ mOutputVideoPath = getVideoPath(MainActivity.this);
+ MediaCodecSurfaceAsync codecAsyncTask = new MediaCodecSurfaceAsync(this);
+ codecAsyncTask.execute(
+ "Encoding reference test vector with MediaCodec APIs using surface");
+ }
+ }
+ }
+
+ private static class MediaCodecSurfaceAsync extends AsyncTask<String, String, Integer> {
+
+ private final WeakReference<MainActivity> activityReference;
+
+ MediaCodecSurfaceAsync(MainActivity context) {
+ activityReference = new WeakReference<>(context);
+ }
+
+ @Override
+ protected Integer doInBackground(String... strings) {
+ MainActivity mainActivity = activityReference.get();
+ int resId = R.raw.crowd_1920x1080_25fps_4000kbps_h265;
+ int encodingStatus = 1;
+ MediaCodecSurfaceEncoder codecSurfaceEncoder =
+ new MediaCodecSurfaceEncoder(mainActivity.getApplicationContext(), resId,
+ mainActivity.mMime, mainActivity.mIsCodecSoftware,
+ mainActivity.mOutputVideoPath);
+ try {
+ encodingStatus = codecSurfaceEncoder.startEncodingSurface();
+ mainActivity.mFrameTypeOccurrences = codecSurfaceEncoder.getFrameTypes();
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ }
+ return encodingStatus;
+ }
+
+ @Override
+ protected void onPostExecute(Integer encodingStatus) {
+ MainActivity mainActivity = activityReference.get();
+ mainActivity.mStartButton.setEnabled(true);
+ if (encodingStatus == 0) {
+ Toast.makeText(mainActivity.getApplicationContext(), "Encoding Completed",
+ Toast.LENGTH_SHORT).show();
+ mainActivity.mTextView.append("\n Encoded stream contains: ");
+ mainActivity.mTextView.append("\n Number of I-Frames: " +
+ mainActivity.mFrameTypeOccurrences[FRAME_TYPE_I]);
+ mainActivity.mTextView.append("\n Number of P-Frames: " +
+ mainActivity.mFrameTypeOccurrences[FRAME_TYPE_P]);
+ mainActivity.mTextView.append("\n Number of B-Frames: " +
+ mainActivity.mFrameTypeOccurrences[FRAME_TYPE_B]);
+ } else {
+ Toast.makeText(mainActivity.getApplicationContext(),
+ "Error occurred while " + "encoding", Toast.LENGTH_SHORT).show();
+ }
+ mainActivity.mOutputVideoPath = null;
+ super.onPostExecute(encodingStatus);
+ }
+ }
+
+ private final TextureView.SurfaceTextureListener mSurfaceTextureListener =
+ new TextureView.SurfaceTextureListener() {
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
+ int height) {
+ openCamera(width, height);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
+ int height) {
+ configureTransform(width, height);
+ Log.v(TAG, "Keeping camera preview size fixed");
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ }
+ };
+
+
+ private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
+
+ @Override
+ public void onOpened(CameraDevice cameraDevice) {
+ mCameraDevice = cameraDevice;
+ startPreview();
+ mCameraOpenCloseLock.release();
+ }
+
+ @Override
+ public void onDisconnected(CameraDevice cameraDevice) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ }
+
+ @Override
+ public void onError(CameraDevice cameraDevice, int error) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ Activity activity = MainActivity.this;
+ activity.finish();
+ }
+ };
+
+ private boolean shouldShowRequestPermissionRationale(String[] recordPermissions) {
+ for (String permission : recordPermissions) {
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void requestRecordPermissions() {
+ if (!shouldShowRequestPermissionRationale(RECORD_PERMISSIONS)) {
+ ActivityCompat.requestPermissions(this, RECORD_PERMISSIONS, REQUEST_RECORD_PERMISSIONS);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (requestCode == REQUEST_RECORD_PERMISSIONS) {
+ if (grantResults.length == RECORD_PERMISSIONS.length) {
+ for (int result : grantResults) {
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ Log.e(TAG, "Permission is not granted");
+ break;
+ }
+ }
+ }
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+ }
+
+ @SuppressWarnings("MissingPermission")
+ private void openCamera(int width, int height) {
+ if (!hasPermissionGranted(RECORD_PERMISSIONS)) {
+ Log.e(TAG, "Camera does not have permission to record video");
+ requestRecordPermissions();
+ return;
+ }
+ final Activity activity = MainActivity.this;
+ if (activity == null || activity.isFinishing()) {
+ Log.e(TAG, "Activity not found");
+ return;
+ }
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ try {
+ Log.v(TAG, "Acquire Camera");
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Timed out waiting to lock camera opening");
+ }
+ Log.d(TAG, "Camera Acquired");
+
+ String cameraId = manager.getCameraIdList()[0];
+ if (mIsFrontCamera) {
+ cameraId = manager.getCameraIdList()[1];
+ }
+
+ CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
+ StreamConfigurationMap map =
+ characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
+ mPreviewSize =
+ chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height,
+ mVideoSize);
+ mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ configureTransform(width, height);
+ mMediaRecorder = new MediaRecorder();
+ manager.openCamera(cameraId, mStateCallback, null);
+ } catch (InterruptedException | CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void closeCamera() {
+ try {
+ mCameraOpenCloseLock.acquire();
+ closePreviewSession();
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ if (null != mMediaRecorder) {
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera closing.");
+ } finally {
+ mCameraOpenCloseLock.release();
+ }
+ }
+
+ private static Size chooseVideoSize(Size[] choices) {
+ for (Size size : choices) {
+ if (size.getWidth() == size.getHeight() * 16 / 9 && size.getWidth() <= 1920) {
+ return size;
+ }
+ }
+ Log.e(TAG, "Couldn't find any suitable video size");
+ return choices[choices.length - 1];
+ }
+
+ private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
+ List<Size> bigEnough = new ArrayList<>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getHeight() == option.getWidth() * h / w && option.getWidth() >= width &&
+ option.getHeight() >= height) {
+ bigEnough.add(option);
+ }
+ }
+
+ // Pick the smallest of those, assuming we found any
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else {
+ Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
+ private boolean hasPermissionGranted(String[] recordPermissions) {
+ for (String permission : recordPermissions) {
+ if (ActivityCompat.checkSelfPermission(MainActivity.this, permission) !=
+ PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ startBackgroundThread();
+ if (mTextureView.isAvailable()) {
+ openCamera(mTextureView.getWidth(), mTextureView.getHeight());
+ } else {
+ mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ closeCamera();
+ stopBackgroundThread();
+ super.onPause();
+ }
+
+ private void startBackgroundThread() {
+ mBackgroundThread = new HandlerThread("CameraBackground");
+ mBackgroundThread.start();
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
+ }
+
+ private void stopBackgroundThread() {
+ mBackgroundThread.quitSafely();
+ try {
+ mBackgroundThread.join();
+ mBackgroundThread = null;
+ mBackgroundHandler = null;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void startRecordingVideo() {
+ if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
+ Toast.makeText(MainActivity.this, "Cannot start recording.", Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Cannot start recording.");
+ return;
+ }
+ try {
+ closePreviewSession();
+ setUpMediaRecorder();
+ SurfaceTexture texture = mTextureView.getSurfaceTexture();
+ assert texture != null;
+ texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+ mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+ List<Surface> surfaces = new ArrayList<>();
+
+ // Set up Surface for the camera preview
+ Surface previewSurface = new Surface(texture);
+ surfaces.add(previewSurface);
+ mPreviewBuilder.addTarget(previewSurface);
+
+ // Set up Surface for the MediaRecorder
+ Surface recorderSurface = mMediaRecorder.getSurface();
+ surfaces.add(recorderSurface);
+ mPreviewBuilder.addTarget(recorderSurface);
+
+ //Start a capture session
+ mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(CameraCaptureSession session) {
+ mPreviewSession = session;
+ updatePreview();
+ MainActivity.this.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mIsRecording = true;
+ mMediaRecorder.start();
+ mStartButton.setText(R.string.stop);
+ mStartButton.setEnabled(true);
+ }
+ });
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession session) {
+ Log.e(TAG, "Failed to configure. Cannot start Recording");
+ }
+ }, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void setUpMediaRecorder() {
+ final Activity activity = MainActivity.this;
+ if (activity == null) {
+ Toast.makeText(MainActivity.this, "Error occurred while setting up the MediaRecorder",
+ Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Error occurred while setting up the MediaRecorder");
+ return;
+ }
+ try {
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ }
+ if (mOutputVideoPath == null) {
+ mOutputVideoPath = getVideoPath(MainActivity.this);
+ }
+ mMediaRecorder.setOutputFile(mOutputVideoPath);
+ mMediaRecorder.setVideoEncodingBitRate(VIDEO_BITRATE);
+ mMediaRecorder.setVideoFrameRate(VIDEO_FRAMERATE);
+ mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
+ mMediaRecorder.setOrientationHint(270);
+ if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+ mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.HEVC);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ mMediaRecorder.setVideoEncodingProfileLevel(
+ MediaCodecInfo.CodecProfileLevel.HEVCProfileMain,
+ MediaCodecInfo.CodecProfileLevel.HEVCMainTierLevel4);
+ }
+ } else {
+ mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ mMediaRecorder.setVideoEncodingProfileLevel(
+ MediaCodecInfo.CodecProfileLevel.AVCProfileMain,
+ MediaCodecInfo.CodecProfileLevel.AVCLevel4);
+ }
+ }
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+ try {
+ mMediaRecorder.prepare();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String getVideoPath(Activity activity) {
+ File dir = activity.getApplicationContext().getExternalFilesDir(null);
+ if (dir == null) {
+ Log.e(TAG, "Cannot get external directory path to save output video");
+ return null;
+ }
+ String videoPath = dir.getAbsolutePath() + "/Video-" + System.currentTimeMillis() + ".mp4";
+ Log.d(TAG, "Output video is saved at: " + videoPath);
+ return videoPath;
+ }
+
+ private void closePreviewSession() {
+ if (mPreviewSession != null) {
+ mPreviewSession.close();
+ mPreviewSession = null;
+ }
+ }
+
+ private void stopRecordingVideo() {
+ mIsRecording = false;
+ mStartButton.setText(R.string.start);
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ Toast.makeText(MainActivity.this, "Recording Finished", Toast.LENGTH_SHORT).show();
+ mOutputVideoPath = null;
+ startPreview();
+ }
+
+ private void startPreview() {
+ if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
+ return;
+ }
+ try {
+ closePreviewSession();
+ SurfaceTexture texture = mTextureView.getSurfaceTexture();
+ assert texture != null;
+ texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+ mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+ Surface previewSurface = new Surface(texture);
+ mPreviewBuilder.addTarget(previewSurface);
+
+ mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
+ new CameraCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(CameraCaptureSession session) {
+ mPreviewSession = session;
+ updatePreview();
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession session) {
+ Toast.makeText(MainActivity.this,
+ "Configure Failed; Cannot start " + "preview",
+ Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Configure failed; Cannot start preview");
+ }
+ }, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void updatePreview() {
+ if (mCameraDevice == null) {
+ Toast.makeText(MainActivity.this, "Camera not found; Cannot update " + "preview",
+ Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Camera not found; Cannot update preview");
+ return;
+ }
+ try {
+ mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
+ HandlerThread thread = new HandlerThread("Camera preview");
+ thread.start();
+ mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void configureTransform(int viewWidth, int viewHeight) {
+ Activity activity = MainActivity.this;
+ if (null == mTextureView || null == mPreviewSize || null == activity) {
+ return;
+ }
+ Matrix matrix = new Matrix();
+ RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ float centerX = viewRect.centerX();
+ float centerY = viewRect.centerY();
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
+ float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(),
+ (float) viewWidth / mPreviewSize.getWidth());
+ matrix.postScale(scale, scale, centerX, centerY);
+ mTextureView.setTransform(matrix);
+ }
+
+ static class CompareSizesByArea implements Comparator<Size> {
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
+ (long) rhs.getWidth() * rhs.getHeight());
+ }
+ }
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecBase.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecBase.java
new file mode 100644
index 0000000..88ce73b
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecBase.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.media.samplevideoencoder;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+class CodecAsyncHandler extends MediaCodec.Callback {
+ private static final String TAG = CodecAsyncHandler.class.getSimpleName();
+ private final Lock mLock = new ReentrantLock();
+ private final Condition mCondition = mLock.newCondition();
+ private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mCbInputQueue;
+ private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mCbOutputQueue;
+ private volatile boolean mSignalledError;
+
+ CodecAsyncHandler() {
+ mCbInputQueue = new LinkedList<>();
+ mCbOutputQueue = new LinkedList<>();
+ mSignalledError = false;
+ }
+
+ void clearQueues() {
+ mLock.lock();
+ mCbInputQueue.clear();
+ mCbOutputQueue.clear();
+ mLock.unlock();
+ }
+
+ void resetContext() {
+ clearQueues();
+ mSignalledError = false;
+ }
+
+ @Override
+ public void onInputBufferAvailable(MediaCodec codec, int bufferIndex) {
+ mLock.lock();
+ mCbInputQueue.add(new Pair<>(bufferIndex, (MediaCodec.BufferInfo) null));
+ mCondition.signalAll();
+ mLock.unlock();
+ }
+
+ @Override
+ public void onOutputBufferAvailable(MediaCodec codec, int bufferIndex,
+ MediaCodec.BufferInfo info) {
+ mLock.lock();
+ mCbOutputQueue.add(new Pair<>(bufferIndex, info));
+ mCondition.signalAll();
+ mLock.unlock();
+ }
+
+ @Override
+ public void onError(MediaCodec codec, MediaCodec.CodecException e) {
+ mLock.lock();
+ mSignalledError = true;
+ mCondition.signalAll();
+ mLock.unlock();
+ Log.e(TAG, "Received media codec error : " + e.getMessage());
+ }
+
+ @Override
+ public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
+ Log.i(TAG, "Output format changed: " + format.toString());
+ }
+
+ void setCallBack(MediaCodec codec, boolean isCodecInAsyncMode) {
+ if (isCodecInAsyncMode) {
+ codec.setCallback(this);
+ }
+ }
+
+ Pair<Integer, MediaCodec.BufferInfo> getOutput() throws InterruptedException {
+ Pair<Integer, MediaCodec.BufferInfo> element = null;
+ mLock.lock();
+ while (!mSignalledError) {
+ if (mCbOutputQueue.isEmpty()) {
+ mCondition.await();
+ } else {
+ element = mCbOutputQueue.remove(0);
+ break;
+ }
+ }
+ mLock.unlock();
+ return element;
+ }
+
+ Pair<Integer, MediaCodec.BufferInfo> getWork() throws InterruptedException {
+ Pair<Integer, MediaCodec.BufferInfo> element = null;
+ mLock.lock();
+ while (!mSignalledError) {
+ if (mCbInputQueue.isEmpty() && mCbOutputQueue.isEmpty()) {
+ mCondition.await();
+ } else {
+ if (!mCbOutputQueue.isEmpty()) {
+ element = mCbOutputQueue.remove(0);
+ break;
+ }
+ if (!mCbInputQueue.isEmpty()) {
+ element = mCbInputQueue.remove(0);
+ break;
+ }
+ }
+ }
+ mLock.unlock();
+ return element;
+ }
+
+ boolean hasSeenError() {
+ return mSignalledError;
+ }
+}
+
+abstract public class MediaCodecBase {
+ static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
+ String[] features, boolean isEncoder,
+ boolean isSoftware) {
+
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+ ArrayList<String> listOfCodecs = new ArrayList<>();
+ for (MediaCodecInfo codecInfo : codecInfos) {
+ if (isEncoder) {
+ if (!codecInfo.isEncoder()) continue;
+ } else {
+ if (codecInfo.isEncoder()) continue;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) continue;
+ String[] types = codecInfo.getSupportedTypes();
+ for (String type : types) {
+ if (type.equalsIgnoreCase(mime)) {
+ boolean isOk = true;
+ MediaCodecInfo.CodecCapabilities codecCapabilities =
+ codecInfo.getCapabilitiesForType(type);
+ if (formats != null) {
+ for (MediaFormat format : formats) {
+ if (!codecCapabilities.isFormatSupported(format)) {
+ isOk = false;
+ break;
+ }
+ }
+ }
+ if (features != null) {
+ for (String feature : features) {
+ if (!codecCapabilities.isFeatureSupported(feature)) {
+ isOk = false;
+ break;
+ }
+ }
+ }
+ if (isSoftware) {
+ if (codecInfo.getName().contains("software") ||
+ codecInfo.getName().contains("android") ||
+ codecInfo.getName().contains("google")) {
+ if (isOk) listOfCodecs.add(codecInfo.getName());
+ }
+ } else {
+ if (codecInfo.getName().contains("software") ||
+ codecInfo.getName().contains("android") ||
+ codecInfo.getName().contains("google")) {
+ continue;
+ } else {
+ if (isOk) listOfCodecs.add(codecInfo.getName());
+ }
+ }
+ }
+ }
+ }
+ return listOfCodecs;
+ }
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
new file mode 100644
index 0000000..011c38c
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media.samplevideoencoder;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Surface;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static com.android.media.samplevideoencoder.MainActivity.FRAME_TYPE_B;
+import static com.android.media.samplevideoencoder.MainActivity.FRAME_TYPE_I;
+import static com.android.media.samplevideoencoder.MainActivity.FRAME_TYPE_P;
+
+public class MediaCodecSurfaceEncoder {
+ private static final String TAG = MediaCodecSurfaceEncoder.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final int VIDEO_BITRATE = 8000000 /*8 Mbps*/;
+ private static final int VIDEO_FRAMERATE = 30;
+ private final Context mActivityContext;
+ private final int mResID;
+ private final int mMaxBFrames;
+ private final String mMime;
+ private final String mOutputPath;
+ private int mTrackID = -1;
+ private int mFrameNum = 0;
+ private int[] mFrameTypeOccurrences = {0, 0, 0};
+
+ private Surface mSurface;
+ private MediaExtractor mExtractor;
+ private MediaCodec mDecoder;
+ private MediaCodec mEncoder;
+ private MediaMuxer mMuxer;
+
+ private final boolean mIsCodecSoftware;
+ private boolean mSawDecInputEOS;
+ private boolean mSawDecOutputEOS;
+ private boolean mSawEncOutputEOS;
+ private int mDecOutputCount;
+ private int mEncOutputCount;
+
+ private final CodecAsyncHandler mAsyncHandleEncoder = new CodecAsyncHandler();
+ private final CodecAsyncHandler mAsyncHandleDecoder = new CodecAsyncHandler();
+
+ public MediaCodecSurfaceEncoder(Context context, int resId, String mime, boolean isSoftware,
+ String outputPath, int maxBFrames) {
+ mActivityContext = context;
+ mResID = resId;
+ mMime = mime;
+ mIsCodecSoftware = isSoftware;
+ mOutputPath = outputPath;
+ mMaxBFrames = maxBFrames;
+ }
+
+ public MediaCodecSurfaceEncoder(Context context, int resId, String mime, boolean isSoftware,
+ String outputPath) {
+ // Default value of MediaFormat.KEY_MAX_B_FRAMES is set to 1, if not passed as a parameter.
+ this(context, resId, mime, isSoftware, outputPath, 1);
+ }
+
+ public int startEncodingSurface() throws IOException, InterruptedException {
+ MediaFormat decoderFormat = setUpSource();
+ if (decoderFormat == null) {
+ return -1;
+ }
+
+ String decoderMime = decoderFormat.getString(MediaFormat.KEY_MIME);
+ ArrayList<String> listOfDeocders =
+ MediaCodecBase.selectCodecs(decoderMime, null, null, false, mIsCodecSoftware);
+ if (listOfDeocders.isEmpty()) {
+ Log.e(TAG, "No suitable decoder found for mime: " + decoderMime);
+ return -1;
+ }
+ mDecoder = MediaCodec.createByCodecName(listOfDeocders.get(0));
+
+ MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat);
+ ArrayList<String> listOfEncoders =
+ MediaCodecBase.selectCodecs(mMime, null, null, true, mIsCodecSoftware);
+ if (listOfEncoders.isEmpty()) {
+ Log.e(TAG, "No suitable encoder found for mime: " + mMime);
+ return -1;
+ }
+
+ boolean muxOutput = true;
+ for (String encoder : listOfEncoders) {
+ mEncoder = MediaCodec.createByCodecName(encoder);
+ mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ if (muxOutput) {
+ int muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
+ mMuxer = new MediaMuxer(mOutputPath, muxerFormat);
+ }
+ configureCodec(decoderFormat, encoderFormat);
+ mEncoder.start();
+ mDecoder.start();
+ doWork(Integer.MAX_VALUE);
+ queueEOS();
+ waitForAllEncoderOutputs();
+ if (muxOutput) {
+ if (mTrackID != -1) {
+ mMuxer.stop();
+ mTrackID = -1;
+ }
+ if (mMuxer != null) {
+ mMuxer.release();
+ mMuxer = null;
+ }
+ }
+ mDecoder.reset();
+ mEncoder.reset();
+ mSurface.release();
+ mSurface = null;
+ Log.i(TAG, "Number of I-frames = " + mFrameTypeOccurrences[FRAME_TYPE_I]);
+ Log.i(TAG, "Number of P-frames = " + mFrameTypeOccurrences[FRAME_TYPE_P]);
+ Log.i(TAG, "Number of B-frames = " + mFrameTypeOccurrences[FRAME_TYPE_B]);
+ }
+ mEncoder.release();
+ mDecoder.release();
+ mExtractor.release();
+ return 0;
+ }
+
+ private MediaFormat setUpSource() throws IOException {
+ mExtractor = new MediaExtractor();
+ AssetFileDescriptor fd = mActivityContext.getResources().openRawResourceFd(mResID);
+ mExtractor.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+ for (int trackID = 0; trackID < mExtractor.getTrackCount(); trackID++) {
+ MediaFormat format = mExtractor.getTrackFormat(trackID);
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ if (mime.startsWith("video/")) {
+ mExtractor.selectTrack(trackID);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+ MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
+ return format;
+ }
+ }
+ mExtractor.release();
+ return null;
+ }
+
+ private MediaFormat setUpEncoderFormat(MediaFormat decoderFormat) {
+ MediaFormat encoderFormat = new MediaFormat();
+ encoderFormat.setString(MediaFormat.KEY_MIME, mMime);
+ encoderFormat
+ .setInteger(MediaFormat.KEY_WIDTH, decoderFormat.getInteger(MediaFormat.KEY_WIDTH));
+ encoderFormat.setInteger(MediaFormat.KEY_HEIGHT,
+ decoderFormat.getInteger(MediaFormat.KEY_HEIGHT));
+ encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, VIDEO_FRAMERATE);
+ encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, VIDEO_BITRATE);
+ encoderFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
+ encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+ MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+ if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+ encoderFormat.setInteger(MediaFormat.KEY_PROFILE,
+ MediaCodecInfo.CodecProfileLevel.HEVCProfileMain);
+ encoderFormat.setInteger(MediaFormat.KEY_LEVEL,
+ MediaCodecInfo.CodecProfileLevel.HEVCMainTierLevel4);
+ } else {
+ encoderFormat.setInteger(MediaFormat.KEY_PROFILE,
+ MediaCodecInfo.CodecProfileLevel.AVCProfileMain);
+ encoderFormat
+ .setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel4);
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ encoderFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ encoderFormat.setInteger(MediaFormat.KEY_LATENCY, 1);
+ }
+ return encoderFormat;
+ }
+
+ private void resetContext() {
+ mAsyncHandleDecoder.resetContext();
+ mAsyncHandleEncoder.resetContext();
+ mSawDecInputEOS = false;
+ mSawDecOutputEOS = false;
+ mSawEncOutputEOS = false;
+ mDecOutputCount = 0;
+ mEncOutputCount = 0;
+ mFrameNum = 0;
+ Arrays.fill(mFrameTypeOccurrences, 0);
+ }
+
+ private void configureCodec(MediaFormat decFormat, MediaFormat encFormat) {
+ resetContext();
+ mAsyncHandleEncoder.setCallBack(mEncoder, true);
+ mEncoder.configure(encFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+ mSurface = mEncoder.createInputSurface();
+ if (!mSurface.isValid()) {
+ Log.e(TAG, "Surface is not valid");
+ return;
+ }
+ mAsyncHandleDecoder.setCallBack(mDecoder, true);
+ mDecoder.configure(decFormat, mSurface, null, 0);
+ Log.d(TAG, "Codec configured");
+ if (DEBUG) {
+ Log.d(TAG, "Encoder Output format: " + mEncoder.getOutputFormat());
+ }
+ }
+
+ private void dequeueDecoderOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ mSawDecOutputEOS = true;
+ }
+ if (DEBUG) {
+ Log.d(TAG,
+ "output: id: " + bufferIndex + " flags: " + info.flags + " size: " + info.size +
+ " timestamp: " + info.presentationTimeUs);
+ }
+ if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+ mDecOutputCount++;
+ }
+ mDecoder.releaseOutputBuffer(bufferIndex, mSurface != null);
+ }
+
+ private void enqueueDecoderInput(int bufferIndex) {
+ ByteBuffer inputBuffer = mDecoder.getInputBuffer(bufferIndex);
+ int size = mExtractor.readSampleData(inputBuffer, 0);
+ if (size < 0) {
+ enqueueDecoderEOS(bufferIndex);
+ } else {
+ long pts = mExtractor.getSampleTime();
+ int extractorFlags = mExtractor.getSampleFlags();
+ int codecFlags = 0;
+ if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
+ codecFlags |= MediaCodec.BUFFER_FLAG_KEY_FRAME;
+ }
+ if ((extractorFlags & MediaExtractor.SAMPLE_FLAG_PARTIAL_FRAME) != 0) {
+ codecFlags |= MediaCodec.BUFFER_FLAG_PARTIAL_FRAME;
+ }
+ if (!mExtractor.advance()) {
+ codecFlags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ mSawDecInputEOS = true;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "input: id: " + bufferIndex + " size: " + size + " pts: " + pts +
+ " flags: " + codecFlags);
+ }
+ mDecoder.queueInputBuffer(bufferIndex, 0, size, pts, codecFlags);
+ }
+ }
+
+ private void doWork(int frameLimit) throws InterruptedException {
+ int frameCount = 0;
+ while (!hasSeenError() && !mSawDecInputEOS && frameCount < frameLimit) {
+ Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleDecoder.getWork();
+ if (element != null) {
+ int bufferID = element.first;
+ MediaCodec.BufferInfo info = element.second;
+ if (info != null) {
+ // <id, info> corresponds to output callback.
+ dequeueDecoderOutput(bufferID, info);
+ } else {
+ // <id, null> corresponds to input callback.
+ enqueueDecoderInput(bufferID);
+ frameCount++;
+ }
+ }
+ // check decoder EOS
+ if (mSawDecOutputEOS) mEncoder.signalEndOfInputStream();
+ // encoder output
+ if (mDecOutputCount - mEncOutputCount > mMaxBFrames) {
+ tryEncoderOutput();
+ }
+ }
+ }
+
+ private void queueEOS() throws InterruptedException {
+ while (!mAsyncHandleDecoder.hasSeenError() && !mSawDecInputEOS) {
+ Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleDecoder.getWork();
+ if (element != null) {
+ int bufferID = element.first;
+ MediaCodec.BufferInfo info = element.second;
+ if (info != null) {
+ dequeueDecoderOutput(bufferID, info);
+ } else {
+ enqueueDecoderEOS(element.first);
+ }
+ }
+ }
+
+ while (!hasSeenError() && !mSawDecOutputEOS) {
+ Pair<Integer, MediaCodec.BufferInfo> decOp = mAsyncHandleDecoder.getOutput();
+ if (decOp != null) dequeueDecoderOutput(decOp.first, decOp.second);
+ if (mSawDecOutputEOS) mEncoder.signalEndOfInputStream();
+ if (mDecOutputCount - mEncOutputCount > mMaxBFrames) {
+ tryEncoderOutput();
+ }
+ }
+ }
+
+ private void tryEncoderOutput() throws InterruptedException {
+ if (!hasSeenError() && !mSawEncOutputEOS) {
+ Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandleEncoder.getOutput();
+ if (element != null) {
+ dequeueEncoderOutput(element.first, element.second);
+ }
+ }
+ }
+
+ private void waitForAllEncoderOutputs() throws InterruptedException {
+ while (!hasSeenError() && !mSawEncOutputEOS) {
+ tryEncoderOutput();
+ }
+ }
+
+ private void enqueueDecoderEOS(int bufferIndex) {
+ if (!mSawDecInputEOS) {
+ mDecoder.queueInputBuffer(bufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ mSawDecInputEOS = true;
+ Log.d(TAG, "Queued End of Stream");
+ }
+ }
+
+ private void dequeueEncoderOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ if (DEBUG) {
+ Log.d(TAG, "encoder output: id: " + bufferIndex + " flags: " + info.flags + " size: " +
+ info.size + " timestamp: " + info.presentationTimeUs);
+ }
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ mSawEncOutputEOS = true;
+ }
+ if (info.size > 0) {
+ ByteBuffer buf = mEncoder.getOutputBuffer(bufferIndex);
+ // Parse the buffer to get the frame type
+ if (DEBUG) Log.d(TAG, "[ Frame : " + (mFrameNum++) + " ]");
+ int frameTypeResult = -1;
+ if (mMime == MediaFormat.MIMETYPE_VIDEO_AVC) {
+ frameTypeResult = NalUnitUtil.getStandardizedFrameTypesFromAVC(buf);
+ } else if (mMime == MediaFormat.MIMETYPE_VIDEO_HEVC){
+ frameTypeResult = NalUnitUtil.getStandardizedFrameTypesFromHEVC(buf);
+ } else {
+ Log.e(TAG, "Mime type " + mMime + " is not supported.");
+ return;
+ }
+ if (frameTypeResult != -1) {
+ mFrameTypeOccurrences[frameTypeResult]++;
+ }
+
+ if (mMuxer != null) {
+ if (mTrackID == -1) {
+ mTrackID = mMuxer.addTrack(mEncoder.getOutputFormat());
+ mMuxer.start();
+ }
+ mMuxer.writeSampleData(mTrackID, buf, info);
+ }
+ if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+ mEncOutputCount++;
+ }
+ }
+ mEncoder.releaseOutputBuffer(bufferIndex, false);
+ }
+
+ private boolean hasSeenError() {
+ return mAsyncHandleDecoder.hasSeenError() || mAsyncHandleEncoder.hasSeenError();
+ }
+
+ public int[] getFrameTypes() {
+ return mFrameTypeOccurrences;
+ }
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/NalUnitUtil.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/NalUnitUtil.java
new file mode 100644
index 0000000..efff4fd
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/NalUnitUtil.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media.samplevideoencoder;
+
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+
+import static com.android.media.samplevideoencoder.MainActivity.FRAME_TYPE_B;
+import static com.android.media.samplevideoencoder.MainActivity.FRAME_TYPE_I;
+import static com.android.media.samplevideoencoder.MainActivity.FRAME_TYPE_P;
+
+public class NalUnitUtil {
+ private static final String TAG = MediaCodecSurfaceEncoder.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ public static int findNalUnit(byte[] dataArray, int pos, int limit) {
+ int startOffset = 0;
+ if (limit - pos < 4) {
+ return startOffset;
+ }
+ if (dataArray[pos] == 0 && dataArray[pos + 1] == 0 && dataArray[pos + 2] == 1) {
+ startOffset = 3;
+ } else {
+ if (dataArray[pos] == 0 && dataArray[pos + 1] == 0 && dataArray[pos + 2] == 0 &&
+ dataArray[pos + 3] == 1) {
+ startOffset = 4;
+ }
+ }
+ return startOffset;
+ }
+
+ private static int getAVCNalUnitType(byte[] dataArray, int nalUnitOffset) {
+ return dataArray[nalUnitOffset] & 0x1F;
+ }
+
+ private static int parseAVCNALUnitData(byte[] dataArray, int offset, int limit) {
+ ParsableBitArray bitArray = new ParsableBitArray(dataArray);
+ bitArray.reset(dataArray, offset, limit);
+
+ bitArray.skipBit(); // forbidden_zero_bit
+ bitArray.readBits(2); // nal_ref_idc
+ bitArray.skipBits(5); // nal_unit_type
+
+ bitArray.readUEV(); // first_mb_in_slice
+ if (!bitArray.canReadUEV()) {
+ return -1;
+ }
+ int sliceType = bitArray.readUEV();
+ if (DEBUG) Log.d(TAG, "slice_type = " + sliceType);
+ if (sliceType == 0) {
+ return FRAME_TYPE_P;
+ } else if (sliceType == 1) {
+ return FRAME_TYPE_B;
+ } else if (sliceType == 2) {
+ return FRAME_TYPE_I;
+ } else {
+ return -1;
+ }
+ }
+
+ private static int getHEVCNalUnitType(byte[] dataArray, int nalUnitOffset) {
+ return (dataArray[nalUnitOffset] & 0x7E) >> 1;
+ }
+
+ private static int parseHEVCNALUnitData(byte[] dataArray, int offset, int limit,
+ int nalUnitType) {
+ // nal_unit_type values from H.265/HEVC Table 7-1.
+ final int BLA_W_LP = 16;
+ final int RSV_IRAP_VCL23 = 23;
+
+ ParsableBitArray bitArray = new ParsableBitArray(dataArray);
+ bitArray.reset(dataArray, offset, limit);
+
+ bitArray.skipBit(); // forbidden zero bit
+ bitArray.readBits(6); // nal_unit_header
+ bitArray.readBits(6); // nuh_layer_id
+ bitArray.readBits(3); // nuh_temporal_id_plus1
+
+ // Parsing slice_segment_header values from H.265/HEVC Table 7.3.6.1
+ boolean first_slice_segment = bitArray.readBit(); // first_slice_segment_in_pic_flag
+ if (!first_slice_segment) return -1;
+ if (nalUnitType >= BLA_W_LP && nalUnitType <= RSV_IRAP_VCL23) {
+ bitArray.readBit(); // no_output_of_prior_pics_flag
+ }
+ bitArray.readUEV(); // slice_pic_parameter_set_id
+ // Assume num_extra_slice_header_bits element of PPS data to be 0
+ int sliceType = bitArray.readUEV();
+ if (DEBUG) Log.d(TAG, "slice_type = " + sliceType);
+ if (sliceType == 0) {
+ return FRAME_TYPE_B;
+ } else if (sliceType == 1) {
+ return FRAME_TYPE_P;
+ } else if (sliceType == 2) {
+ return FRAME_TYPE_I;
+ } else {
+ return -1;
+ }
+ }
+
+ public static int getStandardizedFrameTypesFromAVC(ByteBuffer buf) {
+ int limit = buf.limit();
+ byte[] dataArray = new byte[buf.remaining()];
+ buf.get(dataArray);
+ int frameType = -1;
+ for (int pos = 0; pos + 3 < limit; ) {
+ int startOffset = NalUnitUtil.findNalUnit(dataArray, pos, limit);
+ if (startOffset != 0) {
+ int nalUnitType = getAVCNalUnitType(dataArray, (pos + startOffset));
+ if (DEBUG) {
+ Log.d(TAG, "NalUnitOffset = " + (pos + startOffset));
+ Log.d(TAG, "NalUnitType = " + nalUnitType);
+ }
+ // SLICE_NAL = 1; IDR_SLICE_NAL = 5
+ if (nalUnitType == 1 || nalUnitType == 5) {
+ frameType = parseAVCNALUnitData(dataArray, (pos + startOffset),
+ (limit - pos - startOffset));
+ break;
+ }
+ pos += 3;
+ } else {
+ pos++;
+ }
+ }
+ return frameType;
+ }
+
+ public static int getStandardizedFrameTypesFromHEVC(ByteBuffer buf) {
+ int limit = buf.limit();
+ byte[] dataArray = new byte[buf.remaining()];
+ buf.get(dataArray);
+ int frameType = -1;
+ for (int pos = 0; pos + 3 < limit; ) {
+ int startOffset = NalUnitUtil.findNalUnit(dataArray, pos, limit);
+ if (startOffset != 0) {
+ int nalUnitType = NalUnitUtil.getHEVCNalUnitType(dataArray, (pos + startOffset));
+ if (DEBUG) {
+ Log.d(TAG, "NalUnitOffset = " + (pos + startOffset));
+ Log.d(TAG, "NalUnitType = " + nalUnitType);
+ }
+ // Parse NALUnits containing slice_headers which lies in the range of 0 to 21
+ if (nalUnitType >= 0 && nalUnitType <= 21) {
+ frameType = parseHEVCNALUnitData(dataArray, (pos + startOffset),
+ (limit - pos - startOffset), nalUnitType);
+ break;
+ }
+ pos += 3;
+ } else {
+ pos++;
+ }
+ }
+ return frameType;
+ }
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/ParsableBitArray.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/ParsableBitArray.java
new file mode 100644
index 0000000..e4bfaa3
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/ParsableBitArray.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media.samplevideoencoder;
+
+public class ParsableBitArray {
+ public byte[] data;
+ private int byteOffset;
+ private int bitOffset;
+ private int byteLimit;
+
+ public ParsableBitArray(byte[] dataArray) {
+ this(dataArray, dataArray.length);
+ }
+
+ public ParsableBitArray(byte[] dataArray, int limit) {
+ this.data = dataArray;
+ byteLimit = limit;
+ }
+
+ public void reset(byte[] data, int offset, int limit) {
+ this.data = data;
+ byteOffset = offset;
+ bitOffset = 0;
+ byteLimit = limit;
+ }
+
+ public void skipBit() {
+ if (++bitOffset == 8) {
+ bitOffset = 0;
+ byteOffset++;
+ }
+ }
+
+ public void skipBits(int numBits) {
+ int numBytes = numBits / 8;
+ byteOffset += numBytes;
+ bitOffset += numBits - (numBytes * 8);
+ if (bitOffset > 7) {
+ byteOffset++;
+ bitOffset -= 8;
+ }
+ }
+
+ public boolean readBit() {
+ boolean returnValue = (data[byteOffset] & (0x80 >> bitOffset)) != 0;
+ skipBit();
+ return returnValue;
+ }
+
+ public int readBits(int numBits) {
+ if (numBits == 0) {
+ return 0;
+ }
+ int returnValue = 0;
+ bitOffset += numBits;
+ while (bitOffset > 8) {
+ bitOffset -= 8;
+ returnValue |= (data[byteOffset++] & 0xFF) << bitOffset;
+ }
+ returnValue |= (data[byteOffset] & 0xFF) >> (8 - bitOffset);
+ returnValue &= 0xFFFFFFFF >>> (32 - numBits);
+ if (bitOffset == 8) {
+ bitOffset = 0;
+ byteOffset++;
+ }
+ return returnValue;
+ }
+
+ public boolean canReadUEV() {
+ int initialByteOffset = byteOffset;
+ int initialBitOffset = bitOffset;
+ int leadingZeros = 0;
+ while (byteOffset < byteLimit && !readBit()) {
+ leadingZeros++;
+ }
+ boolean hitLimit = byteOffset == byteLimit;
+ byteOffset = initialByteOffset;
+ bitOffset = initialBitOffset;
+ return !hitLimit && canReadBits(leadingZeros * 2 + 1);
+ }
+
+ public int readUEV() {
+ int leadingZeros = 0;
+ while (!readBit()) {
+ leadingZeros++;
+ }
+ return (1 << leadingZeros) - 1 + (leadingZeros > 0 ? readBits(leadingZeros) : 0);
+ }
+
+ public boolean canReadBits(int numBits) {
+ int oldByteOffset = byteOffset;
+ int numBytes = numBits / 8;
+ int newByteOffset = byteOffset + numBytes;
+ int newBitOffset = bitOffset + numBits - (numBytes * 8);
+ if (newBitOffset > 7) {
+ newByteOffset++;
+ newBitOffset -= 8;
+ }
+ for (int i = oldByteOffset + 1; i <= newByteOffset && newByteOffset < byteLimit; i++) {
+ if (shouldSkipByte(i)) {
+ // Skip the byte and check three bytes ahead.
+ newByteOffset++;
+ i += 2;
+ }
+ }
+ return newByteOffset < byteLimit || (newByteOffset == byteLimit && newBitOffset == 0);
+ }
+
+ private boolean shouldSkipByte(int offset) {
+ return (2 <= offset && offset < byteLimit && data[offset] == (byte) 0x03 &&
+ data[offset - 2] == (byte) 0x00 && data[offset - 1] == (byte) 0x00);
+ }
+
+}
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/media/tests/SampleVideoEncoder/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:endX="85.84757"
+ android:endY="92.4963"
+ android:startX="42.9492"
+ android:startY="49.59793"
+ android:type="linear">
+ <item
+ android:color="#44000000"
+ android:offset="0.0" />
+ <item
+ android:color="#00000000"
+ android:offset="1.0" />
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000" />
+</vector>
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/drawable/ic_launcher_background.xml b/media/tests/SampleVideoEncoder/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillColor="#3DDC84"
+ android:pathData="M0,0h108v108h-108z" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M9,0L9,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,0L19,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,0L29,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,0L39,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,0L49,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,0L59,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,0L69,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,0L79,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M89,0L89,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M99,0L99,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,9L108,9"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,19L108,19"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,29L108,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,39L108,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,49L108,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,59L108,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,69L108,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,79L108,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,89L108,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,99L108,99"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,29L89,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,39L89,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,49L89,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,59L89,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,69L89,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,79L89,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,19L29,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,19L39,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,19L49,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,19L59,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,19L69,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,19L79,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/layout/activity_main.xml b/media/tests/SampleVideoEncoder/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..017012d
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ tools:context="com.android.media.samplevideoencoder.MainActivity">
+
+ <com.android.media.samplevideoencoder.AutoFitTextureView
+ android:id="@+id/texture"
+ android:layout_width="wrap_content"
+ android:layout_height="300dp"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginBottom="16dp"
+ android:gravity="center"
+ app:layout_constraintBottom_toTopOf="@+id/checkBox_media_recorder"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <CheckBox
+ android:id="@+id/checkBox_media_recorder"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="90dp"
+ android:layout_marginTop="10dp"
+ android:fontFamily="sans-serif-medium"
+ android:text="@string/media_recorder"
+ android:textAppearance="@style/TextAppearance.AppCompat.Large"
+ android:textStyle="normal"
+ android:checked="true"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/texture"/>
+
+ <CheckBox
+ android:id="@+id/checkBox_media_codec"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="90dp"
+ android:fontFamily="sans-serif-medium"
+ android:text="@string/media_codec"
+ android:textAppearance="@style/TextAppearance.AppCompat.Large"
+ android:textStyle="normal"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/checkBox_media_recorder" />
+
+ <RadioGroup
+ android:id="@+id/radio_group_mime"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="40dp"
+ android:layout_marginTop="10dp"
+ android:orientation="vertical"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/frameLayout2"
+ app:layout_constraintTop_toBottomOf="@+id/checkBox_media_codec">
+
+ <RadioButton
+ android:id="@+id/avc"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:checked="true"
+ android:text="@string/avc" />
+
+ <RadioButton
+ android:id="@+id/hevc"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hevc" />
+ </RadioGroup>
+
+ <RadioGroup
+ android:id="@+id/radio_group_codec"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginEnd="40dp"
+ android:orientation="vertical"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/checkBox_media_codec">
+
+ <RadioButton
+ android:id="@+id/hw"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:checked="true"
+ android:enabled="false"
+ android:text="@string/hardware" />
+
+ <RadioButton
+ android:id="@+id/sw"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:enabled="false"
+ android:text="@string/software" />
+ </RadioGroup>
+
+ <FrameLayout
+ android:id="@+id/frameLayout2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/radio_group_mime"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginTop="10dp"
+ android:background="@color/colorPrimary"
+ app:layout_constraintTop_toBottomOf="@+id/radio_group_mime"
+ tools:layout_editor_absoluteX="80dp">
+
+ <Button
+ android:id="@+id/start_button"
+ android:layout_width="108dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:text="@string/start_button"
+ tools:layout_editor_absoluteX="155dp"
+ tools:layout_editor_absoluteY="455dp" />
+
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/textViewResults"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:fontFamily="sans-serif-medium"
+ android:textSize="18sp"
+ android:textStyle="normal"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf = "@+id/frameLayout2" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/media/tests/SampleVideoEncoder/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/media/tests/SampleVideoEncoder/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/raw/crowd_1920x1080_25fps_4000kbps_h265.mp4 b/media/tests/SampleVideoEncoder/app/src/main/res/raw/crowd_1920x1080_25fps_4000kbps_h265.mp4
new file mode 100644
index 0000000..6204008
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/raw/crowd_1920x1080_25fps_4000kbps_h265.mp4
Binary files differ
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/values/colors.xml b/media/tests/SampleVideoEncoder/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..4faecfa
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#6200EE</color>
+ <color name="colorPrimaryDark">#3700B3</color>
+ <color name="colorAccent">#03DAC5</color>
+</resources>
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/values/strings.xml b/media/tests/SampleVideoEncoder/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..f825a7f
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/values/strings.xml
@@ -0,0 +1,13 @@
+<resources>
+ <string name="app_name">SampleVideoEncoder</string>
+ <string name="media_recorder">MediaRecorder</string>
+ <string name="media_codec">MediaCodec</string>
+ <string name="start_button">Start</string>
+ <string name="stop">Stop</string>
+ <string name="start">Start</string>
+ <string name="avc">AVC</string>
+ <string name="hevc">HEVC</string>
+ <string name="hardware">H/W</string>
+ <string name="software">S/W</string>
+
+</resources>
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/app/src/main/res/values/styles.xml b/media/tests/SampleVideoEncoder/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..fac9291
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/app/src/main/res/values/styles.xml
@@ -0,0 +1,10 @@
+<resources>
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp b/media/tests/SampleVideoEncoder/build.gradle
similarity index 65%
rename from media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp
rename to media/tests/SampleVideoEncoder/build.gradle
index 1e08a55..4ca0c7e 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp
+++ b/media/tests/SampleVideoEncoder/build.gradle
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,5 +14,19 @@
* limitations under the License.
*/
-#include "BIQUAD.h"
-#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.1'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
\ No newline at end of file
diff --git a/media/tests/SampleVideoEncoder/gradle.properties b/media/tests/SampleVideoEncoder/gradle.properties
new file mode 100644
index 0000000..5ae443b
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/gradle.properties
@@ -0,0 +1,4 @@
+# Project-wide Gradle settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/media/tests/SampleVideoEncoder/gradle/wrapper/gradle-wrapper.jar b/media/tests/SampleVideoEncoder/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/media/tests/SampleVideoEncoder/gradle/wrapper/gradle-wrapper.properties b/media/tests/SampleVideoEncoder/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..a9a12eb
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 16 10:06:45 IST 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
diff --git a/media/tests/SampleVideoEncoder/gradlew b/media/tests/SampleVideoEncoder/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/media/tests/SampleVideoEncoder/gradlew.bat b/media/tests/SampleVideoEncoder/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/media/tests/SampleVideoEncoder/settings.gradle b/media/tests/SampleVideoEncoder/settings.gradle
new file mode 100644
index 0000000..4d3c3a5
--- /dev/null
+++ b/media/tests/SampleVideoEncoder/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "SampleVideoEncoder"
\ No newline at end of file
diff --git a/media/tests/benchmark/Android.bp b/media/tests/benchmark/Android.bp
index de408dd..8503a9c 100644
--- a/media/tests/benchmark/Android.bp
+++ b/media/tests/benchmark/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
subdirs = [
"src",
"tests",
diff --git a/media/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
index d80d9a5..2e06da5 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
android_test {
name: "MediaBenchmarkTest",
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
index 3e5e4c8..af92424 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test_library {
name: "libmediabenchmark_jni",
sdk_version: "current",
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
index d4389da..6b54c6a 100644
--- a/media/tests/benchmark/src/native/common/Android.bp
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libmediabenchmark_common",
defaults: [
diff --git a/media/tests/benchmark/src/native/decoder/Android.bp b/media/tests/benchmark/src/native/decoder/Android.bp
index 9791c11..601b2f6 100644
--- a/media/tests/benchmark/src/native/decoder/Android.bp
+++ b/media/tests/benchmark/src/native/decoder/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libmediabenchmark_decoder",
defaults: [
diff --git a/media/tests/benchmark/src/native/encoder/Android.bp b/media/tests/benchmark/src/native/encoder/Android.bp
index 8de7823..a787068 100644
--- a/media/tests/benchmark/src/native/encoder/Android.bp
+++ b/media/tests/benchmark/src/native/encoder/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libmediabenchmark_encoder",
defaults: [
diff --git a/media/tests/benchmark/src/native/extractor/Android.bp b/media/tests/benchmark/src/native/extractor/Android.bp
index 7ed9476..4946990 100644
--- a/media/tests/benchmark/src/native/extractor/Android.bp
+++ b/media/tests/benchmark/src/native/extractor/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libmediabenchmark_extractor",
defaults: [
diff --git a/media/tests/benchmark/src/native/muxer/Android.bp b/media/tests/benchmark/src/native/muxer/Android.bp
index f669d4a..84985e4 100644
--- a/media/tests/benchmark/src/native/muxer/Android.bp
+++ b/media/tests/benchmark/src/native/muxer/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libmediabenchmark_muxer",
defaults: [
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
index f46fa4a..0fbd20d 100644
--- a/media/tests/benchmark/tests/Android.bp
+++ b/media/tests/benchmark/tests/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "extractorTest",
gtest: true,
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index e3f1e44..cdbd52c 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libmediautils",
@@ -28,6 +37,7 @@
],
static_libs: [
"libc_malloc_debug_backtrace",
+ "libbatterystats_aidl",
],
shared_libs: [
"libaudioutils", // for clock.h
@@ -39,6 +49,9 @@
"android.hardware.graphics.bufferqueue@1.0",
"android.hidl.token@1.0-utils",
],
+ export_static_lib_headers: [
+ "libbatterystats_aidl",
+ ],
logtags: ["EventLogTags.logtags"],
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..1b1717f 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -62,7 +62,7 @@
}
static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
- uid_t uid, bool start) {
+ uid_t uid, bool start, bool isHotwordSource) {
// Okay to not track in app ops as audio server or media server is us and if
// device is rooted security model is considered compromised.
// system_server loses its RECORD_AUDIO permission when a secondary
@@ -87,16 +87,21 @@
}
AppOpsManager appOps;
- const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+ const int32_t opRecordAudio = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+
if (start) {
+ const int32_t op = isHotwordSource ?
+ AppOpsManager::OP_RECORD_AUDIO_HOTWORD : opRecordAudio;
if (appOps.startOpNoThrow(op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false)
!= AppOpsManager::MODE_ALLOWED) {
ALOGE("Request denied by app op: %d", op);
return false;
}
} else {
- if (appOps.checkOp(op, uid, resolvedOpPackageName) != AppOpsManager::MODE_ALLOWED) {
- ALOGE("Request denied by app op: %d", op);
+ // Always use OP_RECORD_AUDIO for checks at creation time.
+ if (appOps.checkOp(opRecordAudio, uid, resolvedOpPackageName)
+ != AppOpsManager::MODE_ALLOWED) {
+ ALOGE("Request denied by app op: %d", opRecordAudio);
return false;
}
}
@@ -105,14 +110,15 @@
}
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
- return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false);
+ return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false,
+ /*is_hotword_source*/ false);
}
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
- return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource) {
+ return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, isHotwordSource);
}
-void finishRecording(const String16& opPackageName, uid_t uid) {
+void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource) {
// Okay to not track in app ops as audio server is us and if
// device is rooted security model is considered compromised.
if (isAudioServerOrRootUid(uid)) return;
@@ -125,7 +131,8 @@
}
AppOpsManager appOps;
- const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+ const int32_t op = isHotwordSource ? AppOpsManager::OP_RECORD_AUDIO_HOTWORD
+ : appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
appOps.finishOp(op, uid, resolvedOpPackageName);
}
@@ -259,7 +266,7 @@
return NO_ERROR;
}
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+sp<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() {
const sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
@@ -276,27 +283,27 @@
std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
if (mPackageManager == nullptr) {
/** Can not fetch package manager at construction it may not yet be registered. */
- mPackageManager = retreivePackageManager();
+ mPackageManager = retrievePackageManager();
if (mPackageManager == nullptr) {
ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
return std::nullopt;
}
}
+ // Retrieve package names for the UID and transform to a std::vector<std::string>.
+ Vector<String16> str16PackageNames;
+ PermissionController{}.getPackagesForUid(uid, str16PackageNames);
std::vector<std::string> packageNames;
- auto status = mPackageManager->getNamesForUids({(int32_t)uid}, &packageNames);
- if (!status.isOk()) {
- ALOGW("%s: Playback capture is denied for uid %u as the package names could not be "
- "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
- return std::nullopt;
+ for (const auto& str16PackageName : str16PackageNames) {
+ packageNames.emplace_back(String8(str16PackageName).string());
}
if (packageNames.empty()) {
ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
- "from the package manager: %s", __func__, uid, status.toString8().c_str());
+ "from the package manager.", __func__, uid);
return std::nullopt;
}
std::vector<bool> isAllowed;
- status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
+ auto status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
if (!status.isOk()) {
ALOGW("%s: Playback capture is denied for uid %u as the manifest property could not be "
"retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
diff --git a/media/utils/fuzzers/Android.bp b/media/utils/fuzzers/Android.bp
index ca1123c..5c03926 100644
--- a/media/utils/fuzzers/Android.bp
+++ b/media/utils/fuzzers/Android.bp
@@ -1,6 +1,16 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_defaults {
name: "libmediautils_fuzzer_defaults",
shared_libs: [
+ "libbatterystats_aidl",
"libbinder",
"libcutils",
"liblog",
diff --git a/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp b/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
index 4521853..130feee 100644
--- a/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
+++ b/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#define LOG_TAG "BatteryNotifierFuzzer"
-#include <binder/IBatteryStats.h>
+#include <batterystats/IBatteryStats.h>
#include <binder/IServiceManager.h>
#include <utils/String16.h>
#include <android/log.h>
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 3d141b5..20b3713 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -54,8 +54,8 @@
std::string packageNameStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
android::String16 opPackageName(packageNameStr.c_str());
android::recordingAllowed(opPackageName, pid, uid);
- android::startRecording(opPackageName, pid, uid);
- android::finishRecording(opPackageName, uid);
+ android::startRecording(opPackageName, pid, uid, false);
+ android::finishRecording(opPackageName, uid, false);
android::captureAudioOutputAllowed(pid, uid);
android::captureMediaOutputAllowed(pid, uid);
android::captureHotwordAllowed(opPackageName, pid, uid);
diff --git a/media/utils/include/mediautils/BatteryNotifier.h b/media/utils/include/mediautils/BatteryNotifier.h
index a4e42ad..3812d7a 100644
--- a/media/utils/include/mediautils/BatteryNotifier.h
+++ b/media/utils/include/mediautils/BatteryNotifier.h
@@ -17,7 +17,7 @@
#ifndef MEDIA_BATTERY_NOTIFIER_H
#define MEDIA_BATTERY_NOTIFIER_H
-#include <binder/IBatteryStats.h>
+#include <batterystats/IBatteryStats.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..c7d49fd 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -79,8 +79,8 @@
}
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid);
-void finishRecording(const String16& opPackageName, uid_t uid);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource);
+void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource);
bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
@@ -110,7 +110,7 @@
private:
static constexpr const char* nativePackageManagerName = "package_native";
std::optional<bool> doIsAllowed(uid_t uid);
- sp<content::pm::IPackageManagerNative> retreivePackageManager();
+ sp<content::pm::IPackageManagerNative> retrievePackageManager();
sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
uint_t mPackageManagerErrors = 0;
struct Package {
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 3873600..3c9897d 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -1,5 +1,24 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_av_services_audioflinger_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_services_audioflinger_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libaudioflinger",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5f0b575..4ac46b7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -852,7 +852,8 @@
input.notificationsPerBuffer, input.speed,
input.sharedBuffer, sessionId, &output.flags,
callingPid, input.clientInfo.clientTid, clientUid,
- &lStatus, portId, input.audioTrackCallback);
+ &lStatus, portId, input.audioTrackCallback,
+ input.opPackageName);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
@@ -1461,6 +1462,20 @@
}
}
+// Update downstream patches for all playback threads attached to an MSD module
+void AudioFlinger::updateDownStreamPatches_l(const struct audio_patch *patch,
+ const std::set<audio_io_handle_t> streams)
+{
+ for (const audio_io_handle_t stream : streams) {
+ PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
+ if (playbackThread == nullptr || !playbackThread->isMsdDevice()) {
+ continue;
+ }
+ playbackThread->setDownStreamPatch(patch);
+ playbackThread->sendIoConfigEvent(AUDIO_OUTPUT_CONFIG_CHANGED);
+ }
+}
+
// Filter reserved keys from setParameters() before forwarding to audio HAL or acting upon.
// Some keys are used for audio routing and audio path configuration and should be reserved for use
// by audio policy and audio flinger for functional, privacy and security reasons.
@@ -2068,8 +2083,8 @@
Mutex::Autolock _l(mLock);
RecordThread *thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
- ALOGE("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
- lStatus = BAD_VALUE;
+ ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
+ lStatus = FAILED_TRANSACTION;
goto Exit;
}
@@ -2533,7 +2548,11 @@
*output, thread.get());
}
mPlaybackThreads.add(*output, thread);
- mPatchPanel.notifyStreamOpened(outHwDev, *output);
+ struct audio_patch patch;
+ mPatchPanel.notifyStreamOpened(outHwDev, *output, &patch);
+ if (thread->isMsdDevice()) {
+ thread->setDownStreamPatch(&patch);
+ }
return thread;
}
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 20f561e..10d4029 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -320,6 +320,9 @@
status_t removeEffectFromHal(audio_port_handle_t deviceId,
audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+ void updateDownStreamPatches_l(const struct audio_patch *patch,
+ const std::set<audio_io_handle_t> streams);
+
private:
// FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
static const size_t kLogMemorySize = 400 * 1024;
@@ -405,7 +408,7 @@
case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
// Haptic channel mask is only applicable for channel position mask.
const uint32_t channelCount = audio_channel_count_from_out_mask(
- channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
+ static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL));
const uint32_t maxChannelCount = kEnableExtendedChannels
? AudioMixer::MAX_NUM_CHANNELS : FCC_2;
if (channelCount < FCC_2 // mono is not supported at this time
@@ -642,6 +645,13 @@
virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
virtual status_t getTimestamp(AudioTimestamp& timestamp);
virtual void signal(); // signal playback thread for a change in control block
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override;
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) override;
+ status_t getAudioDescriptionMixLevel(float* leveldB) override;
+ status_t setAudioDescriptionMixLevel(float leveldB) override;
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override;
+ status_t setPlaybackRateParameters(
+ const audio_playback_rate_t& playbackRate) override;
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 529b87c..eebaa7e 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2994,7 +2994,7 @@
__func__, port->type, port->ext.device.type,
port->ext.device.address, port->id, patch.isSoftware());
if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType
- || port->ext.device.address != mDevice.mAddress) {
+ || port->ext.device.address != mDevice.address()) {
return NAME_NOT_FOUND;
}
status_t status = NAME_NOT_FOUND;
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index cd3c743..13e2ced 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -353,7 +353,8 @@
#endif
//ALOGD("Eric FastMixer::onWork() mIsWarm");
} else {
- dumpState->mTimestampVerifier.discontinuity();
+ dumpState->mTimestampVerifier.discontinuity(
+ dumpState->mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS);
// See comment in if block.
#ifdef FASTMIXER_LOG_HIST_TS
LOG_AUDIO_STATE();
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index b58fd8b..37aa13e 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -413,10 +413,10 @@
*handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
newPatch.mHalHandle = halHandle;
mAudioFlinger.mDeviceEffectManager.createAudioPatch(*handle, newPatch);
- mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
- addSoftwarePatchToInsertedModules(insertedModule, *handle);
+ addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
}
+ mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
} else {
newPatch.clearConnections(this);
}
@@ -781,10 +781,20 @@
}
void AudioFlinger::PatchPanel::notifyStreamOpened(
- AudioHwDevice *audioHwDevice, audio_io_handle_t stream)
+ AudioHwDevice *audioHwDevice, audio_io_handle_t stream, struct audio_patch *patch)
{
if (audioHwDevice->isInsert()) {
mInsertedModules[audioHwDevice->handle()].streams.insert(stream);
+ if (patch != nullptr) {
+ std::vector <SoftwarePatch> swPatches;
+ getDownstreamSoftwarePatches(stream, &swPatches);
+ if (swPatches.size() > 0) {
+ auto iter = mPatches.find(swPatches[0].getPatchHandle());
+ if (iter != mPatches.end()) {
+ *patch = iter->second.mAudioPatch;
+ }
+ }
+ }
}
}
@@ -813,9 +823,13 @@
}
void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
- audio_module_handle_t module, audio_patch_handle_t handle)
+ audio_module_handle_t module, audio_patch_handle_t handle,
+ const struct audio_patch *patch)
{
mInsertedModules[module].sw_patches.insert(handle);
+ if (!mInsertedModules[module].streams.empty()) {
+ mAudioFlinger.updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
+ }
}
void AudioFlinger::PatchPanel::removeSoftwarePatchFromInsertedModules(
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 89d4eb1..ea38559 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -71,7 +71,8 @@
std::vector<SoftwarePatch> *patches) const;
// Notifies patch panel about all opened and closed streams.
- void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream);
+ void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
+ struct audio_patch *patch);
void notifyStreamClosed(audio_io_handle_t stream);
void dump(int fd) const;
@@ -226,7 +227,8 @@
AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
void addSoftwarePatchToInsertedModules(
- audio_module_handle_t module, audio_patch_handle_t handle);
+ audio_module_handle_t module, audio_patch_handle_t handle,
+ const struct audio_patch *patch);
void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
void erasePatch(audio_patch_handle_t handle);
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index d8eebf3..472c359 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -26,10 +26,11 @@
bool hasOpPlayAudio() const;
static sp<OpPlayAudioMonitor> createIfNeeded(
- uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType);
+ uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType,
+ const std::string& opPackageName);
private:
- OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id);
+ OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id, const String16& opPackageName);
void onFirstRef() override;
static void getPackagesForUid(uid_t uid, Vector<String16>& packages);
@@ -49,10 +50,10 @@
void checkPlayAudioForUsage();
std::atomic_bool mHasOpPlayAudio;
- Vector<String16> mPackages;
const uid_t mUid;
const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t
const int mId; // for logging purposes only
+ const String16 mOpPackageName;
};
// playback track
@@ -77,7 +78,8 @@
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
/** default behaviour is to start when there are as many frames
* ready as possible (aka. Buffer is full). */
- size_t frameCountToBeReady = SIZE_MAX);
+ size_t frameCountToBeReady = SIZE_MAX,
+ const std::string opPackageName = "");
virtual ~Track();
virtual status_t initCheck() const;
@@ -115,6 +117,12 @@
int auxEffectId() const { return mAuxEffectId; }
virtual status_t getTimestamp(AudioTimestamp& timestamp);
void signal();
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode);
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode);
+ status_t getAudioDescriptionMixLevel(float* leveldB);
+ status_t setAudioDescriptionMixLevel(float leveldB);
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate);
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate);
// implement FastMixerState::VolumeProvider interface
virtual gain_minifloat_packed_t getVolumeLR();
@@ -146,7 +154,7 @@
*/
bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
- using SourceMetadatas = std::vector<playback_track_metadata_t>;
+ using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
/** Copy the track metadata in the provided iterator. Thread safe. */
virtual void copyMetadataTo(MetadataInserter& backInserter) const;
@@ -276,8 +284,10 @@
};
sp<AudioVibrationController> mAudioVibrationController;
sp<os::ExternalVibration> mExternalVibration;
- /** How many frames should be in the buffer before the track is considered ready */
- const size_t mFrameCountToBeReady;
+
+ audio_dual_mono_mode_t mDualMonoMode = AUDIO_DUAL_MONO_MODE_OFF;
+ float mAudioDescriptionMixLevel = -std::numeric_limits<float>::infinity();
+ audio_playback_rate_t mPlaybackRateParameters = AUDIO_PLAYBACK_RATE_INITIALIZER;
private:
void interceptBuffer(const AudioBufferProvider::Buffer& buffer);
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index c7aba79..0ce5681 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -39,7 +39,7 @@
, mSpdifEncoder(this, format)
, mApplicationFormat(AUDIO_FORMAT_DEFAULT)
, mApplicationSampleRate(0)
- , mApplicationChannelMask(0)
+ , mApplicationChannelMask(AUDIO_CHANNEL_NONE)
{
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b143388..64e935d 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -622,7 +622,7 @@
mIoJitterMs.reset();
mLatencyMs.reset();
mProcessTimeMs.reset();
- mTimestampVerifier.discontinuity();
+ mTimestampVerifier.discontinuity(mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS);
sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid, portId);
sendConfigEvent_l(configEvent);
@@ -1864,7 +1864,8 @@
// index 0 is reserved for normal mixer's submix
mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
- mLeftVolFloat(-1.0), mRightVolFloat(-1.0)
+ mLeftVolFloat(-1.0), mRightVolFloat(-1.0),
+ mDownStreamPatch{}
{
snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -1902,9 +1903,8 @@
: AUDIO_DEVICE_NONE));
}
- // ++ operator does not compile
- for (audio_stream_type_t stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_FOR_POLICY_CNT;
- stream = (audio_stream_type_t) (stream + 1)) {
+ for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
+ const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
mStreamTypes[stream].volume = 0.0f;
mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
}
@@ -2068,7 +2068,8 @@
uid_t uid,
status_t *status,
audio_port_handle_t portId,
- const sp<media::IAudioTrackCallback>& callback)
+ const sp<media::IAudioTrackCallback>& callback,
+ const std::string& opPackageName)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2349,7 +2350,8 @@
track = new Track(this, client, streamType, attr, sampleRate, format,
channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
- sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId);
+ sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId,
+ SIZE_MAX /*frameCountToBeReady*/, opPackageName);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2361,7 +2363,7 @@
{
Mutex::Autolock _atCbL(mAudioTrackCbLock);
if (callback.get() != nullptr) {
- mAudioTrackCallbacks.emplace(callback);
+ mAudioTrackCallbacks.emplace(track, callback);
}
}
@@ -2589,6 +2591,10 @@
mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
mTracks.remove(track);
+ {
+ Mutex::Autolock _atCbL(mAudioTrackCbLock);
+ mAudioTrackCallbacks.erase(track);
+ }
if (track->isFastTrack()) {
int index = track->mFastIndex;
ALOG_ASSERT(0 < index && index < (int)FastMixerState::sMaxFastTracks);
@@ -2627,12 +2633,16 @@
ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
desc->mIoHandle = mId;
+ struct audio_patch patch = mPatch;
+ if (isMsdDevice()) {
+ patch = mDownStreamPatch;
+ }
switch (event) {
case AUDIO_OUTPUT_OPENED:
case AUDIO_OUTPUT_REGISTERED:
case AUDIO_OUTPUT_CONFIG_CHANGED:
- desc->mPatch = mPatch;
+ desc->mPatch = patch;
desc->mChannelMask = mChannelMask;
desc->mSamplingRate = mSampleRate;
desc->mFormat = mFormat;
@@ -2642,7 +2652,7 @@
desc->mLatency = latency_l();
break;
case AUDIO_CLIENT_STARTED:
- desc->mPatch = mPatch;
+ desc->mPatch = patch;
desc->mPortId = portId;
break;
case AUDIO_OUTPUT_CLOSED:
@@ -2684,8 +2694,8 @@
audio_utils::metadata::byteStringFromData(metadata);
std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
Mutex::Autolock _l(mAudioTrackCbLock);
- for (const auto& callback : mAudioTrackCallbacks) {
- callback->onCodecFormatChanged(metadataVec);
+ for (const auto& callbackPair : mAudioTrackCallbacks) {
+ callbackPair.second->onCodecFormatChanged(metadataVec);
}
}).detach();
}
@@ -2709,7 +2719,7 @@
// the timestamp frame position to reset to 0 for direct and offload threads.
// (Out of sequence requests are ignored, since the discontinuity would be handled
// elsewhere, e.g. in flush).
- mTimestampVerifier.discontinuity();
+ mTimestampVerifier.discontinuity(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
mDrainSequence &= ~1;
mWaitWorkCV.signal();
}
@@ -2863,8 +2873,8 @@
(void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
}
- mHapticChannelMask = mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
- mChannelMask &= ~mHapticChannelMask;
+ mHapticChannelMask = static_cast<audio_channel_mask_t>(mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+ mChannelMask = static_cast<audio_channel_mask_t>(mChannelMask & ~mHapticChannelMask);
mHapticChannelCount = audio_channel_count_from_out_mask(mHapticChannelMask);
mChannelCount -= mHapticChannelCount;
@@ -3398,7 +3408,6 @@
mStandbyTimeNs = systemTime();
int64_t lastLoopCountWritten = -2; // never matches "previous" loop, when loopCount = 0.
- int64_t lastFramesWritten = -1; // track changes in timestamp server frames written
// MIXER
nsecs_t lastWarning = 0;
@@ -3434,14 +3443,6 @@
checkSilentMode_l();
- // DIRECT and OFFLOAD threads should reset frame count to zero on stop/flush
- // TODO: add confirmation checks:
- // 1) DIRECT threads and linear PCM format really resets to 0?
- // 2) Is frame count really valid if not linear pcm?
- // 3) Are all 64 bits of position returned, not just lowest 32 bits?
- if (mType == OFFLOAD || mType == DIRECT) {
- mTimestampVerifier.setDiscontinuityMode(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
- }
audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
// loopCount is used for statistics and diagnostics.
@@ -3513,135 +3514,8 @@
logString = NULL;
}
- // Collect timestamp statistics for the Playback Thread types that support it.
- if (mType == MIXER
- || mType == DUPLICATING
- || mType == DIRECT
- || mType == OFFLOAD) { // no indentation
- // Gather the framesReleased counters for all active tracks,
- // and associate with the sink frames written out. We need
- // this to convert the sink timestamp to the track timestamp.
- bool kernelLocationUpdate = false;
- ExtendedTimestamp timestamp; // use private copy to fetch
- if (mStandby) {
- mTimestampVerifier.discontinuity();
- } else if (threadloop_getHalTimestamp_l(×tamp) == OK) {
- mTimestampVerifier.add(timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
- timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
- mSampleRate);
+ collectTimestamps_l();
- if (isTimestampCorrectionEnabled()) {
- ALOGVV("TS_BEFORE: %d %lld %lld", id(),
- (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
- (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
- auto correctedTimestamp = mTimestampVerifier.getLastCorrectedTimestamp();
- timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
- = correctedTimestamp.mFrames;
- timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]
- = correctedTimestamp.mTimeNs;
- ALOGVV("TS_AFTER: %d %lld %lld", id(),
- (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
- (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
-
- // Note: Downstream latency only added if timestamp correction enabled.
- if (mDownstreamLatencyStatMs.getN() > 0) { // we have latency info.
- const int64_t newPosition =
- timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
- - int64_t(mDownstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
- // prevent retrograde
- timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = max(
- newPosition,
- (mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
- - mSuspendedFrames));
- }
- }
-
- // We always fetch the timestamp here because often the downstream
- // sink will block while writing.
-
- // We keep track of the last valid kernel position in case we are in underrun
- // and the normal mixer period is the same as the fast mixer period, or there
- // is some error from the HAL.
- if (mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] >= 0) {
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] =
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] =
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
-
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] =
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER];
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] =
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER];
- }
-
- if (timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] >= 0) {
- kernelLocationUpdate = true;
- } else {
- ALOGVV("getTimestamp error - no valid kernel position");
- }
-
- // copy over kernel info
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
- timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
- + mSuspendedFrames; // add frames discarded when suspended
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
- timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
- } else {
- mTimestampVerifier.error();
- }
-
- // mFramesWritten for non-offloaded tracks are contiguous
- // even after standby() is called. This is useful for the track frame
- // to sink frame mapping.
- bool serverLocationUpdate = false;
- if (mFramesWritten != lastFramesWritten) {
- serverLocationUpdate = true;
- lastFramesWritten = mFramesWritten;
- }
- // Only update timestamps if there is a meaningful change.
- // Either the kernel timestamp must be valid or we have written something.
- if (kernelLocationUpdate || serverLocationUpdate) {
- if (serverLocationUpdate) {
- // use the time before we called the HAL write - it is a bit more accurate
- // to when the server last read data than the current time here.
- //
- // If we haven't written anything, mLastIoBeginNs will be -1
- // and we use systemTime().
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastIoBeginNs == -1
- ? systemTime() : mLastIoBeginNs;
- }
-
- for (const sp<Track> &t : mActiveTracks) {
- if (!t->isFastTrack()) {
- t->updateTrackFrameInfo(
- t->mAudioTrackServerProxy->framesReleased(),
- mFramesWritten,
- mSampleRate,
- mTimestamp);
- }
- }
- }
-
- if (audio_has_proportional_frames(mFormat)) {
- const double latencyMs = mTimestamp.getOutputServerLatencyMs(mSampleRate);
- if (latencyMs != 0.) { // note 0. means timestamp is empty.
- mLatencyMs.add(latencyMs);
- }
- }
-
- } // if (mType ... ) { // no indentation
-#if 0
- // logFormat example
- if (z % 100 == 0) {
- timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- LOGT("This is an integer %d, this is a float %f, this is my "
- "pid %p %% %s %t", 42, 3.14, "and this is a timestamp", ts);
- LOGT("A deceptive null-terminated string %\0");
- }
- ++z;
-#endif
saveOutputTracks();
if (mSignalPending) {
// A signal was raised while we were unlocked
@@ -4081,6 +3955,148 @@
return false;
}
+void AudioFlinger::PlaybackThread::collectTimestamps_l()
+{
+ // Collect timestamp statistics for the Playback Thread types that support it.
+ if (mType != MIXER
+ && mType != DUPLICATING
+ && mType != DIRECT
+ && mType != OFFLOAD) {
+ return;
+ }
+ if (mStandby) {
+ mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
+ return;
+ } else if (mHwPaused) {
+ mTimestampVerifier.discontinuity(mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS);
+ return;
+ }
+
+ // Gather the framesReleased counters for all active tracks,
+ // and associate with the sink frames written out. We need
+ // this to convert the sink timestamp to the track timestamp.
+ bool kernelLocationUpdate = false;
+ ExtendedTimestamp timestamp; // use private copy to fetch
+
+ // Always query HAL timestamp and update timestamp verifier. In standby or pause,
+ // HAL may be draining some small duration buffered data for fade out.
+ if (threadloop_getHalTimestamp_l(×tamp) == OK) {
+ mTimestampVerifier.add(timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
+ mSampleRate);
+
+ if (isTimestampCorrectionEnabled()) {
+ ALOGVV("TS_BEFORE: %d %lld %lld", id(),
+ (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
+ (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
+ auto correctedTimestamp = mTimestampVerifier.getLastCorrectedTimestamp();
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
+ = correctedTimestamp.mFrames;
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]
+ = correctedTimestamp.mTimeNs;
+ ALOGVV("TS_AFTER: %d %lld %lld", id(),
+ (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
+ (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
+
+ // Note: Downstream latency only added if timestamp correction enabled.
+ if (mDownstreamLatencyStatMs.getN() > 0) { // we have latency info.
+ const int64_t newPosition =
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
+ - int64_t(mDownstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
+ // prevent retrograde
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = max(
+ newPosition,
+ (mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
+ - mSuspendedFrames));
+ }
+ }
+
+ // We always fetch the timestamp here because often the downstream
+ // sink will block while writing.
+
+ // We keep track of the last valid kernel position in case we are in underrun
+ // and the normal mixer period is the same as the fast mixer period, or there
+ // is some error from the HAL.
+ if (mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] >= 0) {
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] =
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] =
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] =
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER];
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] =
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER];
+ }
+
+ if (timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] >= 0) {
+ kernelLocationUpdate = true;
+ } else {
+ ALOGVV("getTimestamp error - no valid kernel position");
+ }
+
+ // copy over kernel info
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
+ + mSuspendedFrames; // add frames discarded when suspended
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+ } else {
+ mTimestampVerifier.error();
+ }
+
+ // mFramesWritten for non-offloaded tracks are contiguous
+ // even after standby() is called. This is useful for the track frame
+ // to sink frame mapping.
+ bool serverLocationUpdate = false;
+ if (mFramesWritten != mLastFramesWritten) {
+ serverLocationUpdate = true;
+ mLastFramesWritten = mFramesWritten;
+ }
+ // Only update timestamps if there is a meaningful change.
+ // Either the kernel timestamp must be valid or we have written something.
+ if (kernelLocationUpdate || serverLocationUpdate) {
+ if (serverLocationUpdate) {
+ // use the time before we called the HAL write - it is a bit more accurate
+ // to when the server last read data than the current time here.
+ //
+ // If we haven't written anything, mLastIoBeginNs will be -1
+ // and we use systemTime().
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastIoBeginNs == -1
+ ? systemTime() : mLastIoBeginNs;
+ }
+
+ for (const sp<Track> &t : mActiveTracks) {
+ if (!t->isFastTrack()) {
+ t->updateTrackFrameInfo(
+ t->mAudioTrackServerProxy->framesReleased(),
+ mFramesWritten,
+ mSampleRate,
+ mTimestamp);
+ }
+ }
+ }
+
+ if (audio_has_proportional_frames(mFormat)) {
+ const double latencyMs = mTimestamp.getOutputServerLatencyMs(mSampleRate);
+ if (latencyMs != 0.) { // note 0. means timestamp is empty.
+ mLatencyMs.add(latencyMs);
+ }
+ }
+#if 0
+ // logFormat example
+ if (z % 100 == 0) {
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ LOGT("This is an integer %d, this is a float %f, this is my "
+ "pid %p %% %s %t", 42, 3.14, "and this is a timestamp", ts);
+ LOGT("A deceptive null-terminated string %\0");
+ }
+ ++z;
+#endif
+}
+
// removeTracks_l() must be called with ThreadBase::mLock held
void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
{
@@ -4127,20 +4143,15 @@
return status;
}
if ((mType == OFFLOAD || mType == DIRECT) && mOutput != NULL) {
- uint64_t position64;
- if (mOutput->getPresentationPosition(&position64, ×tamp.mTime) == OK) {
- timestamp.mPosition = (uint32_t)position64;
- if (mDownstreamLatencyStatMs.getN() > 0) {
- const uint32_t positionOffset =
- (uint32_t)(mDownstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
- if (positionOffset > timestamp.mPosition) {
- timestamp.mPosition = 0;
- } else {
- timestamp.mPosition -= positionOffset;
- }
- }
- return NO_ERROR;
+ collectTimestamps_l();
+ if (mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] <= 0) {
+ return INVALID_OPERATION;
}
+ timestamp.mPosition = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ const int64_t timeNs = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+ timestamp.mTime.tv_sec = timeNs / NANOS_PER_SECOND;
+ timestamp.mTime.tv_nsec = timeNs - (timestamp.mTime.tv_sec * NANOS_PER_SECOND);
+ return NO_ERROR;
}
return INVALID_OPERATION;
}
@@ -4200,7 +4211,7 @@
"Enumerated device type(%#x) must not be used "
"as it does not support audio patches",
patch->sinks[i].ext.device.type);
- type |= patch->sinks[i].ext.device.type;
+ type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
patch->sinks[i].ext.device.address));
}
@@ -4450,8 +4461,9 @@
// wrap the source side of the MonoPipe to make it an AudioBufferProvider
fastTrack->mBufferProvider = new SourceAudioBufferProvider(new MonoPipeReader(monoPipe));
fastTrack->mVolumeProvider = NULL;
- fastTrack->mChannelMask = mChannelMask | mHapticChannelMask; // mPipeSink channel mask for
- // audio to FastMixer
+ fastTrack->mChannelMask = static_cast<audio_channel_mask_t>(
+ mChannelMask | mHapticChannelMask); // mPipeSink channel mask for
+ // audio to FastMixer
fastTrack->mFormat = mFormat; // mPipeSink format for audio to FastMixer
fastTrack->mHapticPlaybackEnabled = mHapticChannelMask != AUDIO_CHANNEL_NONE;
fastTrack->mHapticIntensity = AudioMixer::HAPTIC_SCALE_NONE;
@@ -4465,7 +4477,8 @@
// specify sink channel mask when haptic channel mask present as it can not
// be calculated directly from channel count
state->mSinkChannelMask = mHapticChannelMask == AUDIO_CHANNEL_NONE
- ? AUDIO_CHANNEL_NONE : mChannelMask | mHapticChannelMask;
+ ? AUDIO_CHANNEL_NONE
+ : static_cast<audio_channel_mask_t>(mChannelMask | mHapticChannelMask);
state->mCommand = FastMixerState::COLD_IDLE;
// already done in constructor initialization list
//mFastMixerFutex = 0;
@@ -5539,8 +5552,6 @@
status_t& status)
{
bool reconfig = false;
- bool a2dpDeviceChanged = false;
-
status = NO_ERROR;
AutoPark<FastMixer> park(mFastMixer);
@@ -5612,7 +5623,7 @@
}
}
- return reconfig || a2dpDeviceChanged;
+ return reconfig;
}
@@ -6073,8 +6084,6 @@
status_t& status)
{
bool reconfig = false;
- bool a2dpDeviceChanged = false;
-
status = NO_ERROR;
AudioParameter param = AudioParameter(keyValuePair);
@@ -6109,7 +6118,7 @@
}
}
- return reconfig || a2dpDeviceChanged;
+ return reconfig;
}
uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
@@ -6166,7 +6175,7 @@
mOutput->flush();
mHwPaused = false;
mFlushPending = false;
- mTimestampVerifier.discontinuity(); // DIRECT and OFFLOADED flush resets frame count.
+ mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
mTimestamp.clear();
}
@@ -6502,13 +6511,14 @@
track->presentationComplete(framesWritten, audioHALFrames);
track->reset();
tracksToRemove->add(track);
- // DIRECT and OFFLOADED stop resets frame counts.
+ // OFFLOADED stop resets frame counts.
if (!mUseAsyncWrite) {
// If we don't get explicit drain notification we must
// register discontinuity regardless of whether this is
// the previous (!last) or the upcoming (last) track
// to avoid skipping the discontinuity.
- mTimestampVerifier.discontinuity();
+ mTimestampVerifier.discontinuity(
+ mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
}
}
} else {
@@ -7366,7 +7376,9 @@
if (mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
int64_t position, time;
if (mStandby) {
- mTimestampVerifier.discontinuity();
+ mTimestampVerifier.discontinuity(audio_is_linear_pcm(mFormat) ?
+ mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS :
+ mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
} else if (mSource->getCapturePosition(&position, &time) == NO_ERROR
&& time > mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]) {
@@ -7870,7 +7882,8 @@
AutoMutex lock(mLock);
if (recordTrack->isInvalid()) {
recordTrack->clearSyncStartEvent();
- return INVALID_OPERATION;
+ ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
+ return DEAD_OBJECT;
}
if (mActiveTracks.indexOf(recordTrack) >= 0) {
if (recordTrack->mState == TrackBase::PAUSING) {
@@ -7900,7 +7913,8 @@
recordTrack->mState = TrackBase::STARTING_2;
// STARTING_2 forces destroy to call stopInput.
}
- return INVALID_OPERATION;
+ ALOGW("%s track %d: invalidated after startInput", __func__, recordTrack->portId());
+ return DEAD_OBJECT;
}
if (recordTrack->mState != TrackBase::STARTING_1) {
ALOGW("%s(%d): unsynchronized mState:%d change",
@@ -8047,10 +8061,15 @@
StreamInHalInterface::SinkMetadata metadata;
for (const sp<RecordTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
@@ -8555,7 +8574,7 @@
// store new device and send to effects
mInDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
- mInDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
+ mInDeviceTypeAddr.setAddress(patch->sources[0].ext.device.address);
audio_port_handle_t deviceId = patch->sources[0].id;
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->setInputDevice_l(inDeviceTypeAddr());
@@ -8634,6 +8653,7 @@
void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
{
+ Mutex::Autolock _l(mLock);
mOutDevices = outDevices;
mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9185,7 +9205,7 @@
"Enumerated device type(%#x) must not be used "
"as it does not support audio patches",
patch->sinks[i].ext.device.type);
- type |= patch->sinks[i].ext.device.type;
+ type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
patch->sinks[i].ext.device.address));
}
@@ -9196,7 +9216,7 @@
deviceId = patch->sources[0].id;
numDevices = mPatch.num_sources;
sourceDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
- sourceDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
+ sourceDeviceTypeAddr.setAddress(patch->sources[0].ext.device.address);
}
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9611,11 +9631,15 @@
StreamOutHalInterface::SourceMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ playback_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.usage = track->attributes().usage,
.content_type = track->attributes().content_type,
.gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mOutput->stream->updateSourceMetadata(metadata);
}
@@ -9722,10 +9746,14 @@
StreamInHalInterface::SinkMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index c1ac2e4..9f65562 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -590,6 +590,11 @@
ExtendedTimestamp mTimestamp;
TimestampVerifier< // For timestamp statistics.
int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
+ // DIRECT and OFFLOAD threads should reset frame count to zero on stop/flush
+ // TODO: add confirmation checks:
+ // 1) DIRECT threads and linear PCM format really resets to 0?
+ // 2) Is frame count really valid if not linear pcm?
+ // 3) Are all 64 bits of position returned, not just lowest 32 bits?
// Timestamp corrected device should be a single device.
audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE;
@@ -864,7 +869,8 @@
uid_t uid,
status_t *status /*non-NULL*/,
audio_port_handle_t portId,
- const sp<media::IAudioTrackCallback>& callback);
+ const sp<media::IAudioTrackCallback>& callback,
+ const std::string& opPackageName);
AudioStreamOut* getOutput() const;
AudioStreamOut* clearOutput();
@@ -939,6 +945,11 @@
&& outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
}
+ void setDownStreamPatch(const struct audio_patch *patch) {
+ Mutex::Autolock _l(mLock);
+ mDownStreamPatch = *patch;
+ }
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1017,6 +1028,8 @@
int64_t mBytesWritten;
int64_t mFramesWritten; // not reset on standby
+ int64_t mLastFramesWritten = -1; // track changes in timestamp
+ // server frames written.
int64_t mSuspendedFrames; // not reset on standby
// mHapticChannelMask and mHapticChannelCount will only be valid when the thread support
@@ -1029,6 +1042,14 @@
// copy rather than the one in AudioFlinger. This optimization saves a lock.
bool mMasterMute;
void setMasterMute_l(bool muted) { mMasterMute = muted; }
+
+ auto discontinuityForStandbyOrFlush() const { // call on threadLoop or with lock.
+ return ((mType == DIRECT && !audio_is_linear_pcm(mFormat))
+ || mType == OFFLOAD)
+ ? mTimestampVerifier.DISCONTINUITY_MODE_ZERO
+ : mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS;
+ }
+
protected:
ActiveTracks<Track> mActiveTracks;
@@ -1075,6 +1096,8 @@
void updateMetadata_l() final;
virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata);
+ void collectTimestamps_l();
+
// The Tracks class manages tracks added and removed from the Thread.
template <typename T>
class Tracks {
@@ -1186,7 +1209,7 @@
Mutex mAudioTrackCbLock;
// Record of IAudioTrackCallback
- std::set<sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
+ std::map<sp<Track>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
private:
// The HAL output sink is treated as non-blocking, but current implementation is blocking
@@ -1217,6 +1240,10 @@
// volumes last sent to audio HAL with stream->setVolume()
float mLeftVolFloat;
float mRightVolFloat;
+
+ // audio patch used by the downstream software patch.
+ // Only used if ThreadBase::mIsMsdDevice is true.
+ struct audio_patch mDownStreamPatch;
};
class MixerThread : public PlaybackThread {
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 01d5345..38dab5b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -253,6 +253,8 @@
// Called to tally underrun frames in playback.
virtual void tallyUnderrunFrames(size_t /* frames */) {}
+ audio_channel_mask_t channelMask() const { return mChannelMask; }
+
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -278,8 +280,6 @@
size_t frameSize() const { return mFrameSize; }
- audio_channel_mask_t channelMask() const { return mChannelMask; }
-
virtual uint32_t sampleRate() const { return mSampleRate; }
bool isStopped() const {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index d366bb7..fb43a6e 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -54,6 +54,60 @@
namespace android {
+// Validation methods for input
+namespace {
+
+status_t validateAudioDescriptionMixLevel(float leveldB)
+{
+ constexpr float MAX_AUDIO_DESCRIPTION_MIX_LEVEL = 48.f;
+ return std::isnan(leveldB) || leveldB > MAX_AUDIO_DESCRIPTION_MIX_LEVEL ? BAD_VALUE : OK;
+}
+
+status_t validateDualMonoMode(audio_dual_mono_mode_t dualMonoMode)
+{
+ switch (dualMonoMode) {
+ case AUDIO_DUAL_MONO_MODE_OFF:
+ case AUDIO_DUAL_MONO_MODE_LR:
+ case AUDIO_DUAL_MONO_MODE_LL:
+ case AUDIO_DUAL_MONO_MODE_RR:
+ return OK;
+ }
+ return BAD_VALUE;
+}
+
+status_t validatePlaybackRateFallbackMode(
+ audio_timestretch_fallback_mode_t fallbackMode)
+{
+ switch (fallbackMode) {
+ case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+ break; // warning if not listed.
+ case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+ case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+ case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+ return OK;
+ }
+ return BAD_VALUE;
+}
+
+status_t validatePlaybackRateStretchMode(audio_timestretch_stretch_mode_t stretchMode)
+{
+ switch (stretchMode) {
+ case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+ case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+ return OK;
+ }
+ return BAD_VALUE;
+}
+
+status_t validatePlaybackRate(const audio_playback_rate_t& playbackRate)
+{
+ if (playbackRate.mSpeed < 0.f || playbackRate.mPitch < 0.f) return BAD_VALUE;
+ return validatePlaybackRateFallbackMode(playbackRate.mFallbackMode) ?:
+ validatePlaybackRateStretchMode(playbackRate.mStretchMode);
+}
+
+} // namespace
+
using media::VolumeShaper;
// ----------------------------------------------------------------------------
// TrackBase
@@ -367,12 +421,45 @@
return mTrack->getTimestamp(timestamp);
}
-
void AudioFlinger::TrackHandle::signal()
{
return mTrack->signal();
}
+status_t AudioFlinger::TrackHandle::getDualMonoMode(audio_dual_mono_mode_t* mode)
+{
+ return mTrack->getDualMonoMode(mode);
+}
+
+status_t AudioFlinger::TrackHandle::setDualMonoMode(audio_dual_mono_mode_t mode)
+{
+ return validateDualMonoMode(mode) ?: mTrack->setDualMonoMode(mode);
+}
+
+status_t AudioFlinger::TrackHandle::getAudioDescriptionMixLevel(float* leveldB)
+{
+ return mTrack->getAudioDescriptionMixLevel(leveldB);
+}
+
+status_t AudioFlinger::TrackHandle::setAudioDescriptionMixLevel(float leveldB)
+{
+ return validateAudioDescriptionMixLevel(leveldB)
+ ?: mTrack->setAudioDescriptionMixLevel(leveldB);
+}
+
+status_t AudioFlinger::TrackHandle::getPlaybackRateParameters(
+ audio_playback_rate_t* playbackRate)
+{
+ return mTrack->getPlaybackRateParameters(playbackRate);
+}
+
+status_t AudioFlinger::TrackHandle::setPlaybackRateParameters(
+ const audio_playback_rate_t& playbackRate)
+{
+ return validatePlaybackRate(playbackRate)
+ ?: mTrack->setPlaybackRateParameters(playbackRate);
+}
+
status_t AudioFlinger::TrackHandle::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
@@ -386,11 +473,12 @@
// static
sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
- uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType)
+ uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType,
+ const std::string& opPackageName)
{
+ Vector <String16> packages;
+ getPackagesForUid(uid, packages);
if (isServiceUid(uid)) {
- Vector <String16> packages;
- getPackagesForUid(uid, packages);
if (packages.isEmpty()) {
ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
id,
@@ -410,12 +498,32 @@
id, attr.flags);
return nullptr;
}
- return new OpPlayAudioMonitor(uid, attr.usage, id);
+
+ String16 opPackageNameStr(opPackageName.c_str());
+ if (opPackageName.empty()) {
+ // If no package name is provided by the client, use the first associated with the uid
+ if (!packages.isEmpty()) {
+ opPackageNameStr = packages[0];
+ }
+ } else {
+ // If the provided package name is invalid, we force app ops denial by clearing the package
+ // name passed to OpPlayAudioMonitor
+ if (std::find_if(packages.begin(), packages.end(),
+ [&opPackageNameStr](const auto& package) {
+ return opPackageNameStr == package; }) == packages.end()) {
+ ALOGW("The package name(%s) provided does not correspond to the uid %d, "
+ "force muting the track", opPackageName.c_str(), uid);
+ // Set package name as an empty string so that hasOpPlayAudio will always return false.
+ opPackageNameStr = String16("");
+ }
+ }
+ return new OpPlayAudioMonitor(uid, attr.usage, id, opPackageNameStr);
}
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
- uid_t uid, audio_usage_t usage, int id)
- : mHasOpPlayAudio(true), mUid(uid), mUsage((int32_t) usage), mId(id)
+ uid_t uid, audio_usage_t usage, int id, const String16& opPackageName)
+ : mHasOpPlayAudio(true), mUid(uid), mUsage((int32_t) usage), mId(id),
+ mOpPackageName(opPackageName)
{
}
@@ -429,11 +537,10 @@
void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
{
- getPackagesForUid(mUid, mPackages);
checkPlayAudioForUsage();
- if (!mPackages.isEmpty()) {
+ if (mOpPackageName.size() != 0) {
mOpCallback = new PlayAudioOpCallback(this);
- mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackages[0], mOpCallback);
+ mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mOpPackageName, mOpCallback);
}
}
@@ -446,18 +553,11 @@
// - not called from PlayAudioOpCallback because the callback is not installed in this case
void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage()
{
- if (mPackages.isEmpty()) {
+ if (mOpPackageName.size() == 0) {
mHasOpPlayAudio.store(false);
} else {
- bool hasIt = true;
- for (const String16& packageName : mPackages) {
- const int32_t mode = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO,
- mUsage, mUid, packageName);
- if (mode != AppOpsManager::MODE_ALLOWED) {
- hasIt = false;
- break;
- }
- }
+ bool hasIt = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO,
+ mUsage, mUid, mOpPackageName) == AppOpsManager::MODE_ALLOWED;
ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasIt ? "not " : "");
mHasOpPlayAudio.store(hasIt);
}
@@ -511,7 +611,8 @@
audio_output_flags_t flags,
track_type type,
audio_port_handle_t portId,
- size_t frameCountToBeReady)
+ size_t frameCountToBeReady,
+ const std::string opPackageName)
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -534,9 +635,9 @@
mPresentationCompleteFrames(0),
mFrameMap(16 /* sink-frame-to-track-frame map memory */),
mVolumeHandler(new media::VolumeHandler(sampleRate)),
- mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
+ mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(
+ uid, attr, id(), streamType, opPackageName)),
// mSinkTimestamp
- mFrameCountToBeReady(frameCountToBeReady),
mFastIndex(-1),
mCachedVolume(1.0),
/* The track might not play immediately after being active, similarly as if its volume was 0.
@@ -570,6 +671,7 @@
mFrameSize, sampleRate);
}
mServerProxy = mAudioTrackServerProxy;
+ mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
// only allocate a fast track index if we were able to allocate a normal track name
if (flags & AUDIO_OUTPUT_FLAG_FAST) {
@@ -598,7 +700,7 @@
if (channelMask & AUDIO_CHANNEL_HAPTIC_ALL) {
mAudioVibrationController = new AudioVibrationController(this);
mExternalVibration = new os::ExternalVibration(
- mUid, "" /* pkg */, mAttr, mAudioVibrationController);
+ mUid, opPackageName, mAttr, mAudioVibrationController);
}
// Once this item is logged by the server, the client can add properties.
@@ -897,7 +999,10 @@
}
size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
- size_t framesToBeReady = std::min(mFrameCountToBeReady, bufferSizeInFrames);
+ // Note: mServerProxy->getStartThresholdInFrames() is clamped.
+ const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
+ const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
+ std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
@@ -936,6 +1041,11 @@
// initial state-stopping. next state-pausing.
// What if resume is called ?
+ if (state == FLUSHED) {
+ // avoid underrun glitches when starting after flush
+ reset();
+ }
+
if (state == PAUSED || state == PAUSING) {
if (mResumeToStopping) {
// happened we need to resume to STOPPING_1
@@ -1251,11 +1361,15 @@
void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
{
- *backInserter++ = {
+ playback_track_metadata_v7_t metadata;
+ metadata.base = {
.usage = mAttr.usage,
.content_type = mAttr.content_type,
.gain = mFinalVolume,
};
+ metadata.channel_mask = mChannelMask,
+ strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ *backInserter++ = metadata;
}
void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {
@@ -1437,6 +1551,108 @@
}
}
+status_t AudioFlinger::PlaybackThread::Track::getDualMonoMode(audio_dual_mono_mode_t* mode)
+{
+ status_t status = INVALID_OPERATION;
+ if (isOffloadedOrDirect()) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != nullptr) {
+ PlaybackThread *t = (PlaybackThread *)thread.get();
+ Mutex::Autolock _l(t->mLock);
+ status = t->mOutput->stream->getDualMonoMode(mode);
+ ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
+ "%s: mode %d inconsistent", __func__, mDualMonoMode);
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::setDualMonoMode(audio_dual_mono_mode_t mode)
+{
+ status_t status = INVALID_OPERATION;
+ if (isOffloadedOrDirect()) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != nullptr) {
+ auto t = static_cast<PlaybackThread *>(thread.get());
+ Mutex::Autolock lock(t->mLock);
+ status = t->mOutput->stream->setDualMonoMode(mode);
+ if (status == NO_ERROR) {
+ mDualMonoMode = mode;
+ }
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::getAudioDescriptionMixLevel(float* leveldB)
+{
+ status_t status = INVALID_OPERATION;
+ if (isOffloadedOrDirect()) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != nullptr) {
+ auto t = static_cast<PlaybackThread *>(thread.get());
+ Mutex::Autolock lock(t->mLock);
+ status = t->mOutput->stream->getAudioDescriptionMixLevel(leveldB);
+ ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
+ "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::setAudioDescriptionMixLevel(float leveldB)
+{
+ status_t status = INVALID_OPERATION;
+ if (isOffloadedOrDirect()) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != nullptr) {
+ auto t = static_cast<PlaybackThread *>(thread.get());
+ Mutex::Autolock lock(t->mLock);
+ status = t->mOutput->stream->setAudioDescriptionMixLevel(leveldB);
+ if (status == NO_ERROR) {
+ mAudioDescriptionMixLevel = leveldB;
+ }
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::getPlaybackRateParameters(
+ audio_playback_rate_t* playbackRate)
+{
+ status_t status = INVALID_OPERATION;
+ if (isOffloadedOrDirect()) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != nullptr) {
+ auto t = static_cast<PlaybackThread *>(thread.get());
+ Mutex::Autolock lock(t->mLock);
+ status = t->mOutput->stream->getPlaybackRateParameters(playbackRate);
+ ALOGD_IF((status == NO_ERROR) &&
+ !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
+ "%s: playbackRate inconsistent", __func__);
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::setPlaybackRateParameters(
+ const audio_playback_rate_t& playbackRate)
+{
+ status_t status = INVALID_OPERATION;
+ if (isOffloadedOrDirect()) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != nullptr) {
+ auto t = static_cast<PlaybackThread *>(thread.get());
+ Mutex::Autolock lock(t->mLock);
+ status = t->mOutput->stream->setPlaybackRateParameters(playbackRate);
+ if (status == NO_ERROR) {
+ mPlaybackRateParameters = playbackRate;
+ }
+ }
+ }
+ return status;
+}
+
//To be called with thread lock held
bool AudioFlinger::PlaybackThread::Track::isResumePending() {
@@ -2226,7 +2442,8 @@
RecordThread *recordThread = (RecordThread *)thread.get();
return recordThread->start(this, event, triggerSession);
} else {
- return BAD_VALUE;
+ ALOGW("%s track %d: thread was destroyed", __func__, portId());
+ return DEAD_OBJECT;
}
}
diff --git a/services/audiopolicy/Android.bp b/services/audiopolicy/Android.bp
index a42b89f..e018dd3 100644
--- a/services/audiopolicy/Android.bp
+++ b/services/audiopolicy/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudiopolicymanager_interface_headers",
host_supported: true,
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 8d0e5db..93819f5 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -250,12 +250,12 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
- virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ virtual status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices)
= 0;
virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
virtual status_t setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices) = 0;
+ const AudioDeviceTypeAddrVector& devices) = 0;
virtual status_t removeUserIdDeviceAffinities(int userId) = 0;
virtual status_t startAudioSource(const struct audio_port_config *source,
@@ -295,13 +295,36 @@
virtual bool isCallScreenModeSupported() = 0;
- virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device) = 0;
+ virtual status_t setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
- virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
+ virtual status_t removeDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role) = 0;
- virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device) = 0;
+
+ virtual status_t getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices) = 0;
+
+ virtual status_t setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
+
+ virtual status_t addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
+
+ virtual status_t removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector& devices) = 0;
+
+ virtual status_t clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role) = 0;
+
+ virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices) = 0;
};
diff --git a/services/audiopolicy/common/Android.bp b/services/audiopolicy/common/Android.bp
index 6e0d2f6..91701ad 100644
--- a/services/audiopolicy/common/Android.bp
+++ b/services/audiopolicy/common/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudiopolicycommon",
header_libs: [
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 57f0b5b..227c2d8 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_static {
name: "libaudiopolicycomponents",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 39d1140..1d9223e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -498,11 +498,6 @@
*/
bool isA2dpOffloadedOnPrimary() const;
- /**
- * returns true if A2DP is supported (either via hardware offload or software encoding)
- */
- bool isA2dpSupported() const;
-
sp<SwAudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
sp<SwAudioOutputDescriptor> getPrimaryOutput() const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 395bc70..cf1f64c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -33,6 +33,15 @@
namespace android {
+// This class gathers together various bits of AudioPolicyManager
+// configuration, which are usually filled out as a result of parsing
+// the audio_policy_configuration.xml file.
+//
+// Note that AudioPolicyConfig doesn't own some of the data,
+// it simply proxies access to the fields of AudioPolicyManager
+// class. Be careful about the fields that are references,
+// e.g. 'mOutputDevices'. This also means that it's impossible
+// to implement "deep copying" of this class without re-designing it.
class AudioPolicyConfig
{
public:
@@ -40,14 +49,24 @@
DeviceVector &outputDevices,
DeviceVector &inputDevices,
sp<DeviceDescriptor> &defaultOutputDevice)
- : mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix),
- mHwModules(hwModules),
+ : mHwModules(hwModules),
mOutputDevices(outputDevices),
mInputDevices(inputDevices),
- mDefaultOutputDevice(defaultOutputDevice),
- mIsSpeakerDrcEnabled(false),
- mIsCallScreenModeSupported(false)
- {}
+ mDefaultOutputDevice(defaultOutputDevice) {
+ clear();
+ }
+
+ void clear() {
+ mSource = {};
+ mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
+ mHwModules.clear();
+ mOutputDevices.clear();
+ mInputDevices.clear();
+ mDefaultOutputDevice.clear();
+ mIsSpeakerDrcEnabled = false;
+ mIsCallScreenModeSupported = false;
+ mSurroundFormats.clear();
+ }
const std::string& getSource() const {
return mSource;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index b82305d..c6bdb04 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -101,7 +101,7 @@
* An example of failure is when there are already rules in place to restrict
* a mix to the given uid (i.e. when a MATCH_UID rule was set for it).
*/
- status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+ status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices);
status_t removeUidDeviceAffinities(uid_t uid);
status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
@@ -115,7 +115,7 @@
* An example of failure is when there are already rules in place to restrict
* a mix to the given userId (i.e. when a MATCH_USERID rule was set for it).
*/
- status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+ status_t setUserIdDeviceAffinities(int userId, const AudioDeviceTypeAddrVector& devices);
status_t removeUserIdDeviceAffinities(int userId);
status_t getDevicesForUserId(int userId, Vector<AudioDeviceTypeAddr>& devices) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 923310c..ce97748 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -195,10 +195,18 @@
~SourceClientDescriptor() override = default;
+ void connect(audio_patch_handle_t patchHandle, const sp<DeviceDescriptor>& sinkDevice) {
+ mPatchHandle = patchHandle;
+ mSinkDevice = sinkDevice;
+ }
+ void disconnect() {
+ mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+ mSinkDevice = nullptr;
+ }
+ bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
- void setPatchHandle(audio_patch_handle_t patchHandle) { mPatchHandle = patchHandle; }
-
sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
+ sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; }
wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
@@ -210,6 +218,7 @@
private:
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
const sp<DeviceDescriptor> mSrcDevice;
+ sp<DeviceDescriptor> mSinkDevice;
wp<SwAudioOutputDescriptor> mSwOutput;
wp<HwAudioOutputDescriptor> mHwOutput;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 016aaa5..ca29591 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -151,6 +151,15 @@
// 4) the combination of all devices is invalid for selection
sp<DeviceDescriptor> getDeviceForOpening() const;
+ // Return the device descriptor that matches the given AudioDeviceTypeAddr
+ sp<DeviceDescriptor> getDeviceFromDeviceTypeAddr(
+ const AudioDeviceTypeAddr& deviceTypeAddr) const;
+
+ // Return the device vector that contains device descriptor whose AudioDeviceTypeAddr appears
+ // in the given AudioDeviceTypeAddrVector
+ DeviceVector getDevicesFromDeviceTypeAddrVec(
+ const AudioDeviceTypeAddrVector& deviceTypeAddrVector) const;
+
// If there are devices with the given type and the devices to add is not empty,
// remove all the devices with the given type and add all the devices to add.
void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index b5b10f3..9ba745a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -52,8 +52,12 @@
devices.merge(mDynamicDevices);
return devices;
}
+ std::string getTagForDevice(audio_devices_t device,
+ const String8 &address = String8(),
+ audio_format_t codec = AUDIO_FORMAT_DEFAULT);
void addDynamicDevice(const sp<DeviceDescriptor> &device)
{
+ device->setDynamic();
mDynamicDevices.add(device);
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/Serializer.h b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
index 48c4147..b70c595 100644
--- a/services/audiopolicy/common/managerdefinitions/include/Serializer.h
+++ b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
@@ -21,5 +21,9 @@
namespace android {
status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config);
+// In VTS mode all vendor extensions are ignored. This is done because
+// VTS tests are built using AOSP code and thus can not use vendor overlays
+// of system libraries.
+status_t deserializeAudioPolicyFileForVts(const char *fileName, AudioPolicyConfig *config);
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index a2e2eec..5c47d1b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -505,6 +505,9 @@
lConfig.offload_info.duration_us = -1;
lConfig.offload_info.has_video = true; // conservative
lConfig.offload_info.is_streaming = true; // likely
+ lConfig.offload_info.encapsulation_mode = lConfig.offload_info.encapsulation_mode;
+ lConfig.offload_info.content_id = lConfig.offload_info.content_id;
+ lConfig.offload_info.sync_id = lConfig.offload_info.sync_id;
}
mFlags = (audio_output_flags_t)(mFlags | flags);
@@ -764,11 +767,6 @@
return false;
}
-bool SwAudioOutputCollection::isA2dpSupported() const
-{
- return (isA2dpOffloadedOnPrimary() || (getA2dpOutput() != 0));
-}
-
sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
{
for (size_t i = 0; i < size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index b6de4be..fc1d0e2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -463,7 +463,7 @@
}
status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
- const Vector<AudioDeviceTypeAddr>& devices) {
+ const AudioDeviceTypeAddrVector& devices) {
// verify feasibility: for each player mix: if it already contains a
// "match uid" rule for this uid, return an error
// (adding a uid-device affinity would result in contradictory rules)
@@ -565,7 +565,7 @@
}
status_t AudioPolicyMixCollection::setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices) {
+ const AudioDeviceTypeAddrVector& devices) {
// verify feasibility: for each player mix: if it already contains a
// "match userId" rule for this userId, return an error
// (adding a userId-device affinity would result in contradictory rules)
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 5120aeb..f6859c7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -49,11 +49,13 @@
{
}
+// Let DeviceDescriptorBase initialize the address since it handles specific cases like
+// legacy remote submix where "0" is added as default address.
DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
const std::string &tagName,
const FormatVector &encodedFormats) :
DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats),
- mDeclaredAddress(deviceTypeAddr.getAddress())
+ mDeclaredAddress(DeviceDescriptorBase::address())
{
mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
/* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
@@ -380,7 +382,7 @@
if (isEmpty()) {
// Return nullptr if this collection is empty.
return nullptr;
- } else if (areAllOfSameDeviceType(types(), audio_is_input_device)) {
+ } else if (areAllOfSameDeviceType(types(), audio_call_is_input_device)) {
// For input case, return the first one when there is only one device.
return size() > 1 ? nullptr : *begin();
} else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
@@ -393,6 +395,24 @@
return nullptr;
}
+sp<DeviceDescriptor> DeviceVector::getDeviceFromDeviceTypeAddr(
+ const AudioDeviceTypeAddr& deviceTypeAddr) const {
+ return getDevice(deviceTypeAddr.mType, String8(deviceTypeAddr.getAddress()),
+ AUDIO_FORMAT_DEFAULT);
+}
+
+DeviceVector DeviceVector::getDevicesFromDeviceTypeAddrVec(
+ const AudioDeviceTypeAddrVector& deviceTypeAddrVector) const {
+ DeviceVector devices;
+ for (const auto& deviceTypeAddr : deviceTypeAddrVector) {
+ sp<DeviceDescriptor> device = getDeviceFromDeviceTypeAddr(deviceTypeAddr);
+ if (device != nullptr) {
+ devices.add(device);
+ }
+ }
+ return devices;
+}
+
void DeviceVector::replaceDevicesByType(
audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 2967014..3a143b0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -41,6 +41,14 @@
}
}
+std::string HwModule::getTagForDevice(audio_devices_t device, const String8 &address,
+ audio_format_t codec)
+{
+ DeviceVector declaredDevices = getDeclaredDevices();
+ sp<DeviceDescriptor> deviceDesc = declaredDevices.getDevice(device, address, codec);
+ return deviceDesc ? deviceDesc->getTagName() : std::string{};
+}
+
status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address)
{
@@ -49,7 +57,8 @@
profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
config->sample_rate));
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, "" /*tagName*/, address.string());
+ sp<DeviceDescriptor> devDesc =
+ new DeviceDescriptor(device, getTagForDevice(device), address.string());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@@ -116,7 +125,8 @@
profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
config->sample_rate));
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, "" /*tagName*/, address.string());
+ sp<DeviceDescriptor> devDesc =
+ new DeviceDescriptor(device, getTagForDevice(device), address.string());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index bf1a0f7..ae92b40 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "APM::IOProfile"
//#define LOG_NDEBUG 0
-#include <system/audio-base.h>
+#include <system/audio.h>
#include "IOProfile.h"
#include "HwModule.h"
#include "TypeConverter.h"
@@ -112,12 +112,11 @@
dst->append(portStr.c_str());
dst->appendFormat(" - flags: 0x%04x", getFlags());
- std::string flagsLiteral;
- if (getRole() == AUDIO_PORT_ROLE_SINK) {
- InputFlagConverter::maskToString(getFlags(), flagsLiteral);
- } else if (getRole() == AUDIO_PORT_ROLE_SOURCE) {
- OutputFlagConverter::maskToString(getFlags(), flagsLiteral);
- }
+ std::string flagsLiteral =
+ getRole() == AUDIO_PORT_ROLE_SINK ?
+ toString(static_cast<audio_input_flags_t>(getFlags())) :
+ getRole() == AUDIO_PORT_ROLE_SOURCE ?
+ toString(static_cast<audio_output_flags_t>(getFlags())) : "";
if (!flagsLiteral.empty()) {
dst->appendFormat(" (%s)", flagsLiteral.c_str());
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 883e713..562c213 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -20,8 +20,8 @@
#include <memory>
#include <string>
#include <utility>
+#include <variant>
-#include <hidl/Status.h>
#include <libxml/parser.h>
#include <libxml/xinclude.h>
#include <media/convert.h>
@@ -36,11 +36,14 @@
namespace {
-// TODO(mnaganov): Consider finding an alternative for using HIDL code.
-using hardware::Return;
-using hardware::Status;
using utilities::convertTo;
+static inline bool maybeVendorExtension(const std::string& s) {
+ // Only checks whether the string starts with the "vendor prefix".
+ static const std::string vendorPrefix = "VX_";
+ return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
+}
+
template<typename E, typename C>
struct AndroidCollectionTraits {
typedef sp<E> Element;
@@ -89,7 +92,6 @@
};
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
// No children
};
@@ -106,8 +108,6 @@
static constexpr const char *format = "format";
static constexpr const char *channelMasks = "channelMasks";
};
-
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
};
struct MixPortTraits : public AndroidCollectionTraits<IOProfile, IOProfileCollection>
@@ -125,7 +125,6 @@
static constexpr const char *maxActiveCount = "maxActiveCount";
};
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
// Children: GainTraits
};
@@ -147,7 +146,6 @@
static constexpr const char *encodedFormats = "encodedFormats";
};
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
// Children: GainTraits (optional)
};
@@ -166,8 +164,6 @@
};
typedef HwModule *PtrSerializingCtx;
-
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
};
struct ModuleTraits : public AndroidCollectionTraits<HwModule, HwModuleCollection>
@@ -187,13 +183,14 @@
typedef AudioPolicyConfig *PtrSerializingCtx;
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
// Children: mixPortTraits, devicePortTraits, and routeTraits
// Need to call deserialize on each child
};
struct GlobalConfigTraits
{
+ typedef std::monostate Element;
+
static constexpr const char *tag = "globalConfiguration";
struct Attributes
@@ -203,14 +200,16 @@
static constexpr const char *engineLibrarySuffix = "engine_library";
};
- static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
+ typedef AudioPolicyConfig *PtrSerializingCtx;
};
struct SurroundSoundTraits
{
+ typedef std::monostate Element;
+
static constexpr const char *tag = "surroundSound";
- static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
+ typedef AudioPolicyConfig *PtrSerializingCtx;
// Children: SurroundSoundFormatTraits
};
@@ -224,28 +223,32 @@
static constexpr const char *name = "name";
static constexpr const char *subformats = "subformats";
};
-
- static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
};
class PolicySerializer
{
public:
- PolicySerializer() : mVersion{std::to_string(gMajor) + "." + std::to_string(gMinor)}
- {
- ALOGV("%s: Version=%s Root=%s", __func__, mVersion.c_str(), rootName);
- }
- status_t deserialize(const char *configFile, AudioPolicyConfig *config);
+ status_t deserialize(const char *configFile, AudioPolicyConfig *config,
+ bool ignoreVendorExtensions = false);
+
+ template <class Trait>
+ status_t deserializeCollection(const xmlNode *cur,
+ typename Trait::Collection *collection,
+ typename Trait::PtrSerializingCtx serializingContext);
+ template <class Trait>
+ std::variant<status_t, typename Trait::Element> deserialize(const xmlNode *cur,
+ typename Trait::PtrSerializingCtx serializingContext);
private:
static constexpr const char *rootName = "audioPolicyConfiguration";
static constexpr const char *versionAttribute = "version";
- static constexpr uint32_t gMajor = 1; /**< the major number of the policy xml format version. */
- static constexpr uint32_t gMinor = 0; /**< the minor number of the policy xml format version. */
typedef AudioPolicyConfig Element;
- const std::string mVersion;
+ bool mIgnoreVendorExtensions = false;
+ std::string mChannelMasksSeparator = ",";
+ std::string mSamplingRatesSeparator = ",";
+ std::string mFlagsSeparator = "|";
// Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
};
@@ -254,9 +257,8 @@
constexpr void (*xmlDeleter)(T* t);
template <>
constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
-// http://b/111067277 - Add back constexpr when we switch to C++17.
template <>
-auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
+constexpr auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
/** @return a unique_ptr with the correct deleter for the libxml2 object. */
template <class T>
@@ -296,7 +298,7 @@
}
template <class Trait>
-status_t deserializeCollection(const xmlNode *cur,
+status_t PolicySerializer::deserializeCollection(const xmlNode *cur,
typename Trait::Collection *collection,
typename Trait::PtrSerializingCtx serializingContext)
{
@@ -309,14 +311,17 @@
}
for (; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
- auto element = Trait::deserialize(child, serializingContext);
- if (element.isOk()) {
- status_t status = Trait::addElementToCollection(element, collection);
+ auto maybeElement = deserialize<Trait>(child, serializingContext);
+ if (maybeElement.index() == 1) {
+ status_t status = Trait::addElementToCollection(
+ std::get<1>(maybeElement), collection);
if (status != NO_ERROR) {
ALOGE("%s: could not add element to %s collection", __func__,
Trait::collectionTag);
return status;
}
+ } else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) {
+ // Skip a vendor extension element.
} else {
return BAD_VALUE;
}
@@ -329,15 +334,18 @@
return NO_ERROR;
}
-Return<AudioGainTraits::Element> AudioGainTraits::deserialize(const xmlNode *cur,
- PtrSerializingCtx /*serializingContext*/)
+template<>
+std::variant<status_t, AudioGainTraits::Element> PolicySerializer::deserialize<AudioGainTraits>(
+ const xmlNode *cur, AudioGainTraits::PtrSerializingCtx /*serializingContext*/)
{
+ using Attributes = AudioGainTraits::Attributes;
+
static uint32_t index = 0;
- Element gain = new AudioGain(index++, true);
+ AudioGainTraits::Element gain = new AudioGain(index++, true);
std::string mode = getXmlAttribute(cur, Attributes::mode);
if (!mode.empty()) {
- gain->setMode(GainModeConverter::maskFromString(mode));
+ gain->setMode(GainModeConverter::maskFromString(mode, " "));
}
std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask);
@@ -392,20 +400,28 @@
if (gain->getMode() != 0) {
return gain;
} else {
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
}
-Return<AudioProfileTraits::Element> AudioProfileTraits::deserialize(const xmlNode *cur,
- PtrSerializingCtx /*serializingContext*/)
+template<>
+std::variant<status_t, AudioProfileTraits::Element>
+PolicySerializer::deserialize<AudioProfileTraits>(
+ const xmlNode *cur, AudioProfileTraits::PtrSerializingCtx /*serializingContext*/)
{
+ using Attributes = AudioProfileTraits::Attributes;
+
std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);
std::string format = getXmlAttribute(cur, Attributes::format);
std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
- Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
- channelMasksFromString(channels, ","),
- samplingRatesFromString(samplingRates, ","));
+ if (mIgnoreVendorExtensions && maybeVendorExtension(format)) {
+ ALOGI("%s: vendor extension format \"%s\" skipped", __func__, format.c_str());
+ return NO_INIT;
+ }
+ AudioProfileTraits::Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
+ channelMasksFromString(channels, mChannelMasksSeparator.c_str()),
+ samplingRatesFromString(samplingRates, mSamplingRatesSeparator.c_str()));
profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
profile->setDynamicChannels(profile->getChannels().empty());
@@ -414,30 +430,33 @@
return profile;
}
-Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child,
- PtrSerializingCtx /*serializingContext*/)
+template<>
+std::variant<status_t, MixPortTraits::Element> PolicySerializer::deserialize<MixPortTraits>(
+ const xmlNode *child, MixPortTraits::PtrSerializingCtx /*serializingContext*/)
{
+ using Attributes = MixPortTraits::Attributes;
+
std::string name = getXmlAttribute(child, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
- ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str());
+ ALOGV("%s: %s %s=%s", __func__, MixPortTraits::tag, Attributes::name, name.c_str());
std::string role = getXmlAttribute(child, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::role);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: Role=%s", __func__, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
- Element mixPort = new IOProfile(name, portRole);
+ MixPortTraits::Element mixPort = new IOProfile(name, portRole);
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
@@ -451,10 +470,10 @@
if (!flags.empty()) {
// Source role
if (portRole == AUDIO_PORT_ROLE_SOURCE) {
- mixPort->setFlags(OutputFlagConverter::maskFromString(flags));
+ mixPort->setFlags(OutputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str()));
} else {
// Sink role
- mixPort->setFlags(InputFlagConverter::maskFromString(flags));
+ mixPort->setFlags(InputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str()));
}
}
std::string maxOpenCount = getXmlAttribute(child, Attributes::maxOpenCount);
@@ -469,43 +488,51 @@
AudioGainTraits::Collection gains;
status = deserializeCollection<AudioGainTraits>(child, &gains, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
mixPort->setGains(gains);
return mixPort;
}
-Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *cur,
- PtrSerializingCtx /*serializingContext*/)
+template<>
+std::variant<status_t, DevicePortTraits::Element> PolicySerializer::deserialize<DevicePortTraits>(
+ const xmlNode *cur, DevicePortTraits::PtrSerializingCtx /*serializingContext*/)
{
+ using Attributes = DevicePortTraits::Attributes;
+ auto& tag = DevicePortTraits::tag;
+
std::string name = getXmlAttribute(cur, Attributes::tagName);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::tagName);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str());
std::string typeName = getXmlAttribute(cur, Attributes::type);
if (typeName.empty()) {
ALOGE("%s: no type for %s", __func__, name.c_str());
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str());
std::string role = getXmlAttribute(cur, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::role);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
+ if (mIgnoreVendorExtensions && maybeVendorExtension(typeName)) {
+ ALOGI("%s: vendor extension device type \"%s\" skipped", __func__, typeName.c_str());
+ return NO_INIT;
+ }
audio_devices_t type = AUDIO_DEVICE_NONE;
- if (!deviceFromString(typeName, type) ||
+ if (!DeviceConverter::fromString(typeName, type) ||
(!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
(!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
ALOGW("%s: bad type %08x", __func__, type);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
@@ -514,12 +541,13 @@
encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
}
std::string address = getXmlAttribute(cur, Attributes::address);
- Element deviceDesc = new DeviceDescriptor(type, name, address, encodedFormats);
+ DevicePortTraits::Element deviceDesc =
+ new DeviceDescriptor(type, name, address, encodedFormats);
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
@@ -532,43 +560,51 @@
// Deserialize AudioGain children
status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
ALOGV("%s: adding device tag %s type %08x address %s", __func__,
deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
return deviceDesc;
}
-Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx)
+template<>
+std::variant<status_t, RouteTraits::Element> PolicySerializer::deserialize<RouteTraits>(
+ const xmlNode *cur, RouteTraits::PtrSerializingCtx ctx)
{
+ using Attributes = RouteTraits::Attributes;
+
std::string type = getXmlAttribute(cur, Attributes::type);
if (type.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::type);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
audio_route_type_t routeType = (type == Attributes::typeMix) ?
AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
- ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, type.c_str());
- Element route = new AudioRoute(routeType);
+ ALOGV("%s: %s %s=%s", __func__, RouteTraits::tag, Attributes::type, type.c_str());
+ RouteTraits::Element route = new AudioRoute(routeType);
std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);
if (sinkAttr.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::sink);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
// Convert Sink name to port pointer
sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
- if (sink == NULL) {
+ if (sink == NULL && !mIgnoreVendorExtensions) {
ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
+ } else if (sink == NULL) {
+ ALOGW("Skipping route to sink \"%s\" as it likely has vendor extension type",
+ sinkAttr.c_str());
+ return NO_INIT;
}
route->setSink(sink);
std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);
if (sourcesAttr.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::sources);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
// Tokenize and Convert Sources name to port pointer
PolicyAudioPortVector sources;
@@ -578,11 +614,15 @@
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
- if (source == NULL) {
+ if (source == NULL && !mIgnoreVendorExtensions) {
ALOGE("%s: no source found with name=%s", __func__, devTag);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
+ } else if (source == NULL) {
+ ALOGW("Skipping route source \"%s\" as it likely has vendor extension type",
+ devTag);
+ } else {
+ sources.add(source);
}
- sources.add(source);
}
devTag = strtok(NULL, ",");
}
@@ -596,12 +636,20 @@
return route;
}
-Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx)
+template<>
+std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(
+ const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
{
+ using Attributes = ModuleTraits::Attributes;
+ auto& tag = ModuleTraits::tag;
+ auto& childAttachedDevicesTag = ModuleTraits::childAttachedDevicesTag;
+ auto& childAttachedDeviceTag = ModuleTraits::childAttachedDeviceTag;
+ auto& childDefaultOutputDeviceTag = ModuleTraits::childDefaultOutputDeviceTag;
+
std::string name = getXmlAttribute(cur, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
uint32_t versionMajor = 0, versionMinor = 0;
std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
@@ -611,29 +659,29 @@
versionMajor, versionMajor);
}
- ALOGV("%s: %s %s=%s", __func__, tag, Attributes::name, name.c_str());
+ ALOGV("%s: %s %s=%s", __func__, ModuleTraits::tag, Attributes::name, name.c_str());
- Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
+ ModuleTraits::Element module = new HwModule(name.c_str(), versionMajor, versionMinor);
- // Deserialize childrens: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
+ // Deserialize children: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes
MixPortTraits::Collection mixPorts;
status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
module->setProfiles(mixPorts);
DevicePortTraits::Collection devicePorts;
status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
module->setDeclaredDevices(devicePorts);
RouteTraits::Collection routes;
status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
module->setRoutes(routes);
@@ -653,6 +701,12 @@
sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get())));
+ if (device == nullptr && mIgnoreVendorExtensions) {
+ ALOGW("Skipped attached device \"%s\" because it likely uses a vendor"
+ "extension type",
+ reinterpret_cast<const char*>(attachedDevice.get()));
+ continue;
+ }
ctx->addDevice(device);
}
}
@@ -678,10 +732,15 @@
return module;
}
-status_t GlobalConfigTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config)
+template<>
+std::variant<status_t, GlobalConfigTraits::Element>
+PolicySerializer::deserialize<GlobalConfigTraits>(
+ const xmlNode *root, GlobalConfigTraits::PtrSerializingCtx config)
{
+ using Attributes = GlobalConfigTraits::Attributes;
+
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
- if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
+ if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(GlobalConfigTraits::tag))) {
bool value;
std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
if (!attr.empty() &&
@@ -703,12 +762,15 @@
return NO_ERROR;
}
-status_t SurroundSoundTraits::deserialize(const xmlNode *root, AudioPolicyConfig *config)
+template<>
+std::variant<status_t, SurroundSoundTraits::Element>
+PolicySerializer::deserialize<SurroundSoundTraits>(
+ const xmlNode *root, SurroundSoundTraits::PtrSerializingCtx config)
{
config->setDefaultSurroundFormats();
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
- if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
+ if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(SurroundSoundTraits::tag))) {
AudioPolicyConfig::SurroundFormats formats;
status_t status = deserializeCollection<SurroundSoundFormatTraits>(
cur, &formats, nullptr);
@@ -721,20 +783,29 @@
return NO_ERROR;
}
-Return<SurroundSoundFormatTraits::Element> SurroundSoundFormatTraits::deserialize(
- const xmlNode *cur, PtrSerializingCtx /*serializingContext*/)
+template<>
+std::variant<status_t, SurroundSoundFormatTraits::Element>
+PolicySerializer::deserialize<SurroundSoundFormatTraits>(
+ const xmlNode *cur, SurroundSoundFormatTraits::PtrSerializingCtx /*serializingContext*/)
{
+ using Attributes = SurroundSoundFormatTraits::Attributes;
+
std::string formatLiteral = getXmlAttribute(cur, Attributes::name);
if (formatLiteral.empty()) {
ALOGE("%s: No %s found for a surround format", __func__, Attributes::name);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ if (mIgnoreVendorExtensions && maybeVendorExtension(formatLiteral)) {
+ ALOGI("%s: vendor extension format \"%s\" skipped", __func__, formatLiteral.c_str());
+ return NO_INIT;
}
audio_format_t format = formatFromString(formatLiteral);
if (format == AUDIO_FORMAT_DEFAULT) {
ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str());
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
- Element pair = std::make_pair(format, Collection::mapped_type{});
+ SurroundSoundFormatTraits::Element pair = std::make_pair(
+ format, SurroundSoundFormatTraits::Collection::mapped_type{});
std::string subformatsLiteral = getXmlAttribute(cur, Attributes::subformats);
if (subformatsLiteral.empty()) return pair;
@@ -743,14 +814,16 @@
auto result = pair.second.insert(subformat);
if (!result.second) {
ALOGE("%s: could not add subformat %x to collection", __func__, subformat);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
}
return pair;
}
-status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config)
+status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config,
+ bool ignoreVendorExtensions)
{
+ mIgnoreVendorExtensions = ignoreVendorExtensions;
auto doc = make_xmlUnique(xmlParseFile(configFile));
if (doc == nullptr) {
ALOGE("%s: Could not parse %s document.", __func__, configFile);
@@ -776,12 +849,14 @@
ALOGE("%s: No version found in root node %s", __func__, rootName);
return BAD_VALUE;
}
- if (version != mVersion) {
- ALOGE("%s: Version does not match; expect %s got %s", __func__, mVersion.c_str(),
- version.c_str());
+ if (version == "7.0") {
+ mChannelMasksSeparator = mSamplingRatesSeparator = mFlagsSeparator = " ";
+ } else if (version != "1.0") {
+ ALOGE("%s: Version does not match; expected \"1.0\" or \"7.0\" got \"%s\"",
+ __func__, version.c_str());
return BAD_VALUE;
}
- // Lets deserialize children
+ // Let's deserialize children
// Modules
ModuleTraits::Collection modules;
status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);
@@ -791,10 +866,10 @@
config->setHwModules(modules);
// Global Configuration
- GlobalConfigTraits::deserialize(root, config);
+ deserialize<GlobalConfigTraits>(root, config);
// Surround configuration
- SurroundSoundTraits::deserialize(root, config);
+ deserialize<SurroundSoundTraits>(root, config);
return android::OK;
}
@@ -804,7 +879,17 @@
status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
{
PolicySerializer serializer;
- return serializer.deserialize(fileName, config);
+ status_t status = serializer.deserialize(fileName, config);
+ if (status != OK) config->clear();
+ return status;
+}
+
+status_t deserializeAudioPolicyFileForVts(const char *fileName, AudioPolicyConfig *config)
+{
+ PolicySerializer serializer;
+ status_t status = serializer.deserialize(fileName, config, true /*ignoreVendorExtensions*/);
+ if (status != OK) config->clear();
+ return status;
}
} // namespace android
diff --git a/services/audiopolicy/config/Android.bp b/services/audiopolicy/config/Android.bp
index f4610bb..671b30a 100644
--- a/services/audiopolicy/config/Android.bp
+++ b/services/audiopolicy/config/Android.bp
@@ -17,6 +17,15 @@
soong_namespace {
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "a2dp_in_audio_policy_configuration.xml",
vendor: true,
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
index b28381b..dcdc035 100644
--- a/services/audiopolicy/config/audio_policy_configuration.xml
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -91,7 +91,7 @@
<!-- Output devices declaration, i.e. Sink DEVICE PORT -->
<devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
diff --git a/services/audiopolicy/config/audio_policy_configuration_7_0.xml b/services/audiopolicy/config/audio_policy_configuration_7_0.xml
index b30ab30..9961a00 100644
--- a/services/audiopolicy/config/audio_policy_configuration_7_0.xml
+++ b/services/audiopolicy/config/audio_policy_configuration_7_0.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
<!-- Global configuration Decalaration -->
@@ -91,7 +91,7 @@
<!-- Output devices declaration, i.e. Sink DEVICE PORT -->
<devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</devicePort>
<devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
diff --git a/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml b/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
index b4cc1d3..5f4e5f2 100644
--- a/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
+++ b/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
@@ -185,6 +185,9 @@
<!-- Hearing aid Audio HAL -->
<xi:include href="hearing_aid_audio_policy_configuration.xml"/>
+ <!-- Le Audio Audio HAL -->
+ <xi:include href="le_audio_policy_configuration.xml"/>
+
<!-- MSD Audio HAL (optional) -->
<xi:include href="msd_audio_policy_configuration.xml"/>
diff --git a/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml b/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
index ce78eb0..98415b7 100644
--- a/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
@@ -10,6 +10,18 @@
samplingRates="24000,16000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
+ <!-- Le Audio Audio Ports -->
+ <mixPort name="le audio output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+ samplingRates="8000,16000,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000,16000,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<!-- A2DP Audio Ports -->
@@ -30,6 +42,13 @@
</devicePort>
<!-- Hearing AIDs Audio Ports -->
<devicePort tagName="BT Hearing Aid Out" type="AUDIO_DEVICE_OUT_HEARING_AID" role="sink"/>
+ <!-- BLE Audio Ports -->
+ <!-- Note that these device types are not valid in HAL versions < 7. Any device
+ running pre-V7 HAL and using this file will not pass VTS. Need to use
+ bluetooth_audio_policy_configuration_7_0.xml instead.
+ -->
+ <devicePort tagName="BLE Headset Out" type="AUDIO_DEVICE_OUT_BLE_HEADSET" role="sink"/>
+ <devicePort tagName="BLE Speaker Out" type="AUDIO_DEVICE_OUT_BLE_SPEAKER" role="sink"/>
</devicePorts>
<routes>
<route type="mix" sink="BT A2DP Out"
@@ -40,5 +59,9 @@
sources="a2dp output"/>
<route type="mix" sink="BT Hearing Aid Out"
sources="hearing aid output"/>
+ <route type="mix" sink="BLE Headset Out"
+ sources="le audio output"/>
+ <route type="mix" sink="BLE Speaker Out"
+ sources="le audio output"/>
</routes>
</module>
diff --git a/services/audiopolicy/config/bluetooth_audio_policy_configuration_7_0.xml b/services/audiopolicy/config/bluetooth_audio_policy_configuration_7_0.xml
index 2dffe02..fbe7571 100644
--- a/services/audiopolicy/config/bluetooth_audio_policy_configuration_7_0.xml
+++ b/services/audiopolicy/config/bluetooth_audio_policy_configuration_7_0.xml
@@ -10,6 +10,18 @@
samplingRates="24000 16000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
+ <!-- Le Audio Audio Ports -->
+ <mixPort name="le audio output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+ samplingRates="8000 16000 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000 16000 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<!-- A2DP Audio Ports -->
@@ -30,6 +42,9 @@
</devicePort>
<!-- Hearing AIDs Audio Ports -->
<devicePort tagName="BT Hearing Aid Out" type="AUDIO_DEVICE_OUT_HEARING_AID" role="sink"/>
+ <!-- BLE Audio Ports -->
+ <devicePort tagName="BLE Headset Out" type="AUDIO_DEVICE_OUT_BLE_HEADSET" role="sink"/>
+ <devicePort tagName="BLE Speaker Out" type="AUDIO_DEVICE_OUT_BLE_SPEAKER" role="sink"/>
</devicePorts>
<routes>
<route type="mix" sink="BT A2DP Out"
@@ -40,5 +55,9 @@
sources="a2dp output"/>
<route type="mix" sink="BT Hearing Aid Out"
sources="hearing aid output"/>
+ <route type="mix" sink="BLE Headset Out"
+ sources="le audio output"/>
+ <route type="mix" sink="BLE Speaker Out"
+ sources="le audio output"/>
</routes>
</module>
diff --git a/services/audiopolicy/config/le_audio_policy_configuration.xml b/services/audiopolicy/config/le_audio_policy_configuration.xml
new file mode 100644
index 0000000..a3dc72b
--- /dev/null
+++ b/services/audiopolicy/config/le_audio_policy_configuration.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Le Audio HAL Audio Policy Configuration file -->
+<module name="bluetooth" halVersion="2.1">
+ <mixPorts>
+ <mixPort name="le audio output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT,AUDIO_FORMAT_PCM_24_BIT,AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000,16000,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="BLE Headset Out" type="AUDIO_DEVICE_OUT_BLE_HEADSET" role="sink"/>
+ <devicePort tagName="BLE Speaker Out" type="AUDIO_DEVICE_OUT_BLE_SPEAKER" role="sink"/>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="BLE Headset Out" sources="le audio output"/>
+ <route type="mix" sink="BLE Speaker Out" sources="le audio output"/>
+ </routes>
+</module>
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index a1c69f2..50c5eab 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudiopolicyengine_common_headers",
host_supported: true,
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7f339dc..4510f63 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -93,13 +93,13 @@
void dump(String8 *dst) const override;
- status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device) override;
+ status_t setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) override;
- status_t removePreferredDeviceForStrategy(product_strategy_t strategy) override;
+ status_t removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role) override;
- status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device) const override;
+ status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
+ AudioDeviceTypeAddrVector &devices) const override;
engineConfig::ParsingResult loadAudioPolicyEngineConfig();
@@ -127,11 +127,36 @@
status_t restoreOriginVolumeCurve(audio_stream_type_t stream);
+ status_t setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) override;
+
+ status_t addDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) override;
+
+ /**
+ * Remove devices role for capture preset. When `forceMatched` is true, the devices to be
+ * removed must all show as role for the capture preset. Otherwise, only devices that has shown
+ * as role for the capture preset will be remove.
+ */
+ status_t doRemoveDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector& devices,
+ bool forceMatched=true);
+
+ status_t removeDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector& devices) override;
+
+ status_t clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role) override;
+
+ status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role, AudioDeviceTypeAddrVector &devices) const override;
+
private:
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
ProductStrategyPreferredRoutingMap mProductStrategyPreferredDevices;
+ CapturePresetDevicesRoleMap mCapturePresetDevicesRole;
VolumeGroupMap mVolumeGroups;
LastRemovableMediaDevices mLastRemovableMediaDevices;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 3ebe7d1..c505456 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -28,8 +28,11 @@
#include <utils/String8.h>
#include <media/AudioAttributes.h>
#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
+#include <vector>
+
namespace android {
/**
@@ -164,7 +167,8 @@
product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};
-class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t, AudioDeviceTypeAddr>
+class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t,
+ AudioDeviceTypeAddrVector>
{
public:
void dump(String8 *dst, int spaces = 0) const;
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 1bc7fe3..8c7fb97 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -339,8 +339,8 @@
return NO_ERROR;
}
-status_t EngineBase::setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device)
+status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
{
// verify strategy exists
if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
@@ -348,11 +348,24 @@
return BAD_VALUE;
}
- mProductStrategyPreferredDevices[strategy] = device;
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ mProductStrategyPreferredDevices[strategy] = devices;
+ break;
+ case DEVICE_ROLE_DISABLED:
+ // TODO: support set devices role as disabled for strategy.
+ ALOGI("%s no implemented for role as %d", __func__, role);
+ break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as it is no need to set device role as none for a strategy.
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
return NO_ERROR;
}
-status_t EngineBase::removePreferredDeviceForStrategy(product_strategy_t strategy)
+status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
{
// verify strategy exists
if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
@@ -360,29 +373,218 @@
return BAD_VALUE;
}
- if (mProductStrategyPreferredDevices.erase(strategy) == 0) {
- // no preferred device was set
- return NAME_NOT_FOUND;
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ if (mProductStrategyPreferredDevices.erase(strategy) == 0) {
+ // no preferred device was set
+ return NAME_NOT_FOUND;
+ }
+ break;
+ case DEVICE_ROLE_DISABLED:
+ // TODO: support remove devices role as disabled for strategy.
+ ALOGI("%s no implemented for role as %d", __func__, role);
+ break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as it makes no sense to remove devices with
+ // role as DEVICE_ROLE_NONE for a strategy
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
}
return NO_ERROR;
}
-status_t EngineBase::getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device) const
+status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
+ AudioDeviceTypeAddrVector &devices) const
{
// verify strategy exists
if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
ALOGE("%s unknown strategy %u", __func__, strategy);
return BAD_VALUE;
}
- // preferred device for this strategy?
- auto devIt = mProductStrategyPreferredDevices.find(strategy);
- if (devIt == mProductStrategyPreferredDevices.end()) {
- ALOGV("%s no preferred device for strategy %u", __func__, strategy);
- return NAME_NOT_FOUND;
+
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED: {
+ // preferred device for this strategy?
+ auto devIt = mProductStrategyPreferredDevices.find(strategy);
+ if (devIt == mProductStrategyPreferredDevices.end()) {
+ ALOGV("%s no preferred device for strategy %u", __func__, strategy);
+ return NAME_NOT_FOUND;
+ }
+
+ devices = devIt->second;
+ } break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as the DEVICE_ROLE_NONE is never set
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+status_t EngineBase::setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
+{
+ // verify if the audio source is valid
+ if (!audio_is_valid_audio_source(audioSource)) {
+ ALOGE("%s unknown audio source %u", __func__, audioSource);
}
- device = devIt->second;
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ mCapturePresetDevicesRole[audioSource][role] = devices;
+ // When the devices are set as preferred devices, remove them from the disabled devices.
+ doRemoveDevicesRoleForCapturePreset(
+ audioSource, DEVICE_ROLE_DISABLED, devices, false /*forceMatched*/);
+ break;
+ case DEVICE_ROLE_DISABLED:
+ // TODO: support setting devices role as disabled for capture preset.
+ ALOGI("%s no implemented for role as %d", __func__, role);
+ break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as it is no need to set device role as none
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+status_t EngineBase::addDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
+{
+ // verify if the audio source is valid
+ if (!audio_is_valid_audio_source(audioSource)) {
+ ALOGE("%s unknown audio source %u", __func__, audioSource);
+ }
+
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ mCapturePresetDevicesRole[audioSource][role] = excludeDeviceTypeAddrsFrom(
+ mCapturePresetDevicesRole[audioSource][role], devices);
+ for (const auto& device : devices) {
+ mCapturePresetDevicesRole[audioSource][role].push_back(device);
+ }
+ // When the devices are set as preferred devices, remove them from the disabled devices.
+ doRemoveDevicesRoleForCapturePreset(
+ audioSource, DEVICE_ROLE_DISABLED, devices, false /*forceMatched*/);
+ break;
+ case DEVICE_ROLE_DISABLED:
+ // TODO: support setting devices role as disabled for capture preset.
+ ALOGI("%s no implemented for role as %d", __func__, role);
+ break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as it is no need to set device role as none
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+status_t EngineBase::removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector& devices) {
+ return doRemoveDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t EngineBase::doRemoveDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector& devices, bool forceMatched)
+{
+ // verify if the audio source is valid
+ if (!audio_is_valid_audio_source(audioSource)) {
+ ALOGE("%s unknown audio source %u", __func__, audioSource);
+ }
+
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ case DEVICE_ROLE_DISABLED: {
+ if (mCapturePresetDevicesRole.count(audioSource) == 0 ||
+ mCapturePresetDevicesRole[audioSource].count(role) == 0) {
+ return NAME_NOT_FOUND;
+ }
+ AudioDeviceTypeAddrVector remainingDevices = excludeDeviceTypeAddrsFrom(
+ mCapturePresetDevicesRole[audioSource][role], devices);
+ if (forceMatched && remainingDevices.size() !=
+ mCapturePresetDevicesRole[audioSource][role].size() - devices.size()) {
+ // There are some devices from `devicesToRemove` that are not shown in the cached record
+ return BAD_VALUE;
+ }
+ mCapturePresetDevicesRole[audioSource][role] = remainingDevices;
+ if (mCapturePresetDevicesRole[audioSource][role].empty()) {
+ // Remove the role when device list is empty
+ mCapturePresetDevicesRole[audioSource].erase(role);
+ }
+ } break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as it makes no sense to remove devices with
+ // role as DEVICE_ROLE_NONE
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+status_t EngineBase::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role)
+{
+ // verify if the audio source is valid
+ if (!audio_is_valid_audio_source(audioSource)) {
+ ALOGE("%s unknown audio source %u", __func__, audioSource);
+ }
+
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ if (mCapturePresetDevicesRole.count(audioSource) == 0 ||
+ mCapturePresetDevicesRole[audioSource].erase(role) == 0) {
+ // no preferred device for the given audio source
+ return NAME_NOT_FOUND;
+ }
+ break;
+ case DEVICE_ROLE_DISABLED:
+ // TODO: support remove devices role as disabled for strategy.
+ ALOGI("%s no implemented for role as %d", __func__, role);
+ break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as it makes no sense to remove devices with
+ // role as DEVICE_ROLE_NONE for a strategy
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+status_t EngineBase::getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role, AudioDeviceTypeAddrVector &devices) const
+{
+ // verify if the audio source is valid
+ if (!audio_is_valid_audio_source(audioSource)) {
+ ALOGE("%s unknown audio source %u", __func__, audioSource);
+ return BAD_VALUE;
+ }
+
+ switch (role) {
+ case DEVICE_ROLE_PREFERRED:
+ case DEVICE_ROLE_DISABLED: {
+ if (mCapturePresetDevicesRole.count(audioSource) == 0) {
+ return NAME_NOT_FOUND;
+ }
+ auto devIt = mCapturePresetDevicesRole.at(audioSource).find(role);
+ if (devIt == mCapturePresetDevicesRole.at(audioSource).end()) {
+ ALOGV("%s no devices role(%d) for capture preset %u", __func__, role, audioSource);
+ return NAME_NOT_FOUND;
+ }
+
+ devices = devIt->second;
+ } break;
+ case DEVICE_ROLE_NONE:
+ // Intentionally fall-through as the DEVICE_ROLE_NONE is never set
+ default:
+ ALOGE("%s invalid role %d", __func__, role);
+ return BAD_VALUE;
+ }
return NO_ERROR;
}
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 1821140..d39eff6 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -26,8 +26,8 @@
{"STRATEGY_PHONE",
{
{"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
- {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT, 0,
- ""}},
+ {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}},
},
{"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
@@ -39,10 +39,11 @@
{
{"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
- AUDIO_SOURCE_DEFAULT, 0, ""}}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
},
{"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
- {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, 0, ""}},
+ {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}},
}
},
},
@@ -58,7 +59,7 @@
{
{"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
- AUDIO_SOURCE_DEFAULT, 0, ""}}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
}
},
},
@@ -66,15 +67,16 @@
{
{"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
{
- {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT, 0, ""},
+ {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_EVENT,
- AUDIO_SOURCE_DEFAULT, 0, ""}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
}
}
},
@@ -83,21 +85,25 @@
{
{"assistant", AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
{{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
- AUDIO_SOURCE_DEFAULT, 0, ""}}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
},
{"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
{
- {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, 0, ""},
- {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT, 0, ""},
- {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANT, AUDIO_SOURCE_DEFAULT, 0, ""},
+ {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""},
+ {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""},
+ {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANT, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
- AUDIO_SOURCE_DEFAULT, 0, ""},
- {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
+ {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}
},
},
{"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
- AUDIO_SOURCE_DEFAULT, 0, ""}}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
}
},
},
@@ -106,7 +112,7 @@
{"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
- AUDIO_SOURCE_DEFAULT, 0, ""}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
}
}
},
@@ -114,7 +120,8 @@
{"STRATEGY_CALL_ASSISTANT",
{
{"", AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
- {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT, 0, ""}}
+ {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}}
}
},
},
@@ -136,14 +143,16 @@
{"rerouting",
{
{"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
- {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT, 0, ""}}
+ {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}}
}
},
},
{"patch",
{
{"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
- {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
+ {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}}
}
},
}
diff --git a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
index 87b6aaf..96cc140 100644
--- a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
+++ b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
@@ -69,6 +69,11 @@
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+ // TODO (b/122931261): remove when preferred device for strategy media will be used instead of
+ // AUDIO_POLICY_FORCE_NO_BT_A2DP.
+ case AUDIO_DEVICE_OUT_HEARING_AID:
+ case AUDIO_DEVICE_OUT_BLE_HEADSET:
+ case AUDIO_DEVICE_OUT_BLE_SPEAKER:
return GROUP_BT_A2DP;
default:
return GROUP_NONE;
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 151c7bb..060568a 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -321,10 +321,11 @@
void ProductStrategyPreferredRoutingMap::dump(android::String8* dst, int spaces) const {
dst->appendFormat("\n%*sPreferred devices per product strategy dump:", spaces, "");
for (const auto& iter : *this) {
- dst->appendFormat("\n%*sStrategy %u dev:%08x addr:%s",
+ dst->appendFormat("\n%*sStrategy %u %s",
spaces + 2, "",
(uint32_t) iter.first,
- iter.second.mType, iter.second.mAddress.c_str());
+ dumpAudioDeviceTypeAddrVector(iter.second, true /*includeSensitiveInfo*/)
+ .c_str());
}
dst->appendFormat("\n");
}
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index ff840f9..459cc78 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libaudiopolicyengine_config",
export_include_dirs: ["include"],
diff --git a/services/audiopolicy/engine/config/TEST_MAPPING b/services/audiopolicy/engine/config/TEST_MAPPING
new file mode 100644
index 0000000..06ce111
--- /dev/null
+++ b/services/audiopolicy/engine/config/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "audiopolicy_engineconfig_tests"
+ }
+ ]
+}
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 5d22c24..c565926 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -111,6 +111,8 @@
*/
ParsingResult parse(const char* path = DEFAULT_PATH);
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups);
+// Exposed for testing.
+android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups);
} // namespace engineConfig
} // namespace android
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 4842cb2..7cfef5b 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -228,7 +228,8 @@
std::string flags = getXmlAttribute(cur, "value");
ALOGV("%s flags %s", __FUNCTION__, flags.c_str());
- attributes.flags = AudioFlagConverter::maskFromString(flags, " ");
+ attributes.flags = static_cast<audio_flags_mask_t>(
+ AudioFlagConverter::maskFromString(flags, " "));
}
if (!xmlStrcmp(cur->name, (const xmlChar *)("Bundle"))) {
std::string bundleKey = getXmlAttribute(cur, "key");
@@ -588,6 +589,7 @@
}
}
}
+ VolumeGroups tempVolumeGroups = volumeGroups;
for (const auto &volumeMapIter : legacyVolumeMap) {
// In order to let AudioService setting the min and max (compatibility), set Min and Max
// to -1 except for private streams
@@ -598,8 +600,10 @@
}
int indexMin = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 0 : -1;
int indexMax = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 100 : -1;
- volumeGroups.push_back({ volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });
+ tempVolumeGroups.push_back(
+ { volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });
}
+ std::swap(tempVolumeGroups, volumeGroups);
return NO_ERROR;
}
@@ -694,35 +698,14 @@
return deserializeLegacyVolumeCollection(doc, cur, volumeGroups, nbSkippedElements);
}
-static const int gApmXmlConfigFilePathMaxLength = 128;
-
-static constexpr const char *apmXmlConfigFileName = "audio_policy_configuration.xml";
-static constexpr const char *apmA2dpOffloadDisabledXmlConfigFileName =
- "audio_policy_configuration_a2dp_offload_disabled.xml";
-
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups) {
- char audioPolicyXmlConfigFile[gApmXmlConfigFilePathMaxLength];
- std::vector<const char *> fileNames;
- status_t ret;
-
- if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false) &&
- property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
- // A2DP offload supported but disabled: try to use special XML file
- fileNames.push_back(apmA2dpOffloadDisabledXmlConfigFileName);
+ if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file();
+ !audioPolicyXmlConfigFile.empty()) {
+ return parseLegacyVolumeFile(audioPolicyXmlConfigFile.c_str(), volumeGroups);
+ } else {
+ ALOGE("No readable audio policy config file found");
+ return BAD_VALUE;
}
- fileNames.push_back(apmXmlConfigFileName);
-
- for (const char* fileName : fileNames) {
- for (const auto& path : audio_get_configuration_paths()) {
- snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
- "%s/%s", path.c_str(), fileName);
- ret = parseLegacyVolumeFile(audioPolicyXmlConfigFile, volumeGroups);
- if (ret == NO_ERROR) {
- return ret;
- }
- }
- }
- return BAD_VALUE;
}
} // namespace engineConfig
diff --git a/services/audiopolicy/engine/config/tests/Android.bp b/services/audiopolicy/engine/config/tests/Android.bp
new file mode 100644
index 0000000..5791f17
--- /dev/null
+++ b/services/audiopolicy/engine/config/tests/Android.bp
@@ -0,0 +1,34 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+ name: "audiopolicy_engineconfig_tests",
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ "libxml2",
+ ],
+ static_libs: [
+ "libaudiopolicyengine_config",
+ ],
+
+ srcs: ["engineconfig_tests.cpp"],
+
+ data: [":audiopolicy_engineconfig_files"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/services/audiopolicy/engine/config/tests/engineconfig_tests.cpp b/services/audiopolicy/engine/config/tests/engineconfig_tests.cpp
new file mode 100644
index 0000000..f61e02f
--- /dev/null
+++ b/services/audiopolicy/engine/config/tests/engineconfig_tests.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "APM_Test"
+#include <android-base/file.h>
+#include <log/log.h>
+
+#include "EngineConfig.h"
+
+using namespace android;
+
+TEST(EngineConfigTestInit, LegacyVolumeGroupsLoadingIsTransactional) {
+ engineConfig::VolumeGroups groups;
+ ASSERT_TRUE(groups.empty());
+ status_t status = engineConfig::parseLegacyVolumeFile(
+ (base::GetExecutableDirectory() + "/test_invalid_apm_volume_tables.xml").c_str(),
+ groups);
+ ASSERT_NE(NO_ERROR, status);
+ EXPECT_TRUE(groups.empty());
+ status = engineConfig::parseLegacyVolumeFile(
+ (base::GetExecutableDirectory() + "/test_apm_volume_tables.xml").c_str(),
+ groups);
+ ASSERT_EQ(NO_ERROR, status);
+ EXPECT_FALSE(groups.empty());
+}
diff --git a/services/audiopolicy/engine/config/tests/resources/Android.bp b/services/audiopolicy/engine/config/tests/resources/Android.bp
new file mode 100644
index 0000000..9cee978
--- /dev/null
+++ b/services/audiopolicy/engine/config/tests/resources/Android.bp
@@ -0,0 +1,16 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+filegroup {
+ name: "audiopolicy_engineconfig_files",
+ srcs: [
+ "test_apm_volume_tables.xml",
+ "test_invalid_apm_volume_tables.xml",
+ ],
+}
diff --git a/services/audiopolicy/engine/config/tests/resources/test_apm_volume_tables.xml b/services/audiopolicy/engine/config/tests/resources/test_apm_volume_tables.xml
new file mode 100644
index 0000000..16126b6
--- /dev/null
+++ b/services/audiopolicy/engine/config/tests/resources/test_apm_volume_tables.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="true"/>
+ <volumes>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEARING_AID"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ </volumes>
+ <volumes>
+ <reference name="FULL_SCALE_VOLUME_CURVE">
+ <!-- Full Scale reference Volume Curve -->
+ <point>0,0</point>
+ <point>100,0</point>
+ </reference>
+ </volumes>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/engine/config/tests/resources/test_invalid_apm_volume_tables.xml b/services/audiopolicy/engine/config/tests/resources/test_invalid_apm_volume_tables.xml
new file mode 100644
index 0000000..3ec5d10
--- /dev/null
+++ b/services/audiopolicy/engine/config/tests/resources/test_invalid_apm_volume_tables.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This file uses a non-existent audio stream name. -->
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="true"/>
+ <volumes>
+ <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_NON_EXISTING" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_HEADSET"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_HEADSET"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2970</point>
+ <point>33,-2010</point>
+ <point>66,-1020</point>
+ <point>100,0</point>
+ </volume>
+ <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_HEADSET"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_HEARING_AID"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+ ref="FULL_SCALE_VOLUME_CURVE"/>
+ </volumes>
+ <volumes>
+ <reference name="FULL_SCALE_VOLUME_CURVE">
+ <!-- Full Scale reference Volume Curve -->
+ <point>0,0</point>
+ <point>100,0</point>
+ </reference>
+ </volumes>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/engine/interface/Android.bp b/services/audiopolicy/engine/interface/Android.bp
index 2ea42b6..5dd5adb 100644
--- a/services/audiopolicy/engine/interface/Android.bp
+++ b/services/audiopolicy/engine/interface/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudiopolicyengine_interface_headers",
host_supported: true,
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index dfb20b5..f64608d 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -34,6 +34,8 @@
using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
using StrategyVector = std::vector<product_strategy_t>;
using VolumeGroupVector = std::vector<volume_group_t>;
+using CapturePresetDevicesRoleMap =
+ std::map<audio_source_t, std::map<device_role_t, AudioDeviceTypeAddrVector>>;
/**
* This interface is dedicated to the policy manager that a Policy Engine shall implement.
@@ -293,36 +295,113 @@
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const = 0;
/**
- * @brief setPreferredDeviceForStrategy sets the default device to be used for a
- * strategy when available
+ * @brief setDevicesRoleForStrategy sets devices role for a strategy when available. To remove
+ * devices role, removeDevicesRoleForStrategy must be called. When devices role is set
+ * successfully, previously set devices for the same role and strategy will be removed.
* @param strategy the audio strategy whose routing will be affected
- * @param device the audio device to route to when available
- * @return BAD_VALUE if the strategy is invalid,
- * or NO_ERROR if the preferred device was set
+ * @param role the role of the devices for the strategy. All device roles are defined at
+ * system/media/audio/include/system/audio_policy.h. DEVICE_ROLE_NONE is invalid
+ * for setting.
+ * @param devices the audio devices to be set
+ * @return BAD_VALUE if the strategy or role is invalid,
+ * or NO_ERROR if the role of the devices for strategy was set
*/
- virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device) = 0;
+ virtual status_t setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
/**
- * @brief removePreferredDeviceForStrategy removes the preferred device previously set
+ * @brief removeDevicesRoleForStrategy removes the role of device(s) previously set
* for the given strategy
* @param strategy the audio strategy whose routing will be affected
- * @return BAD_VALUE if the strategy is invalid,
- * or NO_ERROR if the preferred device was removed
+ * @param role the role of the devices for strategy
+ * @return BAD_VALUE if the strategy or role is invalid,
+ * or NO_ERROR if the devices for this role was removed
*/
- virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
+ virtual status_t removeDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role) = 0;
/**
- * @brief getPreferredDeviceForStrategy queries which device is set as the
- * preferred device for the given strategy
+ * @brief getDevicesForRoleAndStrategy queries which devices have the specified role for the
+ * specified strategy
* @param strategy the strategy to query
- * @param device returns configured as the preferred device if one was set
- * @return BAD_VALUE if the strategy is invalid,
- * or NAME_NOT_FOUND if no preferred device was set
- * or NO_ERROR if the device parameter was initialized to the preferred device
+ * @param role the role of the devices to query
+ * @param devices returns list of devices with matching role for the specified strategy.
+ * DEVICE_ROLE_NONE is invalid as input.
+ * @return BAD_VALUE if the strategy or role is invalid,
+ * or NAME_NOT_FOUND if no device for the role and strategy was set
+ * or NO_ERROR if the devices parameter contains a list of devices
*/
- virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device) const = 0;
+ virtual status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
+ AudioDeviceTypeAddrVector &devices) const = 0;
+
+ /**
+ * @brief setDevicesRoleForCapturePreset sets devices role for a capture preset when available.
+ * To remove devices role, removeDevicesRoleForCapturePreset must be called. Calling
+ * clearDevicesRoleForCapturePreset will remove all devices as role. When devices role is set
+ * successfully, previously set devices for the same role and capture preset will be removed.
+ * @param audioSource the audio capture preset whose routing will be affected
+ * @param role the role of the devices for the capture preset. All device roles are defined at
+ * system/media/audio/include/system/audio_policy.h. DEVICE_ROLE_NONE is invalid
+ * for setting.
+ * @param devices the audio devices to be set
+ * @return BAD_VALUE if the capture preset or role is invalid,
+ * or NO_ERROR if the role of the devices for capture preset was set
+ */
+ virtual status_t setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
+
+ /**
+ * @brief addDevicesRoleForCapturePreset adds devices role for a capture preset when available.
+ * To remove devices role, removeDevicesRoleForCapturePreset must be called. Calling
+ * clearDevicesRoleForCapturePreset will remove all devices as role.
+ * @param audioSource the audio capture preset whose routing will be affected
+ * @param role the role of the devices for the capture preset. All device roles are defined at
+ * system/media/audio/include/system/audio_policy.h. DEVICE_ROLE_NONE is invalid
+ * for setting.
+ * @param devices the audio devices to be added
+ * @return BAD_VALUE if the capture preset or role is invalid,
+ * or NO_ERROR if the role of the devices for capture preset was added
+ */
+ virtual status_t addDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) = 0;
+
+ /**
+ * @brief removeDevicesRoleForCapturePreset removes the role of device(s) previously set
+ * for the given capture preset
+ * @param audioSource the audio capture preset whose routing will be affected
+ * @param role the role of the devices for the capture preset
+ * @param devices the devices to be removed
+ * @return BAD_VALUE if 1) the capture preset is invalid, 2) role is invalid or 3) the list of
+ * devices to be removed are not all present as role for a capture preset
+ * or NO_ERROR if the devices for this role was removed
+ */
+ virtual status_t removeDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role, const AudioDeviceTypeAddrVector& devices) = 0;
+
+ /**
+ * @brief clearDevicesRoleForCapturePreset removes the role of all device(s) previously set
+ * for the given capture preset
+ * @param audioSource the audio capture preset whose routing will be affected
+ * @param role the role of the devices for the capture preset
+ * @return BAD_VALUE if the capture preset or role is invalid,
+ * or NO_ERROR if the devices for this role was removed
+ */
+ virtual status_t clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role);
+
+ /**
+ * @brief getDevicesForRoleAndCapturePreset queries which devices have the specified role for
+ * the specified capture preset
+ * @param audioSource the capture preset to query
+ * @param role the role of the devices to query
+ * @param devices returns list of devices with matching role for the specified capture preset.
+ * DEVICE_ROLE_NONE is invalid as input.
+ * @return BAD_VALUE if the capture preset or role is invalid,
+ * or NAME_NOT_FOUND if no device for the role and capture preset was set
+ * or NO_ERROR if the devices parameter contains a list of devices
+ */
+ virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role, AudioDeviceTypeAddrVector &devices) const = 0;
virtual void dump(String8 *dst) const = 0;
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index 8f522f0..a747822 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_headers {
name: "libaudiopolicyengineconfigurable_interface_headers",
host_supported: true,
diff --git a/services/audiopolicy/engineconfigurable/config/Android.bp b/services/audiopolicy/engineconfigurable/config/Android.bp
index fe3eae0..b3d1f97 100644
--- a/services/audiopolicy/engineconfigurable/config/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/Android.bp
@@ -16,6 +16,15 @@
// Root soong_namespace for common components
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "audio_policy_engine_criteria.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp b/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
index f913a14..e46b60f 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
@@ -22,6 +22,15 @@
],
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "audio_policy_engine_configuration.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp b/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
index fae6b7b..ad6eeb1 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
@@ -23,6 +23,15 @@
],
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "audio_policy_engine_configuration.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp b/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
index 94d33bd..773a99a 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
@@ -22,6 +22,15 @@
],
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "audio_policy_engine_configuration.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
index 90ebffd..ee62d5e 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
@@ -16,6 +16,15 @@
// Root soong_namespace for common components
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "PolicyClass.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
index 82b1b6d..2d57d4f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
@@ -26,6 +26,17 @@
//
// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "ProductStrategies.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
index e4605b2..df31bb9 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
@@ -27,6 +27,17 @@
//
// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "ProductStrategies.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
index 61b54cf..65ab8b6 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
@@ -26,6 +26,17 @@
//
// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "ProductStrategies.xml",
vendor: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
index 9abcb70..90154ee 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
@@ -23,6 +23,17 @@
],
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "parameter-framework.policy",
filename_from_src: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
index 27172a4..5b06852 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
@@ -23,6 +23,17 @@
],
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "parameter-framework.policy",
filename_from_src: true,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index 2685c6d..0398fc7 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libpolicy-subsystem",
srcs: [
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
index f91f8d7..f8a6fc0 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
@@ -45,7 +45,7 @@
bool InputSource::sendToHW(string & /*error*/)
{
- uint32_t applicableInputDevice;
+ audio_devices_t applicableInputDevice;
blackboardRead(&applicableInputDevice, sizeof(applicableInputDevice));
return mPolicyPluginInterface->setDeviceForInputSource(mId, applicableInputDevice);
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h
index 244f082..6c8eb65 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h
@@ -32,7 +32,7 @@
struct Device
{
- uint32_t applicableDevice; /**< applicable device for this strategy. */
+ audio_devices_t applicableDevice; /**< applicable device for this strategy. */
char deviceAddress[mMaxStringSize]; /**< device address associated with this strategy. */
} __attribute__((packed));
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index aa06ae3..f4645e6 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -51,7 +51,7 @@
mApplicableDevices = devices;
return NO_ERROR;
}
- devices |= AUDIO_DEVICE_BIT_IN;
+ devices = static_cast<audio_devices_t>(devices | AUDIO_DEVICE_BIT_IN);
if (!audio_is_input_device(devices)) {
ALOGE("%s: trying to set an invalid device 0x%X for input source %s",
__FUNCTION__, devices, getName().c_str());
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 3e47324..40efb3d 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
python_defaults {
name: "tools_default",
version: {
@@ -42,8 +51,8 @@
cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
"cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
"$(location buildPolicyCriterionTypes.py) " +
- // @todo update if 1428659 is merged "--androidaudiobaseheader $(location :android_audio_base_header_file) " +
- " --androidaudiobaseheader system/media/audio/include/system/audio-base.h " +
+ " --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
+ " --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
"--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
"--criteriontypes $(location :audio_policy_engine_criterion_types_template) " +
"--outputfile $(out)",
@@ -51,6 +60,8 @@
// The commented inputs must be provided to use this genrule_defaults
// @todo uncomment if 1428659 is merged":android_audio_base_header_file",
":audio_policy_engine_criterion_types_template",
+ ":libaudio_system_audio_base",
+ ":libaudio_system_audio_common_base",
// ":audio_policy_configuration_top_file",
// ":audio_policy_configuration_files",
],
diff --git a/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
index f060d45..5083b14 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
@@ -126,9 +126,9 @@
ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
criteria_pattern = re.compile(
- r"\s*(?P<type>(?:"+'|'.join(component_type_mapping_table.keys()) + "))_" \
- r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
- r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+ r"\s*V\((?P<type>(?:"+'|'.join(component_type_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*,\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])[0-9a-fA-F]+|[0-9]+)")
logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
@@ -164,6 +164,13 @@
logging.debug("type:{}, literal:{}, values:{}.".format(component_type_name, component_type_literal, component_type_numerical_value))
+ if "stub" not in all_component_types["OutputDevicesMask"]:
+ all_component_types["OutputDevicesMask"]["stub"] = 0x40000000
+ logging.info("added stub output device mask")
+ if "stub" not in all_component_types["InputDevicesMask"]:
+ all_component_types["InputDevicesMask"]["stub"] = 0x40000000
+ logging.info("added stub input device mask")
+
# Transform input source in inclusive criterion
shift = len(all_component_types['OutputDevicesMask'])
if shift > 32:
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
index b8b60c1..b5885c0 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -55,6 +55,11 @@
metavar="ANDROID_AUDIO_BASE_HEADER",
type=argparse.FileType('r'),
required=True)
+ argparser.add_argument('--androidaudiocommonbaseheader',
+ help="Android Audio CommonBase C header file, Mandatory.",
+ metavar="ANDROID_AUDIO_COMMON_BASE_HEADER",
+ type=argparse.FileType('r'),
+ required=True)
argparser.add_argument('--audiopolicyconfigurationfile',
help="Android Audio Policy Configuration file, Mandatory.",
metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
@@ -176,12 +181,12 @@
# -Output devices type
# -Input devices type
#
-def parseAndroidAudioFile(androidaudiobaseheaderFile):
+def parseAndroidAudioFile(androidaudiobaseheaderFile, androidaudiocommonbaseheaderFile):
#
# Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
#
criterion_mapping_table = {
- 'AUDIO_MODE' : "AndroidModeType",
+ 'HAL_AUDIO_MODE' : "AndroidModeType",
'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
@@ -196,9 +201,9 @@
ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
criteria_pattern = re.compile(
- r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
- r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
- r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+ r"\s*V\((?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*,\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
@@ -209,27 +214,91 @@
androidaudiobaseheaderFile.name, line_number, line))
criterion_name = criterion_mapping_table[match.groupdict()['type']]
- literal = ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
- numerical_value = match.groupdict()['values']
+ criterion_literal = \
+ ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+ criterion_numerical_value = match.groupdict()['values']
- # for AUDIO_DEVICE_IN: need to remove sign bit
+ # for AUDIO_DEVICE_IN: need to remove sign bit / rename default to stub
if criterion_name == "InputDevicesMaskType":
- numerical_value = str(int(numerical_value, 0) & ~2147483648)
+ if criterion_literal == "Default":
+ criterion_numerical_value = str(int("0x40000000", 0))
+ else:
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("value {}:{} for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+ criterion_numerical_value = str(int(criterion_numerical_value, 0) & ~2147483648)
+
+ if criterion_name == "OutputDevicesMaskType":
+ if criterion_literal == "Default":
+ criterion_numerical_value = str(int("0x40000000", 0))
+
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
# Remove duplicated numerical values
- if int(numerical_value, 0) in all_criteria[criterion_name].values():
+ if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
logging.info("criterion {} duplicated values:".format(criterion_name))
- logging.info("{}:{}".format(numerical_value, literal))
+ logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
logging.info("KEEPING LATEST")
for key in list(all_criteria[criterion_name]):
- if all_criteria[criterion_name][key] == int(numerical_value, 0):
+ if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
del all_criteria[criterion_name][key]
- all_criteria[criterion_name][literal] = int(numerical_value, 0)
+ all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
logging.debug("type:{},".format(criterion_name))
- logging.debug("iteral:{},".format(literal))
- logging.debug("values:{}.".format(numerical_value))
+ logging.debug("iteral:{},".format(criterion_literal))
+ logging.debug("values:{}.".format(criterion_numerical_value))
+
+ logging.info("Checking Android Common Header file {}".format(androidaudiocommonbaseheaderFile))
+
+ criteria_pattern = re.compile(
+ r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+ for line_number, line in enumerate(androidaudiocommonbaseheaderFile):
+ match = criteria_pattern.match(line)
+ if match:
+ logging.debug("The following line is VALID: {}:{}\n{}".format(
+ androidaudiocommonbaseheaderFile.name, line_number, line))
+
+ criterion_name = criterion_mapping_table[match.groupdict()['type']]
+ criterion_literal = \
+ ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+ criterion_numerical_value = match.groupdict()['values']
+
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+
+ # Remove duplicated numerical values
+ if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+ logging.info("criterion {} duplicated values:".format(criterion_name))
+ logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+ logging.info("KEEPING LATEST")
+ for key in list(all_criteria[criterion_name]):
+ if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+ del all_criteria[criterion_name][key]
+
+ all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+ logging.debug("type:{},".format(criterion_name))
+ logging.debug("iteral:{},".format(criterion_literal))
+ logging.debug("values:{}.".format(criterion_numerical_value))
return all_criteria
@@ -238,7 +307,8 @@
logging.root.setLevel(logging.INFO)
args = parseArgs()
- all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader)
+ all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader,
+ args.androidaudiocommonbaseheader)
address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.bp b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
index 301ecc0..3e04b68 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.bp
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libaudiopolicyengineconfigurable_pfwwrapper",
export_include_dirs: ["include"],
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index aaf4158..7f9c0ac 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libaudiopolicyenginedefault",
srcs: [
diff --git a/services/audiopolicy/enginedefault/config/example/Android.bp b/services/audiopolicy/enginedefault/config/example/Android.bp
index 0bfcaa1..59a704b 100644
--- a/services/audiopolicy/enginedefault/config/example/Android.bp
+++ b/services/audiopolicy/enginedefault/config/example/Android.bp
@@ -19,6 +19,15 @@
soong_namespace {
}
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
prebuilt_etc {
name: "audio_policy_engine_configuration.xml",
vendor: true,
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index b14d2bb..e0a0bbb 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -184,16 +184,7 @@
break;
case STRATEGY_DTMF:
- if (!isInCall()) {
- // when off call, DTMF strategy follows the same rules as MEDIA strategy
- devices = getDevicesForStrategyInt(
- STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
- break;
- }
- // when in call, DTMF and PHONE strategies follow the same rules
- FALLTHROUGH_INTENDED;
-
- case STRATEGY_PHONE:
+ case STRATEGY_PHONE: {
// Force use of only devices on primary output if:
// - in call AND
// - cannot route from voice call RX OR
@@ -216,75 +207,24 @@
availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
- String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
- ((availPrimaryInputDevices.getDevice(
- txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
- (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
+ String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
+ ((availPrimaryInputDevices.getDevice(
+ txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
+ (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
availableOutputDevices = availPrimaryOutputDevices;
}
}
- // for phone strategy, we first consider the forced use and then the available devices by
- // order of priority
- switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
- case AUDIO_POLICY_FORCE_BT_SCO:
- if (!isInCall() || strategy != STRATEGY_DTMF) {
- devices = availableOutputDevices.getDevicesFromType(
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
- if (!devices.isEmpty()) break;
- // if SCO device is requested but no SCO device is available, fall back to default case
- FALLTHROUGH_INTENDED;
-
- default: // FORCE_NONE
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
- if (!devices.isEmpty()) break;
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
- if (!isInCall() &&
- (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
- outputs.isA2dpSupported()) {
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
- AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
- AUDIO_DEVICE_OUT_USB_DEVICE});
- if (!devices.isEmpty()) break;
- if (!isInCall()) {
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
- AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
- break;
-
- case AUDIO_POLICY_FORCE_SPEAKER:
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
- // A2DP speaker when forcing to speaker output
- if (!isInCall() &&
- (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
- outputs.isA2dpSupported()) {
- devices = availableOutputDevices.getDevicesFromType(
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
- if (!devices.isEmpty()) break;
- }
- if (!isInCall()) {
- devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
- AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
- if (!devices.isEmpty()) break;
- }
- devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
- break;
- }
- break;
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
+ if (!devices.isEmpty()) break;
+ devices = availableOutputDevices.getFirstDevicesFromTypes({
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AUDIO_DEVICE_OUT_LINE,
+ AUDIO_DEVICE_OUT_USB_HEADSET,
+ AUDIO_DEVICE_OUT_USB_DEVICE});
+ if (!devices.isEmpty()) break;
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
+ } break;
case STRATEGY_SONIFICATION:
@@ -327,7 +267,8 @@
}
}
// Use both Bluetooth SCO and phone default output when ringing in normal mode
- if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
+ if (audio_is_bluetooth_out_sco_device(getPreferredDeviceTypeForLegacyStrategy(
+ availableOutputDevices, STRATEGY_PHONE))) {
if (strategy == STRATEGY_SONIFICATION) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
@@ -386,18 +327,13 @@
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
break;
}
- // FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
- if ((devices2.isEmpty()) &&
- (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
- devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
- }
+
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
if (devices2.isEmpty() && (getLastRemovableMediaDevices().size() > 0)) {
- if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
- outputs.isA2dpSupported()) {
+ if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
// Get the last connected device of wired and bluetooth a2dp
devices2 = availableOutputDevices.getFirstDevicesFromTypes(
getLastRemovableMediaDevices());
@@ -502,20 +438,24 @@
}
}
+ audio_devices_t commDeviceType =
+ getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE);
+
switch (inputSource) {
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) break;
- if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) break;
}
device = availableDevices.getFirstExistingDevice({
- AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
@@ -528,46 +468,63 @@
availableDevices = availablePrimaryDevices;
}
- switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
- case AUDIO_POLICY_FORCE_BT_SCO:
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
// if SCO device is requested but no SCO device is available, fall back to default case
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) {
break;
}
- FALLTHROUGH_INTENDED;
-
- default: // FORCE_NONE
- device = availableDevices.getFirstExistingDevice({
- AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+ }
+ switch (commDeviceType) {
+ case AUDIO_DEVICE_OUT_BLE_HEADSET:
+ device = availableDevices.getDevice(
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
break;
-
- case AUDIO_POLICY_FORCE_SPEAKER:
+ case AUDIO_DEVICE_OUT_SPEAKER:
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
+ default: // FORCE_NONE
+ device = availableDevices.getFirstExistingDevice({
+ AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
+ AUDIO_DEVICE_IN_BUILTIN_MIC});
+ break;
+
}
break;
case AUDIO_SOURCE_VOICE_RECOGNITION:
case AUDIO_SOURCE_UNPROCESSED:
- case AUDIO_SOURCE_HOTWORD:
- if (inputSource == AUDIO_SOURCE_HOTWORD) {
- // We should not use primary output criteria for Hotword but rather limit
- // to devices attached to the same HW module as the build in mic
- LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
- availableDevices = availablePrimaryDevices;
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
+ device = availableDevices.getDevice(
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+ if (device != nullptr) break;
}
- if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+ // we need to make BLUETOOTH_BLE has higher priority than BUILTIN_MIC,
+ // because sometimes user want to do voice search by bt remote
+ // even if BUILDIN_MIC is available.
+ device = availableDevices.getFirstExistingDevice({
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+
+ break;
+ case AUDIO_SOURCE_HOTWORD:
+ // We should not use primary output criteria for Hotword but rather limit
+ // to devices attached to the same HW module as the build in mic
+ LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
+ availableDevices = availablePrimaryDevices;
+ if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
if (device != nullptr) break;
}
device = availableDevices.getFirstExistingDevice({
- AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
case AUDIO_SOURCE_CAMCORDER:
// For a device without built-in mic, adding usb device
@@ -584,7 +541,8 @@
case AUDIO_SOURCE_VOICE_PERFORMANCE:
device = availableDevices.getFirstExistingDevice({
AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
+ AUDIO_DEVICE_IN_BUILTIN_MIC});
break;
case AUDIO_SOURCE_REMOTE_SUBMIX:
device = availableDevices.getDevice(
@@ -609,6 +567,7 @@
ALOGE_IF(device == nullptr,
"getDeviceForInputSource() no default device defined");
}
+
ALOGV_IF(device != nullptr,
"getDeviceForInputSource()input source %d, device %08x",
inputSource, device->type());
@@ -626,31 +585,66 @@
}
}
-DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
- DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
+ for (const auto& strategyMap : mLegacyStrategyMap) {
+ if (strategyMap.second == legacyStrategy) {
+ return strategyMap.first;
+ }
+ }
+ return PRODUCT_STRATEGY_NONE;
+}
- // check if this strategy has a preferred device that is available,
- // if yes, give priority to it
- AudioDeviceTypeAddr preferredStrategyDevice;
- const status_t status = getPreferredDeviceForStrategy(strategy, preferredStrategyDevice);
+audio_devices_t Engine::getPreferredDeviceTypeForLegacyStrategy(
+ const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const {
+ product_strategy_t strategy = getProductStrategyFromLegacy(legacyStrategy);
+ DeviceVector devices = getPreferredAvailableDevicesForProductStrategy(
+ availableOutputDevices, strategy);
+ if (devices.size() > 0) {
+ return devices[0]->type();
+ }
+ return AUDIO_DEVICE_NONE;
+}
+
+DeviceVector Engine::getPreferredAvailableDevicesForProductStrategy(
+ const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
+ DeviceVector preferredAvailableDevVec = {};
+ AudioDeviceTypeAddrVector preferredStrategyDevices;
+ const status_t status = getDevicesForRoleAndStrategy(
+ strategy, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
if (status == NO_ERROR) {
// there is a preferred device, is it available?
- sp<DeviceDescriptor> preferredAvailableDevDescr = availableOutputDevices.getDevice(
- preferredStrategyDevice.mType,
- String8(preferredStrategyDevice.mAddress.c_str()),
- AUDIO_FORMAT_DEFAULT);
- if (preferredAvailableDevDescr != nullptr) {
- ALOGVV("%s using pref device 0x%08x/%s for strategy %u",
- __func__, preferredStrategyDevice.mType,
- preferredStrategyDevice.mAddress.c_str(), strategy);
- return DeviceVector(preferredAvailableDevDescr);
+ preferredAvailableDevVec =
+ availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
+ if (preferredAvailableDevVec.size() == preferredAvailableDevVec.size()) {
+ ALOGVV("%s using pref device %s for strategy %u",
+ __func__, preferredAvailableDevVec.toString().c_str(), strategy);
+ return preferredAvailableDevVec;
}
}
+ return preferredAvailableDevVec;
+}
+
+DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
+ DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+ auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
+ mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
+ // When not in call, STRATEGY_PHONE and STRATEGY_DTMF follow STRATEGY_MEDIA
+ if (!isInCall() && (legacyStrategy == STRATEGY_PHONE || legacyStrategy == STRATEGY_DTMF)) {
+ legacyStrategy = STRATEGY_MEDIA;
+ strategy = getProductStrategyFromLegacy(STRATEGY_MEDIA);
+ }
+ // check if this strategy has a preferred device that is available,
+ // if yes, give priority to it.
+ DeviceVector preferredAvailableDevVec =
+ getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, strategy);
+ if (!preferredAvailableDevVec.isEmpty()) {
+ return preferredAvailableDevVec;
+ }
DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
- auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
- mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
return getDevicesForStrategyInt(legacyStrategy,
availableOutputDevices,
availableInputDevices, outputs);
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index bb9e2df..6214fe7 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -83,6 +83,12 @@
sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
+ product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
+ audio_devices_t getPreferredDeviceTypeForLegacyStrategy(
+ const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
+ DeviceVector getPreferredAvailableDevicesForProductStrategy(
+ const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
+
DeviceStrategyMap mDevicesForStrategies;
std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
diff --git a/services/audiopolicy/manager/Android.mk b/services/audiopolicy/manager/Android.mk
index cae6cfa..6fc8388 100644
--- a/services/audiopolicy/manager/Android.mk
+++ b/services/audiopolicy/manager/Android.mk
@@ -24,6 +24,9 @@
LOCAL_CFLAGS := -Wall -Werror
LOCAL_MODULE:= libaudiopolicymanager
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../../NOTICE
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 577b42f..5572beb 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library_shared {
name: "libaudiopolicymanagerdefault",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ae71959..5b53c0b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -29,30 +29,25 @@
#define ALOGVV(a...) do { } while(0)
#endif
-#define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
-#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
-#define AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME \
- "audio_policy_configuration_a2dp_offload_disabled.xml"
-#define AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME \
- "audio_policy_configuration_bluetooth_legacy_hal.xml"
-
#include <algorithm>
#include <inttypes.h>
#include <math.h>
#include <set>
#include <unordered_set>
#include <vector>
+
+#include <Serializer.h>
#include <cutils/bitops.h>
#include <cutils/properties.h>
-#include <utils/Log.h>
#include <media/AudioParameter.h>
+#include <policy.h>
#include <private/android_filesystem_config.h>
#include <system/audio.h>
#include <system/audio_config.h>
+#include <utils/Log.h>
+
#include "AudioPolicyManager.h"
-#include <Serializer.h>
#include "TypeConverter.h"
-#include <policy.h>
namespace android {
@@ -65,11 +60,11 @@
constexpr float IN_CALL_EARPIECE_HEADROOM_DB = 3.f;
// Compressed formats for MSD module, ordered from most preferred to least preferred.
-static const std::vector<audio_format_t> compressedFormatsOrder = {{
- AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
+static const std::vector<audio_format_t> msdCompressedFormatsOrder = {{
+ AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
// Channel masks for MSD module, 3D > 2D > 1D ordering (most preferred to least preferred).
-static const std::vector<audio_channel_mask_t> surroundChannelMasksOrder = {{
+static const std::vector<audio_channel_mask_t> msdSurroundChannelMasksOrder = {{
AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
@@ -247,6 +242,7 @@
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
(((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
(desc->mDirectOpenCount == 0))) {
+ clearAudioSourcesForOutput(output);
closeOutput(output);
}
}
@@ -261,11 +257,7 @@
} else {
checkCloseOutputs();
}
-
- if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
- DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
- updateCallRouting(newDevices);
- }
+ (void)updateCallRouting(false /*fromCache*/);
const DeviceVector msdOutDevices = getMsdAudioOutDevices();
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
@@ -353,11 +345,12 @@
// getDeviceForStrategy() cache
updateDevicesAndOutputs();
- if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
- DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
- updateCallRouting(newDevices);
+ (void)updateCallRouting(false /*fromCache*/);
+ // Reconnect Audio Source
+ for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
+ auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
+ checkAudioSourceForAttributes(attributes);
}
-
if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
cleanUpForDevice(device);
}
@@ -442,7 +435,7 @@
// Case 1: A2DP active device switches from primary to primary
// module
// Case 2: A2DP device config changes on primary module.
- if (audio_is_a2dp_out_device(device)) {
+ if (audio_is_a2dp_out_device(device) && hasPrimaryOutput()) {
sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
if (availablePrimaryOutputDevices().contains(devDesc) &&
@@ -517,30 +510,61 @@
return status;
}
-uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs)
+DeviceVector AudioPolicyManager::selectBestRxSinkDevicesForCall(bool fromCache)
+{
+ DeviceVector rxSinkdevices{};
+ rxSinkdevices = mEngine->getOutputDevicesForAttributes(
+ attributes_initializer(AUDIO_USAGE_VOICE_COMMUNICATION), nullptr, fromCache);
+ if (!rxSinkdevices.isEmpty() && mAvailableOutputDevices.contains(rxSinkdevices.itemAt(0))) {
+ auto rxSinkDevice = rxSinkdevices.itemAt(0);
+ auto telephonyRxModule = mHwModules.getModuleForDeviceType(
+ AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
+ // retrieve Rx Source device descriptor
+ sp<DeviceDescriptor> rxSourceDevice = mAvailableInputDevices.getDevice(
+ AUDIO_DEVICE_IN_TELEPHONY_RX, String8(), AUDIO_FORMAT_DEFAULT);
+
+ // RX Telephony and Rx sink devices are declared by Primary Audio HAL
+ if (isPrimaryModule(telephonyRxModule) && (telephonyRxModule->getHalVersionMajor() >= 3) &&
+ telephonyRxModule->supportsPatch(rxSourceDevice, rxSinkDevice)) {
+ ALOGW("%s() device %s using HW Bridge", __func__, rxSinkDevice->toString().c_str());
+ return DeviceVector(rxSinkDevice);
+ }
+ }
+ // Note that despite the fact that getNewOutputDevices() is called on the primary output,
+ // the device returned is not necessarily reachable via this output
+ // (filter later by setOutputDevices())
+ return getNewOutputDevices(mPrimaryOutput, fromCache);
+}
+
+status_t AudioPolicyManager::updateCallRouting(bool fromCache, uint32_t delayMs, uint32_t *waitMs)
+{
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
+ DeviceVector rxDevices = selectBestRxSinkDevicesForCall(fromCache);
+ return updateCallRoutingInternal(rxDevices, delayMs, waitMs);
+ }
+ return INVALID_OPERATION;
+}
+
+status_t AudioPolicyManager::updateCallRoutingInternal(
+ const DeviceVector &rxDevices, uint32_t delayMs, uint32_t *waitMs)
{
bool createTxPatch = false;
bool createRxPatch = false;
uint32_t muteWaitMs = 0;
-
if(!hasPrimaryOutput() ||
mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
- return muteWaitMs;
+ return INVALID_OPERATION;
}
- ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device");
+ ALOG_ASSERT(!rxDevices.isEmpty(), "%s() no selected output device", __func__);
audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);
- ALOG_ASSERT(txSourceDevice != 0, "updateCallRouting() input selected device not available");
+ ALOG_ASSERT(txSourceDevice != 0, "%s() input selected device not available", __func__);
- ALOGV("updateCallRouting device rxDevice %s txDevice %s",
+ ALOGV("%s device rxDevice %s txDevice %s", __func__,
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
- // release existing RX patch if any
- if (mCallRxPatch != 0) {
- releaseAudioPatchInternal(mCallRxPatch->getHandle());
- mCallRxPatch.clear();
- }
+ disconnectTelephonyRxAudioSource();
// release TX patch if any
if (mCallTxPatch != 0) {
releaseAudioPatchInternal(mCallTxPatch->getHandle());
@@ -566,8 +590,8 @@
(telephonyRxModule->getHalVersionMajor() >= 3)) {
if (rxSourceDevice == 0 || txSinkDevice == 0) {
// RX / TX Telephony device(s) is(are) not currently available
- ALOGE("updateCallRouting() no telephony Tx and/or RX device");
- return muteWaitMs;
+ ALOGE("%s() no telephony Tx and/or RX device", __func__);
+ return INVALID_OPERATION;
}
// createAudioPatchInternal now supports both HW / SW bridging
createRxPatch = true;
@@ -588,8 +612,7 @@
if (!createRxPatch) {
muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
} else { // create RX path audio patch
- mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevices.itemAt(0), delayMs);
-
+ connectTelephonyRxAudioSource();
// If the TX device is on the primary HW module but RX device is
// on other HW module, SinkMetaData of telephony input should handle it
// assuming the device uses audio HAL V5.0 and above
@@ -606,8 +629,10 @@
}
mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs);
}
-
- return muteWaitMs;
+ if (waitMs != nullptr) {
+ *waitMs = muteWaitMs;
+ }
+ return NO_ERROR;
}
sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(
@@ -652,6 +677,24 @@
return false;
}
+void AudioPolicyManager::connectTelephonyRxAudioSource()
+{
+ disconnectTelephonyRxAudioSource();
+ const struct audio_port_config source = {
+ .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE,
+ .ext.device.type = AUDIO_DEVICE_IN_TELEPHONY_RX, .ext.device.address = ""
+ };
+ const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
+ status_t status = startAudioSource(&source, &aa, &mCallRxSourceClientPort, 0/*uid*/);
+ ALOGE_IF(status != NO_ERROR, "%s failed to start Telephony Rx AudioSource", __func__);
+}
+
+void AudioPolicyManager::disconnectTelephonyRxAudioSource()
+{
+ stopAudioSource(mCallRxSourceClientPort);
+ mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+}
+
void AudioPolicyManager::setPhoneState(audio_mode_t state)
{
ALOGV("setPhoneState() state %d", state);
@@ -707,28 +750,22 @@
}
if (hasPrimaryOutput()) {
- // Note that despite the fact that getNewOutputDevices() is called on the primary output,
- // the device returned is not necessarily reachable via this output
- DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
- // force routing command to audio hardware when ending call
- // even if no device change is needed
- if (isStateInCall(oldState) && rxDevices.isEmpty()) {
- rxDevices = mPrimaryOutput->devices();
- }
-
if (state == AUDIO_MODE_IN_CALL) {
- updateCallRouting(rxDevices, delayMs);
- } else if (oldState == AUDIO_MODE_IN_CALL) {
- if (mCallRxPatch != 0) {
- releaseAudioPatchInternal(mCallRxPatch->getHandle());
- mCallRxPatch.clear();
- }
- if (mCallTxPatch != 0) {
- releaseAudioPatchInternal(mCallTxPatch->getHandle());
- mCallTxPatch.clear();
- }
- setOutputDevices(mPrimaryOutput, rxDevices, force, 0);
+ (void)updateCallRouting(false /*fromCache*/, delayMs);
} else {
+ DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
+ // force routing command to audio hardware when ending call
+ // even if no device change is needed
+ if (isStateInCall(oldState) && rxDevices.isEmpty()) {
+ rxDevices = mPrimaryOutput->devices();
+ }
+ if (oldState == AUDIO_MODE_IN_CALL) {
+ disconnectTelephonyRxAudioSource();
+ if (mCallTxPatch != 0) {
+ releaseAudioPatchInternal(mCallTxPatch->getHandle());
+ mCallTxPatch.clear();
+ }
+ }
setOutputDevices(mPrimaryOutput, rxDevices, force, 0);
}
}
@@ -790,16 +827,7 @@
}
updateCallAndOutputRouting(forceVolumeReeval, delayMs);
-
- for (const auto& activeDesc : mInputs.getActiveInputs()) {
- auto newDevice = getNewInputDevice(activeDesc);
- // Force new input selection if the new device can not be reached via current input
- if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
- setInputDevice(activeDesc->mIoHandle, newDevice);
- } else {
- closeInput(activeDesc->mIoHandle);
- }
- }
+ updateInputRouting();
}
void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
@@ -903,7 +931,8 @@
// Only honor audibility enforced when required. The client will be
// forced to reconnect if the forced usage changes.
if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
- dstAttr->flags &= ~AUDIO_FLAG_AUDIBILITY_ENFORCED;
+ dstAttr->flags = static_cast<audio_flags_mask_t>(
+ dstAttr->flags & ~AUDIO_FLAG_AUDIBILITY_ENFORCED);
}
return NO_ERROR;
@@ -935,7 +964,7 @@
return status;
}
if (auto it = mAllowedCapturePolicies.find(uid); it != end(mAllowedCapturePolicies)) {
- resultAttr->flags |= it->second;
+ resultAttr->flags = static_cast<audio_flags_mask_t>(resultAttr->flags | it->second);
}
*stream = mEngine->getStreamTypeForAttributes(*resultAttr);
@@ -1030,11 +1059,9 @@
*output = AUDIO_IO_HANDLE_NONE;
if (!msdDevices.isEmpty()) {
*output = getOutputForDevices(msdDevices, session, *stream, config, flags);
- sp<DeviceDescriptor> device = outputDevices.isEmpty() ? nullptr : outputDevices.itemAt(0);
- if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
+ if (*output != AUDIO_IO_HANDLE_NONE && setMsdOutputPatches(&outputDevices) == NO_ERROR) {
ALOGV("%s() Using MSD devices %s instead of devices %s",
__func__, msdDevices.toString().c_str(), outputDevices.toString().c_str());
- outputDevices = msdDevices;
} else {
*output = AUDIO_IO_HANDLE_NONE;
}
@@ -1048,6 +1075,12 @@
}
*selectedDeviceId = getFirstDeviceId(outputDevices);
+ for (auto &outputDevice : outputDevices) {
+ if (outputDevice->getId() == getConfig().getDefaultOutputDevice()->getId()) {
+ *selectedDeviceId = outputDevice->getId();
+ break;
+ }
+ }
if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
*outputType = API_OUTPUT_TELEPHONY_TX;
@@ -1190,24 +1223,9 @@
sp<SwAudioOutputDescriptor> outputDesc =
new SwAudioOutputDescriptor(profile, mpClientInterface);
- String8 address = getFirstDeviceAddress(devices);
-
- // MSD patch may be using the only output stream that can service this request. Release
- // MSD patch to prioritize this request over any active output on MSD.
- AudioPatchCollection msdPatches = getMsdPatches();
- for (size_t i = 0; i < msdPatches.size(); i++) {
- const auto& patch = msdPatches[i];
- for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
- const struct audio_port_config *sink = &patch->mPatch.sinks[j];
- if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- devices.containsDeviceWithType(sink->ext.device.type) &&
- (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
- AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
- releaseAudioPatch(patch->getHandle(), mUidCached);
- break;
- }
- }
- }
+ // An MSD patch may be using the only output stream that can service this request. Release
+ // all MSD patches to prioritize this request over any active output on MSD.
+ releaseMsdOutputPatches(devices);
status_t status = outputDesc->open(config, devices, stream, flags, output);
@@ -1253,7 +1271,8 @@
// Discard haptic channel mask when forcing muting haptic channels.
audio_channel_mask_t channelMask = forceMutingHaptic
- ? (config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL) : config->channel_mask;
+ ? static_cast<audio_channel_mask_t>(config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL)
+ : config->channel_mask;
// open a direct output if required by specified parameters
//force direct flag if offload flag is set: offloading implies a direct output stream
@@ -1329,7 +1348,7 @@
mAvailableOutputDevices);
}
-const AudioPatchCollection AudioPolicyManager::getMsdPatches() const {
+const AudioPatchCollection AudioPolicyManager::getMsdOutputPatches() const {
AudioPatchCollection msdPatches;
sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
if (msdModule != 0) {
@@ -1347,49 +1366,47 @@
return msdPatches;
}
-status_t AudioPolicyManager::getBestMsdAudioProfileFor(const sp<DeviceDescriptor> &outputDevice,
- bool hwAvSync, audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
-{
- sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
- if (msdModule == nullptr) {
- ALOGE("%s() unable to get MSD module", __func__);
- return NO_INIT;
- }
- sp<HwModule> deviceModule = mHwModules.getModuleForDevice(outputDevice, AUDIO_FORMAT_DEFAULT);
- if (deviceModule == nullptr) {
- ALOGE("%s() unable to get module for %s", __func__, outputDevice->toString().c_str());
- return NO_INIT;
- }
- const InputProfileCollection &inputProfiles = msdModule->getInputProfiles();
+status_t AudioPolicyManager::getMsdProfiles(bool hwAvSync,
+ const InputProfileCollection &inputProfiles,
+ const OutputProfileCollection &outputProfiles,
+ const sp<DeviceDescriptor> &sourceDevice,
+ const sp<DeviceDescriptor> &sinkDevice,
+ AudioProfileVector& sourceProfiles,
+ AudioProfileVector& sinkProfiles) const {
if (inputProfiles.isEmpty()) {
- ALOGE("%s() no input profiles for MSD module", __func__);
+ ALOGE("%s() no input profiles for source module", __func__);
return NO_INIT;
}
- const OutputProfileCollection &outputProfiles = deviceModule->getOutputProfiles();
if (outputProfiles.isEmpty()) {
- ALOGE("%s() no output profiles for device %s", __func__, outputDevice->toString().c_str());
+ ALOGE("%s() no output profiles for sink module", __func__);
return NO_INIT;
}
- AudioProfileVector msdProfiles;
- // Each IOProfile represents a MixPort from audio_policy_configuration.xml
for (const auto &inProfile : inputProfiles) {
- if (hwAvSync == ((inProfile->getFlags() & AUDIO_INPUT_FLAG_HW_AV_SYNC) != 0)) {
- appendAudioProfiles(msdProfiles, inProfile->getAudioProfiles());
+ if (hwAvSync == ((inProfile->getFlags() & AUDIO_INPUT_FLAG_HW_AV_SYNC) != 0) &&
+ inProfile->supportsDevice(sourceDevice)) {
+ appendAudioProfiles(sourceProfiles, inProfile->getAudioProfiles());
}
}
- AudioProfileVector deviceProfiles;
for (const auto &outProfile : outputProfiles) {
- if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0)) {
- appendAudioProfiles(deviceProfiles, outProfile->getAudioProfiles());
+ if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) &&
+ outProfile->supportsDevice(sinkDevice)) {
+ appendAudioProfiles(sinkProfiles, outProfile->getAudioProfiles());
}
}
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getBestMsdConfig(bool hwAvSync,
+ const AudioProfileVector &sourceProfiles, const AudioProfileVector &sinkProfiles,
+ audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
+{
struct audio_config_base bestSinkConfig;
- status_t result = findBestMatchingOutputConfig(msdProfiles, deviceProfiles,
- compressedFormatsOrder, surroundChannelMasksOrder, true /*preferHigherSamplingRates*/,
- bestSinkConfig);
+ status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles,
+ msdCompressedFormatsOrder, msdSurroundChannelMasksOrder,
+ true /*preferHigherSamplingRates*/, bestSinkConfig);
if (result != NO_ERROR) {
- ALOGD("%s() no matching profiles found for device: %s, hwAvSync: %d",
- __func__, outputDevice->toString().c_str(), hwAvSync);
+ ALOGD("%s() no matching config found for sink, hwAvSync: %d",
+ __func__, hwAvSync);
return result;
}
sinkConfig->sample_rate = bestSinkConfig.sample_rate;
@@ -1400,7 +1417,7 @@
sinkConfig->flags.output | AUDIO_OUTPUT_FLAG_DIRECT);
if (audio_is_iec61937_compatible(sinkConfig->format)) {
// For formats compatible with IEC61937 encapsulation, assume that
- // the record thread input from MSD is IEC61937 framed (for proportional buffer sizing).
+ // the input is IEC61937 framed (for proportional buffer sizing).
// Add the AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO flag so downstream HAL can distinguish between
// raw and IEC61937 framed streams.
sinkConfig->flags.output = static_cast<audio_output_flags_t>(
@@ -1426,61 +1443,128 @@
return NO_ERROR;
}
-PatchBuilder AudioPolicyManager::buildMsdPatch(const sp<DeviceDescriptor> &outputDevice) const
+PatchBuilder AudioPolicyManager::buildMsdPatch(bool msdIsSource,
+ const sp<DeviceDescriptor> &device) const
{
PatchBuilder patchBuilder;
- patchBuilder.addSource(getMsdAudioInDevice()).addSink(outputDevice);
+ sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
+ ALOG_ASSERT(msdModule != nullptr, "MSD module not available");
+ sp<HwModule> deviceModule = mHwModules.getModuleForDevice(device, AUDIO_FORMAT_DEFAULT);
+ if (deviceModule == nullptr) {
+ ALOGE("%s() unable to get module for %s", __func__, device->toString().c_str());
+ return patchBuilder;
+ }
+ const InputProfileCollection inputProfiles = msdIsSource ?
+ msdModule->getInputProfiles() : deviceModule->getInputProfiles();
+ const OutputProfileCollection outputProfiles = msdIsSource ?
+ deviceModule->getOutputProfiles() : msdModule->getOutputProfiles();
+
+ const sp<DeviceDescriptor> sourceDevice = msdIsSource ? getMsdAudioInDevice() : device;
+ const sp<DeviceDescriptor> sinkDevice = msdIsSource ?
+ device : getMsdAudioOutDevices().itemAt(0);
+ patchBuilder.addSource(sourceDevice).addSink(sinkDevice);
+
audio_port_config sourceConfig = patchBuilder.patch()->sources[0];
audio_port_config sinkConfig = patchBuilder.patch()->sinks[0];
+ AudioProfileVector sourceProfiles;
+ AudioProfileVector sinkProfiles;
// TODO: Figure out whether MSD module has HW_AV_SYNC flag set in the AP config file.
// For now, we just forcefully try with HwAvSync first.
- status_t res = getBestMsdAudioProfileFor(outputDevice, true /*hwAvSync*/,
- &sourceConfig, &sinkConfig) == NO_ERROR ? NO_ERROR :
- getBestMsdAudioProfileFor(
- outputDevice, false /*hwAvSync*/, &sourceConfig, &sinkConfig);
- if (res == NO_ERROR) {
- // Found a matching profile for encoded audio. Re-create PatchBuilder with this config.
- return (PatchBuilder()).addSource(sourceConfig).addSink(sinkConfig);
+ for (auto hwAvSync : { true, false }) {
+ if (getMsdProfiles(hwAvSync, inputProfiles, outputProfiles, sourceDevice, sinkDevice,
+ sourceProfiles, sinkProfiles) != NO_ERROR) {
+ continue;
+ }
+ if (getBestMsdConfig(hwAvSync, sourceProfiles, sinkProfiles, &sourceConfig,
+ &sinkConfig) == NO_ERROR) {
+ // Found a matching config. Re-create PatchBuilder with this config.
+ return (PatchBuilder()).addSource(sourceConfig).addSink(sinkConfig);
+ }
}
- ALOGV("%s() no matching profile found. Fall through to default PCM patch"
+ ALOGV("%s() no matching config found. Fall through to default PCM patch"
" supporting PCM format conversion.", __func__);
return patchBuilder;
}
-status_t AudioPolicyManager::setMsdPatch(const sp<DeviceDescriptor> &outputDevice) {
- sp<DeviceDescriptor> device = outputDevice;
- if (device == nullptr) {
+status_t AudioPolicyManager::setMsdOutputPatches(const DeviceVector *outputDevices) {
+ DeviceVector devices;
+ if (outputDevices != nullptr && outputDevices->size() > 0) {
+ devices.add(*outputDevices);
+ } else {
// Use media strategy for unspecified output device. This should only
// occur on checkForDeviceAndOutputChanges(). Device connection events may
// therefore invalidate explicit routing requests.
- DeviceVector devices = mEngine->getOutputDevicesForAttributes(
+ devices = mEngine->getOutputDevicesForAttributes(
attributes_initializer(AUDIO_USAGE_MEDIA), nullptr, false /*fromCache*/);
- LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no outpudevice to set Msd Patch");
- device = devices.itemAt(0);
+ LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no output device to set MSD patch");
}
- ALOGV("%s() for device %s", __func__, device->toString().c_str());
- PatchBuilder patchBuilder = buildMsdPatch(device);
- const struct audio_patch* patch = patchBuilder.patch();
- const AudioPatchCollection msdPatches = getMsdPatches();
- if (!msdPatches.isEmpty()) {
- LOG_ALWAYS_FATAL_IF(msdPatches.size() > 1,
- "The current MSD prototype only supports one output patch");
- sp<AudioPatch> currentPatch = msdPatches.valueAt(0);
- if (audio_patches_are_equal(¤tPatch->mPatch, patch)) {
- return NO_ERROR;
+ std::vector<PatchBuilder> patchesToCreate;
+ for (auto i = 0u; i < devices.size(); ++i) {
+ ALOGV("%s() for device %s", __func__, devices[i]->toString().c_str());
+ patchesToCreate.push_back(buildMsdPatch(true /*msdIsSource*/, devices[i]));
+ }
+ // Retain only the MSD patches associated with outputDevices request.
+ // Tear down the others, and create new ones as needed.
+ AudioPatchCollection patchesToRemove = getMsdOutputPatches();
+ for (auto it = patchesToCreate.begin(); it != patchesToCreate.end(); ) {
+ auto retainedPatch = false;
+ for (auto i = 0u; i < patchesToRemove.size(); ++i) {
+ if (audio_patches_are_equal(it->patch(), &patchesToRemove[i]->mPatch)) {
+ patchesToRemove.removeItemsAt(i);
+ retainedPatch = true;
+ break;
+ }
}
+ if (retainedPatch) {
+ it = patchesToCreate.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if (patchesToCreate.size() == 0 && patchesToRemove.size() == 0) {
+ return NO_ERROR;
+ }
+ for (auto i = 0u; i < patchesToRemove.size(); ++i) {
+ auto ¤tPatch = patchesToRemove.valueAt(i);
releaseAudioPatch(currentPatch->getHandle(), mUidCached);
}
- status_t status = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
- patch, 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
- ALOGE_IF(status != NO_ERROR, "%s() error %d creating MSD audio patch", __func__, status);
- ALOGI_IF(status == NO_ERROR, "%s() Patch created from MSD_IN to "
- "device:%s (format:%#x channels:%#x samplerate:%d)", __func__,
- device->toString().c_str(), patch->sources[0].format,
- patch->sources[0].channel_mask, patch->sources[0].sample_rate);
+ status_t status = NO_ERROR;
+ for (const auto &p : patchesToCreate) {
+ auto currStatus = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
+ p.patch(), 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
+ char message[256];
+ snprintf(message, sizeof(message), "%s() %s: creating MSD patch from device:IN_BUS to "
+ "device:%#x (format:%#x channels:%#x samplerate:%d)", __func__,
+ currStatus == NO_ERROR ? "Success" : "Error",
+ p.patch()->sinks[0].ext.device.type, p.patch()->sources[0].format,
+ p.patch()->sources[0].channel_mask, p.patch()->sources[0].sample_rate);
+ if (currStatus == NO_ERROR) {
+ ALOGD("%s", message);
+ } else {
+ ALOGE("%s", message);
+ if (status == NO_ERROR) {
+ status = currStatus;
+ }
+ }
+ }
return status;
}
+void AudioPolicyManager::releaseMsdOutputPatches(const DeviceVector& devices) {
+ AudioPatchCollection msdPatches = getMsdOutputPatches();
+ for (size_t i = 0; i < msdPatches.size(); i++) {
+ const auto& patch = msdPatches[i];
+ for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
+ const struct audio_port_config *sink = &patch->mPatch.sinks[j];
+ if (sink->type == AUDIO_PORT_TYPE_DEVICE && devices.getDevice(sink->ext.device.type,
+ String8(sink->ext.device.address), AUDIO_FORMAT_DEFAULT) != nullptr) {
+ releaseAudioPatch(patch->getHandle(), mUidCached);
+ break;
+ }
+ }
+ }
+}
+
audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
audio_output_flags_t flags,
audio_format_t format,
@@ -2267,7 +2351,7 @@
sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
if (inputDesc == 0) {
ALOGW("%s no input for client %d", __FUNCTION__, portId);
- return BAD_VALUE;
+ return DEAD_OBJECT;
}
audio_io_handle_t input = inputDesc->mIoHandle;
sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
@@ -3094,16 +3178,16 @@
// Returns true if all devices types match the predicate and are supported by one HW module
bool AudioPolicyManager::areAllDevicesSupported(
- const Vector<AudioDeviceTypeAddr>& devices,
+ const AudioDeviceTypeAddrVector& devices,
std::function<bool(audio_devices_t)> predicate,
const char *context) {
for (size_t i = 0; i < devices.size(); i++) {
sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
- devices[i].mType, devices[i].mAddress.c_str(), String8(),
+ devices[i].mType, devices[i].getAddress(), String8(),
AUDIO_FORMAT_DEFAULT, false /*allowToCreate*/, true /*matchAddress*/);
if (devDesc == nullptr || (predicate != nullptr && !predicate(devices[i].mType))) {
- ALOGE("%s: device type %#x address %s not supported or not an output device",
- context, devices[i].mType, devices[i].mAddress.c_str());
+ ALOGE("%s: device type %#x address %s not supported or not match predicate",
+ context, devices[i].mType, devices[i].getAddress());
return false;
}
}
@@ -3111,7 +3195,7 @@
}
status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
- const Vector<AudioDeviceTypeAddr>& devices) {
+ const AudioDeviceTypeAddrVector& devices) {
ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
return BAD_VALUE;
@@ -3143,25 +3227,35 @@
return res;
}
-status_t AudioPolicyManager::setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device) {
- ALOGV("%s() strategy=%d device=%08x addr=%s", __FUNCTION__,
- strategy, device.mType, device.mAddress.c_str());
- Vector<AudioDeviceTypeAddr> devices;
- devices.add(device);
+status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices) {
+ ALOGV("%s() strategy=%d role=%d %s", __func__, strategy, role,
+ dumpAudioDeviceTypeAddrVector(devices).c_str());
+
if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
return BAD_VALUE;
}
- status_t status = mEngine->setPreferredDeviceForStrategy(strategy, device);
+ status_t status = mEngine->setDevicesRoleForStrategy(strategy, role, devices);
if (status != NO_ERROR) {
- ALOGW("Engine could not set preferred device %08x %s for strategy %d",
- device.mType, device.mAddress.c_str(), strategy);
+ ALOGW("Engine could not set preferred devices %s for strategy %d role %d",
+ dumpAudioDeviceTypeAddrVector(devices).c_str(), strategy, role);
return status;
}
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+
+ bool forceVolumeReeval = false;
+ // FIXME: workaround for truncated touch sounds
+ // to be removed when the problem is handled by system UI
+ uint32_t delayMs = 0;
+ if (strategy == mCommunnicationStrategy) {
+ forceVolumeReeval = true;
+ delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
+ updateInputRouting();
+ }
+ updateCallAndOutputRouting(forceVolumeReeval, delayMs);
return NO_ERROR;
}
@@ -3169,9 +3263,9 @@
void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs)
{
uint32_t waitMs = 0;
- if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
- DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
- waitMs = updateCallRouting(newDevices, delayMs);
+ if (updateCallRouting(true /*fromCache*/, delayMs, &waitMs) == NO_ERROR) {
+ // Only apply special touch sound delay once
+ delayMs = 0;
}
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
@@ -3181,6 +3275,8 @@
// preventing the force re-routing in case of default dev that distinguishes on address.
// Let's give back to engine full device choice decision however.
waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
+ // Only apply special touch sound delay once
+ delayMs = 0;
}
if (forceVolumeReeval && !newDevices.isEmpty()) {
applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
@@ -3188,30 +3284,124 @@
}
}
-status_t AudioPolicyManager::removePreferredDeviceForStrategy(product_strategy_t strategy)
-{
- ALOGI("%s() strategy=%d", __FUNCTION__, strategy);
+void AudioPolicyManager::updateInputRouting() {
+ for (const auto& activeDesc : mInputs.getActiveInputs()) {
+ auto newDevice = getNewInputDevice(activeDesc);
+ // Force new input selection if the new device can not be reached via current input
+ if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
+ setInputDevice(activeDesc->mIoHandle, newDevice);
+ } else {
+ closeInput(activeDesc->mIoHandle);
+ }
+ }
+}
- status_t status = mEngine->removePreferredDeviceForStrategy(strategy);
+status_t AudioPolicyManager::removeDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role)
+{
+ ALOGI("%s() strategy=%d role=%d", __func__, strategy, role);
+
+ status_t status = mEngine->removeDevicesRoleForStrategy(strategy, role);
if (status != NO_ERROR) {
- ALOGW("Engine could not remove preferred device for strategy %d", strategy);
+ ALOGV("Engine could not remove preferred device for strategy %d status %d",
+ strategy, status);
return status;
}
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+
+ bool forceVolumeReeval = false;
+ // FIXME: workaround for truncated touch sounds
+ // to be removed when the problem is handled by system UI
+ uint32_t delayMs = 0;
+ if (strategy == mCommunnicationStrategy) {
+ forceVolumeReeval = true;
+ delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
+ updateInputRouting();
+ }
+ updateCallAndOutputRouting(forceVolumeReeval, delayMs);
return NO_ERROR;
}
-status_t AudioPolicyManager::getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device) {
- return mEngine->getPreferredDeviceForStrategy(strategy, device);
+status_t AudioPolicyManager::getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices) {
+ return mEngine->getDevicesForRoleAndStrategy(strategy, role, devices);
+}
+
+status_t AudioPolicyManager::setDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector &devices) {
+ ALOGV("%s() audioSource=%d role=%d %s", __func__, audioSource, role,
+ dumpAudioDeviceTypeAddrVector(devices).c_str());
+
+ if (!areAllDevicesSupported(devices, audio_call_is_input_device, __func__)) {
+ return BAD_VALUE;
+ }
+ status_t status = mEngine->setDevicesRoleForCapturePreset(audioSource, role, devices);
+ ALOGW_IF(status != NO_ERROR,
+ "Engine could not set preferred devices %s for audio source %d role %d",
+ dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);
+
+ return status;
+}
+
+status_t AudioPolicyManager::addDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector &devices) {
+ ALOGV("%s() audioSource=%d role=%d %s", __func__, audioSource, role,
+ dumpAudioDeviceTypeAddrVector(devices).c_str());
+
+ if (!areAllDevicesSupported(devices, audio_call_is_input_device, __func__)) {
+ return BAD_VALUE;
+ }
+ status_t status = mEngine->addDevicesRoleForCapturePreset(audioSource, role, devices);
+ ALOGW_IF(status != NO_ERROR,
+ "Engine could not add preferred devices %s for audio source %d role %d",
+ dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);
+
+ updateInputRouting();
+ return status;
+}
+
+status_t AudioPolicyManager::removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector& devices)
+{
+ ALOGV("%s() audioSource=%d role=%d devices=%s", __func__, audioSource, role,
+ dumpAudioDeviceTypeAddrVector(devices).c_str());
+
+ if (!areAllDevicesSupported(devices, audio_call_is_input_device, __func__)) {
+ return BAD_VALUE;
+ }
+
+ status_t status = mEngine->removeDevicesRoleForCapturePreset(
+ audioSource, role, devices);
+ ALOGW_IF(status != NO_ERROR,
+ "Engine could not remove devices role (%d) for capture preset %d", role, audioSource);
+
+ updateInputRouting();
+ return status;
+}
+
+status_t AudioPolicyManager::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role) {
+ ALOGV("%s() audioSource=%d role=%d", __func__, audioSource, role);
+
+ status_t status = mEngine->clearDevicesRoleForCapturePreset(audioSource, role);
+ ALOGW_IF(status != NO_ERROR,
+ "Engine could not clear devices role (%d) for capture preset %d", role, audioSource);
+
+ updateInputRouting();
+ return status;
+}
+
+status_t AudioPolicyManager::getDevicesForRoleAndCapturePreset(
+ audio_source_t audioSource, device_role_t role, AudioDeviceTypeAddrVector &devices) {
+ return mEngine->getDevicesForRoleAndCapturePreset(audioSource, role, devices);
}
status_t AudioPolicyManager::setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices) {
- ALOGI("%s() userId=%d num devices %zu", __FUNCTION__, userId, devices.size());\
+ const AudioDeviceTypeAddrVector& devices) {
+ ALOGI("%s() userId=%d num devices %zu", __func__, userId, devices.size());
if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
return BAD_VALUE;
}
@@ -3270,7 +3460,9 @@
}
dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
+ dst->appendFormat(" Communnication Strategy: %d\n", mCommunnicationStrategy);
dst->appendFormat(" Config source: %s\n", mConfig.getSource().c_str()); // getConfig not const
+
mAvailableOutputDevices.dump(dst, String8("Available output"));
mAvailableInputDevices.dump(dst, String8("Available input"));
mHwModulesAll.dump(dst);
@@ -3676,6 +3868,15 @@
// be incomplete.
PatchBuilder patchBuilder;
audio_port_config sourcePortConfig = {};
+
+ // if first sink is to MSD, establish single MSD patch
+ if (getMsdAudioOutDevices().contains(
+ mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id))) {
+ ALOGV("%s patching to MSD", __FUNCTION__);
+ patchBuilder = buildMsdPatch(false /*msdIsSource*/, srcDevice);
+ goto installPatch;
+ }
+
srcDevice->toAudioPortConfig(&sourcePortConfig, &patch->sources[0]);
patchBuilder.addSource(sourcePortConfig);
@@ -3693,6 +3894,41 @@
sinkDevice->toAudioPortConfig(&sinkPortConfig, &patch->sinks[i]);
patchBuilder.addSink(sinkPortConfig);
+ // Whatever Sw or Hw bridge, we do attach an SwOutput to an Audio Source for
+ // volume management purpose (tracking activity)
+ // In case of Hw bridge, it is a Work Around. The mixPort used is the one declared
+ // in config XML to reach the sink so that is can be declared as available.
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ sp<SwAudioOutputDescriptor> outputDesc = nullptr;
+ if (sourceDesc != nullptr) {
+ // take care of dynamic routing for SwOutput selection,
+ audio_attributes_t attributes = sourceDesc->attributes();
+ audio_stream_type_t stream = sourceDesc->stream();
+ audio_attributes_t resultAttr;
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.sample_rate = sourceDesc->config().sample_rate;
+ config.channel_mask = sourceDesc->config().channel_mask;
+ config.format = sourceDesc->config().format;
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ bool isRequestedDeviceForExclusiveUse = false;
+ output_type_t outputType;
+ getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
+ &stream, sourceDesc->uid(), &config, &flags,
+ &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
+ nullptr, &outputType);
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ ALOGV("%s no output for device %s",
+ __FUNCTION__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
+ outputDesc = mOutputs.valueFor(output);
+ if (outputDesc->isDuplicated()) {
+ ALOGE("%s output is duplicated", __func__);
+ return INVALID_OPERATION;
+ }
+ sourceDesc->setSwOutput(outputDesc);
+ }
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
// - audio HAL version is < 3.0
@@ -3708,49 +3944,25 @@
if (patch->num_sinks > 1) {
return INVALID_OPERATION;
}
- audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- if (sourceDesc != nullptr) {
- // take care of dynamic routing for SwOutput selection,
- audio_attributes_t attributes = sourceDesc->attributes();
- audio_stream_type_t stream = sourceDesc->stream();
- audio_attributes_t resultAttr;
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
- config.sample_rate = sourceDesc->config().sample_rate;
- config.channel_mask = sourceDesc->config().channel_mask;
- config.format = sourceDesc->config().format;
- audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- bool isRequestedDeviceForExclusiveUse = false;
- output_type_t outputType;
- getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
- &stream, sourceDesc->uid(), &config, &flags,
- &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- nullptr, &outputType);
- if (output == AUDIO_IO_HANDLE_NONE) {
- ALOGV("%s no output for device %s",
- __FUNCTION__, sinkDevice->toString().c_str());
- return INVALID_OPERATION;
- }
- } else {
+ if (sourceDesc == nullptr) {
SortedVector<audio_io_handle_t> outputs =
getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
// if the sink device is reachable via an opened output stream, request to
// go via this output stream by adding a second source to the patch
// description
output = selectOutput(outputs);
- }
- if (output != AUDIO_IO_HANDLE_NONE) {
- sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
- if (outputDesc->isDuplicated()) {
- ALOGV("%s output for device %s is duplicated",
- __FUNCTION__, sinkDevice->toString().c_str());
- return INVALID_OPERATION;
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ outputDesc = mOutputs.valueFor(output);
+ if (outputDesc->isDuplicated()) {
+ ALOGV("%s output for device %s is duplicated",
+ __FUNCTION__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
}
+ }
+ if (outputDesc != nullptr) {
audio_port_config srcMixPortConfig = {};
outputDesc->toAudioPortConfig(&srcMixPortConfig, &patch->sources[0]);
- if (sourceDesc != nullptr) {
- sourceDesc->setSwOutput(outputDesc);
- }
// for volume control, we may need a valid stream
srcMixPortConfig.ext.mix.usecase.stream = sourceDesc != nullptr ?
sourceDesc->stream() : AUDIO_STREAM_PATCH;
@@ -3760,6 +3972,7 @@
}
// TODO: check from routing capabilities in config file and other conflicting patches
+installPatch:
status_t status = installPatch(
__func__, index, handle, patchBuilder.patch(), delayMs, uid, &patchDesc);
if (status != NO_ERROR) {
@@ -3841,8 +4054,9 @@
sp<SwAudioOutputDescriptor> outputDesc =
mOutputs.getOutputFromId(patch->sources[1].id);
if (outputDesc == NULL) {
- ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
- return BAD_VALUE;
+ ALOGW("%s output not found for id %d", __func__, patch->sources[0].id);
+ // releaseOutput has already called closeOuput in case of direct output
+ return NO_ERROR;
}
if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
// force SwOutput patch removal as AF counter part patch has already gone.
@@ -4108,15 +4322,19 @@
disconnectAudioSource(sourceDesc);
audio_attributes_t attributes = sourceDesc->attributes();
- sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();
-
+ // May the device (dynamic) have been disconnected/reconnected, id has changed.
+ sp<DeviceDescriptor> srcDevice = mAvailableInputDevices.getDevice(
+ sourceDesc->srcDevice()->type(),
+ String8(sourceDesc->srcDevice()->address().c_str()),
+ AUDIO_FORMAT_DEFAULT);
DeviceVector sinkDevices =
- mEngine->getOutputDevicesForAttributes(attributes, nullptr, true);
+ mEngine->getOutputDevicesForAttributes(attributes, nullptr, false /*fromCache*/);
ALOG_ASSERT(!sinkDevices.isEmpty(), "connectAudioSource(): no device found for attributes");
sp<DeviceDescriptor> sinkDevice = sinkDevices.itemAt(0);
- ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
- __FUNCTION__, sinkDevice->toString().c_str());
-
+ if (!mAvailableOutputDevices.contains(sinkDevice)) {
+ ALOGE("%s Device %s not available", __func__, sinkDevice->toString().c_str());
+ return INVALID_OPERATION;
+ }
PatchBuilder patchBuilder;
patchBuilder.addSink(sinkDevice).addSource(srcDevice);
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
@@ -4126,7 +4344,7 @@
ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
return INVALID_OPERATION;
}
- sourceDesc->setPatchHandle(handle);
+ sourceDesc->connect(handle, sinkDevice);
// SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
if (swOutput != 0) {
@@ -4409,6 +4627,10 @@
status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
{
ALOGV("%s port Id %d", __FUNCTION__, sourceDesc->portId());
+ if (!sourceDesc->isConnected()) {
+ ALOGV("%s port Id %d already disconnected", __FUNCTION__, sourceDesc->portId());
+ return NO_ERROR;
+ }
sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
if (swOutput != 0) {
status_t status = stopSource(swOutput, sourceDesc);
@@ -4424,7 +4646,9 @@
ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
}
}
- return releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+ status_t status = releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+ sourceDesc->disconnect();
+ return status;
}
sp<SourceClientDescriptor> AudioPolicyManager::getSourceForAttributesOnOutput(
@@ -4452,37 +4676,15 @@
}
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
- char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
- std::vector<const char*> fileNames;
- status_t ret;
-
- if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false)) {
- if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false) &&
- property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
- // Both BluetoothAudio@2.0 and BluetoothA2dp@1.0 (Offlaod) are disabled, and uses
- // the legacy hardware module for A2DP and hearing aid.
- fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
- } else if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
- // A2DP offload supported but disabled: try to use special XML file
- fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
+ if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file();
+ !audioPolicyXmlConfigFile.empty()) {
+ status_t ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile.c_str(), &config);
+ if (ret == NO_ERROR) {
+ config.setSource(audioPolicyXmlConfigFile);
}
- } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false)) {
- fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
+ return ret;
}
- fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);
-
- for (const char* fileName : fileNames) {
- for (const auto& path : audio_get_configuration_paths()) {
- snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
- "%s/%s", path.c_str(), fileName);
- ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile, &config);
- if (ret == NO_ERROR) {
- config.setSource(audioPolicyXmlConfigFile);
- return ret;
- }
- }
- }
- return ret;
+ return BAD_VALUE;
}
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
@@ -4558,14 +4760,14 @@
}
}
- if (mPrimaryOutput == 0) {
- ALOGE("Failed to open primary output");
- status = NO_INIT;
- }
+ ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
+ mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
+ mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
+
updateDevicesAndOutputs();
return status;
}
@@ -4671,7 +4873,7 @@
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
}
}
- if (mPrimaryOutput == 0 &&
+ if (mPrimaryOutput == nullptr &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
@@ -4748,6 +4950,10 @@
void AudioPolicyManager::removeOutput(audio_io_handle_t output)
{
+ if (mPrimaryOutput != 0 && mPrimaryOutput == mOutputs.valueFor(output)) {
+ ALOGV("%s: removing primary output", __func__);
+ mPrimaryOutput = nullptr;
+ }
mOutputs.removeItem(output);
selectOutputForMusicEffects();
}
@@ -4906,6 +5112,11 @@
output = AUDIO_IO_HANDLE_NONE;
}
}
+ if (mPrimaryOutput == nullptr
+ && (profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) != 0) {
+ ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
+ mPrimaryOutput = desc;
+ }
}
} else {
output = AUDIO_IO_HANDLE_NONE;
@@ -5161,8 +5372,13 @@
}
}
if (!directOutputOpen) {
- ALOGV("no direct outputs open, reset MSD patch");
- setMsdPatch();
+ ALOGV("no direct outputs open, reset MSD patches");
+ // TODO: The MSD patches to be established here may differ to current MSD patches due to
+ // how output devices for patching are resolved. Avoid by caching and reusing the
+ // arguments to mEngine->getOutputDevicesForAttributes() when resolving which output
+ // devices to patch to. This may be complicated by the fact that devices may become
+ // unavailable.
+ setMsdOutputPatches();
}
}
}
@@ -5229,7 +5445,13 @@
if (onOutputsChecked != nullptr && onOutputsChecked()) checkA2dpSuspend();
updateDevicesAndOutputs();
if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
- setMsdPatch();
+ // TODO: The MSD patches to be established here may differ to current MSD patches due to how
+ // output devices for patching are resolved. Nevertheless, AudioTracks affected by device
+ // configuration changes will ultimately be rerouted correctly. We can still avoid
+ // unnecessary rerouting by caching and reusing the arguments to
+ // mEngine->getOutputDevicesForAttributes() when resolving which output devices to patch to.
+ // This may be complicated by the fact that devices may become unavailable.
+ setMsdOutputPatches();
}
}
@@ -5240,6 +5462,29 @@
mEngine->getProductStrategyForAttributes(rAttr);
}
+void AudioPolicyManager::checkAudioSourceForAttributes(const audio_attributes_t &attr)
+{
+ for (size_t i = 0; i < mAudioSources.size(); i++) {
+ sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+ if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
+ && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE
+ && !isCallRxAudioSource(sourceDesc)) {
+ connectAudioSource(sourceDesc);
+ }
+ }
+}
+
+void AudioPolicyManager::clearAudioSourcesForOutput(audio_io_handle_t output)
+{
+ for (size_t i = 0; i < mAudioSources.size(); i++) {
+ sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+ if (sourceDesc != nullptr && sourceDesc->swOutput().promote() != nullptr
+ && sourceDesc->swOutput().promote()->mIoHandle == output) {
+ disconnectAudioSource(sourceDesc);
+ }
+ }
+}
+
void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr)
{
auto psId = mEngine->getProductStrategyForAttributes(attr);
@@ -5335,7 +5580,7 @@
newDevices.types());
}
sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
- if (source != 0){
+ if (source != nullptr && !isCallRxAudioSource(source)) {
connectAudioSource(source);
}
}
@@ -5358,6 +5603,7 @@
for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
checkOutputForAttributes(attributes);
+ checkAudioSourceForAttributes(attributes);
}
}
@@ -5393,6 +5639,17 @@
}
}
+bool AudioPolicyManager::isScoRequestedForComm() const {
+ AudioDeviceTypeAddrVector devices;
+ mEngine->getDevicesForRoleAndStrategy(mCommunnicationStrategy, DEVICE_ROLE_PREFERRED, devices);
+ for (const auto &device : devices) {
+ if (audio_is_bluetooth_out_sco_device(device.mType)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void AudioPolicyManager::checkA2dpSuspend()
{
audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
@@ -5404,23 +5661,21 @@
bool isScoConnected =
(mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
!Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
+ bool isScoRequested = isScoRequestedForComm();
// if suspended, restore A2DP output if:
// ((SCO device is NOT connected) ||
- // ((forced usage communication is NOT SCO) && (forced usage for record is NOT SCO) &&
+ // ((SCO is not requested) &&
// (phone state is NOT in call) && (phone state is NOT ringing)))
//
// if not suspended, suspend A2DP output if:
// (SCO device is connected) &&
- // ((forced usage for communication is SCO) || (forced usage for record is SCO) ||
+ // ((SCO is requested) ||
// ((phone state is in call) || (phone state is ringing)))
//
if (mA2dpSuspended) {
if (!isScoConnected ||
- ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) !=
- AUDIO_POLICY_FORCE_BT_SCO) &&
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) !=
- AUDIO_POLICY_FORCE_BT_SCO) &&
+ (!isScoRequested &&
(mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
(mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
@@ -5429,10 +5684,7 @@
}
} else {
if (isScoConnected &&
- ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ==
- AUDIO_POLICY_FORCE_BT_SCO) ||
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) ==
- AUDIO_POLICY_FORCE_BT_SCO) ||
+ (isScoRequested ||
(mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
(mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
@@ -5550,8 +5802,8 @@
}
DeviceVector activeDevices;
DeviceVector devices;
- for (audio_stream_type_t curStream = AUDIO_STREAM_MIN; curStream < AUDIO_STREAM_PUBLIC_CNT;
- curStream = (audio_stream_type_t) (curStream + 1)) {
+ for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_PUBLIC_CNT; ++i) {
+ const audio_stream_type_t curStream{static_cast<audio_stream_type_t>(i)};
if (!streamsMatchForvolume(stream, curStream)) {
continue;
}
@@ -5665,7 +5917,7 @@
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
const uint32_t latency = desc->latency() * 2;
- if (latency > maxLatency) {
+ if (desc->isActive(latency * 2) && latency > maxLatency) {
maxLatency = latency;
}
}
@@ -6144,16 +6396,17 @@
bool isVoiceVolSrc = callVolSrc == volumeSource;
bool isBtScoVolSrc = btScoVolSrc == volumeSource;
- audio_policy_forced_cfg_t forceUseForComm =
- mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
+ bool isScoRequested = isScoRequestedForComm();
// do not change in call volume if bluetooth is connected and vice versa
// if sco and call follow same curves, bypass forceUseForComm
if ((callVolSrc != btScoVolSrc) &&
- ((isVoiceVolSrc && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
- (isBtScoVolSrc && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO))) {
- ALOGV("%s cannot set volume group %d volume with force use = %d for comm", __func__,
- volumeSource, forceUseForComm);
- return INVALID_OPERATION;
+ ((isVoiceVolSrc && isScoRequested) ||
+ (isBtScoVolSrc && !isScoRequested))) {
+ ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
+ volumeSource, isScoRequested ? " " : "n ot ");
+ // Do not return an error here as AudioService will always set both voice call
+ // and bluetooth SCO volumes due to stream aliasing.
+ return NO_ERROR;
}
if (deviceTypes.empty()) {
deviceTypes = outputDesc->devices().types();
@@ -6161,9 +6414,8 @@
float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
if (outputDesc->isFixedVolume(deviceTypes) ||
- // Force VoIP volume to max for bluetooth SCO
-
- ((isVoiceVolSrc || isBtScoVolSrc) &&
+ // Force VoIP volume to max for bluetooth SCO device except if muted
+ (index != 0 && (isVoiceVolSrc || isBtScoVolSrc) &&
isSingleDeviceType(deviceTypes, audio_is_bluetooth_out_sco_device))) {
volumeDb = 0.0f;
}
@@ -6323,9 +6575,10 @@
{
for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--) {
sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
- if (sourceDesc->srcDevice()->equals(deviceDesc)) {
- ALOGV("%s releasing audio source %d", __FUNCTION__, sourceDesc->portId());
- stopAudioSource(sourceDesc->portId());
+ if (sourceDesc->isConnected() && (sourceDesc->srcDevice()->equals(deviceDesc) ||
+ sourceDesc->sinkDevice()->equals(deviceDesc))
+ && !isCallRxAudioSource(sourceDesc)) {
+ disconnectAudioSource(sourceDesc);
}
}
@@ -6339,10 +6592,14 @@
release = true;
}
}
+ const char *address = deviceDesc->address().c_str();
for (size_t j = 0; j < patchDesc->mPatch.num_sinks && !release; j++) {
const struct audio_port_config *sink = &patchDesc->mPatch.sinks[j];
if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- sink->ext.device.type == deviceDesc->type()) {
+ sink->ext.device.type == deviceDesc->type() &&
+ (strnlen(address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0
+ || strncmp(sink->ext.device.address, address,
+ AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
release = true;
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index b588f89..5533829 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -263,17 +263,42 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
virtual status_t setUidDeviceAffinities(uid_t uid,
- const Vector<AudioDeviceTypeAddr>& devices);
+ const AudioDeviceTypeAddrVector& devices);
virtual status_t removeUidDeviceAffinities(uid_t uid);
virtual status_t setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices);
+ const AudioDeviceTypeAddrVector& devices);
virtual status_t removeUserIdDeviceAffinities(int userId);
- virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device);
- virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
- virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device);
+ virtual status_t setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t removeDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role);
+
+
+ virtual status_t getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector& devices);
+
+ virtual status_t clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role);
+
+ virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices);
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
@@ -531,6 +556,20 @@
*/
void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
+ bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
+ return mCallRxSourceClientPort != AUDIO_PORT_HANDLE_NONE
+ && source == mAudioSources.valueFor(mCallRxSourceClientPort);
+ }
+
+ void connectTelephonyRxAudioSource();
+
+ void disconnectTelephonyRxAudioSource();
+
+ /**
+ * @brief updates routing for all inputs.
+ */
+ void updateInputRouting();
+
/**
* @brief checkOutputForAttributes checks and if necessary changes outputs used for the
* given audio attributes.
@@ -541,6 +580,16 @@
*/
void checkOutputForAttributes(const audio_attributes_t &attr);
+ /**
+ * @brief checkAudioSourceForAttributes checks if any AudioSource following the same routing
+ * as the given audio attributes is not routed and try to connect it.
+ * It must be called once checkOutputForAttributes has been called for orphans AudioSource,
+ * aka AudioSource not attached to any Audio Output (e.g. AudioSource connected to direct
+ * Output which has been disconnected (and output closed) due to sink device unavailable).
+ * @param attr to be considered
+ */
+ void checkAudioSourceForAttributes(const audio_attributes_t &attr);
+
bool followsSameRouting(const audio_attributes_t &lAttr,
const audio_attributes_t &rAttr) const;
@@ -680,9 +729,22 @@
String8(devices.itemAt(0)->address().c_str()) : String8("");
}
- uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0);
+ status_t updateCallRouting(
+ bool fromCache, uint32_t delayMs = 0, uint32_t *waitMs = nullptr);
+ status_t updateCallRoutingInternal(
+ const DeviceVector &rxDevices, uint32_t delayMs, uint32_t *waitMs);
sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device,
uint32_t delayMs);
+ /**
+ * @brief selectBestRxSinkDevicesForCall: if the primary module host both Telephony Rx/Tx
+ * devices, and it declares also supporting a HW bridge between the Telephony Rx and the
+ * given sink device for Voice Call audio attributes, select this device in prio.
+ * Otherwise, getNewOutputDevices() is called on the primary output to select sink device.
+ * @param fromCache true to prevent engine reconsidering all product strategies and retrieve
+ * from engine cache.
+ * @return vector of devices, empty if none is found.
+ */
+ DeviceVector selectBestRxSinkDevicesForCall(bool fromCache);
bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const;
status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
@@ -709,6 +771,7 @@
sp<SourceClientDescriptor> getSourceForAttributesOnOutput(audio_io_handle_t output,
const audio_attributes_t &attr);
+ void clearAudioSourcesForOutput(audio_io_handle_t output);
void cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc);
@@ -755,7 +818,6 @@
SoundTriggerSessionCollection mSoundTriggerSessions;
sp<AudioPatch> mCallTxPatch;
- sp<AudioPatch> mCallRxPatch;
HwAudioOutputCollection mHwOutputs;
SourceClientCollection mAudioSources;
@@ -787,6 +849,33 @@
std::unordered_set<audio_format_t> mManualSurroundFormats;
std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
+
+ // Cached product strategy ID corresponding to legacy strategy STRATEGY_PHONE
+ product_strategy_t mCommunnicationStrategy;
+
+ // The port handle of the hardware audio source created internally for the Call RX audio
+ // end point.
+ audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+
+ // Support for Multi-Stream Decoder (MSD) module
+ sp<DeviceDescriptor> getMsdAudioInDevice() const;
+ DeviceVector getMsdAudioOutDevices() const;
+ const AudioPatchCollection getMsdOutputPatches() const;
+ status_t getMsdProfiles(bool hwAvSync,
+ const InputProfileCollection &inputProfiles,
+ const OutputProfileCollection &outputProfiles,
+ const sp<DeviceDescriptor> &sourceDevice,
+ const sp<DeviceDescriptor> &sinkDevice,
+ AudioProfileVector &sourceProfiles,
+ AudioProfileVector &sinkProfiles) const;
+ status_t getBestMsdConfig(bool hwAvSync,
+ const AudioProfileVector &sourceProfiles,
+ const AudioProfileVector &sinkProfiles,
+ audio_port_config *sourceConfig,
+ audio_port_config *sinkConfig) const;
+ PatchBuilder buildMsdPatch(bool msdIsSource, const sp<DeviceDescriptor> &device) const;
+ status_t setMsdOutputPatches(const DeviceVector *outputDevices = nullptr);
+ void releaseMsdOutputPatches(const DeviceVector& devices);
private:
void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
@@ -794,17 +883,6 @@
void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
- // Support for Multi-Stream Decoder (MSD) module
- sp<DeviceDescriptor> getMsdAudioInDevice() const;
- DeviceVector getMsdAudioOutDevices() const;
- const AudioPatchCollection getMsdPatches() const;
- status_t getBestMsdAudioProfileFor(const sp<DeviceDescriptor> &outputDevice,
- bool hwAvSync,
- audio_port_config *sourceConfig,
- audio_port_config *sinkConfig) const;
- PatchBuilder buildMsdPatch(const sp<DeviceDescriptor> &outputDevice) const;
- status_t setMsdPatch(const sp<DeviceDescriptor> &outputDevice = nullptr);
-
// If any, resolve any "dynamic" fields of an Audio Profiles collection
void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
AudioProfileVector &profiles);
@@ -938,10 +1016,11 @@
sp<AudioPatch> *patchDescPtr);
bool areAllDevicesSupported(
- const Vector<AudioDeviceTypeAddr>& devices,
+ const AudioDeviceTypeAddrVector& devices,
std::function<bool(audio_devices_t)> predicate,
const char* context);
+ bool isScoRequestedForComm() const;
};
};
diff --git a/services/audiopolicy/service/Android.mk b/services/audiopolicy/service/Android.mk
index 680b077..7015b7b 100644
--- a/services/audiopolicy/service/Android.mk
+++ b/services/audiopolicy/service/Android.mk
@@ -42,9 +42,11 @@
libaudiopolicycomponents
LOCAL_MODULE:= libaudiopolicyservice
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../../NOTICE
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_CFLAGS += -Wall -Werror -Wthread-safety
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index b738633..5dac55b 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -970,7 +970,7 @@
for (const auto& deviceEffectsIter : mDeviceEffects) {
const auto& deviceEffects = deviceEffectsIter.second;
for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
- auto fx = std::make_unique<AudioEffect>(String16("android"));
+ sp<AudioEffect> fx = new AudioEffect(String16("android"));
fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0, nullptr,
nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
@@ -987,7 +987,7 @@
ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
effectDesc->mName, deviceEffects->getDeviceType(),
deviceEffects->getDeviceAddress().c_str());
- deviceEffects->mEffects.push_back(std::move(fx));
+ deviceEffects->mEffects.push_back(fx);
}
}
}
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 81c728d..13d5d0c 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -207,7 +207,7 @@
mDeviceType(device), mDeviceAddress(address) {}
/*virtual*/ ~DeviceEffects() = default;
- std::vector<std::unique_ptr<AudioEffect>> mEffects;
+ std::vector< sp<AudioEffect> > mEffects;
audio_devices_t getDeviceType() const { return mDeviceType; }
std::string getDeviceAddress() const { return mDeviceAddress; }
const std::unique_ptr<EffectDescVector> mEffectDescriptors;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 34d07b6..dcd30f6 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -244,11 +244,12 @@
uid = callingUid;
}
if (!mPackageManager.allowPlaybackCapture(uid)) {
- attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
+ attr->flags = static_cast<audio_flags_mask_t>(attr->flags | AUDIO_FLAG_NO_MEDIA_PROJECTION);
}
if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
&& !bypassInterruptionPolicyAllowed(pid, uid)) {
- attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
+ attr->flags = static_cast<audio_flags_mask_t>(
+ attr->flags & ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE));
}
AutoCallerClear acc;
AudioPolicyInterface::output_type_t outputType;
@@ -572,7 +573,8 @@
}
// check calling permissions
- if (!(startRecording(client->opPackageName, client->pid, client->uid)
+ if (!(startRecording(client->opPackageName, client->pid, client->uid,
+ client->attributes.source == AUDIO_SOURCE_HOTWORD)
|| client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, client->uid, client->pid);
@@ -660,7 +662,8 @@
client->active = false;
client->startTimeNs = 0;
updateUidStates_l();
- finishRecording(client->opPackageName, client->uid);
+ finishRecording(client->opPackageName, client->uid,
+ client->attributes.source == AUDIO_SOURCE_HOTWORD);
}
return status;
@@ -686,7 +689,8 @@
updateUidStates_l();
// finish the recording app op
- finishRecording(client->opPackageName, client->uid);
+ finishRecording(client->opPackageName, client->uid,
+ client->attributes.source == AUDIO_SOURCE_HOTWORD);
AutoCallerClear acc;
return mAudioPolicyManager->stopInput(portId);
}
@@ -1257,7 +1261,7 @@
}
status_t AudioPolicyService::setUidDeviceAffinities(uid_t uid,
- const Vector<AudioDeviceTypeAddr>& devices) {
+ const AudioDeviceTypeAddrVector& devices) {
Mutex::Autolock _l(mLock);
if(!modifyAudioRoutingAllowed()) {
return PERMISSION_DENIED;
@@ -1282,7 +1286,7 @@
}
status_t AudioPolicyService::setUserIdDeviceAffinities(int userId,
- const Vector<AudioDeviceTypeAddr>& devices) {
+ const AudioDeviceTypeAddrVector& devices) {
Mutex::Autolock _l(mLock);
if(!modifyAudioRoutingAllowed()) {
return PERMISSION_DENIED;
@@ -1494,33 +1498,36 @@
return mAudioPolicyManager->isCallScreenModeSupported();
}
-status_t AudioPolicyService::setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device)
+status_t AudioPolicyService::setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mAudioPolicyManager->setPreferredDeviceForStrategy(strategy, device);
+ return mAudioPolicyManager->setDevicesRoleForStrategy(strategy, role, devices);
}
-status_t AudioPolicyService::removePreferredDeviceForStrategy(product_strategy_t strategy)
+status_t AudioPolicyService::removeDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mAudioPolicyManager->removePreferredDeviceForStrategy(strategy);
+ return mAudioPolicyManager->removeDevicesRoleForStrategy(strategy, role);
}
-status_t AudioPolicyService::getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device)
+status_t AudioPolicyService::getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mAudioPolicyManager->getPreferredDeviceForStrategy(strategy, device);
+ return mAudioPolicyManager->getDevicesForRoleAndStrategy(strategy, role, devices);
}
status_t AudioPolicyService::registerSoundTriggerCaptureStateListener(
@@ -1531,4 +1538,55 @@
return NO_ERROR;
}
+status_t AudioPolicyService::setDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector &devices)
+{
+ if (mAudioPolicyManager == nullptr) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->setDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t AudioPolicyService::addDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector &devices)
+{
+ if (mAudioPolicyManager == nullptr) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->addDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t AudioPolicyService::removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role, const AudioDeviceTypeAddrVector& devices)
+{
+ if (mAudioPolicyManager == nullptr) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->removeDevicesRoleForCapturePreset(audioSource, role, devices);
+}
+
+status_t AudioPolicyService::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role)
+{
+ if (mAudioPolicyManager == nullptr) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->clearDevicesRoleForCapturePreset(audioSource, role);
+}
+
+status_t AudioPolicyService::getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices)
+{
+ if (mAudioPolicyManager == nullptr) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices);
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e847f9f..a6e8989 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -488,9 +488,9 @@
}
bool isAccessibility = mUidPolicy->isA11yUid(current->uid);
- // Clients capturing for Accessibility services are not considered
+ // Clients capturing for Accessibility services or virtual sources are not considered
// for top or latest active to avoid masking regular clients started before
- if (!isAccessibility) {
+ if (!isAccessibility && !isVirtualSource(current->attributes.source)) {
bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
bool isPrivacySensitive =
(current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 869a963..0b218c2 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -226,19 +226,41 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
- virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+ virtual status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices);
virtual status_t removeUidDeviceAffinities(uid_t uid);
- virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
- const AudioDeviceTypeAddr &device);
+ virtual status_t setDevicesRoleForStrategy(product_strategy_t strategy,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices);
- virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
+ virtual status_t removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role);
+ virtual status_t getDevicesForRoleAndStrategy(product_strategy_t strategy,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices);
- virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
- AudioDeviceTypeAddr &device);
- virtual status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+ virtual status_t setDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t addDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ const AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t removeDevicesRoleForCapturePreset(
+ audio_source_t audioSource, device_role_t role,
+ const AudioDeviceTypeAddrVector& devices);
+
+ virtual status_t clearDevicesRoleForCapturePreset(audio_source_t audioSource,
+ device_role_t role);
+
+ virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
+ device_role_t role,
+ AudioDeviceTypeAddrVector &devices);
+
+ virtual status_t setUserIdDeviceAffinities(int userId,
+ const AudioDeviceTypeAddrVector& devices);
virtual status_t removeUserIdDeviceAffinities(int userId);
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index efdb241..42f0342 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "audiopolicy_tests",
@@ -18,7 +27,10 @@
"libxml2",
],
- static_libs: ["libaudiopolicycomponents"],
+ static_libs: [
+ "libaudiopolicycomponents",
+ "libgmock"
+ ],
header_libs: [
"libaudiopolicycommon",
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 8bab020..6150206 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -29,6 +29,9 @@
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
+ using AudioPolicyManager::releaseMsdOutputPatches;
+ using AudioPolicyManager::setMsdOutputPatches;
+ using AudioPolicyManager::getAudioPatches;
uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index b5c67a1..e1634cf 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include <media/AudioSystem.h>
+#include <media/TypeConverter.h>
#include <system/audio.h>
#include <utils/Log.h>
@@ -68,9 +69,18 @@
ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
for (auto desc : manager.getConfig().getInputDevices()) {
- ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
+ if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
+ std::string deviceType;
+ (void)DeviceConverter::toString(desc->type(), deviceType);
+ ADD_FAILURE() << "Input device \"" << deviceType << "\" not found";
+ }
}
for (auto desc : manager.getConfig().getOutputDevices()) {
- ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
+ if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
+ std::string deviceType;
+ (void)DeviceConverter::toString(desc->type(), deviceType);
+ ADD_FAILURE() << "Output device \"" << deviceType << "\" not found";
+ }
}
}
+
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index a0074bc..a3d6db0 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <gtest/gtest.h>
+#include <gmock/gmock.h>
#define LOG_TAG "APM_Test"
#include <Serializer.h>
@@ -36,6 +37,7 @@
#include "AudioPolicyTestManager.h"
using namespace android;
+using testing::UnorderedElementsAre;
TEST(AudioPolicyManagerTestInit, EngineFailure) {
AudioPolicyTestClient client;
@@ -56,6 +58,34 @@
ASSERT_EQ(NO_INIT, manager.initCheck());
}
+// Verifies that a failure while loading a config doesn't leave
+// APM config in a "dirty" state. Since AudioPolicyConfig object
+// is a proxy for the data hosted by APM, it isn't possible
+// to "deep copy" it, and thus we have to test its elements
+// individually.
+TEST(AudioPolicyManagerTestInit, ConfigLoadingIsTransactional) {
+ AudioPolicyTestClient client;
+ AudioPolicyTestManager manager(&client);
+ ASSERT_TRUE(manager.getConfig().getHwModules().isEmpty());
+ ASSERT_TRUE(manager.getConfig().getInputDevices().isEmpty());
+ ASSERT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
+ status_t status = deserializeAudioPolicyFile(
+ (base::GetExecutableDirectory() +
+ "/test_invalid_audio_policy_configuration.xml").c_str(),
+ &manager.getConfig());
+ ASSERT_NE(NO_ERROR, status);
+ EXPECT_TRUE(manager.getConfig().getHwModules().isEmpty());
+ EXPECT_TRUE(manager.getConfig().getInputDevices().isEmpty());
+ EXPECT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
+ status = deserializeAudioPolicyFile(
+ (base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml").c_str(),
+ &manager.getConfig());
+ ASSERT_EQ(NO_ERROR, status);
+ EXPECT_FALSE(manager.getConfig().getHwModules().isEmpty());
+ EXPECT_FALSE(manager.getConfig().getInputDevices().isEmpty());
+ EXPECT_FALSE(manager.getConfig().getOutputDevices().isEmpty());
+}
+
class PatchCountCheck {
public:
@@ -87,7 +117,7 @@
void getOutputForAttr(
audio_port_handle_t *selectedDeviceId,
audio_format_t format,
- int channelMask,
+ audio_channel_mask_t channelMask,
int sampleRate,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
audio_io_handle_t *output = nullptr,
@@ -98,7 +128,7 @@
audio_unique_id_t riid,
audio_port_handle_t *selectedDeviceId,
audio_format_t format,
- int channelMask,
+ audio_channel_mask_t channelMask,
int sampleRate,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
audio_port_handle_t *portId = nullptr);
@@ -164,7 +194,7 @@
void AudioPolicyManagerTest::getOutputForAttr(
audio_port_handle_t *selectedDeviceId,
audio_format_t format,
- int channelMask,
+ audio_channel_mask_t channelMask,
int sampleRate,
audio_output_flags_t flags,
audio_io_handle_t *output,
@@ -194,7 +224,7 @@
audio_unique_id_t riid,
audio_port_handle_t *selectedDeviceId,
audio_format_t format,
- int channelMask,
+ audio_channel_mask_t channelMask,
int sampleRate,
audio_input_flags_t flags,
audio_port_handle_t *portId) {
@@ -317,15 +347,46 @@
// TODO: Add patch creation tests that involve already existing patch
-class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
+enum
+{
+ MSD_AUDIO_PATCH_COUNT_NUM_AUDIO_PATCHES_INDEX = 0,
+ MSD_AUDIO_PATCH_COUNT_NAME_INDEX = 1
+};
+using MsdAudioPatchCountSpecification = std::tuple<size_t, std::string>;
+
+class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest,
+ public ::testing::WithParamInterface<MsdAudioPatchCountSpecification> {
+ public:
+ AudioPolicyManagerTestMsd();
protected:
void SetUpManagerConfig() override;
void TearDown() override;
sp<DeviceDescriptor> mMsdOutputDevice;
sp<DeviceDescriptor> mMsdInputDevice;
+ sp<DeviceDescriptor> mDefaultOutputDevice;
+
+ const size_t mExpectedAudioPatchCount;
+ sp<DeviceDescriptor> mSpdifDevice;
+
+ sp<DeviceDescriptor> mHdmiInputDevice;
};
+AudioPolicyManagerTestMsd::AudioPolicyManagerTestMsd()
+ : mExpectedAudioPatchCount(std::get<MSD_AUDIO_PATCH_COUNT_NUM_AUDIO_PATCHES_INDEX>(
+ GetParam())) {}
+
+INSTANTIATE_TEST_CASE_P(
+ MsdAudioPatchCount,
+ AudioPolicyManagerTestMsd,
+ ::testing::Values(
+ MsdAudioPatchCountSpecification(1u, "single"),
+ MsdAudioPatchCountSpecification(2u, "dual")
+ ),
+ [](const ::testing::TestParamInfo<MsdAudioPatchCountSpecification> &info) {
+ return std::get<MSD_AUDIO_PATCH_COUNT_NAME_INDEX>(info.param); }
+);
+
void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
// TODO: Consider using Serializer to load part of the config from a string.
AudioPolicyManagerTest::SetUpManagerConfig();
@@ -335,8 +396,11 @@
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
sp<AudioProfile> ac3OutputProfile = new AudioProfile(
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+ sp<AudioProfile> iec958OutputProfile = new AudioProfile(
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, 48000);
mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
+ mMsdOutputDevice->addAudioProfile(iec958OutputProfile);
mMsdInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUS);
// Match output profile from AudioPolicyConfig::setDefault.
sp<AudioProfile> pcmInputProfile = new AudioProfile(
@@ -345,6 +409,19 @@
config.addDevice(mMsdOutputDevice);
config.addDevice(mMsdInputDevice);
+ if (mExpectedAudioPatchCount == 2) {
+ // Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
+ mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
+ mSpdifDevice->addAudioProfile(pcmOutputProfile);
+ config.addDevice(mSpdifDevice);
+
+ sp<OutputProfile> spdifOutputProfile = new OutputProfile("spdif output");
+ spdifOutputProfile->addAudioProfile(pcmOutputProfile);
+ spdifOutputProfile->addSupportedDevice(mSpdifDevice);
+ config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ addOutputProfile(spdifOutputProfile);
+ }
+
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
HwModuleCollection modules = config.getHwModules();
modules.add(msdModule);
@@ -361,6 +438,11 @@
AUDIO_OUTPUT_FLAG_NON_BLOCKING);
msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
msdModule->addOutputProfile(msdCompressedOutputProfile);
+ sp<OutputProfile> msdIec958OutputProfile = new OutputProfile("msd iec958 input");
+ msdIec958OutputProfile->addAudioProfile(iec958OutputProfile);
+ msdIec958OutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
+ msdIec958OutputProfile->addSupportedDevice(mMsdOutputDevice);
+ msdModule->addOutputProfile(msdIec958OutputProfile);
sp<InputProfile> msdInputProfile = new InputProfile("msd output");
msdInputProfile->addAudioProfile(pcmInputProfile);
@@ -378,62 +460,104 @@
primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(primaryEncodedOutputProfile);
+
+ mDefaultOutputDevice = config.getDefaultOutputDevice();
+ if (mExpectedAudioPatchCount == 2) {
+ mSpdifDevice->addAudioProfile(dtsOutputProfile);
+ primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
+ }
+
+ // Add HDMI input device with IEC60958 profile for HDMI in -> MSD patching.
+ mHdmiInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_HDMI);
+ sp<AudioProfile> iec958InputProfile = new AudioProfile(
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, 48000);
+ mHdmiInputDevice->addAudioProfile(iec958InputProfile);
+ config.addDevice(mHdmiInputDevice);
+ sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
+ hdmiInputProfile->addAudioProfile(iec958InputProfile);
+ hdmiInputProfile->setFlags(AUDIO_INPUT_FLAG_DIRECT);
+ hdmiInputProfile->addSupportedDevice(mHdmiInputDevice);
+ config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ addInputProfile(hdmiInputProfile);
}
void AudioPolicyManagerTestMsd::TearDown() {
mMsdOutputDevice.clear();
mMsdInputDevice.clear();
+ mDefaultOutputDevice.clear();
+ mSpdifDevice.clear();
+ mHdmiInputDevice.clear();
AudioPolicyManagerTest::TearDown();
}
-TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
+TEST_P(AudioPolicyManagerTestMsd, InitSuccess) {
ASSERT_TRUE(mMsdOutputDevice);
ASSERT_TRUE(mMsdInputDevice);
+ ASSERT_TRUE(mDefaultOutputDevice);
}
-TEST_F(AudioPolicyManagerTestMsd, Dump) {
+TEST_P(AudioPolicyManagerTestMsd, Dump) {
dumpToLog();
}
-TEST_F(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
const PatchCountCheck patchCount = snapshotPatchCount();
mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationSetReleaseMsdOutputPatches) {
+ const PatchCountCheck patchCount = snapshotPatchCount();
+ DeviceVector devices = mManager->getAvailableOutputDevices();
+ // Remove MSD output device to avoid patching to itself
+ devices.remove(mMsdOutputDevice);
+ ASSERT_EQ(mExpectedAudioPatchCount, devices.size());
+ mManager->setMsdOutputPatches(&devices);
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ // Dual patch: exercise creating one new audio patch and reusing another existing audio patch.
+ DeviceVector singleDevice(devices[0]);
+ mManager->releaseMsdOutputPatches(singleDevice);
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
+ mManager->setMsdOutputPatches(&devices);
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ mManager->releaseMsdOutputPatches(devices);
+ ASSERT_EQ(0, patchCount.deltaFromSnapshot());
+}
+
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
@@ -442,7 +566,7 @@
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
// Switch between formats that are supported and not supported by MSD.
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -451,10 +575,10 @@
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -464,7 +588,7 @@
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(-1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(-static_cast<int>(mExpectedAudioPatchCount), patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
@@ -473,11 +597,39 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
- ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
}
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationFromHdmiInToMsd) {
+ audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+ uid_t uid = 42;
+ const PatchCountCheck patchCount = snapshotPatchCount();
+ ASSERT_FALSE(mManager->getAvailableInputDevices().isEmpty());
+ PatchBuilder patchBuilder;
+ patchBuilder.
+ addSource(mManager->getAvailableInputDevices().
+ getDevice(AUDIO_DEVICE_IN_HDMI, String8(""), AUDIO_FORMAT_DEFAULT)).
+ addSink(mManager->getAvailableOutputDevices().
+ getDevice(AUDIO_DEVICE_OUT_BUS, String8(""), AUDIO_FORMAT_DEFAULT));
+ ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
+ ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
+ AudioPatchCollection patches = mManager->getAudioPatches();
+ sp<AudioPatch> patch = patches.valueFor(handle);
+ ASSERT_EQ(1, patch->mPatch.num_sources);
+ ASSERT_EQ(1, patch->mPatch.num_sinks);
+ ASSERT_EQ(AUDIO_PORT_ROLE_SOURCE, patch->mPatch.sources[0].role);
+ ASSERT_EQ(AUDIO_PORT_ROLE_SINK, patch->mPatch.sinks[0].role);
+ ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sources[0].format);
+ ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sinks[0].format);
+ ASSERT_EQ(AUDIO_CHANNEL_IN_STEREO, patch->mPatch.sources[0].channel_mask);
+ ASSERT_EQ(AUDIO_CHANNEL_OUT_STEREO, patch->mPatch.sinks[0].channel_mask);
+ ASSERT_EQ(48000, patch->mPatch.sources[0].sample_rate);
+ ASSERT_EQ(48000, patch->mPatch.sinks[0].sample_rate);
+ ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+}
+
class AudioPolicyManagerTestWithConfigurationFile : public AudioPolicyManagerTest {
protected:
void SetUpManagerConfig() override;
@@ -707,7 +859,8 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
- audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, 0, ""};
+ audio_attributes_t attr = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
std::string tags = "addr=" + mMixAddress;
strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
getInputForAttr(attr, mTracker->getRiid(), &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
@@ -757,9 +910,9 @@
AudioPolicyManagerTestDPPlaybackReRouting,
testing::Values(
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
- AUDIO_SOURCE_DEFAULT, 0, ""}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
)
);
@@ -768,47 +921,47 @@
AudioPolicyManagerTestDPPlaybackReRouting,
testing::Values(
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
- AUDIO_USAGE_ASSISTANCE_SONIFICATION,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VIRTUAL_SOURCE,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
- AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"}
)
);
@@ -817,41 +970,41 @@
AudioPolicyManagerTestDPPlaybackReRouting,
testing::Values(
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
AUDIO_USAGE_ASSISTANCE_SONIFICATION,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
- AUDIO_SOURCE_DEFAULT, 0, ""},
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
- AUDIO_SOURCE_DEFAULT, 0, ""}
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
)
);
@@ -892,7 +1045,8 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_usage_t usage = AUDIO_USAGE_VIRTUAL_SOURCE;
- audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, 0, ""};
+ audio_attributes_t attr =
+ {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
std::string tags = std::string("addr=") + mMixAddress;
strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
@@ -941,17 +1095,19 @@
AudioPolicyManagerTestDPMixRecordInjection,
testing::Values(
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_CAMCORDER, 0, ""},
+ AUDIO_SOURCE_CAMCORDER, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_CAMCORDER, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_CAMCORDER, AUDIO_FLAG_NONE,
+ "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_MIC, 0, "addr=remote_submix_media"},
+ AUDIO_SOURCE_MIC, AUDIO_FLAG_NONE,
+ "addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_MIC, 0, ""},
+ AUDIO_SOURCE_MIC, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_VOICE_COMMUNICATION, 0, ""},
+ AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_VOICE_COMMUNICATION, 0,
+ AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE,
"addr=remote_submix_media"}
)
);
@@ -962,14 +1118,15 @@
AudioPolicyManagerTestDPMixRecordInjection,
testing::Values(
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_VOICE_RECOGNITION, 0, ""},
+ AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_HOTWORD, 0, ""},
+ AUDIO_SOURCE_HOTWORD, AUDIO_FLAG_NONE, ""},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_VOICE_RECOGNITION, 0,
+ AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_FLAG_NONE,
"addr=remote_submix_media"},
(audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_HOTWORD, 0, "addr=remote_submix_media"}
+ AUDIO_SOURCE_HOTWORD, AUDIO_FLAG_NONE,
+ "addr=remote_submix_media"}
)
);
@@ -1188,3 +1345,109 @@
EXPECT_GT(mClient->getAudioPortListUpdateCount(), prevAudioPortListUpdateCount);
EXPECT_GT(mManager->getAudioPortGeneration(), prevAudioPortGeneration);
}
+
+using DevicesRoleForCapturePresetParam = std::tuple<audio_source_t, device_role_t>;
+
+class AudioPolicyManagerDevicesRoleForCapturePresetTest
+ : public AudioPolicyManagerTestWithConfigurationFile,
+ public testing::WithParamInterface<DevicesRoleForCapturePresetParam> {
+protected:
+ // The `inputDevice` and `inputDevice2` indicate the audio devices type to be used for setting
+ // device role. They must be declared in the test_audio_policy_configuration.xml
+ AudioDeviceTypeAddr inputDevice = AudioDeviceTypeAddr(AUDIO_DEVICE_IN_BUILTIN_MIC, "");
+ AudioDeviceTypeAddr inputDevice2 = AudioDeviceTypeAddr(AUDIO_DEVICE_IN_HDMI, "");
+};
+
+TEST_P(AudioPolicyManagerDevicesRoleForCapturePresetTest, DevicesRoleForCapturePreset) {
+ const audio_source_t audioSource = std::get<0>(GetParam());
+ const device_role_t role = std::get<1>(GetParam());
+
+ // Test invalid device when setting
+ const AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+ const AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+ ASSERT_EQ(BAD_VALUE,
+ mManager->setDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+ ASSERT_EQ(BAD_VALUE,
+ mManager->addDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+ AudioDeviceTypeAddrVector devices;
+ ASSERT_EQ(NAME_NOT_FOUND,
+ mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ ASSERT_TRUE(devices.empty());
+ ASSERT_EQ(BAD_VALUE,
+ mManager->removeDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+
+ // Without setting, call get/remove/clear must fail
+ ASSERT_EQ(NAME_NOT_FOUND,
+ mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ ASSERT_EQ(NAME_NOT_FOUND,
+ mManager->removeDevicesRoleForCapturePreset(audioSource, role, devices));
+ ASSERT_EQ(NAME_NOT_FOUND,
+ mManager->clearDevicesRoleForCapturePreset(audioSource, role));
+
+ // Test set/get devices role
+ const AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+ ASSERT_EQ(NO_ERROR,
+ mManager->setDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+ ASSERT_EQ(NO_ERROR, mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_THAT(devices, UnorderedElementsAre(inputDevice));
+
+ // Test setting will change the previously set devices
+ const AudioDeviceTypeAddrVector inputDevices2 = {inputDevice2};
+ ASSERT_EQ(NO_ERROR,
+ mManager->setDevicesRoleForCapturePreset(audioSource, role, inputDevices2));
+ devices.clear();
+ ASSERT_EQ(NO_ERROR, mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_THAT(devices, UnorderedElementsAre(inputDevice2));
+
+ // Test add devices
+ ASSERT_EQ(NO_ERROR,
+ mManager->addDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+ devices.clear();
+ ASSERT_EQ(NO_ERROR, mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_THAT(devices, UnorderedElementsAre(inputDevice, inputDevice2));
+
+ // Test remove devices
+ ASSERT_EQ(NO_ERROR,
+ mManager->removeDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+ devices.clear();
+ ASSERT_EQ(NO_ERROR, mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+ EXPECT_THAT(devices, UnorderedElementsAre(inputDevice2));
+
+ // Test remove devices that are not set as the device role
+ ASSERT_EQ(BAD_VALUE,
+ mManager->removeDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+
+ // Test clear devices
+ ASSERT_EQ(NO_ERROR,
+ mManager->clearDevicesRoleForCapturePreset(audioSource, role));
+ devices.clear();
+ ASSERT_EQ(NAME_NOT_FOUND,
+ mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ DevicesRoleForCapturePresetOperation,
+ AudioPolicyManagerDevicesRoleForCapturePresetTest,
+ testing::Values(
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_MIC, DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_VOICE_UPLINK,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_VOICE_DOWNLINK,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_VOICE_CALL, DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_CAMCORDER, DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_VOICE_RECOGNITION,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_VOICE_COMMUNICATION,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_REMOTE_SUBMIX,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_UNPROCESSED, DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_VOICE_PERFORMANCE,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_ECHO_REFERENCE,
+ DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_FM_TUNER, DEVICE_ROLE_PREFERRED}),
+ DevicesRoleForCapturePresetParam({AUDIO_SOURCE_HOTWORD, DEVICE_ROLE_PREFERRED})
+ )
+ );
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
index d9476d9..630bbcf 100644
--- a/services/audiopolicy/tests/resources/Android.bp
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -1,8 +1,20 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
filegroup {
name: "audiopolicytest_configuration_files",
srcs: [
"test_audio_policy_configuration.xml",
"test_audio_policy_primary_only_configuration.xml",
+ "test_invalid_audio_policy_configuration.xml",
"test_tv_apm_configuration.xml",
],
}
diff --git a/services/audiopolicy/tests/resources/test_invalid_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_invalid_audio_policy_configuration.xml
new file mode 100644
index 0000000..25641d5
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_invalid_audio_policy_configuration.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This file contains an unnamed device port in the "r_submix" module section. -->
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="true"/>
+
+ <modules>
+ <!-- Primary module -->
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bt_hfp_output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bt_hfp_input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,16000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
+ </devicePort>
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ </devicePort>
+ <devicePort tagName="Hdmi" type="AUDIO_DEVICE_OUT_HDMI" role="sink">
+ </devicePort>
+ <devicePort tagName="Hdmi-In Mic" type="AUDIO_DEVICE_IN_HDMI" role="source">
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"
+ role="sink" address="hfp_client_out">
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"
+ role="source" address="hfp_client_in">
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Speaker"
+ sources="primary output"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Hdmi-In Mic"/>
+ <route type="mix" sink="Hdmi"
+ sources="primary output"/>
+ <route type="mix" sink="BT SCO"
+ sources="mixport_bt_hfp_output"/>
+ <route type="mix" sink="mixport_bt_hfp_input"
+ sources="BT SCO Headset Mic"/>
+ </routes>
+ </module>
+
+ <!-- Remote Submix module -->
+ <module name="r_submix" halVersion="2.0">
+ <attachedDevices>
+ <item>Remote Submix In</item>
+ </attachedDevices>
+ <mixPorts>
+ <mixPort name="r_submix output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="r_submix input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <!-- This port is missing "tagName" attribute. -->
+ <devicePort type="AUDIO_DEVICE_OUT_REMOTE_SUBMIX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Remote Submix In" type="AUDIO_DEVICE_IN_REMOTE_SUBMIX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Remote Submix Out"
+ sources="r_submix output"/>
+ <route type="mix" sink="r_submix input"
+ sources="Remote Submix In"/>
+ </routes>
+ </module>
+ </modules>
+</audioPolicyConfiguration>
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 501d922..11df5f3 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -16,6 +16,25 @@
// libcameraservice
//
+package {
+ default_applicable_licenses: [
+ "frameworks_av_services_camera_libcameraservice_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_services_camera_libcameraservice_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libcameraservice",
@@ -159,4 +178,3 @@
],
}
-
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index a63f402..2462fd5 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -65,7 +65,6 @@
mYuvBufferAcquired(false),
mProducerListener(new ProducerListener()),
mDequeuedOutputBufferCnt(0),
- mLockedAppSegmentBufferCnt(0),
mCodecOutputCounter(0),
mQuality(-1),
mGridTimestampUs(0),
@@ -634,7 +633,6 @@
mAppSegmentConsumer->unlockBuffer(imgBuffer);
} else {
mPendingInputFrames[frameNumber].appSegmentBuffer = imgBuffer;
- mLockedAppSegmentBufferCnt++;
}
mInputAppSegmentBuffers.erase(it);
mAppSegmentFrameNumbers.pop();
@@ -897,10 +895,6 @@
strerror(-res), res);
return res;
}
- } else if (mLockedAppSegmentBufferCnt == kMaxAcquiredAppSegment) {
- ALOGE("%s: Out-of-order app segment buffers reaches limit %u", __FUNCTION__,
- kMaxAcquiredAppSegment);
- return INVALID_OPERATION;
}
}
@@ -1038,7 +1032,6 @@
mAppSegmentConsumer->unlockBuffer(inputFrame.appSegmentBuffer);
inputFrame.appSegmentBuffer.data = nullptr;
inputFrame.exifError = false;
- mLockedAppSegmentBufferCnt--;
return OK;
}
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 33ca69a..a373127 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -253,7 +253,6 @@
// Keep all incoming APP segment Blob buffer pending further processing.
std::vector<int64_t> mInputAppSegmentBuffers;
- int32_t mLockedAppSegmentBufferCnt;
// Keep all incoming HEIC blob buffer pending further processing.
std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 32d118d..876d70d 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1344,6 +1344,20 @@
}
}
+ // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+ // before setCallback returns
+ hardware::Return<Status> status = interface->setCallback(this);
+ if (!status.isOk()) {
+ ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), status.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+
hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
if (!linked.isOk()) {
ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
@@ -1372,7 +1386,6 @@
return res;
}
- Status status;
// Get initial list of camera devices, if any
std::vector<std::string> devices;
hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
@@ -1437,26 +1450,43 @@
}
}
- // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
- // before setCallback returns. setCallback must be called after addDevice so that
- // the physical camera status callback can look up available regular
- // cameras.
- hardware::Return<Status> st = interface->setCallback(this);
- if (!st.isOk()) {
- ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), st.description().c_str());
- return DEAD_OBJECT;
- }
- if (st != Status::OK) {
- ALOGE("%s: Unable to register callbacks with camera provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(st);
- }
-
ALOGI("Camera provider %s ready with %zu camera devices",
mProviderName.c_str(), mDevices.size());
- mInitialized = true;
+ // Process cached status callbacks
+ std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
+ std::make_unique<std::vector<CameraStatusInfoT>>();
+ {
+ std::lock_guard<std::mutex> lock(mInitLock);
+
+ for (auto& statusInfo : mCachedStatus) {
+ std::string id, physicalId;
+ status_t res = OK;
+ if (statusInfo.isPhysicalCameraStatus) {
+ res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
+ statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
+ } else {
+ res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
+ }
+ if (res == OK) {
+ cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
+ id.c_str(), physicalId.c_str(), statusInfo.status);
+ }
+ }
+ mCachedStatus.clear();
+
+ mInitialized = true;
+ }
+
+ // The cached status change callbacks cannot be fired directly from this
+ // function, due to same-thread deadlock trying to acquire mInterfaceMutex
+ // twice.
+ if (listener != nullptr) {
+ mInitialStatusCallbackFuture = std::async(std::launch::async,
+ &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
+ listener, std::move(cachedStatus));
+ }
+
return OK;
}
@@ -1734,104 +1764,139 @@
CameraDeviceStatus newStatus) {
sp<StatusListener> listener;
std::string id;
- bool initialized = false;
+ std::lock_guard<std::mutex> lock(mInitLock);
+
+ if (!mInitialized) {
+ mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
+ cameraDeviceName.c_str(), std::string().c_str(), newStatus);
+ return hardware::Void();
+ }
+
{
std::lock_guard<std::mutex> lock(mLock);
- bool known = false;
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
- deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
- deviceInfo->mStatus = newStatus;
- // TODO: Handle device removal (NOT_PRESENT)
- id = deviceInfo->mId;
- known = true;
- break;
- }
- }
- // Previously unseen device; status must not be NOT_PRESENT
- if (!known) {
- if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
- ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str());
- return hardware::Void();
- }
- addDevice(cameraDeviceName, newStatus, &id);
- } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
- removeDevice(id);
+ if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
+ return hardware::Void();
}
listener = mManager->getStatusListener();
- initialized = mInitialized;
- if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
- ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
- __FUNCTION__, mProviderName.c_str());
- }
}
+
// Call without lock held to allow reentrancy into provider manager
- // Don't send the callback if providerInfo hasn't been initialized.
- // CameraService will initialize device status after provider is
- // initialized
- if (listener != nullptr && initialized) {
+ if (listener != nullptr) {
listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
}
+
return hardware::Void();
}
+status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
+ std::string* id, const hardware::hidl_string& cameraDeviceName,
+ CameraDeviceStatus newStatus) {
+ bool known = false;
+ std::string cameraId;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
+ deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
+ deviceInfo->mStatus = newStatus;
+ // TODO: Handle device removal (NOT_PRESENT)
+ cameraId = deviceInfo->mId;
+ known = true;
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+ ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ addDevice(cameraDeviceName, newStatus, &cameraId);
+ } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+ removeDevice(cameraId);
+ }
+ if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+ ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+ __FUNCTION__, mProviderName.c_str());
+ }
+ *id = cameraId;
+ return OK;
+}
+
hardware::Return<void> CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChange(
const hardware::hidl_string& cameraDeviceName,
const hardware::hidl_string& physicalCameraDeviceName,
CameraDeviceStatus newStatus) {
sp<StatusListener> listener;
std::string id;
- bool initialized = false;
+ std::string physicalId;
+ std::lock_guard<std::mutex> lock(mInitLock);
+
+ if (!mInitialized) {
+ mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
+ physicalCameraDeviceName, newStatus);
+ return hardware::Void();
+ }
+
{
std::lock_guard<std::mutex> lock(mLock);
- bool known = false;
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- id = deviceInfo->mId;
- if (!deviceInfo->mIsLogicalCamera) {
- ALOGE("%s: Invalid combination of camera id %s, physical id %s",
- __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
- return hardware::Void();
- }
- if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
- physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
- ALOGE("%s: Invalid combination of camera id %s, physical id %s",
- __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
- return hardware::Void();
- }
- ALOGI("Camera device %s physical device %s status is now %s, was %s",
- cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
- deviceStatusToString(newStatus), deviceStatusToString(
- deviceInfo->mPhysicalStatus[physicalCameraDeviceName]));
- known = true;
- break;
- }
- }
- // Previously unseen device; status must not be NOT_PRESENT
- if (!known) {
- ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str(),
- physicalCameraDeviceName.c_str());
+ if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
+ physicalCameraDeviceName, newStatus)) {
return hardware::Void();
}
+
listener = mManager->getStatusListener();
- initialized = mInitialized;
}
// Call without lock held to allow reentrancy into provider manager
- // Don't send the callback if providerInfo hasn't been initialized.
- // CameraService will initialize device status after provider is
- // initialized
- if (listener != nullptr && initialized) {
- String8 physicalId(physicalCameraDeviceName.c_str());
+ if (listener != nullptr) {
listener->onDeviceStatusChanged(String8(id.c_str()),
- physicalId, newStatus);
+ String8(physicalId.c_str()), newStatus);
}
return hardware::Void();
}
+status_t CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeLocked(
+ std::string* id, std::string* physicalId,
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ CameraDeviceStatus newStatus) {
+ bool known = false;
+ std::string cameraId;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ cameraId = deviceInfo->mId;
+ if (!deviceInfo->mIsLogicalCamera) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+ physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ ALOGI("Camera device %s physical device %s status is now %s",
+ cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+ deviceStatusToString(newStatus));
+ known = true;
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(),
+ physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+
+ *id = cameraId;
+ *physicalId = physicalCameraDeviceName.c_str();
+ return OK;
+}
+
hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
const hardware::hidl_string& cameraDeviceName,
TorchModeStatus newStatus) {
@@ -1986,6 +2051,20 @@
return INVALID_OPERATION;
}
+void CameraProviderManager::ProviderInfo::notifyInitialStatusChange(
+ sp<StatusListener> listener,
+ std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus) {
+ for (auto& statusInfo : *cachedStatus) {
+ if (statusInfo.isPhysicalCameraStatus) {
+ listener->onDeviceStatusChanged(String8(statusInfo.cameraId.c_str()),
+ String8(statusInfo.physicalCameraId.c_str()), statusInfo.status);
+ } else {
+ listener->onDeviceStatusChanged(
+ String8(statusInfo.cameraId.c_str()), statusInfo.status);
+ }
+ }
+}
+
template<class DeviceInfoT>
std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
CameraProviderManager::ProviderInfo::initializeDeviceInfo(
@@ -2689,9 +2768,11 @@
CameraProviderManager::ProviderInfo::~ProviderInfo() {
+ if (mInitialStatusCallbackFuture.valid()) {
+ mInitialStatusCallbackFuture.wait();
+ }
// Destruction of ProviderInfo is only supposed to happen when the respective
// CameraProvider interface dies, so do not unregister callbacks.
-
}
status_t CameraProviderManager::mapToStatusT(const Status& s) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 25d3639..a0e5f8f 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -22,6 +22,7 @@
#include <unordered_set>
#include <string>
#include <mutex>
+#include <future>
#include <camera/camera2/ConcurrentCamera.h>
#include <camera/CameraParameters2.h>
@@ -403,6 +404,15 @@
const hardware::hidl_string& physicalCameraDeviceName,
hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
+ status_t cameraDeviceStatusChangeLocked(
+ std::string* id, const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
+ status_t physicalCameraDeviceStatusChangeLocked(
+ std::string* id, std::string* physicalId,
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
+
// hidl_death_recipient interface - this locks the parent mInterfaceMutex
virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
@@ -444,8 +454,6 @@
const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
- std::map<std::string, hardware::camera::common::V1_0::CameraDeviceStatus>
- mPhysicalStatus;
wp<ProviderInfo> mParentProvider;
@@ -600,7 +608,27 @@
CameraProviderManager *mManager;
+ struct CameraStatusInfoT {
+ bool isPhysicalCameraStatus = false;
+ hardware::hidl_string cameraId;
+ hardware::hidl_string physicalCameraId;
+ hardware::camera::common::V1_0::CameraDeviceStatus status;
+ CameraStatusInfoT(bool isForPhysicalCamera, const hardware::hidl_string& id,
+ const hardware::hidl_string& physicalId,
+ hardware::camera::common::V1_0::CameraDeviceStatus s) :
+ isPhysicalCameraStatus(isForPhysicalCamera), cameraId(id),
+ physicalCameraId(physicalId), status(s) {}
+ };
+
+ // Lock to synchronize between initialize() and camera status callbacks
+ std::mutex mInitLock;
bool mInitialized = false;
+ std::vector<CameraStatusInfoT> mCachedStatus;
+ // End of scope for mInitLock
+
+ std::future<void> mInitialStatusCallbackFuture;
+ void notifyInitialStatusChange(sp<StatusListener> listener,
+ std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus);
std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 7b3dfb4..ea6d59e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2312,6 +2312,15 @@
newRequest->mRotateAndCropAuto = false;
}
+ auto zoomRatioEntry =
+ newRequest->mSettingsList.begin()->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+ if (zoomRatioEntry.count > 0 &&
+ zoomRatioEntry.data.f[0] == 1.0f) {
+ newRequest->mZoomRatioIs1x = true;
+ } else {
+ newRequest->mZoomRatioIs1x = false;
+ }
+
return newRequest;
}
@@ -4432,13 +4441,17 @@
parent->mDistortionMappers.end()) {
continue;
}
- res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
- &(it->metadata));
- if (res != OK) {
- SET_ERR("RequestThread: Unable to correct capture requests "
- "for lens distortion for request %d: %s (%d)",
- halRequest->frame_number, strerror(-res), res);
- return INVALID_OPERATION;
+
+ if (!captureRequest->mDistortionCorrectionUpdated) {
+ res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
+ &(it->metadata));
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to correct capture requests "
+ "for lens distortion for request %d: %s (%d)",
+ halRequest->frame_number, strerror(-res), res);
+ return INVALID_OPERATION;
+ }
+ captureRequest->mDistortionCorrectionUpdated = true;
}
}
@@ -4449,21 +4462,24 @@
continue;
}
- camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
- if (e.count > 0 && e.data.f[0] != 1.0f) {
+ if (!captureRequest->mZoomRatioIs1x) {
cameraIdsWithZoom.insert(it->cameraId);
}
- res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
- &(it->metadata));
- if (res != OK) {
- SET_ERR("RequestThread: Unable to correct capture requests "
- "for zoom ratio for request %d: %s (%d)",
- halRequest->frame_number, strerror(-res), res);
- return INVALID_OPERATION;
+ if (!captureRequest->mZoomRatioUpdated) {
+ res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
+ &(it->metadata));
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to correct capture requests "
+ "for zoom ratio for request %d: %s (%d)",
+ halRequest->frame_number, strerror(-res), res);
+ return INVALID_OPERATION;
+ }
+ captureRequest->mZoomRatioUpdated = true;
}
}
- if (captureRequest->mRotateAndCropAuto) {
+ if (captureRequest->mRotateAndCropAuto &&
+ !captureRequest->mRotationAndCropUpdated) {
for (it = captureRequest->mSettingsList.begin();
it != captureRequest->mSettingsList.end(); it++) {
auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
@@ -4477,6 +4493,7 @@
}
}
}
+ captureRequest->mRotationAndCropUpdated = true;
}
}
}
@@ -4658,15 +4675,21 @@
}
bool isStillCapture = false;
bool isZslCapture = false;
+ const camera_metadata_t* settings = halRequest->settings;
+ bool shouldUnlockSettings = false;
+ if (settings == nullptr) {
+ shouldUnlockSettings = true;
+ settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
+ }
if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
- find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
+ find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
isStillCapture = true;
ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
}
- find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
+ find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
isZslCapture = true;
}
@@ -4675,7 +4698,7 @@
totalNumBuffers, captureRequest->mResultExtras,
/*hasInput*/halRequest->input_buffer != NULL,
hasCallback,
- calculateMaxExpectedDuration(halRequest->settings),
+ calculateMaxExpectedDuration(settings),
requestedPhysicalCameras, isStillCapture, isZslCapture,
captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
(mUseHalBufManager) ? uniqueSurfaceIdMap :
@@ -4685,6 +4708,11 @@
__FUNCTION__,
captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
captureRequest->mResultExtras.burstId);
+
+ if (shouldUnlockSettings) {
+ captureRequest->mSettingsList.begin()->metadata.unlock(settings);
+ }
+
if (res != OK) {
SET_ERR("RequestThread: Unable to register new in-flight request:"
" %s (%d)", strerror(-res), res);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 4c5f484..e10da2c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -517,6 +517,19 @@
// overriding of ROTATE_AND_CROP value and adjustment of coordinates
// in several other controls in both the request and the result
bool mRotateAndCropAuto;
+ // Whether this capture request has its zoom ratio set to 1.0x before
+ // the framework overrides it for camera HAL consumption.
+ bool mZoomRatioIs1x;
+
+
+ // Whether this capture request's distortion correction update has
+ // been done.
+ bool mDistortionCorrectionUpdated = false;
+ // Whether this capture request's rotation and crop update has been
+ // done.
+ bool mRotationAndCropUpdated = false;
+ // Whether this capture request's zoom ratio update has been done.
+ bool mZoomRatioUpdated = false;
};
typedef List<sp<CaptureRequest> > RequestList;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index eea5ef1..08cde5d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -1218,13 +1218,13 @@
return;
}
+ bufRet.streamId = streamId;
if (outputStream->isAbandoned()) {
bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
allReqsSucceeds = false;
continue;
}
- bufRet.streamId = streamId;
size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
uint32_t numBuffersRequested = bufReq.numBuffersRequested;
size_t totalHandout = handOutBufferCount + numBuffersRequested;
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index a87de77..4e98bf6 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -153,6 +153,19 @@
entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
if (entry.count == 1 && entry.data.f[0] != 1.0f) {
zoomRatioIs1 = false;
+
+ // If cropRegion is windowboxing, override it with activeArray
+ camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
+ if (cropRegionEntry.count == 4) {
+ int cropWidth = cropRegionEntry.data.i32[2];
+ int cropHeight = cropRegionEntry.data.i32[3];
+ if (cropWidth < mArrayWidth && cropHeight < mArrayHeight) {
+ cropRegionEntry.data.i32[0] = 0;
+ cropRegionEntry.data.i32[1] = 0;
+ cropRegionEntry.data.i32[2] = mArrayWidth;
+ cropRegionEntry.data.i32[3] = mArrayHeight;
+ }
+ }
}
if (mHalSupportsZoomRatio && zoomRatioIs1) {
diff --git a/services/camera/libcameraservice/fuzzer/Android.bp b/services/camera/libcameraservice/fuzzer/Android.bp
index c5b7f00..9a9a03b 100644
--- a/services/camera/libcameraservice/fuzzer/Android.bp
+++ b/services/camera/libcameraservice/fuzzer/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_services_camera_libcameraservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_services_camera_libcameraservice_license",
+ ],
+}
+
cc_defaults {
name: "libcameraservice_fuzz_defaults",
fuzz_config: {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
new file mode 100644
index 0000000..d06b2c5
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_services_camera_libcameraservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_services_camera_libcameraservice_license",
+ ],
+}
+
+cc_fuzz {
+ name: "camera_service_fuzzer",
+ srcs: [
+ "camera_service_fuzzer.cpp",
+ ],
+ header_libs: [
+ "libmedia_headers",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "libcameraservice",
+ "libcamera_client",
+ "libui",
+ "libgui",
+ "android.hardware.camera.common@1.0",
+ "android.hardware.camera.provider@2.4",
+ "android.hardware.camera.provider@2.5",
+ "android.hardware.camera.provider@2.6",
+ "android.hardware.camera.device@1.0",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
+ "android.hardware.camera.device@3.6",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/README.md b/services/camera/libcameraservice/libcameraservice_fuzzer/README.md
new file mode 100644
index 0000000..c703845
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/README.md
@@ -0,0 +1,59 @@
+# Fuzzer for libcameraservice
+
+## Plugin Design Considerations
+The fuzzer plugin is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libcameraservice supports the following parameters:
+1. Camera Type (parameter name: `cameraType`)
+2. Camera API Version (parameter name: `cameraAPIVersion`)
+3. Event ID (parameter name: `eventId`)
+4. Camera Sound Kind (parameter name: `soundKind`)
+5. Shell Command (parameter name: `shellCommand`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `cameraType` | 0. `CAMERA_TYPE_BACKWARD_COMPATIBLE` 1. `CAMERA_TYPE_ALL` | Value obtained from FuzzedDataProvider |
+| `cameraAPIVersion` | 0. `API_VERSION_1` 1. `API_VERSION_2` | Value obtained from FuzzedDataProvider |
+| `eventId` | 0. `EVENT_USER_SWITCHED` 1. `EVENT_NONE` | Value obtained from FuzzedDataProvider |
+| `soundKind` | 0. `SOUND_SHUTTER` 1. `SOUND_RECORDING_START` 2. `SOUND_RECORDING_STOP`| Value obtained from FuzzedDataProvider |
+| `shellCommand` | 0. `set-uid-state` 1. `reset-uid-state` 2. `get-uid-state` 3. `set-rotate-and-crop` 4. `get-rotate-and-crop` 5. `help`| Value obtained from FuzzedDataProvider |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesn't `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build camera_service_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) camera_service_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+ $ adb shell mkdir CORPUS_DIR
+```
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/camera_service_fuzzer/camera_service_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
new file mode 100644
index 0000000..54550a5
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -0,0 +1,433 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include <CameraService.h>
+#include <android/hardware/ICameraServiceListener.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/android_filesystem_config.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+using namespace android;
+using namespace hardware;
+using namespace std;
+
+const int32_t kPreviewThreshold = 8;
+const nsecs_t kPreviewTimeout = 5000000000; // .5 [s.]
+const nsecs_t kEventTimeout = 10000000000; // 1 [s.]
+const size_t kMaxNumLines = USHRT_MAX;
+const size_t kMinArgs = 1;
+const size_t kMaxArgs = 5;
+const int32_t kCamType[] = {hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
+ hardware::ICameraService::CAMERA_TYPE_ALL};
+const int kCameraApiVersion[] = {android::CameraService::API_VERSION_1,
+ android::CameraService::API_VERSION_2};
+const int kLayerMetadata[] = {
+ 0x00100000 /*GRALLOC_USAGE_RENDERSCRIPT*/, 0x00000003 /*GRALLOC_USAGE_SW_READ_OFTEN*/,
+ 0x00000100 /*GRALLOC_USAGE_HW_TEXTURE*/, 0x00000800 /*GRALLOC_USAGE_HW_COMPOSER*/,
+ 0x00000200 /*GRALLOC_USAGE_HW_RENDER*/, 0x00010000 /*GRALLOC_USAGE_HW_VIDEO_ENCODER*/};
+const int kCameraMsg[] = {0x001 /*CAMERA_MSG_ERROR*/,
+ 0x002 /*CAMERA_MSG_SHUTTER*/,
+ 0x004 /*CAMERA_MSG_FOCUS*/,
+ 0x008 /*CAMERA_MSG_ZOOM*/,
+ 0x010 /*CAMERA_MSG_PREVIEW_FRAME*/,
+ 0x020 /*CAMERA_MSG_VIDEO_FRAME */,
+ 0x040 /*CAMERA_MSG_POSTVIEW_FRAME*/,
+ 0x080 /*CAMERA_MSG_RAW_IMAGE */,
+ 0x100 /*CAMERA_MSG_COMPRESSED_IMAGE*/,
+ 0x200 /*CAMERA_MSG_RAW_IMAGE_NOTIFY*/,
+ 0x400 /*CAMERA_MSG_PREVIEW_METADATA*/,
+ 0x800 /*CAMERA_MSG_FOCUS_MOVE*/};
+const int32_t kEventId[] = {ICameraService::EVENT_USER_SWITCHED, ICameraService::EVENT_NONE};
+const android::CameraService::sound_kind kSoundKind[] = {
+ android::CameraService::SOUND_SHUTTER, android::CameraService::SOUND_RECORDING_START,
+ android::CameraService::SOUND_RECORDING_STOP};
+const String16 kShellCmd[] = {String16("set-uid-state"), String16("reset-uid-state"),
+ String16("get-uid-state"), String16("set-rotate-and-crop"),
+ String16("get-rotate-and-crop"), String16("help")};
+const size_t kNumLayerMetaData = size(kLayerMetadata);
+const size_t kNumCameraMsg = size(kCameraMsg);
+const size_t kNumSoundKind = size(kSoundKind);
+const size_t kNumShellCmd = size(kShellCmd);
+
+class CameraFuzzer : public ::android::hardware::BnCameraClient {
+ public:
+ CameraFuzzer() = default;
+ ~CameraFuzzer() { deInit(); }
+ bool init();
+ void process(const uint8_t *data, size_t size);
+ void deInit();
+
+ private:
+ FuzzedDataProvider *mFuzzedDataProvider = nullptr;
+ sp<CameraService> mCameraService = nullptr;
+ sp<SurfaceComposerClient> mComposerClient = nullptr;
+ int32_t mNumCameras = 0;
+ size_t mPreviewBufferCount = 0;
+ bool mAutoFocusMessage = false;
+ bool mSnapshotNotification = false;
+ mutable Mutex mPreviewLock;
+ mutable Condition mPreviewCondition;
+ mutable Mutex mAutoFocusLock;
+ mutable Condition mAutoFocusCondition;
+ mutable Mutex mSnapshotLock;
+ mutable Condition mSnapshotCondition;
+
+ void getNumCameras();
+ void getCameraInformation(int32_t cameraId);
+ void invokeCameraAPIs();
+ void invokeCameraSound();
+ void invokeDump();
+ void invokeShellCommand();
+ void invokeNotifyCalls();
+
+ // CameraClient interface
+ void notifyCallback(int32_t msgType, int32_t, int32_t) override;
+ void dataCallback(int32_t msgType, const sp<IMemory> &, camera_frame_metadata_t *) override;
+ void dataCallbackTimestamp(nsecs_t, int32_t, const sp<IMemory> &) override{};
+ void recordingFrameHandleCallbackTimestamp(nsecs_t, native_handle_t *) override{};
+ void recordingFrameHandleCallbackTimestampBatch(
+ const std::vector<nsecs_t> &, const std::vector<native_handle_t *> &) override{};
+ status_t waitForPreviewStart();
+ status_t waitForEvent(Mutex &mutex, Condition &condition, bool &flag);
+};
+
+void CameraFuzzer::notifyCallback(int32_t msgType, int32_t, int32_t) {
+ if (CAMERA_MSG_FOCUS == msgType) {
+ Mutex::Autolock l(mAutoFocusLock);
+ mAutoFocusMessage = true;
+ mAutoFocusCondition.broadcast();
+ }
+};
+
+void CameraFuzzer::dataCallback(int32_t msgType, const sp<IMemory> & /*data*/,
+ camera_frame_metadata_t *) {
+ switch (msgType) {
+ case CAMERA_MSG_PREVIEW_FRAME: {
+ Mutex::Autolock l(mPreviewLock);
+ ++mPreviewBufferCount;
+ mPreviewCondition.broadcast();
+ break;
+ }
+ case CAMERA_MSG_COMPRESSED_IMAGE: {
+ Mutex::Autolock l(mSnapshotLock);
+ mSnapshotNotification = true;
+ mSnapshotCondition.broadcast();
+ break;
+ }
+ default:
+ break;
+ }
+};
+
+status_t CameraFuzzer::waitForPreviewStart() {
+ status_t rc = NO_ERROR;
+ Mutex::Autolock l(mPreviewLock);
+ mPreviewBufferCount = 0;
+
+ while (mPreviewBufferCount < kPreviewThreshold) {
+ rc = mPreviewCondition.waitRelative(mPreviewLock, kPreviewTimeout);
+ if (NO_ERROR != rc) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+status_t CameraFuzzer::waitForEvent(Mutex &mutex, Condition &condition, bool &flag) {
+ status_t rc = NO_ERROR;
+ Mutex::Autolock l(mutex);
+ flag = false;
+
+ while (!flag) {
+ rc = condition.waitRelative(mutex, kEventTimeout);
+ if (NO_ERROR != rc) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+bool CameraFuzzer::init() {
+ setuid(AID_MEDIA);
+ mCameraService = new CameraService();
+ if (mCameraService) {
+ return true;
+ }
+ return false;
+}
+
+void CameraFuzzer::deInit() {
+ if (mCameraService) {
+ mCameraService = nullptr;
+ }
+ if (mComposerClient) {
+ mComposerClient->dispose();
+ }
+}
+
+void CameraFuzzer::getNumCameras() {
+ bool shouldPassInvalidCamType = mFuzzedDataProvider->ConsumeBool();
+ int32_t camType;
+ if (shouldPassInvalidCamType) {
+ camType = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ } else {
+ camType = kCamType[mFuzzedDataProvider->ConsumeBool()];
+ }
+ mCameraService->getNumberOfCameras(camType, &mNumCameras);
+}
+
+void CameraFuzzer::getCameraInformation(int32_t cameraId) {
+ String16 cameraIdStr = String16(String8::format("%d", cameraId));
+ bool isSupported = false;
+ mCameraService->supportsCameraApi(
+ cameraIdStr, kCameraApiVersion[mFuzzedDataProvider->ConsumeBool()], &isSupported);
+ mCameraService->isHiddenPhysicalCamera(cameraIdStr, &isSupported);
+
+ String16 parameters;
+ mCameraService->getLegacyParameters(cameraId, ¶meters);
+
+ std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination> concurrentCameraIds;
+ mCameraService->getConcurrentCameraIds(&concurrentCameraIds);
+
+ hardware::camera2::params::VendorTagDescriptorCache cache;
+ mCameraService->getCameraVendorTagCache(&cache);
+
+ CameraInfo cameraInfo;
+ mCameraService->getCameraInfo(cameraId, &cameraInfo);
+
+ CameraMetadata metadata;
+ mCameraService->getCameraCharacteristics(cameraIdStr, &metadata);
+}
+
+void CameraFuzzer::invokeCameraSound() {
+ mCameraService->increaseSoundRef();
+ mCameraService->decreaseSoundRef();
+ bool shouldPassInvalidPlaySound = mFuzzedDataProvider->ConsumeBool();
+ bool shouldPassInvalidLockSound = mFuzzedDataProvider->ConsumeBool();
+ android::CameraService::sound_kind playSound, lockSound;
+ if (shouldPassInvalidPlaySound) {
+ playSound = static_cast<android::CameraService::sound_kind>(
+ mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ playSound =
+ kSoundKind[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumSoundKind - 1)];
+ }
+
+ if (shouldPassInvalidLockSound) {
+ lockSound = static_cast<android::CameraService::sound_kind>(
+ mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ lockSound =
+ kSoundKind[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumSoundKind - 1)];
+ }
+ mCameraService->playSound(playSound);
+ mCameraService->loadSoundLocked(lockSound);
+}
+
+void CameraFuzzer::invokeDump() {
+ Vector<String16> args;
+ size_t numberOfLines = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxNumLines);
+ for (size_t lineIdx = 0; lineIdx < numberOfLines; ++lineIdx) {
+ args.add(static_cast<String16>(mFuzzedDataProvider->ConsumeRandomLengthString().c_str()));
+ }
+ const char *fileName = "logDumpFile";
+ int fd = memfd_create(fileName, MFD_ALLOW_SEALING);
+ mCameraService->dump(fd, args);
+ close(fd);
+}
+
+void CameraFuzzer::invokeShellCommand() {
+ int in = mFuzzedDataProvider->ConsumeIntegral<int>();
+ int out = mFuzzedDataProvider->ConsumeIntegral<int>();
+ int err = mFuzzedDataProvider->ConsumeIntegral<int>();
+ Vector<String16> args;
+ size_t numArgs = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinArgs, kMaxArgs);
+ for (size_t argsIdx = 0; argsIdx < numArgs; ++argsIdx) {
+ bool shouldPassInvalidCommand = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassInvalidCommand) {
+ args.add(
+ static_cast<String16>(mFuzzedDataProvider->ConsumeRandomLengthString().c_str()));
+ } else {
+ args.add(kShellCmd[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kNumShellCmd - 1)]);
+ }
+ }
+ mCameraService->shellCommand(in, out, err, args);
+}
+
+void CameraFuzzer::invokeNotifyCalls() {
+ mCameraService->notifyMonitoredUids();
+ int64_t newState = mFuzzedDataProvider->ConsumeIntegral<int64_t>();
+ mCameraService->notifyDeviceStateChange(newState);
+ std::vector<int32_t> args;
+ size_t numArgs = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinArgs, kMaxArgs);
+ for (size_t argsIdx = 0; argsIdx < numArgs; ++argsIdx) {
+ args.push_back(mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ }
+ bool shouldPassInvalidEvent = mFuzzedDataProvider->ConsumeBool();
+ int32_t eventId;
+ if (shouldPassInvalidEvent) {
+ eventId = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ } else {
+ eventId = kEventId[mFuzzedDataProvider->ConsumeBool()];
+ }
+ mCameraService->notifySystemEvent(eventId, args);
+}
+
+void CameraFuzzer::invokeCameraAPIs() {
+ for (int32_t cameraId = 0; cameraId < mNumCameras; ++cameraId) {
+ getCameraInformation(cameraId);
+
+ const String16 opPackageName("com.fuzzer.poc");
+ ::android::binder::Status rc;
+ sp<ICamera> cameraDevice;
+
+ rc = mCameraService->connect(this, cameraId, opPackageName, AID_MEDIA, AID_ROOT,
+ &cameraDevice);
+ if (!rc.isOk()) {
+ // camera not connected
+ return;
+ }
+ if (cameraDevice) {
+ sp<Surface> previewSurface;
+ sp<SurfaceControl> surfaceControl;
+ CameraParameters params(cameraDevice->getParameters());
+ String8 focusModes(params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES));
+ bool isAFSupported = false;
+ const char *focusMode = nullptr;
+
+ if (focusModes.contains(CameraParameters::FOCUS_MODE_AUTO)) {
+ isAFSupported = true;
+ } else if (focusModes.contains(CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE)) {
+ isAFSupported = true;
+ focusMode = CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE;
+ } else if (focusModes.contains(CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO)) {
+ isAFSupported = true;
+ focusMode = CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO;
+ } else if (focusModes.contains(CameraParameters::FOCUS_MODE_MACRO)) {
+ isAFSupported = true;
+ focusMode = CameraParameters::FOCUS_MODE_MACRO;
+ }
+ if (nullptr != focusMode) {
+ params.set(CameraParameters::KEY_FOCUS_MODE, focusMode);
+ cameraDevice->setParameters(params.flatten());
+ }
+ int previewWidth, previewHeight;
+ params.getPreviewSize(&previewWidth, &previewHeight);
+
+ mComposerClient = new SurfaceComposerClient;
+ mComposerClient->initCheck();
+
+ bool shouldPassInvalidLayerMetaData = mFuzzedDataProvider->ConsumeBool();
+ int layerMetaData;
+ if (shouldPassInvalidLayerMetaData) {
+ layerMetaData = mFuzzedDataProvider->ConsumeIntegral<int>();
+ } else {
+ layerMetaData = kLayerMetadata[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kNumLayerMetaData - 1)];
+ }
+ surfaceControl = mComposerClient->createSurface(
+ String8("Test Surface"), previewWidth, previewHeight,
+ CameraParameters::previewFormatToEnum(params.getPreviewFormat()), layerMetaData);
+
+ if (surfaceControl.get() != nullptr) {
+ SurfaceComposerClient::Transaction{}
+ .setLayer(surfaceControl, 0x7fffffff)
+ .show(surfaceControl)
+ .apply();
+
+ previewSurface = surfaceControl->getSurface();
+ cameraDevice->setPreviewTarget(previewSurface->getIGraphicBufferProducer());
+ }
+ cameraDevice->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER);
+
+ Vector<Size> pictureSizes;
+ params.getSupportedPictureSizes(pictureSizes);
+
+ for (size_t i = 0; i < pictureSizes.size(); ++i) {
+ params.setPictureSize(pictureSizes[i].width, pictureSizes[i].height);
+ cameraDevice->setParameters(params.flatten());
+ cameraDevice->startPreview();
+ waitForPreviewStart();
+ cameraDevice->autoFocus();
+ waitForEvent(mAutoFocusLock, mAutoFocusCondition, mAutoFocusMessage);
+ bool shouldPassInvalidCameraMsg = mFuzzedDataProvider->ConsumeBool();
+ int msgType;
+ if (shouldPassInvalidCameraMsg) {
+ msgType = mFuzzedDataProvider->ConsumeIntegral<int>();
+ } else {
+ msgType = kCameraMsg[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kNumCameraMsg - 1)];
+ }
+ cameraDevice->takePicture(msgType);
+
+ waitForEvent(mSnapshotLock, mSnapshotCondition, mSnapshotNotification);
+ }
+
+ Vector<Size> videoSizes;
+ params.getSupportedVideoSizes(videoSizes);
+
+ for (size_t i = 0; i < videoSizes.size(); ++i) {
+ params.setVideoSize(videoSizes[i].width, videoSizes[i].height);
+
+ cameraDevice->setParameters(params.flatten());
+ cameraDevice->startPreview();
+ waitForPreviewStart();
+ cameraDevice->setVideoBufferMode(
+ android::hardware::BnCamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE);
+ cameraDevice->setVideoTarget(previewSurface->getIGraphicBufferProducer());
+ cameraDevice->startRecording();
+ cameraDevice->stopRecording();
+ }
+ cameraDevice->stopPreview();
+ cameraDevice->disconnect();
+ }
+ }
+}
+
+void CameraFuzzer::process(const uint8_t *data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ getNumCameras();
+ invokeCameraSound();
+ if (mNumCameras > 0) {
+ invokeCameraAPIs();
+ }
+ invokeDump();
+ invokeShellCommand();
+ invokeNotifyCalls();
+ delete mFuzzedDataProvider;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ sp<CameraFuzzer> camerafuzzer = new CameraFuzzer();
+ if (!camerafuzzer) {
+ return 0;
+ }
+ if (camerafuzzer->init()) {
+ camerafuzzer->process(data, size);
+ }
+ return 0;
+}
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index 3ead715..b530342 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -51,6 +51,9 @@
LOCAL_SANITIZE := address
LOCAL_MODULE:= cameraservice_test
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../NOTICE
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_MODULE_TAGS := tests
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 05bbbc7..6788afb 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_av_services_mediacodec_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_services_mediacodec_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "mediaswcodec",
vendor_available: true,
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index 0441cfa..696b967 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_services_mediacodec_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_mediacodec_license"],
+}
+
cc_library_shared {
name: "libmedia_codecserviceregistrant",
vendor_available: true,
@@ -55,4 +64,3 @@
"libcodec2_soft_gsmdec",
],
}
-
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86.policy b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
index a9d32d6..4bcc077 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
index a9d32d6..4bcc077 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
index eb71e28..9bafe7b 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
index e72d4db..b0ed040 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
@@ -27,6 +27,7 @@
mmap: 1
fstat64: 1
fstat: 1
+stat: 1
stat64: 1
statfs64: 1
madvise: 1
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index 03e1e41..85ce110 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -1,4 +1,23 @@
// service library
+package {
+ default_applicable_licenses: [
+ "frameworks_av_services_mediaextractor_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_services_mediaextractor_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libmediaextractorservice",
cflags: [
@@ -67,4 +86,3 @@
"code_coverage.policy",
],
}
-
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index b7b51a6..10b8135 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -15,6 +15,9 @@
** limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "main_extractorservice"
+
#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
@@ -26,6 +29,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <utils/Log.h>
#include <utils/misc.h>
// from LOCAL_C_INCLUDES
@@ -41,10 +45,16 @@
int main(int argc __unused, char** argv)
{
+
+#if __has_feature(hwaddress_sanitizer)
+ ALOGI("disable media.extractor memory limits (hwasan enabled)");
+#else
+ ALOGI("enable media.extractor memory limits");
limitProcessMemory(
"ro.media.maxmem", /* property that defines limit */
SIZE_MAX, /* upper limit in bytes */
20 /* upper limit as percentage of physical RAM */);
+#endif
signal(SIGPIPE, SIG_IGN);
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
index 3a27a43..cfc4c40 100644
--- a/services/medialog/Android.bp
+++ b/services/medialog/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libmedialogservice",
diff --git a/services/medialog/fuzzer/Android.bp b/services/medialog/fuzzer/Android.bp
index 2afaaae..9ff0ce4 100644
--- a/services/medialog/fuzzer/Android.bp
+++ b/services/medialog/fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_fuzz {
name: "media_log_fuzzer",
static_libs: [
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 67e6c39..f13ca74 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -1,6 +1,15 @@
// Media Statistics service
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
tidy_errors = [
// https://clang.llvm.org/extra/clang-tidy/checks/list.html
// For many categories, the checks are too many to specify individually.
@@ -21,7 +30,7 @@
"modernize-loop-convert",
"modernize-make-shared",
"modernize-make-unique",
- "modernize-pass-by-value",
+ // "modernize-pass-by-value", // found in TimeMachine.h
"modernize-raw-string-literal",
"modernize-redundant-void-arg",
"modernize-replace-auto-ptr",
@@ -29,13 +38,13 @@
"modernize-return-braced-init-list",
"modernize-shrink-to-fit",
"modernize-unary-static-assert",
- "modernize-use-auto", // debatable - auto can obscure type
+ // "modernize-use-auto", // found in MediaMetricsService.h, debatable - auto can obscure type
"modernize-use-bool-literals",
"modernize-use-default-member-init",
"modernize-use-emplace",
"modernize-use-equals-default",
"modernize-use-equals-delete",
- "modernize-use-nodiscard",
+ // "modernize-use-nodiscard", // found in TimeMachine.h
"modernize-use-noexcept",
"modernize-use-nullptr",
"modernize-use-override",
@@ -48,6 +57,11 @@
// Remove some pedantic stylistic requirements.
"-google-readability-casting", // C++ casts not always necessary and may be verbose
"-google-readability-todo", // do not require TODO(info)
+
+ "-bugprone-unhandled-self-assignment", // found in TimeMachine.h
+ "-bugprone-suspicious-string-compare", // found in TimeMachine.h
+ "-cert-oop54-cpp", // found in TransactionLog.h
+ "-bugprone-narrowing-conversions", // b/182410845
]
cc_defaults {
@@ -79,8 +93,7 @@
tidy_checks: tidy_errors,
tidy_checks_as_errors: tidy_errors,
tidy_flags: [
- "-format-style='file'",
- "--header-filter='frameworks/av/services/mediametrics/'",
+ "-format-style=file",
],
}
@@ -131,6 +144,7 @@
"statsd_codec.cpp",
"statsd_drm.cpp",
"statsd_extractor.cpp",
+ "statsd_mediaparser.cpp",
"statsd_nuplayer.cpp",
"statsd_recorder.cpp",
"StringUtils.cpp"
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index d78d1e3..2a52599 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -348,7 +348,7 @@
} else {
ss << "Statsd atoms:\n" << statsd;
}
- ll -= n;
+ ll -= (int32_t)n;
}
}
@@ -737,7 +737,7 @@
mA2dpConnectionServiceNs = 0;
++mA2dpConnectionSuccesses;
- const auto connectionTimeMs = float(timeDiffNs * 1e-6);
+ const auto connectionTimeMs = float((double)timeDiffNs * 1e-6);
const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index 33dfa8fa..e584f12 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -28,7 +28,7 @@
#include <cutils/properties.h>
#include <statslog.h>
#include <sys/timerfd.h>
-#include <system/audio-base.h>
+#include <system/audio.h>
// property to disable audio power use metrics feature, default is enabled
#define PROP_AUDIO_METRICS_DISABLED "persist.media.audio_metrics.power_usage_disabled"
@@ -174,8 +174,8 @@
if (item_device == device && item_type == type) {
int64_t final_duration_ns = item_duration_ns + duration_ns;
double final_volume = (device & INPUT_DEVICE_BIT) ? 1.0:
- ((item_volume * item_duration_ns +
- average_vol * duration_ns) / final_duration_ns);
+ ((item_volume * (double)item_duration_ns +
+ average_vol * (double)duration_ns) / (double)final_duration_ns);
item->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, final_duration_ns);
item->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, final_volume);
@@ -289,7 +289,7 @@
const int64_t durationNs = endCallNs - mDeviceTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(endCallNs - mVolumeTimeNs)) / durationNs;
+ mVoiceVolume * double(endCallNs - mVolumeTimeNs)) / (double)durationNs;
saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
}
} else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
@@ -317,7 +317,7 @@
const int64_t durationNs = timeNs - mDeviceTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(timeNs - mVolumeTimeNs)) / durationNs;
+ mVoiceVolume * double(timeNs - mVolumeTimeNs)) / (double)durationNs;
mVolumeTimeNs = timeNs;
}
}
@@ -348,7 +348,7 @@
const int64_t durationNs = endDeviceNs - mDeviceTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(endDeviceNs - mVolumeTimeNs)) / durationNs;
+ mVoiceVolume * double(endDeviceNs - mVolumeTimeNs)) / (double)durationNs;
saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
}
// reset statistics
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 48e766e..0e89054 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -107,7 +107,7 @@
{
ALOGD("%s", __func__);
// the class destructor clears anyhow, but we enforce clearing items first.
- mItemsDiscarded += mItems.size();
+ mItemsDiscarded += (int64_t)mItems.size();
mItems.clear();
}
@@ -287,7 +287,7 @@
std::lock_guard _l(mLock);
if (clear) {
- mItemsDiscarded += mItems.size();
+ mItemsDiscarded += (int64_t)mItems.size();
mItems.clear();
mAudioAnalytics.clear();
} else {
@@ -416,10 +416,10 @@
if (const size_t toErase = overlimit + expired;
toErase > 0) {
- mItemsDiscardedCount += overlimit;
- mItemsDiscardedExpire += expired;
- mItemsDiscarded += toErase;
- mItems.erase(mItems.begin(), mItems.begin() + toErase); // erase from front
+ mItemsDiscardedCount += (int64_t)overlimit;
+ mItemsDiscardedExpire += (int64_t)expired;
+ mItemsDiscarded += (int64_t)toErase;
+ mItems.erase(mItems.begin(), mItems.begin() + (ptrdiff_t)toErase); // erase from front
}
return more;
}
@@ -468,6 +468,7 @@
"codec",
"extractor",
"mediadrm",
+ "mediaparser",
"nuplayer",
}) {
if (key == allowedKey) {
diff --git a/services/mediametrics/benchmarks/Android.bp b/services/mediametrics/benchmarks/Android.bp
index b61f44f..68d4145 100644
--- a/services/mediametrics/benchmarks/Android.bp
+++ b/services/mediametrics/benchmarks/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "mediametrics_benchmarks",
srcs: ["mediametrics_benchmarks.cpp"],
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
new file mode 100644
index 0000000..3053666
--- /dev/null
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_fuzz {
+ name: "mediametrics_service_fuzzer",
+
+ srcs: [
+ "mediametrics_service_fuzzer.cpp",
+ ],
+
+ static_libs: [
+ "libmediametrics",
+ "libmediametricsservice",
+ "libplatformprotos",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libmedia_helper",
+ "libmediautils",
+ "libmemunreachable",
+ "libprotobuf-cpp-lite",
+ "libstagefright",
+ "libstatslog",
+ "libutils",
+ ],
+
+ include_dirs: [
+ "frameworks/av/services/mediametrics",
+ "system/media/audio_utils/include",
+ ],
+
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/services/mediametrics/fuzzer/README.md b/services/mediametrics/fuzzer/README.md
new file mode 100644
index 0000000..a13830e
--- /dev/null
+++ b/services/mediametrics/fuzzer/README.md
@@ -0,0 +1,54 @@
+# Fuzzer for libmediametricsservice
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediametricsservice is designed based on the
+understanding of the service and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Media Metrics Service contains the following modules:
+1. Media Metrics Item Manipulation (module name: `Item`)
+2. Media Metrics Time Machine Storage (module name: `TimeMachineStorage`)
+3. Media Metrics Transaction Log (module name: `TransactionLog`)
+4. Media Metrics Analytics Action (module name: `AnalyticsAction`)
+5. Media Metrics Audio Analytics (module name: `AudioAnalytics`)
+6. Media Metrics Timed Action (module name: `TimedAction`)
+
+| Module| Valid Input Values| Configured Value|
+|------------- |-------------| ----- |
+| `Item` | Key: `std::string`. Values: `INT32_MIN` to `INT32_MAX`, `INT64_MIN` to `INT64_MAX`, `std::string`, `double`, `pair<INT32_MIN to INT32_MAX, INT32_MIN to INT32_MAX>` | Value obtained from FuzzedDataProvider |
+| `TimeMachineStorage` | Key: `std::string`. Values: `INT32_MIN` to `INT32_MAX`, `INT64_MIN` to `INT64_MAX`, `std::string`, `double`, `pair<INT32_MIN to INT32_MAX, INT32_MIN to INT32_MAX>` | Value obtained from FuzzedDataProvider |
+| `TranscationLog` | `mediametrics::Item` | `mediametrics::Item` created by obtaining values from FuzzedDataProvider|
+| `AnalyticsAction` | URL: `std::string` ending with .event, Value: `std::string`, action: A function | URL and Values obtained from FuzzedDataProvider, a placeholder function was passed as action|
+| `AudioAnalytics` | `mediametrics::Item` | `mediametrics::Item` created by obtaining values from FuzzedDataProvider|
+| `TimedAction` | time: `std::chrono::seconds`, function: `std::function` | `std::chrono::seconds` : value obtained from FuzzedDataProvider, `std::function`: a placeholder function was used. |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+## Build
+
+This describes steps to build mediametrics_service_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) mediametrics_service_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some files to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mediametrics_service_fuzzer/mediametrics_service_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
new file mode 100644
index 0000000..0cb2594
--- /dev/null
+++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
@@ -0,0 +1,372 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/MediaMetricsItem.h>
+#include <stdio.h>
+#include <string.h>
+#include <utils/Log.h>
+#include <algorithm>
+
+#include "AudioTypes.h"
+#include "MediaMetricsService.h"
+#include "StringUtils.h"
+
+using namespace android;
+
+// low water mark
+constexpr size_t kLogItemsLowWater = 1;
+// high water mark
+constexpr size_t kLogItemsHighWater = 2;
+
+class MediaMetricsServiceFuzzer {
+ public:
+ void invokeStartsWith(const uint8_t *data, size_t size);
+ void invokeInstantiate(const uint8_t *data, size_t size);
+ void invokePackageInstallerCheck(const uint8_t *data, size_t size);
+ void invokeItemManipulation(const uint8_t *data, size_t size);
+ void invokeItemExpansion(const uint8_t *data, size_t size);
+ void invokeTimeMachineStorage(const uint8_t *data, size_t size);
+ void invokeTransactionLog(const uint8_t *data, size_t size);
+ void invokeAnalyticsAction(const uint8_t *data, size_t size);
+ void invokeAudioAnalytics(const uint8_t *data, size_t size);
+ void invokeTimedAction(const uint8_t *data, size_t size);
+ void process(const uint8_t *data, size_t size);
+};
+
+void MediaMetricsServiceFuzzer::invokeStartsWith(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ while (fdp.remaining_bytes()) {
+ android::mediametrics::startsWith(fdp.ConsumeRandomLengthString(),
+ fdp.ConsumeRandomLengthString());
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokeInstantiate(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ sp mediaMetricsService = new MediaMetricsService();
+
+ while (fdp.remaining_bytes()) {
+ std::unique_ptr<mediametrics::Item> random_key(
+ mediametrics::Item::create(fdp.ConsumeRandomLengthString()));
+ mediaMetricsService->submit(random_key.get());
+ random_key->setInt32(fdp.ConsumeRandomLengthString().c_str(),
+ fdp.ConsumeIntegral<int32_t>());
+ mediaMetricsService->submit(random_key.get());
+
+ std::unique_ptr<mediametrics::Item> audiotrack_key(
+ mediametrics::Item::create("audiotrack"));
+ mediaMetricsService->submit(audiotrack_key.get());
+ audiotrack_key->addInt32(fdp.ConsumeRandomLengthString().c_str(),
+ fdp.ConsumeIntegral<int32_t>());
+ mediaMetricsService->submit(audiotrack_key.get());
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokePackageInstallerCheck(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ while (fdp.remaining_bytes()) {
+ MediaMetricsService::useUidForPackage(fdp.ConsumeRandomLengthString().c_str(),
+ fdp.ConsumeRandomLengthString().c_str());
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokeItemManipulation(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ mediametrics::Item item(fdp.ConsumeRandomLengthString().c_str());
+ while (fdp.remaining_bytes()) {
+ const uint8_t action = fdp.ConsumeIntegralInRange<uint8_t>(0, 16);
+ const std::string key = fdp.ConsumeRandomLengthString();
+ if (fdp.remaining_bytes() < 1 || key.length() < 1) {
+ break;
+ }
+ switch (action) {
+ case 0: {
+ item.setInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
+ break;
+ }
+ case 1: {
+ item.addInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
+ break;
+ }
+ case 2: {
+ int32_t i32 = 0;
+ item.getInt32(key.c_str(), &i32);
+ break;
+ }
+ case 3: {
+ item.setInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
+ break;
+ }
+ case 4: {
+ item.addInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
+ break;
+ }
+ case 5: {
+ int64_t i64 = 0;
+ item.getInt64(key.c_str(), &i64);
+ break;
+ }
+ case 6: {
+ item.setDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
+ break;
+ }
+ case 7: {
+ item.addDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
+ break;
+ }
+ case 8: {
+ double d = 0;
+ item.getDouble(key.c_str(), &d);
+ break;
+ }
+ case 9: {
+ item.setCString(key.c_str(), fdp.ConsumeRandomLengthString().c_str());
+ break;
+ }
+ case 10: {
+ char *s = nullptr;
+ item.getCString(key.c_str(), &s);
+ if (s) free(s);
+ break;
+ }
+ case 11: {
+ std::string s;
+ item.getString(key.c_str(), &s);
+ break;
+ }
+ case 12: {
+ item.setRate(key.c_str(), fdp.ConsumeIntegral<int64_t>(),
+ fdp.ConsumeIntegral<int64_t>());
+ break;
+ }
+ case 13: {
+ int64_t b = 0, h = 0;
+ double d = 0;
+ item.getRate(key.c_str(), &b, &h, &d);
+ break;
+ }
+ case 14: {
+ (void)item.filter(key.c_str());
+ break;
+ }
+ case 15: {
+ const char *arr[1] = {""};
+ arr[0] = const_cast<char *>(key.c_str());
+ (void)item.filterNot(1, arr);
+ break;
+ }
+ case 16: {
+ (void)item.toString().c_str();
+ break;
+ }
+ }
+ }
+
+ Parcel p;
+ mediametrics::Item item2;
+
+ (void)item.writeToParcel(&p);
+ p.setDataPosition(0); // rewind for reading
+ (void)item2.readFromParcel(p);
+
+ char *byteData = nullptr;
+ size_t length = 0;
+ (void)item.writeToByteString(&byteData, &length);
+ (void)item2.readFromByteString(byteData, length);
+ if (byteData) {
+ free(byteData);
+ }
+
+ sp mediaMetricsService = new MediaMetricsService();
+ mediaMetricsService->submit(&item2);
+}
+
+void MediaMetricsServiceFuzzer::invokeItemExpansion(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ mediametrics::LogItem<1> item("FuzzItem");
+ item.setPid(fdp.ConsumeIntegral<int16_t>()).setUid(fdp.ConsumeIntegral<int16_t>());
+
+ while (fdp.remaining_bytes()) {
+ int32_t i = fdp.ConsumeIntegral<int32_t>();
+ item.set(std::to_string(i).c_str(), (int32_t)i);
+ }
+ item.updateHeader();
+
+ mediametrics::Item item2;
+ (void)item2.readFromByteString(item.getBuffer(), item.getLength());
+
+ sp mediaMetricsService = new MediaMetricsService();
+ mediaMetricsService->submit(&item2);
+}
+
+void MediaMetricsServiceFuzzer::invokeTimeMachineStorage(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ auto item = std::make_shared<mediametrics::Item>("FuzzKey");
+ int32_t i32 = fdp.ConsumeIntegral<int32_t>();
+ int64_t i64 = fdp.ConsumeIntegral<int64_t>();
+ double d = fdp.ConsumeFloatingPoint<double>();
+ std::string str = fdp.ConsumeRandomLengthString();
+ std::pair<int64_t, int64_t> pair(fdp.ConsumeIntegral<int64_t>(),
+ fdp.ConsumeIntegral<int64_t>());
+ (*item).set("i32", i32).set("i64", i64).set("double", d).set("string", str).set("rate", pair);
+
+ android::mediametrics::TimeMachine timeMachine;
+ timeMachine.put(item, true);
+
+ timeMachine.get("Key", "i32", &i32, -1);
+
+ timeMachine.get("Key", "i64", &i64, -1);
+
+ timeMachine.get("Key", "double", &d, -1);
+
+ timeMachine.get("Key", "string", &str, -1);
+
+ timeMachine.get("Key.i32", &i32, -1);
+
+ timeMachine.get("Key.i64", &i64, -1);
+
+ timeMachine.get("Key.double", &d, -1);
+
+ str.clear();
+ timeMachine.get("Key.string", &str, -1);
+}
+
+void MediaMetricsServiceFuzzer::invokeTransactionLog(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ auto item = std::make_shared<mediametrics::Item>("Key1");
+ (*item)
+ .set("one", fdp.ConsumeIntegral<int32_t>())
+ .set("two", fdp.ConsumeIntegral<int32_t>())
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+ android::mediametrics::TransactionLog transactionLog(
+ kLogItemsLowWater, kLogItemsHighWater); // keep at most 2 items
+ transactionLog.size();
+
+ transactionLog.put(item);
+ transactionLog.size();
+
+ auto item2 = std::make_shared<mediametrics::Item>("Key2");
+ (*item2)
+ .set("three", fdp.ConsumeIntegral<int32_t>())
+ .set("[Key1]three", fdp.ConsumeIntegral<int32_t>())
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+ transactionLog.put(item2);
+ transactionLog.size();
+
+ auto item3 = std::make_shared<mediametrics::Item>("Key3");
+ (*item3)
+ .set("six", fdp.ConsumeIntegral<int32_t>())
+ .set("[Key1]four", fdp.ConsumeIntegral<int32_t>()) // affects Key1
+ .set("[Key1]five", fdp.ConsumeIntegral<int32_t>()) // affects key1
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+ transactionLog.put(item3);
+ transactionLog.size();
+}
+
+void MediaMetricsServiceFuzzer::invokeAnalyticsAction(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ mediametrics::AnalyticsActions analyticsActions;
+ bool action = false;
+
+ while (fdp.remaining_bytes()) {
+ analyticsActions.addAction(
+ (fdp.ConsumeRandomLengthString() + std::string(".event")).c_str(),
+ fdp.ConsumeRandomLengthString(),
+ std::make_shared<mediametrics::AnalyticsActions::Function>(
+ [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+ action = true;
+ }));
+ }
+
+ FuzzedDataProvider fdp2 = FuzzedDataProvider(data, size);
+
+ while (fdp2.remaining_bytes()) {
+ // make a test item
+ auto item = std::make_shared<mediametrics::Item>(fdp2.ConsumeRandomLengthString().c_str());
+ (*item).set("event", fdp2.ConsumeRandomLengthString().c_str());
+
+ // get the actions and execute them
+ auto actions = analyticsActions.getActionsForItem(item);
+ for (const auto &action : actions) {
+ action->operator()(item);
+ }
+ }
+}
+
+void MediaMetricsServiceFuzzer::invokeAudioAnalytics(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ android::mediametrics::AudioAnalytics audioAnalytics;
+
+ while (fdp.remaining_bytes()) {
+ auto item = std::make_shared<mediametrics::Item>(fdp.ConsumeRandomLengthString().c_str());
+ int32_t transactionUid = fdp.ConsumeIntegral<int32_t>(); // arbitrary
+ (*item)
+ .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
+ .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
+ .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
+ .setUid(transactionUid)
+ .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+ audioAnalytics.submit(item, fdp.ConsumeBool());
+ }
+
+ audioAnalytics.dump(1000);
+}
+
+void MediaMetricsServiceFuzzer::invokeTimedAction(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ android::mediametrics::TimedAction timedAction;
+ std::atomic_int value = 0;
+
+ while (fdp.remaining_bytes()) {
+ timedAction.postIn(std::chrono::seconds(fdp.ConsumeIntegral<int32_t>()),
+ [&value] { ++value; });
+ timedAction.size();
+ }
+}
+
+void MediaMetricsServiceFuzzer::process(const uint8_t *data, size_t size) {
+ invokeStartsWith(data, size);
+ invokeInstantiate(data, size);
+ invokePackageInstallerCheck(data, size);
+ invokeItemManipulation(data, size);
+ invokeItemExpansion(data, size);
+ invokeTimeMachineStorage(data, size);
+ invokeTransactionLog(data, size);
+ invokeAnalyticsAction(data, size);
+ invokeAudioAnalytics(data, size);
+ invokeTimedAction(data, size);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer;
+ mediaMetricsServiceFuzzer.process(data, size);
+ return 0;
+}
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
index 6e51f72..16204de 100644
--- a/services/mediametrics/iface_statsd.cpp
+++ b/services/mediametrics/iface_statsd.cpp
@@ -64,6 +64,7 @@
{ "drmmanager", statsd_drmmanager },
{ "extractor", statsd_extractor },
{ "mediadrm", statsd_mediadrm },
+ { "mediaparser", statsd_mediaparser },
{ "nuplayer", statsd_nuplayer },
{ "nuplayer2", statsd_nuplayer },
{ "recorder", statsd_recorder },
diff --git a/services/mediametrics/iface_statsd.h b/services/mediametrics/iface_statsd.h
index 19505a4..9b49556 100644
--- a/services/mediametrics/iface_statsd.h
+++ b/services/mediametrics/iface_statsd.h
@@ -25,6 +25,7 @@
extern bool statsd_audiotrack(const mediametrics::Item *);
extern bool statsd_codec(const mediametrics::Item *);
extern bool statsd_extractor(const mediametrics::Item *);
+extern bool statsd_mediaparser(const mediametrics::Item *);
extern bool statsd_nuplayer(const mediametrics::Item *);
extern bool statsd_recorder(const mediametrics::Item *);
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 16814d9..4180e0c 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -71,6 +71,22 @@
metrics_proto.set_tracks(ntrk);
}
+ // android.media.mediaextractor.entry string
+ std::string entry_point_string;
+ if (item->getString("android.media.mediaextractor.entry", &entry_point_string)) {
+ stats::mediametrics::ExtractorData::EntryPoint entry_point;
+ if (entry_point_string == "sdk") {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_SDK;
+ } else if (entry_point_string == "ndk-with-jvm") {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_WITH_JVM;
+ } else if (entry_point_string == "ndk-no-jvm") {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_NO_JVM;
+ } else {
+ entry_point = stats::mediametrics::ExtractorData_EntryPoint_OTHER;
+ }
+ metrics_proto.set_entry_point(entry_point);
+ }
+
std::string serialized;
if (!metrics_proto.SerializeToString(&serialized)) {
ALOGE("Failed to serialize extractor metrics");
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
new file mode 100644
index 0000000..262b2ae
--- /dev/null
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 "statsd_mediaparser"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_mediaparser(const mediametrics::Item *item)
+{
+ if (item == nullptr) {
+ return false;
+ }
+
+ // statsd wrapper data.
+ const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+ std::string pkgName = item->getPkgName();
+ int64_t pkgVersionCode = item->getPkgVersionCode();
+
+ std::string parserName;
+ item->getString("android.media.mediaparser.parserName", &parserName);
+
+ int32_t createdByName = -1;
+ item->getInt32("android.media.mediaparser.createdByName", &createdByName);
+
+ std::string parserPool;
+ item->getString("android.media.mediaparser.parserPool", &parserPool);
+
+ std::string lastException;
+ item->getString("android.media.mediaparser.lastException", &lastException);
+
+ int64_t resourceByteCount = -1;
+ item->getInt64("android.media.mediaparser.resourceByteCount", &resourceByteCount);
+
+ int64_t durationMillis = -1;
+ item->getInt64("android.media.mediaparser.durationMillis", &durationMillis);
+
+ std::string trackMimeTypes;
+ item->getString("android.media.mediaparser.trackMimeTypes", &trackMimeTypes);
+
+ std::string trackCodecs;
+ item->getString("android.media.mediaparser.trackCodecs", &trackCodecs);
+
+ std::string alteredParameters;
+ item->getString("android.media.mediaparser.alteredParameters", &alteredParameters);
+
+ int32_t videoWidth = -1;
+ item->getInt32("android.media.mediaparser.videoWidth", &videoWidth);
+
+ int32_t videoHeight = -1;
+ item->getInt32("android.media.mediaparser.videoHeight", &videoHeight);
+
+ if (enabled_statsd) {
+ (void) android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
+ timestamp,
+ pkgName.c_str(),
+ pkgVersionCode,
+ parserName.c_str(),
+ createdByName,
+ parserPool.c_str(),
+ lastException.c_str(),
+ resourceByteCount,
+ durationMillis,
+ trackMimeTypes.c_str(),
+ trackCodecs.c_str(),
+ alteredParameters.c_str(),
+ videoWidth,
+ videoHeight);
+ } else {
+ ALOGV("NOT sending MediaParser media metrics.");
+ }
+
+ return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
index c2e0759..3aee209 100644
--- a/services/mediametrics/tests/Android.bp
+++ b/services/mediametrics/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "mediametrics_tests",
test_suites: ["device-tests"],
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index 0d53c5e..e503885 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_library {
name: "libresourcemanagerservice",
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
similarity index 61%
copy from media/libstagefright/codecs/amrnb/fuzzer/Android.bp
copy to services/mediaresourcemanager/fuzzer/Android.bp
index c1eaa53..81c85e5 100644
--- a/media/libstagefright/codecs/amrnb/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,22 +18,30 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_fuzz {
- name: "amrnb_dec_fuzzer",
- host_supported: true,
+ name: "mediaresourcemanager_fuzzer",
srcs: [
- "amrnb_dec_fuzzer.cpp",
+ "mediaresourcemanager_fuzzer.cpp",
],
static_libs: [
- "libstagefright_amrnbdec",
- "libstagefright_amrnb_common",
"liblog",
+ "libresourcemanagerservice",
],
- target: {
- darwin: {
- enabled: false,
- },
- },
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libmedia",
+ "libutils",
+ ],
fuzz_config: {
cc: [
"android-media-fuzzing-reports@google.com",
diff --git a/services/mediaresourcemanager/fuzzer/README.md b/services/mediaresourcemanager/fuzzer/README.md
new file mode 100644
index 0000000..c600be4
--- /dev/null
+++ b/services/mediaresourcemanager/fuzzer/README.md
@@ -0,0 +1,46 @@
+# Fuzzer for libresourcemanagerservice
+
+## Plugin Design Considerations
+The fuzzer plugin for libresourcemanagerservice is designed based on the
+understanding of the service and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Media Resource Manager supports the following parameters:
+1. Media Resource Type (parameter name: `mediaResourceType`)
+2. Media Resource SubType (parameter name: `mediaResourceSubType`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `mediaResourceType` | 0.`MediaResource::kSecureCodec` 1.`MediaResource::kNonSecureCodecC` 2.`MediaResource::kGraphicMemory` 3.`MediaResource::kCpuBoost` 4.`MediaResource::kBattery` 5.`MediaResource::kDrmSession`| Value obtained from FuzzedDataProvider |
+| `mediaResourceSubType` | 0.`MediaResource::kAudioCodec` 1.`MediaResource::kVideoCodec` 2.`MediaResource::kUnspecifiedSubType` | Value obtained from FuzzedDataProvider |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+## Build
+
+This describes steps to build mediaresourcemanager_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) mediaresourcemanager_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some files to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mediaresourcemanager_fuzzer/mediaresourcemanager_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
new file mode 100644
index 0000000..6690b16
--- /dev/null
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -0,0 +1,299 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include <ServiceLog.h>
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <media/MediaResource.h>
+#include <media/MediaResourcePolicy.h>
+#include <media/stagefright/ProcessInfoInterface.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include "ResourceManagerService.h"
+#include "fuzzer/FuzzedDataProvider.h"
+
+using namespace std;
+using namespace android;
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::BnResourceManagerClient;
+using ::aidl::android::media::IResourceManagerClient;
+using ::aidl::android::media::IResourceManagerService;
+using MedResType = aidl::android::media::MediaResourceType;
+using MedResSubType = aidl::android::media::MediaResourceSubType;
+
+const size_t kMaxStringLength = 100;
+const int32_t kMaxServiceLog = 100;
+const int32_t kMinServiceLog = 1;
+const int32_t kMinResourceType = 0;
+const int32_t kMaxResourceType = 10;
+const int32_t kMinThreadPairs = 1;
+const int32_t kMaxThreadPairs = 3;
+
+const string kPolicyType[] = {IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
+ IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec};
+
+struct resourceThreadArgs {
+ int32_t pid;
+ int32_t uid;
+ int64_t testClientId;
+ shared_ptr<ResourceManagerService> service;
+ shared_ptr<IResourceManagerClient> testClient;
+ vector<MediaResourceParcel> mediaResource;
+};
+
+static int64_t getId(const shared_ptr<IResourceManagerClient>& client) {
+ return (int64_t)client.get();
+}
+
+struct TestProcessInfo : public ProcessInfoInterface {
+ TestProcessInfo() {}
+ virtual ~TestProcessInfo() {}
+
+ virtual bool getPriority(int pid, int* priority) {
+ // For testing, use pid as priority.
+ // Lower the value higher the priority.
+ *priority = pid;
+ return true;
+ }
+
+ virtual bool isValidPid(int /* pid */) { return true; }
+ virtual bool overrideProcessInfo(int /* pid */, int /*procState*/, int /*oomScore*/) {
+ return true;
+ }
+ virtual void removeProcessInfoOverride(int /* pid */) { return; }
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
+};
+
+struct TestSystemCallback : public ResourceManagerService::SystemCallbackInterface {
+ TestSystemCallback() : mLastEvent({EventType::INVALID, 0}), mEventCount(0) {}
+
+ enum EventType {
+ INVALID = -1,
+ VIDEO_ON = 0,
+ VIDEO_OFF = 1,
+ VIDEO_RESET = 2,
+ CPUSET_ENABLE = 3,
+ CPUSET_DISABLE = 4,
+ };
+
+ struct EventEntry {
+ EventType type;
+ int arg;
+ };
+
+ virtual void noteStartVideo(int uid) override {
+ mLastEvent = {EventType::VIDEO_ON, uid};
+ ++mEventCount;
+ }
+
+ virtual void noteStopVideo(int uid) override {
+ mLastEvent = {EventType::VIDEO_OFF, uid};
+ ++mEventCount;
+ }
+
+ virtual void noteResetVideo() override {
+ mLastEvent = {EventType::VIDEO_RESET, 0};
+ ++mEventCount;
+ }
+
+ virtual bool requestCpusetBoost(bool enable) override {
+ mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
+ ++mEventCount;
+ return true;
+ }
+
+ size_t eventCount() { return mEventCount; }
+ EventType lastEventType() { return mLastEvent.type; }
+ EventEntry lastEvent() { return mLastEvent; }
+
+ protected:
+ virtual ~TestSystemCallback() {}
+
+ private:
+ EventEntry mLastEvent;
+ size_t mEventCount;
+
+ DISALLOW_EVIL_CONSTRUCTORS(TestSystemCallback);
+};
+
+struct TestClient : public BnResourceManagerClient {
+ TestClient(int pid, const shared_ptr<ResourceManagerService>& service)
+ : mReclaimed(false), mPid(pid), mService(service) {}
+
+ Status reclaimResource(bool* aidlReturn) override {
+ mService->removeClient(mPid, getId(ref<TestClient>()));
+ mReclaimed = true;
+ *aidlReturn = true;
+ return Status::ok();
+ }
+
+ Status getName(string* aidlReturn) override {
+ *aidlReturn = "test_client";
+ return Status::ok();
+ }
+
+ virtual ~TestClient() {}
+
+ private:
+ bool mReclaimed;
+ int mPid;
+ shared_ptr<ResourceManagerService> mService;
+ DISALLOW_EVIL_CONSTRUCTORS(TestClient);
+};
+
+class ResourceManagerServiceFuzzer {
+ public:
+ ResourceManagerServiceFuzzer() = default;
+ ~ResourceManagerServiceFuzzer() {
+ mService = nullptr;
+ delete mFuzzedDataProvider;
+ }
+ void process(const uint8_t* data, size_t size);
+
+ private:
+ void setConfig();
+ void setResources();
+ void setServiceLog();
+
+ static void* addResource(void* arg) {
+ resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
+ if (tArgs) {
+ (tArgs->service)
+ ->addResource(tArgs->pid, tArgs->uid, tArgs->testClientId, tArgs->testClient,
+ tArgs->mediaResource);
+ }
+ return nullptr;
+ }
+
+ static void* removeResource(void* arg) {
+ resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
+ if (tArgs) {
+ bool result;
+ (tArgs->service)->markClientForPendingRemoval(tArgs->pid, tArgs->testClientId);
+ (tArgs->service)->removeResource(tArgs->pid, tArgs->testClientId, tArgs->mediaResource);
+ (tArgs->service)->reclaimResource(tArgs->pid, tArgs->mediaResource, &result);
+ (tArgs->service)->removeClient(tArgs->pid, tArgs->testClientId);
+ (tArgs->service)->overridePid(tArgs->pid, tArgs->pid - 1);
+ }
+ return nullptr;
+ }
+
+ shared_ptr<ResourceManagerService> mService =
+ ::ndk::SharedRefBase::make<ResourceManagerService>(new TestProcessInfo(),
+ new TestSystemCallback());
+ FuzzedDataProvider* mFuzzedDataProvider = nullptr;
+};
+
+void ResourceManagerServiceFuzzer::process(const uint8_t* data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ setConfig();
+ setResources();
+ setServiceLog();
+}
+
+void ResourceManagerServiceFuzzer::setConfig() {
+ bool policyTypeIndex = mFuzzedDataProvider->ConsumeBool();
+ string policyValue = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength);
+ if (mService) {
+ vector<MediaResourcePolicyParcel> policies;
+ policies.push_back(MediaResourcePolicy(kPolicyType[policyTypeIndex], policyValue));
+ mService->config(policies);
+ }
+}
+
+void ResourceManagerServiceFuzzer::setResources() {
+ if (!mService) {
+ return;
+ }
+ size_t numThreadPairs =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinThreadPairs, kMaxThreadPairs);
+ // Make even number of threads
+ size_t numThreads = numThreadPairs * 2;
+ resourceThreadArgs threadArgs;
+ vector<MediaResourceParcel> mediaResource;
+ pthread_t pt[numThreads];
+ int i;
+ for (i = 0; i < numThreads - 1; i += 2) {
+ threadArgs.pid = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ threadArgs.uid = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ int32_t mediaResourceType = mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
+ kMinResourceType, kMaxResourceType);
+ int32_t mediaResourceSubType = mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
+ kMinResourceType, kMaxResourceType);
+ uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
+ threadArgs.service = mService;
+ shared_ptr<IResourceManagerClient> testClient =
+ ::ndk::SharedRefBase::make<TestClient>(threadArgs.pid, mService);
+ threadArgs.testClient = testClient;
+ threadArgs.testClientId = getId(testClient);
+ mediaResource.push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
+ static_cast<MedResSubType>(mediaResourceSubType),
+ mediaResourceValue));
+ threadArgs.mediaResource = mediaResource;
+ pthread_create(&pt[i], nullptr, addResource, &threadArgs);
+ pthread_create(&pt[i + 1], nullptr, removeResource, &threadArgs);
+ mediaResource.clear();
+ }
+
+ for (i = 0; i < numThreads; ++i) {
+ pthread_join(pt[i], nullptr);
+ }
+
+ // No resource was added with pid = 0
+ int32_t pidZero = 0;
+ shared_ptr<IResourceManagerClient> testClient =
+ ::ndk::SharedRefBase::make<TestClient>(pidZero, mService);
+ int32_t mediaResourceType =
+ mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinResourceType, kMaxResourceType);
+ int32_t mediaResourceSubType =
+ mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinResourceType, kMaxResourceType);
+ uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
+ mediaResource.push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
+ static_cast<MedResSubType>(mediaResourceSubType),
+ mediaResourceValue));
+ bool result;
+ mService->reclaimResource(pidZero, mediaResource, &result);
+ mService->removeResource(pidZero, getId(testClient), mediaResource);
+ mService->removeClient(pidZero, getId(testClient));
+ mediaResource.clear();
+}
+
+void ResourceManagerServiceFuzzer::setServiceLog() {
+ size_t maxNum =
+ mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinServiceLog, kMaxServiceLog);
+ sp<ServiceLog> serviceLog = new ServiceLog(maxNum);
+ if (serviceLog) {
+ serviceLog->add(String8("log"));
+ serviceLog->toString();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ ResourceManagerServiceFuzzer* rmFuzzer = new ResourceManagerServiceFuzzer();
+ if (!rmFuzzer) {
+ return 0;
+ }
+ rmFuzzer->process(data, size);
+ delete rmFuzzer;
+ return 0;
+}
diff --git a/services/mediaresourcemanager/test/Android.bp b/services/mediaresourcemanager/test/Android.bp
index 6b2ef69..0c5b8a2 100644
--- a/services/mediaresourcemanager/test/Android.bp
+++ b/services/mediaresourcemanager/test/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
cc_test {
name: "ResourceManagerService_test",
srcs: ["ResourceManagerService_test.cpp"],
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index a6ecc09..3a45dcf 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -27,14 +27,6 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/ProcessInfoInterface.h>
-namespace aidl {
-namespace android {
-namespace media {
-bool operator== (const MediaResourceParcel& lhs, const MediaResourceParcel& rhs) {
- return lhs.type == rhs.type && lhs.subType == rhs.subType &&
- lhs.id == rhs.id && lhs.value == rhs.value;
-}}}}
-
namespace android {
using Status = ::ndk::ScopedAStatus;
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
index 8cf2d62..a895071 100644
--- a/services/mediatranscoding/Android.bp
+++ b/services/mediatranscoding/Android.bp
@@ -1,4 +1,23 @@
// service library
+package {
+ default_applicable_licenses: [
+ "frameworks_av_services_mediatranscoding_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_services_mediatranscoding_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libmediatranscodingservice",
diff --git a/services/mediatranscoding/tests/Android.bp b/services/mediatranscoding/tests/Android.bp
index e0e040c..86e047e 100644
--- a/services/mediatranscoding/tests/Android.bp
+++ b/services/mediatranscoding/tests/Android.bp
@@ -1,5 +1,16 @@
// Build the unit tests for MediaTranscodingService
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_services_mediatranscoding_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_services_mediatranscoding_license",
+ ],
+}
+
cc_defaults {
name: "mediatranscodingservice_test_defaults",
@@ -32,4 +43,4 @@
defaults: ["mediatranscodingservice_test_defaults"],
srcs: ["mediatranscodingservice_tests.cpp"],
-}
\ No newline at end of file
+}
diff --git a/services/minijail/Android.bp b/services/minijail/Android.bp
index b057968..3a89e12 100644
--- a/services/minijail/Android.bp
+++ b/services/minijail/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
minijail_common_cflags = [
"-Wall",
"-Werror",
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index ceefe93..b139be1 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -182,11 +182,12 @@
: AUDIO_SOURCE_DEFAULT;
audio_flags_mask_t flags;
if (direction == AAUDIO_DIRECTION_OUTPUT) {
- flags = AUDIO_FLAG_LOW_LATENCY
- | AAudioConvert_allowCapturePolicyToAudioFlagsMask(params->getAllowedCapturePolicy());
+ flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
+ | AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+ params->getAllowedCapturePolicy()));
} else {
- flags = AUDIO_FLAG_LOW_LATENCY
- | AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive());
+ flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
+ | AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive()));
}
return {
.content_type = contentType,
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index a171cb0..04b906a 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -47,7 +47,11 @@
virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
- virtual aaudio_result_t close() = 0;
+ /*
+ * Perform any cleanup necessary before deleting the stream.
+ * This might include releasing and closing internal streams.
+ */
+ virtual void close() = 0;
aaudio_result_t registerStream(android::sp<AAudioServiceStreamBase> stream);
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 37d105b..3ba3c28 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -36,18 +36,18 @@
using namespace aaudio; // TODO just import names needed
AAudioServiceEndpointCapture::AAudioServiceEndpointCapture(AAudioService &audioService)
- : mStreamInternalCapture(audioService, true) {
- mStreamInternal = &mStreamInternalCapture;
+ : AAudioServiceEndpointShared(
+ (AudioStreamInternal *)(new AudioStreamInternalCapture(audioService, true))) {
}
AAudioServiceEndpointCapture::~AAudioServiceEndpointCapture() {
- delete mDistributionBuffer;
+ delete[] mDistributionBuffer;
}
aaudio_result_t AAudioServiceEndpointCapture::open(const aaudio::AAudioStreamRequest &request) {
aaudio_result_t result = AAudioServiceEndpointShared::open(request);
if (result == AAUDIO_OK) {
- delete mDistributionBuffer;
+ delete[] mDistributionBuffer;
int distributionBufferSizeBytes = getStreamInternal()->getFramesPerBurst()
* getStreamInternal()->getBytesPerFrame();
mDistributionBuffer = new uint8_t[distributionBufferSizeBytes];
@@ -69,7 +69,9 @@
// Read audio data from stream using a blocking read.
result = getStreamInternal()->read(mDistributionBuffer, getFramesPerBurst(), timeoutNanos);
if (result == AAUDIO_ERROR_DISCONNECTED) {
- disconnectRegisteredStreams();
+ ALOGD("%s() read() returned AAUDIO_ERROR_DISCONNECTED", __func__);
+ // We do not need the returned vector.
+ (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
break;
} else if (result != getFramesPerBurst()) {
ALOGW("callbackLoop() read %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.h b/services/oboeservice/AAudioServiceEndpointCapture.h
index 971da9a..2bbe81d 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.h
+++ b/services/oboeservice/AAudioServiceEndpointCapture.h
@@ -36,8 +36,7 @@
void *callbackLoop() override;
private:
- AudioStreamInternalCapture mStreamInternalCapture;
- uint8_t *mDistributionBuffer = nullptr;
+ uint8_t *mDistributionBuffer = nullptr;
};
} /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 0843e0b..04c6453 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -226,7 +226,7 @@
return result;
}
-aaudio_result_t AAudioServiceEndpointMMAP::close() {
+void AAudioServiceEndpointMMAP::close() {
if (mMmapStream != nullptr) {
// Needs to be explicitly cleared or CTS will fail but it is not clear why.
mMmapStream.clear();
@@ -235,8 +235,6 @@
// FIXME Make closing synchronous.
AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
}
-
- return AAUDIO_OK;
}
aaudio_result_t AAudioServiceEndpointMMAP::startStream(sp<AAudioServiceStreamBase> stream,
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 3d10861..b6003b6 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -50,7 +50,7 @@
aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
- aaudio_result_t close() override;
+ void close() override;
aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
audio_port_handle_t *clientHandle) override;
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index bda4b90..89aa70d 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -42,8 +42,8 @@
#define BURSTS_PER_BUFFER_DEFAULT 2
AAudioServiceEndpointPlay::AAudioServiceEndpointPlay(AAudioService &audioService)
- : mStreamInternalPlay(audioService, true) {
- mStreamInternal = &mStreamInternalPlay;
+ : AAudioServiceEndpointShared(
+ (AudioStreamInternal *)(new AudioStreamInternalPlay(audioService, true))) {
}
aaudio_result_t AAudioServiceEndpointPlay::open(const aaudio::AAudioStreamRequest &request) {
@@ -145,7 +145,9 @@
result = getStreamInternal()->write(mMixer.getOutputBuffer(),
getFramesPerBurst(), timeoutNanos);
if (result == AAUDIO_ERROR_DISCONNECTED) {
- AAudioServiceEndpointShared::disconnectRegisteredStreams();
+ ALOGD("%s() write() returned AAUDIO_ERROR_DISCONNECTED", __func__);
+ // We do not need the returned vector.
+ (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
break;
} else if (result != getFramesPerBurst()) {
ALOGW("callbackLoop() wrote %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.h b/services/oboeservice/AAudioServiceEndpointPlay.h
index 981e430..160a1de 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.h
+++ b/services/oboeservice/AAudioServiceEndpointPlay.h
@@ -45,7 +45,6 @@
void *callbackLoop() override;
private:
- AudioStreamInternalPlay mStreamInternalPlay; // for playing output of mixer
bool mLatencyTuningEnabled = false; // TODO implement tuning
AAudioMixer mMixer; //
};
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index dc21886..f5de59f 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -40,6 +40,9 @@
// This is the maximum size in frames. The effective size can be tuned smaller at runtime.
#define DEFAULT_BUFFER_CAPACITY (48 * 8)
+AAudioServiceEndpointShared::AAudioServiceEndpointShared(AudioStreamInternal *streamInternal)
+ : mStreamInternal(streamInternal) {}
+
std::string AAudioServiceEndpointShared::dump() const {
std::stringstream result;
@@ -84,8 +87,8 @@
return result;
}
-aaudio_result_t AAudioServiceEndpointShared::close() {
- return getStreamInternal()->releaseCloseFinal();
+void AAudioServiceEndpointShared::close() {
+ getStreamInternal()->releaseCloseFinal();
}
// Glue between C and C++ callbacks.
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index bfc1744..020b926 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -35,12 +35,13 @@
class AAudioServiceEndpointShared : public AAudioServiceEndpoint {
public:
+ explicit AAudioServiceEndpointShared(AudioStreamInternal *streamInternal);
std::string dump() const override;
aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
- aaudio_result_t close() override;
+ void close() override;
aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
audio_port_handle_t *clientHandle) override;
@@ -57,15 +58,15 @@
protected:
AudioStreamInternal *getStreamInternal() const {
- return mStreamInternal;
+ return mStreamInternal.get();
};
aaudio_result_t startSharingThread_l();
aaudio_result_t stopSharingThread();
- // pointer to object statically allocated in subclasses
- AudioStreamInternal *mStreamInternal = nullptr;
+ // An MMAP stream that is shared by multiple clients.
+ android::sp<AudioStreamInternal> mStreamInternal;
std::atomic<bool> mCallbackEnabled{false};
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 8b1e2c0..c40a79e 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -12,7 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
name: "libaaudioservice",