Merge "C2SoftHevcEnc: Add support for dynamic bitrate change" into qt-dev
diff --git a/media/bufferpool/1.0/BufferPoolClient.cpp b/media/bufferpool/1.0/BufferPoolClient.cpp
index 41520ca..d712398 100644
--- a/media/bufferpool/1.0/BufferPoolClient.cpp
+++ b/media/bufferpool/1.0/BufferPoolClient.cpp
@@ -528,6 +528,10 @@
(void) outStatus;
(void) outBuffer;
});
+ if(!transResult.isOk()) {
+ ALOGD("sync from client %lld failed: bufferpool process died.",
+ (long long)mConnectionId);
+ }
}
mRemoteSyncLock.unlock();
}
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 5260909..94cf006 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -261,13 +261,19 @@
mBufferPool.mInvalidation.onHandleAck(&observers, &invalidationId);
}
// Do not hold lock for send invalidations
+ size_t deadClients = 0;
for (auto it = observers.begin(); it != observers.end(); ++it) {
const sp<IObserver> observer = it->second;
if (observer) {
Return<void> transResult = observer->onMessage(it->first, invalidationId);
- (void) transResult;
+ if (!transResult.isOk()) {
+ ++deadClients;
+ }
}
}
+ if (deadClients > 0) {
+ ALOGD("During invalidation found %zu dead clients", deadClients);
+ }
}
bool Accessor::Impl::isValid() {
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index f907de5..342fef6 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -582,6 +582,10 @@
(void) outStatus;
(void) outBuffer;
});
+ if (!transResult.isOk()) {
+ ALOGD("sync from client %lld failed: bufferpool process died.",
+ (long long)mConnectionId);
+ }
}
mRemoteSyncLock.unlock();
}
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 fb2da7c..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() {
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index e01fc90..f54690d 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1772,7 +1772,7 @@
int64_t codecDelay = pre_skip * 1000000000ll / kOpusSampleRate;
AMediaFormat_setBuffer(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CSD_0, opusInfo, sizeof(opusInfo));
+ AMEDIAFORMAT_KEY_CSD_0, opusInfo, opusInfoSize);
AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay));
AMediaFormat_setBuffer(mLastTrack->meta,
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/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp
index acb9ccf..513e41f 100644
--- a/media/libstagefright/foundation/OpusHeader.cpp
+++ b/media/libstagefright/foundation/OpusHeader.cpp
@@ -208,7 +208,7 @@
headerLen += AOPUS_LENGTH_SIZE;
int headerSize = WriteOpusHeader(header, inputSampleRate, output + headerLen,
- outputSize);
+ outputSize - headerLen);
if (headerSize < 0) {
ALOGD("%s: WriteOpusHeader failed", __func__);
return -1;
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/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 7008cee..a093893 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -31,6 +31,7 @@
private:
OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id);
void onFirstRef() override;
+ static void getPackagesForUid(uid_t uid, Vector<String16>& packages);
AppOpsManager mAppOpsManager;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b0817ed..78db80c 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -389,9 +389,16 @@
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType)
{
- if (isAudioServerOrRootUid(uid)) {
- ALOGD("OpPlayAudio: not muting track:%d usage:%d root or audioserver", id, attr.usage);
- return nullptr;
+ if (isServiceUid(uid)) {
+ Vector <String16> packages;
+ getPackagesForUid(uid, packages);
+ if (packages.isEmpty()) {
+ ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
+ id,
+ attr.usage,
+ uid);
+ return nullptr;
+ }
}
// stream type has been filtered by audio policy to indicate whether it can be muted
if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
@@ -423,8 +430,7 @@
void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
{
- PermissionController permissionController;
- permissionController.getPackagesForUid(mUid, mPackages);
+ getPackagesForUid(mUid, mPackages);
checkPlayAudioForUsage();
if (!mPackages.isEmpty()) {
mOpCallback = new PlayAudioOpCallback(this);
@@ -475,6 +481,14 @@
}
}
+// static
+void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::getPackagesForUid(
+ uid_t uid, Vector<String16>& packages)
+{
+ PermissionController permissionController;
+ permissionController.getPackagesForUid(uid, packages);
+}
+
// ----------------------------------------------------------------------------
#undef LOG_TAG
#define LOG_TAG "AF::Track"
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 {
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 743c816..5a87134 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -330,9 +330,9 @@
}
bool HeicCompositeStream::isSizeSupportedByHeifEncoder(int32_t width, int32_t height,
- bool* useHeic, bool* useGrid, int64_t* stall) {
+ bool* useHeic, bool* useGrid, int64_t* stall, AString* hevcName) {
static HeicEncoderInfoManager& heicManager = HeicEncoderInfoManager::getInstance();
- return heicManager.isSizeSupported(width, height, useHeic, useGrid, stall);
+ return heicManager.isSizeSupported(width, height, useHeic, useGrid, stall, hevcName);
}
bool HeicCompositeStream::isInMemoryTempFileSupported() {
@@ -1115,8 +1115,9 @@
ALOGV("%s", __FUNCTION__);
bool useGrid = false;
+ AString hevcName;
bool isSizeSupported = isSizeSupportedByHeifEncoder(width, height,
- &mUseHeic, &useGrid, nullptr);
+ &mUseHeic, &useGrid, nullptr, &hevcName);
if (!isSizeSupported) {
ALOGE("%s: Encoder doesnt' support size %u x %u!",
__FUNCTION__, width, height);
@@ -1138,7 +1139,11 @@
}
// Create HEIC/HEVC codec.
- mCodec = MediaCodec::CreateByType(mCodecLooper, desiredMime, true /*encoder*/);
+ if (mUseHeic) {
+ mCodec = MediaCodec::CreateByType(mCodecLooper, desiredMime, true /*encoder*/);
+ } else {
+ mCodec = MediaCodec::CreateByComponentName(mCodecLooper, hevcName);
+ }
if (mCodec == nullptr) {
ALOGE("%s: Failed to create codec for %s", __FUNCTION__, desiredMime);
return NO_INIT;
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 2aa3c38..260c68e 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -71,7 +71,7 @@
const CameraMetadata& ch, std::vector<OutputStreamInfo>* compositeOutput /*out*/);
static bool isSizeSupportedByHeifEncoder(int32_t width, int32_t height,
- bool* useHeic, bool* useGrid, int64_t* stall);
+ bool* useHeic, bool* useGrid, int64_t* stall, AString* hevcName = nullptr);
static bool isInMemoryTempFileSupported();
protected:
diff --git a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
index ed9be6e..d7cc2bf 100644
--- a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
+++ b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
@@ -49,7 +49,7 @@
}
bool HeicEncoderInfoManager::isSizeSupported(int32_t width, int32_t height, bool* useHeic,
- bool* useGrid, int64_t* stall) const {
+ bool* useGrid, int64_t* stall, AString* hevcName) const {
if (useHeic == nullptr || useGrid == nullptr) {
ALOGE("%s: invalid parameters: useHeic %p, useGrid %p",
__FUNCTION__, useHeic, useGrid);
@@ -72,6 +72,9 @@
(width <= 1920 && height <= 1080))) {
enableGrid = false;
}
+ if (hevcName != nullptr) {
+ *hevcName = mHevcName;
+ }
} else {
// No encoder available for the requested size.
return false;
@@ -113,9 +116,8 @@
}
sp<AMessage> heicDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
- sp<AMessage> hevcDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_VIDEO_HEVC);
- if (hevcDetails == nullptr) {
+ if (!getHevcCodecDetails(codecsList, MEDIA_MIMETYPE_VIDEO_HEVC)) {
if (heicDetails != nullptr) {
ALOGE("%s: Device must support HEVC codec if HEIC codec is available!",
__FUNCTION__);
@@ -123,22 +125,7 @@
}
return OK;
}
-
- // Check CQ mode for HEVC codec
- {
- AString bitrateModes;
- auto hasItem = hevcDetails->findString("feature-bitrate-modes", &bitrateModes);
- if (!hasItem) {
- ALOGE("%s: Failed to query bitrate modes for HEVC codec", __FUNCTION__);
- return BAD_VALUE;
- }
- ALOGV("%s: HEVC codec's feature-bitrate-modes value is %d, %s",
- __FUNCTION__, hasItem, bitrateModes.c_str());
- std::regex pattern("(^|,)CQ($|,)", std::regex_constants::icase);
- if (!std::regex_search(bitrateModes.c_str(), pattern)) {
- return OK;
- }
- }
+ mHasHEVC = true;
// HEIC size range
if (heicDetails != nullptr) {
@@ -152,19 +139,6 @@
mHasHEIC = true;
}
- // HEVC size range
- {
- auto res = getCodecSizeRange(MEDIA_MIMETYPE_VIDEO_HEVC,
- hevcDetails, &mMinSizeHevc, &mMaxSizeHevc, &mHevcFrameRateMaps);
- if (res != OK) {
- ALOGE("%s: Failed to get HEVC codec size range: %s (%d)", __FUNCTION__,
- strerror(-res), res);
- return BAD_VALUE;
- }
-
- mHasHEVC = true;
- }
-
return OK;
}
@@ -290,5 +264,80 @@
return details;
}
+
+bool HeicEncoderInfoManager::getHevcCodecDetails(
+ sp<IMediaCodecList> codecsList, const char* mime) {
+ bool found = false;
+ ssize_t idx = 0;
+ while ((idx = codecsList->findCodecByType(mime, true /*encoder*/, idx)) >= 0) {
+ const sp<MediaCodecInfo> info = codecsList->getCodecInfo(idx++);
+ if (info == nullptr) {
+ ALOGE("%s: Failed to get codec info for %s", __FUNCTION__, mime);
+ break;
+ }
+
+ // Filter out software ones as they may be too slow
+ if (!(info->getAttributes() & MediaCodecInfo::kFlagIsHardwareAccelerated)) {
+ continue;
+ }
+
+ const sp<MediaCodecInfo::Capabilities> caps =
+ info->getCapabilitiesFor(mime);
+ if (caps == nullptr) {
+ ALOGE("%s: [%s] Failed to get capabilities", __FUNCTION__,
+ info->getCodecName());
+ break;
+ }
+ const sp<AMessage> details = caps->getDetails();
+ if (details == nullptr) {
+ ALOGE("%s: [%s] Failed to get details", __FUNCTION__,
+ info->getCodecName());
+ break;
+ }
+
+ // Check CQ mode
+ AString bitrateModes;
+ auto hasItem = details->findString("feature-bitrate-modes", &bitrateModes);
+ if (!hasItem) {
+ ALOGE("%s: [%s] Failed to query bitrate modes", __FUNCTION__,
+ info->getCodecName());
+ break;
+ }
+ ALOGV("%s: [%s] feature-bitrate-modes value is %d, %s",
+ __FUNCTION__, info->getCodecName(), hasItem, bitrateModes.c_str());
+ std::regex pattern("(^|,)CQ($|,)", std::regex_constants::icase);
+ if (!std::regex_search(bitrateModes.c_str(), pattern)) {
+ continue; // move on to next encoder
+ }
+
+ std::pair<int32_t, int32_t> minSizeHevc, maxSizeHevc;
+ FrameRateMaps hevcFrameRateMaps;
+ auto res = getCodecSizeRange(MEDIA_MIMETYPE_VIDEO_HEVC,
+ details, &minSizeHevc, &maxSizeHevc, &hevcFrameRateMaps);
+ if (res != OK) {
+ ALOGE("%s: [%s] Failed to get size range: %s (%d)", __FUNCTION__,
+ info->getCodecName(), strerror(-res), res);
+ break;
+ }
+ if (kGridWidth < minSizeHevc.first
+ || kGridWidth > maxSizeHevc.first
+ || kGridHeight < minSizeHevc.second
+ || kGridHeight > maxSizeHevc.second) {
+ continue; // move on to next encoder
+ }
+
+ // Found: save name, size, frame rate
+ mHevcName = info->getCodecName();
+ mMinSizeHevc = minSizeHevc;
+ mMaxSizeHevc = maxSizeHevc;
+ mHevcFrameRateMaps = hevcFrameRateMaps;
+
+ found = true;
+ break;
+ }
+
+ return found;
+}
+
} //namespace camera3
} // namespace android
diff --git a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.h b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.h
index fb0b914..58edba2 100644
--- a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.h
+++ b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.h
@@ -36,7 +36,7 @@
}
bool isSizeSupported(int32_t width, int32_t height,
- bool* useHeic, bool* useGrid, int64_t* stall) const;
+ bool* useHeic, bool* useGrid, int64_t* stall, AString* hevcName) const;
static const auto kGridWidth = 512;
static const auto kGridHeight = 512;
@@ -61,11 +61,13 @@
FrameRateMaps::const_iterator findClosestSize(const FrameRateMaps& maps,
int32_t width, int32_t height) const;
sp<AMessage> getCodecDetails(sp<IMediaCodecList> codecsList, const char* name);
+ bool getHevcCodecDetails(sp<IMediaCodecList> codecsList, const char* mime);
bool mIsInited;
std::pair<int32_t, int32_t> mMinSizeHeic, mMaxSizeHeic;
std::pair<int32_t, int32_t> mMinSizeHevc, mMaxSizeHevc;
bool mHasHEVC, mHasHEIC;
+ AString mHevcName;
FrameRateMaps mHeicFrameRateMaps, mHevcFrameRateMaps;
bool mDisableGrid;