• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef AUDIO_DEVICE_STREAM_INFO_H
16 #define AUDIO_DEVICE_STREAM_INFO_H
17 
18 #include <parcel.h>
19 #include <set>
20 #include <limits>
21 #include <unordered_set>
22 #include <sstream>
23 #include <list>
24 #include <vector>
25 #include "securec.h"
26 #include <audio_stream_info.h>
27 
28 namespace OHOS {
29 namespace AudioStandard {
30 constexpr size_t AUDIO_DEVICE_INFO_SIZE_LIMIT = 30;
31 
MarshallingSetInt32(const std::set<T> & value,Parcel & parcel)32 template<typename T> bool MarshallingSetInt32(const std::set<T> &value, Parcel &parcel)
33 {
34     size_t size = value.size();
35     if (!parcel.WriteUint64(size)) {
36         return false;
37     }
38     for (const auto &i : value) {
39         if (!parcel.WriteInt32(i)) {
40             return false;
41         }
42     }
43     return true;
44 }
45 
46 template<typename T> std::set<T> UnmarshallingSetInt32(Parcel &parcel,
47     const size_t maxSize = std::numeric_limits<size_t>::max())
48 {
49     size_t size = parcel.ReadUint64();
50     // due to security concerns, sizelimit has been imposed
51     if (size > maxSize) {
52         size = maxSize;
53     }
54 
55     std::set<T> res;
56     for (size_t i = 0; i < size; i++) {
57         res.insert(static_cast<T>(parcel.ReadInt32()));
58     }
59     return res;
60 }
61 
MarshallingSetInt64(const std::set<T> & value,Parcel & parcel)62 template<typename T> bool MarshallingSetInt64(const std::set<T> &value, Parcel &parcel)
63 {
64     size_t size = value.size();
65     if (!parcel.WriteUint64(size)) {
66         return false;
67     }
68     for (const auto &i : value) {
69         if (!parcel.WriteInt64(i)) {
70             return false;
71         }
72     }
73     return true;
74 }
75 
76 template<typename T> std::set<T> UnmarshallingSetInt64(Parcel &parcel,
77     const size_t maxSize = std::numeric_limits<size_t>::max())
78 {
79     size_t size = parcel.ReadUint64();
80     // due to security concerns, sizelimit has been imposed
81     if (size > maxSize) {
82         size = maxSize;
83     }
84 
85     std::set<T> res;
86     for (size_t i = 0; i < size; i++) {
87         res.insert(static_cast<T>(parcel.ReadInt64()));
88     }
89     return res;
90 }
91 
ConvertLayoutToAudioChannel(AudioChannelLayout layout)92 static AudioChannel ConvertLayoutToAudioChannel(AudioChannelLayout layout)
93 {
94     AudioChannel channel = AudioChannel::CHANNEL_UNKNOW;
95     switch (layout) {
96         case AudioChannelLayout::CH_LAYOUT_MONO:
97             channel = AudioChannel::MONO;
98             break;
99         case AudioChannelLayout::CH_LAYOUT_STEREO:
100             channel = AudioChannel::STEREO;
101             break;
102         case AudioChannelLayout::CH_LAYOUT_2POINT1:
103         case AudioChannelLayout::CH_LAYOUT_3POINT0:
104             channel = AudioChannel::CHANNEL_3;
105             break;
106         case AudioChannelLayout::CH_LAYOUT_3POINT1:
107         case AudioChannelLayout::CH_LAYOUT_4POINT0:
108         case AudioChannelLayout::CH_LAYOUT_QUAD:
109             channel = AudioChannel::CHANNEL_4;
110             break;
111         case AudioChannelLayout::CH_LAYOUT_5POINT0:
112         case AudioChannelLayout::CH_LAYOUT_2POINT1POINT2:
113             channel = AudioChannel::CHANNEL_5;
114             break;
115         case AudioChannelLayout::CH_LAYOUT_5POINT1:
116         case AudioChannelLayout::CH_LAYOUT_HEXAGONAL:
117         case AudioChannelLayout::CH_LAYOUT_3POINT1POINT2:
118             channel = AudioChannel::CHANNEL_6;
119             break;
120         case AudioChannelLayout::CH_LAYOUT_7POINT0:
121             channel = AudioChannel::CHANNEL_7;
122             break;
123         case AudioChannelLayout::CH_LAYOUT_7POINT1:
124             channel = AudioChannel::CHANNEL_8;
125             break;
126         case AudioChannelLayout::CH_LAYOUT_7POINT1POINT2:
127             channel = AudioChannel::CHANNEL_10;
128             break;
129         case AudioChannelLayout::CH_LAYOUT_7POINT1POINT4:
130             channel = AudioChannel::CHANNEL_12;
131             break;
132         default:
133             channel = AudioChannel::CHANNEL_UNKNOW;
134             break;
135     }
136     return channel;
137 }
138 
ConvertAudioChannelToLayout(AudioChannel channel)139 static AudioChannelLayout ConvertAudioChannelToLayout(AudioChannel channel)
140 {
141     AudioChannelLayout channelLayout = AudioChannelLayout::CH_LAYOUT_UNKNOWN;
142 
143     switch (channel) {
144         case AudioChannel::MONO:
145             channelLayout = AudioChannelLayout::CH_LAYOUT_MONO;
146             break;
147         case AudioChannel::STEREO:
148             channelLayout = AudioChannelLayout::CH_LAYOUT_STEREO;
149             break;
150         case AudioChannel::CHANNEL_3:
151             channelLayout = AudioChannelLayout::CH_LAYOUT_2POINT1;
152             break;
153         case AudioChannel::CHANNEL_4:
154             channelLayout = AudioChannelLayout::CH_LAYOUT_3POINT1;
155             break;
156         case AudioChannel::CHANNEL_5:
157             channelLayout = AudioChannelLayout::CH_LAYOUT_2POINT1POINT2;
158             break;
159         case AudioChannel::CHANNEL_6:
160             channelLayout = AudioChannelLayout::CH_LAYOUT_5POINT1;
161             break;
162         case AudioChannel::CHANNEL_7:
163             channelLayout = AudioChannelLayout::CH_LAYOUT_7POINT0;
164             break;
165         case AudioChannel::CHANNEL_8:
166             channelLayout = AudioChannelLayout::CH_LAYOUT_7POINT1;
167             break;
168         case AudioChannel::CHANNEL_10:
169             channelLayout = AudioChannelLayout::CH_LAYOUT_7POINT1POINT2;
170             break;
171         case AudioChannel::CHANNEL_12:
172             channelLayout = AudioChannelLayout::CH_LAYOUT_7POINT1POINT4;
173             break;
174         default:
175             channelLayout = AudioChannelLayout::CH_LAYOUT_UNKNOWN;
176             break;
177     }
178 
179     return channelLayout;
180 }
181 
SplitStr(const std::string & str,const char delimiter)182 static std::vector<std::string> SplitStr(const std::string &str, const char delimiter)
183 {
184     std::vector<std::string> res;
185     std::istringstream iss(str);
186     std::string item;
187     while (getline(iss, item, delimiter)) {
188         res.push_back(item);
189     }
190     return res;
191 }
192 
193 struct DeviceStreamInfo {
194     AudioEncodingType encoding = AudioEncodingType::ENCODING_PCM;
195     AudioSampleFormat format = AudioSampleFormat::INVALID_WIDTH;
196     std::set<AudioChannelLayout> channelLayout;
197     std::set<AudioSamplingRate> samplingRate;
198 
DeviceStreamInfoDeviceStreamInfo199     DeviceStreamInfo(AudioSamplingRate samplingRate_, AudioEncodingType encoding_, AudioSampleFormat format_,
200         AudioChannelLayout channelLayout_)
201         : encoding(encoding_), format(format_), channelLayout({channelLayout_}), samplingRate({samplingRate_})
202     {}
DeviceStreamInfoDeviceStreamInfo203     DeviceStreamInfo(AudioSamplingRate samplingRate_, AudioEncodingType encoding_, AudioSampleFormat format_,
204         AudioChannel channels_) : DeviceStreamInfo(samplingRate_, encoding_, format_,
205         ConvertAudioChannelToLayout(channels_))
206     {}
DeviceStreamInfoDeviceStreamInfo207     DeviceStreamInfo(AudioStreamInfo audioStreamInfo) : DeviceStreamInfo(audioStreamInfo.samplingRate,
208         audioStreamInfo.encoding, audioStreamInfo.format, ConvertAudioChannelToLayout(audioStreamInfo.channels))
209     {}
210     DeviceStreamInfo() = default;
211 
GetChannelsDeviceStreamInfo212     std::set<AudioChannel> GetChannels() const
213     {
214         std::set<AudioChannel> channels;
215         for (const auto &layout : channelLayout) {
216             channels.insert(ConvertLayoutToAudioChannel(layout));
217         }
218         return channels;
219     }
220 
221     // warning: force set default channelLayout by channel
SetChannelsDeviceStreamInfo222     void SetChannels(const std::set<AudioChannel> &channels)
223     {
224         channelLayout.clear();
225         for (const auto &channel : channels) {
226             channelLayout.insert(ConvertAudioChannelToLayout(channel));
227         }
228     }
229 
MarshallingDeviceStreamInfo230     bool Marshalling(Parcel &parcel) const
231     {
232         return parcel.WriteInt32(static_cast<int32_t>(encoding))
233             && parcel.WriteInt32(static_cast<int32_t>(format))
234             && MarshallingSetInt32(samplingRate, parcel)
235             && MarshallingSetInt64(channelLayout, parcel);
236     }
UnmarshallingDeviceStreamInfo237     void Unmarshalling(Parcel &parcel)
238     {
239         encoding = static_cast<AudioEncodingType>(parcel.ReadInt32());
240         format = static_cast<AudioSampleFormat>(parcel.ReadInt32());
241         samplingRate = UnmarshallingSetInt32<AudioSamplingRate>(parcel, AUDIO_DEVICE_INFO_SIZE_LIMIT);
242         channelLayout = UnmarshallingSetInt64<AudioChannelLayout>(parcel, AUDIO_DEVICE_INFO_SIZE_LIMIT);
243     }
244 
SerializeListDeviceStreamInfo245     static std::string SerializeList(const std::list<DeviceStreamInfo> &streamInfoList)
246     {
247         std::string res;
248         bool isFirst = true;
249         for (const auto &streamInfo : streamInfoList) {
250             std::string infoStr = streamInfo.Serialize();
251             if (!isFirst) {
252                 res.append("-");
253             }
254             res.append(infoStr);
255             isFirst = false;
256         }
257         return res;
258     }
259 
DeserializeListDeviceStreamInfo260     static std::list<DeviceStreamInfo> DeserializeList(const std::string &data)
261     {
262         std::list<DeviceStreamInfo> res;
263         std::vector<std::string> strList = SplitStr(data, '-');
264         for (const auto &str : strList) {
265             DeviceStreamInfo streamInfo;
266             streamInfo.Deserialize(str);
267             res.push_back(streamInfo);
268         }
269         return res;
270     }
271 
SerializeDeviceStreamInfo272     std::string Serialize() const
273     {
274         std::stringstream ss;
275         ss << std::to_string(encoding) << "," << std::to_string(format) << ",";
276         bool isFirst = true;
277         for (const auto &item : samplingRate) {
278             if (!isFirst) {
279                 ss << ":";
280             }
281             ss << std::to_string(item);
282             isFirst = false;
283         }
284         ss << ",";
285         isFirst = true;
286         for (const auto &item : channelLayout) {
287             if (!isFirst) {
288                 ss << ":";
289             }
290             ss << std::to_string(item);
291             isFirst = false;
292         }
293         return ss.str();
294     }
295 
DeserializeDeviceStreamInfo296     void Deserialize(const std::string &data)
297     {
298         std::vector<std::string> strList = SplitStr(data, ',');
299         if (strList.size() != 4) { // 4: member num
300             return;
301         }
302         encoding = static_cast<AudioEncodingType>(std::stoi(strList[0])); // 0: encoding
303         format = static_cast<AudioSampleFormat>(std::stoi(strList[1])); // 1: format
304         std::vector<std::string> rateList = SplitStr(strList[2], ':'); // 2: sampling rate
305         for (const auto &str : rateList) {
306             samplingRate.insert(static_cast<AudioSamplingRate>(std::stoi(str)));
307         }
308         std::vector<std::string> layoutList = SplitStr(strList[3], ':'); // 3: channel layout
309         for (const auto &str : layoutList) {
310             channelLayout.insert(static_cast<AudioChannelLayout>(std::stoll(str)));
311         }
312     }
313 
314     bool operator==(const DeviceStreamInfo& info) const
315     {
316         return encoding == info.encoding && format == info.format &&
317             channelLayout == info.channelLayout && samplingRate == info.samplingRate;
318     }
319 
CheckParamsDeviceStreamInfo320     bool CheckParams()
321     {
322         if (samplingRate.size() == 0) {
323             return false;
324         }
325         if (channelLayout.size() == 0) {
326             return false;
327         }
328         return true;
329     }
330 };
331 } // namespace AudioStandard
332 } // namespace OHOS
333 #endif // AUDIO_DEVICE_STREAM_INFO_H