xref: /aosp_15_r20/frameworks/av/media/libaudiofoundation/AudioProfile.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <set>
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioProfile"
20*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioContainers.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioProfile.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/TypeConverter.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>
27*ec779b8eSAndroid Build Coastguard Worker 
28*ec779b8eSAndroid Build Coastguard Worker namespace android {
29*ec779b8eSAndroid Build Coastguard Worker 
30*ec779b8eSAndroid Build Coastguard Worker using media::audio::common::AudioChannelLayout;
31*ec779b8eSAndroid Build Coastguard Worker 
operator ==(const AudioProfile & left,const AudioProfile & right)32*ec779b8eSAndroid Build Coastguard Worker bool operator == (const AudioProfile &left, const AudioProfile &right)
33*ec779b8eSAndroid Build Coastguard Worker {
34*ec779b8eSAndroid Build Coastguard Worker     return (left.getFormat() == right.getFormat()) &&
35*ec779b8eSAndroid Build Coastguard Worker             (left.getChannels() == right.getChannels()) &&
36*ec779b8eSAndroid Build Coastguard Worker             (left.getSampleRates() == right.getSampleRates());
37*ec779b8eSAndroid Build Coastguard Worker }
38*ec779b8eSAndroid Build Coastguard Worker 
39*ec779b8eSAndroid Build Coastguard Worker // static
createFullDynamic(audio_format_t dynamicFormat)40*ec779b8eSAndroid Build Coastguard Worker sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
41*ec779b8eSAndroid Build Coastguard Worker {
42*ec779b8eSAndroid Build Coastguard Worker     AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
43*ec779b8eSAndroid Build Coastguard Worker             ChannelMaskSet(), SampleRateSet());
44*ec779b8eSAndroid Build Coastguard Worker     dynamicProfile->setDynamicFormat(true);
45*ec779b8eSAndroid Build Coastguard Worker     dynamicProfile->setDynamicChannels(true);
46*ec779b8eSAndroid Build Coastguard Worker     dynamicProfile->setDynamicRate(true);
47*ec779b8eSAndroid Build Coastguard Worker     return dynamicProfile;
48*ec779b8eSAndroid Build Coastguard Worker }
49*ec779b8eSAndroid Build Coastguard Worker 
AudioProfile(audio_format_t format,audio_channel_mask_t channelMasks,uint32_t samplingRate)50*ec779b8eSAndroid Build Coastguard Worker AudioProfile::AudioProfile(audio_format_t format,
51*ec779b8eSAndroid Build Coastguard Worker                            audio_channel_mask_t channelMasks,
52*ec779b8eSAndroid Build Coastguard Worker                            uint32_t samplingRate) :
53*ec779b8eSAndroid Build Coastguard Worker         mName(""),
54*ec779b8eSAndroid Build Coastguard Worker         mFormat(format)
55*ec779b8eSAndroid Build Coastguard Worker {
56*ec779b8eSAndroid Build Coastguard Worker     mChannelMasks.insert(channelMasks);
57*ec779b8eSAndroid Build Coastguard Worker     mSamplingRates.insert(samplingRate);
58*ec779b8eSAndroid Build Coastguard Worker }
59*ec779b8eSAndroid Build Coastguard Worker 
AudioProfile(audio_format_t format,const ChannelMaskSet & channelMasks,const SampleRateSet & samplingRateCollection)60*ec779b8eSAndroid Build Coastguard Worker AudioProfile::AudioProfile(audio_format_t format,
61*ec779b8eSAndroid Build Coastguard Worker                            const ChannelMaskSet &channelMasks,
62*ec779b8eSAndroid Build Coastguard Worker                            const SampleRateSet &samplingRateCollection) :
63*ec779b8eSAndroid Build Coastguard Worker         AudioProfile(format, channelMasks, samplingRateCollection,
64*ec779b8eSAndroid Build Coastguard Worker                      AUDIO_ENCAPSULATION_TYPE_NONE) {}
65*ec779b8eSAndroid Build Coastguard Worker 
AudioProfile(audio_format_t format,const ChannelMaskSet & channelMasks,const SampleRateSet & samplingRateCollection,audio_encapsulation_type_t encapsulationType)66*ec779b8eSAndroid Build Coastguard Worker AudioProfile::AudioProfile(audio_format_t format,
67*ec779b8eSAndroid Build Coastguard Worker                            const ChannelMaskSet &channelMasks,
68*ec779b8eSAndroid Build Coastguard Worker                            const SampleRateSet &samplingRateCollection,
69*ec779b8eSAndroid Build Coastguard Worker                            audio_encapsulation_type_t encapsulationType) :
70*ec779b8eSAndroid Build Coastguard Worker         mName(""),
71*ec779b8eSAndroid Build Coastguard Worker         mFormat(format),
72*ec779b8eSAndroid Build Coastguard Worker         mChannelMasks(channelMasks),
73*ec779b8eSAndroid Build Coastguard Worker         mSamplingRates(samplingRateCollection),
74*ec779b8eSAndroid Build Coastguard Worker         mEncapsulationType(encapsulationType) {}
75*ec779b8eSAndroid Build Coastguard Worker 
setChannels(const ChannelMaskSet & channelMasks)76*ec779b8eSAndroid Build Coastguard Worker void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
77*ec779b8eSAndroid Build Coastguard Worker {
78*ec779b8eSAndroid Build Coastguard Worker     if (mIsDynamicChannels) {
79*ec779b8eSAndroid Build Coastguard Worker         mChannelMasks = channelMasks;
80*ec779b8eSAndroid Build Coastguard Worker     }
81*ec779b8eSAndroid Build Coastguard Worker }
82*ec779b8eSAndroid Build Coastguard Worker 
setSampleRates(const SampleRateSet & sampleRates)83*ec779b8eSAndroid Build Coastguard Worker void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
84*ec779b8eSAndroid Build Coastguard Worker {
85*ec779b8eSAndroid Build Coastguard Worker     if (mIsDynamicRate) {
86*ec779b8eSAndroid Build Coastguard Worker         mSamplingRates = sampleRates;
87*ec779b8eSAndroid Build Coastguard Worker     }
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker 
clear()90*ec779b8eSAndroid Build Coastguard Worker void AudioProfile::clear()
91*ec779b8eSAndroid Build Coastguard Worker {
92*ec779b8eSAndroid Build Coastguard Worker     if (mIsDynamicChannels) {
93*ec779b8eSAndroid Build Coastguard Worker         mChannelMasks.clear();
94*ec779b8eSAndroid Build Coastguard Worker     }
95*ec779b8eSAndroid Build Coastguard Worker     if (mIsDynamicRate) {
96*ec779b8eSAndroid Build Coastguard Worker         mSamplingRates.clear();
97*ec779b8eSAndroid Build Coastguard Worker     }
98*ec779b8eSAndroid Build Coastguard Worker }
99*ec779b8eSAndroid Build Coastguard Worker 
dump(std::string * dst,int spaces) const100*ec779b8eSAndroid Build Coastguard Worker void AudioProfile::dump(std::string *dst, int spaces) const
101*ec779b8eSAndroid Build Coastguard Worker {
102*ec779b8eSAndroid Build Coastguard Worker     dst->append(base::StringPrintf("\"%s\"; ", mName.c_str()));
103*ec779b8eSAndroid Build Coastguard Worker     dst->append(base::StringPrintf("%s%s%s%s", mIsDynamicFormat ? "[dynamic format]" : "",
104*ec779b8eSAndroid Build Coastguard Worker              mIsDynamicChannels ? "[dynamic channels]" : "",
105*ec779b8eSAndroid Build Coastguard Worker              mIsDynamicRate ? "[dynamic rates]" : "", isDynamic() ? "; " : ""));
106*ec779b8eSAndroid Build Coastguard Worker     dst->append(base::StringPrintf("%s (0x%x)\n", audio_format_to_string(mFormat), mFormat));
107*ec779b8eSAndroid Build Coastguard Worker 
108*ec779b8eSAndroid Build Coastguard Worker     if (!mSamplingRates.empty()) {
109*ec779b8eSAndroid Build Coastguard Worker         dst->append(base::StringPrintf("%*ssampling rates: ", spaces, ""));
110*ec779b8eSAndroid Build Coastguard Worker         for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
111*ec779b8eSAndroid Build Coastguard Worker             dst->append(base::StringPrintf("%d", *it));
112*ec779b8eSAndroid Build Coastguard Worker             dst->append(++it == mSamplingRates.end() ? "" : ", ");
113*ec779b8eSAndroid Build Coastguard Worker         }
114*ec779b8eSAndroid Build Coastguard Worker         dst->append("\n");
115*ec779b8eSAndroid Build Coastguard Worker     }
116*ec779b8eSAndroid Build Coastguard Worker 
117*ec779b8eSAndroid Build Coastguard Worker     if (!mChannelMasks.empty()) {
118*ec779b8eSAndroid Build Coastguard Worker         dst->append(base::StringPrintf("%*schannel masks: ", spaces, ""));
119*ec779b8eSAndroid Build Coastguard Worker         for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
120*ec779b8eSAndroid Build Coastguard Worker             dst->append(base::StringPrintf("0x%04x", *it));
121*ec779b8eSAndroid Build Coastguard Worker             dst->append(++it == mChannelMasks.end() ? "" : ", ");
122*ec779b8eSAndroid Build Coastguard Worker         }
123*ec779b8eSAndroid Build Coastguard Worker         dst->append("\n");
124*ec779b8eSAndroid Build Coastguard Worker     }
125*ec779b8eSAndroid Build Coastguard Worker 
126*ec779b8eSAndroid Build Coastguard Worker     dst->append(base::StringPrintf(
127*ec779b8eSAndroid Build Coastguard Worker              "%*s%s\n", spaces, "", audio_encapsulation_type_to_string(mEncapsulationType)));
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker 
equals(const sp<AudioProfile> & other,bool ignoreDynamicFlags) const130*ec779b8eSAndroid Build Coastguard Worker bool AudioProfile::equals(const sp<AudioProfile>& other, bool ignoreDynamicFlags) const
131*ec779b8eSAndroid Build Coastguard Worker {
132*ec779b8eSAndroid Build Coastguard Worker     return other != nullptr &&
133*ec779b8eSAndroid Build Coastguard Worker            mName.compare(other->mName) == 0 &&
134*ec779b8eSAndroid Build Coastguard Worker            mFormat == other->getFormat() &&
135*ec779b8eSAndroid Build Coastguard Worker            mChannelMasks == other->getChannels() &&
136*ec779b8eSAndroid Build Coastguard Worker            mSamplingRates == other->getSampleRates() &&
137*ec779b8eSAndroid Build Coastguard Worker            (ignoreDynamicFlags ||
138*ec779b8eSAndroid Build Coastguard Worker                (mIsDynamicFormat == other->isDynamicFormat() &&
139*ec779b8eSAndroid Build Coastguard Worker                mIsDynamicChannels == other->isDynamicChannels() &&
140*ec779b8eSAndroid Build Coastguard Worker                mIsDynamicRate == other->isDynamicRate())) &&
141*ec779b8eSAndroid Build Coastguard Worker            mEncapsulationType == other->getEncapsulationType();
142*ec779b8eSAndroid Build Coastguard Worker }
143*ec779b8eSAndroid Build Coastguard Worker 
operator =(const AudioProfile & other)144*ec779b8eSAndroid Build Coastguard Worker AudioProfile& AudioProfile::operator=(const AudioProfile& other) {
145*ec779b8eSAndroid Build Coastguard Worker     mName = other.mName;
146*ec779b8eSAndroid Build Coastguard Worker     mFormat = other.mFormat;
147*ec779b8eSAndroid Build Coastguard Worker     mChannelMasks = other.mChannelMasks;
148*ec779b8eSAndroid Build Coastguard Worker     mSamplingRates = other.mSamplingRates;
149*ec779b8eSAndroid Build Coastguard Worker     mEncapsulationType = other.mEncapsulationType;
150*ec779b8eSAndroid Build Coastguard Worker     mIsDynamicFormat = other.mIsDynamicFormat;
151*ec779b8eSAndroid Build Coastguard Worker     mIsDynamicChannels = other.mIsDynamicChannels;
152*ec779b8eSAndroid Build Coastguard Worker     mIsDynamicRate = other.mIsDynamicRate;
153*ec779b8eSAndroid Build Coastguard Worker     return *this;
154*ec779b8eSAndroid Build Coastguard Worker }
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker ConversionResult<AudioProfile::Aidl>
toParcelable(bool isInput) const157*ec779b8eSAndroid Build Coastguard Worker AudioProfile::toParcelable(bool isInput) const {
158*ec779b8eSAndroid Build Coastguard Worker     media::audio::common::AudioProfile parcelable = VALUE_OR_RETURN(toCommonParcelable(isInput));
159*ec779b8eSAndroid Build Coastguard Worker     media::AudioProfileSys parcelableSys;
160*ec779b8eSAndroid Build Coastguard Worker     parcelableSys.isDynamicFormat = mIsDynamicFormat;
161*ec779b8eSAndroid Build Coastguard Worker     parcelableSys.isDynamicChannels = mIsDynamicChannels;
162*ec779b8eSAndroid Build Coastguard Worker     parcelableSys.isDynamicRate = mIsDynamicRate;
163*ec779b8eSAndroid Build Coastguard Worker     return std::make_pair(parcelable, parcelableSys);
164*ec779b8eSAndroid Build Coastguard Worker }
165*ec779b8eSAndroid Build Coastguard Worker 
fromParcelable(const AudioProfile::Aidl & aidl,bool isInput)166*ec779b8eSAndroid Build Coastguard Worker ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
167*ec779b8eSAndroid Build Coastguard Worker         const AudioProfile::Aidl& aidl, bool isInput) {
168*ec779b8eSAndroid Build Coastguard Worker     sp<AudioProfile> legacy = VALUE_OR_RETURN(fromCommonParcelable(aidl.first, isInput));
169*ec779b8eSAndroid Build Coastguard Worker     const auto& parcelableSys = aidl.second;
170*ec779b8eSAndroid Build Coastguard Worker     legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
171*ec779b8eSAndroid Build Coastguard Worker     legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
172*ec779b8eSAndroid Build Coastguard Worker     legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
173*ec779b8eSAndroid Build Coastguard Worker     return legacy;
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker 
176*ec779b8eSAndroid Build Coastguard Worker ConversionResult<media::audio::common::AudioProfile>
toCommonParcelable(bool isInput) const177*ec779b8eSAndroid Build Coastguard Worker AudioProfile::toCommonParcelable(bool isInput) const {
178*ec779b8eSAndroid Build Coastguard Worker     media::audio::common::AudioProfile parcelable;
179*ec779b8eSAndroid Build Coastguard Worker     parcelable.name = mName;
180*ec779b8eSAndroid Build Coastguard Worker     parcelable.format = VALUE_OR_RETURN(
181*ec779b8eSAndroid Build Coastguard Worker             legacy2aidl_audio_format_t_AudioFormatDescription(mFormat));
182*ec779b8eSAndroid Build Coastguard Worker     // Note: legacy 'audio_profile' imposes a limit on the number of
183*ec779b8eSAndroid Build Coastguard Worker     // channel masks and sampling rates. That's why it's not used here
184*ec779b8eSAndroid Build Coastguard Worker     // and conversions are performed directly on the fields instead
185*ec779b8eSAndroid Build Coastguard Worker     // of using 'legacy2aidl_audio_profile_AudioProfile' from AidlConversion.
186*ec779b8eSAndroid Build Coastguard Worker     parcelable.channelMasks = VALUE_OR_RETURN(
187*ec779b8eSAndroid Build Coastguard Worker             convertContainer<std::vector<AudioChannelLayout>>(
188*ec779b8eSAndroid Build Coastguard Worker             mChannelMasks,
189*ec779b8eSAndroid Build Coastguard Worker             [isInput](audio_channel_mask_t m) {
190*ec779b8eSAndroid Build Coastguard Worker                 return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
191*ec779b8eSAndroid Build Coastguard Worker             }));
192*ec779b8eSAndroid Build Coastguard Worker     parcelable.sampleRates = VALUE_OR_RETURN(
193*ec779b8eSAndroid Build Coastguard Worker             convertContainer<std::vector<int32_t>>(mSamplingRates,
194*ec779b8eSAndroid Build Coastguard Worker                                                    convertIntegral<int32_t, uint32_t>));
195*ec779b8eSAndroid Build Coastguard Worker     parcelable.encapsulationType = VALUE_OR_RETURN(
196*ec779b8eSAndroid Build Coastguard Worker             legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(mEncapsulationType));
197*ec779b8eSAndroid Build Coastguard Worker     return parcelable;
198*ec779b8eSAndroid Build Coastguard Worker }
199*ec779b8eSAndroid Build Coastguard Worker 
fromCommonParcelable(const media::audio::common::AudioProfile & aidl,bool isInput)200*ec779b8eSAndroid Build Coastguard Worker ConversionResult<sp<AudioProfile>> AudioProfile::fromCommonParcelable(
201*ec779b8eSAndroid Build Coastguard Worker         const media::audio::common::AudioProfile& aidl, bool isInput) {
202*ec779b8eSAndroid Build Coastguard Worker     sp<AudioProfile> legacy = new AudioProfile();
203*ec779b8eSAndroid Build Coastguard Worker     legacy->mName = aidl.name;
204*ec779b8eSAndroid Build Coastguard Worker     legacy->mFormat = VALUE_OR_RETURN(
205*ec779b8eSAndroid Build Coastguard Worker             aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
206*ec779b8eSAndroid Build Coastguard Worker     legacy->mChannelMasks = VALUE_OR_RETURN(
207*ec779b8eSAndroid Build Coastguard Worker             convertContainer<ChannelMaskSet>(aidl.channelMasks,
208*ec779b8eSAndroid Build Coastguard Worker             [isInput](const AudioChannelLayout& l) {
209*ec779b8eSAndroid Build Coastguard Worker                 return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
210*ec779b8eSAndroid Build Coastguard Worker             }));
211*ec779b8eSAndroid Build Coastguard Worker     legacy->mSamplingRates = VALUE_OR_RETURN(
212*ec779b8eSAndroid Build Coastguard Worker             convertContainer<SampleRateSet>(aidl.sampleRates,
213*ec779b8eSAndroid Build Coastguard Worker                                             convertIntegral<uint32_t, int32_t>));
214*ec779b8eSAndroid Build Coastguard Worker     legacy->mEncapsulationType = VALUE_OR_RETURN(
215*ec779b8eSAndroid Build Coastguard Worker             aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
216*ec779b8eSAndroid Build Coastguard Worker                     aidl.encapsulationType));
217*ec779b8eSAndroid Build Coastguard Worker     return legacy;
218*ec779b8eSAndroid Build Coastguard Worker }
219*ec779b8eSAndroid Build Coastguard Worker 
220*ec779b8eSAndroid Build Coastguard Worker ConversionResult<sp<AudioProfile>>
aidl2legacy_AudioProfile(const AudioProfile::Aidl & aidl,bool isInput)221*ec779b8eSAndroid Build Coastguard Worker aidl2legacy_AudioProfile(const AudioProfile::Aidl& aidl, bool isInput) {
222*ec779b8eSAndroid Build Coastguard Worker     return AudioProfile::fromParcelable(aidl, isInput);
223*ec779b8eSAndroid Build Coastguard Worker }
224*ec779b8eSAndroid Build Coastguard Worker 
225*ec779b8eSAndroid Build Coastguard Worker ConversionResult<AudioProfile::Aidl>
legacy2aidl_AudioProfile(const sp<AudioProfile> & legacy,bool isInput)226*ec779b8eSAndroid Build Coastguard Worker legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput) {
227*ec779b8eSAndroid Build Coastguard Worker     return legacy->toParcelable(isInput);
228*ec779b8eSAndroid Build Coastguard Worker }
229*ec779b8eSAndroid Build Coastguard Worker 
230*ec779b8eSAndroid Build Coastguard Worker ConversionResult<sp<AudioProfile>>
aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile & aidl,bool isInput)231*ec779b8eSAndroid Build Coastguard Worker aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile& aidl, bool isInput) {
232*ec779b8eSAndroid Build Coastguard Worker     return AudioProfile::fromCommonParcelable(aidl, isInput);
233*ec779b8eSAndroid Build Coastguard Worker }
234*ec779b8eSAndroid Build Coastguard Worker 
235*ec779b8eSAndroid Build Coastguard Worker ConversionResult<media::audio::common::AudioProfile>
legacy2aidl_AudioProfile_common(const sp<AudioProfile> & legacy,bool isInput)236*ec779b8eSAndroid Build Coastguard Worker legacy2aidl_AudioProfile_common(const sp<AudioProfile>& legacy, bool isInput) {
237*ec779b8eSAndroid Build Coastguard Worker     return legacy->toCommonParcelable(isInput);
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker 
add(const sp<AudioProfile> & profile)240*ec779b8eSAndroid Build Coastguard Worker ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
241*ec779b8eSAndroid Build Coastguard Worker {
242*ec779b8eSAndroid Build Coastguard Worker     ssize_t index = size();
243*ec779b8eSAndroid Build Coastguard Worker     push_back(profile);
244*ec779b8eSAndroid Build Coastguard Worker     return index;
245*ec779b8eSAndroid Build Coastguard Worker }
246*ec779b8eSAndroid Build Coastguard Worker 
clearProfiles()247*ec779b8eSAndroid Build Coastguard Worker void AudioProfileVector::clearProfiles()
248*ec779b8eSAndroid Build Coastguard Worker {
249*ec779b8eSAndroid Build Coastguard Worker     for (auto it = begin(); it != end();) {
250*ec779b8eSAndroid Build Coastguard Worker         if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
251*ec779b8eSAndroid Build Coastguard Worker             it = erase(it);
252*ec779b8eSAndroid Build Coastguard Worker         } else {
253*ec779b8eSAndroid Build Coastguard Worker             (*it)->clear();
254*ec779b8eSAndroid Build Coastguard Worker             ++it;
255*ec779b8eSAndroid Build Coastguard Worker         }
256*ec779b8eSAndroid Build Coastguard Worker     }
257*ec779b8eSAndroid Build Coastguard Worker }
258*ec779b8eSAndroid Build Coastguard Worker 
getFirstValidProfile() const259*ec779b8eSAndroid Build Coastguard Worker sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
260*ec779b8eSAndroid Build Coastguard Worker {
261*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
262*ec779b8eSAndroid Build Coastguard Worker         if (profile->isValid()) {
263*ec779b8eSAndroid Build Coastguard Worker             return profile;
264*ec779b8eSAndroid Build Coastguard Worker         }
265*ec779b8eSAndroid Build Coastguard Worker     }
266*ec779b8eSAndroid Build Coastguard Worker     return nullptr;
267*ec779b8eSAndroid Build Coastguard Worker }
268*ec779b8eSAndroid Build Coastguard Worker 
getFirstValidProfileFor(audio_format_t format) const269*ec779b8eSAndroid Build Coastguard Worker sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
270*ec779b8eSAndroid Build Coastguard Worker {
271*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
272*ec779b8eSAndroid Build Coastguard Worker         if (profile->isValid() && profile->getFormat() == format) {
273*ec779b8eSAndroid Build Coastguard Worker             return profile;
274*ec779b8eSAndroid Build Coastguard Worker         }
275*ec779b8eSAndroid Build Coastguard Worker     }
276*ec779b8eSAndroid Build Coastguard Worker     return nullptr;
277*ec779b8eSAndroid Build Coastguard Worker }
278*ec779b8eSAndroid Build Coastguard Worker 
getSupportedFormats() const279*ec779b8eSAndroid Build Coastguard Worker FormatVector AudioProfileVector::getSupportedFormats() const
280*ec779b8eSAndroid Build Coastguard Worker {
281*ec779b8eSAndroid Build Coastguard Worker     FormatVector supportedFormats;
282*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
283*ec779b8eSAndroid Build Coastguard Worker         if (profile->hasValidFormat()) {
284*ec779b8eSAndroid Build Coastguard Worker             supportedFormats.push_back(profile->getFormat());
285*ec779b8eSAndroid Build Coastguard Worker         }
286*ec779b8eSAndroid Build Coastguard Worker     }
287*ec779b8eSAndroid Build Coastguard Worker     return supportedFormats;
288*ec779b8eSAndroid Build Coastguard Worker }
289*ec779b8eSAndroid Build Coastguard Worker 
hasDynamicChannelsFor(audio_format_t format) const290*ec779b8eSAndroid Build Coastguard Worker bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
291*ec779b8eSAndroid Build Coastguard Worker {
292*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
293*ec779b8eSAndroid Build Coastguard Worker         if (profile->getFormat() == format && profile->isDynamicChannels()) {
294*ec779b8eSAndroid Build Coastguard Worker             return true;
295*ec779b8eSAndroid Build Coastguard Worker         }
296*ec779b8eSAndroid Build Coastguard Worker     }
297*ec779b8eSAndroid Build Coastguard Worker     return false;
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker 
hasDynamicFormat() const300*ec779b8eSAndroid Build Coastguard Worker bool AudioProfileVector::hasDynamicFormat() const
301*ec779b8eSAndroid Build Coastguard Worker {
302*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
303*ec779b8eSAndroid Build Coastguard Worker         if (profile->isDynamicFormat()) {
304*ec779b8eSAndroid Build Coastguard Worker             return true;
305*ec779b8eSAndroid Build Coastguard Worker         }
306*ec779b8eSAndroid Build Coastguard Worker     }
307*ec779b8eSAndroid Build Coastguard Worker     return false;
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker 
hasDynamicProfile() const310*ec779b8eSAndroid Build Coastguard Worker bool AudioProfileVector::hasDynamicProfile() const
311*ec779b8eSAndroid Build Coastguard Worker {
312*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
313*ec779b8eSAndroid Build Coastguard Worker         if (profile->isDynamic()) {
314*ec779b8eSAndroid Build Coastguard Worker             return true;
315*ec779b8eSAndroid Build Coastguard Worker         }
316*ec779b8eSAndroid Build Coastguard Worker     }
317*ec779b8eSAndroid Build Coastguard Worker     return false;
318*ec779b8eSAndroid Build Coastguard Worker }
319*ec779b8eSAndroid Build Coastguard Worker 
hasDynamicRateFor(audio_format_t format) const320*ec779b8eSAndroid Build Coastguard Worker bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
321*ec779b8eSAndroid Build Coastguard Worker {
322*ec779b8eSAndroid Build Coastguard Worker     for (const auto &profile : *this) {
323*ec779b8eSAndroid Build Coastguard Worker         if (profile->getFormat() == format && profile->isDynamicRate()) {
324*ec779b8eSAndroid Build Coastguard Worker             return true;
325*ec779b8eSAndroid Build Coastguard Worker         }
326*ec779b8eSAndroid Build Coastguard Worker     }
327*ec779b8eSAndroid Build Coastguard Worker     return false;
328*ec779b8eSAndroid Build Coastguard Worker }
329*ec779b8eSAndroid Build Coastguard Worker 
getSampleRatesFor(audio_format_t format) const330*ec779b8eSAndroid Build Coastguard Worker const SampleRateSet AudioProfileVector::getSampleRatesFor(audio_format_t format) const {
331*ec779b8eSAndroid Build Coastguard Worker     for (const auto& profile : *this) {
332*ec779b8eSAndroid Build Coastguard Worker         if (profile->getFormat() == format) {
333*ec779b8eSAndroid Build Coastguard Worker             return profile->getSampleRates();
334*ec779b8eSAndroid Build Coastguard Worker         }
335*ec779b8eSAndroid Build Coastguard Worker     }
336*ec779b8eSAndroid Build Coastguard Worker     return {};
337*ec779b8eSAndroid Build Coastguard Worker }
338*ec779b8eSAndroid Build Coastguard Worker 
getChannelMasksFor(audio_format_t format) const339*ec779b8eSAndroid Build Coastguard Worker const ChannelMaskSet AudioProfileVector::getChannelMasksFor(audio_format_t format) const {
340*ec779b8eSAndroid Build Coastguard Worker     for (const auto& profile : *this) {
341*ec779b8eSAndroid Build Coastguard Worker         if (profile->getFormat() == format) {
342*ec779b8eSAndroid Build Coastguard Worker             return profile->getChannels();
343*ec779b8eSAndroid Build Coastguard Worker         }
344*ec779b8eSAndroid Build Coastguard Worker     }
345*ec779b8eSAndroid Build Coastguard Worker     return {};
346*ec779b8eSAndroid Build Coastguard Worker }
347*ec779b8eSAndroid Build Coastguard Worker 
contains(const sp<AudioProfile> & profile,bool ignoreDynamicFlags) const348*ec779b8eSAndroid Build Coastguard Worker bool AudioProfileVector::contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags) const
349*ec779b8eSAndroid Build Coastguard Worker {
350*ec779b8eSAndroid Build Coastguard Worker     for (const auto& audioProfile : *this) {
351*ec779b8eSAndroid Build Coastguard Worker         if (audioProfile->equals(profile, ignoreDynamicFlags)) {
352*ec779b8eSAndroid Build Coastguard Worker             return true;
353*ec779b8eSAndroid Build Coastguard Worker         }
354*ec779b8eSAndroid Build Coastguard Worker     }
355*ec779b8eSAndroid Build Coastguard Worker     return false;
356*ec779b8eSAndroid Build Coastguard Worker }
357*ec779b8eSAndroid Build Coastguard Worker 
dump(std::string * dst,int spaces) const358*ec779b8eSAndroid Build Coastguard Worker void AudioProfileVector::dump(std::string *dst, int spaces) const
359*ec779b8eSAndroid Build Coastguard Worker {
360*ec779b8eSAndroid Build Coastguard Worker     dst->append(base::StringPrintf("%*s- Profiles (%zu):\n", spaces - 2, "", size()));
361*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < size(); i++) {
362*ec779b8eSAndroid Build Coastguard Worker         const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
363*ec779b8eSAndroid Build Coastguard Worker         dst->append(prefix);
364*ec779b8eSAndroid Build Coastguard Worker         std::string profileStr;
365*ec779b8eSAndroid Build Coastguard Worker         at(i)->dump(&profileStr, prefix.size());
366*ec779b8eSAndroid Build Coastguard Worker         dst->append(profileStr);
367*ec779b8eSAndroid Build Coastguard Worker     }
368*ec779b8eSAndroid Build Coastguard Worker }
369*ec779b8eSAndroid Build Coastguard Worker 
equals(const AudioProfileVector & other) const370*ec779b8eSAndroid Build Coastguard Worker bool AudioProfileVector::equals(const AudioProfileVector& other) const
371*ec779b8eSAndroid Build Coastguard Worker {
372*ec779b8eSAndroid Build Coastguard Worker     return std::equal(begin(), end(), other.begin(), other.end(),
373*ec779b8eSAndroid Build Coastguard Worker                       [](const sp<AudioProfile>& left, const sp<AudioProfile>& right) {
374*ec779b8eSAndroid Build Coastguard Worker                           return left->equals(right);
375*ec779b8eSAndroid Build Coastguard Worker                       });
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker 
addAllValidProfiles(const AudioProfileVector & audioProfiles)378*ec779b8eSAndroid Build Coastguard Worker void AudioProfileVector::addAllValidProfiles(const AudioProfileVector& audioProfiles) {
379*ec779b8eSAndroid Build Coastguard Worker     for (const auto& audioProfile : audioProfiles) {
380*ec779b8eSAndroid Build Coastguard Worker         if (audioProfile->isValid() && !contains(audioProfile, true /*ignoreDynamicFlags*/)) {
381*ec779b8eSAndroid Build Coastguard Worker             add(audioProfile);
382*ec779b8eSAndroid Build Coastguard Worker         }
383*ec779b8eSAndroid Build Coastguard Worker     }
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker 
getSupportedChannelMasks() const386*ec779b8eSAndroid Build Coastguard Worker ChannelMaskSet AudioProfileVector::getSupportedChannelMasks() const {
387*ec779b8eSAndroid Build Coastguard Worker     ChannelMaskSet channelMasks;
388*ec779b8eSAndroid Build Coastguard Worker     for (const auto& profile : *this) {
389*ec779b8eSAndroid Build Coastguard Worker         if (profile->isValid()) {
390*ec779b8eSAndroid Build Coastguard Worker             channelMasks.insert(profile->getChannels().begin(), profile->getChannels().end());
391*ec779b8eSAndroid Build Coastguard Worker         }
392*ec779b8eSAndroid Build Coastguard Worker     }
393*ec779b8eSAndroid Build Coastguard Worker     return channelMasks;
394*ec779b8eSAndroid Build Coastguard Worker }
395*ec779b8eSAndroid Build Coastguard Worker 
396*ec779b8eSAndroid Build Coastguard Worker ConversionResult<AudioProfileVector>
aidl2legacy_AudioProfileVector(const AudioProfileVector::Aidl & aidl,bool isInput)397*ec779b8eSAndroid Build Coastguard Worker aidl2legacy_AudioProfileVector(const AudioProfileVector::Aidl& aidl, bool isInput) {
398*ec779b8eSAndroid Build Coastguard Worker     return convertContainers<AudioProfileVector>(aidl.first, aidl.second,
399*ec779b8eSAndroid Build Coastguard Worker             [isInput](const media::audio::common::AudioProfile& p,
400*ec779b8eSAndroid Build Coastguard Worker                       const media::AudioProfileSys& ps) {
401*ec779b8eSAndroid Build Coastguard Worker                 return aidl2legacy_AudioProfile(std::make_pair(p, ps), isInput);
402*ec779b8eSAndroid Build Coastguard Worker             });
403*ec779b8eSAndroid Build Coastguard Worker }
404*ec779b8eSAndroid Build Coastguard Worker 
405*ec779b8eSAndroid Build Coastguard Worker ConversionResult<AudioProfileVector::Aidl>
legacy2aidl_AudioProfileVector(const AudioProfileVector & legacy,bool isInput)406*ec779b8eSAndroid Build Coastguard Worker legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy, bool isInput) {
407*ec779b8eSAndroid Build Coastguard Worker     return convertContainerSplit<
408*ec779b8eSAndroid Build Coastguard Worker             std::vector<media::audio::common::AudioProfile>,
409*ec779b8eSAndroid Build Coastguard Worker             std::vector<media::AudioProfileSys>>(legacy,
410*ec779b8eSAndroid Build Coastguard Worker             [isInput](const sp<AudioProfile>& p) {
411*ec779b8eSAndroid Build Coastguard Worker                 return legacy2aidl_AudioProfile(p, isInput);
412*ec779b8eSAndroid Build Coastguard Worker             });
413*ec779b8eSAndroid Build Coastguard Worker }
414*ec779b8eSAndroid Build Coastguard Worker 
intersectAudioProfiles(const AudioProfileVector & profiles1,const AudioProfileVector & profiles2)415*ec779b8eSAndroid Build Coastguard Worker AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
416*ec779b8eSAndroid Build Coastguard Worker                                           const AudioProfileVector& profiles2)
417*ec779b8eSAndroid Build Coastguard Worker {
418*ec779b8eSAndroid Build Coastguard Worker     std::map<audio_format_t, std::pair<ChannelMaskSet, SampleRateSet>> infos2;
419*ec779b8eSAndroid Build Coastguard Worker     for (const auto& profile : profiles2) {
420*ec779b8eSAndroid Build Coastguard Worker         infos2.emplace(profile->getFormat(),
421*ec779b8eSAndroid Build Coastguard Worker                 std::make_pair(profile->getChannels(), profile->getSampleRates()));
422*ec779b8eSAndroid Build Coastguard Worker     }
423*ec779b8eSAndroid Build Coastguard Worker     AudioProfileVector profiles;
424*ec779b8eSAndroid Build Coastguard Worker     for (const auto& profile : profiles1) {
425*ec779b8eSAndroid Build Coastguard Worker         const auto it = infos2.find(profile->getFormat());
426*ec779b8eSAndroid Build Coastguard Worker         if (it == infos2.end()) {
427*ec779b8eSAndroid Build Coastguard Worker             continue;
428*ec779b8eSAndroid Build Coastguard Worker         }
429*ec779b8eSAndroid Build Coastguard Worker         ChannelMaskSet channelMasks = SetIntersection(profile->getChannels(), it->second.first);
430*ec779b8eSAndroid Build Coastguard Worker         if (channelMasks.empty()) {
431*ec779b8eSAndroid Build Coastguard Worker             continue;
432*ec779b8eSAndroid Build Coastguard Worker         }
433*ec779b8eSAndroid Build Coastguard Worker         SampleRateSet sampleRates = SetIntersection(profile->getSampleRates(), it->second.second);
434*ec779b8eSAndroid Build Coastguard Worker         if (sampleRates.empty()) {
435*ec779b8eSAndroid Build Coastguard Worker             continue;
436*ec779b8eSAndroid Build Coastguard Worker         }
437*ec779b8eSAndroid Build Coastguard Worker         profiles.push_back(new AudioProfile(profile->getFormat(), channelMasks, sampleRates));
438*ec779b8eSAndroid Build Coastguard Worker     }
439*ec779b8eSAndroid Build Coastguard Worker     return profiles;
440*ec779b8eSAndroid Build Coastguard Worker }
441*ec779b8eSAndroid Build Coastguard Worker 
442*ec779b8eSAndroid Build Coastguard Worker } // namespace android
443