Merge "Camera: add default secure camera size key" into sc-dev
diff --git a/METADATA b/METADATA
index 1fbda08..aabda36 100644
--- a/METADATA
+++ b/METADATA
@@ -2,6 +2,22 @@
# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
# DEPENDING ON IT IN YOUR PROJECT. ***
third_party {
- # would be NOTICE save for drm/mediadrm/plugins/clearkey/hidl/
+ # would be NOTICE save for Widevine Master License Agreement in:
+ # drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
+ # drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+ # drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
+ # drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
+ # drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+ # and patent disclaimers in:
+ # media/codec2/components/aac/patent_disclaimer.txt
+ # media/codec2/components/amr_nb_wb/patent_disclaimer.txt
+ # media/codec2/components/mp3/patent_disclaimer.txt
+ # media/codec2/components/mpeg4_h263/patent_disclaimer.txt
+ # media/codecs/amrnb/patent_disclaimer.txt
+ # media/codecs/amrwb/dec/patent_disclaimer.txt
+ # media/codecs/amrwb/enc/patent_disclaimer.txt
+ # media/codecs/m4v_h263/patent_disclaimer.txt
+ # media/codecs/mp3dec/patent_disclaimer.txt
+ # media/libstagefright/codecs/aacenc/patent_disclaimer.txt
license_type: BY_EXCEPTION_ONLY
}
diff --git a/MainlineFiles.cfg b/MainlineFiles.cfg
index 37d714c..f694a41 100644
--- a/MainlineFiles.cfg
+++ b/MainlineFiles.cfg
@@ -24,11 +24,4 @@
media/codec2/components/
media/codecs/
media/extractors/
-media/libstagefright/codecs/amrnb/
-media/libstagefright/codecs/amrwb/
-media/libstagefright/codecs/amrwbenc/
-media/libstagefright/codecs/common/
-media/libstagefright/codecs/flac/
-media/libstagefright/codecs/m4v_h263/
-media/libstagefright/codecs/mp3dec/
media/libstagefright/mpeg2ts
diff --git a/apex/TEST_MAPPING b/apex/TEST_MAPPING
index 09c46d6..4b7c019 100644
--- a/apex/TEST_MAPPING
+++ b/apex/TEST_MAPPING
@@ -16,7 +16,7 @@
"include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineYouTubePerformanceTests"
+ "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
}
]
}
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index aa8a7d8..3642898 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -11,7 +11,7 @@
"include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineYouTubePerformanceTests"
+ "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
}
]
}
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index b49ec75..b042c27 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -64,6 +64,7 @@
"android.hardware.drm@1.0",
"android.hardware.drm@1.1",
"android.hardware.drm@1.2",
+ "android.hardware.drm@1.4",
],
cflags: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 18772e0..9d39f83 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -28,6 +28,7 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmUtils.h>
using drm::V1_0::BufferType;
using drm::V1_0::DestinationBuffer;
@@ -39,6 +40,7 @@
using drm::V1_0::Status;
using drm::V1_0::SubSample;
+using ::android::DrmUtils::toStatusT;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_memory;
@@ -53,42 +55,6 @@
namespace android {
-static status_t toStatusT(Status status) {
- switch (status) {
- case Status::OK:
- return OK;
- case Status::ERROR_DRM_NO_LICENSE:
- return ERROR_DRM_NO_LICENSE;
- case Status::ERROR_DRM_LICENSE_EXPIRED:
- return ERROR_DRM_LICENSE_EXPIRED;
- case Status::ERROR_DRM_RESOURCE_BUSY:
- return ERROR_DRM_RESOURCE_BUSY;
- case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
- return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
- case Status::ERROR_DRM_SESSION_NOT_OPENED:
- return ERROR_DRM_SESSION_NOT_OPENED;
- case Status::ERROR_DRM_CANNOT_HANDLE:
- return ERROR_DRM_CANNOT_HANDLE;
- case Status::ERROR_DRM_DECRYPT:
- return ERROR_DRM_DECRYPT;
- default:
- return UNKNOWN_ERROR;
- }
-}
-
-static status_t toStatusT_1_2(Status_V1_2 status) {
- switch (status) {
- case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
- return ERROR_DRM_SESSION_LOST_STATE;;
- case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
- return ERROR_DRM_FRAME_TOO_LARGE;
- case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
- return ERROR_DRM_INSUFFICIENT_SECURITY;
- default:
- return toStatusT(static_cast<Status>(status));
- }
-}
-
static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
hidl_vec<uint8_t> vec;
vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
@@ -384,7 +350,7 @@
bytesWritten = hBytesWritten;
*errorDetailMsg = toString8(hDetailedError);
}
- err = toStatusT_1_2(status);
+ err = toStatusT(status);
}
);
} else {
@@ -427,4 +393,8 @@
return toStatusT(mPlugin->setMediaDrmSession(toHidlVec(sessionId)));
}
+status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs);
+}
} // namespace android
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 501471c..f8f2bc6 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -55,6 +55,7 @@
using drm::V1_1::SecurityLevel;
using drm::V1_2::KeySetId;
using drm::V1_2::KeyStatusType;
+using ::android::DrmUtils::toStatusT;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
@@ -235,58 +236,6 @@
return keySetIds;
}
-static status_t toStatusT(Status status) {
- switch (status) {
- case Status::OK:
- return OK;
- break;
- case Status::ERROR_DRM_NO_LICENSE:
- return ERROR_DRM_NO_LICENSE;
- break;
- case Status::ERROR_DRM_LICENSE_EXPIRED:
- return ERROR_DRM_LICENSE_EXPIRED;
- break;
- case Status::ERROR_DRM_SESSION_NOT_OPENED:
- return ERROR_DRM_SESSION_NOT_OPENED;
- break;
- case Status::ERROR_DRM_CANNOT_HANDLE:
- return ERROR_DRM_CANNOT_HANDLE;
- break;
- case Status::ERROR_DRM_INVALID_STATE:
- return ERROR_DRM_INVALID_STATE;
- break;
- case Status::BAD_VALUE:
- return BAD_VALUE;
- break;
- case Status::ERROR_DRM_NOT_PROVISIONED:
- return ERROR_DRM_NOT_PROVISIONED;
- break;
- case Status::ERROR_DRM_RESOURCE_BUSY:
- return ERROR_DRM_RESOURCE_BUSY;
- break;
- case Status::ERROR_DRM_DEVICE_REVOKED:
- return ERROR_DRM_DEVICE_REVOKED;
- break;
- case Status::ERROR_DRM_UNKNOWN:
- default:
- return ERROR_DRM_UNKNOWN;
- break;
- }
-}
-
-static status_t toStatusT_1_2(Status_V1_2 status) {
- switch (status) {
- case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION:
- return ERROR_DRM_RESOURCE_CONTENTION;
- case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
- return ERROR_DRM_FRAME_TOO_LARGE;
- case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
- return ERROR_DRM_INSUFFICIENT_SECURITY;
- default:
- return toStatusT(static_cast<Status>(status));
- }
-}
-
Mutex DrmHal::mLock;
struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
@@ -825,7 +774,7 @@
defaultUrl = toString8(hDefaultUrl);
*keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
}
- err = toStatusT_1_2(status);
+ err = toStatusT(status);
});
} else if (mPluginV1_1 != NULL) {
hResult = mPluginV1_1->getKeyRequest_1_1(
@@ -947,7 +896,7 @@
request = toVector(hRequest);
defaultUrl = toString8(hDefaultUrl);
}
- err = toStatusT_1_2(status);
+ err = toStatusT(status);
}
);
} else {
@@ -1119,7 +1068,7 @@
*connected = toHdcpLevel(hConnected);
*max = toHdcpLevel(hMax);
}
- err = toStatusT_1_2(status);
+ err = toStatusT(status);
});
} else if (mPluginV1_1 != NULL) {
hResult = mPluginV1_1->getHdcpLevels(
@@ -1596,4 +1545,9 @@
return toStatusT(err);
}
+status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+}
+
} // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index d85fa61..82eadd9 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -177,5 +177,93 @@
return plugins;
}
+status_t toStatusT_1_4(::V1_4::Status status) {
+ switch (status) {
+ case ::V1_4::Status::OK:
+ return OK;
+ case ::V1_4::Status::BAD_VALUE:
+ return BAD_VALUE;
+ case ::V1_4::Status::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ case ::V1_4::Status::ERROR_DRM_DECRYPT:
+ return ERROR_DRM_DECRYPT;
+ case ::V1_4::Status::ERROR_DRM_DEVICE_REVOKED:
+ return ERROR_DRM_DEVICE_REVOKED;
+ case ::V1_4::Status::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ case ::V1_4::Status::ERROR_DRM_INVALID_STATE:
+ return ERROR_DRM_INVALID_STATE;
+ case ::V1_4::Status::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ case ::V1_4::Status::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ case ::V1_4::Status::ERROR_DRM_NOT_PROVISIONED:
+ return ERROR_DRM_NOT_PROVISIONED;
+ case ::V1_4::Status::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ case ::V1_4::Status::ERROR_DRM_RESOURCE_CONTENTION:
+ return ERROR_DRM_RESOURCE_CONTENTION;
+ case ::V1_4::Status::ERROR_DRM_SESSION_LOST_STATE:
+ return ERROR_DRM_SESSION_LOST_STATE;
+ case ::V1_4::Status::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
+
+ // New in S / drm@1.4:
+ case ::V1_4::Status::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ return ERROR_DRM_ZERO_SUBSAMPLES;
+ case ::V1_4::Status::CRYPTO_LIBRARY_ERROR:
+ return ERROR_DRM_CRYPTO_LIBRARY;
+ case ::V1_4::Status::GENERAL_OEM_ERROR:
+ return ERROR_DRM_GENERIC_OEM;
+ case ::V1_4::Status::GENERAL_PLUGIN_ERROR:
+ return ERROR_DRM_GENERIC_PLUGIN;
+ case ::V1_4::Status::INIT_DATA_INVALID:
+ return ERROR_DRM_INIT_DATA;
+ case ::V1_4::Status::KEY_NOT_LOADED:
+ return ERROR_DRM_KEY_NOT_LOADED;
+ case ::V1_4::Status::LICENSE_PARSE_ERROR:
+ return ERROR_DRM_LICENSE_PARSE;
+ case ::V1_4::Status::LICENSE_POLICY_ERROR:
+ return ERROR_DRM_LICENSE_POLICY;
+ case ::V1_4::Status::LICENSE_RELEASE_ERROR:
+ return ERROR_DRM_LICENSE_RELEASE;
+ case ::V1_4::Status::LICENSE_REQUEST_REJECTED:
+ return ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ case ::V1_4::Status::LICENSE_RESTORE_ERROR:
+ return ERROR_DRM_LICENSE_RESTORE;
+ case ::V1_4::Status::LICENSE_STATE_ERROR:
+ return ERROR_DRM_LICENSE_STATE;
+ case ::V1_4::Status::MALFORMED_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MALFORMED;
+ case ::V1_4::Status::MEDIA_FRAMEWORK_ERROR:
+ return ERROR_DRM_MEDIA_FRAMEWORK;
+ case ::V1_4::Status::MISSING_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MISSING;
+ case ::V1_4::Status::PROVISIONING_CERTIFICATE_ERROR:
+ return ERROR_DRM_PROVISIONING_CERTIFICATE;
+ case ::V1_4::Status::PROVISIONING_CONFIGURATION_ERROR:
+ return ERROR_DRM_PROVISIONING_CONFIG;
+ case ::V1_4::Status::PROVISIONING_PARSE_ERROR:
+ return ERROR_DRM_PROVISIONING_PARSE;
+ case ::V1_4::Status::RETRYABLE_PROVISIONING_ERROR:
+ return ERROR_DRM_PROVISIONING_RETRY;
+ case ::V1_4::Status::SECURE_STOP_RELEASE_ERROR:
+ return ERROR_DRM_SECURE_STOP_RELEASE;
+ case ::V1_4::Status::STORAGE_READ_FAILURE:
+ return ERROR_DRM_STORAGE_READ;
+ case ::V1_4::Status::STORAGE_WRITE_FAILURE:
+ return ERROR_DRM_STORAGE_WRITE;
+
+ case ::V1_4::Status::ERROR_DRM_UNKNOWN:
+ default:
+ return ERROR_DRM_UNKNOWN;
+ }
+ return ERROR_DRM_UNKNOWN;
+}
+
} // namespace DrmUtils
} // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index c9fda67..5fd39e6 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -22,6 +22,7 @@
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.1/ICryptoFactory.h>
#include <android/hardware/drm/1.2/ICryptoPlugin.h>
+#include <android/hardware/drm/1.4/ICryptoPlugin.h>
#include <mediadrm/ICrypto.h>
#include <utils/KeyedVector.h>
@@ -71,6 +72,8 @@
}
virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+
private:
mutable Mutex mLock;
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index 2fd4d81..a0aac30 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -26,6 +26,7 @@
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmPluginListener.h>
#include <android/hardware/drm/1.4/IDrmPlugin.h>
+#include <android/hardware/drm/1.4/types.h>
#include <media/drm/DrmAPI.h>
#include <mediadrm/DrmMetrics.h>
@@ -188,6 +189,8 @@
Vector<uint8_t> const &sessionId,
const char *playbackId);
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+
// Methods of IDrmPluginListener
Return<void> sendEvent(EventType eventType,
const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index ed71eee..b5bc73d 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -24,6 +24,15 @@
#define ANDROID_IDRM_H_
namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_4 {
+struct LogMessage;
+} // namespace V1_4
+} // namespace drm
+} // namespace hardware
+
+namespace drm = ::android::hardware::drm;
struct AString;
@@ -153,9 +162,12 @@
DrmPlugin::SecurityLevel securityLevel) const = 0;
virtual status_t setPlaybackId(
+
Vector<uint8_t> const &sessionId,
const char *playbackId) = 0;
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
+
protected:
IDrm() {}
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 20b3fe9..10b7207 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -19,11 +19,18 @@
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.4/IDrmPlugin.h>
+#include <android/hardware/drm/1.4/types.h>
+#include <media/stagefright/MediaErrors.h>
#include <utils/Errors.h> // for status_t
+#include <utils/Vector.h>
#include <utils/StrongPointer.h>
#include <vector>
+
using namespace ::android::hardware::drm;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
namespace android {
@@ -91,8 +98,46 @@
std::vector<sp<::V1_0::ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16],
const void *initData, size_t initDataSize);
+status_t toStatusT_1_4(::V1_4::Status status);
+
+template<typename S>
+inline status_t toStatusT(S status) {
+ auto err = static_cast<::V1_4::Status>(status);
+ return toStatusT_1_4(err);
+}
+
+template<typename T>
+inline status_t toStatusT(const android::hardware::Return<T> &status) {
+ auto t = static_cast<T>(status);
+ auto err = static_cast<::V1_4::Status>(t);
+ return toStatusT_1_4(err);
+}
+
+template<typename T, typename U>
+status_t GetLogMessages(const sp<U> &obj, Vector<::V1_4::LogMessage> &logs) {
+ sp<T> plugin = T::castFrom(obj);
+ if (plugin == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ ::V1_4::Status err{};
+ ::V1_4::IDrmPlugin::getLogMessages_cb cb = [&](
+ ::V1_4::Status status,
+ hidl_vec<::V1_4::LogMessage> hLogs) {
+ if (::V1_4::Status::OK == status) {
+ err = status;
+ return;
+ }
+ logs.appendArray(hLogs.data(), hLogs.size());
+ };
+
+ Return<void> hResult = plugin->getLogMessages(cb);
+ if (!hResult.isOk()) {
+ return DEAD_OBJECT;
+ }
+ return toStatusT(err);
+}
+
} // namespace DrmUtils
-
} // namespace android
-
#endif // ANDROID_DRMUTILS_H
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index df980ae..2c4df60 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -32,6 +32,10 @@
struct SharedBuffer;
struct DestinationBuffer;
} // namespace V1_0
+
+namespace V1_4 {
+struct LogMessage;
+} // namespace V1_4
} // namespace drm
} // namespace hardware
} // namespace android
@@ -83,6 +87,8 @@
virtual int32_t setHeap(const sp<hardware::HidlMemory>& heap) = 0;
virtual void unsetHeap(int32_t seqNum) = 0;
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
+
protected:
ICrypto() {}
diff --git a/include/drm/TEST_MAPPING b/include/drm/TEST_MAPPING
index 512e844..74fa50d 100644
--- a/include/drm/TEST_MAPPING
+++ b/include/drm/TEST_MAPPING
@@ -10,7 +10,7 @@
"include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineYouTubePerformanceTests"
+ "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
}
]
}
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 80e0924..5bc7262 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -30,7 +30,7 @@
"include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineYouTubePerformanceTests"
+ "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
}
]
}
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index f3341ab..3e6b0ff 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -877,10 +877,14 @@
work->worklets.front()->output.configUpdate.push_back(
C2Param::Copy(currentBoostFactor));
- C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
- (C2Config::drc_compression_mode_t) compressMode);
- work->worklets.front()->output.configUpdate.push_back(
- C2Param::Copy(currentCompressMode));
+ if (android_get_device_api_level() < __ANDROID_API_S__) {
+ // We used to report DRC compression mode in the output format
+ // in Q and R, but stopped doing that in S
+ C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
+ (C2Config::drc_compression_mode_t) compressMode);
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(currentCompressMode));
+ }
C2StreamDrcEncodedTargetLevelTuning::input currentEncodedTargetLevel(0u,
(C2FloatValue) (encTargetLevel*-0.25));
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
index 71956a2..51e1013 100644
--- a/media/codec2/fuzzer/C2Fuzzer.cpp
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -148,9 +148,8 @@
std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
C2ComponentFactory::DestroyCodec2FactoryFunc>> codec2FactoryFunc;
- codec2FactoryFunc.emplace_back(std::make_tuple(C2COMPONENTNAME,
- &CreateCodec2Factory,
- &DestroyCodec2Factory));
+ codec2FactoryFunc.emplace_back(
+ std::make_tuple(C2COMPONENTNAME, &CreateCodec2Factory, &DestroyCodec2Factory));
std::shared_ptr<C2ComponentStore> componentStore = GetTestComponentStore(codec2FactoryFunc);
if (!componentStore) {
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
index 2efad50..d5ac81a 100644
--- a/media/codec2/fuzzer/C2Fuzzer.h
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -59,8 +59,9 @@
private:
class BufferSource {
public:
- BufferSource(const uint8_t* data, size_t size)
- : mData(data), mSize(size), mReadIndex(size - kMarkerSize) {}
+ BufferSource(const uint8_t* data, size_t size) : mData(data), mSize(size) {
+ mReadIndex = (size <= kMarkerSize) ? 0 : (size - kMarkerSize);
+ }
~BufferSource() {
mData = nullptr;
mSize = 0;
@@ -72,10 +73,20 @@
FrameData getFrame();
private:
- bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }
+ bool isMarker() {
+ if ((kMarkerSize < mSize) && (mReadIndex < mSize - kMarkerSize)) {
+ return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0);
+ } else {
+ return false;
+ }
+ }
bool isCSDMarker(size_t position) {
- return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+ if ((kMarkerSuffixSize < mSize) && (position < mSize - kMarkerSuffixSize)) {
+ return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+ } else {
+ return false;
+ }
}
bool searchForMarker();
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 5de4d7f..4fd0341 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -487,6 +487,31 @@
}
};
+void RevertOutputFormatIfNeeded(
+ const sp<AMessage> &oldFormat, sp<AMessage> ¤tFormat) {
+ // We used to not report changes to these keys to the client.
+ const static std::set<std::string> sIgnoredKeys({
+ KEY_BIT_RATE,
+ KEY_MAX_BIT_RATE,
+ "csd-0",
+ "csd-1",
+ "csd-2",
+ });
+ if (currentFormat == oldFormat) {
+ return;
+ }
+ sp<AMessage> diff = currentFormat->changesFrom(oldFormat);
+ AMessage::Type type;
+ for (size_t i = diff->countEntries(); i > 0; --i) {
+ if (sIgnoredKeys.count(diff->getEntryNameAt(i - 1, &type)) > 0) {
+ diff->removeEntryAt(i - 1);
+ }
+ }
+ if (diff->countEntries() == 0) {
+ currentFormat = oldFormat;
+ }
+}
+
} // namespace
// CCodec::ClientListener
@@ -518,9 +543,24 @@
virtual void onError(
const std::weak_ptr<Codec2Client::Component>& component,
uint32_t errorCode) override {
- // TODO
- (void)component;
- (void)errorCode;
+ {
+ // Component is only used for reporting as we use a separate listener for each instance
+ std::shared_ptr<Codec2Client::Component> comp = component.lock();
+ if (!comp) {
+ ALOGD("Component died with error: 0x%x", errorCode);
+ } else {
+ ALOGD("Component \"%s\" returned error: 0x%x", comp->getName().c_str(), errorCode);
+ }
+ }
+
+ // Report to MediaCodec
+ // Note: for now we do not propagate the error code to MediaCodec as we would need
+ // to translate to a MediaCodec error.
+ sp<CCodec> codec(mCodec.promote());
+ if (!codec || !codec->mCallback) {
+ return;
+ }
+ codec->mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
}
virtual void onDeath(
@@ -884,19 +924,84 @@
/*
* Handle desired color format.
*/
+ int32_t defaultColorFormat = COLOR_FormatYUV420Flexible;
if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
- int32_t format = -1;
+ int32_t format = 0;
+ // Query vendor format for Flexible YUV
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
+ if (mClient->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo = C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].get());
+ } else {
+ pixelFormatInfo = nullptr;
+ }
+ std::optional<uint32_t> flexPixelFormat{};
+ std::optional<uint32_t> flexPlanarPixelFormat{};
+ std::optional<uint32_t> flexSemiPlanarPixelFormat{};
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ const C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ if (desc.bitDepth != 8
+ || desc.subsampling != C2Color::YUV_420
+ // TODO(b/180076105): some device report wrong layout
+ // || desc.layout == C2Color::INTERLEAVED_PACKED
+ // || desc.layout == C2Color::INTERLEAVED_ALIGNED
+ || desc.layout == C2Color::UNKNOWN_LAYOUT) {
+ continue;
+ }
+ if (!flexPixelFormat) {
+ flexPixelFormat = desc.pixelFormat;
+ }
+ if (desc.layout == C2Color::PLANAR_PACKED && !flexPlanarPixelFormat) {
+ flexPlanarPixelFormat = desc.pixelFormat;
+ }
+ if (desc.layout == C2Color::SEMIPLANAR_PACKED && !flexSemiPlanarPixelFormat) {
+ flexSemiPlanarPixelFormat = desc.pixelFormat;
+ }
+ }
+ }
if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
- /*
- * Also handle default color format (encoders require color format, so this is only
- * needed for decoders.
- */
+ // Also handle default color format (encoders require color format, so this is only
+ // needed for decoders.
if (!(config->mDomain & Config::IS_ENCODER)) {
- format = (surface == nullptr) ? COLOR_FormatYUV420Planar : COLOR_FormatSurface;
+ if (surface == nullptr) {
+ format = flexPixelFormat.value_or(COLOR_FormatYUV420Flexible);
+ } else {
+ format = COLOR_FormatSurface;
+ }
+ defaultColorFormat = format;
+ }
+ } else {
+ if ((config->mDomain & Config::IS_ENCODER) || !surface) {
+ switch (format) {
+ case COLOR_FormatYUV420Flexible:
+ format = flexPixelFormat.value_or(COLOR_FormatYUV420Planar);
+ break;
+ case COLOR_FormatYUV420Planar:
+ case COLOR_FormatYUV420PackedPlanar:
+ format = flexPlanarPixelFormat.value_or(
+ flexPixelFormat.value_or(format));
+ break;
+ case COLOR_FormatYUV420SemiPlanar:
+ case COLOR_FormatYUV420PackedSemiPlanar:
+ format = flexSemiPlanarPixelFormat.value_or(
+ flexPixelFormat.value_or(format));
+ break;
+ default:
+ // No-op
+ break;
+ }
}
}
- if (format >= 0) {
+ if (format != 0) {
msg->setInt32("android._color-format", format);
}
}
@@ -1049,12 +1154,16 @@
// Set desired color format from configuration parameter
int32_t format;
- if (msg->findInt32("android._color-format", &format)) {
- if (config->mDomain & Config::IS_ENCODER) {
- config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
- } else {
- config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
+ if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
+ format = defaultColorFormat;
+ }
+ if (config->mDomain & Config::IS_ENCODER) {
+ config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
+ if (msg->findInt32("android._color-format", &format)) {
+ config->mInputFormat->setInt32("android._color-format", format);
}
+ } else {
+ config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
}
}
@@ -1687,7 +1796,9 @@
|| comp->getName().find("c2.android.") == 0)) {
mChannel->setParameters(configUpdate);
} else {
+ sp<AMessage> outputFormat = config->mOutputFormat;
(void)config->setParameters(comp, configUpdate, C2_MAY_BLOCK);
+ RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
}
}
@@ -1812,7 +1923,6 @@
// handle configuration changes in work done
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
- bool changed = false;
Config::Watcher<C2StreamInitDataInfo::output> initData =
config->watch<C2StreamInitDataInfo::output>();
if (!work->worklets.empty()
@@ -1847,9 +1957,9 @@
++stream;
}
- if (config->updateConfiguration(updates, config->mOutputDomain)) {
- changed = true;
- }
+ sp<AMessage> outputFormat = config->mOutputFormat;
+ config->updateConfiguration(updates, config->mOutputDomain);
+ RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
// copy standard infos to graphic buffers if not already present (otherwise, we
// may overwrite the actual intermediate value with a final value)
@@ -1883,7 +1993,7 @@
config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
}
mChannel->onWorkDone(
- std::move(work), changed ? config->mOutputFormat->dup() : nullptr,
+ std::move(work), config->mOutputFormat,
initData.hasChanged() ? initData.update().get() : nullptr);
break;
}
@@ -2012,7 +2122,7 @@
}
if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
mInputAllocators.reset(
- C2PortAllocatorsTuning::input::From(params[0].get()));
+ C2PortAllocatorsTuning::input::From(param));
}
}
mInitStatus = OK;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index d656350..2025da2 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -27,6 +27,7 @@
#include <mediadrm/ICrypto.h>
#include "CCodecBuffers.h"
+#include "Codec2Mapper.h"
namespace android {
@@ -161,8 +162,7 @@
setSkipCutBuffer(delay, padding);
}
-void OutputBuffers::updateSkipCutBuffer(
- const sp<AMessage> &format, bool notify) {
+void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
AString mediaType;
if (format->findString(KEY_MIME, &mediaType)
&& mediaType == MIMETYPE_AUDIO_RAW) {
@@ -173,9 +173,6 @@
updateSkipCutBuffer(sampleRate, channelCount);
}
}
- if (notify) {
- mUnreportedFormat = nullptr;
- }
}
void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
@@ -199,7 +196,6 @@
mReorderStash.clear();
mDepth = 0;
mKey = C2Config::ORDINAL;
- mUnreportedFormat = nullptr;
}
void OutputBuffers::flushStash() {
@@ -275,25 +271,25 @@
*c2Buffer = entry.buffer;
sp<AMessage> outputFormat = entry.format;
- // The output format can be processed without a registered slot.
- if (outputFormat) {
- updateSkipCutBuffer(outputFormat, entry.notify);
- }
-
- if (entry.notify) {
- if (outputFormat) {
- setFormat(outputFormat);
- } else if (mUnreportedFormat) {
- outputFormat = mUnreportedFormat;
- setFormat(outputFormat);
+ if (entry.notify && mFormat != outputFormat) {
+ updateSkipCutBuffer(outputFormat);
+ sp<ABuffer> imageData;
+ if (mFormat->findBuffer("image-data", &imageData)) {
+ outputFormat->setBuffer("image-data", imageData);
}
- mUnreportedFormat = nullptr;
- } else {
- if (outputFormat) {
- mUnreportedFormat = outputFormat;
- } else if (!mUnreportedFormat) {
- mUnreportedFormat = mFormat;
+ int32_t stride;
+ if (mFormat->findInt32(KEY_STRIDE, &stride)) {
+ outputFormat->setInt32(KEY_STRIDE, stride);
}
+ int32_t sliceHeight;
+ if (mFormat->findInt32(KEY_SLICE_HEIGHT, &sliceHeight)) {
+ outputFormat->setInt32(KEY_SLICE_HEIGHT, sliceHeight);
+ }
+ ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
+ mName, mFormat.get(), outputFormat.get());
+ ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
+ mName, outputFormat->debugString().c_str());
+ setFormat(outputFormat);
}
// Flushing mReorderStash because no other buffers should come after output
@@ -304,10 +300,6 @@
}
if (!entry.notify) {
- if (outputFormat) {
- ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
- mName, outputFormat->debugString().c_str());
- }
mPending.pop_front();
return DISCARD;
}
@@ -325,10 +317,6 @@
(*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
(*outBuffer)->meta()->setInt32("flags", entry.flags);
(*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
- if (outputFormat) {
- ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
- mName, outputFormat->debugString().c_str());
- }
ALOGV("[%s] popFromStashAndRegister: "
"out buffer index = %zu [%p] => %p + %zu (%lld)",
mName, *index, outBuffer->get(),
@@ -1021,18 +1009,32 @@
// track of the flushed work.
}
+static uint32_t extractPixelFormat(const sp<AMessage> &format) {
+ int32_t frameworkColorFormat = 0;
+ if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
+ if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
+ return pixelFormat;
+ }
+ return PIXEL_FORMAT_UNKNOWN;
+}
+
std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
std::unique_ptr<InputBuffersArray> array(
new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
array->setPool(mPool);
array->setFormat(mFormat);
+ uint32_t pixelFormat = extractPixelFormat(mFormat);
array->initialize(
mImpl,
size,
- [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
+ [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
+ -> sp<Codec2Buffer> {
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
return AllocateGraphicBuffer(
- pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
+ pool, format, pixelFormat, usage, lbp);
});
return std::move(array);
}
@@ -1046,7 +1048,7 @@
(void)mFormat->findInt64("android._C2MemoryUsage", &usageValue);
C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
return AllocateGraphicBuffer(
- mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
+ mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
}
// OutputBuffersArray
@@ -1182,7 +1184,6 @@
void OutputBuffersArray::transferFrom(OutputBuffers* source) {
mFormat = source->mFormat;
mSkipCutBuffer = source->mSkipCutBuffer;
- mUnreportedFormat = source->mUnreportedFormat;
mPending = std::move(source->mPending);
mReorderStash = std::move(source->mReorderStash);
mDepth = source->mDepth;
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index c383a7c..7c4e7b1 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -215,10 +215,8 @@
/**
* Update SkipCutBuffer from format. The @p format must not be null.
- * @p notify determines whether the format comes with a buffer that should
- * be reported to the client or not.
*/
- void updateSkipCutBuffer(const sp<AMessage> &format, bool notify = true);
+ void updateSkipCutBuffer(const sp<AMessage> &format);
/**
* Output Stash
@@ -392,9 +390,6 @@
// Output stash
- // Output format that has not been made available to the client.
- sp<AMessage> mUnreportedFormat;
-
// Struct for an entry in the output stash (mPending and mReorderStash)
struct StashEntry {
inline StashEntry()
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 79c6227..5decb99 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -765,21 +765,13 @@
// convert to compression type and add default
add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
- .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
- .withMappers([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM))
+ .withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
value = property_get_int32(PROP_DRC_OVERRIDE_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
}
return value == 1 ? C2Config::DRC_COMPRESSION_HEAVY : C2Config::DRC_COMPRESSION_LIGHT;
- },[](C2Value v) -> C2Value {
- int32_t value;
- if (v.get(&value)) {
- return value;
- }
- else {
- return C2Value();
- }
}));
// convert to dBFS and add default
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 5072323..fc4ee51 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -212,21 +212,24 @@
* Creates a C2GraphicView <=> MediaImage converter
*
* \param view C2GraphicView object
- * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
- * an attempt is made to simply represent the graphic view as a flexible SDK format
- * without a memcpy)
+ * \param format buffer format
* \param copy whether the converter is used for copy or not
*/
GraphicView2MediaImageConverter(
- const C2GraphicView &view, int32_t colorFormat, bool copy)
+ const C2GraphicView &view, const sp<AMessage> &format, bool copy)
: mInitCheck(NO_INIT),
mView(view),
mWidth(view.width()),
mHeight(view.height()),
- mColorFormat(colorFormat),
mAllocatedDepth(0),
mBackBufferSize(0),
mMediaImage(new ABuffer(sizeof(MediaImage2))) {
+ if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
+ mClientColorFormat = COLOR_FormatYUV420Flexible;
+ }
+ if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
+ mComponentColorFormat = COLOR_FormatYUV420Flexible;
+ }
if (view.error() != C2_OK) {
ALOGD("Converter: view.error() = %d", view.error());
mInitCheck = BAD_VALUE;
@@ -247,70 +250,57 @@
uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
uint32_t vStride = align(view.crop().height, 2);
+ bool tryWrapping = !copy;
+
switch (layout.type) {
- case C2PlanarLayout::TYPE_YUV:
+ case C2PlanarLayout::TYPE_YUV: {
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
if (layout.numPlanes != 3) {
ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
mInitCheck = BAD_VALUE;
return;
}
- if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y
- || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB
- || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR
- || layout.planes[0].colSampling != 1
- || layout.planes[0].rowSampling != 1
- || layout.planes[1].colSampling != 2
- || layout.planes[1].rowSampling != 2
- || layout.planes[2].colSampling != 2
- || layout.planes[2].rowSampling != 2) {
- ALOGD("Converter: not YUV420 for YUV layout");
+ C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+ if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
+ || uPlane.channel != C2PlaneInfo::CHANNEL_CB
+ || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
+ ALOGD("Converter: not YUV layout");
mInitCheck = BAD_VALUE;
return;
}
- switch (mColorFormat) {
- case COLOR_FormatYUV420Flexible:
- if (!copy) {
- // try to map directly. check if the planes are near one another
- const uint8_t *minPtr = mView.data()[0];
- const uint8_t *maxPtr = mView.data()[0];
- int32_t planeSize = 0;
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
- ssize_t minOffset = plane.minOffset(
- mWidth / plane.colSampling, mHeight / plane.rowSampling);
- ssize_t maxOffset = plane.maxOffset(
- mWidth / plane.colSampling, mHeight / plane.rowSampling);
- if (minPtr > mView.data()[i] + minOffset) {
- minPtr = mView.data()[i] + minOffset;
- }
- if (maxPtr < mView.data()[i] + maxOffset) {
- maxPtr = mView.data()[i] + maxOffset;
- }
- planeSize += planeStride * divUp(mAllocatedDepth, 8u)
- * align(mHeight, 64) / plane.rowSampling;
- }
-
- if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
- // FIXME: this is risky as reading/writing data out of bound results
- // in an undefined behavior, but gralloc does assume a
- // contiguous mapping
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
- mediaImage->mPlane[i].mColInc = plane.colInc;
- mediaImage->mPlane[i].mRowInc = plane.rowInc;
- mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
- }
- mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
- maxPtr - minPtr + 1);
- break;
- }
+ bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
+ && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+ && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
+ if (yuv420888) {
+ for (uint32_t i = 0; i < 3; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
+ yuv420888 = false;
+ break;
}
- [[fallthrough]];
-
+ }
+ yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
+ }
+ int32_t copyFormat = mClientColorFormat;
+ if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
+ if (uPlane.colInc == 2 && vPlane.colInc == 2
+ && yPlane.rowInc == uPlane.rowInc) {
+ copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
+ } else if (uPlane.colInc == 1 && vPlane.colInc == 1
+ && yPlane.rowInc == uPlane.rowInc * 2) {
+ copyFormat = COLOR_FormatYUV420PackedPlanar;
+ }
+ }
+ ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
+ "v:{colInc=%d rowInc=%d}",
+ mClientColorFormat,
+ yPlane.colInc, yPlane.rowInc,
+ uPlane.colInc, uPlane.rowInc,
+ vPlane.colInc, vPlane.rowInc);
+ switch (copyFormat) {
+ case COLOR_FormatYUV420Flexible:
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420PackedPlanar:
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
@@ -330,6 +320,13 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+ if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+ tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
+ && yPlane.rowInc == uPlane.rowInc * 2
+ && view.data()[0] < view.data()[1]
+ && view.data()[1] < view.data()[2];
+ }
break;
case COLOR_FormatYUV420SemiPlanar:
@@ -351,64 +348,165 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+ if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+ tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
+ && yPlane.rowInc == uPlane.rowInc
+ && view.data()[0] < view.data()[1]
+ && view.data()[1] < view.data()[2];
+ }
break;
- default:
- ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
+ case COLOR_FormatYUVP010:
+ mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+ mediaImage->mPlane[mediaImage->Y].mColInc = 2;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
+ mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
+
+ mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride * 2;
+ mediaImage->mPlane[mediaImage->U].mColInc = 4;
+ mediaImage->mPlane[mediaImage->U].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
+ mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
+
+ mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 2 + 2;
+ mediaImage->mPlane[mediaImage->V].mColInc = 4;
+ mediaImage->mPlane[mediaImage->V].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
+ mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+ if (tryWrapping) {
+ tryWrapping = yPlane.allocatedDepth == 16
+ && uPlane.allocatedDepth == 16
+ && vPlane.allocatedDepth == 16
+ && yPlane.bitDepth == 10
+ && uPlane.bitDepth == 10
+ && vPlane.bitDepth == 10
+ && yPlane.rightShift == 6
+ && uPlane.rightShift == 6
+ && vPlane.rightShift == 6
+ && yPlane.rowSampling == 1 && yPlane.colSampling == 1
+ && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+ && vPlane.rowSampling == 2 && vPlane.colSampling == 2
+ && yPlane.colInc == 2
+ && uPlane.colInc == 4
+ && vPlane.colInc == 4
+ && yPlane.rowInc == uPlane.rowInc
+ && yPlane.rowInc == vPlane.rowInc;
+ }
+ break;
+
+ default: {
+ // default to fully planar format --- this will be overridden if wrapping
+ // TODO: keep interleaved format
+ int32_t colInc = divUp(mAllocatedDepth, 8u);
+ int32_t rowInc = stride * colInc / yPlane.colSampling;
+ mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+ mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
+ mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
+ int32_t offset = rowInc * vStride / yPlane.rowSampling;
+
+ rowInc = stride * colInc / uPlane.colSampling;
+ mediaImage->mPlane[mediaImage->U].mOffset = offset;
+ mediaImage->mPlane[mediaImage->U].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
+ mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
+ offset += rowInc * vStride / uPlane.rowSampling;
+
+ rowInc = stride * colInc / vPlane.colSampling;
+ mediaImage->mPlane[mediaImage->V].mOffset = offset;
+ mediaImage->mPlane[mediaImage->V].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
+ mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
+ break;
+ }
}
break;
+ }
+
case C2PlanarLayout::TYPE_YUVA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
- // We don't have an SDK YUVA format
- ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
- mInitCheck = BAD_VALUE;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for YUVA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
return;
case C2PlanarLayout::TYPE_RGB:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
- switch (mColorFormat) {
- // TODO media image
- case COLOR_FormatRGBFlexible:
- case COLOR_Format24bitBGR888:
- case COLOR_Format24bitRGB888:
- break;
- default:
- ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (layout.numPlanes != 3) {
- ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
- mInitCheck = BAD_VALUE;
- return;
- }
- break;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ // TODO: support MediaImage layout
+ return;
case C2PlanarLayout::TYPE_RGBA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
- switch (mColorFormat) {
- // TODO media image
- case COLOR_FormatRGBAFlexible:
- case COLOR_Format32bitABGR8888:
- case COLOR_Format32bitARGB8888:
- case COLOR_Format32bitBGRA8888:
- break;
- default:
- ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (layout.numPlanes != 4) {
- ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
- mInitCheck = BAD_VALUE;
- return;
- }
- break;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ // TODO: support MediaImage layout
+ return;
default:
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
- ALOGD("Unknown layout");
- mInitCheck = BAD_VALUE;
- return;
+ if (layout.numPlanes == 1) {
+ const C2PlaneInfo &plane = layout.planes[0];
+ if (plane.colInc < 0 || plane.rowInc < 0) {
+ // Copy-only if we have negative colInc/rowInc
+ tryWrapping = false;
+ }
+ mediaImage->mPlane[0].mOffset = 0;
+ mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
+ mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
+ mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
+ mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
+ } else {
+ ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ return;
+ }
+ break;
+ }
+ if (tryWrapping) {
+ // try to map directly. check if the planes are near one another
+ const uint8_t *minPtr = mView.data()[0];
+ const uint8_t *maxPtr = mView.data()[0];
+ int32_t planeSize = 0;
+ for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
+ ssize_t minOffset = plane.minOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ ssize_t maxOffset = plane.maxOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ if (minPtr > mView.data()[i] + minOffset) {
+ minPtr = mView.data()[i] + minOffset;
+ }
+ if (maxPtr < mView.data()[i] + maxOffset) {
+ maxPtr = mView.data()[i] + maxOffset;
+ }
+ planeSize += planeStride * divUp(mAllocatedDepth, 8u)
+ * align(mHeight, 64) / plane.rowSampling;
+ }
+
+ if ((maxPtr - minPtr + 1) <= planeSize) {
+ // FIXME: this is risky as reading/writing data out of bound results
+ // in an undefined behavior, but gralloc does assume a
+ // contiguous mapping
+ for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
+ mediaImage->mPlane[i].mColInc = plane.colInc;
+ mediaImage->mPlane[i].mRowInc = plane.rowInc;
+ mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
+ mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
+ }
+ mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
+ maxPtr - minPtr + 1);
+ ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
+ }
}
mediaImage->mNumPlanes = layout.numPlanes;
mediaImage->mWidth = view.crop().width;
@@ -431,12 +529,12 @@
return;
}
if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
- ALOGV("different allocatedDepth/bitDepth per plane unsupported");
+ ALOGD("different allocatedDepth/bitDepth per plane unsupported");
mInitCheck = BAD_VALUE;
return;
}
bufferSize += stride * vStride
- / plane.rowSampling / plane.colSampling;
+ / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
}
mBackBufferSize = bufferSize;
@@ -491,7 +589,8 @@
const C2GraphicView mView;
uint32_t mWidth;
uint32_t mHeight;
- int32_t mColorFormat; ///< SDK color format for MediaImage
+ int32_t mClientColorFormat; ///< SDK color format for MediaImage
+ int32_t mComponentColorFormat; ///< SDK color format from component
sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
uint32_t mAllocatedDepth;
uint32_t mBackBufferSize;
@@ -520,10 +619,7 @@
return nullptr;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- (void)format->findInt32("color-format", &colorFormat);
-
- GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
+ GraphicView2MediaImageConverter converter(view, format, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -649,10 +745,7 @@
buffer->data().graphicBlocks()[0].map().get()));
std::unique_ptr<const C2GraphicView> holder;
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- (void)format->findInt32("color-format", &colorFormat);
-
- GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
+ GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -744,12 +837,11 @@
return false;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- // FIXME: format() is not const, but we cannot change it, so do a const cast here
- const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
-
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
+ buffer->data().graphicBlocks()[0].map().get(),
+ // FIXME: format() is not const, but we cannot change it, so do a const cast here
+ const_cast<ConstGraphicBlockBuffer *>(this)->format(),
+ true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
return false;
@@ -767,11 +859,9 @@
setRange(0, 0);
return true;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- format()->findInt32("color-format", &colorFormat);
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
+ buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
return false;
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index b112249..a26f89e 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -103,11 +103,16 @@
c2_status_t err1 = intf->querySupportedParams(¶mDescs);
if (err1 == C2_OK) {
for (const std::shared_ptr<C2ParamDescriptor> &desc : paramDescs) {
- switch ((uint32_t)desc->index()) {
- case C2StreamHdr10PlusInfo::output::PARAM_TYPE:
+ C2Param::Type type = desc->index();
+ // only consider supported parameters on raw ports
+ if (!(encoder ? type.forInput() : type.forOutput())) {
+ continue;
+ }
+ switch (type.coreIndex()) {
+ case C2StreamHdr10PlusInfo::CORE_INDEX:
supportsHdr10Plus = true;
break;
- case C2StreamHdrStaticInfo::output::PARAM_TYPE:
+ case C2StreamHdrStaticInfo::CORE_INDEX:
supportsHdr = true;
break;
default:
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
index ad8f6e5..66b7622 100644
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -18,11 +18,12 @@
#include <gtest/gtest.h>
-#include <media/stagefright/foundation/AString.h>
+#include <codec2/hidl/client.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <C2BlockInternal.h>
#include <C2PlatformSupport.h>
+#include <Codec2Mapper.h>
namespace android {
@@ -105,6 +106,318 @@
}
}
+TEST(RawGraphicOutputBuffersTest, FlexYuvColorFormat) {
+ constexpr int32_t kWidth = 320;
+ constexpr int32_t kHeight = 240;
+
+ std::vector<uint32_t> flexPixelFormats({HAL_PIXEL_FORMAT_YCbCr_420_888});
+ std::shared_ptr<Codec2Client> client = Codec2Client::CreateFromService("default");
+ if (client) {
+ // Query vendor format for Flexible YUV
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
+ if (client->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo = C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].get());
+ } else {
+ pixelFormatInfo = nullptr;
+ }
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ const C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ if (desc.bitDepth != 8
+ || desc.subsampling != C2Color::YUV_420
+ // TODO(b/180076105): some devices report wrong layouts
+ // || desc.layout == C2Color::INTERLEAVED_PACKED
+ // || desc.layout == C2Color::INTERLEAVED_ALIGNED
+ || desc.layout == C2Color::UNKNOWN_LAYOUT) {
+ continue;
+ }
+ flexPixelFormats.push_back(desc.pixelFormat);
+ }
+ }
+ }
+
+ for (uint32_t pixelFormat : flexPixelFormats) {
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>(
+ AStringPrintf("test pixel format 0x%x", pixelFormat).c_str());
+
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_WIDTH, kWidth);
+ format->setInt32(KEY_HEIGHT, kHeight);
+ format->setInt32(KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);
+ int32_t fwkPixelFormat = 0;
+ if (C2Mapper::mapPixelFormatCodecToFramework(pixelFormat, &fwkPixelFormat)) {
+ format->setInt32("android._color-format", fwkPixelFormat);
+ }
+ buffers->setFormat(format);
+
+ std::shared_ptr<C2BlockPool> pool;
+ ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
+
+ std::shared_ptr<C2GraphicBlock> block;
+ ASSERT_EQ(OK, pool->fetchGraphicBlock(
+ kWidth, kHeight, pixelFormat,
+ C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
+
+ {
+ C2GraphicView view = block->map().get();
+ C2PlanarLayout layout = view.layout();
+
+ // Verify the block is in YUV420 format
+ ASSERT_EQ(C2PlanarLayout::TYPE_YUV, layout.type);
+ ASSERT_EQ(3u, layout.numPlanes);
+ const C2PlaneInfo& yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ const C2PlaneInfo& uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ const C2PlaneInfo& vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+
+ // Y plane
+ ASSERT_EQ(1u, yPlane.colSampling);
+ ASSERT_EQ(1u, yPlane.rowSampling);
+ ASSERT_EQ(8u, yPlane.allocatedDepth);
+ ASSERT_EQ(8u, yPlane.bitDepth);
+ ASSERT_EQ(0u, yPlane.rightShift);
+
+ // U plane
+ ASSERT_EQ(2u, uPlane.colSampling);
+ ASSERT_EQ(2u, uPlane.rowSampling);
+ ASSERT_EQ(8u, uPlane.allocatedDepth);
+ ASSERT_EQ(8u, uPlane.bitDepth);
+ ASSERT_EQ(0u, uPlane.rightShift);
+
+ // V plane
+ ASSERT_EQ(2u, vPlane.colSampling);
+ ASSERT_EQ(2u, vPlane.rowSampling);
+ ASSERT_EQ(8u, vPlane.allocatedDepth);
+ ASSERT_EQ(8u, vPlane.bitDepth);
+ ASSERT_EQ(0u, vPlane.rightShift);
+
+ uint8_t *yRowPtr = view.data()[C2PlanarLayout::PLANE_Y];
+ uint8_t *uRowPtr = view.data()[C2PlanarLayout::PLANE_U];
+ uint8_t *vRowPtr = view.data()[C2PlanarLayout::PLANE_V];
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ *yPtr = ((row + col) & 0xFF);
+ yPtr += yPlane.colInc;
+
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ *uPtr = ((row + col + 1) & 0xFF);
+ *vPtr = ((row + col + 2) & 0xFF);
+ uPtr += uPlane.colInc;
+ vPtr += vPlane.colInc;
+ }
+ }
+ yRowPtr += yPlane.rowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.rowInc;
+ vRowPtr += vPlane.rowInc;
+ }
+ }
+ }
+
+ std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateGraphicBuffer(block->share(
+ block->crop(), C2Fence{}));
+ size_t index;
+ sp<MediaCodecBuffer> clientBuffer;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ sp<ABuffer> imageData;
+ ASSERT_TRUE(clientBuffer->format()->findBuffer("image-data", &imageData));
+ MediaImage2 *img = (MediaImage2 *)imageData->data();
+ ASSERT_EQ(MediaImage2::MEDIA_IMAGE_TYPE_YUV, img->mType);
+ ASSERT_EQ(3u, img->mNumPlanes);
+ ASSERT_EQ(kWidth, img->mWidth);
+ ASSERT_EQ(kHeight, img->mHeight);
+ ASSERT_EQ(8u, img->mBitDepth);
+ ASSERT_EQ(8u, img->mBitDepthAllocated);
+ const MediaImage2::PlaneInfo &yPlane = img->mPlane[MediaImage2::Y];
+ const MediaImage2::PlaneInfo &uPlane = img->mPlane[MediaImage2::U];
+ const MediaImage2::PlaneInfo &vPlane = img->mPlane[MediaImage2::V];
+ ASSERT_EQ(1u, yPlane.mHorizSubsampling);
+ ASSERT_EQ(1u, yPlane.mVertSubsampling);
+ ASSERT_EQ(2u, uPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, uPlane.mVertSubsampling);
+ ASSERT_EQ(2u, vPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, vPlane.mVertSubsampling);
+
+ uint8_t *yRowPtr = clientBuffer->data() + yPlane.mOffset;
+ uint8_t *uRowPtr = clientBuffer->data() + uPlane.mOffset;
+ uint8_t *vRowPtr = clientBuffer->data() + vPlane.mOffset;
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ ASSERT_EQ((row + col) & 0xFF, *yPtr);
+ yPtr += yPlane.mColInc;
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ ASSERT_EQ((row + col + 1) & 0xFF, *uPtr);
+ ASSERT_EQ((row + col + 2) & 0xFF, *vPtr);
+ uPtr += uPlane.mColInc;
+ vPtr += vPlane.mColInc;
+ }
+ }
+ yRowPtr += yPlane.mRowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.mRowInc;
+ vRowPtr += vPlane.mRowInc;
+ }
+ }
+ }
+}
+
+TEST(RawGraphicOutputBuffersTest, P010ColorFormat) {
+ constexpr int32_t kWidth = 320;
+ constexpr int32_t kHeight = 240;
+
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ std::make_shared<RawGraphicOutputBuffers>("test P010");
+
+ sp<AMessage> format{new AMessage};
+ format->setInt32(KEY_WIDTH, kWidth);
+ format->setInt32(KEY_HEIGHT, kHeight);
+ format->setInt32(KEY_COLOR_FORMAT, COLOR_FormatYUVP010);
+ int32_t fwkPixelFormat = 0;
+ if (C2Mapper::mapPixelFormatCodecToFramework(HAL_PIXEL_FORMAT_YCBCR_P010, &fwkPixelFormat)) {
+ format->setInt32("android._color-format", fwkPixelFormat);
+ }
+ buffers->setFormat(format);
+
+ std::shared_ptr<C2BlockPool> pool;
+ ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
+
+ std::shared_ptr<C2GraphicBlock> block;
+ c2_status_t err = pool->fetchGraphicBlock(
+ kWidth, kHeight, HAL_PIXEL_FORMAT_YCBCR_P010,
+ C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ if (err != C2_OK) {
+ GTEST_SKIP();
+ }
+
+ {
+ C2GraphicView view = block->map().get();
+ C2PlanarLayout layout = view.layout();
+
+ // Verify the block is in YUV420 format
+ ASSERT_EQ(C2PlanarLayout::TYPE_YUV, layout.type);
+ ASSERT_EQ(3u, layout.numPlanes);
+ const C2PlaneInfo& yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ const C2PlaneInfo& uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ const C2PlaneInfo& vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+
+ // Y plane
+ ASSERT_EQ(1u, yPlane.colSampling);
+ ASSERT_EQ(1u, yPlane.rowSampling);
+ ASSERT_EQ(16u, yPlane.allocatedDepth);
+ ASSERT_EQ(10u, yPlane.bitDepth);
+ ASSERT_EQ(6u, yPlane.rightShift);
+
+ // U plane
+ ASSERT_EQ(2u, uPlane.colSampling);
+ ASSERT_EQ(2u, uPlane.rowSampling);
+ ASSERT_EQ(16u, uPlane.allocatedDepth);
+ ASSERT_EQ(10u, uPlane.bitDepth);
+ ASSERT_EQ(6u, uPlane.rightShift);
+
+ // V plane
+ ASSERT_EQ(2u, vPlane.colSampling);
+ ASSERT_EQ(2u, vPlane.rowSampling);
+ ASSERT_EQ(16u, vPlane.allocatedDepth);
+ ASSERT_EQ(10u, vPlane.bitDepth);
+ ASSERT_EQ(6u, vPlane.rightShift);
+
+ uint8_t *yRowPtr = view.data()[C2PlanarLayout::PLANE_Y];
+ uint8_t *uRowPtr = view.data()[C2PlanarLayout::PLANE_U];
+ uint8_t *vRowPtr = view.data()[C2PlanarLayout::PLANE_V];
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ yPtr[0] = ((row + col) & 0x3) << 6;
+ yPtr[1] = ((row + col) & 0x3FC) >> 2;
+ yPtr += yPlane.colInc;
+
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ uPtr[0] = ((row + col + 1) & 0x3) << 6;
+ uPtr[1] = ((row + col + 1) & 0x3FC) >> 2;
+ vPtr[0] = ((row + col + 2) & 0x3) << 6;
+ vPtr[1] = ((row + col + 2) & 0x3FC) >> 2;
+ uPtr += uPlane.colInc;
+ vPtr += vPlane.colInc;
+ }
+ }
+ yRowPtr += yPlane.rowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.rowInc;
+ vRowPtr += vPlane.rowInc;
+ }
+ }
+ }
+
+ std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateGraphicBuffer(block->share(
+ block->crop(), C2Fence{}));
+ size_t index;
+ sp<MediaCodecBuffer> clientBuffer;
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+ ASSERT_NE(nullptr, clientBuffer);
+ sp<ABuffer> imageData;
+ ASSERT_TRUE(clientBuffer->format()->findBuffer("image-data", &imageData));
+ MediaImage2 *img = (MediaImage2 *)imageData->data();
+ ASSERT_EQ(MediaImage2::MEDIA_IMAGE_TYPE_YUV, img->mType);
+ ASSERT_EQ(3u, img->mNumPlanes);
+ ASSERT_EQ(kWidth, img->mWidth);
+ ASSERT_EQ(kHeight, img->mHeight);
+ ASSERT_EQ(10u, img->mBitDepth);
+ ASSERT_EQ(16u, img->mBitDepthAllocated);
+ const MediaImage2::PlaneInfo &yPlane = img->mPlane[MediaImage2::Y];
+ const MediaImage2::PlaneInfo &uPlane = img->mPlane[MediaImage2::U];
+ const MediaImage2::PlaneInfo &vPlane = img->mPlane[MediaImage2::V];
+ ASSERT_EQ(1u, yPlane.mHorizSubsampling);
+ ASSERT_EQ(1u, yPlane.mVertSubsampling);
+ ASSERT_EQ(2u, uPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, uPlane.mVertSubsampling);
+ ASSERT_EQ(2u, vPlane.mHorizSubsampling);
+ ASSERT_EQ(2u, vPlane.mVertSubsampling);
+
+ uint8_t *yRowPtr = clientBuffer->data() + yPlane.mOffset;
+ uint8_t *uRowPtr = clientBuffer->data() + uPlane.mOffset;
+ uint8_t *vRowPtr = clientBuffer->data() + vPlane.mOffset;
+ for (int32_t row = 0; row < kHeight; ++row) {
+ uint8_t *yPtr = yRowPtr;
+ uint8_t *uPtr = uRowPtr;
+ uint8_t *vPtr = vRowPtr;
+ for (int32_t col = 0; col < kWidth; ++col) {
+ ASSERT_EQ(((row + col) & 0x3) << 6, yPtr[0]);
+ ASSERT_EQ(((row + col) & 0x3FC) >> 2, yPtr[1]);
+ yPtr += yPlane.mColInc;
+ if (row < kHeight / 2 && col < kWidth / 2) {
+ ASSERT_EQ(((row + col + 1) & 0x3) << 6, uPtr[0]);
+ ASSERT_EQ(((row + col + 1) & 0x3FC) >> 2, uPtr[1]);
+ ASSERT_EQ(((row + col + 2) & 0x3) << 6, vPtr[0]);
+ ASSERT_EQ(((row + col + 2) & 0x3FC) >> 2, vPtr[1]);
+ uPtr += uPlane.mColInc;
+ vPtr += vPlane.mColInc;
+ }
+ }
+ yRowPtr += yPlane.mRowInc;
+ if (row < kHeight / 2) {
+ uRowPtr += uPlane.mRowInc;
+ vRowPtr += vPlane.mRowInc;
+ }
+ }
+}
+
class TestGraphicAllocation : public C2GraphicAllocation {
public:
TestGraphicAllocation(
@@ -407,7 +720,6 @@
}
}
}
-
size_t yPlaneSize = stride * kHeight;
size_t uvPlaneSize = stride * kHeight / 4;
size_t capacity = yPlaneSize + uvPlaneSize * 2;
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 903db6c..1390642 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -958,17 +958,16 @@
*c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
return true;
case COLOR_FormatYUV420Flexible:
- *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
- return true;
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420SemiPlanar:
case COLOR_FormatYUV420PackedPlanar:
case COLOR_FormatYUV420PackedSemiPlanar:
- *c2Value = HAL_PIXEL_FORMAT_YV12;
+ *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
return true;
default:
- // TODO: support some sort of passthrough
- return false;
+ // Passthrough
+ *c2Value = uint32_t(frameworkValue);
+ return true;
}
}
@@ -979,11 +978,16 @@
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
*frameworkValue = COLOR_FormatSurface;
return true;
- case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCBCR_422_SP:
+ case HAL_PIXEL_FORMAT_YCRCB_420_SP:
+ case HAL_PIXEL_FORMAT_YCBCR_422_I:
case HAL_PIXEL_FORMAT_YCBCR_420_888:
+ case HAL_PIXEL_FORMAT_YV12:
*frameworkValue = COLOR_FormatYUV420Flexible;
return true;
default:
- return false;
+ // Passthrough
+ *frameworkValue = int32_t(c2Value);
+ return true;
}
}
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 59471a2..8e59df1 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -532,11 +532,15 @@
break;
}
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
+ // fall-through
case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
// fall-through
- case static_cast<uint32_t>(PixelFormat4::YV12):
- // fall-through
- default: {
+ case static_cast<uint32_t>(PixelFormat4::YV12): {
android_ycbcr ycbcrLayout;
status_t err = GraphicBufferMapper::get().lockYCbCr(
@@ -604,6 +608,158 @@
}
break;
}
+
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
+ void *pointer = nullptr;
+ status_t err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(YCBCR_P010)");
+ return C2_CORRUPTED;
+ }
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + mStride * 2 * rect.height();
+ addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 2, // colInc
+ static_cast<int32_t>(2 * mStride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ 4, // colInc
+ static_cast<int32_t>(2 * mStride), // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ 4, // colInc
+ static_cast<int32_t>(2 * mStride), // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 2, // offset
+ };
+ break;
+ }
+
+ default: {
+ // We don't know what it is, but let's try to lock it.
+ android_ycbcr ycbcrLayout;
+
+ status_t err = GraphicBufferMapper::get().lockYCbCr(
+ const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
+ if (err == OK) {
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
+ addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 3;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 1, // colInc
+ (int32_t)ycbcrLayout.ystride, // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_V, // rootIx
+ 0, // offset
+ };
+ // handle interleaved formats
+ intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
+ if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
+ layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
+ } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
+ layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
+ }
+ break;
+ }
+
+ // We really don't know what this is; lock the buffer and pass it through ---
+ // the client may know how to interpret it.
+ void *pointer = nullptr;
+ err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(??? %x)", mFormat);
+ return C2_CORRUPTED;
+ }
+ addr[0] = (uint8_t *)pointer;
+ layout->type = C2PlanarLayout::TYPE_UNKNOWN;
+ layout->numPlanes = 1;
+ layout->rootPlanes = 1;
+ layout->planes[0] = {
+ // TODO: CHANNEL_UNKNOWN?
+ C2PlaneInfo::channel_t(0xFF), // channel
+ 1, // colInc
+ int32_t(mStride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ 0, // rootIx
+ 0, // offset
+ };
+ break;
+ }
}
mLocked = true;
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 74ef9ea..c07c09e 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -445,7 +445,7 @@
c2_status_t _createBlockPool(
C2PlatformAllocatorStore::id_t allocatorId,
- std::shared_ptr<const C2Component> component,
+ std::vector<std::shared_ptr<const C2Component>> components,
C2BlockPool::local_id_t poolId,
std::shared_ptr<C2BlockPool> *pool) {
std::shared_ptr<C2AllocatorStore> allocatorStore =
@@ -466,7 +466,9 @@
allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
case C2PlatformAllocatorStore::BLOB:
@@ -478,7 +480,9 @@
allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
case C2PlatformAllocatorStore::GRALLOC:
@@ -490,7 +494,9 @@
std::make_shared<C2PooledBlockPool>(allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
case C2PlatformAllocatorStore::BUFFERQUEUE:
@@ -502,7 +508,9 @@
allocator, poolId);
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
default:
@@ -513,7 +521,9 @@
if (res == C2_OK) {
*pool = ptr;
mBlockPools[poolId] = ptr;
- mComponents[poolId] = component;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
}
break;
}
@@ -522,9 +532,9 @@
c2_status_t createBlockPool(
C2PlatformAllocatorStore::id_t allocatorId,
- std::shared_ptr<const C2Component> component,
+ std::vector<std::shared_ptr<const C2Component>> components,
std::shared_ptr<C2BlockPool> *pool) {
- return _createBlockPool(allocatorId, component, mBlockPoolSeqId++, pool);
+ return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
}
bool getBlockPool(
@@ -540,8 +550,13 @@
mBlockPools.erase(it);
mComponents.erase(blockPoolId);
} else {
- auto found = mComponents.find(blockPoolId);
- if (component == found->second.lock()) {
+ auto found = std::find_if(
+ mComponents[blockPoolId].begin(),
+ mComponents[blockPoolId].end(),
+ [component](const std::weak_ptr<const C2Component> &ptr) {
+ return component == ptr.lock();
+ });
+ if (found != mComponents[blockPoolId].end()) {
*pool = ptr;
return true;
}
@@ -554,7 +569,7 @@
C2BlockPool::local_id_t mBlockPoolSeqId;
std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
- std::map<C2BlockPool::local_id_t, std::weak_ptr<const C2Component>> mComponents;
+ std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
};
static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
@@ -594,7 +609,7 @@
// TODO: remove this. this is temporary
case C2BlockPool::PLATFORM_START:
res = sBlockPoolCache->_createBlockPool(
- C2PlatformAllocatorStore::BUFFERQUEUE, component, id, pool);
+ C2PlatformAllocatorStore::BUFFERQUEUE, {component}, id, pool);
break;
default:
break;
@@ -604,12 +619,22 @@
c2_status_t CreateCodec2BlockPool(
C2PlatformAllocatorStore::id_t allocatorId,
+ const std::vector<std::shared_ptr<const C2Component>> &components,
+ std::shared_ptr<C2BlockPool> *pool) {
+ pool->reset();
+
+ std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
+ return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
+}
+
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
std::shared_ptr<const C2Component> component,
std::shared_ptr<C2BlockPool> *pool) {
pool->reset();
std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
- return sBlockPoolCache->createBlockPool(allocatorId, component, pool);
+ return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
}
class C2PlatformComponentStore : public C2ComponentStore {
@@ -957,58 +982,10 @@
std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
if (traits) {
- traits->name = intf->getName();
-
- C2ComponentKindSetting kind;
- C2ComponentDomainSetting domain;
- res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
- bool fixDomain = res != C2_OK;
- if (res == C2_OK) {
- traits->kind = kind.value;
- traits->domain = domain.value;
- } else {
- // TODO: remove this fall-back
- ALOGD("failed to query interface for kind and domain: %d", res);
-
- traits->kind =
- (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
- (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
- C2Component::KIND_OTHER;
- }
-
- uint32_t mediaTypeIndex =
- traits->kind == C2Component::KIND_ENCODER ? C2PortMediaTypeSetting::output::PARAM_TYPE
- : C2PortMediaTypeSetting::input::PARAM_TYPE;
- std::vector<std::unique_ptr<C2Param>> params;
- res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms);
- if (res != C2_OK) {
- ALOGD("failed to query interface: %d", res);
+ if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
+ ALOGD("Failed to fill traits from interface");
return mInit;
}
- if (params.size() != 1u) {
- ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
- return mInit;
- }
- C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
- if (mediaTypeConfig == nullptr) {
- ALOGD("failed to query media type");
- return mInit;
- }
- traits->mediaType =
- std::string(mediaTypeConfig->m.value,
- strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
-
- if (fixDomain) {
- if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
- traits->domain = C2Component::DOMAIN_AUDIO;
- } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
- traits->domain = C2Component::DOMAIN_VIDEO;
- } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
- traits->domain = C2Component::DOMAIN_IMAGE;
- } else {
- traits->domain = C2Component::DOMAIN_OTHER;
- }
- }
// TODO: get this properly from the store during emplace
switch (traits->domain) {
@@ -1018,26 +995,6 @@
default:
traits->rank = 512;
}
-
- params.clear();
- res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, ¶ms);
- if (res == C2_OK && params.size() == 1u) {
- C2ComponentAliasesSetting *aliasesSetting =
- C2ComponentAliasesSetting::From(params[0].get());
- if (aliasesSetting) {
- // Split aliases on ','
- // This looks simpler in plain C and even std::string would still make a copy.
- char *aliases = ::strndup(aliasesSetting->m.value, aliasesSetting->flexCount());
- ALOGD("'%s' has aliases: '%s'", intf->getName().c_str(), aliases);
-
- for (char *tok, *ptr, *str = aliases; (tok = ::strtok_r(str, ",", &ptr));
- str = nullptr) {
- traits->aliases.push_back(tok);
- ALOGD("adding alias: '%s'", tok);
- }
- free(aliases);
- }
- }
}
mTraits = traits;
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index 6d351c2..dc82e82 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -138,6 +138,23 @@
std::shared_ptr<C2BlockPool> *pool);
/**
+ * Creates a block pool.
+ * \param allocatorId the allocator ID which is used to allocate blocks
+ * \param components the components using the block pool
+ * \param pool pointer to where the created block pool shall be store on success.
+ * nullptr will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
+ const std::vector<std::shared_ptr<const C2Component>> &components,
+ std::shared_ptr<C2BlockPool> *pool);
+
+/**
* Returns the platform component store.
* \retval nullptr if the platform component store could not be obtained
*/
diff --git a/media/codec2/vndk/include/util/C2InterfaceUtils.h b/media/codec2/vndk/include/util/C2InterfaceUtils.h
index e9037e5..13bdac3 100644
--- a/media/codec2/vndk/include/util/C2InterfaceUtils.h
+++ b/media/codec2/vndk/include/util/C2InterfaceUtils.h
@@ -17,6 +17,7 @@
#ifndef C2UTILS_INTERFACE_UTILS_H_
#define C2UTILS_INTERFACE_UTILS_H_
+#include <C2Component.h>
#include <C2Param.h>
#include <C2Work.h>
@@ -1130,6 +1131,19 @@
};
+/**
+ * Utility class for C2ComponentInterface
+ */
+struct C2InterfaceUtils {
+ /**
+ * Create traits from C2ComponentInterface. Note that rank cannot be queried from interfaces,
+ * so left untouched.
+ */
+ static bool FillTraitsFromInterface(
+ C2Component::Traits *traits,
+ const std::shared_ptr<C2ComponentInterface> &intf);
+};
+
#include <util/C2Debug-interface.h>
#endif // C2UTILS_INTERFACE_UTILS_H_
diff --git a/media/codec2/vndk/util/C2InterfaceHelper.cpp b/media/codec2/vndk/util/C2InterfaceHelper.cpp
index 9eb52d2..19d2295 100644
--- a/media/codec2/vndk/util/C2InterfaceHelper.cpp
+++ b/media/codec2/vndk/util/C2InterfaceHelper.cpp
@@ -645,6 +645,7 @@
lateReadParams.emplace_back(p);
std::unique_ptr<C2Param> request(C2Param::CopyAsRequest(*p));
p = request.get();
+ paramIx = p->index();
paramRequests.emplace_back(std::move(request));
}
}
diff --git a/media/codec2/vndk/util/C2InterfaceUtils.cpp b/media/codec2/vndk/util/C2InterfaceUtils.cpp
index 0c1729b..b5bc691 100644
--- a/media/codec2/vndk/util/C2InterfaceUtils.cpp
+++ b/media/codec2/vndk/util/C2InterfaceUtils.cpp
@@ -21,6 +21,7 @@
#define C2_LOG_VERBOSE
+#include <C2Config.h>
#include <C2Debug.h>
#include <C2Param.h>
#include <C2ParamDef.h>
@@ -30,6 +31,7 @@
#include <cmath>
#include <limits>
#include <map>
+#include <sstream>
#include <type_traits>
#include <android-base/stringprintf.h>
@@ -1304,3 +1306,81 @@
return std::vector<Info>(location.begin(), location.end());
}
+//static
+bool C2InterfaceUtils::FillTraitsFromInterface(
+ C2Component::Traits *traits,
+ const std::shared_ptr<C2ComponentInterface> &intf) {
+ if (!traits) {
+ return false;
+ }
+ traits->name = intf->getName();
+
+ C2ComponentKindSetting kind;
+ C2ComponentDomainSetting domain;
+ c2_status_t res = intf->query_vb({ &kind, &domain }, {}, C2_MAY_BLOCK, nullptr);
+ bool fixDomain = res != C2_OK;
+ if (res == C2_OK) {
+ traits->kind = kind.value;
+ traits->domain = domain.value;
+ } else {
+ // TODO: remove this fall-back
+ C2_LOG(DEBUG) << "failed to query interface for kind and domain: " << res;
+
+ traits->kind =
+ (traits->name.find("encoder") != std::string::npos) ? C2Component::KIND_ENCODER :
+ (traits->name.find("decoder") != std::string::npos) ? C2Component::KIND_DECODER :
+ C2Component::KIND_OTHER;
+ }
+
+ uint32_t mediaTypeIndex = traits->kind == C2Component::KIND_ENCODER
+ ? C2PortMediaTypeSetting::output::PARAM_TYPE
+ : C2PortMediaTypeSetting::input::PARAM_TYPE;
+ std::vector<std::unique_ptr<C2Param>> params;
+ res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms);
+ if (res != C2_OK) {
+ C2_LOG(DEBUG) << "failed to query interface: " << res;
+ return false;
+ }
+ if (params.size() != 1u) {
+ C2_LOG(DEBUG) << "failed to query interface: unexpected vector size: " << params.size();
+ return false;
+ }
+ C2PortMediaTypeSetting *mediaTypeConfig = C2PortMediaTypeSetting::From(params[0].get());
+ if (mediaTypeConfig == nullptr) {
+ C2_LOG(DEBUG) << "failed to query media type";
+ return false;
+ }
+ traits->mediaType =
+ std::string(mediaTypeConfig->m.value,
+ strnlen(mediaTypeConfig->m.value, mediaTypeConfig->flexCount()));
+
+ if (fixDomain) {
+ if (strncmp(traits->mediaType.c_str(), "audio/", 6) == 0) {
+ traits->domain = C2Component::DOMAIN_AUDIO;
+ } else if (strncmp(traits->mediaType.c_str(), "video/", 6) == 0) {
+ traits->domain = C2Component::DOMAIN_VIDEO;
+ } else if (strncmp(traits->mediaType.c_str(), "image/", 6) == 0) {
+ traits->domain = C2Component::DOMAIN_IMAGE;
+ } else {
+ traits->domain = C2Component::DOMAIN_OTHER;
+ }
+ }
+
+ params.clear();
+ res = intf->query_vb({}, { C2ComponentAliasesSetting::PARAM_TYPE }, C2_MAY_BLOCK, ¶ms);
+ if (res == C2_OK && params.size() == 1u) {
+ C2ComponentAliasesSetting *aliasesSetting =
+ C2ComponentAliasesSetting::From(params[0].get());
+ if (aliasesSetting) {
+ std::istringstream iss(
+ std::string(aliasesSetting->m.value, aliasesSetting->flexCount()));
+ C2_LOG(DEBUG) << intf->getName() << " has aliases: " << iss.str();
+
+ for (std::string tok; std::getline(iss, tok, ','); ) {
+ traits->aliases.push_back(tok);
+ C2_LOG(DEBUG) << "adding alias: " << tok;
+ }
+ }
+ }
+ return true;
+}
diff --git a/media/codecs/amrnb/enc/src/pitch_fr.cpp b/media/codecs/amrnb/enc/src/pitch_fr.cpp
index 5a846fa..584f79b 100644
--- a/media/codecs/amrnb/enc/src/pitch_fr.cpp
+++ b/media/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/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
index 15d2feb..5cf1ed3 100644
--- a/media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
+++ b/media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -598,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 */
@@ -618,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/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 2593000..d1f92c1 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -1,6 +1,6 @@
cc_library {
name: "libflacextractor",
- defaults: ["extractor-defaults"],
+ defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
srcs: ["FLACExtractor.cpp"],
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 85d4cce..6a0ef22 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -1,7 +1,7 @@
cc_library {
name: "libwavextractor",
- defaults: ["extractor-defaults"],
+ defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
srcs: ["WAVExtractor.cpp"],
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 14578d6..74258a1 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1849,19 +1849,22 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
-
media::Int numSurroundFormatsAidl;
numSurroundFormatsAidl.value =
VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*numSurroundFormats));
std::vector<media::audio::common::AudioFormat> surroundFormatsAidl;
+ std::vector<bool> surroundFormatsEnabledAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- aps->getSurroundFormats(reported, &numSurroundFormatsAidl, &surroundFormatsAidl,
- surroundFormatsEnabled)));
+ aps->getSurroundFormats(reported, &numSurroundFormatsAidl,
+ &surroundFormatsAidl, &surroundFormatsEnabledAidl)));
+
*numSurroundFormats = VALUE_OR_RETURN_STATUS(
convertIntegral<unsigned int>(numSurroundFormatsAidl.value));
RETURN_STATUS_IF_ERROR(
convertRange(surroundFormatsAidl.begin(), surroundFormatsAidl.end(), surroundFormats,
aidl2legacy_AudioFormat_audio_format_t));
+ std::copy(surroundFormatsEnabledAidl.begin(), surroundFormatsEnabledAidl.end(),
+ surroundFormatsEnabled);
return OK;
}
@@ -1994,7 +1997,8 @@
}
status_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes& aa,
- product_strategy_t& productStrategy) {
+ product_strategy_t& productStrategy,
+ bool fallbackOnDefault) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -2003,7 +2007,8 @@
int32_t productStrategyAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- aps->getProductStrategyFromAudioAttributes(aaAidl, &productStrategyAidl)));
+ aps->getProductStrategyFromAudioAttributes(aaAidl, fallbackOnDefault,
+ &productStrategyAidl)));
productStrategy = VALUE_OR_RETURN_STATUS(
aidl2legacy_int32_t_product_strategy_t(productStrategyAidl));
return OK;
@@ -2022,7 +2027,8 @@
}
status_t AudioSystem::getVolumeGroupFromAudioAttributes(const AudioAttributes& aa,
- volume_group_t& volumeGroup) {
+ volume_group_t& volumeGroup,
+ bool fallbackOnDefault) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -2030,7 +2036,7 @@
legacy2aidl_AudioAttributes_AudioAttributesEx(aa));
int32_t volumeGroupAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- aps->getVolumeGroupFromAudioAttributes(aaAidl, &volumeGroupAidl)));
+ aps->getVolumeGroupFromAudioAttributes(aaAidl, fallbackOnDefault, &volumeGroupAidl)));
volumeGroup = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_volume_group_t(volumeGroupAidl));
return OK;
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 75dfc36..89fad5a 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -272,16 +272,17 @@
float getStreamVolumeDB(AudioStreamType stream, int index, int /* audio_devices_t */ device);
/**
- * Returns whether surround formats are enabled.
+ * Populates supported surround formats and their enabled state in formats and formatsEnabled.
*
* On input, count represents the maximum length of the returned array.
* On output, count is the total number of elements, which may be larger than the array size.
* Passing '0' on input and inspecting the value on output is a common way of determining the
* number of elements without actually retrieving them.
*/
- boolean getSurroundFormats(boolean reported,
- inout Int count,
- out AudioFormat[] formats);
+ void getSurroundFormats(boolean reported,
+ inout Int count,
+ out AudioFormat[] formats,
+ out boolean[] formatsEnabled);
AudioFormat[] getHwOffloadEncodingFormatsSupportedForA2DP();
@@ -296,10 +297,12 @@
boolean isHapticPlaybackSupported();
AudioProductStrategy[] listAudioProductStrategies();
- int /* product_strategy_t */ getProductStrategyFromAudioAttributes(in AudioAttributesEx aa);
+ int /* product_strategy_t */ getProductStrategyFromAudioAttributes(in AudioAttributesEx aa,
+ boolean fallbackOnDefault);
AudioVolumeGroup[] listAudioVolumeGroups();
- int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributesEx aa);
+ int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributesEx aa,
+ boolean fallbackOnDefault);
void setRttEnabled(boolean enabled);
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index edfc5a5..a8eb385 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -21,7 +21,7 @@
],
static_libs: [
"android.hardware.audio.common@7.0-enums",
- "effect-aidl-unstable-cpp",
+ "effect-aidl-cpp",
"libaudioclient",
"libbase",
"libcgrouprc",
@@ -33,16 +33,16 @@
"libmediametricsservice",
"libmedia_helper",
"libprocessgroup",
- "shared-file-region-aidl-unstable-cpp",
+ "shared-file-region-aidl-cpp",
],
shared_libs: [
"android.hardware.audio.common-util",
- "audioclient-types-aidl-unstable-cpp",
- "audioflinger-aidl-unstable-cpp",
- "audiopolicy-aidl-unstable-cpp",
- "audiopolicy-types-aidl-unstable-cpp",
- "av-types-aidl-unstable-cpp",
- "capture_state_listener-aidl-unstable-cpp",
+ "audioclient-types-aidl-cpp",
+ "audioflinger-aidl-cpp",
+ "audiopolicy-aidl-cpp",
+ "audiopolicy-types-aidl-cpp",
+ "av-types-aidl-cpp",
+ "capture_state_listener-aidl-cpp",
"libaudioclient_aidl_conversion",
"libaudioflinger",
"libaudiofoundation",
@@ -55,7 +55,7 @@
"libnblog",
"libutils",
"libxml2",
- "mediametricsservice-aidl-unstable-cpp",
+ "mediametricsservice-aidl-cpp",
],
header_libs: [
"libaudiofoundation_headers",
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index db4c28f..694f2d0 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -428,16 +428,17 @@
static bool isHapticPlaybackSupported();
static status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
- static status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
- product_strategy_t &productStrategy);
+ static status_t getProductStrategyFromAudioAttributes(
+ const AudioAttributes &aa, product_strategy_t &productStrategy,
+ bool fallbackOnDefault = true);
static audio_attributes_t streamTypeToAttributes(audio_stream_type_t stream);
static audio_stream_type_t attributesToStreamType(const audio_attributes_t &attr);
static status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
- static status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
- volume_group_t &volumeGroup);
+ static status_t getVolumeGroupFromAudioAttributes(
+ const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault = true);
static status_t setRttEnabled(bool enabled);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index a8fbe58..b9a3e29 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -265,6 +265,10 @@
(void)outputDevice;
(void)outputDeviceAddress;
#else
+#if MAJOR_VERSION >= 7
+ (void)HidlUtils::audioChannelMaskFromHal(
+ AUDIO_CHANNEL_NONE, true /*isInput*/, &sinkMetadata.tracks[0].channelMask);
+#endif
if (outputDevice != AUDIO_DEVICE_NONE) {
DeviceAddress hidlOutputDevice;
if (status_t status = CoreUtils::deviceAddressFromHal(
diff --git a/media/libeffects/lvm/benchmarks/Android.bp b/media/libeffects/lvm/benchmarks/Android.bp
index 930292f..4f11a8a 100644
--- a/media/libeffects/lvm/benchmarks/Android.bp
+++ b/media/libeffects/lvm/benchmarks/Android.bp
@@ -1,6 +1,7 @@
cc_benchmark {
name: "lvm_benchmark",
vendor: true,
+ host_supported: true,
srcs: ["lvm_benchmark.cpp"],
static_libs: [
"libbundlewrapper",
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 0ac9aa3..73c913b 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -9,6 +9,7 @@
},
vendor: true,
+ host_supported: true,
srcs: [
"StereoWidening/src/LVCS_BypassMix.cpp",
"StereoWidening/src/LVCS_Control.cpp",
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index f96928b..bcbe3e6 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -9,6 +9,7 @@
},
vendor: true,
+ host_supported: true,
srcs: ["Bundle/EffectBundle.cpp"],
cppflags: [
@@ -25,7 +26,6 @@
shared_libs: [
"libaudioutils",
"libcutils",
- "libdl",
"liblog",
],
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 865baad..c9d41ba 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -166,8 +166,8 @@
/* Effect Library Interface Implementation */
-extern "C" int EffectCreate(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId __unused,
- effect_handle_t* pHandle) {
+extern "C" int EffectCreate(const effect_uuid_t* uuid, int32_t sessionId,
+ int32_t /* ioId __unused */, effect_handle_t* pHandle) {
int ret = 0;
int sessionNo = -1;
int i;
@@ -1354,7 +1354,8 @@
//
//----------------------------------------------------------------------------
void VirtualizerGetSpeakerAngles(audio_channel_mask_t channelMask,
- audio_devices_t deviceType __unused, int32_t* pSpeakerAngles) {
+ audio_devices_t /* deviceType __unused */,
+ int32_t* pSpeakerAngles) {
// the channel count is guaranteed to be 1 or 2
// the device is guaranteed to be of type headphone
// this virtualizer is always using 2 virtual speakers at -90 and 90deg of azimuth, 0deg of
@@ -1495,8 +1496,8 @@
// pLow: lower band range
// pLow: upper band range
//----------------------------------------------------------------------------
-int32_t EqualizerGetBandFreqRange(EffectContext* pContext __unused, int32_t band, uint32_t* pLow,
- uint32_t* pHi) {
+int32_t EqualizerGetBandFreqRange(EffectContext* /* pContext __unused */, int32_t band,
+ uint32_t* pLow, uint32_t* pHi) {
*pLow = bandFreqRange[band][0];
*pHi = bandFreqRange[band][1];
return 0;
@@ -1519,7 +1520,7 @@
// pLow: lower band range
// pLow: upper band range
//----------------------------------------------------------------------------
-int32_t EqualizerGetBand(EffectContext* pContext __unused, uint32_t targetFreq) {
+int32_t EqualizerGetBand(EffectContext* /* pContext __unused */, uint32_t targetFreq) {
int band = 0;
if (targetFreq < bandFreqRange[0][0]) {
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index 5e8255a..ff897e8 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -18,6 +18,7 @@
"libaudioeffects",
"libhardware_headers",
],
+ gtest: false,
}
cc_test {
@@ -29,4 +30,5 @@
"-Werror",
"-Wextra",
],
+ gtest: false,
}
diff --git a/media/libeffects/preprocessing/tests/correlation.cpp b/media/libeffects/preprocessing/tests/correlation.cpp
index b13dcc7..eb56fc3 100644
--- a/media/libeffects/preprocessing/tests/correlation.cpp
+++ b/media/libeffects/preprocessing/tests/correlation.cpp
@@ -107,12 +107,19 @@
return EXIT_FAILURE;
}
- int numFrames = fileSize1 / sizeof(int16_t);
+ size_t numFrames = fileSize1 / sizeof(int16_t);
std::unique_ptr<int16_t[]> inBuffer1(new int16_t[numFrames]());
std::unique_ptr<int16_t[]> inBuffer2(new int16_t[numFrames]());
- fread(inBuffer1.get(), sizeof(int16_t), numFrames, fInput1.get());
- fread(inBuffer2.get(), sizeof(int16_t), numFrames, fInput2.get());
+ if (numFrames != fread(inBuffer1.get(), sizeof(int16_t), numFrames, fInput1.get())) {
+ printf("\nError: Unable to read %zu samples from file %s\n", numFrames, argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ if (numFrames != fread(inBuffer2.get(), sizeof(int16_t), numFrames, fInput2.get())) {
+ printf("\nError: Unable to read %zu samples from file %s\n", numFrames, argv[2]);
+ return EXIT_FAILURE;
+ }
auto pairAutoCorr1 = correlation(inBuffer1.get(), inBuffer1.get(), numFrames, enableCrossCorr);
auto pairAutoCorr2 = correlation(inBuffer2.get(), inBuffer2.get(), numFrames, enableCrossCorr);
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index e8839ba..1705c97 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -121,6 +121,11 @@
{"1080p", CAMCORDER_QUALITY_1080P},
{"2160p", CAMCORDER_QUALITY_2160P},
{"qvga", CAMCORDER_QUALITY_QVGA},
+ {"vga", CAMCORDER_QUALITY_VGA},
+ {"4kdci", CAMCORDER_QUALITY_4KDCI},
+ {"qhd", CAMCORDER_QUALITY_QHD},
+ {"2k", CAMCORDER_QUALITY_2K},
+ {"8kuhd", CAMCORDER_QUALITY_8KUHD},
{"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW},
{"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH},
@@ -131,6 +136,10 @@
{"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P},
{"timelapse2160p", CAMCORDER_QUALITY_TIME_LAPSE_2160P},
{"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA},
+ {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA},
+ {"timelapse4kdci", CAMCORDER_QUALITY_TIME_LAPSE_4KDCI},
+ {"timelapseqhd", CAMCORDER_QUALITY_TIME_LAPSE_QHD},
+ {"timelapse2k", CAMCORDER_QUALITY_TIME_LAPSE_2K},
{"highspeedlow", CAMCORDER_QUALITY_HIGH_SPEED_LOW},
{"highspeedhigh", CAMCORDER_QUALITY_HIGH_SPEED_HIGH},
@@ -138,19 +147,11 @@
{"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P},
{"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P},
{"highspeed2160p", CAMCORDER_QUALITY_HIGH_SPEED_2160P},
-
- // Vendor-specific profiles
- {"vga", CAMCORDER_QUALITY_VGA},
- {"4kdci", CAMCORDER_QUALITY_4KDCI},
- {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA},
- {"timelapse4kdci", CAMCORDER_QUALITY_TIME_LAPSE_4KDCI},
{"highspeedcif", CAMCORDER_QUALITY_HIGH_SPEED_CIF},
{"highspeedvga", CAMCORDER_QUALITY_HIGH_SPEED_VGA},
{"highspeed4kdci", CAMCORDER_QUALITY_HIGH_SPEED_4KDCI},
- {"qhd", CAMCORDER_QUALITY_QHD},
- {"2k", CAMCORDER_QUALITY_2k},
- {"timelapseqhd", CAMCORDER_QUALITY_TIME_LAPSE_QHD},
- {"timelapse2k", CAMCORDER_QUALITY_TIME_LAPSE_2k},
+
+ // Vendor-specific profiles
};
#if LOG_NDEBUG
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index 4cc5b95..7f0b99d 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -37,8 +37,9 @@
CAMCORDER_QUALITY_VGA = 9,
CAMCORDER_QUALITY_4KDCI = 10,
CAMCORDER_QUALITY_QHD = 11,
- CAMCORDER_QUALITY_2k = 12,
- CAMCORDER_QUALITY_LIST_END = 12,
+ CAMCORDER_QUALITY_2K = 12,
+ CAMCORDER_QUALITY_8KUHD = 13,
+ CAMCORDER_QUALITY_LIST_END = 13,
CAMCORDER_QUALITY_TIME_LAPSE_LIST_START = 1000,
CAMCORDER_QUALITY_TIME_LAPSE_LOW = 1000,
@@ -53,8 +54,9 @@
CAMCORDER_QUALITY_TIME_LAPSE_VGA = 1009,
CAMCORDER_QUALITY_TIME_LAPSE_4KDCI = 1010,
CAMCORDER_QUALITY_TIME_LAPSE_QHD = 1011,
- CAMCORDER_QUALITY_TIME_LAPSE_2k = 1012,
- CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1012,
+ CAMCORDER_QUALITY_TIME_LAPSE_2K = 1012,
+ CAMCORDER_QUALITY_TIME_LAPSE_8KUHD = 1013,
+ CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1013,
CAMCORDER_QUALITY_HIGH_SPEED_LIST_START = 2000,
CAMCORDER_QUALITY_HIGH_SPEED_LOW = 2000,
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 3dfd850..06e67ad 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -16,7 +16,7 @@
"libcutils",
"liblog",
"libutils",
- "mediametricsservice-aidl-unstable-cpp",
+ "mediametricsservice-aidl-cpp",
],
export_include_dirs: ["include"],
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
index f4371fd..a8350ea 100644
--- a/media/libmediametrics/MediaMetricsItem.cpp
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -285,6 +285,7 @@
status_t status = writeToByteString(&str, &size);
if (status == NO_ERROR) {
status = submitBuffer(str, size);
+ free(str);
}
if (status != NO_ERROR) {
ALOGW("%s: failed to record: %s", __func__, this->toString().c_str());
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index ab6863f..45f2f97 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
srcs: [
"ActivityManager.cpp",
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
index d08c66d..04477c6 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
@@ -23,26 +23,47 @@
],
include_dirs: [
- "system/media/audio/include",
- "frameworks/av/include",
- "frameworks/av/camera/include",
"frameworks/av/media/libmediaplayerservice",
- "frameworks/av/media/libmediametrics/include",
- "frameworks/av/media/ndk/include",
+ ],
+
+ static_libs: [
+ "libmediaplayerservice",
+ "libstagefright_httplive",
+ "libstagefright_rtsp",
],
shared_libs: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.omx@1.0",
+ "libbase",
+ "libandroid_net",
+ "libaudioclient",
+ "libbinder",
+ "libcamera_client",
+ "libcodec2_client",
+ "libcrypto",
+ "libcutils",
+ "libdatasource",
+ "libdl",
+ "libdrmframework",
+ "libgui",
+ "libhidlbase",
"liblog",
"libmedia",
- "libbinder",
- "libutils",
- "libmediaplayerservice",
- "libstagefright",
+ "libmedia_codeclist",
+ "libmedia_omx",
+ "libmediadrm",
"libmediandk",
+ "libmediametrics",
+ "libmediautils",
+ "libmemunreachable",
+ "libnetd_client",
+ "libpowermanager",
+ "libstagefright",
+ "libstagefright_foundation",
+ "libutils",
],
- compile_multilib: "prefer32",
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/AndroidTest.xml b/media/libmediaplayerservice/tests/stagefrightRecorder/AndroidTest.xml
new file mode 100644
index 0000000..427026d
--- /dev/null
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Test module config for StagefrightRecorder unit tests">
+ <option name="test-suite-tag" value="StagefrightRecorderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ <option name="force-root" value="true" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push"
+ value="StagefrightRecorderTest->/data/local/tmp/StagefrightRecorderTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="StagefrightRecorderTest" />
+ </test>
+</configuration>
diff --git a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
index 1a6e7ed..8d36e31 100644
--- a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
+++ b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
@@ -98,6 +98,9 @@
mTrackCursors[mExtractorTrackIndex].next.reset();
}
+ // Update the extractor's sample index even if this track reaches EOS, so that the other tracks
+ // are not given an incorrect extractor position.
+ mExtractorSampleIndex++;
if (!AMediaExtractor_advance(mExtractor)) {
LOG(DEBUG) << " EOS in advanceExtractor_l";
mEosReached = true;
@@ -108,7 +111,6 @@
}
mExtractorTrackIndex = AMediaExtractor_getSampleTrackIndex(mExtractor);
- mExtractorSampleIndex++;
SampleCursor& cursor = mTrackCursors[mExtractorTrackIndex];
if (mExtractorSampleIndex > cursor.previous.index) {
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 3d4ff15..d58d88d 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -234,7 +234,6 @@
lseek(fd, 0, SEEK_SET);
mSampleReader = MediaSampleReaderNDK::createFromFd(fd, 0 /* offset */, fileSize);
-
if (mSampleReader == nullptr) {
LOG(ERROR) << "Unable to parse source fd: " << fd;
return AMEDIA_ERROR_UNSUPPORTED;
diff --git a/media/libmediatranscoding/transcoder/NdkCommon.cpp b/media/libmediatranscoding/transcoder/NdkCommon.cpp
index a7b79dc..f5c9594 100644
--- a/media/libmediatranscoding/transcoder/NdkCommon.cpp
+++ b/media/libmediatranscoding/transcoder/NdkCommon.cpp
@@ -40,6 +40,9 @@
const char* TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate";
const char* TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES = "max-bframes";
+/* TODO(lnilsson): Finalize value or adopt AMediaFormat key once available. */
+const char* TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST = "color-transfer-request";
+
namespace AMediaFormatUtils {
#define DEFINE_FORMAT_VALUE_COPY_FUNC(_type, _typeName) \
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 994695f..04a513e 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -51,6 +51,32 @@
// Default frame rate.
static constexpr int32_t kDefaultFrameRate = 30;
+// Determines whether a track format describes HDR video content or not. The
+// logic is based on isHdr() in libstagefright/Utils.cpp.
+static bool isHdr(AMediaFormat* format) {
+ // If VUI signals HDR content, this internal flag is set by the extractor.
+ int32_t isHdr;
+ if (AMediaFormat_getInt32(format, "android._is-hdr", &isHdr)) {
+ return isHdr;
+ }
+
+ // If container supplied HDR static info without transfer set, assume HDR.
+ const char* hdrInfo;
+ int32_t transfer;
+ if ((AMediaFormat_getString(format, AMEDIAFORMAT_KEY_HDR_STATIC_INFO, &hdrInfo) ||
+ AMediaFormat_getString(format, "hdr10-plus-info", &hdrInfo)) &&
+ !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_TRANSFER, &transfer)) {
+ return true;
+ }
+
+ // Otherwise, check if an HDR transfer function is set.
+ if (AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_TRANSFER, &transfer)) {
+ return transfer == COLOR_TRANSFER_ST2084 || transfer == COLOR_TRANSFER_HLG;
+ }
+
+ return false;
+}
+
template <typename T>
void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
{
@@ -320,6 +346,14 @@
return AMEDIA_ERROR_INVALID_PARAMETER;
}
+ // Request decoder to convert HDR content to SDR.
+ const bool sourceIsHdr = isHdr(mSourceFormat.get());
+ if (sourceIsHdr) {
+ AMediaFormat_setInt32(decoderFormat.get(),
+ TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST,
+ COLOR_TRANSFER_SDR_VIDEO);
+ }
+
// Prevent decoder from overwriting frames that the encoder has not yet consumed.
AMediaFormat_setInt32(decoderFormat.get(), TBD_AMEDIACODEC_PARAMETER_KEY_ALLOW_FRAME_DROP, 0);
@@ -340,6 +374,25 @@
return status;
}
+ if (sourceIsHdr) {
+ bool supported = false;
+ AMediaFormat* inputFormat = AMediaCodec_getInputFormat(mDecoder);
+
+ if (inputFormat != nullptr) {
+ int32_t transferFunc;
+ supported = AMediaFormat_getInt32(inputFormat,
+ TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST,
+ &transferFunc) &&
+ transferFunc == COLOR_TRANSFER_SDR_VIDEO;
+ AMediaFormat_delete(inputFormat);
+ }
+
+ if (!supported) {
+ LOG(ERROR) << "HDR to SDR conversion unsupported by the codec";
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+ }
+
// Configure codecs to run in async mode.
AMediaCodecOnAsyncNotifyCallback asyncCodecCallbacks = {
.onAsyncInputAvailable = AsyncCodecCallbackDispatch::onAsyncInputAvailable,
diff --git a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h b/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
index 1a72be3..cc3399a 100644
--- a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
+++ b/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
@@ -45,11 +45,18 @@
static constexpr int COLOR_FormatYUV420Flexible = 0x7F420888;
static constexpr int COLOR_FormatSurface = 0x7f000789;
+// Color transfer functions defined by MediaCodecConstants.h but not in NDK
+static constexpr int32_t COLOR_TRANSFER_HLG = 7;
+static constexpr int32_t COLOR_TRANSFER_LINEAR = 1;
+static constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
+static constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
+
// constants not defined in NDK
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_ALLOW_FRAME_DROP;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES;
+extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST;
static constexpr int TBD_AMEDIACODEC_BUFFER_FLAG_KEY_FRAME = 0x1;
static constexpr int kBitrateModeConstant = 2;
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
index 11af0b1..3a499e5 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
@@ -272,6 +272,38 @@
compareSamples(tester.getSamples());
}
+/** Reads all samples except the last in each track, before finishing. */
+TEST_F(MediaSampleReaderNDKTests, TestLastSampleBeforeEOS) {
+ LOG(DEBUG) << "TestLastSampleBeforeEOS Starts";
+ initExtractorSamples();
+
+ { // Natural track order
+ SampleAccessTester tester{mSourceFd, mFileSize};
+ for (int trackIndex = 0; trackIndex < mTrackCount; ++trackIndex) {
+ tester.readSamplesAsync(trackIndex, mExtractorSamples[trackIndex].size() - 1);
+ }
+ tester.waitForTracks();
+ for (int trackIndex = 0; trackIndex < mTrackCount; ++trackIndex) {
+ tester.readSamplesAsync(trackIndex, SAMPLE_COUNT_ALL);
+ tester.waitForTrack(trackIndex);
+ }
+ compareSamples(tester.getSamples());
+ }
+
+ { // Reverse track order
+ SampleAccessTester tester{mSourceFd, mFileSize};
+ for (int trackIndex = mTrackCount - 1; trackIndex >= 0; --trackIndex) {
+ tester.readSamplesAsync(trackIndex, mExtractorSamples[trackIndex].size() - 1);
+ }
+ tester.waitForTracks();
+ for (int trackIndex = mTrackCount - 1; trackIndex >= 0; --trackIndex) {
+ tester.readSamplesAsync(trackIndex, SAMPLE_COUNT_ALL);
+ tester.waitForTrack(trackIndex);
+ }
+ compareSamples(tester.getSamples());
+ }
+}
+
/** Reads all samples from all tracks sequentially. */
TEST_F(MediaSampleReaderNDKTests, TestSequentialSampleAccess) {
LOG(DEBUG) << "TestSequentialSampleAccess Starts";
diff --git a/media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh b/media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
index 792c541..bba2bc5 100755
--- a/media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
+++ b/media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
@@ -1,8 +1,11 @@
#!/bin/bash
+
+# Exit on compilation error.
+set -e
+
#
# Run tests in this directory.
#
-
if [ "$SYNC_FINISHED" != true ]; then
if [ -z "$ANDROID_BUILD_TOP" ]; then
echo "Android build environment not set"
@@ -24,6 +27,9 @@
echo "========================================"
+# Don't exit if a test fails.
+set +e
+
echo "testing MediaSampleReaderNDK"
adb shell ASAN_OPTIONS=detect_container_overflow=0 /data/nativetest64/MediaSampleReaderNDKTests/MediaSampleReaderNDKTests
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 9c67338..d3ced29 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -619,6 +619,7 @@
constexpr int32_t COLOR_FormatYUV422SemiPlanar = 24;
constexpr int32_t COLOR_FormatYUV444Flexible = 0x7F444888;
constexpr int32_t COLOR_FormatYUV444Interleaved = 29;
+constexpr int32_t COLOR_FormatYUVP010 = 54;
constexpr int32_t COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00;
constexpr int32_t COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index 5418f10..7368ad9 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -75,7 +75,31 @@
ERROR_DRM_RESOURCE_CONTENTION = DRM_ERROR_BASE - 14,
ERROR_DRM_SESSION_LOST_STATE = DRM_ERROR_BASE - 15,
ERROR_DRM_INVALID_STATE = DRM_ERROR_BASE - 16,
- ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 16,
+
+ // New in S / drm@1.4:
+ ERROR_DRM_CERTIFICATE_MALFORMED = DRM_ERROR_BASE - 17,
+ ERROR_DRM_CERTIFICATE_MISSING = DRM_ERROR_BASE - 18,
+ ERROR_DRM_CRYPTO_LIBRARY = DRM_ERROR_BASE - 19,
+ ERROR_DRM_GENERIC_OEM = DRM_ERROR_BASE - 20,
+ ERROR_DRM_GENERIC_PLUGIN = DRM_ERROR_BASE - 21,
+ ERROR_DRM_INIT_DATA = DRM_ERROR_BASE - 22,
+ ERROR_DRM_KEY_NOT_LOADED = DRM_ERROR_BASE - 23,
+ ERROR_DRM_LICENSE_PARSE = DRM_ERROR_BASE - 24,
+ ERROR_DRM_LICENSE_POLICY = DRM_ERROR_BASE - 25,
+ ERROR_DRM_LICENSE_RELEASE = DRM_ERROR_BASE - 26,
+ ERROR_DRM_LICENSE_REQUEST_REJECTED = DRM_ERROR_BASE - 27,
+ ERROR_DRM_LICENSE_RESTORE = DRM_ERROR_BASE - 28,
+ ERROR_DRM_LICENSE_STATE = DRM_ERROR_BASE - 29,
+ ERROR_DRM_MEDIA_FRAMEWORK = DRM_ERROR_BASE - 30,
+ ERROR_DRM_PROVISIONING_CERTIFICATE = DRM_ERROR_BASE - 31,
+ ERROR_DRM_PROVISIONING_CONFIG = DRM_ERROR_BASE - 32,
+ ERROR_DRM_PROVISIONING_PARSE = DRM_ERROR_BASE - 33,
+ ERROR_DRM_PROVISIONING_RETRY = DRM_ERROR_BASE - 34,
+ ERROR_DRM_SECURE_STOP_RELEASE = DRM_ERROR_BASE - 35,
+ ERROR_DRM_STORAGE_READ = DRM_ERROR_BASE - 36,
+ ERROR_DRM_STORAGE_WRITE = DRM_ERROR_BASE - 37,
+ ERROR_DRM_ZERO_SUBSAMPLES = DRM_ERROR_BASE - 38,
+ ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 38,
ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500,
ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999,
diff --git a/media/libstagefright/renderfright/Android.bp b/media/libstagefright/renderfright/Android.bp
index c17f84e..7a71f52 100644
--- a/media/libstagefright/renderfright/Android.bp
+++ b/media/libstagefright/renderfright/Android.bp
@@ -23,7 +23,6 @@
"libEGL",
"libGLESv1_CM",
"libGLESv2",
- "libgui",
"liblog",
"libnativewindow",
"libprocessgroup",
diff --git a/media/libstagefright/renderfright/RenderEngine.cpp b/media/libstagefright/renderfright/RenderEngine.cpp
index c3fbb60..e96ffdb 100644
--- a/media/libstagefright/renderfright/RenderEngine.cpp
+++ b/media/libstagefright/renderfright/RenderEngine.cpp
@@ -18,7 +18,6 @@
#include <cutils/properties.h>
#include <log/log.h>
-#include <private/gui/SyncFeatures.h>
#include "gl/GLESRenderEngine.h"
#include "threaded/RenderEngineThreaded.h"
@@ -52,6 +51,39 @@
RenderEngine::~RenderEngine() = default;
+// static
+SyncFeatures &SyncFeatures::GetInstance() {
+ static SyncFeatures syncFeatures;
+ return syncFeatures;
+}
+
+bool SyncFeatures::useNativeFenceSync() const { return mHasNativeFenceSync; }
+bool SyncFeatures::useFenceSync() const { return mHasFenceSync; }
+bool SyncFeatures::useWaitSync() const { return mHasWaitSync; }
+
+SyncFeatures::SyncFeatures()
+ : mHasNativeFenceSync(false),
+ mHasFenceSync(false),
+ mHasWaitSync(false) {
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ // This can only be called after EGL has been initialized; otherwise the
+ // check below will abort.
+ const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+ LOG_ALWAYS_FATAL_IF(exts == nullptr, "eglQueryString failed");
+ if (strstr(exts, "EGL_ANDROID_native_fence_sync")) {
+ // This makes GLConsumer use the EGL_ANDROID_native_fence_sync
+ // extension to create Android native fences to signal when all
+ // GLES reads for a given buffer have completed.
+ mHasNativeFenceSync = true;
+ }
+ if (strstr(exts, "EGL_KHR_fence_sync")) {
+ mHasFenceSync = true;
+ }
+ if (strstr(exts, "EGL_KHR_wait_sync")) {
+ mHasWaitSync = true;
+ }
+}
+
namespace impl {
RenderEngine::RenderEngine(const RenderEngineCreationArgs& args) : mArgs(args) {}
@@ -59,11 +91,11 @@
RenderEngine::~RenderEngine() = default;
bool RenderEngine::useNativeFenceSync() const {
- return SyncFeatures::getInstance().useNativeFenceSync();
+ return SyncFeatures::GetInstance().useNativeFenceSync();
}
bool RenderEngine::useWaitSync() const {
- return SyncFeatures::getInstance().useWaitSync();
+ return SyncFeatures::GetInstance().useWaitSync();
}
} // namespace impl
diff --git a/media/libstagefright/renderfright/gl/GLESRenderEngine.cpp b/media/libstagefright/renderfright/gl/GLESRenderEngine.cpp
index 824bdd9..b7f8cb4 100644
--- a/media/libstagefright/renderfright/gl/GLESRenderEngine.cpp
+++ b/media/libstagefright/renderfright/gl/GLESRenderEngine.cpp
@@ -30,7 +30,6 @@
#include <android-base/stringprintf.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
-#include <gui/DebugEGLImageTracker.h>
#include <renderengine/Mesh.h>
#include <renderengine/Texture.h>
#include <renderengine/private/Description.h>
@@ -436,7 +435,6 @@
EGLImageKHR expired = mFramebufferImageCache.front().second;
mFramebufferImageCache.pop_front();
eglDestroyImageKHR(mEGLDisplay, expired);
- DEBUG_EGL_IMAGE_TRACKER_DESTROY();
}
eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
mImageCache.clear();
@@ -1012,15 +1010,11 @@
EGLImageKHR expired = mFramebufferImageCache.front().second;
mFramebufferImageCache.pop_front();
eglDestroyImageKHR(mEGLDisplay, expired);
- DEBUG_EGL_IMAGE_TRACKER_DESTROY();
}
mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
}
}
- if (image != EGL_NO_IMAGE_KHR) {
- DEBUG_EGL_IMAGE_TRACKER_CREATE();
- }
return image;
}
diff --git a/media/libstagefright/renderfright/gl/GLFramebuffer.cpp b/media/libstagefright/renderfright/gl/GLFramebuffer.cpp
index 383486b..d6582b3 100644
--- a/media/libstagefright/renderfright/gl/GLFramebuffer.cpp
+++ b/media/libstagefright/renderfright/gl/GLFramebuffer.cpp
@@ -22,7 +22,6 @@
#include <GLES/glext.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
-#include <gui/DebugEGLImageTracker.h>
#include <nativebase/nativebase.h>
#include <utils/Trace.h>
#include "GLESRenderEngine.h"
@@ -48,7 +47,6 @@
if (mEGLImage != EGL_NO_IMAGE_KHR) {
if (!usingFramebufferCache) {
eglDestroyImageKHR(mEGLDisplay, mEGLImage);
- DEBUG_EGL_IMAGE_TRACKER_DESTROY();
}
mEGLImage = EGL_NO_IMAGE_KHR;
mBufferWidth = 0;
diff --git a/media/libstagefright/renderfright/gl/GLImage.cpp b/media/libstagefright/renderfright/gl/GLImage.cpp
index 8497721..77e648e 100644
--- a/media/libstagefright/renderfright/gl/GLImage.cpp
+++ b/media/libstagefright/renderfright/gl/GLImage.cpp
@@ -20,7 +20,6 @@
#include <vector>
-#include <gui/DebugEGLImageTracker.h>
#include <log/log.h>
#include <utils/Trace.h>
#include "GLESRenderEngine.h"
@@ -59,7 +58,6 @@
if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) {
ALOGE("failed to destroy image: %#x", eglGetError());
}
- DEBUG_EGL_IMAGE_TRACKER_DESTROY();
mEGLImage = EGL_NO_IMAGE_KHR;
}
@@ -71,7 +69,6 @@
ALOGE("failed to create EGLImage: %#x", eglGetError());
return false;
}
- DEBUG_EGL_IMAGE_TRACKER_CREATE();
mProtected = isProtected;
}
diff --git a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
index 40fdff4..af2870f 100644
--- a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
+++ b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
@@ -302,6 +302,20 @@
status_t mStatus;
};
+class SyncFeatures {
+public:
+ static SyncFeatures &GetInstance();
+ bool useNativeFenceSync() const;
+ bool useFenceSync() const;
+ bool useWaitSync() const;
+
+private:
+ SyncFeatures();
+ bool mHasNativeFenceSync;
+ bool mHasFenceSync;
+ bool mHasWaitSync;
+};
+
namespace impl {
// impl::RenderEngine contains common implementation that is graphics back-end agnostic.
diff --git a/media/libstagefright/renderfright/threaded/RenderEngineThreaded.cpp b/media/libstagefright/renderfright/threaded/RenderEngineThreaded.cpp
index d4184fd..222d3ee 100644
--- a/media/libstagefright/renderfright/threaded/RenderEngineThreaded.cpp
+++ b/media/libstagefright/renderfright/threaded/RenderEngineThreaded.cpp
@@ -23,7 +23,6 @@
#include <future>
#include <android-base/stringprintf.h>
-#include <private/gui/SyncFeatures.h>
#include <utils/Trace.h>
#include "gl/GLESRenderEngine.h"
@@ -123,7 +122,7 @@
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& /*instance*/) {
ATRACE_NAME("REThreaded::useNativeFenceSync");
- bool returnValue = SyncFeatures::getInstance().useNativeFenceSync();
+ bool returnValue = SyncFeatures::GetInstance().useNativeFenceSync();
resultPromise.set_value(returnValue);
});
}
@@ -138,7 +137,7 @@
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& /*instance*/) {
ATRACE_NAME("REThreaded::useWaitSync");
- bool returnValue = SyncFeatures::getInstance().useWaitSync();
+ bool returnValue = SyncFeatures::GetInstance().useWaitSync();
resultPromise.set_value(returnValue);
});
}
diff --git a/media/libstagefright/tests/fuzzers/Android.bp b/media/libstagefright/tests/fuzzers/Android.bp
index 49ff69a..d39dd18 100644
--- a/media/libstagefright/tests/fuzzers/Android.bp
+++ b/media/libstagefright/tests/fuzzers/Android.bp
@@ -8,7 +8,9 @@
],
shared_libs: [
"libstagefright",
- "libstagefright_codecbase",
+ "libstagefright_codecbase",
+ "libbase",
+ "libcutils",
"libutils",
"libstagefright_foundation",
"libmedia",
@@ -16,7 +18,10 @@
"libmedia_omx",
"libgui",
"libbinder",
- "libcutils",
+ "liblog",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
],
}
@@ -51,3 +56,27 @@
],
defaults: ["libstagefright_fuzzer_defaults"],
}
+
+cc_fuzz {
+ name: "libstagefright_frameDecoder_fuzzer",
+ srcs: [
+ "FrameDecoderFuzzer.cpp",
+ ],
+ defaults: ["libstagefright_fuzzer_defaults"],
+}
+
+cc_fuzz {
+ name: "libstagefright_writer_fuzzer",
+ srcs: [
+ "FuzzerMediaUtility.cpp",
+ "WriterFuzzer.cpp",
+ ],
+ dictionary: "dictionaries/formats.dict",
+ defaults: ["libstagefright_fuzzer_defaults"],
+ static_libs: [
+ "libstagefright_webm",
+ "libdatasource",
+ "libstagefright_esds",
+ "libogg",
+ ],
+}
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
new file mode 100644
index 0000000..a628c70
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/FrameDecoder.h"
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/IMediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/AString.h>
+#include "FrameDecoderHelpers.h"
+#include "IMediaSourceFuzzImpl.h"
+
+namespace android {
+
+#define MAX_MEDIA_BUFFER_SIZE 2048
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ // Init our wrapper
+ FuzzedDataProvider fdp(data, size);
+
+ std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ AString componentName(name.c_str());
+ sp<MetaData> trackMeta = generateMetaData(&fdp);
+ sp<IMediaSource> source = new IMediaSourceFuzzImpl(&fdp, MAX_MEDIA_BUFFER_SIZE);
+
+ // Image or video Decoder?
+ sp<FrameDecoder> decoder;
+ bool isVideoDecoder = fdp.ConsumeBool();
+ if (isVideoDecoder) {
+ decoder = new VideoFrameDecoder(componentName, trackMeta, source);
+ } else {
+ decoder = new ImageDecoder(componentName, trackMeta, source);
+ }
+
+ while (fdp.remaining_bytes()) {
+ switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 3)) {
+ case 0:
+ decoder->init(/*frameTimeUs*/ fdp.ConsumeIntegral<int64_t>(),
+ /*option*/ fdp.ConsumeIntegral<int>(),
+ /*colorFormat*/ fdp.ConsumeIntegral<int>());
+ break;
+ case 1:
+ decoder->extractFrame();
+ break;
+ case 2: {
+ FrameRect rect;
+ rect.left = fdp.ConsumeIntegral<int32_t>();
+ rect.top = fdp.ConsumeIntegral<int32_t>();
+ rect.right = fdp.ConsumeIntegral<int32_t>();
+ rect.bottom = fdp.ConsumeIntegral<int32_t>();
+ decoder->extractFrame(&rect);
+ break;
+ }
+ case 3: {
+ sp<MetaData> trackMeta = generateMetaData(&fdp);
+ decoder->getMetadataOnly(trackMeta,
+ /*colorFormat*/ fdp.ConsumeIntegral<int>(),
+ /*thumbnail*/ fdp.ConsumeBool());
+ break;
+ }
+ }
+ }
+
+ generated_mime_types.clear();
+
+ return 0;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
new file mode 100644
index 0000000..228c04a
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
@@ -0,0 +1,90 @@
+
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <media/stagefright/MetaData.h>
+#include "MediaMimeTypes.h"
+
+#define MAX_METADATA_BUF_SIZE 512
+
+namespace android {
+
+std::vector<std::shared_ptr<char>> generated_mime_types;
+
+sp<MetaData> generateMetaData(FuzzedDataProvider *fdp) {
+ sp<MetaData> newMeta = new MetaData();
+
+ // random MIME Type
+ const char *mime_type;
+ size_t index = fdp->ConsumeIntegralInRange<size_t>(0, kMimeTypes.size());
+ // Let there be a chance of a true random string
+ if (index == kMimeTypes.size()) {
+ std::string mime_str = fdp->ConsumeRandomLengthString(64);
+ std::shared_ptr<char> mime_cstr(new char[mime_str.length()+1]);
+ generated_mime_types.push_back(mime_cstr);
+ strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1);
+ mime_type = mime_cstr.get();
+ } else {
+ mime_type = kMimeTypes[index];
+ }
+ newMeta->setCString(kKeyMIMEType, mime_type);
+
+ // Thumbnail time
+ newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral<int64_t>());
+
+ // Values used by allocVideoFrame
+ newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegral<int32_t>());
+ size_t profile_size =
+ fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE);
+ std::vector<uint8_t> profile_bytes =
+ fdp->ConsumeBytes<uint8_t>(profile_size);
+ newMeta->setData(kKeyIccProfile,
+ fdp->ConsumeIntegral<int32_t>(),
+ profile_bytes.empty() ? nullptr : profile_bytes.data(),
+ profile_bytes.size());
+ newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral<int32_t>());
+
+ // Values used by findThumbnailInfo
+ newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral<int32_t>());
+ size_t thumbnail_size =
+ fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE);
+ std::vector<uint8_t> thumb_bytes =
+ fdp->ConsumeBytes<uint8_t>(thumbnail_size);
+ newMeta->setData(kKeyThumbnailHVCC,
+ fdp->ConsumeIntegral<int32_t>(),
+ thumb_bytes.empty() ? nullptr : thumb_bytes.data(),
+ thumb_bytes.size());
+
+ // Values used by findGridInfo
+ newMeta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<int32_t>());
+
+ // A few functions perform a CHECK() that height/width are set
+ newMeta->setInt32(kKeyHeight, fdp->ConsumeIntegral<int32_t>());
+ newMeta->setInt32(kKeyWidth, fdp->ConsumeIntegral<int32_t>());
+
+ return newMeta;
+}
+
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
new file mode 100644
index 0000000..810ae95
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FuzzerMediaUtility.h"
+
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OggWriter.h>
+
+#include "MediaMimeTypes.h"
+#include "webm/WebmWriter.h"
+
+namespace android {
+std::string genMimeType(FuzzedDataProvider *dataProvider) {
+ uint8_t idx = dataProvider->ConsumeIntegralInRange<uint8_t>(0, kMimeTypes.size() - 1);
+ return std::string(kMimeTypes[idx]);
+}
+
+sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, std::string mimeType,
+ uint16_t maxDataAmount) {
+ uint32_t dataBlobSize = dataProvider->ConsumeIntegralInRange<uint16_t>(0, maxDataAmount);
+ std::vector<uint8_t> data = dataProvider->ConsumeBytes<uint8_t>(dataBlobSize);
+ // data:[<mediatype>][;base64],<data>
+ std::string uri("data:");
+ uri += mimeType;
+ // Currently libstagefright only accepts base64 uris
+ uri += ";base64,";
+ android::AString out;
+ android::encodeBase64(data.data(), data.size(), &out);
+ uri += out.c_str();
+
+ sp<DataSource> source =
+ DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri.c_str());
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return MediaExtractorFactory::Create(source);
+}
+
+sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize) {
+ std::string mime = genMimeType(dataProvider);
+ sp<IMediaExtractor> extractor = genMediaExtractor(dataProvider, mime, maxMediaBlobSize);
+
+ if (extractor == NULL) {
+ return NULL;
+ }
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *trackMime;
+ if (!strcasecmp(mime.c_str(), trackMime)) {
+ sp<IMediaSource> track = extractor->getTrack(i);
+ if (track == NULL) {
+ return NULL;
+ }
+ return new CallbackMediaSource(track);
+ }
+ }
+
+ return NULL;
+}
+
+sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> fileMeta) {
+ sp<MediaWriter> writer;
+ switch (writerType) {
+ case OGG:
+ writer = new OggWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ break;
+ case AAC:
+ writer = new AACWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ break;
+ case AAC_ADTS:
+ writer = new AACWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+ break;
+ case WEBM:
+ writer = new WebmWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ break;
+ case MPEG4:
+ writer = new MPEG4Writer(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ break;
+ case AMR_NB:
+ writer = new AMRWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ break;
+ case AMR_WB:
+ writer = new AMRWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ break;
+ case MPEG2TS:
+ writer = new MPEG2TSWriter(fd);
+ fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ break;
+ default:
+ return nullptr;
+ }
+ if (writer != nullptr) {
+ fileMeta->setInt32(kKeyRealTimeRecording, false);
+ }
+ return writer;
+}
+} // namespace android
\ No newline at end of file
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
new file mode 100644
index 0000000..98bfb94
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <datasource/DataSourceFactory.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <android/IMediaExtractor.h>
+#include <media/IMediaHTTPService.h>
+#include <media/mediarecorder.h>
+#include <media/stagefright/CallbackMediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <media/stagefright/MediaWriter.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/base64.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+enum StandardWriters {
+ OGG,
+ AAC,
+ AAC_ADTS,
+ WEBM,
+ MPEG4,
+ AMR_NB,
+ AMR_WB,
+ MPEG2TS,
+ // Allows FuzzedDataProvider to find the end of this enum.
+ kMaxValue = MPEG2TS,
+};
+
+std::string genMimeType(FuzzedDataProvider *dataProvider);
+sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
+sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);
+
+sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> fileMeta);
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
new file mode 100644
index 0000000..e769950
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IMEDIASOURCEFUZZIMPL_H
+#define IMEDIASOURCEFUZZIMPL_H
+
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+class IMediaSourceFuzzImpl : public IMediaSource {
+ public:
+ IMediaSourceFuzzImpl(FuzzedDataProvider *_fdp, size_t _max_buffer_size) :
+ fdp(_fdp),
+ max_buffer_size(_max_buffer_size) {}
+ status_t start(MetaData*) override { return 0; }
+ status_t stop() override { return 0; }
+ sp<MetaData> getFormat() override { return nullptr; }
+ status_t read(MediaBufferBase**,
+ const MediaSource::ReadOptions*) override;
+ status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t,
+ const MediaSource::ReadOptions*) override;
+ bool supportReadMultiple() override { return true; }
+ bool supportNonblockingRead() override { return true; }
+ status_t pause() override { return 0; }
+
+ protected:
+ IBinder* onAsBinder() { return nullptr; }
+
+ private:
+ FuzzedDataProvider *fdp;
+ std::vector<std::shared_ptr<MediaBufferBase>> buffer_bases;
+ const size_t max_buffer_size;
+};
+
+// This class is simply to expose the destructor
+class MediaBufferFuzzImpl : public MediaBuffer {
+ public:
+ MediaBufferFuzzImpl(void *data, size_t size) : MediaBuffer(data, size) {}
+ ~MediaBufferFuzzImpl() {}
+};
+
+status_t IMediaSourceFuzzImpl::read(MediaBufferBase **buffer,
+ const MediaSource::ReadOptions *options) {
+ Vector<MediaBufferBase*> buffers;
+ status_t ret = readMultiple(&buffers, 1, options);
+ *buffer = buffers.empty() ? nullptr : buffers[0];
+
+ return ret;
+}
+
+status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers,
+ uint32_t maxNumBuffers, const MediaSource::ReadOptions*) {
+ uint32_t num_buffers =
+ fdp->ConsumeIntegralInRange<uint32_t>(0, maxNumBuffers);
+ for(uint32_t i = 0; i < num_buffers; i++) {
+ std::vector<uint8_t> buf = fdp->ConsumeBytes<uint8_t>(
+ fdp->ConsumeIntegralInRange<size_t>(0, max_buffer_size));
+
+ std::shared_ptr<MediaBufferBase> mbb(
+ new MediaBufferFuzzImpl(buf.data(), buf.size()));
+
+ buffer_bases.push_back(mbb);
+ buffers->push_back(mbb.get());
+ }
+
+ // STATUS_OK
+ return 0;
+}
+
+} // namespace android
+
+#endif // IMEDIASOURCEFUZZIMPL_H
+
diff --git a/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp b/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp
index e473541..9b26f0b 100644
--- a/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/MediaClockFuzzer.cpp
@@ -17,52 +17,53 @@
// dylan.katz@leviathansecurity.com
#include <fuzzer/FuzzedDataProvider.h>
-#include <media/stagefright/MediaClock.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaClock.h>
namespace android {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- sp<MediaClock> mClock(new MediaClock);
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ sp<MediaClock> mClock(new MediaClock);
- bool registered = false;
- while (fdp.remaining_bytes() > 0) {
- switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 5)) {
- case 0: {
- if (registered == false) {
- mClock->init();
- registered = true;
- }
- break;
+ bool registered = false;
+ while (fdp.remaining_bytes() > 0) {
+ switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 5)) {
+ case 0: {
+ if (registered == false) {
+ mClock->init();
+ registered = true;
+ }
+ break;
+ }
+ case 1: {
+ int64_t startingTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ mClock->setStartingTimeMedia(startingTimeMediaUs);
+ break;
+ }
+ case 2: {
+ mClock->clearAnchor();
+ break;
+ }
+ case 3: {
+ int64_t anchorTimeRealUs = fdp.ConsumeIntegral<int64_t>();
+ int64_t anchorTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ mClock->updateAnchor(anchorTimeMediaUs, anchorTimeRealUs,
+ maxTimeMediaUs);
+ break;
+ }
+ case 4: {
+ int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
+ mClock->updateMaxTimeMedia(maxTimeMediaUs);
+ break;
+ }
+ case 5: {
+ wp<AMessage> msg(new AMessage);
+ mClock->setNotificationMessage(msg.promote());
+ }
+ }
}
- case 1: {
- int64_t startingTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- mClock->setStartingTimeMedia(startingTimeMediaUs);
- break;
- }
- case 2: {
- mClock->clearAnchor();
- break;
- }
- case 3: {
- int64_t anchorTimeRealUs = fdp.ConsumeIntegral<int64_t>();
- int64_t anchorTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- mClock->updateAnchor(anchorTimeMediaUs, anchorTimeRealUs, maxTimeMediaUs);
- break;
- }
- case 4: {
- int64_t maxTimeMediaUs = fdp.ConsumeIntegral<int64_t>();
- mClock->updateMaxTimeMedia(maxTimeMediaUs);
- break;
- }
- case 5: {
- wp<AMessage> msg(new AMessage);
- mClock->setNotificationMessage(msg.promote());
- }
- }
- }
- return 0;
+ return 0;
}
-} // namespace android
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
new file mode 100644
index 0000000..9f337ac
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FUZZER_MEDIAMIMETYPES_H_
+#define FUZZER_MEDIAMIMETYPES_H_
+
+#include <media/stagefright/foundation/MediaDefs.h>
+
+namespace android {
+
+static const std::vector<const char*> kMimeTypes {
+ MEDIA_MIMETYPE_IMAGE_JPEG,
+ MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
+ MEDIA_MIMETYPE_VIDEO_VP8,
+ MEDIA_MIMETYPE_VIDEO_VP9,
+ MEDIA_MIMETYPE_VIDEO_AV1,
+ MEDIA_MIMETYPE_VIDEO_AVC,
+ MEDIA_MIMETYPE_VIDEO_HEVC,
+ MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263,
+ MEDIA_MIMETYPE_VIDEO_MPEG2,
+ MEDIA_MIMETYPE_VIDEO_RAW,
+ MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
+ MEDIA_MIMETYPE_VIDEO_SCRAMBLED,
+ MEDIA_MIMETYPE_VIDEO_DIVX,
+ MEDIA_MIMETYPE_VIDEO_DIVX3,
+ MEDIA_MIMETYPE_VIDEO_XVID,
+ MEDIA_MIMETYPE_VIDEO_MJPEG,
+ MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_MPEG,
+ MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
+ MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ MEDIA_MIMETYPE_AUDIO_MIDI,
+ MEDIA_MIMETYPE_AUDIO_AAC,
+ MEDIA_MIMETYPE_AUDIO_QCELP,
+ MEDIA_MIMETYPE_AUDIO_VORBIS,
+ MEDIA_MIMETYPE_AUDIO_OPUS,
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ MEDIA_MIMETYPE_AUDIO_RAW,
+ MEDIA_MIMETYPE_AUDIO_FLAC,
+ MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
+ MEDIA_MIMETYPE_AUDIO_MSGSM,
+ MEDIA_MIMETYPE_AUDIO_AC3,
+ MEDIA_MIMETYPE_AUDIO_EAC3,
+ MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+ MEDIA_MIMETYPE_AUDIO_AC4,
+ MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
+ MEDIA_MIMETYPE_AUDIO_ALAC,
+ MEDIA_MIMETYPE_AUDIO_WMA,
+ MEDIA_MIMETYPE_AUDIO_MS_ADPCM,
+ MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
+ MEDIA_MIMETYPE_CONTAINER_MPEG4,
+ MEDIA_MIMETYPE_CONTAINER_WAV,
+ MEDIA_MIMETYPE_CONTAINER_OGG,
+ MEDIA_MIMETYPE_CONTAINER_MATROSKA,
+ MEDIA_MIMETYPE_CONTAINER_MPEG2TS,
+ MEDIA_MIMETYPE_CONTAINER_AVI,
+ MEDIA_MIMETYPE_CONTAINER_MPEG2PS,
+ MEDIA_MIMETYPE_CONTAINER_HEIF,
+ MEDIA_MIMETYPE_TEXT_3GPP,
+ MEDIA_MIMETYPE_TEXT_SUBRIP,
+ MEDIA_MIMETYPE_TEXT_VTT,
+ MEDIA_MIMETYPE_TEXT_CEA_608,
+ MEDIA_MIMETYPE_TEXT_CEA_708,
+ MEDIA_MIMETYPE_DATA_TIMED_ID3
+};
+
+} // namespace android
+
+#endif // FUZZER_MEDIAMIMETYPES_H_
diff --git a/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp b/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp
index a072b7c..c50c951 100644
--- a/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/StagefrightMediaScannerFuzzer.cpp
@@ -16,7 +16,6 @@
// Authors: corbin.souffrant@leviathansecurity.com
// dylan.katz@leviathansecurity.com
-#include <cutils/ashmem.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/StagefrightMediaScanner.h>
@@ -24,59 +23,39 @@
namespace android {
class FuzzMediaScannerClient : public MediaScannerClient {
-public:
- virtual status_t scanFile(const char *, long long, long long, bool, bool) {
- return 0;
- }
+ public:
+ virtual status_t scanFile(const char*, long long, long long, bool, bool) {
+ return 0;
+ }
- virtual status_t handleStringTag(const char *, const char *) { return 0; }
+ virtual status_t handleStringTag(const char*, const char*) { return 0; }
- virtual status_t setMimeType(const char *) { return 0; }
+ virtual status_t setMimeType(const char*) { return 0; }
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- StagefrightMediaScanner mScanner = StagefrightMediaScanner();
- // Without this, the fuzzer crashes for some reason.
- mScanner.setLocale("");
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ StagefrightMediaScanner mScanner = StagefrightMediaScanner();
+ // Without this, the fuzzer crashes for some reason.
+ mScanner.setLocale("");
- size_t data_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
- int fd =
- ashmem_create_region("stagefrightmediascanner_fuzz_region", data_size);
- if (fd < 0)
+ while (fdp.remaining_bytes() > 0) {
+ switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 1)) {
+ case 0: {
+ std::string path = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ std::string mimeType =
+ fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ std::shared_ptr<MediaScannerClient> client(new FuzzMediaScannerClient());
+ mScanner.processFile(path.c_str(), mimeType.c_str(), *client);
+ break;
+ }
+ case 1: {
+ int fd = fdp.ConsumeIntegral<int>();
+ if (fd >= 0 && fd <= 2) fd = 3;
+ mScanner.extractAlbumArt(fd);
+ }
+ }
+ }
return 0;
-
- uint8_t *sh_data = static_cast<uint8_t *>(
- mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
- if (sh_data == MAP_FAILED)
- return 0;
-
- while (fdp.remaining_bytes() > 8) {
- switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 1)) {
- case 0: {
- std::string path = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
- std::string mimeType =
- fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
- std::shared_ptr<MediaScannerClient> client(new FuzzMediaScannerClient());
- mScanner.processFile(path.c_str(), mimeType.c_str(), *client);
- break;
- }
- case 1: {
- size_t to_copy = fdp.ConsumeIntegralInRange<size_t>(1, data_size);
- std::vector<uint8_t> rand_buf = fdp.ConsumeBytes<uint8_t>(to_copy);
-
- // If fdp doesn't have enough bytes left it will just make a shorter
- // vector.
- to_copy = std::min(rand_buf.size(), data_size);
-
- std::copy(sh_data, sh_data + to_copy, rand_buf.begin());
- mScanner.extractAlbumArt(fd);
- }
- }
- }
-
- munmap(sh_data, data_size);
- close(fd);
- return 0;
}
-} // namespace android
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
new file mode 100644
index 0000000..03e9b43
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Authors: corbin.souffrant@leviathansecurity.com
+// dylan.katz@leviathansecurity.com
+
+#include <android-base/file.h>
+#include <ctype.h>
+#include <media/mediarecorder.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <stdlib.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+#include <functional>
+#include <string>
+
+#include "FuzzerMediaUtility.h"
+#include "fuzzer/FuzzedDataProvider.h"
+
+static constexpr uint16_t kMaxOperations = 5000;
+static constexpr uint8_t kMaxPackageNameLen = 50;
+// For other strings in mpeg we want a higher limit.
+static constexpr uint16_t kMaxMPEGStrLen = 1000;
+static constexpr uint16_t kMaxMediaBlobSize = 1000;
+
+namespace android {
+
+std::string getFourCC(FuzzedDataProvider *fdp) {
+ std::string fourCC = fdp->ConsumeRandomLengthString(4);
+ // Replace any existing nulls
+ for (size_t pos = 0; pos < fourCC.length(); pos++) {
+ if (fourCC.at(pos) == '\0') {
+ fourCC.replace(pos, 1, "a");
+ }
+ }
+
+ // If our string is too short, fill the remainder with "a"s.
+ while (fourCC.length() < 4) {
+ fourCC += 'a';
+ }
+ return fourCC;
+}
+
+typedef std::vector<std::function<void(FuzzedDataProvider*,
+ sp<MediaWriter>, sp<MetaData>, int tmpFileFd)>> OperationVec;
+typedef std::vector<std::function<void(FuzzedDataProvider*, MPEG4Writer*)>> MPEG4OperationVec;
+static const OperationVec operations = {
+ [](FuzzedDataProvider*, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->pause();
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
+ bool valid_fd = dataProvider->ConsumeBool();
+ int fd = -1;
+ if (valid_fd) {
+ fd = tmpFd;
+ }
+ // Args don't seem to be used
+ Vector<String16> args;
+ mediaWriter->dump(fd, args);
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
+ bool valid_fd = dataProvider->ConsumeBool();
+ int fd = -1;
+ if (valid_fd) {
+ fd = tmpFd;
+ }
+ mediaWriter->setNextFd(fd);
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setCaptureRate(dataProvider->ConsumeFloatingPoint<float>());
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setStartTimeOffsetMs(dataProvider->ConsumeIntegral<int>());
+
+ // Likely won't do much, but might as well as do a quick check
+ // while we're here.
+ mediaWriter->getStartTimeOffsetMs();
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
+ },
+ [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
+ mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
+ },
+};
+
+static const MPEG4OperationVec mpeg4Operations = {
+ [](FuzzedDataProvider*, MPEG4Writer *mediaWriter) { mediaWriter->notifyApproachingLimit(); },
+ // Lower level write methods.
+ // High-level startBox/endBox/etc are all called elsewhere,
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint8_t val = dataProvider->ConsumeIntegral<uint8_t>();
+ mediaWriter->writeInt8(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint16_t val = dataProvider->ConsumeIntegral<uint16_t>();
+ mediaWriter->writeInt16(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint32_t val = dataProvider->ConsumeIntegral<uint32_t>();
+ mediaWriter->writeInt32(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint64_t val = dataProvider->ConsumeIntegral<uint64_t>();
+ mediaWriter->writeInt64(val);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ std::string strVal = dataProvider->ConsumeRandomLengthString(kMaxMPEGStrLen);
+ mediaWriter->writeCString(strVal.c_str());
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ std::string fourCC = getFourCC(dataProvider);
+ mediaWriter->writeFourcc(fourCC.c_str());
+ },
+
+ // Misc setters
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint32_t layers = dataProvider->ConsumeIntegral<uint32_t>();
+ mediaWriter->setTemporalLayerCount(layers);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ uint32_t duration = dataProvider->ConsumeIntegral<uint32_t>();
+ mediaWriter->setInterleaveDuration(duration);
+ },
+ [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
+ int lat = dataProvider->ConsumeIntegral<int>();
+ int lon = dataProvider->ConsumeIntegral<int>();
+ mediaWriter->setGeoData(lat, lon);
+ },
+};
+
+// Not all writers can always add new sources, so we'll need additional checks.
+void addSource(FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter) {
+ sp<MediaSource> mediaSource = genMediaSource(dataProvider, kMaxMediaBlobSize);
+ if (mediaSource == NULL) {
+ // There's a static check preventing NULLs in addSource.
+ return;
+ }
+ mediaWriter->addSource(mediaSource);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ FuzzedDataProvider dataProvider(data, size);
+ TemporaryFile tf;
+ sp<MetaData> fileMeta = new MetaData;
+ StandardWriters writerType = dataProvider.ConsumeEnum<StandardWriters>();
+ sp<MediaWriter> writer = createWriter(tf.fd, writerType, fileMeta);
+
+ std::string packageName = dataProvider.ConsumeRandomLengthString(kMaxPackageNameLen);
+
+ sp<MediaRecorder> mr = new MediaRecorder(String16(packageName.c_str()));
+ writer->setListener(mr);
+
+ uint8_t baseOpLen = operations.size();
+ uint8_t totalLen = baseOpLen;
+ uint8_t maxSources;
+ // Different writers support different amounts of sources.
+ switch (writerType) {
+ case StandardWriters::AAC:
+ case StandardWriters::AAC_ADTS:
+ case StandardWriters::AMR_NB:
+ case StandardWriters::AMR_WB:
+ case StandardWriters::OGG:
+ maxSources = 1;
+ break;
+ case StandardWriters::WEBM:
+ maxSources = 2;
+ break;
+ default:
+ maxSources = UINT8_MAX;
+ break;
+ }
+ // Initialize some number of sources and add them to our writer.
+ uint8_t sourceCount = dataProvider.ConsumeIntegralInRange<uint8_t>(0, maxSources);
+ for (uint8_t i = 0; i < sourceCount; i++) {
+ addSource(&dataProvider, writer);
+ }
+
+ // Increase our range if additional operations are implemented.
+ // Currently only MPEG4 has additiona public operations on their writer.
+ if (writerType == StandardWriters::MPEG4) {
+ totalLen += mpeg4Operations.size();
+ }
+
+ // Many operations require the writer to be started.
+ writer->start(fileMeta.get());
+ for (size_t ops_run = 0; dataProvider.remaining_bytes() > 0 && ops_run < kMaxOperations - 1;
+ ops_run++) {
+ uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, totalLen - 1);
+ if (op < baseOpLen) {
+ operations[op](&dataProvider, writer, fileMeta, tf.fd);
+ } else if (writerType == StandardWriters::MPEG4) {
+ mpeg4Operations[op - baseOpLen](&dataProvider, (MPEG4Writer*)writer.get());
+ } else {
+ // Here just in case, will error out.
+ operations[op](&dataProvider, writer, fileMeta, tf.fd);
+ }
+ }
+ writer->stop();
+
+ writer.clear();
+ writer = nullptr;
+ return 0;
+}
+} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/dictionaries/formats.dict b/media/libstagefright/tests/fuzzers/dictionaries/formats.dict
new file mode 100644
index 0000000..4ab22de
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/dictionaries/formats.dict
@@ -0,0 +1,299 @@
+############################################################################################################
+# This file is a combination of these dictionaries: #
+# https://github.com/google/fuzzing/blob/0c48531c4d317cea9479b3ec1b0ddb9edc438c3a/dictionaries/mp4.dict #
+# https://github.com/google/fuzzing/blob/0c48531c4d317cea9479b3ec1b0ddb9edc438c3a/dictionaries/webm.dict #
+# https://github.com/google/fuzzing/blob/0c48531c4d317cea9479b3ec1b0ddb9edc438c3a/dictionaries/ogg.dict #
+# MPEG4, OGG, and WEBM are all formats used by MediaWriter. #
+############################################################################################################
+# mp4.dict
+# Taken from https://chromium.googlesource.com/chromium/src/+/master/media/test/mp4.dict
+FOURCC_NULL="\x00\x00\x00\x00"
+FOURCC_AC3 ="\x61\x63\x2d\x33"
+FOURCC_EAC3="\x65\x63\x2d\x33"
+FOURCC_AVC1="\x61\x76\x63\x31"
+FOURCC_AVC3="\x61\x76\x63\x33"
+FOURCC_AVCC="\x61\x76\x63\x43"
+FOURCC_BLOC="\x62\x6C\x6F\x63"
+FOURCC_CENC="\x63\x65\x6e\x63"
+FOURCC_CO64="\x63\x6f\x36\x34"
+FOURCC_CTTS="\x63\x74\x74\x73"
+FOURCC_DINF="\x64\x69\x6e\x66"
+FOURCC_EDTS="\x65\x64\x74\x73"
+FOURCC_EMSG="\x65\x6d\x73\x67"
+FOURCC_ELST="\x65\x6c\x73\x74"
+FOURCC_ENCA="\x65\x6e\x63\x61"
+FOURCC_ENCV="\x65\x6e\x63\x76"
+FOURCC_ESDS="\x65\x73\x64\x73"
+FOURCC_FREE="\x66\x72\x65\x65"
+FOURCC_FRMA="\x66\x72\x6d\x61"
+FOURCC_FTYP="\x66\x74\x79\x70"
+FOURCC_HDLR="\x68\x64\x6c\x72"
+FOURCC_HINT="\x68\x69\x6e\x74"
+FOURCC_HVC1="\x68\x76\x63\x31"
+FOURCC_HVCC="\x68\x76\x63\x43"
+FOURCC_IODS="\x69\x6f\x64\x73"
+FOURCC_MDAT="\x6d\x64\x61\x74"
+FOURCC_MDHD="\x6d\x64\x68\x64"
+FOURCC_MDIA="\x6d\x64\x69\x61"
+FOURCC_MECO="\x6d\x65\x63\x6f"
+FOURCC_MEHD="\x6d\x65\x68\x64"
+FOURCC_META="\x6d\x65\x74\x61"
+FOURCC_MFHD="\x6d\x66\x68\x64"
+FOURCC_MFRA="\x6d\x66\x72\x61"
+FOURCC_MINF="\x6d\x69\x6e\x66"
+FOURCC_MOOF="\x6d\x6f\x6f\x66"
+FOURCC_MOOV="\x6d\x6f\x6f\x76"
+FOURCC_MP4A="\x6d\x70\x34\x61"
+FOURCC_MP4V="\x6d\x70\x34\x76"
+FOURCC_MVEX="\x6d\x76\x65\x78"
+FOURCC_MVHD="\x6d\x76\x68\x64"
+FOURCC_PASP="\x70\x61\x73\x70"
+FOURCC_PDIN="\x70\x64\x69\x6e"
+FOURCC_PRFT="\x70\x72\x66\x74"
+FOURCC_PSSH="\x70\x73\x73\x68"
+FOURCC_SAIO="\x73\x61\x69\x6f"
+FOURCC_SAIZ="\x73\x61\x69\x7a"
+FOURCC_SBGP="\x73\x62\x67\x70"
+FOURCC_SCHI="\x73\x63\x68\x69"
+FOURCC_SCHM="\x73\x63\x68\x6d"
+FOURCC_SDTP="\x73\x64\x74\x70"
+FOURCC_SEIG="\x73\x65\x69\x67"
+FOURCC_SENC="\x73\x65\x6e\x63"
+FOURCC_SGPD="\x73\x67\x70\x64"
+FOURCC_SIDX="\x73\x69\x64\x78"
+FOURCC_SINF="\x73\x69\x6e\x66"
+FOURCC_SKIP="\x73\x6b\x69\x70"
+FOURCC_SMHD="\x73\x6d\x68\x64"
+FOURCC_SOUN="\x73\x6f\x75\x6e"
+FOURCC_SSIX="\x73\x73\x69\x78"
+FOURCC_STBL="\x73\x74\x62\x6c"
+FOURCC_STCO="\x73\x74\x63\x6f"
+FOURCC_STSC="\x73\x74\x73\x63"
+FOURCC_STSD="\x73\x74\x73\x64"
+FOURCC_STSS="\x73\x74\x73\x73"
+FOURCC_STSZ="\x73\x74\x73\x7a"
+FOURCC_STTS="\x73\x74\x74\x73"
+FOURCC_STYP="\x73\x74\x79\x70"
+FOURCC_TENC="\x74\x65\x6e\x63"
+FOURCC_TFDT="\x74\x66\x64\x74"
+FOURCC_TFHD="\x74\x66\x68\x64"
+FOURCC_TKHD="\x74\x6b\x68\x64"
+FOURCC_TRAF="\x74\x72\x61\x66"
+FOURCC_TRAK="\x74\x72\x61\x6b"
+FOURCC_TREX="\x74\x72\x65\x78"
+FOURCC_TRUN="\x74\x72\x75\x6e"
+FOURCC_UDTA="\x75\x64\x74\x61"
+FOURCC_UUID="\x75\x75\x69\x64"
+FOURCC_VIDE="\x76\x69\x64\x65"
+FOURCC_VMHD="\x76\x6d\x68\x64"
+FOURCC_WIDE="\x77\x69\x64\x65"
+
+# ogg.dict
+# https://xiph.org/vorbis/doc/Vorbis_I_spec.html
+
+header="OggS"
+
+# Codecs
+"BBCD\x00"
+"\x7fFLAC"
+"\x80theora"
+"\x01vorbis"
+"CELT "
+"CMML\x00\x00\x00\x00"
+"\x8bJNG\x0d\x0a\x1a\x0a"
+"\x80kate\x00\x00\x00"
+"OggMIDI\x00"
+"\x8aMNG\x0d\x0a\x1a\x0a"
+"PCM "
+"\x89PNG\x0d\x0a\x1a\x0a"
+"Speex "
+"YUV4MPEG"
+
+# Metadata
+"TITLE="
+"VERSION="
+"ALBUM="
+"TRACKNUMBER="
+"ARTIST="
+"PERFORMER="
+"COPYRIGHT="
+"LICENSE="
+"ORGANIZATION="
+"DESCRIPTION="
+"GENRE="
+"DATE="
+"LOCATION="
+"CONTACT="
+"ISRC="
+
+# webm.dict
+# Element IDs.
+IdAesSettingsCipherMode = "\x47\xE8"
+IdAlphaMode = "\x53\xC0"
+IdAspectRatioType = "\x54\xB3"
+IdAudio = "\xE1"
+IdBitDepth = "\x62\x64"
+IdBitsPerChannel = "\x55\xB2"
+IdBlock = "\xA1"
+IdBlockAddId = "\xEE"
+IdBlockAdditional = "\xA5"
+IdBlockAdditions = "\x75\xA1"
+IdBlockDuration = "\x9B"
+IdBlockGroup = "\xA0"
+IdBlockMore = "\xA6"
+IdBlockVirtual = "\xA2"
+IdCbSubsamplingHorz = "\x55\xB5"
+IdCbSubsamplingVert = "\x55\xB6"
+IdChannels = "\x9F"
+IdChapCountry = "\x43\x7E"
+IdChapLanguage = "\x43\x7C"
+IdChapString = "\x85"
+IdChapterAtom = "\xB6"
+IdChapterDisplay = "\x80"
+IdChapterStringUID = "\x56\x54"
+IdChapterStringUid = "\x56\x54"
+IdChapterTimeEnd = "\x92"
+IdChapterTimeStart = "\x91"
+IdChapterUID = "\x73\xC4"
+IdChapterUid = "\x73\xC4"
+IdChapters = "\x10\x43\xA7\x70"
+IdChromaSitingHorz = "\x55\xB7"
+IdChromaSitingVert = "\x55\xB8"
+IdChromaSubsamplingHorz = "\x55\xB3"
+IdChromaSubsamplingVert = "\x55\xB4"
+IdCluster = "\x1F\x43\xB6\x75"
+IdCodecDelay = "\x56\xAA"
+IdCodecID = "\x86"
+IdCodecName = "\x25\x86\x88"
+IdCodecPrivate = "\x63\xA2"
+IdColour = "\x55\xB0"
+IdContentEncAESSettings = "\x47\xE7"
+IdContentEncAesSettings = "\x47\xE7"
+IdContentEncAlgo = "\x47\xE1"
+IdContentEncKeyId = "\x47\xE2"
+IdContentEncoding = "\x62\x40"
+IdContentEncodingOrder = "\x50\x31"
+IdContentEncodingScope = "\x50\x32"
+IdContentEncodingType = "\x50\x33"
+IdContentEncodings = "\x6D\x80"
+IdContentEncryption = "\x50\x35"
+IdCueBlockNumber = "\x53\x78"
+IdCueClusterPosition = "\xF1"
+IdCueDuration = "\xB2"
+IdCuePoint = "\xBB"
+IdCueRelativePosition = "\xF0"
+IdCueTime = "\xB3"
+IdCueTrack = "\xF7"
+IdCueTrackPositions = "\xB7"
+IdCues = "\x1C\x53\xBB\x6B"
+IdDateUTC = "\x44\x61"
+IdDateUtc = "\x44\x61"
+IdDefaultDuration = "\x23\xE3\x83"
+IdDiscardPadding = "\x75\xA2"
+IdDisplayHeight = "\x54\xBA"
+IdDisplayUnit = "\x54\xB2"
+IdDisplayWidth = "\x54\xB0"
+IdDocType = "\x42\x82"
+IdDocTypeReadVersion = "\x42\x85"
+IdDocTypeVersion = "\x42\x87"
+IdDuration = "\x44\x89"
+IdEBML = "\x1A\x45\xDF\xA3"
+IdEBMLMaxIDLength = "\x42\xF2"
+IdEBMLMaxSizeLength = "\x42\xF3"
+IdEBMLReadVersion = "\x42\xF7"
+IdEBMLVersion = "\x42\x86"
+IdEbml = "\x1A\x45\xDF\xA3"
+IdEbmlMaxIdLength = "\x42\xF2"
+IdEbmlMaxSizeLength = "\x42\xF3"
+IdEbmlReadVersion = "\x42\xF7"
+IdEbmlVersion = "\x42\x86"
+IdEditionEntry = "\x45\xB9"
+IdFileUsedEndTime = "\x46\x62"
+IdFileUsedStartTime = "\x46\x61"
+IdFlagDefault = "\x88"
+IdFlagEnabled = "\xB9"
+IdFlagForced = "\x55\xAA"
+IdFlagInterlaced = "\x9A"
+IdFlagLacing = "\x9C"
+IdFrameRate = "\x23\x83\xE3"
+IdInfo = "\x15\x49\xA9\x66"
+IdLaceNumber = "\xCC"
+IdLanguage = "\x22\xB5\x9C"
+IdLuminanceMax = "\x55\xD9"
+IdLuminanceMin = "\x55\xDA"
+IdMasteringMetadata = "\x55\xD0"
+IdMatrixCoefficients = "\x55\xB1"
+IdMaxCll = "\x55\xBC"
+IdMaxFall = "\x55\xBD"
+IdMuxingApp = "\x4D\x80"
+IdName = "\x53\x6E"
+IdOutputSamplingFrequency = "\x78\xB5"
+IdPixelCropBottom = "\x54\xAA"
+IdPixelCropLeft = "\x54\xCC"
+IdPixelCropRight = "\x54\xDD"
+IdPixelCropTop = "\x54\xBB"
+IdPixelHeight = "\xBA"
+IdPixelWidth = "\xB0"
+IdPrevSize = "\xAB"
+IdPrimaries = "\x55\xBB"
+IdPrimaryBChromaticityX = "\x55\xD5"
+IdPrimaryBChromaticityY = "\x55\xD6"
+IdPrimaryGChromaticityX = "\x55\xD3"
+IdPrimaryGChromaticityY = "\x55\xD4"
+IdPrimaryRChromaticityX = "\x55\xD1"
+IdPrimaryRChromaticityY = "\x55\xD2"
+IdProjection = "\x76\x70"
+IdProjectionPosePitch = "\x76\x74"
+IdProjectionPoseRoll = "\x76\x75"
+IdProjectionPoseYaw = "\x76\x73"
+IdProjectionPrivate = "\x76\x72"
+IdProjectionType = "\x76\x71"
+IdRange = "\x55\xB9"
+IdReferenceBlock = "\xFB"
+IdSamplingFrequency = "\xB5"
+IdSeek = "\x4D\xBB"
+IdSeekHead = "\x11\x4D\x9B\x74"
+IdSeekID = "\x53\xAB"
+IdSeekPosition = "\x53\xAC"
+IdSeekPreRoll = "\x56\xBB"
+IdSegment = "\x18\x53\x80\x67"
+IdSimpleBlock = "\xA3"
+IdSimpleTag = "\x67\xC8"
+IdSliceDuration = "\xCF"
+IdSlices = "\x8E"
+IdStereoMode = "\x53\xB8"
+IdTag = "\x73\x73"
+IdTagBinary = "\x44\x85"
+IdTagDefault = "\x44\x84"
+IdTagLanguage = "\x44\x7A"
+IdTagName = "\x45\xA3"
+IdTagString = "\x44\x87"
+IdTagTrackUid = "\x63\xC5"
+IdTags = "\x12\x54\xC3\x67"
+IdTargetType = "\x63\xCA"
+IdTargetTypeValue = "\x68\xCA"
+IdTargets = "\x63\xC0"
+IdTimeSlice = "\xE8"
+IdTimecode = "\xE7"
+IdTimecodeScale = "\x2A\xD7\xB1"
+IdTitle = "\x7B\xA9"
+IdTrackEntry = "\xAE"
+IdTrackNumber = "\xD7"
+IdTrackType = "\x83"
+IdTrackUID = "\x73\xC5"
+IdTracks = "\x16\x54\xAE\x6B"
+IdTransferCharacteristics = "\x55\xBA"
+IdTrickMasterTrackSegmentUID = "\xC4"
+IdTrickMasterTrackUID = "\xC7"
+IdTrickTrackFlag = "\xC6"
+IdTrickTrackSegmentUID = "\xC1"
+IdTrickTrackUID = "\xC0"
+IdVideo = "\xE0"
+IdVoid = "\xEC"
+IdWhitePointChromaticityX = "\x55\xD7"
+IdWhitePointChromaticityY = "\x55\xD8"
+IdWritingApp = "\x57\x41"
+
+# Interesting sizes.
+SizeUnknown = "\xFF"
+
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
index 224aeb3..f1e504d 100644
--- a/media/libstagefright/writer_fuzzers/Android.bp
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -58,3 +58,59 @@
"WriterFuzzerBase.cpp",
],
}
+
+cc_fuzz {
+ name: "amrnb_writer_fuzzer",
+ defaults: ["writer-fuzzer-defaults"],
+ srcs: [
+ "amr_writer_fuzzer.cpp",
+ ],
+ cflags: [
+ "-DAMRNB",
+ ],
+}
+
+cc_fuzz {
+ name: "amrwb_writer_fuzzer",
+ defaults: ["writer-fuzzer-defaults"],
+ srcs: [
+ "amr_writer_fuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name : "mpeg4_writer_fuzzer",
+ defaults : ["writer-fuzzer-defaults"],
+ srcs : [
+ "mpeg4_writer_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_esds",
+ ],
+}
+
+cc_fuzz {
+ name : "ogg_writer_fuzzer",
+ defaults : ["writer-fuzzer-defaults"],
+ srcs : [
+ "ogg_writer_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libogg",
+ ],
+}
+
+cc_fuzz {
+ name : "webm_writer_fuzzer",
+ defaults : ["writer-fuzzer-defaults"],
+ srcs : [
+ "webm_writer_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_webm",
+ "libdatasource",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
+ ],
+}
diff --git a/media/libstagefright/writer_fuzzers/README.md b/media/libstagefright/writer_fuzzers/README.md
index 037236a..0d21031 100644
--- a/media/libstagefright/writer_fuzzers/README.md
+++ b/media/libstagefright/writer_fuzzers/README.md
@@ -1,7 +1,11 @@
# Fuzzer for writers
## Table of contents
- [libwriterfuzzerbase](#WriterFuzzerBase)
++ [libwriterfuzzerbase](#WriterFuzzerBase)
++ [Amr Writer](#amrWriterFuzzer)
++ [MPEG4 Writer](#mpeg4WriterFuzzer)
++ [OGG Writer](#oggWriterFuzzer)
++ [WEBM Writer](#webmWriterFuzzer)
# <a name="WriterFuzzerBase"></a> Fuzzer for libwriterfuzzerbase
All the writers have a common API - creating a writer, adding a source for
@@ -40,6 +44,56 @@
This ensures that the plugin tolerates any kind of input (huge,
malformed, etc) and thereby increasing the chance of identifying vulnerabilities.
+# <a name="amrWriterFuzzer"></a> Fuzzer for Amr Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for AMR writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the AMR writer class.
+
+##### Other considerations
+ * Two fuzzer binaries - amrnb_writer_fuzzer and amrwb_writer_fuzzer are generated based on the presence of a flag - 'AMRNB'
+
+# <a name="mpeg4WriterFuzzer"></a> Fuzzer for MPEG4 Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for MPEG4 writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the MPEG4 writer class.
+
+# <a name="oggWriterFuzzer"></a> Fuzzer for OGG Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for OGG writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the OGG writer class.
+
+# <a name="webmWriterFuzzer"></a> Fuzzer for WEBM Writer
+
+## Plugin Design Considerations
+The fuzzer plugin for WEBM writer uses the `WriterFuzzerBase` class and
+implements only the `createWriter` to create the WEBM writer class.
+
+## Build
+
+This describes steps to build writer fuzzer binaries.
+
+### Android
+
+`*` = amrnb/amrwb/mpeg4/ogg/webm
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) *_writer_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some media files to that folder
+Push this directory to device.
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/*_writer_fuzzer/*_writer_fuzzer CORPUS_DIR
+```
+
## References:
* http://llvm.org/docs/LibFuzzer.html
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
index 65593e7..844db39 100644
--- a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -218,7 +218,7 @@
}
}
-void WriterFuzzerBase::processData(const uint8_t *data, size_t size) {
+void WriterFuzzerBase::initFileWriterAndProcessData(const uint8_t *data, size_t size) {
if (!createOutputFile()) {
return;
}
diff --git a/media/libstagefright/writer_fuzzers/amr_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/amr_writer_fuzzer.cpp
new file mode 100644
index 0000000..bbb6f9f
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/amr_writer_fuzzer.cpp
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <media/stagefright/AMRWriter.h>
+
+using namespace android;
+
+class AmrWriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool AmrWriterFuzzer::createWriter() {
+ mWriter = new AMRWriter(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+#ifdef AMRNB
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+#else
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+#endif
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ AmrWriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
index d819d43..da06463 100644
--- a/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
+++ b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
@@ -107,7 +107,7 @@
void sendBuffersToWriter(sp<MediaAdapter>& currentTrack, int32_t trackIndex);
- void processData(const uint8_t* data, size_t size);
+ void initFileWriterAndProcessData(const uint8_t* data, size_t size);
protected:
class BufferSource {
diff --git a/media/libstagefright/writer_fuzzers/mpeg4_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/mpeg4_writer_fuzzer.cpp
new file mode 100644
index 0000000..99bd2b6
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/mpeg4_writer_fuzzer.cpp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <media/stagefright/MPEG4Writer.h>
+
+using namespace android;
+
+class Mpeg4WriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool Mpeg4WriterFuzzer::createWriter() {
+ mWriter = new MPEG4Writer(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ Mpeg4WriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/writer_fuzzers/ogg_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/ogg_writer_fuzzer.cpp
new file mode 100644
index 0000000..ae9c94c
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/ogg_writer_fuzzer.cpp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <media/stagefright/OggWriter.h>
+
+using namespace android;
+
+class OGGWriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool OGGWriterFuzzer::createWriter() {
+ mWriter = new OggWriter(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ OGGWriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/writer_fuzzers/webm_writer_fuzzer.cpp b/media/libstagefright/writer_fuzzers/webm_writer_fuzzer.cpp
new file mode 100644
index 0000000..0a91b72
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/webm_writer_fuzzer.cpp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include "WriterFuzzerBase.h"
+
+#include <webm/WebmWriter.h>
+
+using namespace android;
+
+class WEBMWriterFuzzer : public WriterFuzzerBase {
+ public:
+ bool createWriter();
+};
+
+bool WEBMWriterFuzzer::createWriter() {
+ mWriter = new WebmWriter(mFd);
+ if (!mWriter) {
+ return false;
+ }
+ mFileMeta = new MetaData;
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ WEBMWriterFuzzer writerFuzzer;
+ writerFuzzer.initFileWriterAndProcessData(data, size);
+ return 0;
+}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index ee4def5..6aed994 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -83,6 +83,7 @@
static_libs: [
"libgrallocusage",
+ "libnativehelper_lazy",
],
header_libs: [
@@ -111,7 +112,6 @@
"libgui",
"libui",
"libmediandk_utils",
- "libnativehelper",
],
export_header_lib_headers: ["jni_headers"],
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 941e3a1..eb6d510 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -40,18 +40,8 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-#ifndef __ANDROID__
-// Value copied from 'bionic/libc/include/android/api-level.h' which is not available on
-// non Android systems. It is set to 10000 which is same as __ANDROID_API_FUTURE__ value.
-#ifndef __ANDROID_API__
-#define __ANDROID_API__ 10000
-#endif
-
-// Value copied from 'bionic/libc/include/android/versioning.h' which is not available on
-// non Android systems
-#ifndef __INTRODUCED_IN
-#define __INTRODUCED_IN(api_level)
-#endif
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#include "NdkMediaError.h"
@@ -312,13 +302,11 @@
*/
extern const char* AMEDIAFORMAT_KEY_LOW_LATENCY __INTRODUCED_IN(30);
-#if __ANDROID_API__ >= 31
extern const char* AMEDIAFORMAT_KEY_HDR10_PLUS_INFO __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_SLOW_MOTION_MARKERS __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_CSD_AV1C __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_XMP_OFFSET __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_XMP_SIZE __INTRODUCED_IN(31);
-#endif /* __ANDROID_API__ >= 31 */
__END_DECLS
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 7c0f2ce..9132086 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -285,13 +285,14 @@
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
- virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
- product_strategy_t &productStrategy) = 0;
+ virtual status_t getProductStrategyFromAudioAttributes(
+ const AudioAttributes &aa, product_strategy_t &productStrategy,
+ bool fallbackOnDefault) = 0;
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
- virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
- volume_group_t &volumeGroup) = 0;
+ virtual status_t getVolumeGroupFromAudioAttributes(
+ const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault) = 0;
virtual bool isCallScreenModeSupported() = 0;
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 3e42e2d..9bef97c 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -53,7 +53,7 @@
audio_policy_dev_state_t /*state*/) override;
product_strategy_t getProductStrategyForAttributes(
- const audio_attributes_t &attr) const override;
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const override;
audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const override;
@@ -79,9 +79,11 @@
VolumeGroupVector getVolumeGroups() const override;
- volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const override;
+ volume_group_t getVolumeGroupForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const override;
- volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const override;
+ volume_group_t getVolumeGroupForStreamType(
+ audio_stream_type_t stream, bool fallbackOnDefault = true) const override;
status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const override;
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index c505456..54625ea 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -129,7 +129,8 @@
* @param attr
* @return applicable product strategy for the given attribute, default if none applicable.
*/
- product_strategy_t getProductStrategyForAttributes(const audio_attributes_t &attr) const;
+ product_strategy_t getProductStrategyForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const;
product_strategy_t getProductStrategyForStream(audio_stream_type_t stream) const;
@@ -153,9 +154,11 @@
std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;
- volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
+ volume_group_t getVolumeGroupForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const;
- volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
+ volume_group_t getVolumeGroupForStreamType(
+ audio_stream_type_t stream, bool fallbackOnDefault = true) const;
volume_group_t getDefaultVolumeGroup() const;
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 2137dd0..37e4caa 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -74,9 +74,10 @@
return NO_ERROR;
}
-product_strategy_t EngineBase::getProductStrategyForAttributes(const audio_attributes_t &attr) const
+product_strategy_t EngineBase::getProductStrategyForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault) const
{
- return mProductStrategies.getProductStrategyForAttributes(attr);
+ return mProductStrategies.getProductStrategyForAttributes(attr, fallbackOnDefault);
}
audio_stream_type_t EngineBase::getStreamTypeForAttributes(const audio_attributes_t &attr) const
@@ -320,14 +321,16 @@
return group;
}
-volume_group_t EngineBase::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+volume_group_t EngineBase::getVolumeGroupForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault) const
{
- return mProductStrategies.getVolumeGroupForAttributes(attr);
+ return mProductStrategies.getVolumeGroupForAttributes(attr, fallbackOnDefault);
}
-volume_group_t EngineBase::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+volume_group_t EngineBase::getVolumeGroupForStreamType(
+ audio_stream_type_t stream, bool fallbackOnDefault) const
{
- return mProductStrategies.getVolumeGroupForStreamType(stream);
+ return mProductStrategies.getVolumeGroupForStreamType(stream, fallbackOnDefault);
}
status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 060568a..d4cea5a 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -169,7 +169,7 @@
}
product_strategy_t ProductStrategyMap::getProductStrategyForAttributes(
- const audio_attributes_t &attr) const
+ const audio_attributes_t &attr, bool fallbackOnDefault) const
{
for (const auto &iter : *this) {
if (iter.second->matches(attr)) {
@@ -178,7 +178,7 @@
}
ALOGV("%s: No matching product strategy for attributes %s, return default", __FUNCTION__,
toString(attr).c_str());
- return getDefault();
+ return fallbackOnDefault? getDefault() : PRODUCT_STRATEGY_NONE;
}
audio_attributes_t ProductStrategyMap::getAttributesForStreamType(audio_stream_type_t stream) const
@@ -272,7 +272,8 @@
return at(psId)->getDeviceAddress();
}
-volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
+volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault) const
{
for (const auto &iter : *this) {
volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
@@ -280,10 +281,11 @@
return group;
}
}
- return getDefaultVolumeGroup();
+ return fallbackOnDefault ? getDefaultVolumeGroup() : VOLUME_GROUP_NONE;
}
-volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(audio_stream_type_t stream) const
+volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(
+ audio_stream_type_t stream, bool fallbackOnDefault) const
{
for (const auto &iter : *this) {
volume_group_t group = iter.second->getVolumeGroupForStreamType(stream);
@@ -292,7 +294,7 @@
}
}
ALOGW("%s: no volume group for %s, using default", __func__, toString(stream).c_str());
- return getDefaultVolumeGroup();
+ return fallbackOnDefault ? getDefaultVolumeGroup() : VOLUME_GROUP_NONE;
}
volume_group_t ProductStrategyMap::getDefaultVolumeGroup() const
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index a9b536b..f0a01d3 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -110,11 +110,12 @@
* Get the strategy selected for a given audio attributes.
*
* @param[in] audio attributes to get the selected @product_strategy_t followed by.
- *
+ * @param fallbackOnDefault if true, will return the fallback strategy if the attributes
+ * are not explicitly assigned to a given strategy.
* @return @product_strategy_t to be followed.
*/
virtual product_strategy_t getProductStrategyForAttributes(
- const audio_attributes_t &attr) const = 0;
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const = 0;
/**
* @brief getOutputDevicesForAttributes retrieves the devices to be used for given
@@ -271,19 +272,25 @@
* @brief getVolumeGroupForAttributes gets the appropriate volume group to be used for a given
* Audio Attributes.
* @param attr to be considered
+ * @param fallbackOnDefault if true, will return the fallback volume group if the attributes
+ * are not associated to any volume group.
* @return volume group associated to the given audio attributes, default group if none
* applicable, VOLUME_GROUP_NONE if no default group defined.
*/
- virtual volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const = 0;
+ virtual volume_group_t getVolumeGroupForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const = 0;
/**
* @brief getVolumeGroupForStreamType gets the appropriate volume group to be used for a given
* legacy stream type
* @param stream type to be considered
+ * @param fallbackOnDefault if true, will return the fallback volume group if the stream type
+ * is not associated to any volume group.
* @return volume group associated to the given stream type, default group if none applicable,
* VOLUME_GROUP_NONE if no default group defined.
*/
- virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
+ virtual volume_group_t getVolumeGroupForStreamType(
+ audio_stream_type_t stream, bool fallbackOnDefault = true) const = 0;
/**
* @brief listAudioVolumeGroups introspection API to get the Audio Volume Groups, aka
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 3e47324..b51918a 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -42,8 +42,8 @@
cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
"cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
"$(location buildPolicyCriterionTypes.py) " +
- // @todo update if 1428659 is merged "--androidaudiobaseheader $(location :android_audio_base_header_file) " +
- " --androidaudiobaseheader system/media/audio/include/system/audio-base.h " +
+ " --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
+ " --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
"--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
"--criteriontypes $(location :audio_policy_engine_criterion_types_template) " +
"--outputfile $(out)",
@@ -51,6 +51,8 @@
// The commented inputs must be provided to use this genrule_defaults
// @todo uncomment if 1428659 is merged":android_audio_base_header_file",
":audio_policy_engine_criterion_types_template",
+ ":libaudio_system_audio_base",
+ ":libaudio_system_audio_common_base",
// ":audio_policy_configuration_top_file",
// ":audio_policy_configuration_files",
],
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
index b8b60c1..b5885c0 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -55,6 +55,11 @@
metavar="ANDROID_AUDIO_BASE_HEADER",
type=argparse.FileType('r'),
required=True)
+ argparser.add_argument('--androidaudiocommonbaseheader',
+ help="Android Audio CommonBase C header file, Mandatory.",
+ metavar="ANDROID_AUDIO_COMMON_BASE_HEADER",
+ type=argparse.FileType('r'),
+ required=True)
argparser.add_argument('--audiopolicyconfigurationfile',
help="Android Audio Policy Configuration file, Mandatory.",
metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
@@ -176,12 +181,12 @@
# -Output devices type
# -Input devices type
#
-def parseAndroidAudioFile(androidaudiobaseheaderFile):
+def parseAndroidAudioFile(androidaudiobaseheaderFile, androidaudiocommonbaseheaderFile):
#
# Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
#
criterion_mapping_table = {
- 'AUDIO_MODE' : "AndroidModeType",
+ 'HAL_AUDIO_MODE' : "AndroidModeType",
'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
@@ -196,9 +201,9 @@
ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
criteria_pattern = re.compile(
- r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
- r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
- r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+ r"\s*V\((?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*,\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
@@ -209,27 +214,91 @@
androidaudiobaseheaderFile.name, line_number, line))
criterion_name = criterion_mapping_table[match.groupdict()['type']]
- literal = ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
- numerical_value = match.groupdict()['values']
+ criterion_literal = \
+ ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+ criterion_numerical_value = match.groupdict()['values']
- # for AUDIO_DEVICE_IN: need to remove sign bit
+ # for AUDIO_DEVICE_IN: need to remove sign bit / rename default to stub
if criterion_name == "InputDevicesMaskType":
- numerical_value = str(int(numerical_value, 0) & ~2147483648)
+ if criterion_literal == "Default":
+ criterion_numerical_value = str(int("0x40000000", 0))
+ else:
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("value {}:{} for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+ criterion_numerical_value = str(int(criterion_numerical_value, 0) & ~2147483648)
+
+ if criterion_name == "OutputDevicesMaskType":
+ if criterion_literal == "Default":
+ criterion_numerical_value = str(int("0x40000000", 0))
+
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
# Remove duplicated numerical values
- if int(numerical_value, 0) in all_criteria[criterion_name].values():
+ if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
logging.info("criterion {} duplicated values:".format(criterion_name))
- logging.info("{}:{}".format(numerical_value, literal))
+ logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
logging.info("KEEPING LATEST")
for key in list(all_criteria[criterion_name]):
- if all_criteria[criterion_name][key] == int(numerical_value, 0):
+ if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
del all_criteria[criterion_name][key]
- all_criteria[criterion_name][literal] = int(numerical_value, 0)
+ all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
logging.debug("type:{},".format(criterion_name))
- logging.debug("iteral:{},".format(literal))
- logging.debug("values:{}.".format(numerical_value))
+ logging.debug("iteral:{},".format(criterion_literal))
+ logging.debug("values:{}.".format(criterion_numerical_value))
+
+ logging.info("Checking Android Common Header file {}".format(androidaudiocommonbaseheaderFile))
+
+ criteria_pattern = re.compile(
+ r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+ for line_number, line in enumerate(androidaudiocommonbaseheaderFile):
+ match = criteria_pattern.match(line)
+ if match:
+ logging.debug("The following line is VALID: {}:{}\n{}".format(
+ androidaudiocommonbaseheaderFile.name, line_number, line))
+
+ criterion_name = criterion_mapping_table[match.groupdict()['type']]
+ criterion_literal = \
+ ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+ criterion_numerical_value = match.groupdict()['values']
+
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+
+ # Remove duplicated numerical values
+ if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+ logging.info("criterion {} duplicated values:".format(criterion_name))
+ logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+ logging.info("KEEPING LATEST")
+ for key in list(all_criteria[criterion_name]):
+ if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+ del all_criteria[criterion_name][key]
+
+ all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+ logging.debug("type:{},".format(criterion_name))
+ logging.debug("iteral:{},".format(criterion_literal))
+ logging.debug("values:{}.".format(criterion_numerical_value))
return all_criteria
@@ -238,7 +307,8 @@
logging.root.setLevel(logging.INFO)
args = parseArgs()
- all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader)
+ all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader,
+ args.androidaudiocommonbaseheader)
address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 340eca4..04bc5f1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1214,7 +1214,7 @@
(config->channel_mask == desc->getChannelMask()) &&
(session == desc->mDirectClientSession)) {
desc->mDirectOpenCount++;
- ALOGI("%s reusing direct output %d for session %d", __func__,
+ ALOGV("%s reusing direct output %d for session %d", __func__,
mOutputs.keyAt(i), session);
*output = mOutputs.keyAt(i);
return NO_ERROR;
@@ -2139,7 +2139,7 @@
*inputType = API_INPUT_LEGACY;
device = inputDesc->getDevice();
- ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
+ ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
goto exit;
}
@@ -3322,7 +3322,7 @@
status_t AudioPolicyManager::removeDevicesRoleForStrategy(product_strategy_t strategy,
device_role_t role)
{
- ALOGI("%s() strategy=%d role=%d", __func__, strategy, role);
+ ALOGV("%s() strategy=%d role=%d", __func__, strategy, role);
status_t status = mEngine->removeDevicesRoleForStrategy(strategy, role);
if (status != NO_ERROR) {
@@ -3424,7 +3424,7 @@
status_t AudioPolicyManager::setUserIdDeviceAffinities(int userId,
const AudioDeviceTypeAddrVector& devices) {
- ALOGI("%s() userId=%d num devices %zu", __func__, userId, devices.size());
+ ALOGV("%s() userId=%d num devices %zu", __func__, userId, devices.size());
if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
return BAD_VALUE;
}
@@ -3443,7 +3443,7 @@
}
status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) {
- ALOGI("%s() userId=%d", __FUNCTION__, userId);
+ ALOGV("%s() userId=%d", __FUNCTION__, userId);
status_t status = mPolicyMixes.removeUserIdDeviceAffinities(userId);
if (status != NO_ERROR) {
ALOGE("%s() Could not remove all device affinities fo userId = %d",
@@ -4945,7 +4945,8 @@
const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
if (availProfileDevices.isEmpty()) {
- ALOGE("%s: Input device list is empty!", __FUNCTION__);
+ ALOGV("%s: Input device list is empty! for profile %s",
+ __func__, inProfile->getTagName().c_str());
continue;
}
sp<AudioInputDescriptor> inputDesc =
@@ -6684,7 +6685,7 @@
for (auto it = channelMasks.begin(); it != channelMasks.end();) {
audio_channel_mask_t channelMask = *it;
if (channelMask & ~AUDIO_CHANNEL_OUT_STEREO) {
- ALOGI("%s: force NEVER, so remove channelMask 0x%08x", __FUNCTION__, channelMask);
+ ALOGV("%s: force NEVER, so remove channelMask 0x%08x", __FUNCTION__, channelMask);
it = channelMasks.erase(it);
} else {
++it;
@@ -6704,7 +6705,7 @@
// If not then add 5.1 support.
if (!supports5dot1) {
channelMasks.insert(AUDIO_CHANNEL_OUT_5POINT1);
- ALOGI("%s: force MANUAL or ALWAYS, so adding channelMask for 5.1 surround", __func__);
+ ALOGV("%s: force MANUAL or ALWAYS, so adding channelMask for 5.1 surround", __func__);
}
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index d3ceb1b..d0c8673 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -329,11 +329,14 @@
return mEngine->listAudioProductStrategies(strategies);
}
- virtual status_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa,
- product_strategy_t &productStrategy)
+ virtual status_t getProductStrategyFromAudioAttributes(
+ const AudioAttributes &aa, product_strategy_t &productStrategy,
+ bool fallbackOnDefault)
{
- productStrategy = mEngine->getProductStrategyForAttributes(aa.getAttributes());
- return productStrategy != PRODUCT_STRATEGY_NONE ? NO_ERROR : BAD_VALUE;
+ productStrategy = mEngine->getProductStrategyForAttributes(
+ aa.getAttributes(), fallbackOnDefault);
+ return (fallbackOnDefault && productStrategy == PRODUCT_STRATEGY_NONE) ?
+ BAD_VALUE : NO_ERROR;
}
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups)
@@ -341,11 +344,13 @@
return mEngine->listAudioVolumeGroups(groups);
}
- virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
- volume_group_t &volumeGroup)
+ virtual status_t getVolumeGroupFromAudioAttributes(
+ const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault)
{
- volumeGroup = mEngine->getVolumeGroupForAttributes(aa.getAttributes());
- return volumeGroup != VOLUME_GROUP_NONE ? NO_ERROR : BAD_VALUE;
+ volumeGroup = mEngine->getVolumeGroupForAttributes(
+ aa.getAttributes(), fallbackOnDefault);
+ return (fallbackOnDefault && volumeGroup == VOLUME_GROUP_NONE) ?
+ BAD_VALUE : NO_ERROR;
}
bool isCallScreenModeSupported() override;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index caf7309..07122cc 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1804,7 +1804,7 @@
Status AudioPolicyService::getSurroundFormats(
bool reported, media::Int* count,
std::vector<media::audio::common::AudioFormat>* formats,
- bool* _aidl_return) {
+ std::vector<bool>* formatsEnabled) {
unsigned int numSurroundFormats = VALUE_OR_RETURN_BINDER_STATUS(
convertIntegral<unsigned int>(count->value));
if (numSurroundFormats > MAX_ITEMS_PER_LIST) {
@@ -1812,6 +1812,7 @@
}
unsigned int numSurroundFormatsReq = numSurroundFormats;
std::unique_ptr<audio_format_t[]>surroundFormats(new audio_format_t[numSurroundFormats]);
+ std::unique_ptr<bool[]>surroundFormatsEnabled(new bool[numSurroundFormats]);
if (mAudioPolicyManager == NULL) {
return binderStatusFromStatusT(NO_INIT);
@@ -1820,11 +1821,15 @@
AutoCallerClear acc;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
mAudioPolicyManager->getSurroundFormats(&numSurroundFormats, surroundFormats.get(),
- _aidl_return, reported)));
+ surroundFormatsEnabled.get(), reported)));
numSurroundFormatsReq = std::min(numSurroundFormats, numSurroundFormatsReq);
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
convertRange(surroundFormats.get(), surroundFormats.get() + numSurroundFormatsReq,
std::back_inserter(*formats), legacy2aidl_audio_format_t_AudioFormat)));
+ formatsEnabled->insert(
+ formatsEnabled->begin(),
+ surroundFormatsEnabled.get(),
+ surroundFormatsEnabled.get() + numSurroundFormatsReq);
count->value = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<uint32_t>(numSurroundFormats));
return Status::ok();
}
@@ -1922,7 +1927,7 @@
}
Status AudioPolicyService::getProductStrategyFromAudioAttributes(
- const media::AudioAttributesEx& aaAidl, int32_t* _aidl_return) {
+ const media::AudioAttributesEx& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) {
AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioAttributesEx_AudioAttributes(aaAidl));
product_strategy_t productStrategy;
@@ -1932,8 +1937,8 @@
}
Mutex::Autolock _l(mLock);
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
- mAudioPolicyManager->getProductStrategyFromAudioAttributes(aa,
- productStrategy)));
+ mAudioPolicyManager->getProductStrategyFromAudioAttributes(
+ aa, productStrategy, fallbackOnDefault)));
*_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_product_strategy_t_int32_t(productStrategy));
return Status::ok();
@@ -1954,8 +1959,8 @@
return Status::ok();
}
-Status AudioPolicyService::getVolumeGroupFromAudioAttributes(const media::AudioAttributesEx& aaAidl,
- int32_t* _aidl_return) {
+Status AudioPolicyService::getVolumeGroupFromAudioAttributes(
+ const media::AudioAttributesEx& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) {
AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioAttributesEx_AudioAttributes(aaAidl));
volume_group_t volumeGroup;
@@ -1966,7 +1971,8 @@
Mutex::Autolock _l(mLock);
RETURN_IF_BINDER_ERROR(
binderStatusFromStatusT(
- mAudioPolicyManager->getVolumeGroupFromAudioAttributes(aa, volumeGroup)));
+ mAudioPolicyManager->getVolumeGroupFromAudioAttributes(
+ aa, volumeGroup, fallbackOnDefault)));
*_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_volume_group_t_int32_t(volumeGroup));
return Status::ok();
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index e25d542..a11b2cc 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -184,7 +184,7 @@
float* _aidl_return) override;
binder::Status getSurroundFormats(bool reported, media::Int* count,
std::vector<media::audio::common::AudioFormat>* formats,
- bool* _aidl_return) override;
+ std::vector<bool>* formatsEnabled) override;
binder::Status getHwOffloadEncodingFormatsSupportedForA2DP(
std::vector<media::audio::common::AudioFormat>* _aidl_return) override;
binder::Status setSurroundFormatEnabled(media::audio::common::AudioFormat audioFormat,
@@ -196,10 +196,12 @@
binder::Status listAudioProductStrategies(
std::vector<media::AudioProductStrategy>* _aidl_return) override;
binder::Status getProductStrategyFromAudioAttributes(const media::AudioAttributesEx& aa,
+ bool fallbackOnDefault,
int32_t* _aidl_return) override;
binder::Status listAudioVolumeGroups(
std::vector<media::AudioVolumeGroup>* _aidl_return) override;
binder::Status getVolumeGroupFromAudioAttributes(const media::AudioAttributesEx& aa,
+ bool fallbackOnDefault,
int32_t* _aidl_return) override;
binder::Status setRttEnabled(bool enabled) override;
binder::Status isCallScreenModeSupported(bool* _aidl_return) override;
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index ca2f0c6..df4389b 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <media/AudioSystem.h>
+#include <media/TypeConverter.h>
#include <system/audio.h>
#include <utils/Log.h>
@@ -70,10 +71,18 @@
ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
for (auto desc : manager.getConfig().getInputDevices()) {
- ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
+ if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
+ std::string deviceType;
+ (void)DeviceConverter::toString(desc->type(), deviceType);
+ ADD_FAILURE() << "Input device \"" << deviceType << "\" not found";
+ }
}
for (auto desc : manager.getConfig().getOutputDevices()) {
- ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
+ if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
+ std::string deviceType;
+ (void)DeviceConverter::toString(desc->type(), deviceType);
+ ADD_FAILURE() << "Output device \"" << deviceType << "\" not found";
+ }
}
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 641e463..1234dfd 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2937,10 +2937,21 @@
res == AppOpsManager::MODE_ERRORED ? "ERRORED" :
"UNKNOWN");
- if (res != AppOpsManager::MODE_ALLOWED) {
+ if (res == AppOpsManager::MODE_ERRORED) {
ALOGI("Camera %s: Access for \"%s\" revoked", mCameraIdStr.string(),
String8(mClientPackageName).string());
block();
+ } else if (res == AppOpsManager::MODE_IGNORED) {
+ bool isUidActive = sCameraService->mUidPolicy->isUidActive(mClientUid, mClientPackageName);
+ ALOGI("Camera %s: Access for \"%s\" has been restricted, isUidTrusted %d, isUidActive %d",
+ mCameraIdStr.string(), String8(mClientPackageName).string(),
+ mUidIsTrusted, isUidActive);
+ // If the calling Uid is trusted (a native service), or the client Uid is active (WAR for
+ // b/175320666), the AppOpsManager could return MODE_IGNORED. Do not treat such cases as
+ // error.
+ if (!mUidIsTrusted && !isUidActive) {
+ block();
+ }
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 7606d7d..3204217 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -4802,6 +4802,7 @@
ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
}
+ e = camera_metadata_ro_entry_t();
find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
isZslCapture = true;
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index b64f726..8e1a88b 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -100,7 +100,7 @@
"libmediametricsservice",
"libmediautils",
"libutils",
- "mediametricsservice-aidl-unstable-cpp",
+ "mediametricsservice-aidl-cpp",
],
header_libs: [
"libaudioutils_headers",
@@ -143,7 +143,7 @@
},
shared_libs: [
- "mediametricsservice-aidl-unstable-cpp",
+ "mediametricsservice-aidl-cpp",
"libbase", // android logging
"libbinder",
"libcutils",
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 6ac9d20..19ed919 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -43,7 +43,7 @@
"libstagefright",
"libstatslog",
"libutils",
- "mediametricsservice-aidl-unstable-cpp",
+ "mediametricsservice-aidl-cpp",
],
include_dirs: [
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
index 94112b0..e9d91c2 100644
--- a/services/mediametrics/tests/Android.bp
+++ b/services/mediametrics/tests/Android.bp
@@ -19,7 +19,7 @@
"libmediametricsservice",
"libmediautils",
"libutils",
- "mediametricsservice-aidl-unstable-cpp",
+ "mediametricsservice-aidl-cpp",
],
header_libs: [
diff --git a/services/tuner/TunerDemux.cpp b/services/tuner/TunerDemux.cpp
index 8346992..ba8d6a7 100644
--- a/services/tuner/TunerDemux.cpp
+++ b/services/tuner/TunerDemux.cpp
@@ -222,6 +222,8 @@
}
Result res = mDemux->close();
+ mDemux = NULL;
+
if (res != Result::SUCCESS) {
return Status::fromServiceSpecificError(static_cast<int32_t>(res));
}
diff --git a/services/tuner/TunerDescrambler.cpp b/services/tuner/TunerDescrambler.cpp
index 6b2889d..16338db 100644
--- a/services/tuner/TunerDescrambler.cpp
+++ b/services/tuner/TunerDescrambler.cpp
@@ -97,6 +97,8 @@
}
Result res = mDescrambler->close();
+ mDescrambler = NULL;
+
if (res != Result::SUCCESS) {
return Status::fromServiceSpecificError(static_cast<int32_t>(res));
}
diff --git a/services/tuner/TunerDvr.cpp b/services/tuner/TunerDvr.cpp
index c7227b6..db4e07b 100644
--- a/services/tuner/TunerDvr.cpp
+++ b/services/tuner/TunerDvr.cpp
@@ -154,6 +154,8 @@
}
Result res = mDvr->close();
+ mDvr = NULL;
+
if (res != Result::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
}
diff --git a/services/tuner/TunerFilter.cpp b/services/tuner/TunerFilter.cpp
index af5a600..dc9d246 100644
--- a/services/tuner/TunerFilter.cpp
+++ b/services/tuner/TunerFilter.cpp
@@ -285,6 +285,7 @@
.srcPort = static_cast<uint16_t>(ipConf.ipAddr.srcPort),
.dstPort = static_cast<uint16_t>(ipConf.ipAddr.dstPort),
};
+
ipConf.ipAddr.srcIpAddress.isIpV6
? ipAddr.srcIpAddress.v6(getIpV6Address(ipConf.ipAddr.srcIpAddress))
: ipAddr.srcIpAddress.v4(getIpV4Address(ipConf.ipAddr.srcIpAddress));
@@ -314,7 +315,7 @@
}
hidl_array<uint8_t, IP_V6_LENGTH> TunerFilter::getIpV6Address(TunerDemuxIpAddress addr) {
- hidl_array<uint8_t, IP_V6_LENGTH> ip = {0};
+ hidl_array<uint8_t, IP_V6_LENGTH> ip;
if (addr.addr.size() != IP_V6_LENGTH) {
return ip;
}
@@ -323,7 +324,7 @@
}
hidl_array<uint8_t, IP_V4_LENGTH> TunerFilter::getIpV4Address(TunerDemuxIpAddress addr) {
- hidl_array<uint8_t, IP_V4_LENGTH> ip = {0};
+ hidl_array<uint8_t, IP_V4_LENGTH> ip;
if (addr.addr.size() != IP_V4_LENGTH) {
return ip;
}
@@ -541,6 +542,9 @@
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
}
Result res = mFilter->close();
+ mFilter = NULL;
+ mFilter_1_1 = NULL;
+
if (res != Result::SUCCESS) {
return Status::fromServiceSpecificError(static_cast<int32_t>(res));
}
@@ -620,16 +624,17 @@
switch (eventExt.getDiscriminator()) {
case DemuxFilterEventExt::Event::hidl_discriminator::monitorEvent: {
getMonitorEvent(eventsExt, tunerEvent);
- break;
+ return;
}
case DemuxFilterEventExt::Event::hidl_discriminator::startId: {
getRestartEvent(eventsExt, tunerEvent);
- break;
+ return;
}
default: {
break;
}
}
+ return;
}
if (!events.empty()) {
@@ -889,9 +894,6 @@
tunerMonitor.set<TunerFilterMonitorEvent::cid>(static_cast<int>(monitorEvent.cid()));
break;
}
- default: {
- break;
- }
}
TunerFilterEvent tunerEvent;
diff --git a/services/tuner/TunerFrontend.cpp b/services/tuner/TunerFrontend.cpp
index b85e58b..74b5519 100644
--- a/services/tuner/TunerFrontend.cpp
+++ b/services/tuner/TunerFrontend.cpp
@@ -278,11 +278,13 @@
}
Result status = mFrontend->close();
- if (status == Result::SUCCESS) {
- return Status::ok();
- }
+ mFrontend = NULL;
+ mFrontend_1_1 = NULL;
- return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+ if (status != Result::SUCCESS) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return Status::ok();
}
Status TunerFrontend::getStatus(const vector<int32_t>& statusTypes,
@@ -804,13 +806,13 @@
case FrontendStatusExt1_1::hidl_discriminator::rollOff: {
switch (s.rollOff().getDiscriminator()) {
case FrontendRollOff::hidl_discriminator::dvbs:
- status.set<TunerFrontendStatus::interleaving>((int)s.rollOff().dvbs());
+ status.set<TunerFrontendStatus::rollOff>((int)s.rollOff().dvbs());
break;
case FrontendRollOff::hidl_discriminator::isdbs:
- status.set<TunerFrontendStatus::interleaving>((int)s.rollOff().isdbs());
+ status.set<TunerFrontendStatus::rollOff>((int)s.rollOff().isdbs());
break;
case FrontendRollOff::hidl_discriminator::isdbs3:
- status.set<TunerFrontendStatus::interleaving>((int)s.rollOff().isdbs3());
+ status.set<TunerFrontendStatus::rollOff>((int)s.rollOff().isdbs3());
break;
}
aidlStatus.push_back(status);
diff --git a/services/tuner/TunerLnb.cpp b/services/tuner/TunerLnb.cpp
index 0bfa3fd..4a5acf5 100644
--- a/services/tuner/TunerLnb.cpp
+++ b/services/tuner/TunerLnb.cpp
@@ -97,8 +97,13 @@
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
}
- Result status = mLnb->close();
- return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+ Result res = mLnb->close();
+ mLnb = NULL;
+
+ if (res != Result::SUCCESS) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return Status::ok();
}
/////////////// ILnbCallback ///////////////////////
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 4f6f16c..b80fd85 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -52,10 +52,10 @@
TunerService::TunerService() {}
TunerService::~TunerService() {}
-void TunerService::instantiate() {
+binder_status_t TunerService::instantiate() {
shared_ptr<TunerService> service =
::ndk::SharedRefBase::make<TunerService>();
- AServiceManager_addService(service->asBinder().get(), getServiceName());
+ return AServiceManager_addService(service->asBinder().get(), getServiceName());
}
bool TunerService::hasITuner() {
@@ -68,23 +68,20 @@
ALOGE("Failed to get ITuner service");
return false;
}
+ mTunerVersion = TUNER_HAL_VERSION_1_0;
+ mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::castFrom(mTuner);
+ if (mTuner_1_1 != nullptr) {
+ mTunerVersion = TUNER_HAL_VERSION_1_1;
+ } else {
+ ALOGE("Failed to get ITuner_1_1 service");
+ }
return true;
}
bool TunerService::hasITuner_1_1() {
ALOGD("hasITuner_1_1");
- if (mTuner_1_1 != nullptr) {
- return true;
- }
- if (!hasITuner()) {
- return false;
- }
- mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::castFrom(mTuner);
- if (mTuner_1_1 == nullptr) {
- ALOGE("Failed to get ITuner_1_1 service");
- return false;
- }
- return true;
+ hasITuner();
+ return (mTunerVersion == TUNER_HAL_VERSION_1_1);
}
Status TunerService::openDemux(
@@ -300,6 +297,12 @@
return Status::ok();
}
+Status TunerService::getTunerHalVersion(int* _aidl_return) {
+ hasITuner();
+ *_aidl_return = mTunerVersion;
+ return Status::ok();
+}
+
void TunerService::updateFrontendResources() {
hidl_vec<FrontendId> ids;
Result res = getHidlFrontendIds(ids);
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index ce085cb..cc65b39 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -69,6 +69,10 @@
namespace android {
+const static int TUNER_HAL_VERSION_UNKNOWN = 0;
+const static int TUNER_HAL_VERSION_1_0 = 1 << 16;
+const static int TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
+
typedef enum {
FRONTEND,
LNB,
@@ -93,7 +97,7 @@
public:
static char const *getServiceName() { return "media.tuner"; }
- static void instantiate();
+ static binder_status_t instantiate();
TunerService();
virtual ~TunerService();
@@ -110,6 +114,7 @@
Status openDescrambler(int32_t descramblerHandle,
std::shared_ptr<ITunerDescrambler>* _aidl_return) override;
Status updateTunerResources() override;
+ Status getTunerHalVersion(int* _aidl_return) override;
// TODO: create a map between resource id and handles.
static int getResourceIdFromHandle(int resourceHandle, int /*type*/) {
@@ -141,6 +146,8 @@
shared_ptr<ITunerResourceManager> mTunerResourceManager;
int mResourceRequestCount = 0;
+
+ int mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
};
} // namespace android
diff --git a/services/tuner/TunerTimeFilter.cpp b/services/tuner/TunerTimeFilter.cpp
index dce76d2..25e1ad9 100644
--- a/services/tuner/TunerTimeFilter.cpp
+++ b/services/tuner/TunerTimeFilter.cpp
@@ -18,6 +18,9 @@
#include "TunerTimeFilter.h"
+using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
+
namespace android {
TunerTimeFilter::TunerTimeFilter(sp<ITimeFilter> timeFilter) {
@@ -28,23 +31,76 @@
mTimeFilter = NULL;
}
-Status TunerTimeFilter::setTimeStamp(int64_t /*timeStamp*/) {
- return Status::ok();
+Status TunerTimeFilter::setTimeStamp(int64_t timeStamp) {
+ if (mTimeFilter == NULL) {
+ ALOGE("ITimeFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status = mTimeFilter->setTimeStamp(timeStamp);
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
Status TunerTimeFilter::clearTimeStamp() {
- return Status::ok();
+ if (mTimeFilter == NULL) {
+ ALOGE("ITimeFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status = mTimeFilter->clearTimeStamp();
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
-Status TunerTimeFilter::getSourceTime(int64_t* /*_aidl_return*/) {
- return Status::ok();
+Status TunerTimeFilter::getSourceTime(int64_t* _aidl_return) {
+ if (mTimeFilter == NULL) {
+ *_aidl_return = (int64_t)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ ALOGE("ITimeFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status;
+ mTimeFilter->getSourceTime(
+ [&](Result r, uint64_t t) {
+ status = r;
+ *_aidl_return = t;
+ });
+ if (status != Result::SUCCESS) {
+ *_aidl_return = (int64_t)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ }
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
-Status TunerTimeFilter::getTimeStamp(int64_t* /*_aidl_return*/) {
- return Status::ok();
+Status TunerTimeFilter::getTimeStamp(int64_t* _aidl_return) {
+ if (mTimeFilter == NULL) {
+ *_aidl_return = (int64_t)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ ALOGE("ITimeFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result status;
+ mTimeFilter->getTimeStamp(
+ [&](Result r, uint64_t t) {
+ status = r;
+ *_aidl_return = t;
+ });
+ if (status != Result::SUCCESS) {
+ *_aidl_return = (int64_t)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ }
+ return Status::fromServiceSpecificError(static_cast<int32_t>(status));
}
Status TunerTimeFilter::close() {
+ if (mTimeFilter == NULL) {
+ ALOGE("ITimeFilter is not initialized");
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Result res = mTimeFilter->close();
+ mTimeFilter = NULL;
+
+ if (res != Result::SUCCESS) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
return Status::ok();
}
} // namespace android
diff --git a/services/tuner/TunerTimeFilter.h b/services/tuner/TunerTimeFilter.h
index 50b8f54..d675319 100644
--- a/services/tuner/TunerTimeFilter.h
+++ b/services/tuner/TunerTimeFilter.h
@@ -19,6 +19,7 @@
#include <aidl/android/media/tv/tuner/BnTunerTimeFilter.h>
#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
#include <media/stagefright/foundation/ADebug.h>
#include <utils/Log.h>
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index bea8811..f1651b9 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -101,4 +101,11 @@
*/
// TODO: b/178124017 update TRM in TunerService independently.
void updateTunerResources();
+
+ /**
+ * Get an integer that carries the Tuner HIDL version. The high 16 bits are the
+ * major version number while the low 16 bits are the minor version. Default
+ * value is unknown version 0.
+ */
+ int getTunerHalVersion();
}
diff --git a/services/tuner/main_tunerservice.cpp b/services/tuner/main_tunerservice.cpp
index a0e7a9f..586a0e2 100644
--- a/services/tuner/main_tunerservice.cpp
+++ b/services/tuner/main_tunerservice.cpp
@@ -32,7 +32,11 @@
sp<IServiceManager> sm = defaultServiceManager();
ALOGD("ServiceManager: %p", sm.get());
- TunerService::instantiate();
+ binder_status_t status = TunerService::instantiate();
+ if (status != STATUS_OK) {
+ ALOGD("Failed to add tuner service as AIDL interface");
+ return -1;
+ }
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
diff --git a/tools/mainline_hook.sh b/tools/mainline_hook.sh
deleted file mode 100755
index 58afb49..0000000
--- a/tools/mainline_hook.sh
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/bash
-LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
-
-MAINLINE_FRAMEWORKS_AV_PATHS=(
- media/extractors/
- media/codec2/components/
- media/libstagefright/codecs/amrnb
- media/libstagefright/codecs/amrwb
- media/libstagefright/codecs/amrwbenc
- media/libstagefright/codecs/common
- media/libstagefright/codecs/mp3dec
- media/libstagefright/codecs/m4v_h263
- media/libstagefright/flac/dec
- media/libstagefright/mpeg2ts
-)
-
-MAINLINE_EXTERNAL_PROJECTS=(
- external/aac
- external/flac
- external/libaac
- external/libaom
- external/libavc
- external/libgav1
- external/libgsm
- external/libhevc
- external/libmpeg2
- external/libopus
- external/libvpx
- external/libxaac
- external/sonivox
- external/tremolo
-)
-
-DEV_BRANCH=qt-aml-media-dev
-RED=$(tput setaf 1)
-NORMAL=$(tput sgr0)
-WARNING_FULL="${RED}Please upload this change in ${DEV_BRANCH} unless it is restricted
-from mainline release until next dessert release. Low/moderate security bugs
-are restricted this way.${NORMAL}"
-WARNING_PARTIAL="${RED}It looks like your change has mainline and non-mainline changes;
-Consider separating them into two separate CLs -- one for mainline files,
-one for non-mainline files.${NORMAL}"
-PWD=`pwd`
-
-if git branch -vv | grep -q -P "^\*[^\[]+\[goog/qt-aml-media-dev"; then
- # Change appears to be in mainline dev branch
- exit 0
-fi
-
-for path in "${MAINLINE_EXTERNAL_PROJECTS[@]}"; do
- if [[ $PWD =~ $path ]]; then
- echo -e "${RED}The source of truth for '$path' is in ${DEV_BRANCH}.${NORMAL}"
- echo -e ${WARNING_FULL}
- exit 1
- fi
-done
-
-if [[ ! $PWD =~ frameworks/av ]]; then
- exit 0
-fi
-
-mainline_count=0
-total_count=0
-echo
-while read -r file ; do
- (( total_count++ ))
- for path in "${MAINLINE_FRAMEWORKS_AV_PATHS[@]}"; do
- if [[ $file =~ ^$path ]]; then
- echo -e "${RED}The source of truth for '$file' is in ${DEV_BRANCH}.${NORMAL}"
- (( mainline_count++ ))
- break
- fi
- done
-done < <(git show --name-only --pretty=format: $1 | grep -- "$2")
-
-if (( mainline_count != 0 )); then
- if (( mainline_count == total_count )); then
- echo -e ${WARNING_FULL}
- else
- echo -e ${WARNING_PARTIAL}
- fi
- exit 1
-fi
-exit 0
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index 3dc6163..74c8ebd 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index 8d35470..e432000 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -16,7 +16,8 @@
# tunables
-DEV_BRANCH=rvc-dev
+DEV_BRANCH=master
+MAINLINE_BRANCH=mainline-prod
###
RED=$(tput setaf 1)
@@ -25,41 +26,27 @@
## check the active branch:
## * b131183694 d198c6a [goog/master] Fix to handle missing checks on error returned
##
-current=`git branch -vv | grep -P "^\*[^\[]+\[goog/"|sed -e 's/^.*\[//' | sed -e 's/:.*$//'| sed -e 's/^goog\///'`
+current=`git branch -vv | grep -P "^\*[^\[]+\[goog/"|sed -e 's/^.*\[//' | sed -e 's/\].*$//'|sed -e 's/:.*$//'| sed -e 's/^goog\///'`
if [ "${current}" = "" ] ; then
current=unknown
fi
-if [ "${current}" = "${DEV_BRANCH}" ] ; then
- # Change appears to be in mainline dev branch
- exit 0
+# simple reminder that it should also land in mainline branch
+#
+if [ "${current}" != "${MAINLINE_BRANCH}" ] ; then
+ # simple reminder to ensure it hits mainline
+ cat - <<EOF
+You are uploading repo ${RED}${REPO_PATH}${NORMAL} to branch ${RED}${current}${NORMAL}.
+The mainline branch for ${RED}${REPO_PATH}${NORMAL} is branch ${RED}${MAINLINE_BRANCH}${NORMAL}.
+
+Ensure an appropriate cherry pick or equivalent lands in branch ${RED}${MAINLINE_BRANCH}${NORMAL}.
+Security bulletin timing or unreleased functionality may determine when that can be landed.
+
+EOF
fi
-## warn the user that about not being on the typical/desired branch.
-
-cat - <<EOF
-
-You are uploading repo ${RED}${REPO_PATH}${NORMAL} to branch ${RED}${current}${NORMAL}.
-The source of truth for ${RED}${REPO_PATH}${NORMAL} is branch ${RED}${DEV_BRANCH}${NORMAL}.
-
-Please upload this change to branch ${RED}${DEV_BRANCH}${NORMAL} unless one or more of
-the following apply:
-- this is a security bug prohibited from disclosure before the next dessert release.
- (moderate security bugs fall into this category).
-- this is new functionality prohibitied from disclosure before the next dessert release.
-EOF
-
-
-##
-## TODO: prompt the user y/n to continue right now instead of re-invoking with no-verify
-## this has to get around how repo buffers stdout from this script such that the output
-## is not flushed before we try to read the input.
-##
-
-cat - <<EOF
-If you are sure you want to proceed uploading to branch ${RED}${current}${NORMAL},
-re-run your repo upload command with the '--no-verify' option
-
-EOF
-exit 1
+# exit 0 is "all good, no output passed along to user"
+# exit 77 is "all ok, but output is passed along to the user"
+#
+exit 77