Merge "codec2: cache ion buffers with CPU access flags." into qt-dev
diff --git a/apex/AndroidManifest-media.xml b/apex/AndroidManifest-media.xml
index 78ed0ed..1af4586 100644
--- a/apex/AndroidManifest-media.xml
+++ b/apex/AndroidManifest-media.xml
@@ -18,10 +18,9 @@
package="com.android.media">
<!-- APEX does not have classes.dex -->
<application android:hasCode="false" />
- <!-- Setting maxSdk to lock the module to Q. minSdk is 28 for now to cover Q beta devices. -->
+ <!-- Setting maxSdk to lock the module to Q. minSdk is auto-set by build system -->
<uses-sdk
- android:minSdkVersion="28"
android:maxSdkVersion="29"
- android:targetSdkVersion="28"
+ android:targetSdkVersion="29"
/>
</manifest>
diff --git a/apex/AndroidManifest-swcodec.xml b/apex/AndroidManifest-swcodec.xml
index 9558644..de50864 100644
--- a/apex/AndroidManifest-swcodec.xml
+++ b/apex/AndroidManifest-swcodec.xml
@@ -18,10 +18,9 @@
package="com.android.media.swcodec">
<!-- APEX does not have classes.dex -->
<application android:hasCode="false" />
- <!-- Setting maxSdk to lock the module to Q. minSdk is 28 for now to cover Q beta devices. -->
+ <!-- Setting maxSdk to lock the module to Q. minSdk is auto-set by build system -->
<uses-sdk
- android:minSdkVersion="28"
android:maxSdkVersion="29"
- android:targetSdkVersion="28"
+ android:targetSdkVersion="29"
/>
</manifest>
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index 87af5a1..a5937fd 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -127,3 +127,5 @@
# namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so
+# Add a link for libz.so which is llndk on devices where VNDK is not enforced.
+namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index d7dacb8..d74bc53 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -401,20 +401,25 @@
sendExpirationUpdate(sessionId, 100);
- std::vector<KeyStatus> keysStatus;
- KeyStatus keyStatus;
+ std::vector<KeyStatus_V1_2> keysStatus;
+ KeyStatus_V1_2 keyStatus;
std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
keyStatus.keyId = keyId1;
- keyStatus.type = V1_0::KeyStatusType::USABLE;
+ keyStatus.type = V1_2::KeyStatusType::USABLE;
keysStatus.push_back(keyStatus);
std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
keyStatus.keyId = keyId2;
- keyStatus.type = V1_0::KeyStatusType::EXPIRED;
+ keyStatus.type = V1_2::KeyStatusType::EXPIRED;
keysStatus.push_back(keyStatus);
- sendKeysChange(sessionId, keysStatus, true);
+ std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 };
+ keyStatus.keyId = keyId3;
+ keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE;
+ keysStatus.push_back(keyStatus);
+
+ sendKeysChange_1_2(sessionId, keysStatus, true);
installSecureStop(sessionId);
} else {
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 7efc7f1..8e3852c 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -103,11 +103,24 @@
})
.withSetter(ProfileLevelSetter)
.build());
+
+ addParameter(
+ DefineParam(mSBRMode, C2_PARAMKEY_AAC_SBR_MODE)
+ .withDefault(new C2StreamAacSbrModeTuning::input(0u, AAC_SBR_AUTO))
+ .withFields({C2F(mSBRMode, value).oneOf({
+ C2Config::AAC_SBR_OFF,
+ C2Config::AAC_SBR_SINGLE_RATE,
+ C2Config::AAC_SBR_DUAL_RATE,
+ C2Config::AAC_SBR_AUTO })})
+ .withSetter(Setter<decltype(*mSBRMode)>::NonStrictValueWithNoDeps)
+ .build());
}
uint32_t getSampleRate() const { return mSampleRate->value; }
uint32_t getChannelCount() const { return mChannelCount->value; }
uint32_t getBitrate() const { return mBitrate->value; }
+ uint32_t getSBRMode() const { return mSBRMode->value; }
+ uint32_t getProfile() const { return mProfileLevel->profile; }
static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output> &me) {
(void)mayBlock;
(void)me; // TODO: validate
@@ -129,6 +142,7 @@
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
+ std::shared_ptr<C2StreamAacSbrModeTuning::input> mSBRMode;
};
C2SoftAacEnc::C2SoftAacEnc(
@@ -138,9 +152,6 @@
: SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
mIntf(intfImpl),
mAACEncoder(nullptr),
- mSBRMode(-1),
- mSBRRatio(0),
- mAACProfile(AOT_AAC_LC),
mNumBytesPerInputFrame(0u),
mOutBufferSize(0u),
mSentCodecSpecificData(false),
@@ -208,31 +219,37 @@
return chMode;
}
-//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
-// if (profile == OMX_AUDIO_AACObjectLC) {
-// return AOT_AAC_LC;
-// } else if (profile == OMX_AUDIO_AACObjectHE) {
-// return AOT_SBR;
-// } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
-// return AOT_PS;
-// } else if (profile == OMX_AUDIO_AACObjectLD) {
-// return AOT_ER_AAC_LD;
-// } else if (profile == OMX_AUDIO_AACObjectELD) {
-// return AOT_ER_AAC_ELD;
-// } else {
-// ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
-// return AOT_AAC_LC;
-// }
-//}
+static AUDIO_OBJECT_TYPE getAOTFromProfile(uint32_t profile) {
+ if (profile == C2Config::PROFILE_AAC_LC) {
+ return AOT_AAC_LC;
+ } else if (profile == C2Config::PROFILE_AAC_HE) {
+ return AOT_SBR;
+ } else if (profile == C2Config::PROFILE_AAC_HE_PS) {
+ return AOT_PS;
+ } else if (profile == C2Config::PROFILE_AAC_LD) {
+ return AOT_ER_AAC_LD;
+ } else if (profile == C2Config::PROFILE_AAC_ELD) {
+ return AOT_ER_AAC_ELD;
+ } else {
+ ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
+ return AOT_AAC_LC;
+ }
+}
status_t C2SoftAacEnc::setAudioParams() {
// We call this whenever sample rate, number of channels, bitrate or SBR mode change
// in reponse to setParameter calls.
+ int32_t sbrRatio = 0;
+ uint32_t sbrMode = mIntf->getSBRMode();
+ if (sbrMode == AAC_SBR_SINGLE_RATE) sbrRatio = 1;
+ else if (sbrMode == AAC_SBR_DUAL_RATE) sbrRatio = 2;
ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
- mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(), mSBRMode, mSBRRatio);
+ mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(),
+ sbrMode, sbrRatio);
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
+ uint32_t aacProfile = mIntf->getProfile();
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, getAOTFromProfile(aacProfile))) {
ALOGE("Failed to set AAC encoder parameters");
return UNKNOWN_ERROR;
}
@@ -255,8 +272,8 @@
return UNKNOWN_ERROR;
}
- if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
+ if (sbrMode != -1 && aacProfile == C2Config::PROFILE_AAC_ELD) {
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, sbrMode)) {
ALOGE("Failed to set AAC encoder parameters");
return UNKNOWN_ERROR;
}
@@ -268,7 +285,7 @@
1: Downsampled SBR (default for ELD)
2: Dualrate SBR (default for HE-AAC)
*/
- if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
+ if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, sbrRatio)) {
ALOGE("Failed to set AAC encoder parameters");
return UNKNOWN_ERROR;
}
diff --git a/media/codec2/components/aac/C2SoftAacEnc.h b/media/codec2/components/aac/C2SoftAacEnc.h
index 779365b..a38be19 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.h
+++ b/media/codec2/components/aac/C2SoftAacEnc.h
@@ -50,9 +50,6 @@
HANDLE_AACENCODER mAACEncoder;
- int32_t mSBRMode;
- int32_t mSBRRatio;
- AUDIO_OBJECT_TYPE mAACProfile;
UINT mNumBytesPerInputFrame;
UINT mOutBufferSize;
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 8d9f21a..b41c271 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -41,6 +41,37 @@
constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
+void ParseGop(
+ const C2StreamGopTuning::output &gop,
+ uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
+ uint32_t syncInt = 1;
+ uint32_t iInt = 1;
+ for (size_t i = 0; i < gop.flexCount(); ++i) {
+ const C2GopLayerStruct &layer = gop.m.values[i];
+ if (layer.count == UINT32_MAX) {
+ syncInt = 0;
+ } else if (syncInt <= UINT32_MAX / (layer.count + 1)) {
+ syncInt *= (layer.count + 1);
+ }
+ if ((layer.type_ & I_FRAME) == 0) {
+ if (layer.count == UINT32_MAX) {
+ iInt = 0;
+ } else if (iInt <= UINT32_MAX / (layer.count + 1)) {
+ iInt *= (layer.count + 1);
+ }
+ }
+ if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME) && maxBframes) {
+ *maxBframes = layer.count;
+ }
+ }
+ if (syncInterval) {
+ *syncInterval = syncInt;
+ }
+ if (iInterval) {
+ *iInterval = iInt;
+ }
+}
+
} // namespace
class C2SoftAvcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -81,10 +112,19 @@
.build());
addParameter(
+ DefineParam(mGop, C2_PARAMKEY_GOP)
+ .withDefault(C2StreamGopTuning::output::AllocShared(
+ 0 /* flexCount */, 0u /* stream */))
+ .withFields({C2F(mGop, m.values[0].type_).any(),
+ C2F(mGop, m.values[0].count).any()})
+ .withSetter(GopSetter)
+ .build());
+
+ addParameter(
DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
.withDefault(new C2PortActualDelayTuning::input(DEFAULT_B_FRAMES))
.withFields({C2F(mActualInputDelay, value).inRange(0, MAX_B_FRAMES)})
- .withSetter(Setter<decltype(*mActualInputDelay)>::StrictValueWithNoDeps)
+ .calculatedAs(InputDelaySetter, mGop)
.build());
addParameter(
@@ -160,6 +200,17 @@
.build());
}
+ static C2R InputDelaySetter(
+ bool mayBlock,
+ C2P<C2PortActualDelayTuning::input> &me,
+ const C2P<C2StreamGopTuning::output> &gop) {
+ (void)mayBlock;
+ uint32_t maxBframes = 0;
+ ParseGop(gop.v, nullptr, nullptr, &maxBframes);
+ me.set().value = maxBframes;
+ return C2R::Ok();
+ }
+
static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) {
(void)mayBlock;
C2R res = C2R::Ok();
@@ -273,6 +324,18 @@
return res;
}
+ static C2R GopSetter(bool mayBlock, C2P<C2StreamGopTuning::output> &me) {
+ (void)mayBlock;
+ for (size_t i = 0; i < me.v.flexCount(); ++i) {
+ const C2GopLayerStruct &layer = me.v.m.values[0];
+ if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME)
+ && layer.count > MAX_B_FRAMES) {
+ me.set().m.values[i].count = MAX_B_FRAMES;
+ }
+ }
+ return C2R::Ok();
+ }
+
IV_PROFILE_T getProfile_l() const {
switch (mProfileLevel->profile) {
case PROFILE_AVC_CONSTRAINED_BASELINE: [[fallthrough]];
@@ -314,6 +377,7 @@
ALOGD("Unrecognized level: %x", mProfileLevel->level);
return 41;
}
+
uint32_t getSyncFramePeriod_l() const {
if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) {
return 0;
@@ -328,6 +392,7 @@
std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; }
std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; }
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; }
+ std::shared_ptr<C2StreamGopTuning::output> getGop_l() const { return mGop; }
private:
std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -338,6 +403,7 @@
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
+ std::shared_ptr<C2StreamGopTuning::output> mGop;
};
#define ive_api_function ih264e_api_function
@@ -850,6 +916,7 @@
c2_status_t errType = C2_OK;
+ std::shared_ptr<C2StreamGopTuning::output> gop;
{
IntfImpl::Lock lock = mIntf->lock();
mSize = mIntf->getSize_l();
@@ -859,6 +926,25 @@
mAVCEncLevel = mIntf->getLevel_l();
mIInterval = mIntf->getSyncFramePeriod_l();
mIDRInterval = mIntf->getSyncFramePeriod_l();
+ gop = mIntf->getGop_l();
+ }
+ if (gop && gop->flexCount() > 0) {
+ uint32_t syncInterval = 1;
+ uint32_t iInterval = 1;
+ uint32_t maxBframes = 0;
+ ParseGop(*gop, &syncInterval, &iInterval, &maxBframes);
+ if (syncInterval > 0) {
+ ALOGD("Updating IDR interval from GOP: old %u new %u", mIDRInterval, syncInterval);
+ mIDRInterval = syncInterval;
+ }
+ if (iInterval > 0) {
+ ALOGD("Updating I interval from GOP: old %u new %u", mIInterval, iInterval);
+ mIInterval = iInterval;
+ }
+ if (mBframes != maxBframes) {
+ ALOGD("Updating max B frames from GOP: old %u new %u", mBframes, maxBframes);
+ mBframes = maxBframes;
+ }
}
uint32_t width = mSize->width;
uint32_t height = mSize->height;
@@ -868,8 +954,8 @@
// TODO
mIvVideoColorFormat = IV_YUV_420P;
- ALOGD("Params width %d height %d level %d colorFormat %d", width,
- height, mAVCEncLevel, mIvVideoColorFormat);
+ ALOGD("Params width %d height %d level %d colorFormat %d bframes %d", width,
+ height, mAVCEncLevel, mIvVideoColorFormat, mBframes);
/* Getting Number of MemRecords */
{
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index cf34dff..408db7e 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -74,6 +74,14 @@
.withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
.build());
addParameter(
+ DefineParam(mComplexity, C2_PARAMKEY_COMPLEXITY)
+ .withDefault(new C2StreamComplexityTuning::output(0u,
+ FLAC_COMPRESSION_LEVEL_DEFAULT))
+ .withFields({C2F(mComplexity, value).inRange(
+ FLAC_COMPRESSION_LEVEL_MIN, FLAC_COMPRESSION_LEVEL_MAX)})
+ .withSetter(Setter<decltype(*mComplexity)>::NonStrictValueWithNoDeps)
+ .build());
+ addParameter(
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608))
.build());
@@ -93,12 +101,14 @@
uint32_t getSampleRate() const { return mSampleRate->value; }
uint32_t getChannelCount() const { return mChannelCount->value; }
uint32_t getBitrate() const { return mBitrate->value; }
+ uint32_t getComplexity() const { return mComplexity->value; }
int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
private:
std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate;
std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamComplexityTuning::output> mComplexity;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
std::shared_ptr<C2StreamPcmEncodingInfo::input> mPcmEncodingInfo;
};
@@ -127,7 +137,6 @@
mSignalledError = false;
mSignalledOutputEos = false;
- mCompressionLevel = FLAC_COMPRESSION_LEVEL_DEFAULT;
mIsFirstFrame = true;
mAnchorTimeStamp = 0ull;
mProcessedSamples = 0u;
@@ -153,7 +162,6 @@
}
void C2SoftFlacEnc::onReset() {
- mCompressionLevel = FLAC_COMPRESSION_LEVEL_DEFAULT;
(void) onStop();
}
@@ -369,7 +377,8 @@
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mIntf->getChannelCount());
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate());
ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
- ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
+ ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
+ mIntf->getComplexity());
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
if (!ok) {
ALOGE("unknown error when configuring encoder");
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.h b/media/codec2/components/flac/C2SoftFlacEnc.h
index cdf305e..b3f01d5 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.h
+++ b/media/codec2/components/flac/C2SoftFlacEnc.h
@@ -69,7 +69,6 @@
std::shared_ptr<C2LinearBlock> mOutputBlock;
bool mSignalledError;
bool mSignalledOutputEos;
- uint32_t mCompressionLevel;
uint32_t mBlockSize;
bool mIsFirstFrame;
uint64_t mAnchorTimeStamp;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 0d3357f..b129b1b 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -390,27 +390,23 @@
}
C2SoftHevcEnc::~C2SoftHevcEnc() {
- releaseEncoder();
+ onRelease();
}
c2_status_t C2SoftHevcEnc::onInit() {
- return initEncoder();
+ return C2_OK;
}
c2_status_t C2SoftHevcEnc::onStop() {
- if (!mStarted) {
- return C2_OK;
- }
- return releaseEncoder();
+ return C2_OK;
}
void C2SoftHevcEnc::onReset() {
- onStop();
- initEncoder();
+ releaseEncoder();
}
void C2SoftHevcEnc::onRelease() {
- onStop();
+ releaseEncoder();
}
c2_status_t C2SoftHevcEnc::onFlush_sm() {
@@ -865,6 +861,22 @@
return;
}
}
+
+ // handle dynamic config parameters
+ {
+ IntfImpl::Lock lock = mIntf->lock();
+ std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
+ lock.unlock();
+
+ if (bitrate != mBitrate) {
+ mBitrate = bitrate;
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_tgt_bitrate[0] =
+ mBitrate->value;
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_peak_bitrate[0] =
+ mBitrate->value << 1;
+ }
+ }
+
ihevce_inp_buf_t s_encode_ip{};
ihevce_out_buf_t s_encode_op{};
uint64_t workIndex = work->input.ordinal.frameIndex.peekull();
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index 7b58c9b..384d58b 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -38,6 +38,8 @@
} // namespace
+static const int kMaxNumChannelsSupported = 2;
+
class C2SoftOpusEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
public:
explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
@@ -71,7 +73,7 @@
addParameter(
DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
.withDefault(new C2StreamChannelCountInfo::input(0u, 1))
- .withFields({C2F(mChannelCount, value).inRange(1, 8)})
+ .withFields({C2F(mChannelCount, value).inRange(1, kMaxNumChannelsSupported)})
.withSetter((Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps))
.build());
@@ -128,9 +130,8 @@
}
c2_status_t C2SoftOpusEnc::configureEncoder() {
- unsigned char mono_mapping[256] = {0};
- unsigned char stereo_mapping[256] = {0, 1};
- unsigned char surround_mapping[256] = {0, 1, 255};
+ static const unsigned char mono_mapping[256] = {0};
+ static const unsigned char stereo_mapping[256] = {0, 1};
mSampleRate = mIntf->getSampleRate();
mChannelCount = mIntf->getChannelCount();
uint32_t bitrate = mIntf->getBitrate();
@@ -140,13 +141,14 @@
mChannelCount * mNumSamplesPerFrame * sizeof(int16_t);
int err = C2_OK;
- unsigned char* mapping;
- if (mChannelCount < 2) {
+ const unsigned char* mapping;
+ if (mChannelCount == 1) {
mapping = mono_mapping;
} else if (mChannelCount == 2) {
mapping = stereo_mapping;
} else {
- mapping = surround_mapping;
+ ALOGE("Number of channels (%d) is not supported", mChannelCount);
+ return C2_BAD_VALUE;
}
if (mEncoder != nullptr) {
@@ -154,7 +156,7 @@
}
mEncoder = opus_multistream_encoder_create(mSampleRate, mChannelCount,
- 1, 1, mapping, OPUS_APPLICATION_AUDIO, &err);
+ 1, mChannelCount - 1, mapping, OPUS_APPLICATION_AUDIO, &err);
if (err) {
ALOGE("Could not create libopus encoder. Error code: %i", err);
return C2_CORRUPTED;
@@ -205,15 +207,6 @@
return C2_BAD_VALUE;
}
- // Get codecDelay
- int32_t lookahead;
- if (opus_multistream_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&lookahead)) !=
- OPUS_OK) {
- ALOGE("failed to get lookahead");
- return C2_BAD_VALUE;
- }
- mCodecDelay = lookahead * 1000000000ll / mSampleRate;
-
// Set seek preroll to 80 ms
mSeekPreRoll = 80000000;
return C2_OK;
@@ -406,13 +399,26 @@
if (!mHeaderGenerated) {
uint8_t header[AOPUS_UNIFIED_CSD_MAXSIZE];
memset(header, 0, sizeof(header));
+
+ // Get codecDelay
+ int32_t lookahead;
+ if (opus_multistream_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&lookahead)) !=
+ OPUS_OK) {
+ ALOGE("failed to get lookahead");
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ mCodecDelay = lookahead * 1000000000ll / mSampleRate;
+
OpusHeader opusHeader;
+ memset(&opusHeader, 0, sizeof(opusHeader));
opusHeader.channels = mChannelCount;
opusHeader.num_streams = mChannelCount;
opusHeader.num_coupled = 0;
opusHeader.channel_mapping = ((mChannelCount > 8) ? 255 : (mChannelCount > 2));
opusHeader.gain_db = 0;
- opusHeader.skip_samples = 0;
+ opusHeader.skip_samples = lookahead;
int headerLen = WriteOpusHeaders(opusHeader, mSampleRate, header,
sizeof(header), mCodecDelay, mSeekPreRoll);
diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp
index 8e94a18..95eb909 100644
--- a/media/codec2/components/raw/C2SoftRawDec.cpp
+++ b/media/codec2/components/raw/C2SoftRawDec.cpp
@@ -58,7 +58,7 @@
addParameter(
DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
.withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
- .withFields({C2F(mSampleRate, value).inRange(8000, 192000)})
+ .withFields({C2F(mSampleRate, value).inRange(8000, 384000)})
.withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
.build());
@@ -72,7 +72,7 @@
addParameter(
DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
.withDefault(new C2StreamBitrateInfo::input(0u, 64000))
- .withFields({C2F(mBitrate, value).inRange(1, 10000000)})
+ .withFields({C2F(mBitrate, value).inRange(1, 98304000)})
.withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
.build());
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index c395d62..9f484a3 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -1644,6 +1644,7 @@
* frames.
*/
struct C2GopLayerStruct {
+ C2GopLayerStruct() : type_((C2Config::picture_type_t)0), count(0) {}
C2GopLayerStruct(C2Config::picture_type_t type, uint32_t count_)
: type_(type), count(count_) { }
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index 6ae1c13..f0f62f6 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -50,14 +50,8 @@
} // namespace
C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp)
- : mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0),
+ : mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0), mUsage(0),
mAdjustTimestampGapUs(0), mFirstInputFrame(true) {
- // TODO: read from intf()
- if (!strncmp(comp->getName().c_str(), "c2.android.", 11)) {
- mUsage = GRALLOC_USAGE_SW_READ_OFTEN;
- } else {
- mUsage = GRALLOC_USAGE_HW_VIDEO_ENCODER;
- }
}
status_t C2OMXNode::freeNode() {
@@ -103,13 +97,25 @@
}
status_t C2OMXNode::setParameter(OMX_INDEXTYPE index, const void *params, size_t size) {
- // handle max/fixed frame duration control
- if (index == (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl
- && params != NULL
- && size == sizeof(OMX_PARAM_U32TYPE)) {
- // The incoming number is an int32_t contained in OMX_U32.
- mAdjustTimestampGapUs = (int32_t)((OMX_PARAM_U32TYPE*)params)->nU32;
- return OK;
+ if (params == NULL) {
+ return BAD_VALUE;
+ }
+ switch ((uint32_t)index) {
+ case OMX_IndexParamMaxFrameDurationForBitrateControl:
+ // handle max/fixed frame duration control
+ if (size != sizeof(OMX_PARAM_U32TYPE)) {
+ return BAD_VALUE;
+ }
+ // The incoming number is an int32_t contained in OMX_U32.
+ mAdjustTimestampGapUs = (int32_t)((OMX_PARAM_U32TYPE*)params)->nU32;
+ return OK;
+
+ case OMX_IndexParamConsumerUsageBits:
+ if (size != sizeof(OMX_U32)) {
+ return BAD_VALUE;
+ }
+ mUsage = *((OMX_U32 *)params);
+ return OK;
}
return ERROR_UNSUPPORTED;
}
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 85c783b..f5a4d94 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -183,9 +183,11 @@
GraphicBufferSourceWrapper(
const sp<BGraphicBufferSource> &source,
uint32_t width,
- uint32_t height)
+ uint32_t height,
+ uint64_t usage)
: mSource(source), mWidth(width), mHeight(height) {
mDataSpace = HAL_DATASPACE_BT709;
+ mConfig.mUsage = usage;
}
~GraphicBufferSourceWrapper() override = default;
@@ -193,6 +195,12 @@
mNode = new C2OMXNode(comp);
mNode->setFrameSize(mWidth, mHeight);
+ // Usage is queried during configure(), so setting it beforehand.
+ OMX_U32 usage = mConfig.mUsage & 0xFFFFFFFF;
+ (void)mNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &usage, sizeof(usage));
+
// NOTE: we do not use/pass through color aspects from GraphicBufferSource as we
// communicate that directly to the component.
mSource->configure(mNode, mDataSpace);
@@ -364,7 +372,8 @@
// color aspects (android._color-aspects)
- // consumer usage
+ // consumer usage is queried earlier.
+
ALOGD("ISConfig%s", status.str().c_str());
return err;
}
@@ -745,11 +754,8 @@
return BAD_VALUE;
}
if ((config->mDomain & Config::IS_ENCODER) && (config->mDomain & Config::IS_VIDEO)) {
- C2Config::bitrate_mode_t mode = C2Config::BITRATE_VARIABLE;
- if (msg->findInt32(KEY_BITRATE_MODE, &i32)) {
- mode = (C2Config::bitrate_mode_t) i32;
- }
- if (mode == BITRATE_MODE_CQ) {
+ int32_t mode = BITRATE_MODE_VBR;
+ if (msg->findInt32(KEY_BITRATE_MODE, &mode) && mode == BITRATE_MODE_CQ) {
if (!msg->findInt32(KEY_QUALITY, &i32)) {
ALOGD("quality is missing, which is required for video encoders in CQ.");
return BAD_VALUE;
@@ -766,6 +772,11 @@
ALOGD("I frame interval is missing, which is required for video encoders.");
return BAD_VALUE;
}
+ if (!msg->findInt32(KEY_FRAME_RATE, &i32)
+ && !msg->findFloat(KEY_FRAME_RATE, &flt)) {
+ ALOGD("frame rate is missing, which is required for video encoders.");
+ return BAD_VALUE;
+ }
}
}
@@ -813,6 +824,7 @@
config->mISConfig->mSuspended = true;
}
}
+ config->mISConfig->mUsage = 0;
}
/*
@@ -849,6 +861,22 @@
if (err != OK) {
ALOGW("failed to convert configuration to c2 params");
}
+
+ int32_t maxBframes = 0;
+ if ((config->mDomain & Config::IS_ENCODER)
+ && (config->mDomain & Config::IS_VIDEO)
+ && sdkParams->findInt32(KEY_MAX_B_FRAMES, &maxBframes)
+ && maxBframes > 0) {
+ std::unique_ptr<C2StreamGopTuning::output> gop =
+ C2StreamGopTuning::output::AllocUnique(2 /* flexCount */, 0u /* stream */);
+ gop->m.values[0] = { P_FRAME, UINT32_MAX };
+ gop->m.values[1] = {
+ C2Config::picture_type_t(P_FRAME | B_FRAME),
+ uint32_t(maxBframes)
+ };
+ configUpdate.push_back(std::move(gop));
+ }
+
err = config->setParameters(comp, configUpdate, C2_DONT_BLOCK);
if (err != OK) {
ALOGW("failed to configure c2 params");
@@ -876,8 +904,14 @@
indices.size(), params.size());
return UNKNOWN_ERROR;
}
- if (usage && (usage.value & C2MemoryUsage::CPU_READ)) {
- config->mInputFormat->setInt32("using-sw-read-often", true);
+ if (usage) {
+ if (usage.value & C2MemoryUsage::CPU_READ) {
+ config->mInputFormat->setInt32("using-sw-read-often", true);
+ }
+ if (config->mISConfig) {
+ C2AndroidMemoryUsage androidUsage(C2MemoryUsage(usage.value));
+ config->mISConfig->mUsage = androidUsage.asGrallocUsage();
+ }
}
// NOTE: we don't blindly use client specified input size if specified as clients
@@ -1068,10 +1102,12 @@
sp<AMessage> inputFormat;
sp<AMessage> outputFormat;
+ uint64_t usage = 0;
{
Mutexed<Config>::Locked config(mConfig);
inputFormat = config->mInputFormat;
outputFormat = config->mOutputFormat;
+ usage = config->mISConfig ? config->mISConfig->mUsage : 0;
}
sp<PersistentSurface> persistentSurface = CreateCompatibleInputSurface();
@@ -1095,7 +1131,7 @@
int32_t height = 0;
(void)outputFormat->findInt32("height", &height);
err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
- persistentSurface->getBufferSource(), width, height));
+ persistentSurface->getBufferSource(), width, height, usage));
bufferProducer = persistentSurface->getBufferProducer();
}
@@ -1155,10 +1191,12 @@
void CCodec::setInputSurface(const sp<PersistentSurface> &surface) {
sp<AMessage> inputFormat;
sp<AMessage> outputFormat;
+ uint64_t usage = 0;
{
Mutexed<Config>::Locked config(mConfig);
inputFormat = config->mInputFormat;
outputFormat = config->mOutputFormat;
+ usage = config->mISConfig ? config->mISConfig->mUsage : 0;
}
auto hidlTarget = surface->getHidlTarget();
if (hidlTarget) {
@@ -1182,7 +1220,7 @@
int32_t height = 0;
(void)outputFormat->findInt32("height", &height);
status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
- surface->getBufferSource(), width, height));
+ surface->getBufferSource(), width, height, usage));
if (err != OK) {
ALOGE("Failed to set up input surface: %d", err);
mCallback->onInputSurfaceDeclined(err);
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 428f032..4c3fff7 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -358,14 +358,7 @@
.limitTo(D::ENCODER & D::VIDEO & D::PARAM));
add(ConfigMapper(KEY_BITRATE_MODE, C2_PARAMKEY_BITRATE_MODE, "value")
.limitTo(D::ENCODER & D::CODED)
- .withMapper([](C2Value v) -> C2Value {
- int32_t value;
- C2Config::bitrate_mode_t mode;
- if (v.get(&value) && C2Mapper::map(value, &mode)) {
- return mode;
- }
- return C2Value();
- }));
+ .withC2Mappers<C2Config::bitrate_mode_t>());
// remove when codecs switch to PARAMKEY and new modes
deprecated(ConfigMapper(KEY_BITRATE_MODE, "coded.bitrate-mode", "value")
.limitTo(D::ENCODER));
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 0fd5731..c6cbad3 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -739,6 +739,7 @@
ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
return false;
}
+ setRange(0, aBuffer->size()); // align size info
converter.copyToMediaImage();
setImageData(converter.imageData());
mBufferRef = buffer;
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index 8341fd5..bb35763 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -78,6 +78,7 @@
// IN PARAMS (CODEC WRAPPER)
float mFixedAdjustedFps; // fixed fps via PTS manipulation
float mMinAdjustedFps; // minimum fps via PTS manipulation
+ uint64_t mUsage; // consumer usage
};
/**
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index f54690d..527bb77 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1754,6 +1754,15 @@
// http://wiki.xiph.org/OggOpus#ID_Header
strncpy((char *)opusInfo, "OpusHead", 8);
+ // Version shall be 0 as per mp4 Opus Specific Box
+ // (https://opus-codec.org/docs/opus_in_isobmff.html#4.3.2)
+ if (opusInfo[8]) {
+ return ERROR_MALFORMED;
+ }
+ // Force version to 1 as per OpusHead definition
+ // (http://wiki.xiph.org/OggOpus#ID_Header)
+ opusInfo[8] = 1;
+
// Read Opus Specific Box values
size_t opusOffset = 10;
uint16_t pre_skip = U16_AT(&opusInfo[opusOffset]);
diff --git a/media/libeffects/dynamicsproc/dsp/DPFrequency.cpp b/media/libeffects/dynamicsproc/dsp/DPFrequency.cpp
index 1f53978..ae5c020 100644
--- a/media/libeffects/dynamicsproc/dsp/DPFrequency.cpp
+++ b/media/libeffects/dynamicsproc/dsp/DPFrequency.cpp
@@ -62,11 +62,6 @@
cBInput.resize(mBlockSize * CIRCULAR_BUFFER_UPSAMPLE);
cBOutput.resize(mBlockSize * CIRCULAR_BUFFER_UPSAMPLE);
- //fill input with half block size...
- for (unsigned int k = 0; k < mBlockSize/2; k++) {
- cBInput.write(0);
- }
-
//temp vectors
input.resize(mBlockSize);
output.resize(mBlockSize);
@@ -170,6 +165,11 @@
fill_window(mVWindow, RDSP_WINDOW_HANNING_FLAT_TOP, mBlockSize, mOverlapSize);
+ //split window into analysis and synthesis. Both are the sqrt() of original
+ //window
+ Eigen::Map<Eigen::VectorXf> eWindow(&mVWindow[0], mVWindow.size());
+ eWindow = eWindow.array().sqrt();
+
//compute window rms for energy compensation
mWindowRms = 0;
for (size_t i = 0; i < mVWindow.size(); i++) {
@@ -666,6 +666,11 @@
//##ifft directly to output.
Eigen::Map<Eigen::VectorXf> eOutput(&cb.output[0], cb.output.size());
mFftServer.inv(eOutput, cb.complexTemp);
+
+ //apply rest of window for resynthesis
+ Eigen::Map<Eigen::VectorXf> eWindow(&mVWindow[0], mVWindow.size());
+ eOutput = eOutput.cwiseProduct(eWindow);
+
return mBlockSize;
}
diff --git a/media/libstagefright/data/media_codecs_google_c2_audio.xml b/media/libstagefright/data/media_codecs_google_c2_audio.xml
index be2404d..509f7a9 100644
--- a/media/libstagefright/data/media_codecs_google_c2_audio.xml
+++ b/media/libstagefright/data/media_codecs_google_c2_audio.xml
@@ -112,7 +112,7 @@
<Limit name="sample-rate" ranges="8000,12000,16000,24000,48000" />
<Limit name="bitrate" range="500-512000" />
<Limit name="complexity" range="0-10" default="5" />
- <Feature name="bitrate-modes" value="CQ" />
+ <Feature name="bitrate-modes" value="CBR" />
</MediaCodec>
</Encoders>
</Included>
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 37f3f61..67d3f1a 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -237,7 +237,7 @@
<Limit name="sample-rate" ranges="8000,12000,16000,24000,48000" />
<Limit name="bitrate" range="500-512000" />
<Limit name="complexity" range="0-10" default="5" />
- <Feature name="bitrate-modes" value="CQ" />
+ <Feature name="bitrate-modes" value="CBR" />
</MediaCodec>
<MediaCodec name="c2.android.h263.encoder" type="video/3gpp">
<Alias name="OMX.google.h263.encoder" />
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index f7f4c36..9d7c57d 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -68,16 +68,26 @@
public class MediaCodec {
ctor public MediaCodec();
method public java.util.List<media.codecs.Alias> getAlias_optional();
+ method public java.util.List<media.codecs.Quirk> getAttribute_optional();
+ method public String getDomain();
+ method public String getEnabled();
method public java.util.List<media.codecs.Feature> getFeature_optional();
method public java.util.List<media.codecs.Limit> getLimit_optional();
method public String getName();
method public java.util.List<media.codecs.Quirk> getQuirk_optional();
+ method public String getRank();
method public String getType();
method public java.util.List<media.codecs.Type> getType_optional();
method public String getUpdate();
+ method public String getVariant();
+ method public java.util.List<media.codecs.Variant> getVariant_optional();
+ method public void setDomain(String);
+ method public void setEnabled(String);
method public void setName(String);
+ method public void setRank(String);
method public void setType(String);
method public void setUpdate(String);
+ method public void setVariant(String);
}
public class MediaCodecs {
@@ -91,14 +101,18 @@
public class Quirk {
ctor public Quirk();
method public String getName();
+ method public String getValue();
method public void setName(String);
+ method public void setValue(String);
}
public class Setting {
ctor public Setting();
+ method public String getEnabled();
method public String getName();
method public String getUpdate();
method public String getValue();
+ method public void setEnabled(String);
method public void setName(String);
method public void setUpdate(String);
method public void setValue(String);
@@ -106,7 +120,9 @@
public class Settings {
ctor public Settings();
- method public java.util.List<media.codecs.Setting> getSetting();
+ method public java.util.List<media.codecs.Setting> getDomain_optional();
+ method public java.util.List<media.codecs.Setting> getSetting_optional();
+ method public java.util.List<media.codecs.Setting> getVariant_optional();
}
public class Type {
@@ -120,6 +136,12 @@
method public void setUpdate(String);
}
+ public class Variant {
+ ctor public Variant();
+ method public String getName();
+ method public void setName(String);
+ }
+
public class XmlParser {
ctor public XmlParser();
method public static media.codecs.Included readIncluded(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/media/libstagefright/xmlparser/media_codecs.xsd b/media/libstagefright/xmlparser/media_codecs.xsd
index 77193a2..63ec5d0 100644
--- a/media/libstagefright/xmlparser/media_codecs.xsd
+++ b/media/libstagefright/xmlparser/media_codecs.xsd
@@ -49,24 +49,33 @@
</xs:sequence>
</xs:complexType>
<xs:complexType name="Settings">
- <xs:sequence>
- <xs:element name="Setting" type="Setting" maxOccurs="unbounded"/>
- </xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Setting" type="Setting"/>
+ <xs:element name="Variant" type="Setting"/>
+ <xs:element name="Domain" type="Setting"/>
+ </xs:choice>
</xs:complexType>
<xs:complexType name="MediaCodec">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Quirk" type="Quirk" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Attribute" type="Quirk" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Type" type="Type" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Alias" type="Alias" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Limit" type="Limit" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Feature" type="Feature" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Variant" type="Variant" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="type" type="xs:string"/>
<xs:attribute name="update" type="xs:string"/>
+ <xs:attribute name="rank" type="xs:string"/>
+ <xs:attribute name="domain" type="xs:string"/>
+ <xs:attribute name="variant" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Quirk">
<xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="value" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Type">
<xs:sequence>
@@ -97,9 +106,13 @@
<xs:attribute name="required" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
</xs:complexType>
+ <xs:complexType name="Variant">
+ <xs:attribute name="name" type="xs:string"/>
+ </xs:complexType>
<xs:complexType name="Setting">
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:string"/>
<xs:attribute name="update" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Include">
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1d99b88..ce408be 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4918,6 +4918,10 @@
// read original volumes with volume control
float typeVolume = mStreamTypes[track->streamType()].volume;
float v = masterVolume * typeVolume;
+ // Always fetch volumeshaper volume to ensure state is updated.
+ const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+ const float vh = track->getVolumeHandler()->getVolume(
+ track->mAudioTrackServerProxy->framesReleased()).first;
if (track->isPausing() || mStreamTypes[track->streamType()].mute
|| track->isPlaybackRestricted()) {
@@ -4927,7 +4931,6 @@
track->setPaused();
}
} else {
- sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
@@ -4940,8 +4943,6 @@
ALOGV("Track right volume out of range: %.3g", vrf);
vrf = GAIN_FLOAT_UNITY;
}
- const float vh = track->getVolumeHandler()->getVolume(
- track->mAudioTrackServerProxy->framesReleased()).first;
// now apply the master volume and stream type volume and shaper volume
vlf *= v * vh;
vrf *= v * vh;
@@ -5021,7 +5022,7 @@
(void *)(uintptr_t)(mChannelMask | mHapticChannelMask));
// limit track sample rate to 2 x output sample rate, which changes at re-configuration
uint32_t maxSampleRate = mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX;
- uint32_t reqSampleRate = track->mAudioTrackServerProxy->getSampleRate();
+ uint32_t reqSampleRate = proxy->getSampleRate();
if (reqSampleRate == 0) {
reqSampleRate = mSampleRate;
} else if (reqSampleRate > maxSampleRate) {
@@ -5033,7 +5034,7 @@
AudioMixer::SAMPLE_RATE,
(void *)(uintptr_t)reqSampleRate);
- AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
+ AudioPlaybackRate playbackRate = proxy->getPlaybackRate();
mAudioMixer->setParameter(
trackId,
AudioMixer::TIMESTRETCH,
@@ -5507,19 +5508,17 @@
{
float left, right;
+ // Ensure volumeshaper state always advances even when muted.
+ const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+ const auto [shaperVolume, shaperActive] = track->getVolumeHandler()->getVolume(
+ proxy->framesReleased());
+ mVolumeShaperActive = shaperActive;
+
if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
left = right = 0;
} else {
float typeVolume = mStreamTypes[track->streamType()].volume;
- float v = mMasterVolume * typeVolume;
- sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
-
- // Get volumeshaper scaling
- std::pair<float /* volume */, bool /* active */>
- vh = track->getVolumeHandler()->getVolume(
- track->mAudioTrackServerProxy->framesReleased());
- v *= vh.first;
- mVolumeShaperActive = vh.second;
+ const float v = mMasterVolume * typeVolume * shaperVolume;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
left = float_from_gain(gain_minifloat_unpack_left(vlr));
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 12b5e7d..094f506 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -19,7 +19,7 @@
#include "DeviceDescriptor.h"
#include <utils/RefBase.h>
#include <media/AudioPolicy.h>
-#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
#include <system/audio.h>
#include <utils/String8.h>
@@ -48,14 +48,15 @@
};
-class AudioPolicyMixCollection : public DefaultKeyedVector<String8, sp<AudioPolicyMix> >
+class AudioPolicyMixCollection : public Vector<sp<AudioPolicyMix>>
{
public:
- status_t getAudioPolicyMix(const String8& address, sp<AudioPolicyMix> &policyMix) const;
+ status_t getAudioPolicyMix(audio_devices_t deviceType,
+ const String8& address, sp<AudioPolicyMix> &policyMix) const;
- status_t registerMix(const String8& address, AudioMix mix, sp<SwAudioOutputDescriptor> desc);
+ status_t registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc);
- status_t unregisterMix(const String8& address);
+ status_t unregisterMix(const AudioMix& mix);
void closeOutput(sp<SwAudioOutputDescriptor> &desc);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 98a7800..dca84c0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -73,16 +73,21 @@
}
}
-status_t AudioPolicyMixCollection::registerMix(const String8& address, AudioMix mix,
- sp<SwAudioOutputDescriptor> desc)
+status_t AudioPolicyMixCollection::registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc)
{
- ssize_t index = indexOfKey(address);
- if (index >= 0) {
- ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
- return BAD_VALUE;
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioPolicyMix>& registeredMix = itemAt(i);
+ if (mix.mDeviceType == registeredMix->mDeviceType
+ && mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
+ ALOGE("registerMix(): mix already registered for dev=0x%x addr=%s",
+ mix.mDeviceType, mix.mDeviceAddress.string());
+ return BAD_VALUE;
+ }
}
sp<AudioPolicyMix> policyMix = new AudioPolicyMix(mix);
- add(address, policyMix);
+ add(policyMix);
+ ALOGD("registerMix(): adding mix for dev=0x%x addr=%s",
+ policyMix->mDeviceType, policyMix->mDeviceAddress.string());
if (desc != 0) {
desc->mPolicyMix = policyMix;
@@ -91,34 +96,48 @@
return NO_ERROR;
}
-status_t AudioPolicyMixCollection::unregisterMix(const String8& address)
+status_t AudioPolicyMixCollection::unregisterMix(const AudioMix& mix)
{
- ssize_t index = indexOfKey(address);
- if (index < 0) {
- ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
- return BAD_VALUE;
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioPolicyMix>& registeredMix = itemAt(i);
+ if (mix.mDeviceType == registeredMix->mDeviceType
+ && mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
+ ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
+ mix.mDeviceType, mix.mDeviceAddress.string());
+ removeAt(i);
+ return NO_ERROR;
+ }
}
- removeItemsAt(index);
- return NO_ERROR;
+ ALOGE("unregisterMix(): mix not registered for dev=0x%x addr=%s",
+ mix.mDeviceType, mix.mDeviceAddress.string());
+ return BAD_VALUE;
}
-status_t AudioPolicyMixCollection::getAudioPolicyMix(const String8& address,
- sp<AudioPolicyMix> &policyMix) const
+status_t AudioPolicyMixCollection::getAudioPolicyMix(audio_devices_t deviceType,
+ const String8& address, sp<AudioPolicyMix> &policyMix) const
{
- ssize_t index = indexOfKey(address);
- if (index < 0) {
- ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
- return BAD_VALUE;
+
+ ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.string());
+ for (ssize_t i = 0; i < size(); i++) {
+ if (itemAt(i)->mDeviceType == deviceType
+ && itemAt(i)->mDeviceAddress.compare(address) == 0) {
+ policyMix = itemAt(i);
+ ALOGV("getAudioPolicyMix: found mix %zu match (devType=0x%x addr=%s)",
+ i, deviceType, address.string());
+ return NO_ERROR;
+ }
}
- policyMix = valueAt(index);
- return NO_ERROR;
+
+ ALOGE("getAudioPolicyMix(): mix not registered for dev=0x%x addr=%s",
+ deviceType, address.string());
+ return BAD_VALUE;
}
void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc)
{
for (size_t i = 0; i < size(); i++) {
- sp<AudioPolicyMix> policyMix = valueAt(i);
+ sp<AudioPolicyMix> policyMix = itemAt(i);
if (policyMix->getOutput() == desc) {
policyMix->clearOutput();
}
@@ -134,7 +153,7 @@
ALOGV("getOutputForAttr() querying %zu mixes:", size());
primaryDesc = 0;
for (size_t i = 0; i < size(); i++) {
- sp<AudioPolicyMix> policyMix = valueAt(i);
+ sp<AudioPolicyMix> policyMix = itemAt(i);
const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
if (!primaryOutputMix && (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) {
// AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with
@@ -320,10 +339,10 @@
const DeviceVector &availableOutputDevices)
{
for (size_t i = 0; i < size(); i++) {
- if (valueAt(i)->getOutput() == output) {
+ if (itemAt(i)->getOutput() == output) {
// This Desc is involved in a Mix, which has the highest prio
- audio_devices_t deviceType = valueAt(i)->mDeviceType;
- String8 address = valueAt(i)->mDeviceAddress;
+ audio_devices_t deviceType = itemAt(i)->mDeviceType;
+ String8 address = itemAt(i)->mDeviceAddress;
ALOGV("%s: device (0x%x, addr=%s) forced by mix",
__FUNCTION__, deviceType, address.c_str());
return availableOutputDevices.getDevice(deviceType, address, AUDIO_FORMAT_DEFAULT);
@@ -338,7 +357,7 @@
sp<AudioPolicyMix> *policyMix) const
{
for (size_t i = 0; i < size(); i++) {
- AudioPolicyMix *mix = valueAt(i).get();
+ AudioPolicyMix *mix = itemAt(i).get();
if (mix->mMixType != MIX_TYPE_RECORDERS) {
continue;
}
@@ -374,19 +393,28 @@
String8 address(attr.tags + strlen("addr="));
#ifdef LOG_NDEBUG
- ALOGV("getInputMixForAttr looking for address %s\n mixes available:", address.string());
+ ALOGV("getInputMixForAttr looking for address %s for source %d\n mixes available:",
+ address.string(), attr.source);
for (size_t i = 0; i < size(); i++) {
- sp<AudioPolicyMix> audioPolicyMix = valueAt(i);
- ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
+ const sp<AudioPolicyMix> audioPolicyMix = itemAt(i);
+ ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
}
#endif
- ssize_t index = indexOfKey(address);
- if (index < 0) {
+ size_t index;
+ for (index = 0; index < size(); index++) {
+ const sp<AudioPolicyMix>& registeredMix = itemAt(index);
+ if (registeredMix->mDeviceAddress.compare(address) == 0) {
+ ALOGD("getInputMixForAttr found addr=%s dev=0x%x",
+ registeredMix->mDeviceAddress.string(), registeredMix->mDeviceType);
+ break;
+ }
+ }
+ if (index == size()) {
ALOGW("getInputMixForAttr() no policy for address %s", address.string());
return BAD_VALUE;
}
- sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
+ const sp<AudioPolicyMix> audioPolicyMix = itemAt(index);
if (audioPolicyMix->mMixType != MIX_TYPE_PLAYERS) {
ALOGW("getInputMixForAttr() bad policy mix type for address %s", address.string());
@@ -404,7 +432,7 @@
// "match uid" rule for this uid, return an error
// (adding a uid-device affinity would result in contradictory rules)
for (size_t i = 0; i < size(); i++) {
- const AudioPolicyMix* mix = valueAt(i).get();
+ const AudioPolicyMix* mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
@@ -421,7 +449,7 @@
// AND it doesn't have a "match uid" rule
// THEN add a rule to exclude the uid
for (size_t i = 0; i < size(); i++) {
- const AudioPolicyMix *mix = valueAt(i).get();
+ const AudioPolicyMix *mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
@@ -452,7 +480,7 @@
// for each player mix: remove existing rules that match or exclude this uid
for (size_t i = 0; i < size(); i++) {
bool foundUidRule = false;
- const AudioPolicyMix *mix = valueAt(i).get();
+ const AudioPolicyMix *mix = itemAt(i).get();
if (!mix->isDeviceAffinityCompatible()) {
continue;
}
@@ -481,7 +509,7 @@
// for each player mix: find rules that don't exclude this uid, and add the device to the list
for (size_t i = 0; i < size(); i++) {
bool ruleAllowsUid = true;
- const AudioPolicyMix *mix = valueAt(i).get();
+ const AudioPolicyMix *mix = itemAt(i).get();
if (mix->mMixType != MIX_TYPE_PLAYERS) {
continue;
}
@@ -504,7 +532,7 @@
{
dst->append("\nAudio Policy Mix:\n");
for (size_t i = 0; i < size(); i++) {
- valueAt(i)->dump(dst, 2, i);
+ itemAt(i)->dump(dst, 2, i);
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 575a6c2..3ca7591 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2868,13 +2868,16 @@
}
String8 address = mix.mDeviceAddress;
+ audio_devices_t deviceTypeToMakeAvailable;
if (mix.mMixType == MIX_TYPE_PLAYERS) {
- mix.mDeviceType = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
- } else {
mix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ deviceTypeToMakeAvailable = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ } else {
+ mix.mDeviceType = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ deviceTypeToMakeAvailable = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
- if (mPolicyMixes.registerMix(address, mix, 0 /*output desc*/) != NO_ERROR) {
+ if (mPolicyMixes.registerMix(mix, 0 /*output desc*/) != NO_ERROR) {
ALOGE("Error registering mix %zu for address %s", i, address.string());
res = INVALID_OPERATION;
break;
@@ -2890,7 +2893,7 @@
rSubmixModule->addInputProfile(address, &inputConfig,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
- if ((res = setDeviceConnectionStateInt(mix.mDeviceType,
+ if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
ALOGE("Failed to set remote submix device available, type %u, address %s",
@@ -2916,7 +2919,7 @@
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
if (desc->supportedDevices().contains(device)) {
- if (mPolicyMixes.registerMix(address, mix, desc) != NO_ERROR) {
+ if (mPolicyMixes.registerMix(mix, desc) != NO_ERROR) {
ALOGE("Could not register mix RENDER, dev=0x%X addr=%s", type,
address.string());
res = INVALID_OPERATION;
@@ -2966,7 +2969,7 @@
String8 address = mix.mDeviceAddress;
- if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
+ if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
res = INVALID_OPERATION;
continue;
}
@@ -2987,7 +2990,7 @@
rSubmixModule->removeInputProfile(address);
} else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
- if (mPolicyMixes.unregisterMix(mix.mDeviceAddress) != NO_ERROR) {
+ if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
res = INVALID_OPERATION;
continue;
}
@@ -3924,6 +3927,8 @@
if (status != NO_ERROR) {
mpClientInterface->releaseAudioPatch(sourceDesc->patchDesc()->mAfPatchHandle, 0);
+ outputDesc->removeClient(sourceDesc->portId());
+ outputDesc->stop();
return status;
}
sourceDesc->setSwOutput(outputDesc);
@@ -4188,6 +4193,7 @@
if (status == NO_ERROR) {
swOutputDesc->stop();
}
+ swOutputDesc->removeClient(sourceDesc->portId());
mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
} else {
sp<HwAudioOutputDescriptor> hwOutputDesc = sourceDesc->hwOutput().promote();
@@ -4650,7 +4656,8 @@
addOutput(output, desc);
if (device_distinguishes_on_address(deviceType) && address != "0") {
sp<AudioPolicyMix> policyMix;
- if (mPolicyMixes.getAudioPolicyMix(address, policyMix) == NO_ERROR) {
+ if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
+ == NO_ERROR) {
policyMix->setOutput(desc);
desc->mPolicyMix = policyMix;
} else {