Merge "Add support for manually set surround formats." into pi-dev
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index b53c741..5d0f68e 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -253,7 +253,7 @@
int32_t seqNum = mHeapSeqNum++;
sp<HidlMemory> hidlMemory = fromHeap(heap);
- mHeapBases.add(seqNum, mNextBufferId);
+ mHeapBases.add(seqNum, HeapBase(mNextBufferId, heap->getSize()));
Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, mNextBufferId++);
ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
return seqNum;
@@ -278,10 +278,26 @@
return UNEXPECTED_NULL;
}
- // memory must be in the declared heap
- CHECK(mHeapBases.indexOfKey(seqNum) >= 0);
+ // memory must be in one of the heaps that have been set
+ if (mHeapBases.indexOfKey(seqNum) < 0) {
+ return UNKNOWN_ERROR;
+ }
- buffer->bufferId = mHeapBases.valueFor(seqNum);
+ // heap must be the same size as the one that was set in setHeapBase
+ if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) {
+ android_errorWriteLog(0x534e4554, "76221123");
+ return UNKNOWN_ERROR;
+ }
+
+ // memory must be within the address space of the heap
+ if (memory->pointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset() ||
+ heap->getSize() < memory->offset() + memory->size() ||
+ SIZE_MAX - memory->offset() < memory->size()) {
+ android_errorWriteLog(0x534e4554, "76221123");
+ return UNKNOWN_ERROR;
+ }
+
+ buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId();
buffer->offset = offset >= 0 ? offset : 0;
buffer->size = size;
return OK;
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index fce1717..4fed707 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -29,6 +29,7 @@
using ::android::String16;
using ::android::String8;
using ::android::drm_metrics::DrmFrameworkMetrics;
+using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::drm::V1_0::EventType;
using ::android::hardware::drm::V1_0::KeyStatusType;
@@ -192,6 +193,13 @@
}
}
+inline String16 MakeIndexString(unsigned int index) {
+ std::string str("[");
+ str.append(std::to_string(index));
+ str.append("]");
+ return String16(str.c_str());
+}
+
} // namespace
namespace android {
@@ -370,9 +378,11 @@
}
int groupIndex = 0;
+ std::map<String16, int> indexMap;
for (const auto &hidlMetricGroup : hidlMetricGroups) {
PersistableBundle bundleMetricGroup;
for (const auto &hidlMetric : hidlMetricGroup.metrics) {
+ String16 metricName(hidlMetric.name.c_str());
PersistableBundle bundleMetric;
// Add metric component values.
for (const auto &value : hidlMetric.values) {
@@ -388,14 +398,22 @@
// Add attributes to the bundle metric.
bundleMetric.putPersistableBundle(String16("attributes"),
bundleMetricAttributes);
+ // Add one layer of indirection, allowing for repeated metric names.
+ PersistableBundle repeatedMetrics;
+ bundleMetricGroup.getPersistableBundle(metricName,
+ &repeatedMetrics);
+ int index = indexMap[metricName];
+ repeatedMetrics.putPersistableBundle(MakeIndexString(index),
+ bundleMetric);
+ indexMap[metricName] = ++index;
+
// Add the bundle metric to the group of metrics.
- bundleMetricGroup.putPersistableBundle(
- String16(hidlMetric.name.c_str()), bundleMetric);
+ bundleMetricGroup.putPersistableBundle(metricName,
+ repeatedMetrics);
}
// Add the bundle metric group to the collection of groups.
- bundleMetricGroups->putPersistableBundle(
- String16(std::to_string(groupIndex).c_str()), bundleMetricGroup);
- groupIndex++;
+ bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
+ bundleMetricGroup);
}
return OK;
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index 1a20342..64aa9d0 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -429,7 +429,8 @@
DrmMetricGroup hidlMetricGroup =
{ { {
"open_session_ok",
- { { "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, "" } },
+ { { "status", DrmMetricGroup::ValueType::INT64_TYPE,
+ (int64_t) Status::OK, 0.0, "" } },
{ { "count", DrmMetricGroup::ValueType::INT64_TYPE, 3, 0.0, "" } }
},
{
@@ -444,25 +445,28 @@
&bundleMetricGroups));
ASSERT_EQ(1U, bundleMetricGroups.size());
PersistableBundle bundleMetricGroup;
- ASSERT_TRUE(bundleMetricGroups.getPersistableBundle(String16("0"), &bundleMetricGroup));
+ ASSERT_TRUE(bundleMetricGroups.getPersistableBundle(String16("[0]"), &bundleMetricGroup));
ASSERT_EQ(2U, bundleMetricGroup.size());
// Verify each metric.
PersistableBundle metric;
ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("open_session_ok"), &metric));
+ PersistableBundle metricInstance;
+ ASSERT_TRUE(metric.getPersistableBundle(String16("[0]"), &metricInstance));
int64_t value = 0;
- ASSERT_TRUE(metric.getLong(String16("count"), &value));
+ ASSERT_TRUE(metricInstance.getLong(String16("count"), &value));
ASSERT_EQ(3, value);
PersistableBundle attributeBundle;
- ASSERT_TRUE(metric.getPersistableBundle(String16("attributes"), &attributeBundle));
+ ASSERT_TRUE(metricInstance.getPersistableBundle(String16("attributes"), &attributeBundle));
ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
ASSERT_EQ((int64_t) Status::OK, value);
ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("close_session_not_opened"),
&metric));
- ASSERT_TRUE(metric.getLong(String16("count"), &value));
+ ASSERT_TRUE(metric.getPersistableBundle(String16("[0]"), &metricInstance));
+ ASSERT_TRUE(metricInstance.getLong(String16("count"), &value));
ASSERT_EQ(7, value);
- ASSERT_TRUE(metric.getPersistableBundle(String16("attributes"), &attributeBundle));
+ ASSERT_TRUE(metricInstance.getPersistableBundle(String16("attributes"), &attributeBundle));
value = 0;
ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
ASSERT_EQ((int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, value);
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index a1f6e9a..b6787af 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -1397,7 +1397,8 @@
ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId);
if (image.isGrid()) {
- if (size > 12) {
+ // ImageGrid struct is at least 8-byte, at most 12-byte (if flags&1)
+ if (size < 8 || size > 12) {
return ERROR_MALFORMED;
}
uint8_t buf[12];
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 1981ba3..505f2ee 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -350,7 +350,7 @@
mTimestampPosition.set(getFramesRead());
mAudioRecord->stop();
mCallbackEnabled.store(false);
- mFramesRead.reset32();
+ mFramesWritten.reset32(); // service writes frames, service position reset on flush
mTimestampPosition.reset32();
// Pass false to prevent errorCallback from being called after disconnect
// when app has already requested a stop().
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 9653601..505cd77 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -310,7 +310,7 @@
setState(AAUDIO_STREAM_STATE_FLUSHING);
incrementFramesRead(getFramesWritten() - getFramesRead());
mAudioTrack->flush();
- mFramesWritten.reset32();
+ mFramesRead.reset32(); // service reads frames, service position reset on flush
mTimestampPosition.reset32();
return AAUDIO_OK;
}
@@ -324,7 +324,7 @@
setState(AAUDIO_STREAM_STATE_STOPPING);
incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
mTimestampPosition.set(getFramesWritten());
- mFramesWritten.reset32();
+ mFramesRead.reset32(); // service reads frames, service position reset on stop
mTimestampPosition.reset32();
mAudioTrack->stop();
mCallbackEnabled.store(false);
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 86791c2..ab9efe8 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -806,7 +806,7 @@
return;
}
AutoMutex lock(mLock);
- if (mState == STATE_ACTIVE || mState == STATE_FLUSHED) {
+ if (mState == STATE_ACTIVE) {
return;
}
flush_l();
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index dcd305b..a1236e7 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -926,7 +926,8 @@
case SET_DEVICE_CONNECTION_STATE:
case HANDLE_DEVICE_CONFIG_CHANGE:
case SET_PHONE_STATE:
- case SET_FORCE_USE:
+//FIXME: Allow SET_FORCE_USE calls from system apps until a better use case routing API is available
+// case SET_FORCE_USE:
case INIT_STREAM_VOLUME:
case SET_STREAM_VOLUME:
case REGISTER_POLICY_MIXES:
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 045c2c3..aa39443 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -313,6 +313,14 @@
targetFormat,
kCopyBufferFrameCount));
requiresReconfigure = true;
+ } else if (mFormat == AUDIO_FORMAT_PCM_FLOAT) {
+ // Input and output are floats, make sure application did not provide > 3db samples
+ // that would break volume application (b/68099072)
+ // TODO: add a trusted source flag to avoid the overhead
+ mReformatBufferProvider.reset(new ClampFloatBufferProvider(
+ audio_channel_count_from_out_mask(channelMask),
+ kCopyBufferFrameCount));
+ requiresReconfigure = true;
}
if (targetFormat != mMixerInFormat) {
mPostDownmixReformatBufferProvider.reset(new ReformatBufferProvider(
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index e19af4a..2d9e1cb 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -376,6 +376,23 @@
memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount);
}
+ClampFloatBufferProvider::ClampFloatBufferProvider(int32_t channelCount, size_t bufferFrameCount) :
+ CopyBufferProvider(
+ channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
+ channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
+ bufferFrameCount),
+ mChannelCount(channelCount)
+{
+ ALOGV("ClampFloatBufferProvider(%p)(%u)", this, channelCount);
+}
+
+void ClampFloatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
+{
+ memcpy_to_float_from_float_with_clamping((float*)dst, (const float*)src,
+ frames * mChannelCount,
+ FLOAT_NOMINAL_RANGE_HEADROOM);
+}
+
TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount,
audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate) :
mChannelCount(channelCount),
diff --git a/media/libeffects/data/audio_effects.xml b/media/libeffects/data/audio_effects.xml
new file mode 100644
index 0000000..3f85052
--- /dev/null
+++ b/media/libeffects/data/audio_effects.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<audio_effects_conf version="2.0" xmlns="http://schemas.android.com/audio/audio_effects_conf/v2_0">
+ <!-- List of effect libraries to load.
+ Each library element must contain a "name" attribute and a "path" attribute giving the
+ name of a library .so file in /vendor/lib/soundfx on the target
+
+ If offloadable effects are present, the AOSP library libeffectproxy.so must be listed as
+ well as one library for the SW implementation and one library for the DSP implementation:
+ <library name="proxy" path="libeffectproxy.so"/>
+ <library name="some_fx_sw" path="lib_some_fx_sw.so"/>
+ <library name="some_fx_hw" path="lib_some_fx_hw.so"/>
+
+ If the audio HAL implements support for AOSP software audio pre-processing effects,
+ the following library must be added:
+ <library name="pre_processing" path="libaudiopreprocessing.so"/>
+ -->
+ <libraries>
+ <library name="bundle" path="libbundlewrapper.so"/>
+ <library name="reverb" path="libreverbwrapper.so"/>
+ <library name="visualizer" path="libvisualizer.so"/>
+ <library name="downmix" path="libdownmix.so"/>
+ <library name="loudness_enhancer" path="libldnhncr.so"/>
+ <library name="dynamics_processing" path="libdynproc.so"/>
+ </libraries>
+
+ <!-- list of effects to load.
+ Each "effect" element must contain a "name", "library" and a "uuid" attribute.
+ The value of the "library" element must correspond to the name of one library element in
+ the "libraries" element.
+ The "name" attribute is indicative, only the value of the "uuid" attribute designates
+ the effect.
+ The uuid is the implementation specific UUID as specified by the effect vendor. This is not
+ the generic effect type UUID.
+
+ Offloadable effects are described by an "effectProxy" element which contains one "libsw"
+ element containing the "uuid" and "library" for the SW implementation and one "libhw"
+ element containing the "uuid" and "library" for the DSP implementation.
+ The "uuid" value for the "effectProxy" element must be unique and will override the default
+ uuid in the AOSP proxy effect implementation.
+
+ If the audio HAL implements support for AOSP software audio pre-processing effects,
+ the following effects can be added:
+ <effect name="agc" library="pre_processing" uuid="aa8130e0-66fc-11e0-bad0-0002a5d5c51b"/>
+ <effect name="aec" library="pre_processing" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
+ <effect name="ns" library="pre_processing" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
+ -->
+
+ <effects>
+ <effect name="bassboost" library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
+ <effect name="virtualizer" library="bundle" uuid="1d4033c0-8557-11df-9f2d-0002a5d5c51b"/>
+ <effect name="equalizer" library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
+ <effect name="volume" library="bundle" uuid="119341a0-8469-11df-81f9-0002a5d5c51b"/>
+ <effect name="reverb_env_aux" library="reverb" uuid="4a387fc0-8ab3-11df-8bad-0002a5d5c51b"/>
+ <effect name="reverb_env_ins" library="reverb" uuid="c7a511a0-a3bb-11df-860e-0002a5d5c51b"/>
+ <effect name="reverb_pre_aux" library="reverb" uuid="f29a1400-a3bb-11df-8ddc-0002a5d5c51b"/>
+ <effect name="reverb_pre_ins" library="reverb" uuid="172cdf00-a3bc-11df-a72f-0002a5d5c51b"/>
+ <effect name="visualizer" library="visualizer" uuid="d069d9e0-8329-11df-9168-0002a5d5c51b"/>
+ <effect name="downmix" library="downmix" uuid="93f04452-e4fe-41cc-91f9-e475b6d1d69f"/>
+ <effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
+ <effect name="dynamics_processing" library="dynamics_processing" uuid="e0e6539b-1781-7261-676f-6d7573696340"/>
+ </effects>
+
+ <!-- Audio pre processor configurations.
+ The pre processor configuration is described in a "preprocess" element and consists in a
+ list of elements each describing pre processor settings for a given use case or "stream".
+ Each stream element has a "type" attribute corresponding to the input source used.
+ Valid types are:
+ "mic", "camcorder", "voice_recognition", "voice_communication"
+ Each "stream" element contains a list of "apply" elements indicating one effect to apply.
+ The effect to apply is designated by its name in the "effects" elements.
+
+ <preprocess>
+ <stream type="voice_communication">
+ <apply effect="aec"/>
+ <apply effect="ns"/>
+ </stream>
+ </preprocess>
+ -->
+
+ <!-- Audio post processor configurations.
+ The post processor configuration is described in a "postprocess" element and consists in a
+ list of elements each describing post processor settings for a given use case or "stream".
+ Each stream element has a "type" attribute corresponding to the stream type used.
+ Valid types are:
+ "music", "ring", "alarm", "notification", "voice_call"
+ Each "stream" element contains a list of "apply" elements indicating one effect to apply.
+ The effect to apply is designated by its name in the "effects" elements.
+
+ <postprocess>
+ <stream type="music">
+ <apply effect="music_post_proc"/>
+ </stream>
+ <stream type="voice_call">
+ <apply effect="voice_post_proc"/>
+ </stream>
+ <stream type="notification">
+ <apply effect="notification_post_proc"/>
+ </stream>
+ </postprocess>
+ -->
+
+</audio_effects_conf>
diff --git a/media/libmedia/include/media/BufferProviders.h b/media/libmedia/include/media/BufferProviders.h
index 9d026f6..d6a9cfb 100644
--- a/media/libmedia/include/media/BufferProviders.h
+++ b/media/libmedia/include/media/BufferProviders.h
@@ -161,6 +161,17 @@
const audio_format_t mOutputFormat;
};
+// ClampFloatBufferProvider derives from CopyBufferProvider to clamp floats inside -3db
+class ClampFloatBufferProvider : public CopyBufferProvider {
+public:
+ ClampFloatBufferProvider(int32_t channelCount,
+ size_t bufferFrameCount);
+ virtual void copyFrames(void *dst, const void *src, size_t frames);
+
+protected:
+ const uint32_t mChannelCount;
+};
+
// TimestretchBufferProvider derives from PassthruBufferProvider for time stretching
class TimestretchBufferProvider : public PassthruBufferProvider {
public:
diff --git a/media/libmedia/include/media/CryptoHal.h b/media/libmedia/include/media/CryptoHal.h
index 4414e9d..ff8789d 100644
--- a/media/libmedia/include/media/CryptoHal.h
+++ b/media/libmedia/include/media/CryptoHal.h
@@ -81,7 +81,20 @@
*/
status_t mInitCheck;
- KeyedVector<int32_t, uint32_t> mHeapBases;
+ struct HeapBase {
+ HeapBase() : mBufferId(0), mSize(0) {}
+ HeapBase(uint32_t bufferId, size_t size) :
+ mBufferId(bufferId), mSize(size) {}
+
+ uint32_t getBufferId() const {return mBufferId;}
+ size_t getSize() const {return mSize;}
+
+ private:
+ uint32_t mBufferId;
+ size_t mSize;
+ };
+
+ KeyedVector<int32_t, HeapBase> mHeapBases;
uint32_t mNextBufferId;
int32_t mHeapSeqNum;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 22b1e59..48e351b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -162,7 +162,6 @@
"libmedia_helper",
"libstagefright_codecbase",
"libstagefright_foundation",
- "libstagefright_omx",
"libstagefright_omx_utils",
"libstagefright_xmlparser",
"libRScpp",
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index fe141ab..96b896b 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -108,24 +108,6 @@
if (!transStatus.isOk()) {
ALOGE("Fail to obtain codec roles from IOmxStore.");
return NO_INIT;
- } else if (roles.size() == 0) {
- ALOGW("IOmxStore has empty implementation. "
- "Creating a local default instance...");
- omxStore = new implementation::OmxStore();
- if (omxStore == nullptr) {
- ALOGE("Cannot create a local default instance.");
- return NO_INIT;
- }
- ALOGI("IOmxStore local default instance created.");
- transStatus = omxStore->listRoles(
- [&roles] (
- const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
- roles = inRoleList;
- });
- if (!transStatus.isOk()) {
- ALOGE("Fail to obtain codec roles from local IOmxStore.");
- return NO_INIT;
- }
}
hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index ecd2512..bc0a69f 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -45,7 +45,7 @@
#define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost"
#define PROP_DRC_OVERRIDE_HEAVY "aac_drc_heavy"
#define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
-#define PROP_DRC_OVERRIDE_EFFECT "aac_drc_effect_type"
+#define PROP_DRC_OVERRIDE_EFFECT "ro.aac_drc_effect_type"
namespace android {
@@ -65,6 +65,7 @@
OMX_AUDIO_AACObjectLD,
OMX_AUDIO_AACObjectELD,
OMX_AUDIO_AACObjectER_Scalable,
+ OMX_AUDIO_AACObjectXHE,
};
SoftAAC2::SoftAAC2(
@@ -210,10 +211,8 @@
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, DRC_DEFAULT_MOBILE_ENC_LEVEL);
}
// AAC_UNIDRC_SET_EFFECT
- int32_t effectType = DRC_DEFAULT_MOBILE_DRC_EFFECT;
- // FIXME can't read default property for DRC effect type
- //int32_t effectType =
- // property_get_int32(PROP_DRC_OVERRIDE_EFFECT, DRC_DEFAULT_MOBILE_DRC_EFFECT);
+ int32_t effectType =
+ property_get_int32(PROP_DRC_OVERRIDE_EFFECT, DRC_DEFAULT_MOBILE_DRC_EFFECT);
if (effectType < -1 || effectType > 8) {
effectType = DRC_DEFAULT_MOBILE_DRC_EFFECT;
}
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 1b38852..05f4104 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -25,7 +25,7 @@
#include "libyuv/convert_from.h"
#include "libyuv/video_common.h"
-
+#include <functional>
#include <sys/time.h>
#define USE_LIBYUV
@@ -58,14 +58,16 @@
bool ColorConverter::isValid() const {
switch (mSrcFormat) {
+ case OMX_COLOR_FormatYUV420Planar16:
+ if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
+ return true;
+ }
+ // fall-thru
case OMX_COLOR_FormatYUV420Planar:
return mDstFormat == OMX_COLOR_Format16bitRGB565
|| mDstFormat == OMX_COLOR_Format32BitRGBA8888
|| mDstFormat == OMX_COLOR_Format32bitBGRA8888;
- case OMX_COLOR_FormatYUV420Planar16:
- return mDstFormat == OMX_COLOR_FormatYUV444Y410;
-
case OMX_COLOR_FormatCbYCrY:
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
case OMX_COLOR_FormatYUV420SemiPlanar:
@@ -311,84 +313,120 @@
return OK;
}
-void ColorConverter::writeToDst(
- void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
- signed r1, signed g1, signed b1,
- signed r2, signed g2, signed b2) {
- switch (mDstFormat) {
+std::function<void (void *, void *, void *, size_t,
+ signed *, signed *, signed *, signed *)>
+getReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) {
+ switch(srcFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ return [](void *src_y, void *src_u, void *src_v, size_t x,
+ signed *y1, signed *y2, signed *u, signed *v) {
+ *y1 = ((uint8_t*)src_y)[x] - 16;
+ *y2 = ((uint8_t*)src_y)[x + 1] - 16;
+ *u = ((uint8_t*)src_u)[x / 2] - 128;
+ *v = ((uint8_t*)src_v)[x / 2] - 128;
+ };
+ case OMX_COLOR_FormatYUV420Planar16:
+ return [](void *src_y, void *src_u, void *src_v, size_t x,
+ signed *y1, signed *y2, signed *u, signed *v) {
+ *y1 = (signed)(((uint16_t*)src_y)[x] >> 2) - 16;
+ *y2 = (signed)(((uint16_t*)src_y)[x + 1] >> 2) - 16;
+ *u = (signed)(((uint16_t*)src_u)[x / 2] >> 2) - 128;
+ *v = (signed)(((uint16_t*)src_v)[x / 2] >> 2) - 128;
+ };
+ default:
+ TRESPASS();
+ }
+ return nullptr;
+}
+
+std::function<void (void *, bool, signed, signed, signed, signed, signed, signed)>
+getWriteToDst(OMX_COLOR_FORMATTYPE dstFormat, uint8_t *kAdjustedClip) {
+ switch (dstFormat) {
case OMX_COLOR_Format16bitRGB565:
{
- uint32_t rgb1 =
- ((kAdjustedClip[r1] >> 3) << 11)
- | ((kAdjustedClip[g1] >> 2) << 5)
- | (kAdjustedClip[b1] >> 3);
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ uint32_t rgb1 =
+ ((kAdjustedClip[r1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[b1] >> 3);
- if (uncropped) {
- uint32_t rgb2 =
- ((kAdjustedClip[r2] >> 3) << 11)
- | ((kAdjustedClip[g2] >> 2) << 5)
- | (kAdjustedClip[b2] >> 3);
+ if (uncropped) {
+ uint32_t rgb2 =
+ ((kAdjustedClip[r2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
- *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
- } else {
- *(uint16_t *)dst_ptr = rgb1;
- }
- break;
+ *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
+ } else {
+ *(uint16_t *)dst_ptr = rgb1;
+ }
+ };
}
case OMX_COLOR_Format32BitRGBA8888:
{
- ((uint32_t *)dst_ptr)[0] =
- (kAdjustedClip[r1])
- | (kAdjustedClip[g1] << 8)
- | (kAdjustedClip[b1] << 16)
- | (0xFF << 24);
-
- if (uncropped) {
- ((uint32_t *)dst_ptr)[1] =
- (kAdjustedClip[r2])
- | (kAdjustedClip[g2] << 8)
- | (kAdjustedClip[b2] << 16)
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ ((uint32_t *)dst_ptr)[0] =
+ (kAdjustedClip[r1])
+ | (kAdjustedClip[g1] << 8)
+ | (kAdjustedClip[b1] << 16)
| (0xFF << 24);
- }
- break;
+
+ if (uncropped) {
+ ((uint32_t *)dst_ptr)[1] =
+ (kAdjustedClip[r2])
+ | (kAdjustedClip[g2] << 8)
+ | (kAdjustedClip[b2] << 16)
+ | (0xFF << 24);
+ }
+ };
}
case OMX_COLOR_Format32bitBGRA8888:
{
- ((uint32_t *)dst_ptr)[0] =
- (kAdjustedClip[b1])
- | (kAdjustedClip[g1] << 8)
- | (kAdjustedClip[r1] << 16)
- | (0xFF << 24);
-
- if (uncropped) {
- ((uint32_t *)dst_ptr)[1] =
- (kAdjustedClip[b2])
- | (kAdjustedClip[g2] << 8)
- | (kAdjustedClip[r2] << 16)
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ ((uint32_t *)dst_ptr)[0] =
+ (kAdjustedClip[b1])
+ | (kAdjustedClip[g1] << 8)
+ | (kAdjustedClip[r1] << 16)
| (0xFF << 24);
- }
- break;
+
+ if (uncropped) {
+ ((uint32_t *)dst_ptr)[1] =
+ (kAdjustedClip[b2])
+ | (kAdjustedClip[g2] << 8)
+ | (kAdjustedClip[r2] << 16)
+ | (0xFF << 24);
+ }
+ };
}
default:
- break;
+ TRESPASS();
}
+ return nullptr;
}
+
status_t ColorConverter::convertYUV420Planar(
const BitmapParams &src, const BitmapParams &dst) {
uint8_t *kAdjustedClip = initClip();
+ auto readFromSrc = getReadFromSrc(mSrcFormat);
+ auto writeToDst = getWriteToDst(mDstFormat, kAdjustedClip);
+
uint8_t *dst_ptr = (uint8_t *)dst.mBits
- + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+ + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
- const uint8_t *src_y =
- (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
+ uint8_t *src_y = (uint8_t *)src.mBits
+ + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp;
- const uint8_t *src_u =
- (const uint8_t *)src.mBits + src.mStride * src.mHeight
- + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2;
+ uint8_t *src_u = (uint8_t *)src.mBits + src.mStride * src.mHeight
+ + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2 * src.mBpp;
- const uint8_t *src_v =
- src_u + (src.mStride / 2) * (src.mHeight / 2);
+ uint8_t *src_v = src_u + (src.mStride / 2) * (src.mHeight / 2);
for (size_t y = 0; y < src.cropHeight(); ++y) {
for (size_t x = 0; x < src.cropWidth(); x += 2) {
@@ -410,11 +448,8 @@
// clip range -278 .. 535
- signed y1 = (signed)src_y[x] - 16;
- signed y2 = (signed)src_y[x + 1] - 16;
-
- signed u = (signed)src_u[x / 2] - 128;
- signed v = (signed)src_v[x / 2] - 128;
+ signed y1, y2, u, v;
+ readFromSrc(src_y, src_u, src_v, x, &y1, &y2, &u, &v);
signed u_b = u * 517;
signed u_g = -u * 100;
@@ -432,8 +467,7 @@
signed r2 = (tmp2 + v_r) / 256;
bool uncropped = x + 1 < src.cropWidth();
- (void)writeToDst(dst_ptr + x * dst.mBpp,
- kAdjustedClip, uncropped, r1, g1, b1, r2, g2, b2);
+ writeToDst(dst_ptr + x * dst.mBpp, uncropped, r1, g1, b1, r2, g2, b2);
}
src_y += src.mStride;
@@ -449,6 +483,15 @@
return OK;
}
+status_t ColorConverter::convertYUV420Planar16(
+ const BitmapParams &src, const BitmapParams &dst) {
+ if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
+ return convertYUV420Planar16ToY410(src, dst);
+ }
+
+ return convertYUV420Planar(src, dst);
+}
+
/*
* Pack 10-bit YUV into RGBA_1010102.
*
@@ -480,7 +523,7 @@
#if !USE_NEON_Y410
-status_t ColorConverter::convertYUV420Planar16(
+status_t ColorConverter::convertYUV420Planar16ToY410(
const BitmapParams &src, const BitmapParams &dst) {
uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -554,7 +597,7 @@
#else
-status_t ColorConverter::convertYUV420Planar16(
+status_t ColorConverter::convertYUV420Planar16ToY410(
const BitmapParams &src, const BitmapParams &dst) {
uint8_t *out = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 838bc5f..657a05b 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -79,13 +79,26 @@
cropBottomNew = heightNew - 1;
}
+ // The native window buffer format for high-bitdepth content could
+ // depend on the dataspace also.
+ android_dataspace dataSpace;
+ bool dataSpaceChangedForPlanar16 = false;
+ if (colorFormatNew == OMX_COLOR_FormatYUV420Planar16
+ && format->findInt32("android._dataspace", (int32_t *)&dataSpace)
+ && dataSpace != mDataSpace) {
+ // Do not modify mDataSpace here, it's only modified at last
+ // when we do native_window_set_buffers_data_space().
+ dataSpaceChangedForPlanar16 = true;
+ }
+
if (static_cast<int32_t>(mColorFormat) == colorFormatNew &&
mWidth == widthNew &&
mHeight == heightNew &&
mCropLeft == cropLeftNew &&
mCropTop == cropTopNew &&
mCropRight == cropRightNew &&
- mCropBottom == cropBottomNew) {
+ mCropBottom == cropBottomNew &&
+ !dataSpaceChangedForPlanar16) {
// Nothing changed, no need to reset renderer.
return;
}
@@ -135,11 +148,16 @@
}
case OMX_COLOR_FormatYUV420Planar16:
{
- // Here we would convert OMX_COLOR_FormatYUV420Planar16 into
- // OMX_COLOR_FormatYUV444Y410, and put it inside a buffer with
- // format HAL_PIXEL_FORMAT_RGBA_1010102. Surfaceflinger will
- // use render engine to convert it to RGB if needed.
- halFormat = HAL_PIXEL_FORMAT_RGBA_1010102;
+ if (((dataSpace & HAL_DATASPACE_STANDARD_MASK) == HAL_DATASPACE_STANDARD_BT2020)
+ && ((dataSpace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_ST2084)) {
+ // Here we would convert OMX_COLOR_FormatYUV420Planar16 into
+ // OMX_COLOR_FormatYUV444Y410, and put it inside a buffer with
+ // format HAL_PIXEL_FORMAT_RGBA_1010102. Surfaceflinger will
+ // use render engine to convert it to RGB if needed.
+ halFormat = HAL_PIXEL_FORMAT_RGBA_1010102;
+ } else {
+ halFormat = HAL_PIXEL_FORMAT_YV12;
+ }
bufWidth = (mCropWidth + 1) & ~1;
bufHeight = (mCropHeight + 1) & ~1;
break;
@@ -155,7 +173,7 @@
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_Format16bitRGB565);
CHECK(mConverter->isValid());
- } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
+ } else if (halFormat == HAL_PIXEL_FORMAT_RGBA_1010102) {
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_FormatYUV444Y410);
CHECK(mConverter->isValid());
@@ -300,6 +318,46 @@
dst_u += dst_c_stride;
dst_v += dst_c_stride;
}
+ } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
+ const uint16_t *src_y = (const uint16_t *)data;
+ const uint16_t *src_u = (const uint16_t *)data + mWidth * mHeight;
+ const uint16_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
+
+ src_y += mCropLeft + mCropTop * mWidth;
+ src_u += (mCropLeft + mCropTop * mWidth / 2) / 2;
+ src_v += (mCropLeft + mCropTop * mWidth / 2) / 2;
+
+ uint8_t *dst_y = (uint8_t *)dst;
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ dst_y += mCropTop * buf->stride + mCropLeft;
+ dst_v += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
+ dst_u += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
+
+ for (int y = 0; y < mCropHeight; ++y) {
+ for (int x = 0; x < mCropWidth; ++x) {
+ dst_y[x] = (uint8_t)(src_y[x] >> 2);
+ }
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ for (int x = 0; x < (mCropWidth + 1) / 2; ++x) {
+ dst_u[x] = (uint8_t)(src_u[x] >> 2);
+ dst_v[x] = (uint8_t)(src_v[x] >> 2);
+ }
+
+ src_u += mWidth / 2;
+ src_v += mWidth / 2;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
} else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
const uint8_t *src_y = (const uint8_t *)data;
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 3b84018..738f066 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -944,6 +944,40 @@
return mItems[index].mName;
}
+AMessage::ItemData AMessage::getEntryAt(size_t index) const {
+ ItemData it;
+ if (index < mNumItems) {
+ switch (mItems[index].mType) {
+ case kTypeInt32: it.set(mItems[index].u.int32Value); break;
+ case kTypeInt64: it.set(mItems[index].u.int64Value); break;
+ case kTypeSize: it.set(mItems[index].u.sizeValue); break;
+ case kTypeFloat: it.set(mItems[index].u.floatValue); break;
+ case kTypeDouble: it.set(mItems[index].u.doubleValue); break;
+ case kTypePointer: it.set(mItems[index].u.ptrValue); break;
+ case kTypeRect: it.set(mItems[index].u.rectValue); break;
+ case kTypeString: it.set(*mItems[index].u.stringValue); break;
+ case kTypeObject: {
+ sp<RefBase> obj = mItems[index].u.refValue;
+ it.set(obj);
+ break;
+ }
+ case kTypeMessage: {
+ sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
+ it.set(msg);
+ break;
+ }
+ case kTypeBuffer: {
+ sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
+ it.set(buf);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return it;
+}
+
status_t AMessage::setEntryNameAt(size_t index, const char *name) {
if (index >= mNumItems) {
return BAD_INDEX;
@@ -964,6 +998,60 @@
return OK;
}
+status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
+ AString stringValue;
+ sp<RefBase> refValue;
+ sp<AMessage> msgValue;
+ sp<ABuffer> bufValue;
+
+ if (index >= mNumItems) {
+ return BAD_INDEX;
+ }
+ if (!item.used()) {
+ return BAD_VALUE;
+ }
+ Item *dst = &mItems[index];
+ freeItemValue(dst);
+
+ // some values can be directly set with the getter. others need items to be allocated
+ if (item.find(&dst->u.int32Value)) {
+ dst->mType = kTypeInt32;
+ } else if (item.find(&dst->u.int64Value)) {
+ dst->mType = kTypeInt64;
+ } else if (item.find(&dst->u.sizeValue)) {
+ dst->mType = kTypeSize;
+ } else if (item.find(&dst->u.floatValue)) {
+ dst->mType = kTypeFloat;
+ } else if (item.find(&dst->u.doubleValue)) {
+ dst->mType = kTypeDouble;
+ } else if (item.find(&dst->u.ptrValue)) {
+ dst->mType = kTypePointer;
+ } else if (item.find(&dst->u.rectValue)) {
+ dst->mType = kTypeRect;
+ } else if (item.find(&stringValue)) {
+ dst->u.stringValue = new AString(stringValue);
+ dst->mType = kTypeString;
+ } else if (item.find(&refValue)) {
+ if (refValue != NULL) { refValue->incStrong(this); }
+ dst->u.refValue = refValue.get();
+ dst->mType = kTypeObject;
+ } else if (item.find(&msgValue)) {
+ if (msgValue != NULL) { msgValue->incStrong(this); }
+ dst->u.refValue = msgValue.get();
+ dst->mType = kTypeMessage;
+ } else if (item.find(&bufValue)) {
+ if (bufValue != NULL) { bufValue->incStrong(this); }
+ dst->u.refValue = bufValue.get();
+ dst->mType = kTypeBuffer;
+ } else {
+ // unsupported item - we should not be here.
+ dst->mType = kTypeInt32;
+ dst->u.int32Value = 0xDEADDEAD;
+ return BAD_TYPE;
+ }
+ return OK;
+}
+
status_t AMessage::removeEntryAt(size_t index) {
if (index >= mNumItems) {
return BAD_INDEX;
@@ -983,6 +1071,34 @@
return OK;
}
+void AMessage::setItem(const char *name, const ItemData &item) {
+ if (item.used()) {
+ Item *it = allocateItem(name);
+ if (it != nullptr) {
+ setEntryAt(it - mItems, item);
+ }
+ }
+}
+
+AMessage::ItemData AMessage::findItem(const char *name) const {
+ return getEntryAt(findEntryByName(name));
+}
+
+void AMessage::extend(const sp<AMessage> &other) {
+ // ignore null messages
+ if (other == nullptr) {
+ return;
+ }
+
+ for (size_t ix = 0; ix < other->mNumItems; ++ix) {
+ Item *it = allocateItem(other->mItems[ix].mName);
+ if (it != nullptr) {
+ ItemData data = other->getEntryAt(ix);
+ setEntryAt(it - mItems, data);
+ }
+ }
+}
+
size_t AMessage::findEntryByName(const char *name) const {
return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
}
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
index 49aa0dc..5acc6d6 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
@@ -25,6 +25,9 @@
#include <media/stagefright/foundation/TypeTraits.h>
#include <media/stagefright/foundation/Flagged.h>
+#undef HIDE
+#define HIDE __attribute__((visibility("hidden")))
+
namespace android {
/**
@@ -78,7 +81,7 @@
* This class is needed as member function specialization is not allowed for a
* templated class.
*/
-struct _AUnion_impl {
+struct HIDE _AUnion_impl {
/**
* Calls placement constuctor for type T with arbitrary arguments for a storage at an address.
* Storage MUST be large enough to contain T.
@@ -113,13 +116,13 @@
/** Constructor specialization for void type */
template<>
-inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
+HIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
memset(addr, 0, totalSize);
}
/** Destructor specialization for void type */
template<>
-inline void _AUnion_impl::del<void>(void *) {
+HIDE inline void _AUnion_impl::del<void>(void *) {
}
/// \endcond
@@ -221,7 +224,7 @@
template<
typename T,
bool=std::is_copy_assignable<T>::value>
-struct _AData_copier {
+struct HIDE _AData_copier {
static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here");
/**
@@ -294,7 +297,7 @@
*
*/
template<typename T>
-struct _AData_copier<T, false> {
+struct HIDE _AData_copier<T, false> {
static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here");
static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here");
@@ -318,7 +321,7 @@
template<
typename T,
bool=std::is_move_assignable<T>::value>
-struct _AData_mover {
+struct HIDE _AData_mover {
static_assert(std::is_move_assignable<T>::value, "T must be move assignable here");
/**
@@ -389,7 +392,7 @@
*
*/
template<typename T>
-struct _AData_mover<T, false> {
+struct HIDE _AData_mover<T, false> {
static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here");
static_assert(std::is_move_constructible<T>::value, "T must be move constructible here");
@@ -407,13 +410,13 @@
* \param Ts types to consider for the member
*/
template<typename Flagger, typename U, typename ...Ts>
-struct _AData_deleter;
+struct HIDE _AData_deleter;
/**
* Template specialization when there are still types to consider (T and rest)
*/
template<typename Flagger, typename U, typename T, typename ...Ts>
-struct _AData_deleter<Flagger, U, T, Ts...> {
+struct HIDE _AData_deleter<Flagger, U, T, Ts...> {
static bool del(typename Flagger::type flags, U &data) {
if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
data.template del<T>();
@@ -427,7 +430,7 @@
* Template specialization when there are no more types to consider.
*/
template<typename Flagger, typename U>
-struct _AData_deleter<Flagger, U> {
+struct HIDE _AData_deleter<Flagger, U> {
inline static bool del(typename Flagger::type, U &) {
return false;
}
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index d90a0de..742651e 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -19,6 +19,7 @@
#define A_MESSAGE_H_
#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AData.h>
#include <media/stagefright/foundation/ALooper.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -155,6 +156,9 @@
// their refcount incremented.
sp<AMessage> dup() const;
+ // Adds all items from other into this.
+ void extend(const sp<AMessage> &other);
+
// Performs a shallow or deep comparison of |this| and |other| and returns
// an AMessage with the differences.
// Warning: RefBase items, i.e. "objects" are _not_ copied but only have
@@ -180,10 +184,39 @@
kTypeBuffer,
};
+ struct Rect {
+ int32_t mLeft, mTop, mRight, mBottom;
+ };
+
size_t countEntries() const;
const char *getEntryNameAt(size_t index, Type *type) const;
/**
+ * Retrieves the item at a specific index.
+ */
+ typedef AData<
+ int32_t, int64_t, size_t, float, double, Rect, AString,
+ void *, sp<AMessage>, sp<ABuffer>, sp<RefBase>>::Basic ItemData;
+
+ /**
+ * Finds an item by name. This can be used if the type is unknown.
+ *
+ * \param name name of the item
+ * Returns an empty item if no item is present with that name.
+ */
+ ItemData findItem(const char *name) const;
+
+ /**
+ * Sets an item of arbitrary type. Does nothing if the item value is empty.
+ *
+ * \param name name of the item
+ * \param item value of the item
+ */
+ void setItem(const char *name, const ItemData &item);
+
+ ItemData getEntryAt(size_t index) const;
+
+ /**
* Finds an entry by name and returns its index.
*
* \retval countEntries() if the entry is not found.
@@ -204,6 +237,19 @@
status_t setEntryNameAt(size_t index, const char *name);
/**
+ * Sets the item of an entry based on index.
+ *
+ * \param index index of the entry
+ * \param item new item of the entry
+ *
+ * \retval OK the item was set successfully
+ * \retval BAD_INDEX invalid index
+ * \retval BAD_VALUE item is invalid (null)
+ * \retval BAD_TYPE type is unsupported (should not happen)
+ */
+ status_t setEntryAt(size_t index, const ItemData &item);
+
+ /**
* Removes an entry based on index.
*
* \param index index of the entry
@@ -227,10 +273,6 @@
wp<AHandler> mHandler;
wp<ALooper> mLooper;
- struct Rect {
- int32_t mLeft, mTop, mRight, mBottom;
- };
-
struct Item {
union {
int32_t int32Value;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h b/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
index 1250e9b..2041b22 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
@@ -19,6 +19,9 @@
#include <type_traits>
+#undef HIDE
+#define HIDE __attribute__((visibility("hidden")))
+
namespace android {
/**
@@ -31,7 +34,7 @@
* Type support utility class to check if a type is an integral type or an enum.
*/
template<typename T>
-struct is_integral_or_enum
+struct HIDE is_integral_or_enum
: std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value> { };
/**
@@ -46,7 +49,7 @@
typename U=typename std::enable_if<is_integral_or_enum<T>::value>::type,
bool=std::is_enum<T>::value,
bool=std::is_integral<T>::value>
-struct underlying_integral_type {
+struct HIDE underlying_integral_type {
static_assert(!std::is_enum<T>::value, "T should not be enum here");
static_assert(!std::is_integral<T>::value, "T should not be integral here");
typedef U type;
@@ -54,7 +57,7 @@
/** Specialization for enums. */
template<typename T, typename U>
-struct underlying_integral_type<T, U, true, false> {
+struct HIDE underlying_integral_type<T, U, true, false> {
static_assert(std::is_enum<T>::value, "T should be enum here");
static_assert(!std::is_integral<T>::value, "T should not be integral here");
typedef typename std::underlying_type<T>::type type;
@@ -62,7 +65,7 @@
/** Specialization for non-enum std-integral types. */
template<typename T, typename U>
-struct underlying_integral_type<T, U, false, true> {
+struct HIDE underlying_integral_type<T, U, false, true> {
static_assert(!std::is_enum<T>::value, "T should not be enum here");
static_assert(std::is_integral<T>::value, "T should be integral here");
typedef T type;
@@ -72,7 +75,7 @@
* Type support utility class to check if the underlying integral type is signed.
*/
template<typename T>
-struct is_signed_integral
+struct HIDE is_signed_integral
: std::integral_constant<bool, std::is_signed<
typename underlying_integral_type<T, unsigned>::type>::value> { };
@@ -80,7 +83,7 @@
* Type support utility class to check if the underlying integral type is unsigned.
*/
template<typename T>
-struct is_unsigned_integral
+struct HIDE is_unsigned_integral
: std::integral_constant<bool, std::is_unsigned<
typename underlying_integral_type<T, signed>::type>::value> {
};
@@ -92,26 +95,26 @@
* member constant |value| equal to true. Otherwise value is false.
*/
template<typename T, typename ...Us>
-struct is_one_of;
+struct HIDE is_one_of;
/// \if 0
/**
* Template specialization when first type matches the searched type.
*/
template<typename T, typename ...Us>
-struct is_one_of<T, T, Us...> : std::true_type {};
+struct HIDE is_one_of<T, T, Us...> : std::true_type {};
/**
* Template specialization when first type does not match the searched type.
*/
template<typename T, typename U, typename ...Us>
-struct is_one_of<T, U, Us...> : is_one_of<T, Us...> {};
+struct HIDE is_one_of<T, U, Us...> : is_one_of<T, Us...> {};
/**
* Template specialization when there are no types to search.
*/
template<typename T>
-struct is_one_of<T> : std::false_type {};
+struct HIDE is_one_of<T> : std::false_type {};
/// \endif
/**
@@ -121,44 +124,44 @@
* Otherwise value is false.
*/
template<typename ...Us>
-struct are_unique;
+struct HIDE are_unique;
/// \if 0
/**
* Template specialization when there are no types.
*/
template<>
-struct are_unique<> : std::true_type {};
+struct HIDE are_unique<> : std::true_type {};
/**
* Template specialization when there is at least one type to check.
*/
template<typename T, typename ...Us>
-struct are_unique<T, Us...>
+struct HIDE are_unique<T, Us...>
: std::integral_constant<bool, are_unique<Us...>::value && !is_one_of<T, Us...>::value> {};
/// \endif
/// \if 0
template<size_t Base, typename T, typename ...Us>
-struct _find_first_impl;
+struct HIDE _find_first_impl;
/**
* Template specialization when there are no types to search.
*/
template<size_t Base, typename T>
-struct _find_first_impl<Base, T> : std::integral_constant<size_t, 0> {};
+struct HIDE _find_first_impl<Base, T> : std::integral_constant<size_t, 0> {};
/**
* Template specialization when T is the first type in Us.
*/
template<size_t Base, typename T, typename ...Us>
-struct _find_first_impl<Base, T, T, Us...> : std::integral_constant<size_t, Base> {};
+struct HIDE _find_first_impl<Base, T, T, Us...> : std::integral_constant<size_t, Base> {};
/**
* Template specialization when T is not the first type in Us.
*/
template<size_t Base, typename T, typename U, typename ...Us>
-struct _find_first_impl<Base, T, U, Us...>
+struct HIDE _find_first_impl<Base, T, U, Us...>
: std::integral_constant<size_t, _find_first_impl<Base + 1, T, Us...>::value> {};
/// \endif
@@ -169,7 +172,7 @@
* If T occurs in Us, index is the 1-based left-most index of T in Us. Otherwise, index is 0.
*/
template<typename T, typename ...Us>
-struct find_first {
+struct HIDE find_first {
static constexpr size_t index = _find_first_impl<1, T, Us...>::value;
};
@@ -180,13 +183,13 @@
* Adds a base index.
*/
template<size_t Base, typename T, typename ...Us>
-struct _find_first_convertible_to_helper;
+struct HIDE _find_first_convertible_to_helper;
/**
* Template specialization for when there are more types to consider
*/
template<size_t Base, typename T, typename U, typename ...Us>
-struct _find_first_convertible_to_helper<Base, T, U, Us...> {
+struct HIDE _find_first_convertible_to_helper<Base, T, U, Us...> {
static constexpr size_t index =
std::is_convertible<T, U>::value ? Base :
_find_first_convertible_to_helper<Base + 1, T, Us...>::index;
@@ -199,7 +202,7 @@
* Template specialization for when there are no more types to consider
*/
template<size_t Base, typename T>
-struct _find_first_convertible_to_helper<Base, T> {
+struct HIDE _find_first_convertible_to_helper<Base, T> {
static constexpr size_t index = 0;
typedef void type;
};
@@ -216,7 +219,7 @@
* \param Us types into which the conversion is considered
*/
template<typename T, typename ...Us>
-struct find_first_convertible_to : public _find_first_convertible_to_helper<1, T, Us...> { };
+struct HIDE find_first_convertible_to : public _find_first_convertible_to_helper<1, T, Us...> { };
} // namespace android
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index f4bba59..f615500 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -329,12 +329,25 @@
}
void ID3::removeUnsynchronization() {
- for (size_t i = 0; i + 1 < mSize; ++i) {
- if (mData[i] == 0xff && mData[i + 1] == 0x00) {
- memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
- --mSize;
+
+ // This file has "unsynchronization", so we have to replace occurrences
+ // of 0xff 0x00 with just 0xff in order to get the real data.
+
+ size_t writeOffset = 1;
+ for (size_t readOffset = 1; readOffset < mSize; ++readOffset) {
+ if (mData[readOffset - 1] == 0xff && mData[readOffset] == 0x00) {
+ continue;
}
+ // Only move data if there's actually something to move.
+ // This handles the special case of the data being only [0xff, 0x00]
+ // which should be converted to just 0xff if unsynchronization is on.
+ mData[writeOffset++] = mData[readOffset];
}
+
+ if (writeOffset < mSize) {
+ mSize = writeOffset;
+ }
+
}
static void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index a6c8981..5b3543d 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -75,10 +75,16 @@
status_t convertYUV420Planar(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertYUV420PlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst);
+
status_t convertYUV420Planar16(
const BitmapParams &src, const BitmapParams &dst);
- status_t convertYUV420PlanarUseLibYUV(
+ status_t convertYUV420Planar16ToY410(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertYUV420Planar16ToRGB(
const BitmapParams &src, const BitmapParams &dst);
status_t convertQCOMYUV420SemiPlanar(
@@ -90,10 +96,6 @@
status_t convertTIYUV420PackedSemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
- void writeToDst(void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
- signed r1, signed g1, signed b1,
- signed r2, signed g2, signed b2);
-
ColorConverter(const ColorConverter &);
ColorConverter &operator=(const ColorConverter &);
};
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
new file mode 100644
index 0000000..3ef4c0e
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef MEDIA_CODEC_CONSTANTS_H_
+#define MEDIA_CODEC_CONSTANTS_H_
+
+namespace {
+
+// from MediaCodecInfo.java
+constexpr int32_t AVCProfileBaseline = 0x01;
+constexpr int32_t AVCProfileMain = 0x02;
+constexpr int32_t AVCProfileExtended = 0x04;
+constexpr int32_t AVCProfileHigh = 0x08;
+constexpr int32_t AVCProfileHigh10 = 0x10;
+constexpr int32_t AVCProfileHigh422 = 0x20;
+constexpr int32_t AVCProfileHigh444 = 0x40;
+constexpr int32_t AVCProfileConstrainedBaseline = 0x10000;
+constexpr int32_t AVCProfileConstrainedHigh = 0x80000;
+
+constexpr int32_t AVCLevel1 = 0x01;
+constexpr int32_t AVCLevel1b = 0x02;
+constexpr int32_t AVCLevel11 = 0x04;
+constexpr int32_t AVCLevel12 = 0x08;
+constexpr int32_t AVCLevel13 = 0x10;
+constexpr int32_t AVCLevel2 = 0x20;
+constexpr int32_t AVCLevel21 = 0x40;
+constexpr int32_t AVCLevel22 = 0x80;
+constexpr int32_t AVCLevel3 = 0x100;
+constexpr int32_t AVCLevel31 = 0x200;
+constexpr int32_t AVCLevel32 = 0x400;
+constexpr int32_t AVCLevel4 = 0x800;
+constexpr int32_t AVCLevel41 = 0x1000;
+constexpr int32_t AVCLevel42 = 0x2000;
+constexpr int32_t AVCLevel5 = 0x4000;
+constexpr int32_t AVCLevel51 = 0x8000;
+constexpr int32_t AVCLevel52 = 0x10000;
+
+constexpr int32_t H263ProfileBaseline = 0x01;
+constexpr int32_t H263ProfileH320Coding = 0x02;
+constexpr int32_t H263ProfileBackwardCompatible = 0x04;
+constexpr int32_t H263ProfileISWV2 = 0x08;
+constexpr int32_t H263ProfileISWV3 = 0x10;
+constexpr int32_t H263ProfileHighCompression = 0x20;
+constexpr int32_t H263ProfileInternet = 0x40;
+constexpr int32_t H263ProfileInterlace = 0x80;
+constexpr int32_t H263ProfileHighLatency = 0x100;
+
+constexpr int32_t H263Level10 = 0x01;
+constexpr int32_t H263Level20 = 0x02;
+constexpr int32_t H263Level30 = 0x04;
+constexpr int32_t H263Level40 = 0x08;
+constexpr int32_t H263Level45 = 0x10;
+constexpr int32_t H263Level50 = 0x20;
+constexpr int32_t H263Level60 = 0x40;
+constexpr int32_t H263Level70 = 0x80;
+
+constexpr int32_t MPEG4ProfileSimple = 0x01;
+constexpr int32_t MPEG4ProfileSimpleScalable = 0x02;
+constexpr int32_t MPEG4ProfileCore = 0x04;
+constexpr int32_t MPEG4ProfileMain = 0x08;
+constexpr int32_t MPEG4ProfileNbit = 0x10;
+constexpr int32_t MPEG4ProfileScalableTexture = 0x20;
+constexpr int32_t MPEG4ProfileSimpleFace = 0x40;
+constexpr int32_t MPEG4ProfileSimpleFBA = 0x80;
+constexpr int32_t MPEG4ProfileBasicAnimated = 0x100;
+constexpr int32_t MPEG4ProfileHybrid = 0x200;
+constexpr int32_t MPEG4ProfileAdvancedRealTime = 0x400;
+constexpr int32_t MPEG4ProfileCoreScalable = 0x800;
+constexpr int32_t MPEG4ProfileAdvancedCoding = 0x1000;
+constexpr int32_t MPEG4ProfileAdvancedCore = 0x2000;
+constexpr int32_t MPEG4ProfileAdvancedScalable = 0x4000;
+constexpr int32_t MPEG4ProfileAdvancedSimple = 0x8000;
+
+constexpr int32_t MPEG4Level0 = 0x01;
+constexpr int32_t MPEG4Level0b = 0x02;
+constexpr int32_t MPEG4Level1 = 0x04;
+constexpr int32_t MPEG4Level2 = 0x08;
+constexpr int32_t MPEG4Level3 = 0x10;
+constexpr int32_t MPEG4Level3b = 0x18;
+constexpr int32_t MPEG4Level4 = 0x20;
+constexpr int32_t MPEG4Level4a = 0x40;
+constexpr int32_t MPEG4Level5 = 0x80;
+constexpr int32_t MPEG4Level6 = 0x100;
+
+constexpr int32_t MPEG2ProfileSimple = 0x00;
+constexpr int32_t MPEG2ProfileMain = 0x01;
+constexpr int32_t MPEG2Profile422 = 0x02;
+constexpr int32_t MPEG2ProfileSNR = 0x03;
+constexpr int32_t MPEG2ProfileSpatial = 0x04;
+constexpr int32_t MPEG2ProfileHigh = 0x05;
+
+constexpr int32_t MPEG2LevelLL = 0x00;
+constexpr int32_t MPEG2LevelML = 0x01;
+constexpr int32_t MPEG2LevelH14 = 0x02;
+constexpr int32_t MPEG2LevelHL = 0x03;
+constexpr int32_t MPEG2LevelHP = 0x04;
+
+constexpr int32_t AACObjectMain = 1;
+constexpr int32_t AACObjectLC = 2;
+constexpr int32_t AACObjectSSR = 3;
+constexpr int32_t AACObjectLTP = 4;
+constexpr int32_t AACObjectHE = 5;
+constexpr int32_t AACObjectScalable = 6;
+constexpr int32_t AACObjectERLC = 17;
+constexpr int32_t AACObjectERScalable = 20;
+constexpr int32_t AACObjectLD = 23;
+constexpr int32_t AACObjectHE_PS = 29;
+constexpr int32_t AACObjectELD = 39;
+constexpr int32_t AACObjectXHE = 42;
+
+constexpr int32_t VP8Level_Version0 = 0x01;
+constexpr int32_t VP8Level_Version1 = 0x02;
+constexpr int32_t VP8Level_Version2 = 0x04;
+constexpr int32_t VP8Level_Version3 = 0x08;
+
+constexpr int32_t VP8ProfileMain = 0x01;
+
+constexpr int32_t VP9Profile0 = 0x01;
+constexpr int32_t VP9Profile1 = 0x02;
+constexpr int32_t VP9Profile2 = 0x04;
+constexpr int32_t VP9Profile3 = 0x08;
+constexpr int32_t VP9Profile2HDR = 0x1000;
+constexpr int32_t VP9Profile3HDR = 0x2000;
+
+constexpr int32_t VP9Level1 = 0x1;
+constexpr int32_t VP9Level11 = 0x2;
+constexpr int32_t VP9Level2 = 0x4;
+constexpr int32_t VP9Level21 = 0x8;
+constexpr int32_t VP9Level3 = 0x10;
+constexpr int32_t VP9Level31 = 0x20;
+constexpr int32_t VP9Level4 = 0x40;
+constexpr int32_t VP9Level41 = 0x80;
+constexpr int32_t VP9Level5 = 0x100;
+constexpr int32_t VP9Level51 = 0x200;
+constexpr int32_t VP9Level52 = 0x400;
+constexpr int32_t VP9Level6 = 0x800;
+constexpr int32_t VP9Level61 = 0x1000;
+constexpr int32_t VP9Level62 = 0x2000;
+
+constexpr int32_t HEVCProfileMain = 0x01;
+constexpr int32_t HEVCProfileMain10 = 0x02;
+constexpr int32_t HEVCProfileMainStill = 0x04;
+constexpr int32_t HEVCProfileMain10HDR10 = 0x1000;
+
+constexpr int32_t HEVCMainTierLevel1 = 0x1;
+constexpr int32_t HEVCHighTierLevel1 = 0x2;
+constexpr int32_t HEVCMainTierLevel2 = 0x4;
+constexpr int32_t HEVCHighTierLevel2 = 0x8;
+constexpr int32_t HEVCMainTierLevel21 = 0x10;
+constexpr int32_t HEVCHighTierLevel21 = 0x20;
+constexpr int32_t HEVCMainTierLevel3 = 0x40;
+constexpr int32_t HEVCHighTierLevel3 = 0x80;
+constexpr int32_t HEVCMainTierLevel31 = 0x100;
+constexpr int32_t HEVCHighTierLevel31 = 0x200;
+constexpr int32_t HEVCMainTierLevel4 = 0x400;
+constexpr int32_t HEVCHighTierLevel4 = 0x800;
+constexpr int32_t HEVCMainTierLevel41 = 0x1000;
+constexpr int32_t HEVCHighTierLevel41 = 0x2000;
+constexpr int32_t HEVCMainTierLevel5 = 0x4000;
+constexpr int32_t HEVCHighTierLevel5 = 0x8000;
+constexpr int32_t HEVCMainTierLevel51 = 0x10000;
+constexpr int32_t HEVCHighTierLevel51 = 0x20000;
+constexpr int32_t HEVCMainTierLevel52 = 0x40000;
+constexpr int32_t HEVCHighTierLevel52 = 0x80000;
+constexpr int32_t HEVCMainTierLevel6 = 0x100000;
+constexpr int32_t HEVCHighTierLevel6 = 0x200000;
+constexpr int32_t HEVCMainTierLevel61 = 0x400000;
+constexpr int32_t HEVCHighTierLevel61 = 0x800000;
+constexpr int32_t HEVCMainTierLevel62 = 0x1000000;
+constexpr int32_t HEVCHighTierLevel62 = 0x2000000;
+
+constexpr int32_t DolbyVisionProfileDvavPer = 0x1;
+constexpr int32_t DolbyVisionProfileDvavPen = 0x2;
+constexpr int32_t DolbyVisionProfileDvheDer = 0x4;
+constexpr int32_t DolbyVisionProfileDvheDen = 0x8;
+constexpr int32_t DolbyVisionProfileDvheDtr = 0x10;
+constexpr int32_t DolbyVisionProfileDvheStn = 0x20;
+constexpr int32_t DolbyVisionProfileDvheDth = 0x40;
+constexpr int32_t DolbyVisionProfileDvheDtb = 0x80;
+constexpr int32_t DolbyVisionProfileDvheSt = 0x100;
+constexpr int32_t DolbyVisionProfileDvavSe = 0x200;
+
+constexpr int32_t DolbyVisionLevelHd24 = 0x1;
+constexpr int32_t DolbyVisionLevelHd30 = 0x2;
+constexpr int32_t DolbyVisionLevelFhd24 = 0x4;
+constexpr int32_t DolbyVisionLevelFhd30 = 0x8;
+constexpr int32_t DolbyVisionLevelFhd60 = 0x10;
+constexpr int32_t DolbyVisionLevelUhd24 = 0x20;
+constexpr int32_t DolbyVisionLevelUhd30 = 0x40;
+constexpr int32_t DolbyVisionLevelUhd48 = 0x80;
+constexpr int32_t DolbyVisionLevelUhd60 = 0x100;
+
+constexpr int32_t BITRATE_MODE_CBR = 2;
+constexpr int32_t BITRATE_MODE_CQ = 0;
+constexpr int32_t BITRATE_MODE_VBR = 1;
+
+constexpr int32_t COLOR_Format12bitRGB444 = 3;
+constexpr int32_t COLOR_Format16bitARGB1555 = 5;
+constexpr int32_t COLOR_Format16bitARGB4444 = 4;
+constexpr int32_t COLOR_Format16bitBGR565 = 7;
+constexpr int32_t COLOR_Format16bitRGB565 = 6;
+constexpr int32_t COLOR_Format18bitARGB1665 = 9;
+constexpr int32_t COLOR_Format18BitBGR666 = 41;
+constexpr int32_t COLOR_Format18bitRGB666 = 8;
+constexpr int32_t COLOR_Format19bitARGB1666 = 10;
+constexpr int32_t COLOR_Format24BitABGR6666 = 43;
+constexpr int32_t COLOR_Format24bitARGB1887 = 13;
+constexpr int32_t COLOR_Format24BitARGB6666 = 42;
+constexpr int32_t COLOR_Format24bitBGR888 = 12;
+constexpr int32_t COLOR_Format24bitRGB888 = 11;
+constexpr int32_t COLOR_Format25bitARGB1888 = 14;
+constexpr int32_t COLOR_Format32bitABGR8888 = 0x7F00A000;
+constexpr int32_t COLOR_Format32bitARGB8888 = 16;
+constexpr int32_t COLOR_Format32bitBGRA8888 = 15;
+constexpr int32_t COLOR_Format8bitRGB332 = 2;
+constexpr int32_t COLOR_FormatCbYCrY = 27;
+constexpr int32_t COLOR_FormatCrYCbY = 28;
+constexpr int32_t COLOR_FormatL16 = 36;
+constexpr int32_t COLOR_FormatL2 = 33;
+constexpr int32_t COLOR_FormatL24 = 37;
+constexpr int32_t COLOR_FormatL32 = 38;
+constexpr int32_t COLOR_FormatL4 = 34;
+constexpr int32_t COLOR_FormatL8 = 35;
+constexpr int32_t COLOR_FormatMonochrome = 1;
+constexpr int32_t COLOR_FormatRawBayer10bit = 31;
+constexpr int32_t COLOR_FormatRawBayer8bit = 30;
+constexpr int32_t COLOR_FormatRawBayer8bitcompressed = 32;
+constexpr int32_t COLOR_FormatRGBAFlexible = 0x7F36A888;
+constexpr int32_t COLOR_FormatRGBFlexible = 0x7F36B888;
+constexpr int32_t COLOR_FormatSurface = 0x7F000789;
+constexpr int32_t COLOR_FormatYCbYCr = 25;
+constexpr int32_t COLOR_FormatYCrYCb = 26;
+constexpr int32_t COLOR_FormatYUV411PackedPlanar = 18;
+constexpr int32_t COLOR_FormatYUV411Planar = 17;
+constexpr int32_t COLOR_FormatYUV420Flexible = 0x7F420888;
+constexpr int32_t COLOR_FormatYUV420PackedPlanar = 20;
+constexpr int32_t COLOR_FormatYUV420PackedSemiPlanar = 39;
+constexpr int32_t COLOR_FormatYUV420Planar = 19;
+constexpr int32_t COLOR_FormatYUV420SemiPlanar = 21;
+constexpr int32_t COLOR_FormatYUV422Flexible = 0x7F422888;
+constexpr int32_t COLOR_FormatYUV422PackedPlanar = 23;
+constexpr int32_t COLOR_FormatYUV422PackedSemiPlanar = 40;
+constexpr int32_t COLOR_FormatYUV422Planar = 22;
+constexpr int32_t COLOR_FormatYUV422SemiPlanar = 24;
+constexpr int32_t COLOR_FormatYUV444Flexible = 0x7F444888;
+constexpr int32_t COLOR_FormatYUV444Interleaved = 29;
+constexpr int32_t COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00;
+constexpr int32_t COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
+
+constexpr char FEATURE_AdaptivePlayback[] = "adaptive-playback";
+constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
+constexpr char FEATURE_PartialFrame[] = "partial-frame";
+constexpr char FEATURE_SecurePlayback[] = "secure-playback";
+constexpr char FEATURE_TunneledPlayback[] = "tunneled-playback";
+
+// from MediaFormat.java
+constexpr char MIMETYPE_VIDEO_VP8[] = "video/x-vnd.on2.vp8";
+constexpr char MIMETYPE_VIDEO_VP9[] = "video/x-vnd.on2.vp9";
+constexpr char MIMETYPE_VIDEO_AVC[] = "video/avc";
+constexpr char MIMETYPE_VIDEO_HEVC[] = "video/hevc";
+constexpr char MIMETYPE_VIDEO_MPEG4[] = "video/mp4v-es";
+constexpr char MIMETYPE_VIDEO_H263[] = "video/3gpp";
+constexpr char MIMETYPE_VIDEO_MPEG2[] = "video/mpeg2";
+constexpr char MIMETYPE_VIDEO_RAW[] = "video/raw";
+constexpr char MIMETYPE_VIDEO_DOLBY_VISION[] = "video/dolby-vision";
+constexpr char MIMETYPE_VIDEO_SCRAMBLED[] = "video/scrambled";
+
+constexpr char MIMETYPE_AUDIO_AMR_NB[] = "audio/3gpp";
+constexpr char MIMETYPE_AUDIO_AMR_WB[] = "audio/amr-wb";
+constexpr char MIMETYPE_AUDIO_MPEG[] = "audio/mpeg";
+constexpr char MIMETYPE_AUDIO_AAC[] = "audio/mp4a-latm";
+constexpr char MIMETYPE_AUDIO_QCELP[] = "audio/qcelp";
+constexpr char MIMETYPE_AUDIO_VORBIS[] = "audio/vorbis";
+constexpr char MIMETYPE_AUDIO_OPUS[] = "audio/opus";
+constexpr char MIMETYPE_AUDIO_G711_ALAW[] = "audio/g711-alaw";
+constexpr char MIMETYPE_AUDIO_G711_MLAW[] = "audio/g711-mlaw";
+constexpr char MIMETYPE_AUDIO_RAW[] = "audio/raw";
+constexpr char MIMETYPE_AUDIO_FLAC[] = "audio/flac";
+constexpr char MIMETYPE_AUDIO_MSGSM[] = "audio/gsm";
+constexpr char MIMETYPE_AUDIO_AC3[] = "audio/ac3";
+constexpr char MIMETYPE_AUDIO_EAC3[] = "audio/eac3";
+constexpr char MIMETYPE_AUDIO_SCRAMBLED[] = "audio/scrambled";
+
+constexpr char MIMETYPE_IMAGE_ANDROID_HEIC[] = "image/vnd.android.heic";
+
+constexpr char MIMETYPE_TEXT_CEA_608[] = "text/cea-608";
+constexpr char MIMETYPE_TEXT_CEA_708[] = "text/cea-708";
+constexpr char MIMETYPE_TEXT_SUBRIP[] = "application/x-subrip";
+constexpr char MIMETYPE_TEXT_VTT[] = "text/vtt";
+
+constexpr int32_t COLOR_RANGE_FULL = 1;
+constexpr int32_t COLOR_RANGE_LIMITED = 2;
+constexpr int32_t COLOR_STANDARD_BT2020 = 6;
+constexpr int32_t COLOR_STANDARD_BT601_NTSC = 4;
+constexpr int32_t COLOR_STANDARD_BT601_PAL = 2;
+constexpr int32_t COLOR_STANDARD_BT709 = 1;
+constexpr int32_t COLOR_TRANSFER_HLG = 7;
+constexpr int32_t COLOR_TRANSFER_LINEAR = 1;
+constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
+constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
+
+constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
+constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
+constexpr char KEY_AAC_DRC_EFFECT_TYPE[] = "aac-drc-effect-type";
+constexpr char KEY_AAC_DRC_HEAVY_COMPRESSION[] = "aac-drc-heavy-compression";
+constexpr char KEY_AAC_DRC_TARGET_REFERENCE_LEVEL[] = "aac-target-ref-level";
+constexpr char KEY_AAC_ENCODED_TARGET_LEVEL[] = "aac-encoded-target-level";
+constexpr char KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT[] = "aac-max-output-channel_count";
+constexpr char KEY_AAC_PROFILE[] = "aac-profile";
+constexpr char KEY_AAC_SBR_MODE[] = "aac-sbr-mode";
+constexpr char KEY_AUDIO_SESSION_ID[] = "audio-session-id";
+constexpr char KEY_BIT_RATE[] = "bitrate";
+constexpr char KEY_BITRATE_MODE[] = "bitrate-mode";
+constexpr char KEY_CA_SESSION_ID[] = "ca-session-id";
+constexpr char KEY_CA_SYSTEM_ID[] = "ca-system-id";
+constexpr char KEY_CAPTURE_RATE[] = "capture-rate";
+constexpr char KEY_CHANNEL_COUNT[] = "channel-count";
+constexpr char KEY_CHANNEL_MASK[] = "channel-mask";
+constexpr char KEY_COLOR_FORMAT[] = "color-format";
+constexpr char KEY_COLOR_RANGE[] = "color-range";
+constexpr char KEY_COLOR_STANDARD[] = "color-standard";
+constexpr char KEY_COLOR_TRANSFER[] = "color-transfer";
+constexpr char KEY_COMPLEXITY[] = "complexity";
+constexpr char KEY_DURATION[] = "durationUs";
+constexpr char KEY_FEATURE_[] = "feature-";
+constexpr char KEY_FLAC_COMPRESSION_LEVEL[] = "flac-compression-level";
+constexpr char KEY_FRAME_RATE[] = "frame-rate";
+constexpr char KEY_GRID_COLUMNS[] = "grid-cols";
+constexpr char KEY_GRID_ROWS[] = "grid-rows";
+constexpr char KEY_HDR_STATIC_INFO[] = "hdr-static-info";
+constexpr char KEY_HEIGHT[] = "height";
+constexpr char KEY_I_FRAME_INTERVAL[] = "i-frame-interval";
+constexpr char KEY_INTRA_REFRESH_PERIOD[] = "intra-refresh-period";
+constexpr char KEY_IS_ADTS[] = "is-adts";
+constexpr char KEY_IS_AUTOSELECT[] = "is-autoselect";
+constexpr char KEY_IS_DEFAULT[] = "is-default";
+constexpr char KEY_IS_FORCED_SUBTITLE[] = "is-forced-subtitle";
+constexpr char KEY_IS_TIMED_TEXT[] = "is-timed-text";
+constexpr char KEY_LANGUAGE[] = "language";
+constexpr char KEY_LATENCY[] = "latency";
+constexpr char KEY_LEVEL[] = "level";
+constexpr char KEY_MAX_BIT_RATE[] = "max-bitrate";
+constexpr char KEY_MAX_HEIGHT[] = "max-height";
+constexpr char KEY_MAX_INPUT_SIZE[] = "max-input-size";
+constexpr char KEY_MAX_WIDTH[] = "max-width";
+constexpr char KEY_MIME[] = "mime";
+constexpr char KEY_OPERATING_RATE[] = "operating-rate";
+constexpr char KEY_OUTPUT_REORDER_DEPTH[] = "output-reorder-depth";
+constexpr char KEY_PCM_ENCODING[] = "pcm-encoding";
+constexpr char KEY_PRIORITY[] = "priority";
+constexpr char KEY_PROFILE[] = "profile";
+constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
+constexpr char KEY_QUALITY[] = "quality";
+constexpr char KEY_REPEAT_PREVIOUS_FRAME_AFTER[] = "repeat-previous-frame-after";
+constexpr char KEY_ROTATION[] = "rotation-degrees";
+constexpr char KEY_SAMPLE_RATE[] = "sample-rate";
+constexpr char KEY_SLICE_HEIGHT[] = "slice-height";
+constexpr char KEY_STRIDE[] = "stride";
+constexpr char KEY_TEMPORAL_LAYERING[] = "ts-schema";
+constexpr char KEY_TILE_HEIGHT[] = "tile-height";
+constexpr char KEY_TILE_WIDTH[] = "tile-width";
+constexpr char KEY_TRACK_ID[] = "track-id";
+constexpr char KEY_WIDTH[] = "width";
+
+// from MediaCodec.java
+constexpr int32_t ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+constexpr int32_t ERROR_INSUFFICIENT_RESOURCE = 1100;
+constexpr int32_t ERROR_KEY_EXPIRED = 2;
+constexpr int32_t ERROR_NO_KEY = 1;
+constexpr int32_t ERROR_RECLAIMED = 1101;
+constexpr int32_t ERROR_RESOURCE_BUSY = 3;
+constexpr int32_t ERROR_SESSION_NOT_OPENED = 5;
+constexpr int32_t ERROR_UNSUPPORTED_OPERATION = 6;
+constexpr char CODEC[] = "android.media.mediacodec.codec";
+constexpr char ENCODER[] = "android.media.mediacodec.encoder";
+constexpr char HEIGHT[] = "android.media.mediacodec.height";
+constexpr char MIME_TYPE[] = "android.media.mediacodec.mime";
+constexpr char MODE[] = "android.media.mediacodec.mode";
+constexpr char MODE_AUDIO[] = "audio";
+constexpr char MODE_VIDEO[] = "video";
+constexpr char ROTATION[] = "android.media.mediacodec.rotation";
+constexpr char SECURE[] = "android.media.mediacodec.secure";
+constexpr char WIDTH[] = "android.media.mediacodec.width";
+
+constexpr int32_t BUFFER_FLAG_CODEC_CONFIG = 2;
+constexpr int32_t BUFFER_FLAG_END_OF_STREAM = 4;
+constexpr int32_t BUFFER_FLAG_KEY_FRAME = 1;
+constexpr int32_t BUFFER_FLAG_PARTIAL_FRAME = 8;
+constexpr int32_t BUFFER_FLAG_SYNC_FRAME = 1;
+constexpr int32_t CONFIGURE_FLAG_ENCODE = 1;
+constexpr int32_t CRYPTO_MODE_AES_CBC = 2;
+constexpr int32_t CRYPTO_MODE_AES_CTR = 1;
+constexpr int32_t CRYPTO_MODE_UNENCRYPTED = 0;
+constexpr int32_t INFO_OUTPUT_BUFFERS_CHANGED = -3;
+constexpr int32_t INFO_OUTPUT_FORMAT_CHANGED = -2;
+constexpr int32_t INFO_TRY_AGAIN_LATER = -1;
+constexpr int32_t VIDEO_SCALING_MODE_SCALE_TO_FIT = 1;
+constexpr int32_t VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2;
+constexpr char PARAMETER_KEY_REQUEST_SYNC_FRAME[] = "request-sync";
+constexpr char PARAMETER_KEY_SUSPEND[] = "drop-input-frames";
+constexpr char PARAMETER_KEY_VIDEO_BITRATE[] = "video-bitrate";
+
+}
+
+#endif // MEDIA_CODEC_CONSTANTS_H_
+
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index ff58eb6..227d33e 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -686,6 +686,7 @@
CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex);
+ status_t err = OK;
switch (mode) {
case IOMX::kPortModeDynamicANWBuffer:
{
@@ -694,17 +695,19 @@
CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
"not setting port mode to %s(%d) on output",
asString(mode), mode);
- return StatusFromOMXError(OMX_ErrorUnsupportedIndex);
+ err = StatusFromOMXError(OMX_ErrorUnsupportedIndex);
+ break;
}
- status_t err = enableNativeBuffers_l(
+ err = enableNativeBuffers_l(
portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
if (err != OK) {
- return err;
+ break;
}
}
(void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
- return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);
+ err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);
+ break;
}
case IOMX::kPortModeDynamicNativeHandle:
@@ -712,13 +715,15 @@
if (portIndex != kPortIndexInput) {
CLOG_ERROR(setPortMode, BAD_VALUE,
"%s(%d) mode is only supported on input port", asString(mode), mode);
- return BAD_VALUE;
+ err = BAD_VALUE;
+ break;
}
(void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
(void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
MetadataBufferType metaType = kMetadataBufferTypeNativeHandleSource;
- return storeMetaDataInBuffers_l(portIndex, OMX_TRUE, &metaType);
+ err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, &metaType);
+ break;
}
case IOMX::kPortModePresetSecureBuffer:
@@ -726,7 +731,8 @@
// Allow on both input and output.
(void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
(void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
- return enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);
+ err = enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);
+ break;
}
case IOMX::kPortModePresetANWBuffer:
@@ -734,7 +740,8 @@
if (portIndex != kPortIndexOutput) {
CLOG_ERROR(setPortMode, BAD_VALUE,
"%s(%d) mode is only supported on output port", asString(mode), mode);
- return BAD_VALUE;
+ err = BAD_VALUE;
+ break;
}
// Check if we're simulating legacy mode with metadata mode,
@@ -743,7 +750,7 @@
if (storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL) == OK) {
CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
"metdata mode enabled successfully");
- return OK;
+ break;
}
CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
@@ -754,15 +761,15 @@
// Disable secure buffer and enable graphic buffer
(void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
- status_t err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
+ err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
if (err != OK) {
- return err;
+ break;
}
// Not running experiment, or metadata is not supported.
// Disable metadata mode and use legacy mode.
(void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
- return OK;
+ break;
}
case IOMX::kPortModePresetByteBuffer:
@@ -771,15 +778,19 @@
(void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
(void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
(void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
- return OK;
- }
-
- default:
break;
}
- CLOG_ERROR(setPortMode, BAD_VALUE, "invalid port mode %d", mode);
- return BAD_VALUE;
+ default:
+ CLOG_ERROR(setPortMode, BAD_VALUE, "invalid port mode %d", mode);
+ err = BAD_VALUE;
+ break;
+ }
+
+ if (err == OK) {
+ mPortMode[portIndex] = mode;
+ }
+ return err;
}
status_t OMXNodeInstance::enableNativeBuffers_l(
@@ -1057,28 +1068,48 @@
}
switch (omxBuffer.mBufferType) {
- case OMXBuffer::kBufferTypePreset:
+ case OMXBuffer::kBufferTypePreset: {
+ if (mPortMode[portIndex] != IOMX::kPortModeDynamicANWBuffer
+ && mPortMode[portIndex] != IOMX::kPortModeDynamicNativeHandle) {
+ break;
+ }
return useBuffer_l(portIndex, NULL, NULL, buffer);
+ }
- case OMXBuffer::kBufferTypeSharedMem:
+ case OMXBuffer::kBufferTypeSharedMem: {
+ if (mPortMode[portIndex] != IOMX::kPortModePresetByteBuffer) {
+ break;
+ }
return useBuffer_l(portIndex, omxBuffer.mMem, NULL, buffer);
+ }
- case OMXBuffer::kBufferTypeANWBuffer:
+ case OMXBuffer::kBufferTypeANWBuffer: {
+ if (mPortMode[portIndex] != IOMX::kPortModePresetANWBuffer) {
+ break;
+ }
return useGraphicBuffer_l(portIndex, omxBuffer.mGraphicBuffer, buffer);
+ }
case OMXBuffer::kBufferTypeHidlMemory: {
+ if (mPortMode[portIndex] != IOMX::kPortModePresetByteBuffer
+ && mPortMode[portIndex] != IOMX::kPortModeDynamicANWBuffer) {
+ break;
+ }
sp<IHidlMemory> hidlMemory = mapMemory(omxBuffer.mHidlMemory);
if (hidlMemory == nullptr) {
ALOGE("OMXNodeInstance useBuffer() failed to map memory");
return NO_MEMORY;
}
return useBuffer_l(portIndex, NULL, hidlMemory, buffer);
- }
+ }
default:
+ return BAD_VALUE;
break;
}
- return BAD_VALUE;
+ ALOGE("b/77486542");
+ android_errorWriteLog(0x534e4554, "77486542");
+ return INVALID_OPERATION;
}
status_t OMXNodeInstance::useBuffer_l(
@@ -1514,6 +1545,11 @@
android_errorWriteLog(0x534e4554, "35467458");
return BAD_VALUE;
}
+ if (mPortMode[portIndex] != IOMX::kPortModePresetSecureBuffer) {
+ ALOGE("b/77486542");
+ android_errorWriteLog(0x534e4554, "77486542");
+ return INVALID_OPERATION;
+ }
BufferMeta *buffer_meta = new BufferMeta(portIndex);
OMX_BUFFERHEADERTYPE *header;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3c4f500..76b29c9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -56,6 +56,7 @@
#include <system/audio_effects/effect_aec.h>
#include <audio_utils/primitives.h>
+#include <audio_utils/string.h>
#include <powermanager/PowerManager.h>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a141f49..ee16e07 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -616,7 +616,7 @@
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/);
if (state != AUDIO_MODE_IN_CALL || desc != mPrimaryOutput) {
- setOutputDevice(desc, newDevice, (newDevice != AUDIO_DEVICE_NONE), delayMs);
+ setOutputDevice(desc, newDevice, (newDevice != AUDIO_DEVICE_NONE), 0 /*delayMs*/);
}
}
@@ -4672,14 +4672,23 @@
}
if (!vectorsEqual(srcOutputs,dstOutputs)) {
+ // get maximum latency of all source outputs to determine the minimum mute time guaranteeing
+ // audio from invalidated tracks will be rendered when unmuting
+ uint32_t maxLatency = 0;
+ for (audio_io_handle_t srcOut : srcOutputs) {
+ sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
+ if (desc != 0 && maxLatency < desc->latency()) {
+ maxLatency = desc->latency();
+ }
+ }
ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d",
strategy, srcOutputs[0], dstOutputs[0]);
// mute strategy while moving tracks from one output to another
for (audio_io_handle_t srcOut : srcOutputs) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(srcOut);
- if (isStrategyActive(desc, strategy)) {
+ sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
+ if (desc != 0 && isStrategyActive(desc, strategy)) {
setStrategyMute(strategy, true, desc);
- setStrategyMute(strategy, false, desc, MUTE_TIME_MS, newDevice);
+ setStrategyMute(strategy, false, desc, maxLatency * LATENCY_MUTE_FACTOR, newDevice);
}
sp<AudioSourceDescriptor> source =
getSourceForStrategyOnOutput(srcOut, strategy);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 62a14df..b954714 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -68,6 +68,10 @@
// is switched
#define MUTE_TIME_MS 2000
+// multiplication factor applied to output latency when calculating a safe mute delay when
+// invalidating tracks
+#define LATENCY_MUTE_FACTOR 4
+
#define NUM_TEST_OUTPUTS 5
#define NUM_VOL_CURVE_KNEES 2
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 35857cc..9592b6a 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -121,9 +121,11 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- if (!settingsAllowed()) {
+
+ if (!modifyAudioRoutingAllowed()) {
return PERMISSION_DENIED;
}
+
if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
return BAD_VALUE;
}
@@ -340,6 +342,13 @@
return PERMISSION_DENIED;
}
+ if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
+ attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
+ attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+ !captureAudioOutputAllowed(pid, uid)) {
+ return PERMISSION_DENIED;
+ }
+
if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed(pid, uid)) {
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 8d8bcab..4a58620 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -1215,6 +1215,35 @@
fastInfo.maxJpegSize = getMaxSize(getAvailableJpegSizes());
+ isZslReprocessPresent = false;
+ camera_metadata_ro_entry_t availableCapabilities =
+ staticInfo(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ if (0 < availableCapabilities.count) {
+ const uint8_t *caps = availableCapabilities.data.u8;
+ for (size_t i = 0; i < availableCapabilities.count; i++) {
+ if (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING ==
+ caps[i]) {
+ isZslReprocessPresent = true;
+ break;
+ }
+ }
+ }
+ if (isZslReprocessPresent) {
+ Vector<StreamConfiguration> scs = getStreamConfigurations();
+ Size maxPrivInputSize = {0, 0};
+ for (const auto& sc : scs) {
+ if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT &&
+ sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ if (sc.width * sc.height > maxPrivInputSize.width * maxPrivInputSize.height) {
+ maxPrivInputSize = {sc.width, sc.height};
+ }
+ }
+ }
+ fastInfo.maxZslSize = maxPrivInputSize;
+ } else {
+ fastInfo.maxZslSize = {0, 0};
+ }
+
return OK;
}
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index fe725fd..e35b7a4 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -242,6 +242,7 @@
float minFocalLength;
bool useFlexibleYuv;
Size maxJpegSize;
+ Size maxZslSize;
} fastInfo;
// Quirks information; these are short-lived flags to enable workarounds for
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 372a2c5..37e1495 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -231,63 +231,9 @@
return INVALID_OPERATION;
}
- if ((mZslStreamId != NO_STREAM) || (mInputStreamId != NO_STREAM)) {
- // Check if stream parameters have to change
- CameraDeviceBase::StreamInfo streamInfo;
- res = device->getStreamInfo(mZslStreamId, &streamInfo);
- if (res != OK) {
- ALOGE("%s: Camera %d: Error querying capture output stream info: "
- "%s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
- return res;
- }
- if (streamInfo.width != (uint32_t)params.fastInfo.arrayWidth ||
- streamInfo.height != (uint32_t)params.fastInfo.arrayHeight) {
- if (mZslStreamId != NO_STREAM) {
- ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
- "dimensions changed",
- __FUNCTION__, client->getCameraId(), mZslStreamId);
- res = device->deleteStream(mZslStreamId);
- if (res == -EBUSY) {
- ALOGV("%s: Camera %d: Device is busy, call updateStream again "
- " after it becomes idle", __FUNCTION__, mId);
- return res;
- } else if(res != OK) {
- ALOGE("%s: Camera %d: Unable to delete old output stream "
- "for ZSL: %s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
- return res;
- }
- mZslStreamId = NO_STREAM;
- }
-
- if (mInputStreamId != NO_STREAM) {
- ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
- "dimensions changed",
- __FUNCTION__, client->getCameraId(), mInputStreamId);
- res = device->deleteStream(mInputStreamId);
- if (res == -EBUSY) {
- ALOGV("%s: Camera %d: Device is busy, call updateStream again "
- " after it becomes idle", __FUNCTION__, mId);
- return res;
- } else if(res != OK) {
- ALOGE("%s: Camera %d: Unable to delete old output stream "
- "for ZSL: %s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
- return res;
- }
- mInputStreamId = NO_STREAM;
- }
- if (nullptr != mInputProducer.get()) {
- mInputProducer->disconnect(NATIVE_WINDOW_API_CPU);
- mInputProducer.clear();
- }
- }
- }
-
if (mInputStreamId == NO_STREAM) {
- res = device->createInputStream(params.fastInfo.arrayWidth,
- params.fastInfo.arrayHeight, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ res = device->createInputStream(params.fastInfo.maxZslSize.width,
+ params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
&mInputStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create input stream: "
@@ -309,8 +255,8 @@
mProducer->setName(String8("Camera2-ZslRingBufferConsumer"));
sp<Surface> outSurface = new Surface(producer);
- res = device->createStream(outSurface, params.fastInfo.arrayWidth,
- params.fastInfo.arrayHeight, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ res = device->createStream(outSurface, params.fastInfo.maxZslSize.width,
+ params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId,
String8());
if (res != OK) {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 5675b0b..6a72e5b 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -144,15 +144,14 @@
// If a close request is pending then close the stream
bool AAudioService::releaseStream(const sp<AAudioServiceStreamBase> &serviceStream) {
bool closed = false;
- if ((serviceStream->decrementServiceReferenceCount() == 0) && serviceStream->isCloseNeeded()) {
- // removeStreamByHandle() uses a lock so that if there are two simultaneous closes
- // then only one will get the pointer and do the close.
- sp<AAudioServiceStreamBase> foundStream = mStreamTracker.removeStreamByHandle(serviceStream->getHandle());
- if (foundStream.get() != nullptr) {
- foundStream->close();
- pid_t pid = foundStream->getOwnerProcessId();
- AAudioClientTracker::getInstance().unregisterClientStream(pid, foundStream);
- }
+ // decrementAndRemoveStreamByHandle() uses a lock so that if there are two simultaneous closes
+ // then only one will get the pointer and do the close.
+ sp<AAudioServiceStreamBase> foundStream = mStreamTracker.decrementAndRemoveStreamByHandle(
+ serviceStream->getHandle());
+ if (foundStream.get() != nullptr) {
+ foundStream->close();
+ pid_t pid = foundStream->getOwnerProcessId();
+ AAudioClientTracker::getInstance().unregisterClientStream(pid, foundStream);
closed = true;
}
return closed;
@@ -175,14 +174,15 @@
pid_t pid = serviceStream->getOwnerProcessId();
AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
- serviceStream->setCloseNeeded(true);
+ serviceStream->markCloseNeeded();
(void) releaseStream(serviceStream);
return AAUDIO_OK;
}
sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
aaudio_handle_t streamHandle) {
- sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandle(streamHandle);
+ sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandleAndIncrement(
+ streamHandle);
if (serviceStream.get() != nullptr) {
// Only allow owner or the aaudio service to access the stream.
const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
@@ -194,9 +194,9 @@
if (!allowed) {
ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
callingUserId, streamHandle, ownerUserId);
+ // We incremented the reference count so we must check if it needs to be closed.
+ checkForPendingClose(serviceStream, AAUDIO_OK);
serviceStream.clear();
- } else {
- serviceStream->incrementServiceReferenceCount();
}
}
return serviceStream;
@@ -328,12 +328,11 @@
aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
ALOGD("%s(%d) called", __func__, portHandle);
sp<AAudioServiceStreamBase> serviceStream =
- mStreamTracker.findStreamByPortHandle(portHandle);
+ mStreamTracker.findStreamByPortHandleAndIncrement(portHandle);
if (serviceStream.get() == nullptr) {
ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
- serviceStream->incrementServiceReferenceCount();
aaudio_result_t result = serviceStream->stop();
serviceStream->disconnect();
return checkForPendingClose(serviceStream, result);
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 48d8002..9af8af3 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -414,12 +414,13 @@
sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
}
-int32_t AAudioServiceStreamBase::incrementServiceReferenceCount() {
- std::lock_guard<std::mutex> lock(mCallingCountLock);
+int32_t AAudioServiceStreamBase::incrementServiceReferenceCount_l() {
return ++mCallingCount;
}
-int32_t AAudioServiceStreamBase::decrementServiceReferenceCount() {
- std::lock_guard<std::mutex> lock(mCallingCountLock);
- return --mCallingCount;
+int32_t AAudioServiceStreamBase::decrementServiceReferenceCount_l() {
+ int32_t count = --mCallingCount;
+ // Each call to increment should be balanced with one call to decrement.
+ assert(count >= 0);
+ return count;
}
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 0ad015e..a1815d0 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -205,22 +205,33 @@
/**
* Atomically increment the number of active references to the stream by AAudioService.
+ *
+ * This is called under a global lock in AAudioStreamTracker.
+ *
* @return value after the increment
*/
- int32_t incrementServiceReferenceCount();
+ int32_t incrementServiceReferenceCount_l();
/**
* Atomically decrement the number of active references to the stream by AAudioService.
+ * This should only be called after incrementServiceReferenceCount_l().
+ *
+ * This is called under a global lock in AAudioStreamTracker.
+ *
* @return value after the decrement
*/
- int32_t decrementServiceReferenceCount();
+ int32_t decrementServiceReferenceCount_l();
bool isCloseNeeded() const {
return mCloseNeeded.load();
}
- void setCloseNeeded(bool needed) {
- mCloseNeeded.store(needed);
+ /**
+ * Mark this stream as needing to be closed.
+ * Once marked for closing, it cannot be unmarked.
+ */
+ void markCloseNeeded() {
+ mCloseNeeded.store(true);
}
virtual const char *getTypeText() const { return "Base"; }
@@ -290,8 +301,9 @@
aaudio_handle_t mHandle = -1;
bool mFlowing = false;
- std::mutex mCallingCountLock;
- std::atomic<int32_t> mCallingCount{0};
+ // This is modified under a global lock in AAudioStreamTracker.
+ int32_t mCallingCount = 0;
+
std::atomic<bool> mCloseNeeded{false};
};
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
index 9d5d8fc..3328159 100644
--- a/services/oboeservice/AAudioStreamTracker.cpp
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -30,34 +30,40 @@
using namespace android;
using namespace aaudio;
-sp<AAudioServiceStreamBase> AAudioStreamTracker::removeStreamByHandle(
+sp<AAudioServiceStreamBase> AAudioStreamTracker::decrementAndRemoveStreamByHandle(
+ aaudio_handle_t streamHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.find(streamHandle);
+ if (it != mStreamsByHandle.end()) {
+ sp<AAudioServiceStreamBase> tempStream = it->second;
+ // Does the caller need to close the stream?
+ // The reference count should never be negative.
+ // But it is safer to check for <= 0 than == 0.
+ if ((tempStream->decrementServiceReferenceCount_l() <= 0) && tempStream->isCloseNeeded()) {
+ serviceStream = tempStream; // Only return stream if ready to be closed.
+ mStreamsByHandle.erase(it);
+ }
+ }
+ return serviceStream;
+}
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandleAndIncrement(
aaudio_handle_t streamHandle) {
std::lock_guard<std::mutex> lock(mHandleLock);
sp<AAudioServiceStreamBase> serviceStream;
auto it = mStreamsByHandle.find(streamHandle);
if (it != mStreamsByHandle.end()) {
serviceStream = it->second;
- mStreamsByHandle.erase(it);
+ serviceStream->incrementServiceReferenceCount_l();
}
return serviceStream;
}
-sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle(
- aaudio_handle_t streamHandle) {
- std::lock_guard<std::mutex> lock(mHandleLock);
- sp<AAudioServiceStreamBase> serviceStream;
- auto it = mStreamsByHandle.find(streamHandle);
- if (it != mStreamsByHandle.end()) {
- serviceStream = it->second;
- }
- return serviceStream;
-}
-
-
// The port handle is only available when the stream is started.
// So we have to iterate over all the streams.
// Luckily this rarely happens.
-sp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandle(
+sp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandleAndIncrement(
audio_port_handle_t portHandle) {
std::lock_guard<std::mutex> lock(mHandleLock);
sp<AAudioServiceStreamBase> serviceStream;
@@ -66,6 +72,7 @@
auto candidate = it->second;
if (candidate->getPortHandle() == portHandle) {
serviceStream = candidate;
+ serviceStream->incrementServiceReferenceCount_l();
break;
}
it++;
@@ -86,7 +93,7 @@
aaudio_handle_t AAudioStreamTracker::addStreamForHandle(sp<AAudioServiceStreamBase> serviceStream) {
std::lock_guard<std::mutex> lock(mHandleLock);
- aaudio_handle_t handle = mPreviousHandle.load();
+ aaudio_handle_t handle = mPreviousHandle;
// Assign a unique handle.
while (true) {
handle = bumpHandle(handle);
@@ -98,7 +105,7 @@
break;
}
}
- mPreviousHandle.store(handle);
+ mPreviousHandle = handle;
return handle;
}
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
index 54e46ca..57ec426 100644
--- a/services/oboeservice/AAudioStreamTracker.h
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -32,25 +32,35 @@
public:
/**
- * Remove the stream associated with the handle.
+ * Find the stream associated with the handle.
+ * Decrement its reference counter. If zero and the stream needs
+ * to be closed then remove the stream and return a pointer to the stream.
+ * Otherwise return null if it does not need to be closed.
+ *
* @param streamHandle
- * @return strong pointer to the stream if found or to nullptr
+ * @return strong pointer to the stream if it needs to be closed, or nullptr
*/
- android::sp<AAudioServiceStreamBase> removeStreamByHandle(aaudio_handle_t streamHandle);
+ android::sp<AAudioServiceStreamBase> decrementAndRemoveStreamByHandle(
+ aaudio_handle_t streamHandle);
/**
* Look up a stream based on the handle.
+ * Increment its service reference count if found.
+ *
* @param streamHandle
- * @return strong pointer to the stream if found or to nullptr
+ * @return strong pointer to the stream if found, or nullptr
*/
- android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(aaudio_handle_t streamHandle);
+ android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandleAndIncrement(
+ aaudio_handle_t streamHandle);
/**
* Look up a stream based on the AudioPolicy portHandle.
+ * Increment its service reference count if found.
+ *
* @param portHandle
- * @return strong pointer to the stream if found or to nullptr
+ * @return strong pointer to the stream if found, or nullptr
*/
- android::sp<aaudio::AAudioServiceStreamBase> findStreamByPortHandle(
+ android::sp<aaudio::AAudioServiceStreamBase> findStreamByPortHandleAndIncrement(
audio_port_handle_t portHandle);
/**
@@ -71,7 +81,9 @@
// Track stream using a unique handle that wraps. Only use positive half.
mutable std::mutex mHandleLock;
- std::atomic<aaudio_handle_t> mPreviousHandle{0};
+ // protected by mHandleLock
+ aaudio_handle_t mPreviousHandle = 0;
+ // protected by mHandleLock
std::map<aaudio_handle_t, android::sp<aaudio::AAudioServiceStreamBase>> mStreamsByHandle;
};