| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 1 | /* | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 2 | * Copyright (C) 2019 The Android Open Source Project | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
| Mikhail Naganov | fa69dc6 | 2018-07-27 09:58:58 -0700 | [diff] [blame] | 17 | #include <set> | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 18 |  | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 19 | #define LOG_TAG "AudioProfile" | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 20 | //#define LOG_NDEBUG 0 | 
|  | 21 |  | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 22 | #include <android-base/stringprintf.h> | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 23 | #include <media/AudioContainers.h> | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 24 | #include <media/AudioProfile.h> | 
|  | 25 | #include <media/TypeConverter.h> | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 26 | #include <utils/Errors.h> | 
|  | 27 |  | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 28 | namespace android { | 
|  | 29 |  | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 30 | bool operator == (const AudioProfile &left, const AudioProfile &right) | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 31 | { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 32 | return (left.getFormat() == right.getFormat()) && | 
|  | 33 | (left.getChannels() == right.getChannels()) && | 
|  | 34 | (left.getSampleRates() == right.getSampleRates()); | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 35 | } | 
|  | 36 |  | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 37 | // static | 
|  | 38 | sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat) | 
| Mikhail Naganov | 21b4336 | 2018-06-04 10:37:09 -0700 | [diff] [blame] | 39 | { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 40 | AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat, | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 41 | ChannelMaskSet(), SampleRateSet()); | 
| Mikhail Naganov | 21b4336 | 2018-06-04 10:37:09 -0700 | [diff] [blame] | 42 | dynamicProfile->setDynamicFormat(true); | 
|  | 43 | dynamicProfile->setDynamicChannels(true); | 
|  | 44 | dynamicProfile->setDynamicRate(true); | 
|  | 45 | return dynamicProfile; | 
|  | 46 | } | 
|  | 47 |  | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 48 | AudioProfile::AudioProfile(audio_format_t format, | 
|  | 49 | audio_channel_mask_t channelMasks, | 
|  | 50 | uint32_t samplingRate) : | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 51 | mName(""), | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 52 | mFormat(format) | 
|  | 53 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 54 | mChannelMasks.insert(channelMasks); | 
|  | 55 | mSamplingRates.insert(samplingRate); | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 56 | } | 
|  | 57 |  | 
|  | 58 | AudioProfile::AudioProfile(audio_format_t format, | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 59 | const ChannelMaskSet &channelMasks, | 
|  | 60 | const SampleRateSet &samplingRateCollection) : | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 61 | AudioProfile(format, channelMasks, samplingRateCollection, | 
|  | 62 | AUDIO_ENCAPSULATION_TYPE_NONE) {} | 
|  | 63 |  | 
|  | 64 | AudioProfile::AudioProfile(audio_format_t format, | 
|  | 65 | const ChannelMaskSet &channelMasks, | 
|  | 66 | const SampleRateSet &samplingRateCollection, | 
|  | 67 | audio_encapsulation_type_t encapsulationType) : | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 68 | mName(""), | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 69 | mFormat(format), | 
|  | 70 | mChannelMasks(channelMasks), | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 71 | mSamplingRates(samplingRateCollection), | 
|  | 72 | mEncapsulationType(encapsulationType) {} | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 73 |  | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 74 | void AudioProfile::setChannels(const ChannelMaskSet &channelMasks) | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 75 | { | 
|  | 76 | if (mIsDynamicChannels) { | 
|  | 77 | mChannelMasks = channelMasks; | 
|  | 78 | } | 
|  | 79 | } | 
|  | 80 |  | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 81 | void AudioProfile::setSampleRates(const SampleRateSet &sampleRates) | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 82 | { | 
|  | 83 | if (mIsDynamicRate) { | 
|  | 84 | mSamplingRates = sampleRates; | 
|  | 85 | } | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | void AudioProfile::clear() | 
|  | 89 | { | 
|  | 90 | if (mIsDynamicChannels) { | 
|  | 91 | mChannelMasks.clear(); | 
|  | 92 | } | 
|  | 93 | if (mIsDynamicRate) { | 
|  | 94 | mSamplingRates.clear(); | 
|  | 95 | } | 
|  | 96 | } | 
|  | 97 |  | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 98 | void AudioProfile::dump(std::string *dst, int spaces) const | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 99 | { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 100 | dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 101 | mIsDynamicChannels ? "[dynamic channels]" : "", | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 102 | mIsDynamicRate ? "[dynamic rates]" : "")); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 103 | if (mName.length() != 0) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 104 | dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str())); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 105 | } | 
|  | 106 | std::string formatLiteral; | 
|  | 107 | if (FormatConverter::toString(mFormat, formatLiteral)) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 108 | dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str())); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 109 | } | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 110 | if (!mSamplingRates.empty()) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 111 | dst->append(base::StringPrintf("%*s- sampling rates:", spaces, "")); | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 112 | for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 113 | dst->append(base::StringPrintf("%d", *it)); | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 114 | dst->append(++it == mSamplingRates.end() ? "" : ", "); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 115 | } | 
| Andy Hung | bb54e20 | 2018-10-05 11:42:02 -0700 | [diff] [blame] | 116 | dst->append("\n"); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 117 | } | 
|  | 118 |  | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 119 | if (!mChannelMasks.empty()) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 120 | dst->append(base::StringPrintf("%*s- channel masks:", spaces, "")); | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 121 | for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 122 | dst->append(base::StringPrintf("0x%04x", *it)); | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 123 | dst->append(++it == mChannelMasks.end() ? "" : ", "); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 124 | } | 
| Andy Hung | bb54e20 | 2018-10-05 11:42:02 -0700 | [diff] [blame] | 125 | dst->append("\n"); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 126 | } | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 127 |  | 
|  | 128 | dst->append(base::StringPrintf( | 
|  | 129 | "%*s- encapsulation type: %#x\n", spaces, "", mEncapsulationType)); | 
| François Gaffie | 112b0af | 2015-11-19 16:13:25 +0100 | [diff] [blame] | 130 | } | 
|  | 131 |  | 
| jiabin | 49e69a1 | 2019-10-15 16:04:13 -0700 | [diff] [blame] | 132 | bool AudioProfile::equals(const sp<AudioProfile>& other) const | 
|  | 133 | { | 
|  | 134 | return other != nullptr && | 
|  | 135 | mName.compare(other->mName) == 0 && | 
|  | 136 | mFormat == other->getFormat() && | 
|  | 137 | mChannelMasks == other->getChannels() && | 
|  | 138 | mSamplingRates == other->getSampleRates() && | 
|  | 139 | mIsDynamicFormat == other->isDynamicFormat() && | 
|  | 140 | mIsDynamicChannels == other->isDynamicChannels() && | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 141 | mIsDynamicRate == other->isDynamicRate() && | 
|  | 142 | mEncapsulationType == other->getEncapsulationType(); | 
| jiabin | 49e69a1 | 2019-10-15 16:04:13 -0700 | [diff] [blame] | 143 | } | 
|  | 144 |  | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 145 | AudioProfile& AudioProfile::operator=(const AudioProfile& other) { | 
|  | 146 | mName = other.mName; | 
|  | 147 | mFormat = other.mFormat; | 
|  | 148 | mChannelMasks = other.mChannelMasks; | 
|  | 149 | mSamplingRates = other.mSamplingRates; | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 150 | mEncapsulationType = other.mEncapsulationType; | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 151 | mIsDynamicFormat = other.mIsDynamicFormat; | 
|  | 152 | mIsDynamicChannels = other.mIsDynamicChannels; | 
|  | 153 | mIsDynamicRate = other.mIsDynamicRate; | 
|  | 154 | return *this; | 
| jiabin | 17058fa | 2019-10-08 17:33:38 -0700 | [diff] [blame] | 155 | } | 
|  | 156 |  | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 157 | ConversionResult<media::AudioProfile> | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 158 | AudioProfile::toParcelable(bool isInput) const { | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 159 | media::AudioProfile parcelable; | 
|  | 160 | parcelable.name = mName; | 
| Mikhail Naganov | b60bd1b | 2021-07-15 17:31:43 -0700 | [diff] [blame] | 161 | parcelable.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(mFormat)); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 162 | parcelable.channelMasks = VALUE_OR_RETURN( | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 163 | convertContainer<std::vector<media::AudioChannelLayout>>( | 
| Mikhail Naganov | 2d8df4e | 2021-06-03 13:59:13 -0700 | [diff] [blame] | 164 | mChannelMasks, | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 165 | [isInput](audio_channel_mask_t m) { | 
|  | 166 | return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput); | 
|  | 167 | })); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 168 | parcelable.samplingRates = VALUE_OR_RETURN( | 
|  | 169 | convertContainer<std::vector<int32_t>>(mSamplingRates, | 
|  | 170 | convertIntegral<int32_t, uint32_t>)); | 
|  | 171 | parcelable.isDynamicFormat = mIsDynamicFormat; | 
|  | 172 | parcelable.isDynamicChannels = mIsDynamicChannels; | 
|  | 173 | parcelable.isDynamicRate = mIsDynamicRate; | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 174 | parcelable.encapsulationType = VALUE_OR_RETURN( | 
|  | 175 | legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(mEncapsulationType)); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 176 | return parcelable; | 
|  | 177 | } | 
|  | 178 |  | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 179 | ConversionResult<sp<AudioProfile>> | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 180 | AudioProfile::fromParcelable(const media::AudioProfile& parcelable, bool isInput) { | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 181 | sp<AudioProfile> legacy = new AudioProfile(); | 
|  | 182 | legacy->mName = parcelable.name; | 
| Mikhail Naganov | b60bd1b | 2021-07-15 17:31:43 -0700 | [diff] [blame] | 183 | legacy->mFormat = VALUE_OR_RETURN( | 
|  | 184 | aidl2legacy_AudioFormatDescription_audio_format_t(parcelable.format)); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 185 | legacy->mChannelMasks = VALUE_OR_RETURN( | 
|  | 186 | convertContainer<ChannelMaskSet>(parcelable.channelMasks, | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 187 | [isInput](const media::AudioChannelLayout& l) { | 
|  | 188 | return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput); | 
|  | 189 | })); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 190 | legacy->mSamplingRates = VALUE_OR_RETURN( | 
|  | 191 | convertContainer<SampleRateSet>(parcelable.samplingRates, | 
|  | 192 | convertIntegral<uint32_t, int32_t>)); | 
|  | 193 | legacy->mIsDynamicFormat = parcelable.isDynamicFormat; | 
|  | 194 | legacy->mIsDynamicChannels = parcelable.isDynamicChannels; | 
|  | 195 | legacy->mIsDynamicRate = parcelable.isDynamicRate; | 
| jiabin | 82e5693 | 2021-03-05 06:35:19 +0000 | [diff] [blame] | 196 | legacy->mEncapsulationType = VALUE_OR_RETURN( | 
|  | 197 | aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t( | 
|  | 198 | parcelable.encapsulationType)); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 199 | return legacy; | 
|  | 200 | } | 
|  | 201 |  | 
|  | 202 | ConversionResult<sp<AudioProfile>> | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 203 | aidl2legacy_AudioProfile(const media::AudioProfile& aidl, bool isInput) { | 
|  | 204 | return AudioProfile::fromParcelable(aidl, isInput); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 205 | } | 
|  | 206 |  | 
|  | 207 | ConversionResult<media::AudioProfile> | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 208 | legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput) { | 
|  | 209 | return legacy->toParcelable(isInput); | 
| jiabin | 17058fa | 2019-10-08 17:33:38 -0700 | [diff] [blame] | 210 | } | 
|  | 211 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 212 | ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile) | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 213 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 214 | ssize_t index = size(); | 
|  | 215 | push_back(profile); | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 216 | return index; | 
|  | 217 | } | 
|  | 218 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 219 | void AudioProfileVector::clearProfiles() | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 220 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 221 | for (auto it = begin(); it != end();) { | 
|  | 222 | if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) { | 
|  | 223 | it = erase(it); | 
|  | 224 | } else { | 
|  | 225 | (*it)->clear(); | 
|  | 226 | ++it; | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 227 | } | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 228 | } | 
|  | 229 | } | 
|  | 230 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 231 | sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 232 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 233 | for (const auto &profile : *this) { | 
|  | 234 | if (profile->isValid()) { | 
|  | 235 | return profile; | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 236 | } | 
|  | 237 | } | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 238 | return nullptr; | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 239 | } | 
|  | 240 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 241 | sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 242 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 243 | for (const auto &profile : *this) { | 
|  | 244 | if (profile->isValid() && profile->getFormat() == format) { | 
|  | 245 | return profile; | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 246 | } | 
|  | 247 | } | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 248 | return nullptr; | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 249 | } | 
|  | 250 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 251 | FormatVector AudioProfileVector::getSupportedFormats() const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 252 | { | 
|  | 253 | FormatVector supportedFormats; | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 254 | for (const auto &profile : *this) { | 
|  | 255 | if (profile->hasValidFormat()) { | 
|  | 256 | supportedFormats.push_back(profile->getFormat()); | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 257 | } | 
|  | 258 | } | 
|  | 259 | return supportedFormats; | 
|  | 260 | } | 
|  | 261 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 262 | bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 263 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 264 | for (const auto &profile : *this) { | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 265 | if (profile->getFormat() == format && profile->isDynamicChannels()) { | 
|  | 266 | return true; | 
|  | 267 | } | 
|  | 268 | } | 
|  | 269 | return false; | 
|  | 270 | } | 
|  | 271 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 272 | bool AudioProfileVector::hasDynamicFormat() const | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 273 | { | 
|  | 274 | for (const auto &profile : *this) { | 
|  | 275 | if (profile->isDynamicFormat()) { | 
|  | 276 | return true; | 
|  | 277 | } | 
|  | 278 | } | 
|  | 279 | return false; | 
|  | 280 | } | 
|  | 281 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 282 | bool AudioProfileVector::hasDynamicProfile() const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 283 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 284 | for (const auto &profile : *this) { | 
|  | 285 | if (profile->isDynamic()) { | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 286 | return true; | 
|  | 287 | } | 
|  | 288 | } | 
|  | 289 | return false; | 
|  | 290 | } | 
|  | 291 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 292 | bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 293 | { | 
| jiabin | 06e4bab | 2019-07-29 10:13:34 -0700 | [diff] [blame] | 294 | for (const auto &profile : *this) { | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 295 | if (profile->getFormat() == format && profile->isDynamicRate()) { | 
|  | 296 | return true; | 
|  | 297 | } | 
|  | 298 | } | 
|  | 299 | return false; | 
|  | 300 | } | 
|  | 301 |  | 
| jiabin | b4fed19 | 2020-09-22 14:45:40 -0700 | [diff] [blame] | 302 | bool AudioProfileVector::contains(const sp<AudioProfile>& profile) const | 
|  | 303 | { | 
|  | 304 | for (const auto& audioProfile : *this) { | 
|  | 305 | if (audioProfile->equals(profile)) { | 
|  | 306 | return true; | 
|  | 307 | } | 
|  | 308 | } | 
|  | 309 | return false; | 
|  | 310 | } | 
|  | 311 |  | 
| jiabin | 3e277cc | 2019-09-10 14:27:34 -0700 | [diff] [blame] | 312 | void AudioProfileVector::dump(std::string *dst, int spaces) const | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 313 | { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 314 | dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, "")); | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 315 | for (size_t i = 0; i < size(); i++) { | 
| jiabin | 9bb3a1e | 2019-08-19 10:10:17 -0700 | [diff] [blame] | 316 | dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i)); | 
|  | 317 | std::string profileStr; | 
|  | 318 | at(i)->dump(&profileStr, spaces + 8); | 
|  | 319 | dst->append(profileStr); | 
| Mikhail Naganov | e50f628 | 2018-07-26 16:20:43 -0700 | [diff] [blame] | 320 | } | 
|  | 321 | } | 
|  | 322 |  | 
| jiabin | 49e69a1 | 2019-10-15 16:04:13 -0700 | [diff] [blame] | 323 | bool AudioProfileVector::equals(const AudioProfileVector& other) const | 
|  | 324 | { | 
|  | 325 | return std::equal(begin(), end(), other.begin(), other.end(), | 
|  | 326 | [](const sp<AudioProfile>& left, const sp<AudioProfile>& right) { | 
|  | 327 | return left->equals(right); | 
|  | 328 | }); | 
|  | 329 | } | 
|  | 330 |  | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 331 | ConversionResult<AudioProfileVector> | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 332 | aidl2legacy_AudioProfileVector(const std::vector<media::AudioProfile>& aidl, bool isInput) { | 
|  | 333 | return convertContainer<AudioProfileVector>(aidl, | 
|  | 334 | [isInput](const media::AudioProfile& p) { | 
|  | 335 | return aidl2legacy_AudioProfile(p, isInput); | 
|  | 336 | }); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 337 | } | 
|  | 338 |  | 
|  | 339 | ConversionResult<std::vector<media::AudioProfile>> | 
| Mikhail Naganov | de3fa18 | 2021-07-30 15:06:42 -0700 | [diff] [blame] | 340 | legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy, bool isInput) { | 
|  | 341 | return convertContainer<std::vector<media::AudioProfile>>(legacy, | 
|  | 342 | [isInput](const sp<AudioProfile>& p) { | 
|  | 343 | return legacy2aidl_AudioProfile(p, isInput); | 
|  | 344 | }); | 
| Ytai Ben-Tsvi | 50e016a | 2020-11-12 14:26:12 -0800 | [diff] [blame] | 345 | } | 
|  | 346 |  | 
| jiabin | bce0c1d | 2020-10-05 11:20:18 -0700 | [diff] [blame] | 347 | AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1, | 
|  | 348 | const AudioProfileVector& profiles2) | 
|  | 349 | { | 
|  | 350 | std::map<audio_format_t, std::pair<ChannelMaskSet, SampleRateSet>> infos2; | 
|  | 351 | for (const auto& profile : profiles2) { | 
|  | 352 | infos2.emplace(profile->getFormat(), | 
|  | 353 | std::make_pair(profile->getChannels(), profile->getSampleRates())); | 
|  | 354 | } | 
|  | 355 | AudioProfileVector profiles; | 
|  | 356 | for (const auto& profile : profiles1) { | 
|  | 357 | const auto it = infos2.find(profile->getFormat()); | 
|  | 358 | if (it == infos2.end()) { | 
|  | 359 | continue; | 
|  | 360 | } | 
|  | 361 | ChannelMaskSet channelMasks = SetIntersection(profile->getChannels(), it->second.first); | 
|  | 362 | if (channelMasks.empty()) { | 
|  | 363 | continue; | 
|  | 364 | } | 
|  | 365 | SampleRateSet sampleRates = SetIntersection(profile->getSampleRates(), it->second.second); | 
|  | 366 | if (sampleRates.empty()) { | 
|  | 367 | continue; | 
|  | 368 | } | 
|  | 369 | profiles.push_back(new AudioProfile(profile->getFormat(), channelMasks, sampleRates)); | 
|  | 370 | } | 
|  | 371 | return profiles; | 
|  | 372 | } | 
|  | 373 |  | 
| Mikhail Naganov | 1b2a794 | 2017-12-08 10:18:09 -0800 | [diff] [blame] | 374 | } // namespace android |