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