Merge "C2AllocatorBlob: allow multiple maps" into mainline-prod
diff --git a/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
index 1b8b8c1..089eb1c 100644
--- a/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
@@ -109,6 +109,7 @@
}
void DrmPlugin::setPlayPolicy() {
+ android::Mutex::Autolock lock(mPlayPolicyLock);
mPlayPolicy.clear();
mPlayPolicy.add(kQueryKeyLicenseType, kStreaming);
mPlayPolicy.add(kQueryKeyPlayAllowed, kTrue);
@@ -206,6 +207,7 @@
}
infoMap.clear();
+ android::Mutex::Autolock lock(mPlayPolicyLock);
for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
infoMap.add(mPlayPolicy.keyAt(i), mPlayPolicy.valueAt(i));
}
diff --git a/drm/mediadrm/plugins/clearkey/default/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/default/include/DrmPlugin.h
index 4fa42e5..95f15ca 100644
--- a/drm/mediadrm/plugins/clearkey/default/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/default/include/DrmPlugin.h
@@ -262,6 +262,7 @@
void initProperties();
void setPlayPolicy();
+ mutable android::Mutex mPlayPolicyLock;
android::KeyedVector<String8, String8> mPlayPolicy;
android::KeyedVector<String8, String8> mStringProperties;
android::KeyedVector<String8, Vector<uint8_t>> mByteArrayProperties;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index a194416..c6afa60 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -37,7 +37,7 @@
relative_install_path: "hw",
- cflags: ["-Wall", "-Werror"],
+ cflags: ["-Wall", "-Werror", "-Wthread-safety"],
shared_libs: [
"android.hardware.drm@1.0",
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index 1495703..302dd39 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -37,6 +37,8 @@
sp<IMemory> hidlMemory = mapMemory(base);
ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
+ std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
+
// allow mapMemory to return nullptr
mSharedBufferMap[bufferId] = hidlMemory;
return Void();
@@ -94,6 +96,7 @@
return Void();
}
+ std::unique_lock<std::mutex> shared_buffer_lock(mSharedBufferLock);
if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
_hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
"source decrypt buffer base not set");
@@ -119,7 +122,11 @@
return Void();
}
- if (source.offset + offset + source.size > sourceBase->getSize()) {
+ size_t totalSize = 0;
+ if (__builtin_add_overflow(source.offset, offset, &totalSize) ||
+ __builtin_add_overflow(totalSize, source.size, &totalSize) ||
+ totalSize > sourceBase->getSize()) {
+ android_errorWriteLog(0x534e4554, "176496160");
_hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
@@ -138,12 +145,17 @@
base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer()));
- if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
+ totalSize = 0;
+ if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
+ totalSize > destBase->getSize()) {
+ android_errorWriteLog(0x534e4554, "176444622");
_hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
return Void();
}
- destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+ destPtr = static_cast<void*>(base + destination.nonsecureMemory.offset);
+ // release mSharedBufferLock
+ shared_buffer_lock.unlock();
// Calculate the output buffer size and determine if any subsamples are
// encrypted.
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index f87f830..6f69110 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -220,6 +220,7 @@
if (requestString.find(kOfflineLicense) != std::string::npos) {
std::string emptyResponse;
std::string keySetIdString(keySetId.begin(), keySetId.end());
+ Mutex::Autolock lock(mFileHandleLock);
if (!mFileHandle.StoreLicense(keySetIdString,
DeviceFiles::kLicenseStateReleasing,
emptyResponse)) {
@@ -304,6 +305,7 @@
}
void DrmPlugin::setPlayPolicy() {
+ android::Mutex::Autolock lock(mPlayPolicyLock);
mPlayPolicy.clear();
KeyValue policy;
@@ -334,6 +336,7 @@
}
*keySetId = kKeySetIdPrefix + ByteArrayToHexString(
reinterpret_cast<const uint8_t*>(randomData.data()), randomData.size());
+ Mutex::Autolock lock(mFileHandleLock);
if (mFileHandle.LicenseExists(*keySetId)) {
// collision, regenerate
ALOGV("Retry generating KeySetId");
@@ -391,6 +394,7 @@
if (status == Status::OK) {
if (isOfflineLicense) {
if (isRelease) {
+ Mutex::Autolock lock(mFileHandleLock);
mFileHandle.DeleteLicense(keySetId);
mSessionLibrary->destroySession(session);
} else {
@@ -399,6 +403,7 @@
return Void();
}
+ Mutex::Autolock lock(mFileHandleLock);
bool ok = mFileHandle.StoreLicense(
keySetId,
DeviceFiles::kLicenseStateActive,
@@ -453,6 +458,7 @@
DeviceFiles::LicenseState licenseState;
std::string offlineLicense;
Status status = Status::OK;
+ Mutex::Autolock lock(mFileHandleLock);
if (!mFileHandle.RetrieveLicense(std::string(keySetId.begin(), keySetId.end()),
&licenseState, &offlineLicense)) {
ALOGE("Failed to restore offline license");
@@ -575,7 +581,6 @@
Return<void> DrmPlugin::queryKeyStatus(
const hidl_vec<uint8_t>& sessionId,
queryKeyStatus_cb _hidl_cb) {
-
if (sessionId.size() == 0) {
// Returns empty key status KeyValue pair
_hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
@@ -585,12 +590,14 @@
std::vector<KeyValue> infoMapVec;
infoMapVec.clear();
+ mPlayPolicyLock.lock();
KeyValue keyValuePair;
for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
keyValuePair.key = mPlayPolicy[i].key;
keyValuePair.value = mPlayPolicy[i].value;
infoMapVec.push_back(keyValuePair);
}
+ mPlayPolicyLock.unlock();
_hidl_cb(Status::OK, toHidlVec(infoMapVec));
return Void();
}
@@ -703,6 +710,8 @@
}
Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) {
+ Mutex::Autolock lock(mFileHandleLock);
+
std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
std::vector<KeySetId> keySetIds;
if (mMockError != Status_V1_2::OK) {
@@ -723,6 +732,7 @@
return toStatus_1_0(mMockError);
}
std::string licenseName(keySetId.begin(), keySetId.end());
+ Mutex::Autolock lock(mFileHandleLock);
if (mFileHandle.DeleteLicense(licenseName)) {
return Status::OK;
}
@@ -731,6 +741,8 @@
Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId,
getOfflineLicenseState_cb _hidl_cb) {
+ Mutex::Autolock lock(mFileHandleLock);
+
std::string licenseName(keySetId.begin(), keySetId.end());
DeviceFiles::LicenseState state;
std::string license;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
index 2dcd00f..d29acac 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
@@ -24,11 +24,13 @@
}
bool MemoryFileSystem::FileExists(const std::string& fileName) const {
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
auto result = mMemoryFileSystem.find(fileName);
return result != mMemoryFileSystem.end();
}
ssize_t MemoryFileSystem::GetFileSize(const std::string& fileName) const {
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
auto result = mMemoryFileSystem.find(fileName);
if (result != mMemoryFileSystem.end()) {
return static_cast<ssize_t>(result->second.getFileSize());
@@ -40,6 +42,7 @@
std::vector<std::string> MemoryFileSystem::ListFiles() const {
std::vector<std::string> list;
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
for (const auto& filename : mMemoryFileSystem) {
list.push_back(filename.first);
}
@@ -48,6 +51,7 @@
size_t MemoryFileSystem::Read(const std::string& path, std::string* buffer) {
std::string key = GetFileName(path);
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
auto result = mMemoryFileSystem.find(key);
if (result != mMemoryFileSystem.end()) {
std::string serializedHashFile = result->second.getContent();
@@ -61,6 +65,7 @@
size_t MemoryFileSystem::Write(const std::string& path, const MemoryFile& memoryFile) {
std::string key = GetFileName(path);
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
auto result = mMemoryFileSystem.find(key);
if (result != mMemoryFileSystem.end()) {
mMemoryFileSystem.erase(key);
@@ -70,6 +75,7 @@
}
bool MemoryFileSystem::RemoveFile(const std::string& fileName) {
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
auto result = mMemoryFileSystem.find(fileName);
if (result != mMemoryFileSystem.end()) {
mMemoryFileSystem.erase(result);
@@ -81,6 +87,7 @@
}
bool MemoryFileSystem::RemoveAllFiles() {
+ std::lock_guard<std::mutex> lock(mMemoryFileSystemLock);
mMemoryFileSystem.clear();
return mMemoryFileSystem.empty();
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
index 8680f0c..23a64fa 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
@@ -20,6 +20,8 @@
#include <android/hardware/drm/1.2/ICryptoPlugin.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <mutex>
+
#include "ClearKeyTypes.h"
#include "Session.h"
#include "Utils.h"
@@ -93,7 +95,7 @@
const SharedBuffer& source,
uint64_t offset,
const DestinationBuffer& destination,
- decrypt_1_2_cb _hidl_cb);
+ decrypt_1_2_cb _hidl_cb) NO_THREAD_SAFETY_ANALYSIS; // use unique_lock
Return<void> setSharedBufferBase(const hidl_memory& base,
uint32_t bufferId);
@@ -105,7 +107,8 @@
private:
CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoPlugin);
- std::map<uint32_t, sp<IMemory> > mSharedBufferMap;
+ std::mutex mSharedBufferLock;
+ std::map<uint32_t, sp<IMemory>> mSharedBufferMap GUARDED_BY(mSharedBufferLock);
sp<Session> mSession;
Status mInitStatus;
};
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 3de7589..894985b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -406,6 +406,7 @@
int64_t mCloseSessionOkCount;
int64_t mCloseSessionNotOpenedCount;
uint32_t mNextSecureStopId;
+ android::Mutex mPlayPolicyLock;
// set by property to mock error scenarios
Status_V1_2 mMockError;
@@ -415,7 +416,8 @@
mMockError = Status_V1_2::OK;
}
- DeviceFiles mFileHandle;
+ DeviceFiles mFileHandle GUARDED_BY(mFileHandleLock);
+ Mutex mFileHandleLock;
Mutex mSecureStopLock;
CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
index bcd9fd6..6ac0e2c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
@@ -5,7 +5,9 @@
#ifndef CLEARKEY_MEMORY_FILE_SYSTEM_H_
#define CLEARKEY_MEMORY_FILE_SYSTEM_H_
+#include <android-base/thread_annotations.h>
#include <map>
+#include <mutex>
#include <string>
#include "ClearKeyTypes.h"
@@ -49,10 +51,12 @@
size_t Write(const std::string& pathName, const MemoryFile& memoryFile);
private:
+ mutable std::mutex mMemoryFileSystemLock;
+
// License file name is made up of a unique keySetId, therefore,
// the filename can be used as the key to locate licenses in the
// memory file system.
- std::map<std::string, MemoryFile> mMemoryFileSystem;
+ std::map<std::string, MemoryFile> mMemoryFileSystem GUARDED_BY(mMemoryFileSystemLock);
std::string GetFileName(const std::string& path);
diff --git a/media/bufferpool/1.0/TEST_MAPPING b/media/bufferpool/1.0/TEST_MAPPING
new file mode 100644
index 0000000..a1e6a58
--- /dev/null
+++ b/media/bufferpool/1.0/TEST_MAPPING
@@ -0,0 +1,8 @@
+// mappings for frameworks/av/media/bufferpool/1.0
+{
+ "presubmit": [
+
+ { "name": "VtsVndkHidlBufferpoolV1_0TargetSingleTest" },
+ { "name": "VtsVndkHidlBufferpoolV1_0TargetMultiTest"}
+ ]
+}
diff --git a/media/bufferpool/1.0/vts/Android.bp b/media/bufferpool/1.0/vts/Android.bp
index ee5a757..691ed40 100644
--- a/media/bufferpool/1.0/vts/Android.bp
+++ b/media/bufferpool/1.0/vts/Android.bp
@@ -16,6 +16,7 @@
cc_test {
name: "VtsVndkHidlBufferpoolV1_0TargetSingleTest",
+ test_suites: ["device-tests"],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"allocator.cpp",
@@ -34,6 +35,7 @@
cc_test {
name: "VtsVndkHidlBufferpoolV1_0TargetMultiTest",
+ test_suites: ["device-tests"],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"allocator.cpp",
diff --git a/media/bufferpool/2.0/TEST_MAPPING b/media/bufferpool/2.0/TEST_MAPPING
new file mode 100644
index 0000000..65dee2c
--- /dev/null
+++ b/media/bufferpool/2.0/TEST_MAPPING
@@ -0,0 +1,7 @@
+// mappings for frameworks/av/media/bufferpool/2.0
+{
+ "presubmit": [
+ { "name": "VtsVndkHidlBufferpoolV2_0TargetSingleTest"},
+ { "name": "VtsVndkHidlBufferpoolV2_0TargetMultiTest"}
+ ]
+}
diff --git a/media/bufferpool/2.0/tests/Android.bp b/media/bufferpool/2.0/tests/Android.bp
index 8b44f61..8492939 100644
--- a/media/bufferpool/2.0/tests/Android.bp
+++ b/media/bufferpool/2.0/tests/Android.bp
@@ -16,6 +16,7 @@
cc_test {
name: "VtsVndkHidlBufferpoolV2_0TargetSingleTest",
+ test_suites: ["device-tests"],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"allocator.cpp",
@@ -34,6 +35,7 @@
cc_test {
name: "VtsVndkHidlBufferpoolV2_0TargetMultiTest",
+ test_suites: ["device-tests"],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"allocator.cpp",
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index 8afa1a8..fca3477 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -1,5 +1,10 @@
{
"presubmit": [
+ // TODO failing 4 of 13
+ // { "name": "codec2_core_param_test"},
+ // TODO(b/155516524)
+ // { "name": "codec2_vndk_interface_test"},
+ { "name": "codec2_vndk_test"},
{
"name": "CtsMediaTestCases",
"options": [
diff --git a/media/codec2/components/aac/Android.bp b/media/codec2/components/aac/Android.bp
index 9eca585..50495a9 100644
--- a/media/codec2/components/aac/Android.bp
+++ b/media/codec2/components/aac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_aacdec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_aacenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/amr_nb_wb/Android.bp b/media/codec2/components/amr_nb_wb/Android.bp
index ce25bc9..b09a505 100644
--- a/media/codec2/components/amr_nb_wb/Android.bp
+++ b/media/codec2/components/amr_nb_wb/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrnbdec",
defaults: [
"libcodec2_soft-defaults",
@@ -21,7 +21,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrwbdec",
defaults: [
"libcodec2_soft-defaults",
@@ -40,7 +40,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrnbenc",
defaults: [
"libcodec2_soft-defaults",
@@ -58,7 +58,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_amrwbenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
index 61dbd4c..fcc4552 100644
--- a/media/codec2/components/aom/Android.bp
+++ b/media/codec2/components/aom/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_av1dec_aom",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/avc/Android.bp b/media/codec2/components/avc/Android.bp
index 4021444..6b0e363 100644
--- a/media/codec2/components/avc/Android.bp
+++ b/media/codec2/components/avc/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_avcdec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_avcenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index ab93ce3..566895f 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -1328,13 +1328,13 @@
ps_inp_raw_buf->apv_bufs[1] = uPlane;
ps_inp_raw_buf->apv_bufs[2] = vPlane;
- ps_inp_raw_buf->au4_wd[0] = input->width();
- ps_inp_raw_buf->au4_wd[1] = input->width() / 2;
- ps_inp_raw_buf->au4_wd[2] = input->width() / 2;
+ ps_inp_raw_buf->au4_wd[0] = mSize->width;
+ ps_inp_raw_buf->au4_wd[1] = mSize->width / 2;
+ ps_inp_raw_buf->au4_wd[2] = mSize->width / 2;
- ps_inp_raw_buf->au4_ht[0] = input->height();
- ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
- ps_inp_raw_buf->au4_ht[2] = input->height() / 2;
+ ps_inp_raw_buf->au4_ht[0] = mSize->height;
+ ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
+ ps_inp_raw_buf->au4_ht[2] = mSize->height / 2;
ps_inp_raw_buf->au4_strd[0] = yStride;
ps_inp_raw_buf->au4_strd[1] = uStride;
@@ -1359,11 +1359,11 @@
ps_inp_raw_buf->apv_bufs[0] = yPlane;
ps_inp_raw_buf->apv_bufs[1] = uPlane;
- ps_inp_raw_buf->au4_wd[0] = input->width();
- ps_inp_raw_buf->au4_wd[1] = input->width();
+ ps_inp_raw_buf->au4_wd[0] = mSize->width;
+ ps_inp_raw_buf->au4_wd[1] = mSize->width;
- ps_inp_raw_buf->au4_ht[0] = input->height();
- ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
+ ps_inp_raw_buf->au4_ht[0] = mSize->height;
+ ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
ps_inp_raw_buf->au4_strd[0] = yStride;
ps_inp_raw_buf->au4_strd[1] = uStride;
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index f10835f..3712564 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -1,6 +1,6 @@
// DO NOT DEPEND ON THIS DIRECTLY
// use libcodec2_soft-defaults instead
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_common",
defaults: ["libcodec2-impl-defaults"],
vendor_available: true,
@@ -96,7 +96,7 @@
}
// TEMP: used by cheets2 project - remove when no longer used
-cc_library_shared {
+cc_library {
name: "libcodec2_simple_component",
vendor_available: true,
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index 48cc51b..3529fec 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_flacdec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_flacenc",
defaults: [
"libcodec2_soft-defaults",
@@ -23,11 +23,8 @@
srcs: ["C2SoftFlacEnc.cpp"],
- shared_libs: [
- "libaudioutils",
- ],
-
static_libs: [
"libFLAC",
+ "libaudioutils",
],
}
diff --git a/media/codec2/components/g711/Android.bp b/media/codec2/components/g711/Android.bp
index 3ede68c..22dd5ed 100644
--- a/media/codec2/components/g711/Android.bp
+++ b/media/codec2/components/g711/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_g711alawdec",
defaults: [
"libcodec2_soft-defaults",
@@ -12,7 +12,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_g711mlawdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/gav1/Android.bp b/media/codec2/components/gav1/Android.bp
index f374089..32aa98d 100644
--- a/media/codec2/components/gav1/Android.bp
+++ b/media/codec2/components/gav1/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_av1dec_gav1",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/gsm/Android.bp b/media/codec2/components/gsm/Android.bp
index 9330c01..7f54af8 100644
--- a/media/codec2/components/gsm/Android.bp
+++ b/media/codec2/components/gsm/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_gsmdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/hevc/Android.bp b/media/codec2/components/hevc/Android.bp
index 369bd78..2858212 100644
--- a/media/codec2/components/hevc/Android.bp
+++ b/media/codec2/components/hevc/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_hevcdec",
defaults: [
"libcodec2_soft-defaults",
@@ -11,7 +11,7 @@
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_hevcenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 23104dc..1766843 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -906,7 +906,6 @@
work->result = C2_CORRUPTED;
return;
}
- continue;
}
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
diff --git a/media/codec2/components/mp3/Android.bp b/media/codec2/components/mp3/Android.bp
index 66665ed..b4fb1b0 100644
--- a/media/codec2/components/mp3/Android.bp
+++ b/media/codec2/components/mp3/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mp3dec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg2/Android.bp b/media/codec2/components/mpeg2/Android.bp
index 841f0a9..666e697 100644
--- a/media/codec2/components/mpeg2/Android.bp
+++ b/media/codec2/components/mpeg2/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+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..7e79b78 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();
}
diff --git a/media/codec2/components/mpeg4_h263/Android.bp b/media/codec2/components/mpeg4_h263/Android.bp
index 41e4f44..0673709 100644
--- a/media/codec2/components/mpeg4_h263/Android.bp
+++ b/media/codec2/components/mpeg4_h263/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mpeg4dec",
defaults: [
"libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_h263dec",
defaults: [
"libcodec2_soft-defaults",
@@ -31,7 +31,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_mpeg4enc",
defaults: [
"libcodec2_soft-defaults",
@@ -49,7 +49,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 61b286c..5571e60 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();
}
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..32e2bf8 100644
--- a/media/codec2/components/opus/Android.bp
+++ b/media/codec2/components/opus/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_opusdec",
defaults: [
"libcodec2_soft-defaults",
@@ -9,7 +9,7 @@
shared_libs: ["libopus"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_opusenc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/raw/Android.bp b/media/codec2/components/raw/Android.bp
index dc944da..d4fb8f8 100644
--- a/media/codec2/components/raw/Android.bp
+++ b/media/codec2/components/raw/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_rawdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/tests/Android.bp b/media/codec2/components/tests/Android.bp
new file mode 100644
index 0000000..43bf3c6
--- /dev/null
+++ b/media/codec2/components/tests/Android.bp
@@ -0,0 +1,58 @@
+cc_defaults {
+ name: "C2SoftCodecTest-defaults",
+ gtest: true,
+ host_supported: false,
+ srcs: [
+ "C2SoftCodecTest.cpp",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libion",
+ "libfmq",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "libcodec2",
+ "libhidlbase",
+ "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..ff1183f 100644
--- a/media/codec2/components/vorbis/Android.bp
+++ b/media/codec2/components/vorbis/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vorbisdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/vpx/Android.bp b/media/codec2/components/vpx/Android.bp
index 34f5753..72178aa 100644
--- a/media/codec2/components/vpx/Android.bp
+++ b/media/codec2/components/vpx/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp9dec",
defaults: [
"libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp8dec",
defaults: [
"libcodec2_soft-defaults",
@@ -26,7 +26,7 @@
shared_libs: ["libvpx"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp9enc",
defaults: [
"libcodec2_soft-defaults",
@@ -43,7 +43,7 @@
cflags: ["-DVP9"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_vp8enc",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/components/xaac/Android.bp b/media/codec2/components/xaac/Android.bp
index 7795cc1..4889d78 100644
--- a/media/codec2/components/xaac/Android.bp
+++ b/media/codec2/components/xaac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libcodec2_soft_xaacdec",
defaults: [
"libcodec2_soft-defaults",
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index ce1c9ac..27043f8 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -5,7 +5,7 @@
export_include_dirs: ["include"],
}
-cc_library_shared {
+cc_library {
name: "libcodec2",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/codec2/sfplugin/TEST_MAPPING b/media/codec2/sfplugin/TEST_MAPPING
new file mode 100644
index 0000000..045e5b5
--- /dev/null
+++ b/media/codec2/sfplugin/TEST_MAPPING
@@ -0,0 +1,12 @@
+// mappings for frameworks/av/media/codec2/sfplugin
+{
+ "presubmit": [
+ // failing 1 of 11
+ // TODO(b/156167471)
+ // { "name": "ccodec_unit_test" },
+
+ // failing 4 of 17, around max-input-size defaults & overrides
+ // TODO(b/156167471)
+ //{ "name": "mc_sanity_test"}
+ ]
+}
diff --git a/media/codec2/sfplugin/tests/Android.bp b/media/codec2/sfplugin/tests/Android.bp
index 8d1a9c3..5c774a2 100644
--- a/media/codec2/sfplugin/tests/Android.bp
+++ b/media/codec2/sfplugin/tests/Android.bp
@@ -1,5 +1,6 @@
cc_test {
name: "ccodec_unit_test",
+ test_suites: ["device-tests"],
srcs: [
"CCodecBuffers_test.cpp",
@@ -43,6 +44,7 @@
cc_test {
name: "mc_sanity_test",
+ test_suites: ["device-tests"],
srcs: [
"MediaCodec_sanity_test.cpp",
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 6287221..e7dc92a 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libsfplugin_ccodec_utils",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/codec2/tests/Android.bp b/media/codec2/tests/Android.bp
index fce6e21..c9169a9 100644
--- a/media/codec2/tests/Android.bp
+++ b/media/codec2/tests/Android.bp
@@ -1,5 +1,6 @@
cc_test {
name: "codec2_core_param_test",
+ test_suites: ["device-tests"],
srcs: [
"C2Param_test.cpp",
@@ -28,6 +29,7 @@
cc_test {
name: "codec2_vndk_test",
+ test_suites: ["device-tests"],
srcs: [
"C2_test.cpp",
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 6f7acce..fd1c0ea 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -11,9 +11,9 @@
min_sdk_version: "29",
}
-// !!!DO NOT DEPEND ON THIS SHARED LIBRARY DIRECTLY!!!
+// !!!DO NOT DEPEND ON THIS LIBRARY DIRECTLY!!!
// use libcodec2-impl-defaults instead
-cc_library_shared {
+cc_library {
name: "libcodec2_vndk",
vendor_available: true,
min_sdk_version: "29",
diff --git a/media/extractors/TEST_MAPPING b/media/extractors/TEST_MAPPING
index abefb0f..cf3c30e 100644
--- a/media/extractors/TEST_MAPPING
+++ b/media/extractors/TEST_MAPPING
@@ -13,5 +13,7 @@
// }
// ]
// }
+ // TODO(b/148094059): unit tests not allowed to download content
+ //{ "name": "ExtractorUnitTest" }
]
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index a976a2b..c820ea0 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -2324,7 +2324,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta,
+ AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_ESDS, &buffer[4], chunk_data_size - 4);
if (mPath.size() >= 2
@@ -2406,7 +2406,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta,
+ AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_AVC, buffer.get(), chunk_data_size);
break;
@@ -2428,7 +2428,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta,
+ AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_HEVC, buffer.get(), chunk_data_size);
*offset += chunk_size;
@@ -3978,13 +3978,13 @@
// custom genre string
buffer[size] = '\0';
- AMediaFormat_setString(mFileMetaData,
+ AMediaFormat_setString(mFileMetaData,
metadataKey, (const char *)buffer + 8);
}
} else {
buffer[size] = '\0';
- AMediaFormat_setString(mFileMetaData,
+ AMediaFormat_setString(mFileMetaData,
metadataKey, (const char *)buffer + 8);
}
}
@@ -6104,9 +6104,13 @@
if (newBuffer) {
if (mIsPcm) {
// The twos' PCM block reader assumes that all samples has the same size.
-
- uint32_t samplesToRead = mSampleTable->getLastSampleIndexInChunk()
- - mCurrentSampleIndex + 1;
+ uint32_t lastSampleIndexInChunk = mSampleTable->getLastSampleIndexInChunk();
+ if (lastSampleIndexInChunk < mCurrentSampleIndex) {
+ mBuffer->release();
+ mBuffer = nullptr;
+ return AMEDIA_ERROR_UNKNOWN;
+ }
+ uint32_t samplesToRead = lastSampleIndexInChunk - mCurrentSampleIndex + 1;
if (samplesToRead > kMaxPcmFrameSize) {
samplesToRead = kMaxPcmFrameSize;
}
@@ -6115,13 +6119,17 @@
samplesToRead, size, mCurrentSampleIndex,
mSampleTable->getLastSampleIndexInChunk());
- size_t totalSize = samplesToRead * size;
+ size_t totalSize = samplesToRead * size;
+ if (mBuffer->size() < totalSize) {
+ mBuffer->release();
+ mBuffer = nullptr;
+ return AMEDIA_ERROR_UNKNOWN;
+ }
uint8_t* buf = (uint8_t *)mBuffer->data();
ssize_t bytesRead = mDataSource->readAt(offset, buf, totalSize);
if (bytesRead < (ssize_t)totalSize) {
mBuffer->release();
mBuffer = NULL;
-
return AMEDIA_ERROR_IO;
}
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 20bc23d..eaa2e63 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <android/IDataSource.h>
+#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <gui/IGraphicBufferProducer.h>
#include <media/AudioResamplerPublic.h>
@@ -82,10 +83,36 @@
};
// ModDrm helpers
-static void readVector(const Parcel& reply, Vector<uint8_t>& vector) {
- uint32_t size = reply.readUint32();
- vector.insertAt((size_t)0, size);
- reply.read(vector.editArray(), size);
+static status_t readVector(const Parcel& reply, Vector<uint8_t>& vector) {
+ uint32_t size = 0;
+ status_t status = reply.readUint32(&size);
+ if (status == OK) {
+ status = size <= reply.dataAvail() ? OK : BAD_VALUE;
+ }
+ if (status == OK) {
+ status = vector.insertAt((size_t) 0, size) >= 0 ? OK : NO_MEMORY;
+ }
+ if (status == OK) {
+ status = reply.read(vector.editArray(), size);
+ }
+ if (status != OK) {
+ char errorMsg[100];
+ char buganizerId[] = "173720767";
+ snprintf(errorMsg,
+ sizeof(errorMsg),
+ "%s: failed to read array. Size: %d, status: %d.",
+ __func__,
+ size,
+ status);
+ android_errorWriteWithInfoLog(
+ /* safetyNet tag= */ 0x534e4554,
+ buganizerId,
+ IPCThreadState::self()->getCallingUid(),
+ errorMsg,
+ strlen(errorMsg));
+ ALOGE("%s (b/%s)", errorMsg, buganizerId);
+ }
+ return status;
}
static void writeVector(Parcel& data, Vector<uint8_t> const& vector) {
@@ -961,8 +988,10 @@
uint8_t uuid[16];
data.read(uuid, sizeof(uuid));
Vector<uint8_t> drmSessionId;
- readVector(data, drmSessionId);
-
+ status_t status = readVector(data, drmSessionId);
+ if (status != OK) {
+ return status;
+ }
uint32_t result = prepareDrm(uuid, drmSessionId);
reply->writeInt32(result);
return OK;
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index e71ea2c..12a87d1 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -20,6 +20,8 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include <unistd.h>
+#include <algorithm>
#include <media/MidiIoWrapper.h>
#include <media/MediaExtractorPluginApi.h>
@@ -32,6 +34,8 @@
}
namespace android {
+int MidiIoWrapper::sCacheBufferSize = 0;
+Mutex MidiIoWrapper::mCacheLock;
MidiIoWrapper::MidiIoWrapper(const char *path) {
ALOGV("MidiIoWrapper(%s)", path);
@@ -39,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) {
@@ -47,6 +53,8 @@
mBase = offset;
mLength = size;
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
class MidiIoWrapper::DataSourceUnwrapper {
@@ -96,6 +104,8 @@
} else {
mLength = 0;
}
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::~MidiIoWrapper() {
@@ -104,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/TEST_MAPPING b/media/libmedia/TEST_MAPPING
new file mode 100644
index 0000000..65390ed
--- /dev/null
+++ b/media/libmedia/TEST_MAPPING
@@ -0,0 +1,6 @@
+// test_mapping for frameworks/av/media/libmedia
+{
+ "presubmit": [
+ { "name": "CodecListTest" }
+ ]
+}
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/tests/codeclist/Android.bp b/media/libmedia/tests/codeclist/Android.bp
new file mode 100644
index 0000000..a930d6e
--- /dev/null
+++ b/media/libmedia/tests/codeclist/Android.bp
@@ -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.
+ */
+
+cc_test {
+ name: "CodecListTest",
+ test_suites: ["device-tests"],
+ gtest: true,
+
+ srcs: [
+ "CodecListTest.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libmedia_codeclist",
+ "libstagefright",
+ "libstagefright_foundation",
+ "libstagefright_xmlparser",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ cfi: true,
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
diff --git a/media/libmedia/tests/codeclist/CodecListTest.cpp b/media/libmedia/tests/codeclist/CodecListTest.cpp
new file mode 100644
index 0000000..bd2adf7
--- /dev/null
+++ b/media/libmedia/tests/codeclist/CodecListTest.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "CodecListTest"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#define kSwCodecXmlPath "/apex/com.android.media.swcodec/etc/"
+
+using namespace android;
+
+struct CddReq {
+ CddReq(const char *type, bool encoder) {
+ mediaType = type;
+ isEncoder = encoder;
+ }
+
+ const char *mediaType;
+ bool isEncoder;
+};
+
+TEST(CodecListTest, CodecListSanityTest) {
+ sp<IMediaCodecList> list = MediaCodecList::getInstance();
+ ASSERT_NE(list, nullptr) << "Unable to get MediaCodecList instance.";
+ EXPECT_GT(list->countCodecs(), 0) << "No codecs in CodecList";
+ for (size_t i = 0; i < list->countCodecs(); ++i) {
+ sp<MediaCodecInfo> info = list->getCodecInfo(i);
+ ASSERT_NE(info, nullptr) << "CodecInfo is null";
+ ssize_t index = list->findCodecByName(info->getCodecName());
+ EXPECT_GE(index, 0) << "Wasn't able to find existing codec: " << info->getCodecName();
+ }
+}
+
+TEST(CodecListTest, CodecListByTypeTest) {
+ sp<IMediaCodecList> list = MediaCodecList::getInstance();
+ ASSERT_NE(list, nullptr) << "Unable to get MediaCodecList instance.";
+
+ std::vector<CddReq> cddReq{
+ // media type, isEncoder
+ CddReq(MIMETYPE_AUDIO_AAC, false),
+ CddReq(MIMETYPE_AUDIO_AAC, true),
+
+ CddReq(MIMETYPE_VIDEO_AVC, false),
+ CddReq(MIMETYPE_VIDEO_HEVC, false),
+ CddReq(MIMETYPE_VIDEO_MPEG4, false),
+ CddReq(MIMETYPE_VIDEO_VP8, false),
+ CddReq(MIMETYPE_VIDEO_VP9, false),
+
+ CddReq(MIMETYPE_VIDEO_AVC, true),
+ CddReq(MIMETYPE_VIDEO_VP8, true),
+ };
+
+ for (CddReq codecReq : cddReq) {
+ ssize_t index = list->findCodecByType(codecReq.mediaType, codecReq.isEncoder);
+ EXPECT_GE(index, 0) << "Wasn't able to find codec for media type: " << codecReq.mediaType
+ << (codecReq.isEncoder ? " encoder" : " decoder");
+ }
+}
+
+TEST(CodecInfoTest, ListInfoTest) {
+ ALOGV("Compare CodecInfo with info in XML");
+ MediaCodecsXmlParser parser;
+ status_t status = parser.parseXmlFilesInSearchDirs();
+ ASSERT_EQ(status, OK) << "XML Parsing failed for default paths";
+
+ const std::vector<std::string> &xmlFiles = MediaCodecsXmlParser::getDefaultXmlNames();
+ const std::vector<std::string> &searchDirsApex{std::string(kSwCodecXmlPath)};
+ status = parser.parseXmlFilesInSearchDirs(xmlFiles, searchDirsApex);
+ ASSERT_EQ(status, OK) << "XML Parsing of " << kSwCodecXmlPath << " failed";
+
+ MediaCodecsXmlParser::CodecMap codecMap = parser.getCodecMap();
+
+ sp<IMediaCodecList> list = MediaCodecList::getInstance();
+ ASSERT_NE(list, nullptr) << "Unable to get MediaCodecList instance";
+
+ // Compare CodecMap from XML to CodecList
+ for (auto mapIter : codecMap) {
+ ssize_t index = list->findCodecByName(mapIter.first.c_str());
+ if (index < 0) {
+ std::cout << "[ WARN ] " << mapIter.first << " not found in CodecList \n";
+ continue;
+ }
+
+ sp<MediaCodecInfo> info = list->getCodecInfo(index);
+ ASSERT_NE(info, nullptr) << "CodecInfo is null";
+
+ MediaCodecsXmlParser::CodecProperties codecProperties = mapIter.second;
+ ASSERT_EQ(codecProperties.isEncoder, info->isEncoder()) << "Encoder property mismatch";
+
+ ALOGV("codec name: %s", info->getCodecName());
+ ALOGV("codec rank: %d", info->getRank());
+ ALOGV("codec ownername: %s", info->getOwnerName());
+ ALOGV("codec isEncoder: %d", info->isEncoder());
+
+ ALOGV("attributeFlags: kFlagIsHardwareAccelerated, kFlagIsSoftwareOnly, kFlagIsVendor, "
+ "kFlagIsEncoder");
+ std::bitset<4> attr(info->getAttributes());
+ ALOGV("codec attributes: %s", attr.to_string().c_str());
+
+ Vector<AString> mediaTypes;
+ info->getSupportedMediaTypes(&mediaTypes);
+ ALOGV("supported media types count: %zu", mediaTypes.size());
+ ASSERT_FALSE(mediaTypes.isEmpty())
+ << "no media type supported by codec: " << info->getCodecName();
+
+ MediaCodecsXmlParser::TypeMap typeMap = codecProperties.typeMap;
+ for (auto mediaType : mediaTypes) {
+ ALOGV("codec mediaTypes: %s", mediaType.c_str());
+ auto searchTypeMap = typeMap.find(mediaType.c_str());
+ ASSERT_NE(searchTypeMap, typeMap.end())
+ << "CodecList doesn't contain codec media type: " << mediaType.c_str();
+ MediaCodecsXmlParser::AttributeMap attributeMap = searchTypeMap->second;
+
+ const sp<MediaCodecInfo::Capabilities> &capabilities =
+ info->getCapabilitiesFor(mediaType.c_str());
+
+ Vector<uint32_t> colorFormats;
+ capabilities->getSupportedColorFormats(&colorFormats);
+ for (auto colorFormat : colorFormats) {
+ ALOGV("supported color formats: %d", colorFormat);
+ }
+
+ Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+ capabilities->getSupportedProfileLevels(&profileLevels);
+ if (!profileLevels.empty()) {
+ ALOGV("supported profilelevel for media type: %s", mediaType.c_str());
+ }
+ for (auto profileLevel : profileLevels) {
+ ALOGV("profile: %d, level: %d", profileLevel.mProfile, profileLevel.mLevel);
+ }
+
+ sp<AMessage> details = capabilities->getDetails();
+ ASSERT_NE(details, nullptr) << "Details in codec capabilities is null";
+ ALOGV("no. of entries in details: %zu", details->countEntries());
+
+ for (size_t idxDetail = 0; idxDetail < details->countEntries(); idxDetail++) {
+ AMessage::Type type;
+ const char *name = details->getEntryNameAt(idxDetail, &type);
+ ALOGV("details entry name: %s", name);
+ AMessage::ItemData itemData = details->getEntryAt(idxDetail);
+ switch (type) {
+ case AMessage::kTypeInt32:
+ int32_t val32;
+ if (itemData.find(&val32)) {
+ ALOGV("entry int val: %d", val32);
+ auto searchAttr = attributeMap.find(name);
+ if (searchAttr == attributeMap.end()) {
+ ALOGW("Parser doesn't have key: %s", name);
+ } else if (stoi(searchAttr->second) != val32) {
+ ALOGW("Values didn't match for key: %s", name);
+ ALOGV("Values act/exp: %d / %d", val32, stoi(searchAttr->second));
+ }
+ }
+ break;
+ case AMessage::kTypeString:
+ if (AString valStr; itemData.find(&valStr)) {
+ ALOGV("entry str val: %s", valStr.c_str());
+ auto searchAttr = attributeMap.find(name);
+ if (searchAttr == attributeMap.end()) {
+ ALOGW("Parser doesn't have key: %s", name);
+ } else if (searchAttr->second != valStr.c_str()) {
+ ALOGW("Values didn't match for key: %s", name);
+ ALOGV("Values act/exp: %s / %s", valStr.c_str(),
+ searchAttr->second.c_str());
+ }
+ }
+ break;
+ default:
+ ALOGV("data type: %d shouldn't be present in details", type);
+ break;
+ }
+ }
+ }
+
+ Parcel *codecInfoParcel = new Parcel();
+ ASSERT_NE(codecInfoParcel, nullptr) << "Unable to create parcel";
+
+ status_t status = info->writeToParcel(codecInfoParcel);
+ ASSERT_EQ(status, OK) << "Writing to parcel failed";
+
+ codecInfoParcel->setDataPosition(0);
+ sp<MediaCodecInfo> parcelCodecInfo = info->FromParcel(*codecInfoParcel);
+ ASSERT_NE(parcelCodecInfo, nullptr) << "CodecInfo from parcel is null";
+ delete codecInfoParcel;
+
+ EXPECT_STREQ(info->getCodecName(), parcelCodecInfo->getCodecName())
+ << "Returned codec name in info doesn't match";
+ EXPECT_EQ(info->getRank(), parcelCodecInfo->getRank())
+ << "Returned component rank in info doesn't match";
+ }
+}
+
+TEST(CodecListTest, CodecListGlobalSettingsTest) {
+ sp<IMediaCodecList> list = MediaCodecList::getInstance();
+ ASSERT_NE(list, nullptr) << "Unable to get MediaCodecList instance";
+
+ sp<AMessage> globalSettings = list->getGlobalSettings();
+ ASSERT_NE(globalSettings, nullptr) << "GlobalSettings AMessage is null";
+ ALOGV("global settings: %s", globalSettings->debugString(0).c_str());
+}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 94c0b84..40d8ba2 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -19,6 +19,8 @@
#define LOG_TAG "MediaCodec"
#include <utils/Log.h>
+#include <set>
+
#include <inttypes.h>
#include <stdlib.h>
@@ -201,6 +203,10 @@
// implements DeathRecipient
static void BinderDiedCallback(void* cookie);
void binderDied();
+ static Mutex sLockCookies;
+ static std::set<void*> sCookies;
+ static void addCookie(void* cookie);
+ static void removeCookie(void* cookie);
void addResource(const MediaResourceParcel &resource);
void removeResource(const MediaResourceParcel &resource);
@@ -227,8 +233,15 @@
}
MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
+
+ // remove the cookie, so any in-flight death notification will get dropped
+ // by our handler.
+ removeCookie(this);
+
+ Mutex::Autolock _l(mLock);
if (mService != nullptr) {
AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+ mService = nullptr;
}
}
@@ -240,13 +253,36 @@
return;
}
+ // so our handler will process the death notifications
+ addCookie(this);
+
+ // after this, require mLock whenever using mService
AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
}
//static
+Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
+std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) {
+ Mutex::Autolock _l(sLockCookies);
+ sCookies.insert(cookie);
+}
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) {
+ Mutex::Autolock _l(sLockCookies);
+ sCookies.erase(cookie);
+}
+
+//static
void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
- auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
- thiz->binderDied();
+ Mutex::Autolock _l(sLockCookies);
+ if (sCookies.find(cookie) != sCookies.end()) {
+ auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
+ thiz->binderDied();
+ }
}
void MediaCodec::ResourceManagerServiceProxy::binderDied() {
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 8b36ea5..3dceef7 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -1,5 +1,12 @@
{
"presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ // { "name": "HEVCUtilsUnitTest" },
+ //{ "name": "ExtractorFactoryTest" },
+ // writerTest fails about 5 out of 66
+ // in addition to needing the download ability
+ //{ "name": "writerTest" },
+
{
"name": "CtsMediaTestCases",
"options": [
diff --git a/media/libstagefright/bqhelper/TEST_MAPPING b/media/libstagefright/bqhelper/TEST_MAPPING
new file mode 100644
index 0000000..c7f2fd8
--- /dev/null
+++ b/media/libstagefright/bqhelper/TEST_MAPPING
@@ -0,0 +1,6 @@
+// mappings for frameworks/av/media/libstagefright/bqhelper
+{
+ "presubmit": [
+ { "name": "FrameDropper_test"}
+ ]
+}
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
index 4e83059..7e2909a 100644
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
+++ b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
@@ -30,6 +30,8 @@
FrameDropper();
// maxFrameRate required to be positive.
+ // maxFrameRate negative causes shouldDrop() to always return false
+ // maxFrameRate == 0 is illegal
status_t setMaxFrameRate(float maxFrameRate);
// Returns false if max frame rate has not been set via setMaxFrameRate.
diff --git a/media/libstagefright/bqhelper/tests/Android.bp b/media/libstagefright/bqhelper/tests/Android.bp
index 2fbc3d6..759ff8c 100644
--- a/media/libstagefright/bqhelper/tests/Android.bp
+++ b/media/libstagefright/bqhelper/tests/Android.bp
@@ -1,15 +1,17 @@
cc_test {
name: "FrameDropper_test",
-
+ test_suites: [
+ "device-tests",
+ "mts",
+ ],
srcs: ["FrameDropper_test.cpp"],
-
shared_libs: [
"libstagefright_bufferqueue_helper",
"libutils",
],
-
cflags: [
"-Werror",
"-Wall",
],
+ compile_multilib: "first",
}
diff --git a/media/libstagefright/bqhelper/tests/FrameDropper_test.cpp b/media/libstagefright/bqhelper/tests/FrameDropper_test.cpp
index 55ae77c..b18067f 100644
--- a/media/libstagefright/bqhelper/tests/FrameDropper_test.cpp
+++ b/media/libstagefright/bqhelper/tests/FrameDropper_test.cpp
@@ -110,7 +110,7 @@
};
TEST_F(FrameDropperTest, TestInvalidMaxFrameRate) {
- EXPECT_NE(OK, mFrameDropper->setMaxFrameRate(-1.0));
+ EXPECT_EQ(OK, mFrameDropper->setMaxFrameRate(-1.0));
EXPECT_NE(OK, mFrameDropper->setMaxFrameRate(0));
}
diff --git a/media/libstagefright/codecs/amrnb/TEST_MAPPING b/media/libstagefright/codecs/amrnb/TEST_MAPPING
new file mode 100644
index 0000000..2909099
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/TEST_MAPPING
@@ -0,0 +1,11 @@
+// mappings for frameworks/av/media/libstagefright/codecs/amrnb
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ // { "name": "AmrnbDecoderTest"},
+
+ // TODO(b/148094059): unit tests not allowed to download content
+ // { "name": "AmrnbEncoderTest"}
+
+ ]
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/test/Android.bp b/media/libstagefright/codecs/amrnb/dec/test/Android.bp
index 7a95cfa..91c9f86 100644
--- a/media/libstagefright/codecs/amrnb/dec/test/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/test/Android.bp
@@ -17,6 +17,7 @@
cc_test {
name: "AmrnbDecoderTest",
gtest: true,
+ test_suites: ["device-tests"],
srcs: [
"AmrnbDecoderTest.cpp",
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
index 5a846fa..584f79b 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
@@ -570,12 +570,14 @@
Word16 corr[], /* i : normalized correlation */
Word16 flag3, /* i : subsample resolution
(3: =1 / 6: =0) */
- Flag *pOverflow
+ Flag *pOverflow,
+ enum Mode mode
)
{
Word16 i;
Word16 max;
Word16 corr_int;
+ Word16 minPitch;
/* Test the fractions around T0 and choose the one which maximizes */
/* the interpolated normalized correlation. */
@@ -593,14 +595,22 @@
}
}
+ minPitch = (mode == MR122) ? PIT_MIN_MR122 : PIT_MIN;
if (flag3 == 0)
{
/* Limit the fraction value in the interval [-2,-1,0,1,2,3] */
if (*frac == -3)
{
- *frac = 3;
- (*lag)--;
+ if (*lag > minPitch)
+ {
+ *frac = 3;
+ (*lag)--;
+ }
+ else
+ {
+ *frac = -2;
+ }
}
}
else
@@ -609,13 +619,27 @@
if (*frac == -2)
{
- *frac = 1;
- (*lag)--;
+ if (*lag > minPitch)
+ {
+ *frac = 1;
+ (*lag)--;
+ }
+ else
+ {
+ *frac = -1;
+ }
}
- if (*frac == 2)
+ else if (*frac == 2)
{
- *frac = -1;
- (*lag)++;
+ if (*lag < PIT_MAX)
+ {
+ *frac = -1;
+ (*lag)++;
+ }
+ else
+ {
+ *frac = 1;
+ }
}
}
}
@@ -1533,20 +1557,20 @@
/* normal search in fractions around T0 */
- searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
}
else if (lag == (tmp_lag - 2))
{
/* limit search around T0 to the right side */
frac = 0;
- searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
}
else if (lag == (tmp_lag + 1))
{
/* limit search around T0 to the left side */
last_frac = 0;
- searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
}
else
{
@@ -1556,7 +1580,7 @@
}
else
/* test the fractions around T0 */
- searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
}
/*-----------------------------------------------------------------------*
diff --git a/media/libstagefright/codecs/amrnb/enc/test/Android.bp b/media/libstagefright/codecs/amrnb/enc/test/Android.bp
index e8982fe..7e1b561 100644
--- a/media/libstagefright/codecs/amrnb/enc/test/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/test/Android.bp
@@ -17,6 +17,7 @@
cc_test {
name: "AmrnbEncoderTest",
gtest: true,
+ test_suites: ["device-tests"],
srcs: [
"AmrnbEncoderTest.cpp",
diff --git a/media/libstagefright/codecs/amrwb/TEST_MAPPING b/media/libstagefright/codecs/amrwb/TEST_MAPPING
new file mode 100644
index 0000000..3d58ba2
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/TEST_MAPPING
@@ -0,0 +1,8 @@
+// mappings for frameworks/av/media/libstagefright/codecs/amrwb
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ // { "name": "AmrwbDecoderTest"}
+
+ ]
+}
diff --git a/media/libstagefright/codecs/amrwbenc/TEST_MAPPING b/media/libstagefright/codecs/amrwbenc/TEST_MAPPING
new file mode 100644
index 0000000..d53d665
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/TEST_MAPPING
@@ -0,0 +1,8 @@
+// mappings for frameworks/av/media/libstagefright/codecs/amrwbenc
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ // { "name": "AmrwbEncoderTest"}
+
+ ]
+}
diff --git a/media/libstagefright/codecs/m4v_h263/TEST_MAPPING b/media/libstagefright/codecs/m4v_h263/TEST_MAPPING
new file mode 100644
index 0000000..6b42847
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/TEST_MAPPING
@@ -0,0 +1,16 @@
+// mappings for frameworks/av/media/libstagefright/codecs/m4v_h263
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+
+ // 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/libstagefright/codecs/m4v_h263/dec/test/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
index 655491a..9c753e6 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
@@ -17,6 +17,7 @@
cc_test {
name: "Mpeg4H263DecoderTest",
gtest: true,
+ test_suites: ["device-tests"],
srcs: [
"Mpeg4H263DecoderTest.cpp",
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
index 997b78d..9deb023 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
@@ -1576,7 +1576,7 @@
/* find the last refresh MB */
indx = 0;
- while (intraArray[indx] == 1 && indx < totalMB)
+ while (indx < totalMB && intraArray[indx] == 1)
indx++;
/* add more */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 7ab8f45..30e4fda 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -491,6 +491,9 @@
}
for (i = 0; i < encParams->nLayers; i++)
{
+ if (encOption->encHeight[i] == 0 || encOption->encWidth[i] == 0 ||
+ encOption->encHeight[i] % 16 != 0 || encOption->encWidth[i] % 16 != 0)
+ goto CLEAN_UP;
encParams->LayerHeight[i] = encOption->encHeight[i];
encParams->LayerWidth[i] = encOption->encWidth[i];
}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
index b9a8117..d2982da 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
@@ -17,6 +17,7 @@
cc_test {
name: "Mpeg4H263EncoderTest",
gtest: true,
+ test_suites: ["device-tests"],
srcs : [ "Mpeg4H263EncoderTest.cpp" ],
diff --git a/media/libstagefright/codecs/mp3dec/TEST_MAPPING b/media/libstagefright/codecs/mp3dec/TEST_MAPPING
new file mode 100644
index 0000000..b237d65
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/TEST_MAPPING
@@ -0,0 +1,7 @@
+// mappings for frameworks/av/media/libstagefright/codecs/mp3dec
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ // { "name": "Mp3DecoderTest"}
+ ]
+}
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
index a5c7f5e..5cf1ed3 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -219,6 +219,11 @@
if (info->error_protection)
{
+ if (!bitsAvailable(&pVars->inputStream, 16))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
/*
* Get crc content
*/
@@ -593,18 +598,10 @@
}
else
{
- int32 tmp1 = *(ptr++);
- for (int32 nBytes = temp >> 1; nBytes != 0; nBytes--) /* read main data. */
+ for (int32 nBytes = temp; nBytes != 0; nBytes--) /* read main data. */
{
- int32 tmp2 = *(ptr++);
- fillDataBuf(&pVars->mainDataStream, tmp1);
- fillDataBuf(&pVars->mainDataStream, tmp2);
- tmp1 = *(ptr++);
- }
-
- if (temp&1)
- {
- fillDataBuf(&pVars->mainDataStream, tmp1);
+ int32 tmp = *(ptr++);
+ fillDataBuf(&pVars->mainDataStream, tmp);
}
/* adjust circular buffer counter */
@@ -613,14 +610,9 @@
}
else
{
- for (int32 nBytes = temp >> 1; nBytes != 0; nBytes--) /* read main data. */
+ for (int32 nBytes = temp; nBytes != 0; nBytes--) /* read main data. */
{
fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++ , BUFSIZE)));
- fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++ , BUFSIZE)));
- }
- if (temp&1)
- {
- fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset , BUFSIZE)));
}
}
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
index d644207..1a3fca5 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -73,6 +73,7 @@
#include "pvmp3_get_side_info.h"
#include "pvmp3_crc.h"
+#include "pvmp3_getbits.h"
/*----------------------------------------------------------------------------
@@ -125,12 +126,22 @@
{
if (stereo == 1)
{
+ if (!bitsAvailable(inputStream, 14))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 14, crc, info->error_protection);
si->main_data_begin = (tmp << 18) >> 23; /* 9 */
si->private_bits = (tmp << 27) >> 27; /* 5 */
}
else
{
+ if (!bitsAvailable(inputStream, 12))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 12, crc, info->error_protection);
si->main_data_begin = (tmp << 20) >> 23; /* 9 */
si->private_bits = (tmp << 29) >> 29; /* 3 */
@@ -139,6 +150,11 @@
for (ch = 0; ch < stereo; ch++)
{
+ if (!bitsAvailable(inputStream, 4))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 4, crc, info->error_protection);
si->ch[ch].scfsi[0] = (tmp << 28) >> 31; /* 1 */
si->ch[ch].scfsi[1] = (tmp << 29) >> 31; /* 1 */
@@ -150,6 +166,11 @@
{
for (ch = 0; ch < stereo; ch++)
{
+ if (!bitsAvailable(inputStream, 34))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
si->ch[ch].gran[gr].part2_3_length = getbits_crc(inputStream, 12, crc, info->error_protection);
tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
@@ -160,6 +181,11 @@
if (si->ch[ch].gran[gr].window_switching_flag)
{
+ if (!bitsAvailable(inputStream, 22))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
si->ch[ch].gran[gr].block_type = (tmp << 10) >> 30; /* 2 */;
@@ -192,6 +218,11 @@
}
else
{
+ if (!bitsAvailable(inputStream, 22))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
si->ch[ch].gran[gr].table_select[0] = (tmp << 10) >> 27; /* 5 */;
@@ -204,6 +235,11 @@
si->ch[ch].gran[gr].block_type = 0;
}
+ if (!bitsAvailable(inputStream, 3))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 3, crc, info->error_protection);
si->ch[ch].gran[gr].preflag = (tmp << 29) >> 31; /* 1 */
si->ch[ch].gran[gr].scalefac_scale = (tmp << 30) >> 31; /* 1 */
@@ -213,11 +249,21 @@
}
else /* Layer 3 LSF */
{
+ if (!bitsAvailable(inputStream, 8 + stereo))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
si->main_data_begin = getbits_crc(inputStream, 8, crc, info->error_protection);
si->private_bits = getbits_crc(inputStream, stereo, crc, info->error_protection);
for (ch = 0; ch < stereo; ch++)
{
+ if (!bitsAvailable(inputStream, 39))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 21, crc, info->error_protection);
si->ch[ch].gran[0].part2_3_length = (tmp << 11) >> 20; /* 12 */
si->ch[ch].gran[0].big_values = (tmp << 23) >> 23; /* 9 */
@@ -230,6 +276,11 @@
if (si->ch[ch].gran[0].window_switching_flag)
{
+ if (!bitsAvailable(inputStream, 22))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
si->ch[ch].gran[0].block_type = (tmp << 10) >> 30; /* 2 */;
@@ -262,6 +313,11 @@
}
else
{
+ if (!bitsAvailable(inputStream, 22))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
si->ch[ch].gran[0].table_select[0] = (tmp << 10) >> 27; /* 5 */;
@@ -274,6 +330,11 @@
si->ch[ch].gran[0].block_type = 0;
}
+ if (!bitsAvailable(inputStream, 2))
+ {
+ return SIDE_INFO_ERROR;
+ }
+
tmp = getbits_crc(inputStream, 2, crc, info->error_protection);
si->ch[ch].gran[0].scalefac_scale = tmp >> 1; /* 1 */
si->ch[ch].gran[0].count1table_select = tmp & 1; /* 1 */
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
index 8ff7953..4d252ef 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
@@ -113,10 +113,11 @@
uint32 offset;
uint32 bitIndex;
- uint8 Elem; /* Needs to be same type as pInput->pBuffer */
- uint8 Elem1;
- uint8 Elem2;
- uint8 Elem3;
+ uint32 bytesToFetch;
+ uint8 Elem = 0; /* Needs to be same type as pInput->pBuffer */
+ uint8 Elem1 = 0;
+ uint8 Elem2 = 0;
+ uint8 Elem3 = 0;
uint32 returnValue = 0;
if (!neededBits)
@@ -126,10 +127,25 @@
offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
- Elem = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
- Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
- Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
- Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+ bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
+
+ switch (bytesToFetch)
+ {
+ case 4:
+ Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
+ [[fallthrough]];
+ case 3:
+ Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+ [[fallthrough]];
+ case 2:
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ [[fallthrough]];
+ case 1:
+ Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+ }
returnValue = (((uint32)(Elem)) << 24) |
@@ -137,9 +153,6 @@
(((uint32)(Elem2)) << 8) |
((uint32)(Elem3));
- /* Remove extra high bits by shifting up */
- bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
/* This line is faster than to mask off the high bits. */
returnValue <<= bitIndex;
@@ -161,22 +174,32 @@
uint32 offset;
uint32 bitIndex;
- uint8 Elem; /* Needs to be same type as pInput->pBuffer */
- uint8 Elem1;
+ uint32 bytesToFetch;
+ uint8 Elem = 0; /* Needs to be same type as pInput->pBuffer */
+ uint8 Elem1 = 0;
uint16 returnValue;
offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
- Elem = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
- Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+ bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
+
+ if (bytesToFetch > 1)
+ {
+ Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ }
+ else if (bytesToFetch > 0)
+ {
+ Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+ }
returnValue = (((uint16)(Elem)) << 8) |
((uint16)(Elem1));
- /* Remove extra high bits by shifting up */
- bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
ptBitStream->usedBits += neededBits;
/* This line is faster than to mask off the high bits. */
returnValue = (returnValue << (bitIndex));
@@ -197,25 +220,40 @@
uint32 offset;
uint32 bitIndex;
- uint8 Elem; /* Needs to be same type as pInput->pBuffer */
- uint8 Elem1;
- uint8 Elem2;
+ uint32 bytesToFetch;
+ uint8 Elem = 0; /* Needs to be same type as pInput->pBuffer */
+ uint8 Elem1 = 0;
+ uint8 Elem2 = 0;
uint32 returnValue;
offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
- Elem = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
- Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
- Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+ bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
+
+ if (bytesToFetch > 2)
+ {
+ Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+ }
+ else if (bytesToFetch > 1)
+ {
+ Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ }
+ else if (bytesToFetch > 0)
+ {
+ Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+ }
returnValue = (((uint32)(Elem)) << 16) |
(((uint32)(Elem1)) << 8) |
((uint32)(Elem2));
- /* Remove extra high bits by shifting up */
- bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
ptBitStream->usedBits += neededBits;
/* This line is faster than to mask off the high bits. */
returnValue = 0xFFFFFF & (returnValue << (bitIndex));
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
index b058b00..b04fe6d 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
@@ -104,6 +104,11 @@
; Function Prototype declaration
----------------------------------------------------------------------------*/
+static inline bool bitsAvailable(tmp3Bits *inputStream, uint32 neededBits)
+{
+ return (inputStream->inputBufferCurrentLength << 3) >= (neededBits + inputStream->usedBits);
+}
+
/*----------------------------------------------------------------------------
; END
----------------------------------------------------------------------------*/
diff --git a/media/libstagefright/codecs/mp3dec/test/Android.bp b/media/libstagefright/codecs/mp3dec/test/Android.bp
index 0ff8b12..6b92ae9 100644
--- a/media/libstagefright/codecs/mp3dec/test/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/test/Android.bp
@@ -17,6 +17,7 @@
cc_test {
name: "Mp3DecoderTest",
gtest: true,
+ test_suites: ["device-tests"],
srcs: [
"mp3reader.cpp",
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 32b2075..55807d7 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -20,12 +20,12 @@
},
shared_libs: [
- "libaudioutils",
"liblog",
],
static_libs: [
"libFLAC",
+ "libaudioutils", // needed for 'float_from_i32'
],
export_static_lib_headers: [
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
index c8965d9..c79384c 100644
--- a/media/libstagefright/foundation/ABuffer.cpp
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -67,7 +67,7 @@
void ABuffer::setRange(size_t offset, size_t size) {
CHECK_LE(offset, mCapacity);
- CHECK_LE(offset + size, mCapacity);
+ CHECK_LE(size, mCapacity - offset);
mRangeOffset = offset;
mRangeLength = size;
diff --git a/media/libstagefright/foundation/TEST_MAPPING b/media/libstagefright/foundation/TEST_MAPPING
index 3301c4b..80ad9fb 100644
--- a/media/libstagefright/foundation/TEST_MAPPING
+++ b/media/libstagefright/foundation/TEST_MAPPING
@@ -1,5 +1,9 @@
{
"presubmit": [
- { "name": "sf_foundation_test" }
+ // TODO(b/148094059): unit tests not allowed to download content
+ //{ "name": "OpusHeaderTest" },
+
+ { "name": "sf_foundation_test" },
+ { "name": "MetaDataBaseUnitTest"}
]
}
diff --git a/media/libstagefright/id3/TEST_MAPPING b/media/libstagefright/id3/TEST_MAPPING
new file mode 100644
index 0000000..e4454c1
--- /dev/null
+++ b/media/libstagefright/id3/TEST_MAPPING
@@ -0,0 +1,20 @@
+// frameworks/av/media/libstagefright/id3
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ //{ "name": "ID3Test" },
+
+ // this doesn't seem to run any tests.
+ // but: cts-tradefed run -m CtsMediaTestCases -t android.media.cts.MediaMetadataRetrieverTest
+ // does run he 32 and 64 bit tests, but not the instant tests
+ // but all I know is that with 'atest', it's not running
+ {
+ "name": "CtsMediaTestCases",
+ "options": [
+ {
+ "include-filter": "android.media.cts.MediaMetadataRetrieverTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 62e3a4b..27a94fd 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -60,21 +60,23 @@
mIsAudio = false;
mIsVideo = false;
+ const char *mime;
- if (meta == NULL) {
+ // Do not use meta if no mime.
+ if (meta == NULL || !meta->findCString(kKeyMIMEType, &mime)) {
return;
}
mFormat = meta;
- const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
if (!strncasecmp("audio/", mime, 6)) {
mIsAudio = true;
- } else if (!strncasecmp("video/", mime, 6)) {
+ } else if (!strncasecmp("video/", mime, 6)) {
mIsVideo = true;
+ } else if (!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12)) {
+ return;
} else {
- CHECK(!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12));
+ ALOGW("Unsupported mime type: %s", mime);
}
}
diff --git a/media/libstagefright/mpeg2ts/TEST_MAPPING b/media/libstagefright/mpeg2ts/TEST_MAPPING
new file mode 100644
index 0000000..b25d732
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/TEST_MAPPING
@@ -0,0 +1,7 @@
+// frameworks/av/media/libstagefright/mpeg2ts
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ //{ "name": "Mpeg2tsUnitTest" }
+ ]
+}
diff --git a/media/libstagefright/mpeg2ts/test/Android.bp b/media/libstagefright/mpeg2ts/test/Android.bp
new file mode 100644
index 0000000..bacf23b
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/test/Android.bp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+cc_test {
+ name: "Mpeg2tsUnitTest",
+ gtest: true,
+ test_suites: ["device-tests"],
+
+ srcs: [
+ "Mpeg2tsUnitTest.cpp",
+ ],
+
+ shared_libs: [
+ "android.hardware.cas@1.0",
+ "android.hardware.cas.native@1.0",
+ "android.hidl.token@1.0-utils",
+ "android.hidl.allocator@1.0",
+ "libcrypto",
+ "libhidlbase",
+ "libhidlmemory",
+ "liblog",
+ "libmedia",
+ "libbinder",
+ "libbinder_ndk",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libdatasource",
+ "libstagefright",
+ "libstagefright_foundation",
+ "libstagefright_metadatautils",
+ "libstagefright_mpeg2support",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/extractors/",
+ "frameworks/av/media/libstagefright/",
+ ],
+
+ header_libs: [
+ "libmedia_headers",
+ "libaudioclient_headers",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ sanitize: {
+ cfi: true,
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
diff --git a/media/libstagefright/mpeg2ts/test/AndroidTest.xml b/media/libstagefright/mpeg2ts/test/AndroidTest.xml
new file mode 100644
index 0000000..ac1294d
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<configuration description="Test module config for Mpeg2ts unit tests">
+ <option name="test-suite-tag" value="Mpeg2tsUnitTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="Mpeg2tsUnitTest->/data/local/tmp/Mpeg2tsUnitTest" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true"
+ value="/data/local/tmp/Mpeg2tsUnitTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="Mpeg2tsUnitTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/Mpeg2tsUnitTestRes/" />
+ </test>
+</configuration>
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp b/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
new file mode 100644
index 0000000..79c233b
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
@@ -0,0 +1,236 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "Mpeg2tsUnitTest"
+
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/stat.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaDataBase.h>
+#include <media/stagefright/foundation/AUtils.h>
+
+#include "mpeg2ts/ATSParser.h"
+#include "mpeg2ts/AnotherPacketSource.h"
+
+#include "Mpeg2tsUnitTestEnvironment.h"
+
+constexpr size_t kTSPacketSize = 188;
+constexpr uint16_t kPIDMask = 0x1FFF;
+// Max value of PID which is also used for Null packets
+constexpr uint16_t kPIDMaxValue = 8191;
+constexpr uint8_t kTSSyncByte = 0x47;
+constexpr uint8_t kVideoPresent = 0x01;
+constexpr uint8_t kAudioPresent = 0x02;
+constexpr uint8_t kMetaDataPresent = 0x04;
+
+static Mpeg2tsUnitTestEnvironment *gEnv = nullptr;
+
+using namespace android;
+
+class Mpeg2tsUnitTest
+ : public ::testing ::TestWithParam<
+ tuple</*fileName*/ string, /*sourceType*/ char, /*numSource*/ uint16_t>> {
+ public:
+ Mpeg2tsUnitTest()
+ : mInputBuffer(nullptr), mSource(nullptr), mFpInput(nullptr), mParser(nullptr) {}
+
+ ~Mpeg2tsUnitTest() {
+ if (mInputBuffer) free(mInputBuffer);
+ if (mFpInput) fclose(mFpInput);
+ mSource.clear();
+ }
+
+ void SetUp() override {
+ mOffset = 0;
+ mNumDataSource = 0;
+ tuple<string, char, uint16_t> params = GetParam();
+ char sourceType = get<1>(params);
+ /* mSourceType = 0b x x x x x M A V
+ / | \
+ metaData audio video */
+ mMediaType = (sourceType & 0x07);
+ mNumDataSource = get<2>(params);
+ string inputFile = gEnv->getRes() + get<0>(params);
+ mFpInput = fopen(inputFile.c_str(), "rb");
+ ASSERT_NE(mFpInput, nullptr) << "Failed to open file: " << inputFile;
+
+ struct stat buf;
+ int8_t err = stat(inputFile.c_str(), &buf);
+ ASSERT_EQ(err, 0) << "Failed to get information for file: " << inputFile;
+
+ long fileSize = buf.st_size;
+ mTotalPackets = fileSize / kTSPacketSize;
+ int32_t fd = fileno(mFpInput);
+ ASSERT_GE(fd, 0) << "Failed to get the integer file descriptor";
+
+ mSource = new FileSource(dup(fd), 0, buf.st_size);
+ ASSERT_NE(mSource, nullptr) << "Failed to get the data source!";
+
+ mParser = new ATSParser();
+ ASSERT_NE(mParser, nullptr) << "Unable to create ATS parser!";
+ mInputBuffer = (uint8_t *)malloc(kTSPacketSize);
+ ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate memory for TS packet!";
+ }
+
+ uint64_t mOffset;
+ uint64_t mTotalPackets;
+ uint16_t mNumDataSource;
+
+ int8_t mMediaType;
+
+ uint8_t *mInputBuffer;
+ string mInputFile;
+ sp<DataSource> mSource;
+ FILE *mFpInput;
+ ATSParser *mParser;
+};
+
+TEST_P(Mpeg2tsUnitTest, MediaInfoTest) {
+ bool videoFound = false;
+ bool audioFound = false;
+ bool metaDataFound = false;
+ bool syncPointPresent = false;
+
+ int16_t totalDataSource = 0;
+ int32_t val32 = 0;
+ uint8_t numDataSource = 0;
+ uint8_t packet[kTSPacketSize];
+ ssize_t numBytesRead = -1;
+
+ ATSParser::SyncEvent event(mOffset);
+ static const ATSParser::SourceType mediaType[] = {ATSParser::VIDEO, ATSParser::AUDIO,
+ ATSParser::META, ATSParser::NUM_SOURCE_TYPES};
+ const uint32_t nMediaTypes = sizeof(mediaType) / sizeof(mediaType[0]);
+
+ while ((numBytesRead = mSource->readAt(mOffset, packet, kTSPacketSize)) == kTSPacketSize) {
+ ASSERT_TRUE(packet[0] == kTSSyncByte) << "Sync byte error!";
+
+ // pid is 13 bits
+ uint16_t pid = (packet[1] + (packet[2] << 8)) & kPIDMask;
+ ASSERT_TRUE(pid <= kPIDMaxValue) << "Invalid PID: " << pid;
+
+ status_t err = mParser->feedTSPacket(packet, kTSPacketSize, &event);
+ ASSERT_EQ(err, (status_t)OK) << "Unable to feed TS packet!";
+
+ mOffset += numBytesRead;
+ for (int i = 0; i < nMediaTypes; i++) {
+ if (mParser->hasSource(mediaType[i])) {
+ switch (mediaType[i]) {
+ case ATSParser::VIDEO:
+ videoFound = true;
+ break;
+ case ATSParser::AUDIO:
+ audioFound = true;
+ break;
+ case ATSParser::META:
+ metaDataFound = true;
+ break;
+ case ATSParser::NUM_SOURCE_TYPES:
+ numDataSource = 3;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if (videoFound && audioFound && metaDataFound && (numDataSource == 3)) break;
+ }
+
+ for (int i = 0; i < nMediaTypes; i++) {
+ ATSParser::SourceType currentMediaType = mediaType[i];
+ if (mParser->hasSource(currentMediaType)) {
+ if (event.hasReturnedData()) {
+ syncPointPresent = true;
+ sp<AnotherPacketSource> syncPacketSource = event.getMediaSource();
+ ASSERT_NE(syncPacketSource, nullptr)
+ << "Cannot get sync source for media type: " << currentMediaType;
+
+ status_t err = syncPacketSource->start();
+ ASSERT_EQ(err, (status_t)OK) << "Error returned while starting!";
+
+ sp<MetaData> format = syncPacketSource->getFormat();
+ ASSERT_NE(format, nullptr) << "Unable to get the format of the source packet!";
+
+ MediaBufferBase *buf;
+ syncPacketSource->read(&buf, nullptr);
+ ASSERT_NE(buf, nullptr) << "Failed to read sync packet source data";
+
+ MetaDataBase &inMeta = buf->meta_data();
+ bool status = inMeta.findInt32(kKeyIsSyncFrame, &val32);
+ ASSERT_EQ(status, true) << "Sync frame key is not set";
+
+ status = inMeta.findInt32(kKeyCryptoMode, &val32);
+ ASSERT_EQ(status, false) << "Invalid packet, found scrambled packets!";
+
+ err = syncPacketSource->stop();
+ ASSERT_EQ(err, (status_t)OK) << "Error returned while stopping!";
+ }
+ sp<AnotherPacketSource> packetSource = mParser->getSource(currentMediaType);
+ ASSERT_NE(packetSource, nullptr)
+ << "Cannot get source for media type: " << currentMediaType;
+
+ status_t err = packetSource->start();
+ ASSERT_EQ(err, (status_t)OK) << "Error returned while starting!";
+ sp<MetaData> format = packetSource->getFormat();
+ ASSERT_NE(format, nullptr) << "Unable to get the format of the packet!";
+
+ err = packetSource->stop();
+ ASSERT_EQ(err, (status_t)OK) << "Error returned while stopping!";
+ }
+ }
+
+ ASSERT_EQ(videoFound, bool(mMediaType & kVideoPresent)) << "No Video packets found!";
+ ASSERT_EQ(audioFound, bool(mMediaType & kAudioPresent)) << "No Audio packets found!";
+ ASSERT_EQ(metaDataFound, bool(mMediaType & kMetaDataPresent)) << "No meta data found!";
+
+ if (videoFound || audioFound) {
+ ASSERT_TRUE(syncPointPresent) << "No sync points found for audio/video";
+ }
+
+ if (videoFound) totalDataSource += 1;
+ if (audioFound) totalDataSource += 1;
+ if (metaDataFound) totalDataSource += 1;
+
+ ASSERT_TRUE(totalDataSource == mNumDataSource)
+ << "Expected " << mNumDataSource << " data sources, found " << totalDataSource;
+ if (numDataSource == 3) {
+ ASSERT_EQ(numDataSource, mNumDataSource)
+ << "Expected " << mNumDataSource << " data sources, found " << totalDataSource;
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ infoTest, Mpeg2tsUnitTest,
+ ::testing::Values(make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", 0x01, 1),
+ make_tuple("segment000001.ts", 0x03, 2),
+ make_tuple("bbb_44100hz_2ch_128kbps_mp3_5mins.ts", 0x02, 1)));
+
+int32_t main(int argc, char **argv) {
+ gEnv = new Mpeg2tsUnitTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ uint8_t status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("Mpeg2tsUnit Test Result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h b/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
new file mode 100644
index 0000000..9e41db7
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * 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 __MPEG2TS_UNIT_TEST_ENVIRONMENT_H__
+#define __MPEG2TS_UNIT_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mpeg2tsUnitTestEnvironment : public::testing::Environment {
+ public:
+ Mpeg2tsUnitTestEnvironment() : res("/data/local/tmp/") {}
+
+ // Parses the command line arguments
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int Mpeg2tsUnitTestEnvironment::initFromOptions(int argc, char **argv) {
+ static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+ while (true) {
+ int index = 0;
+ int c = getopt_long(argc, argv, "P:", options, &index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'P': {
+ setRes(optarg);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "unrecognized option: %s\n\n"
+ "usage: %s <gtest options> <test options>\n\n"
+ "test options are:\n\n"
+ "-P, --path: Resource files directory location\n",
+ argv[optind ?: 1], argv[0]);
+ return 2;
+ }
+ return 0;
+}
+
+#endif // __MPEG2TS_UNIT_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/mpeg2ts/test/README.md b/media/libstagefright/mpeg2ts/test/README.md
new file mode 100644
index 0000000..237ce72
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/test/README.md
@@ -0,0 +1,38 @@
+## Media Testing ##
+---
+#### Mpeg2TS Unit Test :
+The Mpeg2TS Unit Test Suite validates the functionality of the libraries present in Mpeg2TS.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/mpeg2ts/test/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/Mpeg2tsUnitTest/Mpeg2tsUnitTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/Mpeg2tsUnitTest/Mpeg2tsUnitTest /data/local/tmp/
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip ).
+Download, unzip and push these files into device for testing.
+
+```
+adb push Mpeg2tsUnitTestRes/. /data/local/tmp/
+```
+
+usage: Mpeg2tsUnitTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mpeg2tsUnitTest -P /data/local/tmp/Mpeg2tsUnitTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg2tsUnitTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index e3e61d7..26ec507 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -17,6 +17,7 @@
cc_test {
name: "ExtractorFactoryTest",
gtest: true,
+ test_suites: ["device-tests"],
srcs: [
"ExtractorFactoryTest.cpp",
diff --git a/media/libstagefright/timedtext/TEST_MAPPING b/media/libstagefright/timedtext/TEST_MAPPING
new file mode 100644
index 0000000..185f824
--- /dev/null
+++ b/media/libstagefright/timedtext/TEST_MAPPING
@@ -0,0 +1,7 @@
+// mappings for frameworks/av/media/libstagefright/timedtext
+{
+ "presubmit": [
+ // TODO(b/148094059): unit tests not allowed to download content
+ //{ "name": "TimedTextUnitTest" }
+ ]
+}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 43989bb..439b063 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -172,6 +172,7 @@
cc_test {
name: "AImageReaderWindowHandleTest",
+ test_suites: ["device-tests"],
srcs: ["tests/AImageReaderWindowHandleTest.cpp"],
shared_libs: [
"libbinder",
diff --git a/media/ndk/TEST_MAPPING b/media/ndk/TEST_MAPPING
new file mode 100644
index 0000000..1a81538
--- /dev/null
+++ b/media/ndk/TEST_MAPPING
@@ -0,0 +1,6 @@
+// mappings for frameworks/av/media/ndk
+{
+ "presubmit": [
+ { "name": "AImageReaderWindowHandleTest" }
+ ]
+}