Merge "Speed up SniffMidi() by parsing the initial bytes of the header" into main
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index b369a62..ba231c1 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -66,7 +66,6 @@
"libmedia_helper",
"libmediametrics",
"libprocessgroup",
- "libprocessgroup_util",
"mediametricsservice-aidl-cpp",
"shared-file-region-aidl-cpp",
],
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
index a215c0b..61d5ccd 100644
--- a/media/libaudioclient/aidl/fuzzer/Android.bp
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -30,7 +30,6 @@
"libjsoncpp",
"libmediametricsservice",
"libprocessgroup",
- "libprocessgroup_util",
"shared-file-region-aidl-cpp",
],
shared_libs: [
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index 8bca8df..a95c700 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -46,7 +46,6 @@
"libmediametrics",
"libmediametricsservice",
"libprocessgroup",
- "libprocessgroup_util",
"shared-file-region-aidl-cpp",
],
shared_libs: [
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 116ed9a..d76ed25 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -122,6 +122,10 @@
static sp<IMediaPlayerService> sService;
Mutex mLock;
+ // Static lock was added to the client in order to consume at most
+ // one service thread from image extraction requests of the same
+ // client process(See also b/21277449).
+ static Mutex sLock;
sp<IMediaMetadataRetriever> mRetriever;
};
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 40fd022..9196f9f 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -35,6 +35,8 @@
sp<IMediaPlayerService> MediaMetadataRetriever::sService;
sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
+Mutex MediaMetadataRetriever::sLock;
+
const sp<IMediaPlayerService> MediaMetadataRetriever::getService()
{
Mutex::Autolock lock(sServiceLock);
@@ -143,6 +145,7 @@
ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)",
timeUs, option, colorFormat, metaOnly);
Mutex::Autolock _l(mLock);
+ Mutex::Autolock _gLock(sLock);
if (mRetriever == 0) {
ALOGE("retriever is not initialized");
return NULL;
@@ -155,6 +158,7 @@
ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
index, colorFormat, metaOnly, thumbnail);
Mutex::Autolock _l(mLock);
+ Mutex::Autolock _gLock(sLock);
if (mRetriever == 0) {
ALOGE("retriever is not initialized");
return NULL;
@@ -167,6 +171,7 @@
ALOGV("getImageRectAtIndex: index(%d) colorFormat(%d) rect {%d, %d, %d, %d}",
index, colorFormat, left, top, right, bottom);
Mutex::Autolock _l(mLock);
+ Mutex::Autolock _gLock(sLock);
if (mRetriever == 0) {
ALOGE("retriever is not initialized");
return NULL;
@@ -180,6 +185,7 @@
ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
index, colorFormat, metaOnly);
Mutex::Autolock _l(mLock);
+ Mutex::Autolock _gLock(sLock);
if (mRetriever == 0) {
ALOGE("retriever is not initialized");
return NULL;
diff --git a/media/module/extractors/Android.bp b/media/module/extractors/Android.bp
index 6e64254..e29d3e6 100644
--- a/media/module/extractors/Android.bp
+++ b/media/module/extractors/Android.bp
@@ -28,6 +28,10 @@
"liblog",
],
+ static_libs: [
+ "libstagefright_metadatautils",
+ ],
+
// extractors are expected to run on Q(29)
min_sdk_version: "29",
apex_available: [
@@ -56,6 +60,7 @@
"libutils",
"libmediandk_format",
"libmedia_ndkformatpriv",
+ "libstagefright_metadatautils",
],
},
},
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index 4ab8d2c..3da1589 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -132,6 +132,7 @@
"libstagefright_id3",
"libstagefright_esds",
"libmp4extractor",
+ "libstagefright_metadatautils",
],
dictionary: "mp4_extractor_fuzzer.dict",
diff --git a/media/module/extractors/mkv/MatroskaExtractor.cpp b/media/module/extractors/mkv/MatroskaExtractor.cpp
index f326db1..10ae07a 100644
--- a/media/module/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/module/extractors/mkv/MatroskaExtractor.cpp
@@ -1787,7 +1787,7 @@
return ERROR_MALFORMED;
}
- if (!MakeVP9CodecSpecificData(trackInfo->mMeta, tmpData.get(), frame.len)) {
+ if (!MakeVP9CodecSpecificDataFromFirstFrame(trackInfo->mMeta, tmpData.get(), frame.len)) {
return ERROR_MALFORMED;
}
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index f247f8c..12c0aaf 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -51,6 +51,7 @@
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataBase.h>
+#include <media/stagefright/MetaDataUtils.h>
#include <utils/String8.h>
#include <byteswap.h>
@@ -2596,8 +2597,32 @@
*offset += chunk_size;
break;
}
-
case FOURCC("vpcC"):
+ {
+ if (mLastTrack == NULL) {
+ return ERROR_MALFORMED;
+ }
+
+ auto buffer = heapbuffer<uint8_t>(chunk_data_size);
+
+ if (buffer.get() == NULL) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
+
+ if (mDataSource->readAt(data_offset, buffer.get(), chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+
+ if (!MakeVP9CodecPrivateFromVpcC(mLastTrack->meta, buffer.get(), chunk_data_size)) {
+ ALOGE("Failed to create VP9 CodecPrivate from vpcC.");
+ return ERROR_MALFORMED;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
case FOURCC("av1C"):
{
auto buffer = heapbuffer<uint8_t>(chunk_data_size);
diff --git a/media/module/metadatautils/MetaDataUtils.cpp b/media/module/metadatautils/MetaDataUtils.cpp
index 0895bb5..177438a 100644
--- a/media/module/metadatautils/MetaDataUtils.cpp
+++ b/media/module/metadatautils/MetaDataUtils.cpp
@@ -134,10 +134,54 @@
}
return true;
}
+
+/**
+ * Build VP9 Codec Feature Metadata (CodecPrivate) to set CSD for VP9 codec.
+ * For reference:
+ * https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate.
+ *
+ * @param meta A pointer to AMediaFormat object.
+ * @param profile The profile value of the VP9 stream.
+ * @param level The VP9 codec level. If the level is unknown, pass -1 to this parameter.
+ * @param bitDepth The bit depth of the luma and color components of the VP9 stream.
+ * @param chromaSubsampling The chroma subsampling of the VP9 stream. If chromaSubsampling is
+ * unknown, pass -1 to this parameter.
+ * @return true if CodecPrivate is set as CSD of AMediaFormat object.
+ *
+ */
+static bool MakeVP9CodecPrivate(AMediaFormat* meta, int32_t profile, int32_t level,
+ int32_t bitDepth, int32_t chromaSubsampling) {
+ if (meta == nullptr) {
+ return false;
+ }
+
+ std::vector<uint8_t> codecPrivate;
+ // Construct CodecPrivate in WebM format (ID | Length | Data).
+ // Helper lambda to add a field to the codec private data
+ auto addField = [&codecPrivate](uint8_t id, uint8_t value) {
+ codecPrivate.push_back(id);
+ codecPrivate.push_back(0x01); // Length is always 1
+ codecPrivate.push_back(value);
+ };
+
+ // Add fields
+ addField(0x01, static_cast<uint8_t>(profile));
+ if (level >= 0) {
+ addField(0x02, static_cast<uint8_t>(level));
+ }
+ addField(0x03, static_cast<uint8_t>(bitDepth));
+ if (chromaSubsampling >= 0) {
+ addField(0x04, static_cast<uint8_t>(chromaSubsampling));
+ }
+ // Set CSD in the meta format
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, codecPrivate.data(), codecPrivate.size());
+ return true;
+}
+
// The param data contains the first frame data, starting with the uncompressed frame
// header. This uncompressed header (refer section 6.2 of the VP9 bitstream spec) is
// used to parse profile, bitdepth and subsampling.
-bool MakeVP9CodecSpecificData(AMediaFormat* meta, const uint8_t* data, size_t size) {
+bool MakeVP9CodecSpecificDataFromFirstFrame(AMediaFormat* meta, const uint8_t* data, size_t size) {
if (meta == nullptr || data == nullptr || size == 0) {
return false;
}
@@ -227,29 +271,29 @@
if (chromaSubsampling != -1) {
csdSize += 3;
}
+ // As level is not present in first frame build CodecPrivate without it.
+ return MakeVP9CodecPrivate(meta, profile, -1, bitDepth, chromaSubsampling);
+}
- // Create VP9 Codec Feature Metadata (CodecPrivate) that can be parsed
- // https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate
- sp<ABuffer> csd = sp<ABuffer>::make(csdSize);
- uint8_t* csdData = csd->data();
-
- *csdData++ = 0x01 /* FEATURE PROFILE */;
- *csdData++ = 0x01 /* length */;
- *csdData++ = profile;
-
- *csdData++ = 0x03 /* FEATURE BITDEPTH */;
- *csdData++ = 0x01 /* length */;
- *csdData++ = bitDepth;
-
- // csdSize more than 6 means chroma subsampling data was found.
- if (csdSize > 6) {
- *csdData++ = 0x04 /* FEATURE SUBSAMPLING */;
- *csdData++ = 0x01 /* length */;
- *csdData++ = chromaSubsampling;
+bool MakeVP9CodecPrivateFromVpcC(AMediaFormat* meta, const uint8_t* csdData, size_t size) {
+ if (meta == nullptr || csdData == nullptr || size < 12) {
+ return false;
}
- AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, csd->data(), csd->size());
- return true;
+ // Check the first 4 bytes (VersionAndFlags) if they match the required value.
+ if (csdData[0] != 0x01 || csdData[1] != 0x00 || csdData[2] != 0x00 || csdData[3] != 0x00) {
+ return false;
+ }
+
+ // Create VP9 Codec Feature Metadata (CodecPrivate) that can be parsed.
+ // https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate
+ const uint8_t* vpcCData = csdData + 4; // Skip the first 4 bytes (VersionAndFlags)
+
+ int32_t profile = vpcCData[0];
+ int32_t level = vpcCData[1];
+ int32_t bitDepth = (vpcCData[2] >> 4) & 0x0F; // Bit Depth (4 bits).
+ int32_t chromaSubsampling = (vpcCData[2] >> 1) & 0x07; // Chroma Subsampling (3 bits).
+ return MakeVP9CodecPrivate(meta, profile, level, bitDepth, chromaSubsampling);
}
bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
diff --git a/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
index 69cf21a..9988544 100644
--- a/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
+++ b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
@@ -38,7 +38,10 @@
void parseVorbisComment(
AMediaFormat *fileMeta, const char *comment, size_t commentLength);
-bool MakeVP9CodecSpecificData(AMediaFormat* meta, const uint8_t* data, size_t size);
+bool MakeVP9CodecSpecificData(AMediaFormat* meta, int32_t csdSize, int32_t profile, int32_t level,
+ int32_t bitDepth, int32_t chromaSubsampling);
+bool MakeVP9CodecSpecificDataFromFirstFrame(AMediaFormat* meta, const uint8_t* data, size_t size);
+bool MakeVP9CodecPrivateFromVpcC(AMediaFormat* meta, const uint8_t* data, size_t size);
} // namespace android
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ecbd0ae..90d3ef9 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3220,9 +3220,9 @@
// Calculate size of normal sink buffer relative to the HAL output buffer size
double multiplier = 1.0;
- // Note: mType == SPATIALIZER does not support FastMixer.
- if (mType == MIXER && (kUseFastMixer == FastMixer_Static ||
- kUseFastMixer == FastMixer_Dynamic)) {
+ // Note: mType == SPATIALIZER does not support FastMixer and DEEP is by definition not "fast"
+ if ((mType == MIXER && !(mOutput->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) &&
+ (kUseFastMixer == FastMixer_Static || kUseFastMixer == FastMixer_Dynamic)) {
size_t minNormalFrameCount = (kMinNormalSinkBufferSizeMs * mSampleRate) / 1000;
size_t maxNormalFrameCount = (kMaxNormalSinkBufferSizeMs * mSampleRate) / 1000;
@@ -5135,7 +5135,16 @@
break;
case FastMixer_Static:
case FastMixer_Dynamic:
- initFastMixer = mFrameCount < mNormalFrameCount;
+ if (mType == MIXER && (output->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
+ /* Do not init fast mixer on deep buffer, warn if buffers are confed too small */
+ initFastMixer = false;
+ ALOGW_IF(mFrameCount * 1000 / mSampleRate < kMinNormalSinkBufferSizeMs,
+ "HAL DEEP BUFFER Buffer (%zu ms) is smaller than set minimal buffer "
+ "(%u ms), seems like a configuration error",
+ mFrameCount * 1000 / mSampleRate, kMinNormalSinkBufferSizeMs);
+ } else {
+ initFastMixer = mFrameCount < mNormalFrameCount;
+ }
break;
}
ALOGW_IF(initFastMixer == false && mFrameCount < mNormalFrameCount,
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 3b7cae3..d499222 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -29,19 +29,21 @@
/**
* Legacy audio policy product strategies IDs. These strategies are supported by the default
* policy engine.
+ * IMPORTANT NOTE: the order of this enum is important as it determines the priority
+ * between active strategies for routing decisions: lower enum value => higher prioriy
*/
enum legacy_strategy {
STRATEGY_NONE = -1,
- STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
- STRATEGY_SONIFICATION_RESPECTFUL,
- STRATEGY_DTMF,
STRATEGY_ENFORCED_AUDIBLE,
- STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
STRATEGY_ACCESSIBILITY,
- STRATEGY_REROUTING,
+ STRATEGY_SONIFICATION_RESPECTFUL,
+ STRATEGY_MEDIA,
+ STRATEGY_DTMF,
STRATEGY_CALL_ASSISTANT,
+ STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
+ STRATEGY_REROUTING,
STRATEGY_PATCH,
};