Merge "AIDLize IAudioPolicyServiceClient"
diff --git a/apex/Android.bp b/apex/Android.bp
index f3e8a55..b314e5d 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -89,6 +89,9 @@
binaries: [
"mediaswcodec",
],
+ native_shared_libs: [
+ "libstagefright_foundation",
+ ],
prebuilts: [
"com.android.media.swcodec-mediaswcodec.rc",
"com.android.media.swcodec-ld.config.txt",
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 12ed725..b520c17 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -734,7 +734,7 @@
}
if (timestampMax < timestamp) timestampMax = timestamp;
}
- timestampOffset = timestampMax;
+ timestampOffset = timestampMax + 33333;
eleInfo.close();
// Reset Total frames before second decode loop
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index bb35763..479acb1 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -61,24 +61,24 @@
/// Input Surface configuration
struct Config {
// IN PARAMS (GBS)
- float mMinFps; // minimum fps (repeat frame to achieve this)
- float mMaxFps; // max fps (via frame drop)
- float mCaptureFps; // capture fps
- float mCodedFps; // coded fps
- bool mSuspended; // suspended
- int64_t mTimeOffsetUs; // time offset (input => codec)
- int64_t mSuspendAtUs; // suspend/resume time
- int64_t mStartAtUs; // start time
- bool mStopped; // stopped
- int64_t mStopAtUs; // stop time
+ float mMinFps = 0.0; // minimum fps (repeat frame to achieve this)
+ float mMaxFps = 0.0; // max fps (via frame drop)
+ float mCaptureFps = 0.0; // capture fps
+ float mCodedFps = 0.0; // coded fps
+ bool mSuspended = false; // suspended
+ int64_t mTimeOffsetUs = 0; // time offset (input => codec)
+ int64_t mSuspendAtUs = 0; // suspend/resume time
+ int64_t mStartAtUs = 0; // start time
+ bool mStopped = false; // stopped
+ int64_t mStopAtUs = 0; // stop time
// OUT PARAMS (GBS)
- int64_t mInputDelayUs; // delay between encoder input and surface input
+ int64_t mInputDelayUs = 0; // delay between encoder input and surface input
// IN PARAMS (CODEC WRAPPER)
- float mFixedAdjustedFps; // fixed fps via PTS manipulation
- float mMinAdjustedFps; // minimum fps via PTS manipulation
- uint64_t mUsage; // consumer usage
+ float mFixedAdjustedFps = 0.0; // fixed fps via PTS manipulation
+ float mMinAdjustedFps = 0.0; // minimum fps via PTS manipulation
+ uint64_t mUsage = 0; // consumer usage
};
/**
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 7ab8f45..30e4fda 100644
--- a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -491,6 +491,9 @@
}
for (i = 0; i < encParams->nLayers; i++)
{
+ if (encOption->encHeight[i] == 0 || encOption->encWidth[i] == 0 ||
+ encOption->encHeight[i] % 16 != 0 || encOption->encWidth[i] % 16 != 0)
+ goto CLEAN_UP;
encParams->LayerHeight[i] = encOption->encHeight[i];
encParams->LayerWidth[i] = encOption->encWidth[i];
}
diff --git a/media/codecs/mp3dec/Android.bp b/media/codecs/mp3dec/Android.bp
index 1acf0a6..f84da21 100644
--- a/media/codecs/mp3dec/Android.bp
+++ b/media/codecs/mp3dec/Android.bp
@@ -1,3 +1,18 @@
+cc_library_headers {
+ name: "libstagefright_mp3dec_headers",
+ vendor_available: true,
+ min_sdk_version: "29",
+ host_supported:true,
+ export_include_dirs: [
+ "include",
+ "src",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
+}
+
cc_library_static {
name: "libstagefright_mp3dec",
vendor_available: true,
@@ -65,10 +80,8 @@
include_dirs: ["frameworks/av/media/libstagefright/include"],
- export_include_dirs: [
- "include",
- "src",
- ],
+ header_libs: ["libstagefright_mp3dec_headers"],
+ export_header_lib_headers: ["libstagefright_mp3dec_headers"],
cflags: [
"-DOSCL_UNUSED_ARG(x)=(void)(x)",
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index ded3d1a..444664c 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -80,13 +80,15 @@
Vector<uint32_t> thumbnails;
Vector<uint32_t> dimgRefs;
- Vector<uint32_t> cdscRefs;
+ Vector<uint32_t> exifRefs;
+ Vector<uint32_t> xmpRefs;
size_t nextTileIndex;
};
-struct ExifItem {
+struct ExternalMetaItem {
off64_t offset;
size_t size;
+ bool isExif;
};
/////////////////////////////////////////////////////////////////////
@@ -482,7 +484,7 @@
void apply(
KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
- KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const;
+ KeyedVector<uint32_t, ExternalMetaItem> &itemIdToMetaMap) const;
private:
uint32_t mItemId;
@@ -494,7 +496,7 @@
void ItemReference::apply(
KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
- KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const {
+ KeyedVector<uint32_t, ExternalMetaItem> &itemIdToMetaMap) const {
ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId);
switch(type()) {
@@ -556,15 +558,15 @@
break;
}
case FOURCC("cdsc"): {
- ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId);
+ ssize_t metaIndex = itemIdToMetaMap.indexOfKey(mItemId);
- // ignore non-exif block items
- if (itemIndex < 0) {
+ // ignore non-meta items
+ if (metaIndex < 0) {
return;
}
for (size_t i = 0; i < mRefs.size(); i++) {
- itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
+ ssize_t itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
// ignore non-image items
if (itemIndex < 0) {
@@ -572,7 +574,11 @@
}
ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId);
ImageItem &image = itemIdToItemMap.editValueAt(itemIndex);
- image.cdscRefs.push_back(mItemId);
+ if (itemIdToMetaMap[metaIndex].isExif) {
+ image.exifRefs.push_back(mItemId);
+ } else {
+ image.xmpRefs.push_back(mItemId);
+ }
}
break;
}
@@ -1065,7 +1071,21 @@
struct ItemInfo {
uint32_t itemId;
uint32_t itemType;
+ String8 contentType;
bool hidden;
+
+ bool isXmp() const {
+ return itemType == FOURCC("mime") && contentType == String8("application/rdf+xml");
+ }
+ bool isExif() const {
+ return itemType == FOURCC("Exif");
+ }
+ bool isGrid() const {
+ return itemType == FOURCC("grid");
+ }
+ bool isSample() const {
+ return itemType == FOURCC("av01") || itemType == FOURCC("hvc1");
+ }
};
struct InfeBox : public FullBox {
@@ -1155,6 +1175,7 @@
if (!parseNullTerminatedString(&offset, &size, &content_type)) {
return ERROR_MALFORMED;
}
+ itemInfo->contentType = content_type;
// content_encoding is optional; can be omitted if would be empty
if (size > 0) {
@@ -1175,18 +1196,18 @@
struct IinfBox : public FullBox {
IinfBox(DataSourceHelper *source, Vector<ItemInfo> *itemInfos) :
- FullBox(source, FOURCC("iinf")), mItemInfos(itemInfos) {}
+ FullBox(source, FOURCC("iinf")), mItemInfos(itemInfos), mNeedIref(false) {}
status_t parse(off64_t offset, size_t size);
- bool hasFourCC(uint32_t type) { return mFourCCSeen.count(type) > 0; }
+ bool needIrefBox() { return mNeedIref; }
protected:
status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
private:
Vector<ItemInfo> *mItemInfos;
- std::unordered_set<uint32_t> mFourCCSeen;
+ bool mNeedIref;
};
status_t IinfBox::parse(off64_t offset, size_t size) {
@@ -1233,7 +1254,7 @@
status_t err = infeBox.parse(offset, size, &itemInfo);
if (err == OK) {
mItemInfos->push_back(itemInfo);
- mFourCCSeen.insert(itemInfo.itemType);
+ mNeedIref |= (itemInfo.isExif() || itemInfo.isXmp() || itemInfo.isGrid());
}
// InfeBox parse returns ERROR_UNSUPPORTED if the box if an unsupported
// version. Ignore this error as it's not fatal.
@@ -1323,7 +1344,7 @@
return err;
}
- if (iinfBox.hasFourCC(FOURCC("grid")) || iinfBox.hasFourCC(FOURCC("Exif"))) {
+ if (iinfBox.needIrefBox()) {
mRequiredBoxes.insert('iref');
}
@@ -1399,12 +1420,9 @@
// Only handle 3 types of items, all others are ignored:
// 'grid': derived image from tiles
- // 'hvc1': coded image (or tile)
- // 'Exif': EXIF metadata
- if (info.itemType != FOURCC("grid") &&
- info.itemType != FOURCC("hvc1") &&
- info.itemType != FOURCC("Exif") &&
- info.itemType != FOURCC("av01")) {
+ // 'hvc1' or 'av01': coded image (or tile)
+ // 'Exif' or XMP: metadata
+ if (!info.isGrid() && !info.isSample() && !info.isExif() && !info.isXmp()) {
continue;
}
@@ -1427,15 +1445,18 @@
return ERROR_MALFORMED;
}
- if (info.itemType == FOURCC("Exif")) {
- // Only add if the Exif data is non-empty. The first 4 bytes contain
+ if (info.isExif() || info.isXmp()) {
+ // Only add if the meta is non-empty. For Exif, the first 4 bytes contain
// the offset to TIFF header, which the Exif parser doesn't use.
- if (size > 4) {
- ExifItem exifItem = {
+ ALOGV("adding meta to mItemIdToMetaMap: isExif %d, offset %lld, size %lld",
+ info.isExif(), (long long)offset, (long long)size);
+ if ((info.isExif() && size > 4) || (info.isXmp() && size > 0)) {
+ ExternalMetaItem metaItem = {
+ .isExif = info.isExif(),
.offset = offset,
.size = size,
};
- mItemIdToExifMap.add(info.itemId, exifItem);
+ mItemIdToMetaMap.add(info.itemId, metaItem);
}
continue;
}
@@ -1470,7 +1491,7 @@
}
for (size_t i = 0; i < mItemReferences.size(); i++) {
- mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap);
+ mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToMetaMap);
}
bool foundPrimary = false;
@@ -1747,11 +1768,11 @@
}
const ImageItem &image = mItemIdToItemMap[itemIndex];
- if (image.cdscRefs.size() == 0) {
+ if (image.exifRefs.size() == 0) {
return NAME_NOT_FOUND;
}
- ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]);
+ ssize_t exifIndex = mItemIdToMetaMap.indexOfKey(image.exifRefs[0]);
if (exifIndex < 0) {
return NAME_NOT_FOUND;
}
@@ -1759,7 +1780,7 @@
// skip the first 4-byte of the offset to TIFF header
uint32_t tiffOffset;
if (!mDataSource->readAt(
- mItemIdToExifMap[exifIndex].offset, &tiffOffset, 4)) {
+ mItemIdToMetaMap[exifIndex].offset, &tiffOffset, 4)) {
return ERROR_IO;
}
@@ -1772,16 +1793,43 @@
// exif data. The size of the item should be > 4 for a non-empty exif (this
// was already checked when the item was added). Also check that the tiff
// header offset is valid.
- if (mItemIdToExifMap[exifIndex].size <= 4 ||
- tiffOffset > mItemIdToExifMap[exifIndex].size - 4) {
+ if (mItemIdToMetaMap[exifIndex].size <= 4 ||
+ tiffOffset > mItemIdToMetaMap[exifIndex].size - 4) {
return ERROR_MALFORMED;
}
// Offset of 'Exif\0\0' relative to the beginning of 'Exif' item
// (first 4-byte is the tiff header offset)
uint32_t exifOffset = 4 + tiffOffset - 6;
- *offset = mItemIdToExifMap[exifIndex].offset + exifOffset;
- *size = mItemIdToExifMap[exifIndex].size - exifOffset;
+ *offset = mItemIdToMetaMap[exifIndex].offset + exifOffset;
+ *size = mItemIdToMetaMap[exifIndex].size - exifOffset;
+ return OK;
+}
+
+status_t ItemTable::getXmpOffsetAndSize(off64_t *offset, size_t *size) {
+ if (!mImageItemsValid) {
+ return INVALID_OPERATION;
+ }
+
+ ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId);
+
+ // this should not happen, something's seriously wrong.
+ if (itemIndex < 0) {
+ return INVALID_OPERATION;
+ }
+
+ const ImageItem &image = mItemIdToItemMap[itemIndex];
+ if (image.xmpRefs.size() == 0) {
+ return NAME_NOT_FOUND;
+ }
+
+ ssize_t xmpIndex = mItemIdToMetaMap.indexOfKey(image.xmpRefs[0]);
+ if (xmpIndex < 0) {
+ return NAME_NOT_FOUND;
+ }
+
+ *offset = mItemIdToMetaMap[xmpIndex].offset;
+ *size = mItemIdToMetaMap[xmpIndex].size;
return OK;
}
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index b19dc18..62826b6 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -34,7 +34,7 @@
struct AssociationEntry;
struct ImageItem;
-struct ExifItem;
+struct ExternalMetaItem;
struct ItemLoc;
struct ItemInfo;
struct ItemProperty;
@@ -59,6 +59,7 @@
status_t getImageOffsetAndSize(
uint32_t *itemIndex, off64_t *offset, size_t *size);
status_t getExifOffsetAndSize(off64_t *offset, size_t *size);
+ status_t getXmpOffsetAndSize(off64_t *offset, size_t *size);
protected:
~ItemTable();
@@ -84,7 +85,7 @@
bool mImageItemsValid;
uint32_t mCurrentItemIndex;
KeyedVector<uint32_t, ImageItem> mItemIdToItemMap;
- KeyedVector<uint32_t, ExifItem> mItemIdToExifMap;
+ KeyedVector<uint32_t, ExternalMetaItem> mItemIdToMetaMap;
Vector<uint32_t> mDisplayables;
status_t parseIlocBox(off64_t offset, size_t size);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 7989d4b..221bf4f 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -681,6 +681,19 @@
AMediaFormat_setInt64(mFileMetaData,
AMEDIAFORMAT_KEY_EXIF_SIZE, (int64_t)exifSize);
}
+ off64_t xmpOffset;
+ size_t xmpSize;
+ if (mItemTable->getXmpOffsetAndSize(&xmpOffset, &xmpSize) == OK) {
+ // TODO(chz): b/175717339
+ // Use a hard-coded string here instead of named keys. The keys are available
+ // only on API 31+. The mp4 extractor is part of mainline and has min_sdk_version
+ // of 29. This hard-coded string can be replaced with the named constant once
+ // the mp4 extractor is built against API 31+.
+ AMediaFormat_setInt64(mFileMetaData,
+ "xmp-offset" /*AMEDIAFORMAT_KEY_XMP_OFFSET*/, (int64_t)xmpOffset);
+ AMediaFormat_setInt64(mFileMetaData,
+ "xmp-size" /*AMEDIAFORMAT_KEY_XMP_SIZE*/, (int64_t)xmpSize);
+ }
for (uint32_t imageIndex = 0;
imageIndex < mItemTable->countImages(); imageIndex++) {
AMediaFormat *meta = mItemTable->getImageMeta(imageIndex);
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 57c4c16..431f0fa 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -171,7 +171,7 @@
aaudio_result_t result = requestStart_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->start();
+ (void) mPlayerBase->startWithStatus(getDeviceId());
}
return result;
}
@@ -221,7 +221,7 @@
aaudio_result_t result = requestPause_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->pause();
+ (void) mPlayerBase->pauseWithStatus();
}
return result;
}
@@ -251,7 +251,7 @@
aaudio_result_t result = safeStop_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->stop();
+ (void) mPlayerBase->stopWithStatus();
}
return result;
}
@@ -265,7 +265,7 @@
aaudio_result_t result = safeStop_l();
if (result == AAUDIO_OK) {
// We only call this for logging in "dumpsys audio". So ignore return code.
- (void) mPlayerBase->stop();
+ (void) mPlayerBase->stopWithStatus();
}
return result;
}
diff --git a/media/libaudioclient/PlayerBase.cpp b/media/libaudioclient/PlayerBase.cpp
index 9e7d89e..8793735 100644
--- a/media/libaudioclient/PlayerBase.cpp
+++ b/media/libaudioclient/PlayerBase.cpp
@@ -30,7 +30,8 @@
PlayerBase::PlayerBase() : BnPlayer(),
mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
- mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
+ mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN),
+ mLastReportedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
ALOGD("PlayerBase::PlayerBase()");
// use checkService() to avoid blocking if audio service is not up yet
@@ -64,14 +65,26 @@
}
//------------------------------------------------------------------------------
-void PlayerBase::servicePlayerEvent(player_state_t event) {
+void PlayerBase::servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId) {
if (mAudioManager != 0) {
- // only report state change
- Mutex::Autolock _l(mPlayerStateLock);
- if (event != mLastReportedEvent
- && mPIId != PLAYER_PIID_INVALID) {
- mLastReportedEvent = event;
- mAudioManager->playerEvent(mPIId, event);
+ bool changed = false;
+ {
+ Mutex::Autolock _l(mDeviceIdLock);
+ changed = mLastReportedDeviceId != deviceId;
+ mLastReportedDeviceId = deviceId;
+ }
+
+ {
+ Mutex::Autolock _l(mPlayerStateLock);
+ // PLAYER_UPDATE_DEVICE_ID is not saved as an actual state, instead it is used to update
+ // device ID only.
+ if ((event != PLAYER_UPDATE_DEVICE_ID) && (event != mLastReportedEvent)) {
+ mLastReportedEvent = event;
+ changed = true;
+ }
+ }
+ if (changed && (mPIId != PLAYER_PIID_INVALID)) {
+ mAudioManager->playerEvent(mPIId, event, deviceId);
}
}
}
@@ -84,14 +97,18 @@
}
//FIXME temporary method while some player state is outside of this class
-void PlayerBase::reportEvent(player_state_t event) {
- servicePlayerEvent(event);
+void PlayerBase::reportEvent(player_state_t event, audio_port_handle_t deviceId) {
+ servicePlayerEvent(event, deviceId);
}
-status_t PlayerBase::startWithStatus() {
+void PlayerBase::baseUpdateDeviceId(audio_port_handle_t deviceId) {
+ servicePlayerEvent(PLAYER_UPDATE_DEVICE_ID, deviceId);
+}
+
+status_t PlayerBase::startWithStatus(audio_port_handle_t deviceId) {
status_t status = playerStart();
if (status == NO_ERROR) {
- servicePlayerEvent(PLAYER_STATE_STARTED);
+ servicePlayerEvent(PLAYER_STATE_STARTED, deviceId);
} else {
ALOGW("PlayerBase::start() error %d", status);
}
@@ -101,18 +118,18 @@
status_t PlayerBase::pauseWithStatus() {
status_t status = playerPause();
if (status == NO_ERROR) {
- servicePlayerEvent(PLAYER_STATE_PAUSED);
+ servicePlayerEvent(PLAYER_STATE_PAUSED, AUDIO_PORT_HANDLE_NONE);
} else {
ALOGW("PlayerBase::pause() error %d", status);
}
return status;
}
-
status_t PlayerBase::stopWithStatus() {
status_t status = playerStop();
+
if (status == NO_ERROR) {
- servicePlayerEvent(PLAYER_STATE_STOPPED);
+ servicePlayerEvent(PLAYER_STATE_STOPPED, AUDIO_PORT_HANDLE_NONE);
} else {
ALOGW("PlayerBase::stop() error %d", status);
}
@@ -123,7 +140,12 @@
// Implementation of IPlayer
binder::Status PlayerBase::start() {
ALOGD("PlayerBase::start() from IPlayer");
- (void)startWithStatus();
+ audio_port_handle_t deviceId;
+ {
+ Mutex::Autolock _l(mDeviceIdLock);
+ deviceId = mLastReportedDeviceId;
+ }
+ (void)startWithStatus(deviceId);
return binder::Status::ok();
}
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index ee78a2d..c9f3ab9 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ToneGenerator"
+#include <utility>
+
#include <math.h>
#include <utils/Log.h>
#include <cutils/properties.h>
@@ -740,6 +742,11 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_JAPAN_RADIO_ACK
+ { .segments = { { .duration = 1000, .waveFreq = { 400, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_JAPAN_RINGTONE
{ .segments = { { .duration = 375, .waveFreq = { 400, 0 }, 0, 0 },
{ .duration = 375, .waveFreq = { 0 }, 0, 0 },
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
@@ -881,7 +888,7 @@
TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
- TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
+ TONE_JAPAN_RINGTONE // TONE_SUP_RINGTONE
},
{ // GB
TONE_ANSI_DIAL, // TONE_SUP_DIAL
@@ -979,7 +986,9 @@
// none
//
////////////////////////////////////////////////////////////////////////////////
-ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava) {
+ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava,
+ std::string opPackageName)
+ : mOpPackageName(std::move(opPackageName)) {
ALOGV("ToneGenerator constructor: streamType=%d, volume=%f", streamType, volume);
@@ -1250,7 +1259,7 @@
////////////////////////////////////////////////////////////////////////////////
bool ToneGenerator::initAudioTrack() {
// Open audio track in mono, PCM 16bit, default sampling rate.
- mpAudioTrack = new AudioTrack();
+ mpAudioTrack = new AudioTrack(mOpPackageName);
ALOGV("AudioTrack(%p) created", mpAudioTrack.get());
audio_attributes_t attr;
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index 372b7c3..5c73756 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -36,6 +36,10 @@
void TrackPlayerBase::init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage) {
PlayerBase::init(playerType, usage);
mAudioTrack = pat;
+ if (mAudioTrack != 0) {
+ mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
+ mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+ }
}
void TrackPlayerBase::destroy() {
@@ -43,9 +47,23 @@
baseDestroy();
}
+TrackPlayerBase::SelfAudioDeviceCallback::SelfAudioDeviceCallback(PlayerBase& self) :
+ AudioSystem::AudioDeviceCallback(), mSelf(self) {
+}
+
+TrackPlayerBase::SelfAudioDeviceCallback::~SelfAudioDeviceCallback() {
+}
+
+void TrackPlayerBase::SelfAudioDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t __unused,
+ audio_port_handle_t deviceId) {
+ mSelf.baseUpdateDeviceId(deviceId);
+}
+
void TrackPlayerBase::doDestroy() {
if (mAudioTrack != 0) {
mAudioTrack->stop();
+ mAudioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
+ mSelfAudioDeviceCallback.clear();
// Note that there may still be another reference in post-unlock phase of SetPlayState
mAudioTrack.clear();
}
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index 4aad9b4..1a42b88 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -44,12 +44,14 @@
const media::VolumeShaperConfiguration& configuration,
const media::VolumeShaperOperation& operation) override;
- status_t startWithStatus();
+ status_t startWithStatus(audio_port_handle_t deviceId);
status_t pauseWithStatus();
status_t stopWithStatus();
//FIXME temporary method while some player state is outside of this class
- void reportEvent(player_state_t event);
+ void reportEvent(player_state_t event, audio_port_handle_t deviceId);
+
+ void baseUpdateDeviceId(audio_port_handle_t deviceId);
protected:
@@ -71,7 +73,7 @@
private:
// report events to AudioService
- void servicePlayerEvent(player_state_t event);
+ void servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId);
void serviceReleasePlayer();
// native interface to AudioService
@@ -83,6 +85,9 @@
// Mutex for state reporting
Mutex mPlayerStateLock;
player_state_t mLastReportedEvent;
+
+ Mutex mDeviceIdLock;
+ audio_port_handle_t mLastReportedDeviceId;
};
} // namespace android
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 04357a8..a575616 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_TONEGENERATOR_H_
#define ANDROID_TONEGENERATOR_H_
+#include <string>
+
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
#include <utils/Compat.h>
@@ -152,7 +154,8 @@
NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
};
- ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false);
+ ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false,
+ std::string opPackageName = {});
~ToneGenerator();
bool startTone(tone_type toneType, int durationMs = -1);
@@ -193,6 +196,7 @@
TONE_JAPAN_DIAL, // Dial tone: 400Hz, continuous
TONE_JAPAN_BUSY, // Busy tone: 400Hz, 500ms ON, 500ms OFF...
TONE_JAPAN_RADIO_ACK, // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
+ TONE_JAPAN_RINGTONE, // Ring Tone: 400 Hz repeated in a 1 s on, 2 s off pattern.
// GB Supervisory tones
TONE_GB_BUSY, // Busy tone: 400 Hz, 375ms ON, 375ms OFF...
TONE_GB_CONGESTION, // Congestion Tone: 400 Hz, 400ms ON, 350ms OFF, 225ms ON, 525ms OFF...
@@ -343,6 +347,8 @@
};
KeyedVector<uint16_t, WaveGenerator *> mWaveGens; // list of active wave generators.
+
+ std::string mOpPackageName;
};
}
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index 6d26e63..b40d1eb 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -53,8 +53,20 @@
void doDestroy();
status_t doSetVolume();
+ class SelfAudioDeviceCallback : public AudioSystem::AudioDeviceCallback {
+ public:
+ SelfAudioDeviceCallback(PlayerBase& self);
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId);
+ private:
+ virtual ~SelfAudioDeviceCallback();
+ PlayerBase& mSelf;
+ };
+
// volume coming from the player volume API
float mPlayerVolumeL, mPlayerVolumeR;
+
+ sp<SelfAudioDeviceCallback> mSelfAudioDeviceCallback;
};
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 77c2550..0108816 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -215,7 +215,7 @@
const struct audio_config *config, size_t *size) {
if (mDevice == 0) return NO_INIT;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
Result retval;
Return<void> ret = mDevice->getInputBufferSize(
hidlConfig,
@@ -240,7 +240,7 @@
status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, false /*isInput*/, &hidlConfig);
Result retval = Result::NOT_INITIALIZED;
Return<void> ret = mDevice->openOutputStream(
handle,
@@ -275,7 +275,7 @@
status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
- HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+ HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
Result retval = Result::NOT_INITIALIZED;
#if MAJOR_VERSION == 2
auto sinkMetadata = AudioSource(source);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 670b415..865baad 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1021,6 +1021,16 @@
ActiveParams.NrChannels = NrChannels;
ActiveParams.ChMask = pConfig->inputCfg.channels;
+ if (NrChannels == 1) {
+ ActiveParams.SourceFormat = LVM_MONO;
+ } else if (NrChannels == 2) {
+ ActiveParams.SourceFormat = LVM_STEREO;
+ } else if (NrChannels > 2 && NrChannels <= LVM_MAX_CHANNELS) {
+ ActiveParams.SourceFormat = LVM_MULTICHANNEL;
+ } else {
+ return -EINVAL;
+ }
+
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_setConfig")
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index 5217cf9..681e247 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -1,35 +1,5 @@
// audio preprocessing wrapper
cc_library_shared {
- name: "libaudiopreprocessing_legacy",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
- srcs: ["PreProcessing.cpp"],
-
- shared_libs: [
- "libwebrtc_audio_preprocessing",
- "libspeexresampler",
- "libutils",
- "liblog",
- ],
-
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=hidden",
- "-Wall",
- "-Werror",
- ],
-
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- ],
-}
-
-cc_library_shared {
name: "libaudiopreprocessing",
vendor: true,
relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 1a5547b..03ccc34 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -23,15 +23,10 @@
#include <hardware/audio_effect.h>
#include <utils/Log.h>
#include <utils/Timers.h>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <audio_processing.h>
#include <module_common_types.h>
-#ifdef WEBRTC_LEGACY
-#include "speex/speex_resampler.h"
-#endif
// undefine to perform multi channels API functional tests
//#define DUAL_MIC_TEST
@@ -46,9 +41,7 @@
// types of pre processing modules
enum preproc_id {
PREPROC_AGC, // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
PREPROC_AGC2, // Automatic Gain Control 2
-#endif
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
PREPROC_NUM_EFFECTS
@@ -110,10 +103,8 @@
int id; // audio session ID
int io; // handle of input stream this session is on
webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
-#ifndef WEBRTC_LEGACY
// Audio Processing module builder
webrtc::AudioProcessingBuilder ap_builder;
-#endif
size_t apmFrameCount; // buffer size for webRTC process (10 ms)
uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
@@ -124,42 +115,25 @@
uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
uint32_t processedMsk; // bit field containing IDs of pre processors already
// processed in current round
-#ifdef WEBRTC_LEGACY
- webrtc::AudioFrame* procFrame; // audio frame passed to webRTC AMP ProcessStream()
-#else
// audio config strucutre
webrtc::AudioProcessing::Config config;
webrtc::StreamConfig inputConfig; // input stream configuration
webrtc::StreamConfig outputConfig; // output stream configuration
-#endif
int16_t* inBuf; // input buffer used when resampling
size_t inBufSize; // input buffer size in frames
size_t framesIn; // number of frames in input buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState* inResampler; // handle on input speex resampler
-#endif
int16_t* outBuf; // output buffer used when resampling
size_t outBufSize; // output buffer size in frames
size_t framesOut; // number of frames in output buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState* outResampler; // handle on output speex resampler
-#endif
uint32_t revChannelCount; // number of channels on reverse stream
uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
// with reverse channel
uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
// channel already processed in current round
-#ifdef WEBRTC_LEGACY
- webrtc::AudioFrame* revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream()
-#else
webrtc::StreamConfig revConfig; // reverse stream configuration.
-#endif
int16_t* revBuf; // reverse channel input buffer
size_t revBufSize; // reverse channel input buffer size
size_t framesRev; // number of frames in reverse channel input buffer
-#ifdef WEBRTC_LEGACY
- SpeexResamplerState* revResampler; // handle on reverse channel input speex resampler
-#endif
};
#ifdef DUAL_MIC_TEST
@@ -213,7 +187,6 @@
"Automatic Gain Control",
"The Android Open Source Project"};
-#ifndef WEBRTC_LEGACY
// Automatic Gain Control 2
static const effect_descriptor_t sAgc2Descriptor = {
{0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
@@ -224,7 +197,6 @@
0, // FIXME indicate memory usage
"Automatic Gain Control 2",
"The Android Open Source Project"};
-#endif
// Acoustic Echo Cancellation
static const effect_descriptor_t sAecDescriptor = {
@@ -249,9 +221,7 @@
"The Android Open Source Project"};
static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
-#ifndef WEBRTC_LEGACY
&sAgc2Descriptor,
-#endif
&sAecDescriptor,
&sNsDescriptor};
@@ -260,9 +230,7 @@
//------------------------------------------------------------------------------
const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
-#ifndef WEBRTC_LEGACY
FX_IID_AGC2,
-#endif
FX_IID_AEC, FX_IID_NS};
const effect_uuid_t* ProcIdToUuid(int procId) {
@@ -297,7 +265,6 @@
static const int kAgcDefaultCompGain = 9;
static const bool kAgcDefaultLimiter = true;
-#ifndef WEBRTC_LEGACY
int Agc2Init(preproc_effect_t* effect) {
ALOGV("Agc2Init");
effect->session->config = effect->session->apm->GetConfig();
@@ -308,48 +275,27 @@
effect->session->apm->ApplyConfig(effect->session->config);
return 0;
}
-#endif
int AgcInit(preproc_effect_t* effect) {
ALOGV("AgcInit");
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
- agc->set_mode(webrtc::GainControl::kFixedDigital);
- agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
- agc->set_compression_gain_db(kAgcDefaultCompGain);
- agc->enable_limiter(kAgcDefaultLimiter);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return 0;
}
-#ifndef WEBRTC_LEGACY
int Agc2Create(preproc_effect_t* effect) {
Agc2Init(effect);
return 0;
}
-#endif
int AgcCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = effect->session->apm->gain_control();
- ALOGV("AgcCreate got agc %p", agc);
- if (agc == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(agc);
-#endif
AgcInit(effect);
return 0;
}
-#ifndef WEBRTC_LEGACY
int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
uint32_t param = *(uint32_t*)pParam;
@@ -422,15 +368,11 @@
return status;
}
-#endif
int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
int status = 0;
uint32_t param = *(uint32_t*)pParam;
t_agc_settings* pProperties = (t_agc_settings*)pValue;
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-#endif
switch (param) {
case AGC_PARAM_TARGET_LEVEL:
@@ -459,32 +401,6 @@
break;
}
-#ifdef WEBRTC_LEGACY
- switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- *(int16_t*)pValue = (int16_t)(agc->target_level_dbfs() * -100);
- ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
- break;
- case AGC_PARAM_COMP_GAIN:
- *(int16_t*)pValue = (int16_t)(agc->compression_gain_db() * 100);
- ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
- break;
- case AGC_PARAM_LIMITER_ENA:
- *(bool*)pValue = (bool)agc->is_limiter_enabled();
- ALOGV("AgcGetParameter() limiter enabled %s",
- (*(int16_t*)pValue != 0) ? "true" : "false");
- break;
- case AGC_PARAM_PROPERTIES:
- pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
- pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
- pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
- break;
- default:
- ALOGW("AgcGetParameter() unknown param %d", param);
- status = -EINVAL;
- break;
- }
-#else
effect->session->config = effect->session->apm->GetConfig();
switch (param) {
case AGC_PARAM_TARGET_LEVEL:
@@ -515,11 +431,9 @@
status = -EINVAL;
break;
}
-#endif
return status;
}
-#ifndef WEBRTC_LEGACY
int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
uint32_t param = *(uint32_t*)pParam;
@@ -567,43 +481,9 @@
return status;
}
-#endif
int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
-#ifdef WEBRTC_LEGACY
- uint32_t param = *(uint32_t*)pParam;
- t_agc_settings* pProperties = (t_agc_settings*)pValue;
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-
- switch (param) {
- case AGC_PARAM_TARGET_LEVEL:
- ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
- status = agc->set_target_level_dbfs(-(*(int16_t*)pValue / 100));
- break;
- case AGC_PARAM_COMP_GAIN:
- ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
- status = agc->set_compression_gain_db(*(int16_t*)pValue / 100);
- break;
- case AGC_PARAM_LIMITER_ENA:
- ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
- status = agc->enable_limiter(*(bool*)pValue);
- break;
- case AGC_PARAM_PROPERTIES:
- ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
- pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
- status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
- if (status != 0) break;
- status = agc->set_compression_gain_db(pProperties->compGain / 100);
- if (status != 0) break;
- status = agc->enable_limiter(pProperties->limiterEnabled);
- break;
- default:
- ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
- status = -EINVAL;
- break;
- }
-#else
uint32_t param = *(uint32_t*)pParam;
t_agc_settings* pProperties = (t_agc_settings*)pValue;
effect->session->config = effect->session->apm->GetConfig();
@@ -637,96 +517,57 @@
break;
}
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
ALOGV("AgcSetParameter() done status %d", status);
return status;
}
-#ifndef WEBRTC_LEGACY
void Agc2Enable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
}
-#endif
void AgcEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
- ALOGV("AgcEnable agc %p", agc);
- agc->Enable(true);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
-#ifndef WEBRTC_LEGACY
void Agc2Disable(preproc_effect_t* effect) {
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
}
-#endif
void AgcDisable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- ALOGV("AgcDisable");
- webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
- agc->Enable(false);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller1.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
AgcSetParameter, AgcGetParameter, NULL};
-#ifndef WEBRTC_LEGACY
static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
Agc2Enable, Agc2Disable, Agc2SetParameter,
Agc2GetParameter, NULL};
-#endif
//------------------------------------------------------------------------------
// Acoustic Echo Canceler (AEC)
//------------------------------------------------------------------------------
-#ifdef WEBRTC_LEGACY
-static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
- webrtc::EchoControlMobile::kEarpiece;
-static const bool kAecDefaultComfortNoise = true;
-#endif
int AecInit(preproc_effect_t* effect) {
ALOGV("AecInit");
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- aec->set_routing_mode(kAecDefaultMode);
- aec->enable_comfort_noise(kAecDefaultComfortNoise);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.mobile_mode = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return 0;
}
int AecCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = effect->session->apm->echo_control_mobile();
- ALOGV("AecCreate got aec %p", aec);
- if (aec == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(aec);
-#endif
AecInit(effect);
return 0;
}
@@ -744,13 +585,11 @@
*(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
break;
-#ifndef WEBRTC_LEGACY
case AEC_PARAM_MOBILE_MODE:
effect->session->config = effect->session->apm->GetConfig();
*(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
break;
-#endif
default:
ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
status = -EINVAL;
@@ -770,14 +609,12 @@
status = effect->session->apm->set_stream_delay_ms(value / 1000);
ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
break;
-#ifndef WEBRTC_LEGACY
case AEC_PARAM_MOBILE_MODE:
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.mobile_mode = value;
ALOGV("AecSetParameter() mobile mode %d us", value);
effect->session->apm->ApplyConfig(effect->session->config);
break;
-#endif
default:
ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
status = -EINVAL;
@@ -787,57 +624,24 @@
}
void AecEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- ALOGV("AecEnable aec %p", aec);
- aec->Enable(true);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
void AecDisable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- ALOGV("AecDisable");
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- aec->Enable(false);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.echo_canceller.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
ALOGV("AecSetDevice %08x", device);
-#ifdef WEBRTC_LEGACY
- webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
- webrtc::EchoControlMobile::RoutingMode mode =
- webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
-#endif
if (audio_is_input_device(device)) {
return 0;
}
-#ifdef WEBRTC_LEGACY
- switch (device) {
- case AUDIO_DEVICE_OUT_EARPIECE:
- mode = webrtc::EchoControlMobile::kEarpiece;
- break;
- case AUDIO_DEVICE_OUT_SPEAKER:
- mode = webrtc::EchoControlMobile::kSpeakerphone;
- break;
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- case AUDIO_DEVICE_OUT_USB_HEADSET:
- default:
- break;
- }
- aec->set_routing_mode(mode);
-#endif
return 0;
}
@@ -849,49 +653,19 @@
// Noise Suppression (NS)
//------------------------------------------------------------------------------
-#ifdef WEBRTC_LEGACY
-static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
-#else
static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
-#endif
int NsInit(preproc_effect_t* effect) {
ALOGV("NsInit");
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- ns->set_level(kNsDefaultLevel);
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- // TODO(aluebs): Make the geometry settable.
- geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
- geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
- // The geometry needs to be set with Beamforming enabled.
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
- effect->session->apm->SetExtraOptions(config);
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
- effect->session->apm->SetExtraOptions(config);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.level = kNsDefaultLevel;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
effect->type = NS_TYPE_SINGLE_CHANNEL;
return 0;
}
int NsCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = effect->session->apm->noise_suppression();
- ALOGV("NsCreate got ns %p", ns);
- if (ns == NULL) {
- ALOGW("AgcCreate Error");
- return -ENOMEM;
- }
- effect->engine = static_cast<preproc_fx_handle_t>(ns);
-#endif
NsInit(effect);
return 0;
}
@@ -904,31 +678,6 @@
int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
int status = 0;
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- uint32_t param = *(uint32_t*)pParam;
- uint32_t value = *(uint32_t*)pValue;
- switch (param) {
- case NS_PARAM_LEVEL:
- ns->set_level((webrtc::NoiseSuppression::Level)value);
- ALOGV("NsSetParameter() level %d", value);
- break;
- case NS_PARAM_TYPE: {
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- bool is_beamforming_enabled = value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
- config.Set<webrtc::Beamforming>(
- new webrtc::Beamforming(is_beamforming_enabled, geometry));
- effect->session->apm->SetExtraOptions(config);
- effect->type = value;
- ALOGV("NsSetParameter() type %d", value);
- break;
- }
- default:
- ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
- status = -EINVAL;
- }
-#else
uint32_t param = *(uint32_t*)pParam;
uint32_t value = *(uint32_t*)pValue;
effect->session->config = effect->session->apm->GetConfig();
@@ -943,52 +692,28 @@
status = -EINVAL;
}
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
return status;
}
void NsEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- ALOGV("NsEnable ns %p", ns);
- ns->Enable(true);
- if (effect->type == NS_TYPE_MULTI_CHANNEL) {
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
- effect->session->apm->SetExtraOptions(config);
- }
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.enabled = true;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
void NsDisable(preproc_effect_t* effect) {
ALOGV("NsDisable");
-#ifdef WEBRTC_LEGACY
- webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
- ns->Enable(false);
- webrtc::Config config;
- std::vector<webrtc::Point> geometry;
- config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
- effect->session->apm->SetExtraOptions(config);
-#else
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.noise_suppression.enabled = false;
effect->session->apm->ApplyConfig(effect->session->config);
-#endif
}
static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
NsDisable, NsSetParameter, NsGetParameter, NULL};
static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
-#ifndef WEBRTC_LEGACY
&sAgc2Ops,
-#endif
&sAecOps, &sNsOps};
//------------------------------------------------------------------------------
@@ -1119,9 +844,6 @@
session->id = 0;
session->io = 0;
session->createdMsk = 0;
-#ifdef WEBRTC_LEGACY
- session->apm = NULL;
-#endif
for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
status = Effect_Init(&session->effects[i], i);
}
@@ -1135,75 +857,32 @@
ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
- session->apm = webrtc::AudioProcessing::Create();
- if (session->apm == NULL) {
- ALOGW("Session_CreateEffect could not get apm engine");
- goto error;
- }
- const webrtc::ProcessingConfig processing_config = {
- {{kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl},
- {kPreprocDefaultSr, kPreProcDefaultCnl}}};
- session->apm->Initialize(processing_config);
- session->procFrame = new webrtc::AudioFrame();
- if (session->procFrame == NULL) {
- ALOGW("Session_CreateEffect could not allocate audio frame");
- goto error;
- }
- session->revFrame = new webrtc::AudioFrame();
- if (session->revFrame == NULL) {
- ALOGW("Session_CreateEffect could not allocate reverse audio frame");
- goto error;
- }
-#else
session->apm = session->ap_builder.Create();
if (session->apm == NULL) {
ALOGW("Session_CreateEffect could not get apm engine");
goto error;
}
-#endif
session->apmSamplingRate = kPreprocDefaultSr;
session->apmFrameCount = (kPreprocDefaultSr) / 100;
session->frameCount = session->apmFrameCount;
session->samplingRate = kPreprocDefaultSr;
session->inChannelCount = kPreProcDefaultCnl;
session->outChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
- session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
- session->procFrame->num_channels_ = kPreProcDefaultCnl;
-#else
session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->inputConfig.set_num_channels(kPreProcDefaultCnl);
session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->outputConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
session->revChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
- session->revFrame->num_channels_ = kPreProcDefaultCnl;
-#else
session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
session->revConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
session->enabledMsk = 0;
session->processedMsk = 0;
session->revEnabledMsk = 0;
session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
- session->inResampler = NULL;
-#endif
session->inBuf = NULL;
session->inBufSize = 0;
-#ifdef WEBRTC_LEGACY
- session->outResampler = NULL;
-#endif
session->outBuf = NULL;
session->outBufSize = 0;
-#ifdef WEBRTC_LEGACY
- session->revResampler = NULL;
-#endif
session->revBuf = NULL;
session->revBufSize = 0;
}
@@ -1217,17 +896,8 @@
error:
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
- delete session->revFrame;
- session->revFrame = NULL;
- delete session->procFrame;
- session->procFrame = NULL;
- delete session->apm;
- session->apm = NULL; // NOLINT(clang-analyzer-cplusplus.NewDelete)
-#else
delete session->apm;
session->apm = NULL;
-#endif
}
return status;
}
@@ -1236,29 +906,8 @@
ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
session->createdMsk &= ~(1 << fx->procId);
if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
delete session->apm;
session->apm = NULL;
- delete session->procFrame;
- session->procFrame = NULL;
- delete session->revFrame;
- session->revFrame = NULL;
- if (session->inResampler != NULL) {
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- }
- if (session->outResampler != NULL) {
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- }
- if (session->revResampler != NULL) {
- speex_resampler_destroy(session->revResampler);
- session->revResampler = NULL;
- }
-#else
- delete session->apm;
- session->apm = NULL;
-#endif
delete session->inBuf;
session->inBuf = NULL;
delete session->outBuf;
@@ -1284,9 +933,6 @@
ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
- int status;
-#endif
// AEC implementation is limited to 16kHz
if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
@@ -1297,51 +943,25 @@
session->apmSamplingRate = 8000;
}
-#ifdef WEBRTC_LEGACY
- const webrtc::ProcessingConfig processing_config = {
- {{static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), outCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl}}};
- status = session->apm->Initialize(processing_config);
- if (status < 0) {
- return -EINVAL;
- }
-#endif
session->samplingRate = config->inputCfg.samplingRate;
session->apmFrameCount = session->apmSamplingRate / 100;
if (session->samplingRate == session->apmSamplingRate) {
session->frameCount = session->apmFrameCount;
} else {
-#ifdef WEBRTC_LEGACY
- session->frameCount =
- (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate + 1;
-#else
session->frameCount =
(session->apmFrameCount * session->samplingRate) / session->apmSamplingRate;
-#endif
}
session->inChannelCount = inCnl;
session->outChannelCount = outCnl;
-#ifdef WEBRTC_LEGACY
- session->procFrame->num_channels_ = inCnl;
- session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
session->inputConfig.set_sample_rate_hz(session->samplingRate);
session->inputConfig.set_num_channels(inCnl);
session->outputConfig.set_sample_rate_hz(session->samplingRate);
session->outputConfig.set_num_channels(inCnl);
-#endif
session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->num_channels_ = inCnl;
- session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
session->revConfig.set_sample_rate_hz(session->samplingRate);
session->revConfig.set_num_channels(inCnl);
-#endif
// force process buffer reallocation
session->inBufSize = 0;
@@ -1349,53 +969,6 @@
session->framesIn = 0;
session->framesOut = 0;
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- }
- if (session->outResampler != NULL) {
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- }
- if (session->revResampler != NULL) {
- speex_resampler_destroy(session->revResampler);
- session->revResampler = NULL;
- }
- if (session->samplingRate != session->apmSamplingRate) {
- int error;
- session->inResampler =
- speex_resampler_init(session->inChannelCount, session->samplingRate,
- session->apmSamplingRate, RESAMPLER_QUALITY, &error);
- if (session->inResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- return -EINVAL;
- }
- session->outResampler =
- speex_resampler_init(session->outChannelCount, session->apmSamplingRate,
- session->samplingRate, RESAMPLER_QUALITY, &error);
- if (session->outResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- return -EINVAL;
- }
- session->revResampler =
- speex_resampler_init(session->inChannelCount, session->samplingRate,
- session->apmSamplingRate, RESAMPLER_QUALITY, &error);
- if (session->revResampler == NULL) {
- ALOGW("Session_SetConfig Cannot create speex resampler: %s",
- speex_resampler_strerror(error));
- speex_resampler_destroy(session->inResampler);
- session->inResampler = NULL;
- speex_resampler_destroy(session->outResampler);
- session->outResampler = NULL;
- return -EINVAL;
- }
- }
-#endif
session->state = PREPROC_SESSION_STATE_CONFIG;
return 0;
@@ -1430,22 +1003,7 @@
return -EINVAL;
}
uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
- const webrtc::ProcessingConfig processing_config = {
- {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
- {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
- {static_cast<int>(session->apmSamplingRate), inCnl},
- {static_cast<int>(session->apmSamplingRate), inCnl}}};
- int status = session->apm->Initialize(processing_config);
- if (status < 0) {
- return -EINVAL;
- }
-#endif
session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
- session->revFrame->num_channels_ = inCnl;
- session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#endif
// force process buffer reallocation
session->revBufSize = 0;
session->framesRev = 0;
@@ -1467,24 +1025,10 @@
if (enabled) {
if (session->enabledMsk == 0) {
session->framesIn = 0;
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- speex_resampler_reset_mem(session->inResampler);
- }
- session->framesOut = 0;
- if (session->outResampler != NULL) {
- speex_resampler_reset_mem(session->outResampler);
- }
-#endif
}
session->enabledMsk |= (1 << procId);
if (HasReverseStream(procId)) {
session->framesRev = 0;
-#ifdef WEBRTC_LEGACY
- if (session->revResampler != NULL) {
- speex_resampler_reset_mem(session->revResampler);
- }
-#endif
session->revEnabledMsk |= (1 << procId);
}
} else {
@@ -1600,82 +1144,6 @@
return 0;
}
-#ifdef WEBRTC_LEGACY
- if (session->inResampler != NULL) {
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- if (session->inBufSize < session->framesIn + fr) {
- int16_t* buf;
- session->inBufSize = session->framesIn + fr;
- buf = (int16_t*)realloc(
- session->inBuf,
- session->inBufSize * session->inChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesIn = 0;
- free(session->inBuf);
- session->inBuf = NULL;
- return -ENOMEM;
- }
- session->inBuf = buf;
- }
- memcpy(session->inBuf + session->framesIn * session->inChannelCount, inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-#ifdef DUAL_MIC_TEST
- pthread_mutex_lock(&gPcmDumpLock);
- if (gPcmDumpFh != NULL) {
- fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
- gPcmDumpFh);
- }
- pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- spx_uint32_t frIn = session->framesIn;
- spx_uint32_t frOut = session->apmFrameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->inResampler, 0, session->inBuf, &frIn,
- session->procFrame->data_, &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->inResampler, session->inBuf, &frIn,
- session->procFrame->data_, &frOut);
- }
- memmove(session->inBuf, session->inBuf + frIn * session->inChannelCount,
- (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
- session->framesIn -= frIn;
- } else {
- size_t fr = session->frameCount - session->framesIn;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
- inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
-
-#ifdef DUAL_MIC_TEST
- pthread_mutex_lock(&gPcmDumpLock);
- if (gPcmDumpFh != NULL) {
- fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
- gPcmDumpFh);
- }
- pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
- session->framesIn += fr;
- inBuffer->frameCount = fr;
- if (session->framesIn < session->frameCount) {
- return 0;
- }
- session->framesIn = 0;
- }
- session->procFrame->samples_per_channel_ = session->apmFrameCount;
-
- effect->session->apm->ProcessStream(session->procFrame);
-#else
size_t fr = session->frameCount - session->framesIn;
if (inBuffer->frameCount < fr) {
fr = inBuffer->frameCount;
@@ -1696,7 +1164,6 @@
return status;
}
outBuffer->frameCount = inBuffer->frameCount;
-#endif
if (session->outBufSize < session->framesOut + session->frameCount) {
int16_t* buf;
@@ -1713,30 +1180,7 @@
session->outBuf = buf;
}
-#ifdef WEBRTC_LEGACY
- if (session->outResampler != NULL) {
- spx_uint32_t frIn = session->apmFrameCount;
- spx_uint32_t frOut = session->frameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(
- session->outResampler, 0, session->procFrame->data_, &frIn,
- session->outBuf + session->framesOut * session->outChannelCount, &frOut);
- } else {
- speex_resampler_process_interleaved_int(
- session->outResampler, session->procFrame->data_, &frIn,
- session->outBuf + session->framesOut * session->outChannelCount, &frOut);
- }
- session->framesOut += frOut;
- } else {
- memcpy(session->outBuf + session->framesOut * session->outChannelCount,
- session->procFrame->data_,
- session->frameCount * session->outChannelCount * sizeof(int16_t));
- session->framesOut += session->frameCount;
- }
- size_t fr = session->framesOut;
-#else
fr = session->framesOut;
-#endif
if (framesRq - framesWr < fr) {
fr = framesRq - framesWr;
}
@@ -2129,63 +1573,6 @@
if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
effect->session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
- if (session->revResampler != NULL) {
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- if (session->revBufSize < session->framesRev + fr) {
- int16_t* buf;
- session->revBufSize = session->framesRev + fr;
- buf = (int16_t*)realloc(
- session->revBuf,
- session->revBufSize * session->inChannelCount * sizeof(int16_t));
- if (buf == NULL) {
- session->framesRev = 0;
- free(session->revBuf);
- session->revBuf = NULL;
- return -ENOMEM;
- }
- session->revBuf = buf;
- }
- memcpy(session->revBuf + session->framesRev * session->inChannelCount, inBuffer->s16,
- fr * session->inChannelCount * sizeof(int16_t));
-
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- spx_uint32_t frIn = session->framesRev;
- spx_uint32_t frOut = session->apmFrameCount;
- if (session->inChannelCount == 1) {
- speex_resampler_process_int(session->revResampler, 0, session->revBuf, &frIn,
- session->revFrame->data_, &frOut);
- } else {
- speex_resampler_process_interleaved_int(session->revResampler, session->revBuf,
- &frIn, session->revFrame->data_, &frOut);
- }
- memmove(session->revBuf, session->revBuf + frIn * session->inChannelCount,
- (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
- session->framesRev -= frIn;
- } else {
- size_t fr = session->frameCount - session->framesRev;
- if (inBuffer->frameCount < fr) {
- fr = inBuffer->frameCount;
- }
- memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
- inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
- session->framesRev += fr;
- inBuffer->frameCount = fr;
- if (session->framesRev < session->frameCount) {
- return 0;
- }
- session->framesRev = 0;
- }
- session->revFrame->samples_per_channel_ = session->apmFrameCount;
- effect->session->apm->AnalyzeReverseStream(session->revFrame);
-#else
size_t fr = session->frameCount - session->framesRev;
if (inBuffer->frameCount < fr) {
fr = inBuffer->frameCount;
@@ -2205,7 +1592,6 @@
ALOGE("Process Reverse Stream failed with error %d\n", status);
return status;
}
-#endif
return 0;
} else {
return -ENODATA;
diff --git a/media/libeffects/preprocessing/benchmarks/Android.bp b/media/libeffects/preprocessing/benchmarks/Android.bp
index 2808293..262fd19 100644
--- a/media/libeffects/preprocessing/benchmarks/Android.bp
+++ b/media/libeffects/preprocessing/benchmarks/Android.bp
@@ -1,31 +1,4 @@
cc_benchmark {
- name: "preprocessing_legacy_benchmark",
- vendor: true,
- relative_install_path: "soundfx",
- srcs: ["preprocessing_benchmark.cpp"],
- shared_libs: [
- "libaudiopreprocessing_legacy",
- "libaudioutils",
- "liblog",
- "libutils",
- "libwebrtc_audio_preprocessing",
- ],
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- "libwebrtc_absl_headers",
- ],
-}
-
-cc_benchmark {
name: "preprocessing_benchmark",
vendor: true,
relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
index 3a0ad6d..694a6c4 100644
--- a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
+++ b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
@@ -54,9 +54,7 @@
#include <cstdlib>
#include <random>
#include <vector>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <benchmark/benchmark.h>
#include <hardware/audio_effect.h>
@@ -76,10 +74,8 @@
{0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
// ns uuid
{0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
-#ifndef WEBRTC_LEGACY
// agc2 uuid
{0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},
-#endif
};
constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
constexpr audio_channel_mask_t kChMasks[] = {
@@ -93,9 +89,7 @@
PREPROC_AGC, // Automatic Gain Control
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
-#ifndef WEBRTC_LEGACY
PREPROC_AGC2, // Automatic Gain Control 2
-#endif
PREPROC_NUM_EFFECTS
};
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index 045b0d3..b439880 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -1,37 +1,5 @@
// audio preprocessing unit test
cc_test {
- name: "AudioPreProcessingLegacyTest",
-
- vendor: true,
-
- relative_install_path: "soundfx",
-
- srcs: ["PreProcessingTest.cpp"],
-
- shared_libs: [
- "libaudiopreprocessing_legacy",
- "libaudioutils",
- "liblog",
- "libutils",
- "libwebrtc_audio_preprocessing",
- ],
-
- cflags: [
- "-DWEBRTC_POSIX",
- "-DWEBRTC_LEGACY",
- "-fvisibility=default",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
-
- header_libs: [
- "libaudioeffects",
- "libhardware_headers",
- ],
-}
-
-cc_test {
name: "AudioPreProcessingTest",
vendor: true,
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 65b9469..5f223c9 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -22,9 +22,7 @@
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_agc.h>
-#ifndef WEBRTC_LEGACY
#include <audio_effects/effect_agc2.h>
-#endif
#include <audio_effects/effect_ns.h>
#include <log/log.h>
@@ -38,9 +36,7 @@
// types of pre processing modules
enum PreProcId {
PREPROC_AGC, // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
PREPROC_AGC2, // Automatic Gain Control 2
-#endif
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
PREPROC_NUM_EFFECTS
@@ -57,11 +53,9 @@
ARG_AGC_COMP_LVL,
ARG_AEC_DELAY,
ARG_NS_LVL,
-#ifndef WEBRTC_LEGACY
ARG_AGC2_GAIN,
ARG_AGC2_LVL,
ARG_AGC2_SAT_MGN
-#endif
};
struct preProcConfigParams_t {
@@ -70,19 +64,15 @@
int nsLevel = 0; // a value between 0-3
int agcTargetLevel = 3; // in dB
int agcCompLevel = 9; // in dB
-#ifndef WEBRTC_LEGACY
float agc2Gain = 0.f; // in dB
float agc2SaturationMargin = 2.f; // in dB
int agc2Level = 0; // either kRms(0) or kPeak(1)
-#endif
int aecDelay = 0; // in ms
};
const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
{0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // agc uuid
-#ifndef WEBRTC_LEGACY
{0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // agc2 uuid
-#endif
{0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // aec uuid
{0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // ns uuid
};
@@ -138,24 +128,20 @@
printf("\n Enable Noise Suppression, default disabled");
printf("\n --agc");
printf("\n Enable Gain Control, default disabled");
-#ifndef WEBRTC_LEGACY
printf("\n --agc2");
printf("\n Enable Gain Controller 2, default disabled");
-#endif
printf("\n --ns_lvl <ns_level>");
printf("\n Noise Suppression level in dB, default value 0dB");
printf("\n --agc_tgt_lvl <target_level>");
printf("\n AGC Target Level in dB, default value 3dB");
printf("\n --agc_comp_lvl <comp_level>");
printf("\n AGC Comp Level in dB, default value 9dB");
-#ifndef WEBRTC_LEGACY
printf("\n --agc2_gain <fixed_digital_gain>");
printf("\n AGC Fixed Digital Gain in dB, default value 0dB");
printf("\n --agc2_lvl <level_estimator>");
printf("\n AGC Adaptive Digital Level Estimator, default value kRms");
printf("\n --agc2_sat_mgn <saturation_margin>");
printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
-#endif
printf("\n --aec_delay <delay>");
printf("\n AEC delay value in ms, default value 0ms");
printf("\n");
@@ -217,18 +203,14 @@
{"ch_mask", required_argument, nullptr, ARG_CH_MASK},
{"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
{"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
-#ifndef WEBRTC_LEGACY
{"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
{"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
{"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
-#endif
{"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
{"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
{"aec", no_argument, &effectEn[PREPROC_AEC], 1},
{"agc", no_argument, &effectEn[PREPROC_AGC], 1},
-#ifndef WEBRTC_LEGACY
{"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
-#endif
{"ns", no_argument, &effectEn[PREPROC_NS], 1},
{nullptr, 0, nullptr, 0},
};
@@ -277,7 +259,6 @@
preProcCfgParams.agcCompLevel = atoi(optarg);
break;
}
-#ifndef WEBRTC_LEGACY
case ARG_AGC2_GAIN: {
preProcCfgParams.agc2Gain = atof(optarg);
break;
@@ -290,7 +271,6 @@
preProcCfgParams.agc2SaturationMargin = atof(optarg);
break;
}
-#endif
case ARG_AEC_DELAY: {
preProcCfgParams.aecDelay = atoi(optarg);
break;
@@ -387,7 +367,6 @@
return EXIT_FAILURE;
}
}
-#ifndef WEBRTC_LEGACY
if (effectEn[PREPROC_AGC2]) {
if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
(float)preProcCfgParams.agc2Gain,
@@ -411,7 +390,6 @@
return EXIT_FAILURE;
}
}
-#endif
if (effectEn[PREPROC_NS]) {
if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
effectHandle[PREPROC_NS]);
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 1fe6ffc..fba1a30 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -74,6 +74,8 @@
METADATA_KEY_SAMPLERATE = 38,
METADATA_KEY_BITS_PER_SAMPLE = 39,
METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40,
+ METADATA_KEY_XMP_OFFSET = 41,
+ METADATA_KEY_XMP_LENGTH = 42,
// Add more here...
};
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 1cc255d..89c7032 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -127,7 +127,8 @@
pid_t pid = IPCThreadState::self()->getCallingPid();
uid_t uid = IPCThreadState::self()->getCallingUid();
- if ((as == AUDIO_SOURCE_FM_TUNER && !captureAudioOutputAllowed(pid, uid))
+ if ((as == AUDIO_SOURCE_FM_TUNER
+ && !(captureAudioOutputAllowed(pid, uid) || captureTunerAudioInputAllowed(pid, uid)))
|| !recordingAllowed(String16(""), pid, uid)) {
return PERMISSION_DENIED;
}
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 02fb6bb..93e03ee 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -529,6 +529,15 @@
mMetaData.add(METADATA_KEY_EXIF_LENGTH, String8(tmp));
}
+ int64_t xmpOffset, xmpSize;
+ if (meta->findInt64(kKeyXmpOffset, &xmpOffset)
+ && meta->findInt64(kKeyXmpSize, &xmpSize)) {
+ sprintf(tmp, "%lld", (long long)xmpOffset);
+ mMetaData.add(METADATA_KEY_XMP_OFFSET, String8(tmp));
+ sprintf(tmp, "%lld", (long long)xmpSize);
+ mMetaData.add(METADATA_KEY_XMP_LENGTH, String8(tmp));
+ }
+
bool hasAudio = false;
bool hasVideo = false;
int32_t videoWidth = -1;
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/libmediatranscoding/TranscodingSessionController.cpp
index 49a7083..b77a3a4 100644
--- a/media/libmediatranscoding/TranscodingSessionController.cpp
+++ b/media/libmediatranscoding/TranscodingSessionController.cpp
@@ -31,6 +31,7 @@
static_assert((SessionIdType)-1 < 0, "SessionIdType should be signed");
constexpr static uid_t OFFLINE_UID = -1;
+constexpr static size_t kSessionHistoryMax = 100;
//static
String8 TranscodingSessionController::sessionToString(const SessionKeyType& sessionKey) {
@@ -47,6 +48,12 @@
return "RUNNING";
case Session::State::PAUSED:
return "PAUSED";
+ case Session::State::FINISHED:
+ return "FINISHED";
+ case Session::State::CANCELED:
+ return "CANCELED";
+ case Session::State::ERROR:
+ return "ERROR";
default:
break;
}
@@ -71,6 +78,30 @@
TranscodingSessionController::~TranscodingSessionController() {}
+void TranscodingSessionController::dumpSession_l(const Session& session, String8& result,
+ bool closedSession) {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ const TranscodingRequestParcel& request = session.request;
+ snprintf(buffer, SIZE, " Session: %s, %s, %d%%\n", sessionToString(session.key).c_str(),
+ sessionStateToString(session.getState()), session.lastProgress);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " pkg: %s\n", request.clientPackageName.c_str());
+ result.append(buffer);
+ snprintf(buffer, SIZE, " src: %s\n", request.sourceFilePath.c_str());
+ result.append(buffer);
+ snprintf(buffer, SIZE, " dst: %s\n", request.destinationFilePath.c_str());
+ result.append(buffer);
+
+ if (closedSession) {
+ snprintf(buffer, SIZE,
+ " waiting: %.1fs, running: %.1fs, paused: %.1fs, paused count: %d\n",
+ session.waitingTime.count() / 1000000.0f, session.runningTime.count() / 1000000.0f,
+ session.pausedTime.count() / 1000000.0f, session.pauseCount);
+ result.append(buffer);
+ }
+}
+
void TranscodingSessionController::dumpAllSessions(int fd, const Vector<String16>& args __unused) {
String8 result;
@@ -78,7 +109,7 @@
char buffer[SIZE];
std::scoped_lock lock{mLock};
- snprintf(buffer, SIZE, "\n========== Dumping all sessions queues =========\n");
+ snprintf(buffer, SIZE, "\n========== Dumping live sessions queues =========\n");
result.append(buffer);
snprintf(buffer, SIZE, " Total num of Sessions: %zu\n", mSessionMap.size());
result.append(buffer);
@@ -91,7 +122,7 @@
if (mSessionQueues[uid].empty()) {
continue;
}
- snprintf(buffer, SIZE, " Uid: %d, pkg: %s\n", uid,
+ snprintf(buffer, SIZE, " uid: %d, pkg: %s\n", uid,
mUidPackageNames.count(uid) > 0 ? mUidPackageNames[uid].c_str() : "(unknown)");
result.append(buffer);
snprintf(buffer, SIZE, " Num of sessions: %zu\n", mSessionQueues[uid].size());
@@ -104,25 +135,16 @@
result.append(buffer);
continue;
}
- Session& session = sessionIt->second;
- TranscodingRequestParcel& request = session.request;
- snprintf(buffer, SIZE, " Session: %s, %s, %d%%\n",
- sessionToString(sessionKey).c_str(), sessionStateToString(session.state),
- session.lastProgress);
- result.append(buffer);
- snprintf(buffer, SIZE, " Src: %s\n", request.sourceFilePath.c_str());
- result.append(buffer);
- snprintf(buffer, SIZE, " Dst: %s\n", request.destinationFilePath.c_str());
- result.append(buffer);
- // For the offline queue, print out the original client.
- if (uid == OFFLINE_UID) {
- snprintf(buffer, SIZE, " Original Client: %s\n",
- request.clientPackageName.c_str());
- result.append(buffer);
- }
+ dumpSession_l(sessionIt->second, result);
}
}
+ snprintf(buffer, SIZE, "\n========== Dumping past sessions =========\n");
+ result.append(buffer);
+ for (auto &session : mSessionHistory) {
+ dumpSession_l(session, result, true /*closedSession*/);
+ }
+
write(fd, result.string(), result.size());
}
@@ -135,6 +157,34 @@
return &mSessionMap[topSessionKey];
}
+void TranscodingSessionController::Session::setState(Session::State newState) {
+ if (state == newState) {
+ return;
+ }
+ auto nowTime = std::chrono::system_clock::now();
+ if (state != INVALID) {
+ std::chrono::microseconds elapsedTime = (nowTime - stateEnterTime);
+ switch (state) {
+ case PAUSED:
+ pausedTime = pausedTime + elapsedTime;
+ break;
+ case RUNNING:
+ runningTime = runningTime + elapsedTime;
+ break;
+ case NOT_STARTED:
+ waitingTime = waitingTime + elapsedTime;
+ break;
+ default:
+ break;
+ }
+ }
+ if (newState == PAUSED) {
+ pauseCount++;
+ }
+ stateEnterTime = nowTime;
+ state = newState;
+}
+
void TranscodingSessionController::updateCurrentSession_l() {
Session* topSession = getTopSession_l();
Session* curSession = mCurrentSession;
@@ -145,29 +195,30 @@
// If we found a topSession that should be run, and it's not already running,
// take some actions to ensure it's running.
if (topSession != nullptr &&
- (topSession != curSession || topSession->state != Session::RUNNING)) {
+ (topSession != curSession || topSession->getState() != Session::RUNNING)) {
// If another session is currently running, pause it first.
- if (curSession != nullptr && curSession->state == Session::RUNNING) {
+ if (curSession != nullptr && curSession->getState() == Session::RUNNING) {
mTranscoder->pause(curSession->key.first, curSession->key.second);
- curSession->state = Session::PAUSED;
+ curSession->setState(Session::PAUSED);
}
// If we are not experiencing resource loss, we can start or resume
// the topSession now.
if (!mResourceLost) {
- if (topSession->state == Session::NOT_STARTED) {
+ if (topSession->getState() == Session::NOT_STARTED) {
mTranscoder->start(topSession->key.first, topSession->key.second,
topSession->request, topSession->callback.lock());
- } else if (topSession->state == Session::PAUSED) {
+ } else if (topSession->getState() == Session::PAUSED) {
mTranscoder->resume(topSession->key.first, topSession->key.second,
topSession->request, topSession->callback.lock());
}
- topSession->state = Session::RUNNING;
+ topSession->setState(Session::RUNNING);
}
}
mCurrentSession = topSession;
}
-void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey) {
+void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey,
+ Session::State finalState) {
ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());
if (mSessionMap.count(sessionKey) == 0) {
@@ -201,6 +252,12 @@
mCurrentSession = nullptr;
}
+ mSessionMap[sessionKey].setState(finalState);
+ mSessionHistory.push_back(mSessionMap[sessionKey]);
+ if (mSessionHistory.size() > kSessionHistoryMax) {
+ mSessionHistory.erase(mSessionHistory.begin());
+ }
+
// Remove session from session map.
mSessionMap.erase(sessionKey);
}
@@ -288,10 +345,11 @@
// Add session to session map.
mSessionMap[sessionKey].key = sessionKey;
mSessionMap[sessionKey].uid = uid;
- mSessionMap[sessionKey].state = Session::NOT_STARTED;
mSessionMap[sessionKey].lastProgress = 0;
+ mSessionMap[sessionKey].pauseCount = 0;
mSessionMap[sessionKey].request = request;
mSessionMap[sessionKey].callback = callback;
+ mSessionMap[sessionKey].setState(Session::NOT_STARTED);
// If it's an offline session, the queue was already added in constructor.
// If it's a real-time sessions, check if a queue is already present for the uid,
@@ -350,12 +408,12 @@
// Note that stop() is needed even if the session is currently paused. This instructs
// the transcoder to discard any states for the session, otherwise the states may
// never be discarded.
- if (mSessionMap[*it].state != Session::NOT_STARTED) {
+ if (mSessionMap[*it].getState() != Session::NOT_STARTED) {
mTranscoder->stop(it->first, it->second);
}
// Remove the session.
- removeSession_l(*it);
+ removeSession_l(*it, Session::CANCELED);
}
// Start next session.
@@ -396,7 +454,7 @@
// Only ignore if session was never started. In particular, propagate the status
// to client if the session is paused. Transcoder could have posted finish when
// we're pausing it, and the finish arrived after we changed current session.
- if (mSessionMap[sessionKey].state == Session::NOT_STARTED) {
+ if (mSessionMap[sessionKey].getState() == Session::NOT_STARTED) {
ALOGW("%s: ignoring %s for session %s that was never started", __FUNCTION__, reason,
sessionToString(sessionKey).c_str());
return;
@@ -445,7 +503,7 @@
}
// Remove the session.
- removeSession_l(sessionKey);
+ removeSession_l(sessionKey, Session::FINISHED);
// Start next session.
updateCurrentSession_l();
@@ -465,7 +523,7 @@
}
// Remove the session.
- removeSession_l(sessionKey);
+ removeSession_l(sessionKey, Session::ERROR);
// Start next session.
updateCurrentSession_l();
@@ -494,15 +552,15 @@
}
Session* resourceLostSession = &mSessionMap[sessionKey];
- if (resourceLostSession->state != Session::RUNNING) {
+ if (resourceLostSession->getState() != Session::RUNNING) {
ALOGW("session %s lost resource but is no longer running",
- sessionToString(sessionKey).c_str());
+ sessionToString(sessionKey).c_str());
return;
}
// If we receive a resource loss event, the transcoder already paused the transcoding,
// so we don't need to call onPaused() to pause it. However, we still need to notify
// the client and update the session state here.
- resourceLostSession->state = Session::PAUSED;
+ resourceLostSession->setState(Session::PAUSED);
// Notify the client as a paused event.
auto clientCallback = resourceLostSession->callback.lock();
if (clientCallback != nullptr) {
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/libmediatranscoding/include/media/TranscodingSessionController.h
index 4215e06..a443265 100644
--- a/media/libmediatranscoding/include/media/TranscodingSessionController.h
+++ b/media/libmediatranscoding/include/media/TranscodingSessionController.h
@@ -26,6 +26,7 @@
#include <utils/String8.h>
#include <utils/Vector.h>
+#include <chrono>
#include <list>
#include <map>
#include <mutex>
@@ -82,16 +83,33 @@
using SessionQueueType = std::list<SessionKeyType>;
struct Session {
- SessionKeyType key;
- uid_t uid;
enum State {
- NOT_STARTED,
+ INVALID = -1,
+ NOT_STARTED = 0,
RUNNING,
PAUSED,
- } state;
+ FINISHED,
+ CANCELED,
+ ERROR,
+ };
+ SessionKeyType key;
+ uid_t uid;
int32_t lastProgress;
+ int32_t pauseCount;
+ std::chrono::time_point<std::chrono::system_clock> stateEnterTime;
+ std::chrono::microseconds waitingTime;
+ std::chrono::microseconds runningTime;
+ std::chrono::microseconds pausedTime;
+
TranscodingRequest request;
std::weak_ptr<ITranscodingClientCallback> callback;
+
+ // Must use setState to change state.
+ void setState(Session::State state);
+ State getState() const { return state; }
+
+ private:
+ State state = INVALID;
};
// TODO(chz): call transcoder without global lock.
@@ -115,15 +133,17 @@
Session* mCurrentSession;
bool mResourceLost;
+ std::list<Session> mSessionHistory;
// Only allow MediaTranscodingService and unit tests to instantiate.
TranscodingSessionController(const std::shared_ptr<TranscoderInterface>& transcoder,
const std::shared_ptr<UidPolicyInterface>& uidPolicy,
const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
+ void dumpSession_l(const Session& session, String8& result, bool closedSession = false);
Session* getTopSession_l();
void updateCurrentSession_l();
- void removeSession_l(const SessionKeyType& sessionKey);
+ void removeSession_l(const SessionKeyType& sessionKey, Session::State finalState);
void moveUidsToTop_l(const std::unordered_set<uid_t>& uids, bool preserveTopUid);
void notifyClient(ClientIdType clientId, SessionIdType sessionId, const char* reason,
std::function<void(const SessionKeyType&)> func);
diff --git a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
index 92ba818..1a6e7ed 100644
--- a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
+++ b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
@@ -235,6 +235,33 @@
return AMEDIA_OK;
}
+media_status_t MediaSampleReaderNDK::unselectTrack(int trackIndex) {
+ std::scoped_lock lock(mExtractorMutex);
+
+ if (trackIndex < 0 || trackIndex >= mTrackCount) {
+ LOG(ERROR) << "Invalid trackIndex " << trackIndex << " for trackCount " << mTrackCount;
+ return AMEDIA_ERROR_INVALID_PARAMETER;
+ } else if (mExtractorTrackIndex >= 0) {
+ LOG(ERROR) << "unselectTrack must be called before sample reading begins.";
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+
+ auto it = mTrackSignals.find(trackIndex);
+ if (it == mTrackSignals.end()) {
+ LOG(ERROR) << "TrackIndex " << trackIndex << " is not selected";
+ return AMEDIA_ERROR_INVALID_PARAMETER;
+ }
+ mTrackSignals.erase(it);
+
+ media_status_t status = AMediaExtractor_unselectTrack(mExtractor, trackIndex);
+ if (status != AMEDIA_OK) {
+ LOG(ERROR) << "AMediaExtractor_selectTrack returned error: " << status;
+ return status;
+ }
+
+ return AMEDIA_OK;
+}
+
media_status_t MediaSampleReaderNDK::setEnforceSequentialAccess(bool enforce) {
LOG(DEBUG) << "setEnforceSequentialAccess( " << enforce << " )";
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 94a9a33..3d4ff15 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -275,12 +275,6 @@
return AMEDIA_ERROR_INVALID_PARAMETER;
}
- media_status_t status = mSampleReader->selectTrack(trackIndex);
- if (status != AMEDIA_OK) {
- LOG(ERROR) << "Unable to select track " << trackIndex;
- return status;
- }
-
std::shared_ptr<MediaTrackTranscoder> transcoder;
std::shared_ptr<AMediaFormat> format;
@@ -322,10 +316,17 @@
format = std::shared_ptr<AMediaFormat>(mergedFormat, &AMediaFormat_delete);
}
+ media_status_t status = mSampleReader->selectTrack(trackIndex);
+ if (status != AMEDIA_OK) {
+ LOG(ERROR) << "Unable to select track " << trackIndex;
+ return status;
+ }
+
status = transcoder->configure(mSampleReader, trackIndex, format);
if (status != AMEDIA_OK) {
LOG(ERROR) << "Configure track transcoder for track #" << trackIndex << " returned error "
<< status;
+ mSampleReader->unselectTrack(trackIndex);
return status;
}
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index b4cc65f..0695bdb 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -40,12 +40,16 @@
// Default key frame interval in seconds.
static constexpr float kDefaultKeyFrameIntervalSeconds = 1.0f;
// Default codec operating rate.
-static int32_t kDefaultCodecOperatingRate =
- base::GetIntProperty("debug.media.transcoding.codec_max_operating_rate", /*default*/ 240);
+static int32_t kDefaultCodecOperatingRate720P = base::GetIntProperty(
+ "debug.media.transcoding.codec_max_operating_rate_720P", /*default*/ 480);
+static int32_t kDefaultCodecOperatingRate1080P = base::GetIntProperty(
+ "debug.media.transcoding.codec_max_operating_rate_1080P", /*default*/ 240);
// Default codec priority.
static constexpr int32_t kDefaultCodecPriority = 1;
// Default bitrate, in case source estimation fails.
static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
+// Default frame rate.
+static constexpr int32_t kDefaultFrameRate = 30;
template <typename T>
void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
@@ -181,6 +185,25 @@
}
}
+// Search the default operating rate based on resolution.
+static int32_t getDefaultOperatingRate(AMediaFormat* encoderFormat) {
+ int32_t width, height;
+ if (AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_WIDTH, &width) && (width > 0) &&
+ AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_HEIGHT, &height) && (height > 0)) {
+ if ((width == 1280 && height == 720) || (width == 720 && height == 1280)) {
+ return kDefaultCodecOperatingRate720P;
+ } else if ((width == 1920 && height == 1080) || (width == 1080 && height == 1920)) {
+ return kDefaultCodecOperatingRate1080P;
+ } else {
+ LOG(WARNING) << "Could not find default operating rate: " << width << " " << height;
+ // Don't set operating rate if the correct dimensions are not found.
+ }
+ } else {
+ LOG(ERROR) << "Failed to get default operating rate due to missing resolution";
+ }
+ return -1;
+}
+
// Creates and configures the codecs.
media_status_t VideoTrackTranscoder::configureDestinationFormat(
const std::shared_ptr<AMediaFormat>& destinationFormat) {
@@ -211,10 +234,15 @@
SetDefaultFormatValueFloat(AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, encoderFormat,
kDefaultKeyFrameIntervalSeconds);
- SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat,
- kDefaultCodecOperatingRate);
- SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
+ int32_t operatingRate = getDefaultOperatingRate(encoderFormat);
+
+ if (operatingRate != -1) {
+ SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat, operatingRate);
+ }
+
+ SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
+ SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_FRAME_RATE, encoderFormat, kDefaultFrameRate);
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
// Always encode without rotation. The rotation degree will be transferred directly to
@@ -239,6 +267,7 @@
}
mEncoder = std::make_shared<CodecWrapper>(encoder, shared_from_this());
+ LOG(DEBUG) << "Configuring encoder with: " << AMediaFormat_toString(mDestinationFormat.get());
status = AMediaCodec_configure(mEncoder->getCodec(), mDestinationFormat.get(),
NULL /* surface */, NULL /* crypto */,
AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
@@ -286,6 +315,7 @@
CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(), kEncoderEntriesToCopy,
entryCount);
+ LOG(DEBUG) << "Configuring decoder with: " << AMediaFormat_toString(decoderFormat.get());
status = AMediaCodec_configure(mDecoder, decoderFormat.get(), mSurface, NULL /* crypto */,
0 /* flags */);
if (status != AMEDIA_OK) {
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
index 351d80b..d6ed2c6 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
@@ -167,6 +167,10 @@
return AMEDIA_OK;
}
+ media_status_t unselectTrack(int trackIndex __unused) override {
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+
media_status_t setEnforceSequentialAccess(bool enforce __unused) override { return AMEDIA_OK; }
media_status_t getEstimatedBitrateForTrack(int trackIndex __unused,
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
index 7b6fbef..5c7eeac 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
@@ -69,6 +69,13 @@
virtual media_status_t selectTrack(int trackIndex) = 0;
/**
+ * Undo a track selection.
+ * @param trackIndex The track to un-select.
+ * @return AMEDIA_OK on success.
+ */
+ virtual media_status_t unselectTrack(int trackIndex) = 0;
+
+ /**
* Toggles sequential access enforcement on or off. When the reader enforces sequential access
* calls to read sample information will block unless the underlying extractor points to the
* specified track.
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
index 2032def..30cc37f 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
@@ -48,6 +48,7 @@
size_t getTrackCount() const override;
AMediaFormat* getTrackFormat(int trackIndex) override;
media_status_t selectTrack(int trackIndex) override;
+ media_status_t unselectTrack(int trackIndex) override;
media_status_t setEnforceSequentialAccess(bool enforce) override;
media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) override;
media_status_t getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) override;
diff --git a/media/libmediatranscoding/transcoder/setloglevel.sh b/media/libmediatranscoding/transcoder/setloglevel.sh
new file mode 100755
index 0000000..5eb7b67
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/setloglevel.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+if [ $# -ne 1 ]
+then
+ echo Usage: $0 loglevel
+ exit 1
+fi
+
+level=$1
+echo Setting transcoder log level to $level
+
+# List all log tags
+declare -a tags=(
+ MediaTranscoder MediaTrackTranscoder VideoTrackTranscoder PassthroughTrackTranscoder
+ MediaSampleWriter MediaSampleReader MediaSampleQueue MediaTranscoderTests
+ MediaTrackTranscoderTests VideoTrackTranscoderTests PassthroughTrackTranscoderTests
+ MediaSampleWriterTests MediaSampleReaderNDKTests MediaSampleQueueTests)
+
+# Set log level for all tags
+for tag in "${tags[@]}"
+do
+ adb shell setprop log.tag.${tag} $level
+done
+
+# Pick up new settings
+adb shell stop && adb shell start
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index 5c59992..bfc1f3b 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -283,20 +283,22 @@
}
EXPECT_NE(videoFormat, nullptr);
+ if (videoFormat != nullptr) {
+ LOG(INFO) << "source video format: " << AMediaFormat_toString(mSourceVideoFormat.get());
+ LOG(INFO) << "transcoded video format: " << AMediaFormat_toString(videoFormat.get());
- LOG(INFO) << "source video format: " << AMediaFormat_toString(mSourceVideoFormat.get());
- LOG(INFO) << "transcoded video format: " << AMediaFormat_toString(videoFormat.get());
+ for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
+ EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
+ mSourceVideoFormat.get(), videoFormat.get()))
+ << "Failed at key " << kFieldsToPreserve[i].key;
+ }
- for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
- EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
- mSourceVideoFormat.get(), videoFormat.get()))
- << "Failed at key " << kFieldsToPreserve[i].key;
- }
-
- if (extraVerifiers != nullptr) {
- for (int i = 0; i < extraVerifiers->size(); ++i) {
- const FormatVerifierEntry& entry = (*extraVerifiers)[i];
- EXPECT_TRUE(entry.equal(entry.key, mSourceVideoFormat.get(), videoFormat.get()));
+ if (extraVerifiers != nullptr) {
+ for (int i = 0; i < extraVerifiers->size(); ++i) {
+ const FormatVerifierEntry& entry = (*extraVerifiers)[i];
+ EXPECT_TRUE(
+ entry.equal(entry.key, mSourceVideoFormat.get(), videoFormat.get()));
+ }
}
}
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index fbaa38e..f63740e 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -729,6 +729,8 @@
{
{ "exif-offset", kKeyExifOffset },
{ "exif-size", kKeyExifSize },
+ { "xmp-offset", kKeyXmpOffset },
+ { "xmp-size", kKeyXmpSize },
{ "target-time", kKeyTargetTime },
{ "thumbnail-time", kKeyThumbnailTime },
{ "timeUs", kKeyTime },
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index f260510..940bd86 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -225,6 +225,8 @@
kKeyExifSize = 'exsz', // int64_t, Exif data size
kKeyExifTiffOffset = 'thdr', // int32_t, if > 0, buffer contains exif data block with
// tiff hdr at specified offset
+ kKeyXmpOffset = 'xmof', // int64_t, XMP data offset
+ kKeyXmpSize = 'xmsz', // int64_t, XMP data size
kKeyPcmBigEndian = 'pcmb', // bool (int32_t)
// Key for ALAC Magic Cookie
diff --git a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
index 09a0f65..40fdff4 100644
--- a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
+++ b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
@@ -33,7 +33,7 @@
/**
* Allows to set RenderEngine backend to GLES (default) or Vulkan (NOT yet supported).
*/
-#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
+#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.stagefright.renderengine.backend"
struct ANativeWindowBuffer;
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 8d5c77f..ee7285d 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -17,6 +17,7 @@
shared_libs: [
"android.hardware.media.omx@1.0",
"libandroidicu",
+ "libfmq",
"libbinder",
"libhidlbase",
"liblog",
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 47214c5..8e673ca 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -384,6 +384,8 @@
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
+EXPORT const char* AMEDIAFORMAT_KEY_XMP_OFFSET = "xmp-offset";
+EXPORT const char* AMEDIAFORMAT_KEY_XMP_SIZE = "xmp-size";
EXPORT const char* AMEDIAFORMAT_KEY_YEAR = "year";
} // extern "C"
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 8f39929..0b9024f 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -325,6 +325,8 @@
#if __ANDROID_API__ >= 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/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 96f1710..237b66e 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -151,6 +151,8 @@
AMEDIAFORMAT_KEY_TRACK_ID; # var introduced=28
AMEDIAFORMAT_KEY_VALID_SAMPLES; # var introduced=29
AMEDIAFORMAT_KEY_WIDTH; # var introduced=21
+ AMEDIAFORMAT_KEY_XMP_OFFSET; # var introduced=31
+ AMEDIAFORMAT_KEY_XMP_SIZE; # var introduced=31
AMEDIAFORMAT_KEY_YEAR; # var introduced=29
AMediaCodecActionCode_isRecoverable; # introduced=28
AMediaCodecActionCode_isTransient; # introduced=28
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 491823e..7d7433a 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -22,6 +22,7 @@
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include "mediautils/ServiceUtilities.h"
+#include <system/audio-hal-enums.h>
#include <iterator>
#include <algorithm>
@@ -61,8 +62,20 @@
return packages[0];
}
+static int32_t getOpForSource(audio_source_t source) {
+ switch (source) {
+ case AUDIO_SOURCE_HOTWORD:
+ return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
+ case AUDIO_SOURCE_DEFAULT:
+ default:
+ return AppOpsManager::OP_RECORD_AUDIO;
+ }
+}
+
static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
- uid_t uid, bool start, bool isHotwordSource) {
+ uid_t uid, bool start, audio_source_t source) {
// Okay to not track in app ops as audio server or media server is us and if
// device is rooted security model is considered compromised.
// system_server loses its RECORD_AUDIO permission when a secondary
@@ -87,11 +100,8 @@
}
AppOpsManager appOps;
- const int32_t opRecordAudio = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
-
+ const int32_t op = getOpForSource(source);
if (start) {
- const int32_t op = isHotwordSource ?
- AppOpsManager::OP_RECORD_AUDIO_HOTWORD : opRecordAudio;
if (int32_t mode = appOps.startOpNoThrow(
op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false);
mode != AppOpsManager::MODE_ALLOWED) {
@@ -101,10 +111,10 @@
}
} else {
// Always use OP_RECORD_AUDIO for checks at creation time.
- if (int32_t mode = appOps.checkOp(opRecordAudio, uid, resolvedOpPackageName);
+ if (int32_t mode = appOps.checkOp(op, uid, resolvedOpPackageName);
mode != AppOpsManager::MODE_ALLOWED) {
ALOGE("Request check for \"%s\" (uid %d) denied by app op: %d, mode: %d",
- String8(resolvedOpPackageName).c_str(), uid, opRecordAudio, mode);
+ String8(resolvedOpPackageName).c_str(), uid, op, mode);
return false;
}
}
@@ -113,15 +123,14 @@
}
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
- return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false,
- /*is_hotword_source*/ false);
+ return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false, AUDIO_SOURCE_DEFAULT);
}
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource) {
- return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, isHotwordSource);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, audio_source_t source) {
+ return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, source);
}
-void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource) {
+void finishRecording(const String16& opPackageName, uid_t uid, audio_source_t source) {
// Okay to not track in app ops as audio server is us and if
// device is rooted security model is considered compromised.
if (isAudioServerOrRootUid(uid)) return;
@@ -134,8 +143,8 @@
}
AppOpsManager appOps;
- const int32_t op = isHotwordSource ? AppOpsManager::OP_RECORD_AUDIO_HOTWORD
- : appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+
+ const int32_t op = getOpForSource(source);
appOps.finishOp(op, uid, resolvedOpPackageName);
}
@@ -155,6 +164,14 @@
return ok;
}
+bool captureTunerAudioInputAllowed(pid_t pid, uid_t uid) {
+ if (isAudioServerOrRootUid(uid)) return true;
+ static const String16 sCaptureTunerAudioInput("android.permission.CAPTURE_TUNER_AUDIO_INPUT");
+ bool ok = PermissionCache::checkPermission(sCaptureTunerAudioInput, pid, uid);
+ if (!ok) ALOGV("Request requires android.permission.CAPTURE_TUNER_AUDIO_INPUT");
+ return ok;
+}
+
bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid) {
if (isAudioServerOrRootUid(uid)) return true;
static const String16 sCaptureVoiceCommOutput(
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 183155c..f4c815c 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <functional>
+#include <type_traits>
#include "fuzzer/FuzzedDataProvider.h"
#include "mediautils/ServiceUtilities.h"
@@ -44,7 +45,8 @@
FuzzedDataProvider data_provider(data, size);
uid_t uid = data_provider.ConsumeIntegral<uid_t>();
pid_t pid = data_provider.ConsumeIntegral<pid_t>();
- bool isHotword = data_provider.ConsumeBool();
+ audio_source_t source = static_cast<audio_source_t>(data_provider
+ .ConsumeIntegral<std::underlying_type_t<audio_source_t>>());
// There is not state here, and order is not significant,
// so we can simply call all of the target functions
@@ -55,8 +57,8 @@
std::string packageNameStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
android::String16 opPackageName(packageNameStr.c_str());
android::recordingAllowed(opPackageName, pid, uid);
- android::startRecording(opPackageName, pid, uid, isHotword);
- android::finishRecording(opPackageName, uid, isHotword);
+ android::startRecording(opPackageName, pid, uid, source);
+ android::finishRecording(opPackageName, uid, source);
android::captureAudioOutputAllowed(pid, uid);
android::captureMediaOutputAllowed(pid, uid);
android::captureHotwordAllowed(opPackageName, pid, uid);
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 431dd7a..276b471 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -24,6 +24,7 @@
#include <binder/PermissionController.h>
#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
+#include <system/audio-hal-enums.h>
#include <map>
#include <optional>
@@ -79,10 +80,11 @@
}
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource);
-void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, audio_source_t source);
+void finishRecording(const String16& opPackageName, uid_t uid, audio_source_t source);
bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
+bool captureTunerAudioInputAllowed(pid_t pid, uid_t uid);
bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
bool settingsAllowed();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index e239850..10bf707 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -454,8 +454,9 @@
}
// check calling permissions.
- // Capturing from FM_TUNER source is controlled by captureAudioOutputAllowed() only as this
- // does not affect users privacy as does capturing from an actual microphone.
+ // Capturing from FM_TUNER source is controlled by captureTunerAudioInputAllowed() and
+ // captureAudioOutputAllowed() (deprecated) as this does not affect users privacy
+ // as does capturing from an actual microphone.
if (!(recordingAllowed(opPackageName, pid, uid) || attr->source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, uid, pid);
@@ -466,9 +467,14 @@
if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
inputSource == AUDIO_SOURCE_VOICE_CALL ||
- inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
- inputSource == AUDIO_SOURCE_FM_TUNER) &&
- !canCaptureOutput) {
+ inputSource == AUDIO_SOURCE_ECHO_REFERENCE)
+ && !canCaptureOutput) {
+ return PERMISSION_DENIED;
+ }
+
+ if (inputSource == AUDIO_SOURCE_FM_TUNER
+ && !captureTunerAudioInputAllowed(pid, uid)
+ && !canCaptureOutput) {
return PERMISSION_DENIED;
}
@@ -574,7 +580,7 @@
// check calling permissions
if (!(startRecording(client->opPackageName, client->pid, client->uid,
- client->attributes.source == AUDIO_SOURCE_HOTWORD)
+ client->attributes.source)
|| client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, client->uid, client->pid);
@@ -663,7 +669,7 @@
client->startTimeNs = 0;
updateUidStates_l();
finishRecording(client->opPackageName, client->uid,
- client->attributes.source == AUDIO_SOURCE_HOTWORD);
+ client->attributes.source);
}
return status;
@@ -690,7 +696,7 @@
// finish the recording app op
finishRecording(client->opPackageName, client->uid,
- client->attributes.source == AUDIO_SOURCE_HOTWORD);
+ client->attributes.source);
AutoCallerClear acc;
return mAudioPolicyManager->stopInput(portId);
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8400dae..b4c0da3 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -21,6 +21,7 @@
#include <algorithm>
#include <climits>
#include <stdio.h>
+#include <cstdlib>
#include <cstring>
#include <ctime>
#include <string>
@@ -1694,6 +1695,8 @@
// Otherwise, add client to active clients list
finishConnectLocked(client, partial);
}
+
+ client->setImageDumpMask(mImageDumpMask);
} // lock is destroyed, allow further connect calls
// Important: release the mutex here so the client can call back into the service from its
@@ -3880,6 +3883,10 @@
return handleSetRotateAndCrop(args);
} else if (args.size() >= 1 && args[0] == String16("get-rotate-and-crop")) {
return handleGetRotateAndCrop(out);
+ } else if (args.size() >= 2 && args[0] == String16("set-image-dump-mask")) {
+ return handleSetImageDumpMask(args);
+ } else if (args.size() >= 1 && args[0] == String16("get-image-dump-mask")) {
+ return handleGetImageDumpMask(out);
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
return NO_ERROR;
@@ -3979,6 +3986,30 @@
return dprintf(out, "rotateAndCrop override: %d\n", mOverrideRotateAndCropMode);
}
+status_t CameraService::handleSetImageDumpMask(const Vector<String16>& args) {
+ char *endPtr;
+ errno = 0;
+ String8 maskString8 = String8(args[1]);
+ long maskValue = strtol(maskString8.c_str(), &endPtr, 10);
+
+ if (errno != 0) return BAD_VALUE;
+ if (endPtr != maskString8.c_str() + maskString8.size()) return BAD_VALUE;
+ if (maskValue < 0 || maskValue > 1) return BAD_VALUE;
+
+ Mutex::Autolock lock(mServiceLock);
+
+ mImageDumpMask = maskValue;
+
+ return OK;
+}
+
+status_t CameraService::handleGetImageDumpMask(int out) {
+ Mutex::Autolock lock(mServiceLock);
+
+ return dprintf(out, "Image dump mask: %d\n", mImageDumpMask);
+}
+
+
status_t CameraService::printHelp(int out) {
return dprintf(out, "Camera service commands:\n"
" get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
@@ -3987,6 +4018,9 @@
" set-rotate-and-crop <ROTATION> overrides the rotate-and-crop value for AUTO backcompat\n"
" Valid values 0=0 deg, 1=90 deg, 2=180 deg, 3=270 deg, 4=No override\n"
" get-rotate-and-crop returns the current override rotate-and-crop value\n"
+ " set-image-dump-mask <MASK> specifies the formats to be saved to disk\n"
+ " Valid values 0=OFF, 1=ON for JPEG\n"
+ " get-image-dump-mask returns the current image-dump-mask value\n"
" help print this message\n");
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d26c62d..43b03e6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -398,6 +398,8 @@
// Check what API level is used for this client. This is used to determine which
// superclass this can be cast to.
virtual bool canCastToApiClient(apiLevel level) const;
+
+ void setImageDumpMask(int /*mask*/) { }
protected:
// Initialized in constructor
@@ -1036,6 +1038,12 @@
// Get the rotate-and-crop AUTO override behavior
status_t handleGetRotateAndCrop(int out);
+ // Set the mask for image dump to disk
+ status_t handleSetImageDumpMask(const Vector<String16>& args);
+
+ // Get the mask for image dump to disk
+ status_t handleGetImageDumpMask(int out);
+
// Prints the shell command help
status_t printHelp(int out);
@@ -1077,6 +1085,9 @@
// Current override rotate-and-crop mode
uint8_t mOverrideRotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_AUTO;
+
+ // Current image dump mask
+ uint8_t mImageDumpMask = 0;
};
} // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 5d40b82..3f72eca 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -206,6 +206,7 @@
virtual void notifyRequestQueueEmpty();
virtual void notifyRepeatingRequestError(long lastFrameNumber);
+ void setImageDumpMask(int mask) { if (mDevice != nullptr) mDevice->setImageDumpMask(mask); }
/**
* Interface used by independent components of CameraDeviceClient.
*/
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index a537ef5..77e660f 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -367,6 +367,14 @@
* Get the status tracker of the camera device
*/
virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
+
+ /**
+ * Set bitmask for image dump flag
+ */
+ void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+
+protected:
+ bool mImageDumpMask = 0;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 50ef953..8754ad3 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1456,6 +1456,8 @@
newStream->setBufferManager(mBufferManager);
+ newStream->setImageDumpMask(mImageDumpMask);
+
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 7b812f2..6dfc838 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -18,8 +18,15 @@
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
+#include <ctime>
+#include <fstream>
+
+#include <android-base/unique_fd.h>
+#include <ui/GraphicBuffer.h>
#include <utils/Log.h>
#include <utils/Trace.h>
+
+#include "api1/client2/JpegProcessor.h"
#include "Camera3OutputStream.h"
#include "utils/TraceHFR.h"
@@ -279,6 +286,12 @@
__FUNCTION__, mId, strerror(-res), res);
return res;
}
+ // If this is a JPEG output, and image dump mask is set, save image to
+ // disk.
+ if (getFormat() == HAL_PIXEL_FORMAT_BLOB && getDataSpace() == HAL_DATASPACE_V0_JFIF &&
+ mImageDumpMask) {
+ dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
+ }
res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
if (shouldLogError(res, state)) {
@@ -957,6 +970,49 @@
return (usage & GRALLOC_USAGE_HW_TEXTURE) != 0;
}
+void Camera3OutputStream::dumpImageToDisk(nsecs_t timestamp,
+ ANativeWindowBuffer* anwBuffer, int fence) {
+ // Deriver output file name
+ std::string fileExtension = "jpg";
+ char imageFileName[64];
+ time_t now = time(0);
+ tm *localTime = localtime(&now);
+ snprintf(imageFileName, sizeof(imageFileName), "IMG_%4d%02d%02d_%02d%02d%02d_%" PRId64 ".%s",
+ 1900 + localTime->tm_year, localTime->tm_mon, localTime->tm_mday,
+ localTime->tm_hour, localTime->tm_min, localTime->tm_sec,
+ timestamp, fileExtension.c_str());
+
+ // Lock the image for CPU read
+ sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(anwBuffer);
+ void* mapped = nullptr;
+ base::unique_fd fenceFd(dup(fence));
+ status_t res = graphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN, &mapped,
+ fenceFd.get());
+ if (res != OK) {
+ ALOGE("%s: Failed to lock the buffer: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return;
+ }
+
+ // Figure out actual file size
+ auto actualJpegSize = android::camera2::JpegProcessor::findJpegSize((uint8_t*)mapped, mMaxSize);
+ if (actualJpegSize == 0) {
+ actualJpegSize = mMaxSize;
+ }
+
+ // Output image data to file
+ std::string filePath = "/data/misc/cameraserver/";
+ filePath += imageFileName;
+ std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
+ if (!imageFile.is_open()) {
+ ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
+ graphicBuffer->unlock();
+ return;
+ }
+ imageFile.write((const char*)mapped, actualJpegSize);
+
+ graphicBuffer->unlock();
+}
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index b4e49f9..55f0d41 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -210,6 +210,8 @@
*/
static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);
+ void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+
protected:
Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height, int format,
@@ -325,9 +327,14 @@
// STATE_ABANDONED
static bool shouldLogError(status_t res, StreamState state);
+ // Dump images to disk before returning to consumer
+ void dumpImageToDisk(nsecs_t timestamp, ANativeWindowBuffer* anwBuffer, int fence);
+
static const int32_t kDequeueLatencyBinSize = 5; // in ms
CameraLatencyHistogram mDequeueBufferLatency;
+ int mImageDumpMask = 0;
+
}; // class Camera3OutputStream
} // namespace camera3
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 80f17f4..9da4867 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
+cc_library {
name: "libaaudioservice",
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 65d8d41..5327289 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -40,6 +40,21 @@
srcs: [
":tv_tuner_aidl",
],
+ imports: [
+ "android.hardware.common.fmq",
+ ],
+
+ backend: {
+ java: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
}
cc_library {
@@ -52,8 +67,10 @@
shared_libs: [
"android.hardware.tv.tuner@1.0",
- "libbinder",
+ "libbase",
"libbinder_ndk",
+ "libcutils",
+ "libfmq",
"libhidlbase",
"liblog",
"libmedia",
@@ -61,7 +78,13 @@
"tv_tuner_aidl_interface-ndk_platform",
],
- include_dirs: ["frameworks/av/include"],
+ static_libs: [
+ "android.hardware.common.fmq-unstable-ndk_platform",
+ ],
+
+ include_dirs: [
+ "frameworks/av/include"
+ ],
cflags: [
"-Werror",
@@ -83,6 +106,7 @@
"android.hardware.tv.tuner@1.0",
"libbase",
"libbinder",
+ "libfmq",
"liblog",
"libtunerservice",
"libutils",
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 2b3de17..56cb34c 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -32,14 +32,17 @@
using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_0::Result;
namespace android {
-sp<ITuner> TunerService::mTuner;
-
TunerService::TunerService() {}
TunerService::~TunerService() {}
@@ -47,17 +50,160 @@
std::shared_ptr<TunerService> service =
::ndk::SharedRefBase::make<TunerService>();
AServiceManager_addService(service->asBinder().get(), getServiceName());
+}
+
+template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
+bool TunerService::unsafeHidlToAidlMQDescriptor(
+ const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
+ MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
+ // TODO: use the builtin coversion method when it's merged.
+ ALOGD("unsafeHidlToAidlMQDescriptor");
+ static_assert(sizeof(HidlPayload) == sizeof(AidlPayload), "Payload types are incompatible");
+ static_assert(
+ has_typedef_fixed_size<AidlPayload>::value == true ||
+ std::is_fundamental<AidlPayload>::value ||
+ std::is_enum<AidlPayload>::value,
+ "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize "
+ "and built for the NDK backend are supported as AIDL payload types.");
+ aidlDesc->fileDescriptor = ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[0]));
+ for (const auto& grantor : hidlDesc.grantors()) {
+ if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0) {
+ ALOGD("Unsafe static_cast of grantor fields. offset=%d, extend=%ld",
+ static_cast<int32_t>(grantor.offset), static_cast<long>(grantor.extent));
+ logError(
+ "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
+ "invalid, or the MessageQueue is too large to be described by AIDL.");
+ return false;
+ }
+ aidlDesc->grantors.push_back(
+ GrantorDescriptor {
+ .offset = static_cast<int32_t>(grantor.offset),
+ .extent = static_cast<int64_t>(grantor.extent)
+ });
+ }
+ if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
+ static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
+ ALOGD("Unsafe static_cast of quantum or flags. Quantum=%d, flags=%d",
+ static_cast<int32_t>(hidlDesc.getQuantum()),
+ static_cast<int32_t>(hidlDesc.getFlags()));
+ logError(
+ "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
+ "invalid, or the MessageQueue is too large to be described by AIDL.");
+ return false;
+ }
+ aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
+ aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
+ return true;
+}
+
+bool TunerService::getITuner() {
+ ALOGD("getITuner");
+ if (mTuner != nullptr) {
+ return true;
+ }
mTuner = ITuner::getService();
if (mTuner == nullptr) {
- ALOGE("Failed to get ITuner service.");
+ ALOGE("Failed to get ITuner service");
+ return false;
}
+ return true;
+}
+
+Result TunerService::openDemux() {
+ ALOGD("openDemux");
+ if (!getITuner()) {
+ return Result::NOT_INITIALIZED;
+ }
+ if (mDemux != nullptr) {
+ return Result::SUCCESS;
+ }
+ Result res;
+ uint32_t id;
+ sp<IDemux> demuxSp;
+ mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
+ demuxSp = demux;
+ id = demuxId;
+ res = r;
+ ALOGD("open demux, id = %d", demuxId);
+ });
+ if (res == Result::SUCCESS) {
+ mDemux = demuxSp;
+ } else {
+ ALOGD("open demux failed, res = %d", res);
+ }
+ return res;
+}
+
+Result TunerService::openFilter() {
+ ALOGD("openFilter");
+ if (!getITuner()) {
+ return Result::NOT_INITIALIZED;
+ }
+ DemuxFilterMainType mainType = DemuxFilterMainType::TS;
+ DemuxFilterType filterType {
+ .mainType = mainType,
+ };
+ filterType.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+
+ sp<FilterCallback> callback = new FilterCallback();
+ Result res;
+ mDemux->openFilter(filterType, 16000000, callback,
+ [&](Result r, const sp<IFilter>& filter) {
+ mFilter = filter;
+ res = r;
+ });
+ if (res != Result::SUCCESS || mFilter == NULL) {
+ ALOGD("Failed to open filter, type = %d", filterType.mainType);
+ return res;
+ }
+
+ return Result::SUCCESS;
+}
+
+Result TunerService::configFilter() {
+ ALOGD("configFilter");
+ if (mFilter == NULL) {
+ ALOGD("Failed to configure filter: filter not found");
+ return Result::NOT_INITIALIZED;
+ }
+ DemuxFilterSettings filterSettings;
+ DemuxTsFilterSettings tsFilterSettings {
+ .tpid = 256,
+ };
+ DemuxFilterAvSettings filterAvSettings {
+ .isPassthrough = false,
+ };
+ tsFilterSettings.filterSettings.av(filterAvSettings);
+ filterSettings.ts(tsFilterSettings);
+ Result res = mFilter->configure(filterSettings);
+
+ if (res != Result::SUCCESS) {
+ ALOGD("config filter failed, res = %d", res);
+ return res;
+ }
+
+ Result getQueueDescResult = Result::UNKNOWN_ERROR;
+ mFilter->getQueueDesc(
+ [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+ mFilterMQDesc = desc;
+ getQueueDescResult = r;
+ ALOGD("getFilterQueueDesc");
+ });
+ if (getQueueDescResult == Result::SUCCESS) {
+ unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
+ mFilterMQDesc, &mAidlMQDesc);
+ mAidlMq = new (std::nothrow) AidlMessageQueue(mAidlMQDesc);
+ EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
+ } else {
+ ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
+ }
+ return getQueueDescResult;
}
Status TunerService::getFrontendIds(std::vector<int32_t>* ids, int32_t* /* _aidl_return */) {
- if (mTuner == nullptr) {
- ALOGE("ITuner service is not init.");
+ if (!getITuner()) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(
- static_cast<int32_t>(Result::UNAVAILABLE));
+ static_cast<int32_t>(Result::NOT_INITIALIZED));
}
hidl_vec<FrontendId> feIds;
Result res;
@@ -221,4 +367,24 @@
info.caps = caps;
return info;
}
+
+Status TunerService::getFmqSyncReadWrite(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
+ ALOGD("getFmqSyncReadWrite");
+ // TODO: put the following methods AIDL, and should be called from clients.
+ openDemux();
+ openFilter();
+ configFilter();
+ mFilter->start();
+ if (mqDesc == nullptr) {
+ ALOGD("getFmqSyncReadWrite null MQDescriptor.");
+ *_aidl_return = false;
+ } else {
+ ALOGD("getFmqSyncReadWrite true");
+ *_aidl_return = true;
+ *mqDesc = std::move(mAidlMQDesc);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace android
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 36ccd3e..26591ab 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -20,17 +20,59 @@
#include <aidl/android/media/tv/tuner/BnTunerService.h>
#include <aidl/android/media/tv/tuner/TunerServiceFrontendInfo.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
-using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::common::fmq::GrantorDescriptor;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using ::aidl::android::media::tv::tuner::BnTunerService;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;
+
+using ::android::hardware::details::logError;
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using Status = ::ndk::ScopedAStatus;
namespace android {
+
+struct FilterCallback : public IFilterCallback {
+ ~FilterCallback() {}
+ Return<void> onFilterEvent(const DemuxFilterEvent&) {
+ return Void();
+ }
+ Return<void> onFilterStatus(const DemuxFilterStatus) {
+ return Void();
+ }
+};
+
class TunerService : public BnTunerService {
+ typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> AidlMessageQueue;
+ typedef MessageQueue<uint8_t, kSynchronizedReadWrite> HidlMessageQueue;
+ typedef MQDescriptor<int8_t, SynchronizedReadWrite> AidlMQDesc;
public:
static char const *getServiceName() { return "media.tuner"; }
@@ -46,10 +88,27 @@
Status getFrontendInfo(int32_t frontendHandle, TunerServiceFrontendInfo* _aidl_return) override;
Status openFrontend(
int32_t frontendHandle, std::shared_ptr<ITunerFrontend>* _aidl_return) override;
+ Status getFmqSyncReadWrite(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) override;
private:
- static sp<ITuner> mTuner;
+ template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
+ bool unsafeHidlToAidlMQDescriptor(
+ const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidl,
+ MQDescriptor<AidlPayload, AidlFlavor>* aidl);
+ bool getITuner();
+ Result openFilter();
+ Result openDemux();
+ Result configFilter();
+
+ sp<ITuner> mTuner;
+ sp<IDemux> mDemux;
+ sp<IFilter> mFilter;
+ AidlMessageQueue* mAidlMq;
+ MQDescriptorSync<uint8_t> mFilterMQDesc;
+ AidlMQDesc mAidlMQDesc;
+ EventFlag* mEventFlag;
TunerServiceFrontendInfo convertToAidlFrontendInfo(int feId, FrontendInfo halInfo);
};
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 5a0b47d..5c1bce7 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -16,6 +16,9 @@
package android.media.tv.tuner;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.common.fmq.UnsynchronizedWrite;
import android.media.tv.tuner.ITunerFrontend;
import android.media.tv.tuner.TunerServiceFrontendInfo;
@@ -24,6 +27,7 @@
*
* {@hide}
*/
+//@VintfStability
interface ITunerService {
/**
@@ -48,4 +52,11 @@
* @return the aidl interface of the frontend.
*/
ITunerFrontend openFrontend(in int frontendHandle);
+
+ /*
+ * Gets synchronized fast message queue.
+ *
+ * @return true if succeeds, false otherwise.
+ */
+ boolean getFmqSyncReadWrite(out MQDescriptor<byte, SynchronizedReadWrite> mqDesc);
}