1 /*
2  * Copyright (C) 2022 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 
16 #include "recorder_profiles_xml_parser.h"
17 #include "media_errors.h"
18 #include "media_log.h"
19 #include "string_ex.h"
20 
21 namespace {
22     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_RECORDER, "RecorderProfilesXmlParser"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 enum class ProfileSourceType : int32_t {
28     PORFILE_SOURCE_CAMERA_RECORDER = 0,
29     PORFILE_SOURCE_VIRTUAL_DISPLAY,
30 };
31 
32 const std::vector<std::string> MP4_VIDEO_CODEC_VECTOR = {
33     "video/mp4v-es",
34     "video/avc",
35 };
36 
37 const std::vector<std::string> MP4_AUDIO_CODEC_VECTOR = {
38     "audio/mp4a-latm",
39 };
40 
41 const std::vector<std::string> M4A_AUDIO_CODEC_VECTOR = {
42     "audio/mp4a-latm",
43 };
44 
45 const std::unordered_map<std::string, std::vector<std::string>> CONTAINER_VIDEOCAPS_VIDEO_MAP = {
46     {"mp4", MP4_VIDEO_CODEC_VECTOR},
47 };
48 
49 const std::unordered_map<std::string, std::vector<std::string>> CONTAINER_VIDEOCAPS_AUDIO_MAP = {
50     {"mp4", MP4_AUDIO_CODEC_VECTOR},
51 };
52 
53 const std::unordered_map<std::string, std::vector<std::string>> CONTAINER_AUDIOCAPS_AUDIO_MAP = {
54     {"m4a", M4A_AUDIO_CODEC_VECTOR},
55 };
56 
57 const std::unordered_map<std::string, int> SOURCE_TYPE_MAP = {
58     {"CameraRecorder", static_cast<int>(ProfileSourceType::PORFILE_SOURCE_CAMERA_RECORDER)},
59     {"VirtualDisplay", static_cast<int>(ProfileSourceType::PORFILE_SOURCE_VIRTUAL_DISPLAY)},
60 };
61 
62 const std::unordered_map<std::string, std::string> SOURCE_TYPE_ID_MAP = {
63     {"CameraRecorder", "cameraId"},
64     {"VirtualDisplay", "displayId"},
65 };
66 
67 const std::unordered_map<std::string, int> PROFILE_QUALITY_MAP = {
68     {"low", RECORDER_QUALITY_LOW},
69     {"high", RECORDER_QUALITY_HIGH},
70     {"qcif", RECORDER_QUALITY_QCIF},
71     {"cif", RECORDER_QUALITY_CIF},
72     {"480p", RECORDER_QUALITY_480P},
73     {"720p", RECORDER_QUALITY_720P},
74     {"1080p", RECORDER_QUALITY_1080P},
75     {"qvga", RECORDER_QUALITY_QVGA},
76     {"2160p", RECORDER_QUALITY_2160P},
77     {"timelapse_low", RECORDER_QUALITY_TIME_LAPSE_LOW},
78     {"timelapse_high", RECORDER_QUALITY_TIME_LAPSE_HIGH},
79     {"timelapse_qcif", RECORDER_QUALITY_TIME_LAPSE_QCIF},
80     {"timelapse_cif", RECORDER_QUALITY_TIME_LAPSE_CIF},
81     {"timelapse_480p", RECORDER_QUALITY_TIME_LAPSE_480P},
82     {"timelapse_720p", RECORDER_QUALITY_TIME_LAPSE_720P},
83     {"timelapse_1080p", RECORDER_QUALITY_TIME_LAPSE_1080P},
84     {"timelapse_qvga", RECORDER_QUALITY_TIME_LAPSE_QVGA},
85     {"timelapse_2160p", RECORDER_QUALITY_TIME_LAPSE_2160P},
86     {"highspeed_low", RECORDER_QUALITY_HIGH_SPEED_LOW},
87     {"highspeed_high", RECORDER_QUALITY_HIGH_SPEED_HIGH},
88     {"highspeed_480p", RECORDER_QUALITY_HIGH_SPEED_480P},
89     {"highspeed_720p", RECORDER_QUALITY_HIGH_SPEED_720P},
90     {"highspeed_1080p", RECORDER_QUALITY_HIGH_SPEED_1080P},
91 };
92 
RecorderProfilesXmlParser()93 RecorderProfilesXmlParser::RecorderProfilesXmlParser()
94 {
95     capabilityKeys_ = {"format", "codecMime", "bitrate", "width", "height", "frameRate",
96         "sampleRate", "channels", "quality", "duration", "name", "hasVideo"};
97     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
98 }
99 
~RecorderProfilesXmlParser()100 RecorderProfilesXmlParser::~RecorderProfilesXmlParser()
101 {
102     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
103 }
104 
ParseInternal(xmlNode * node)105 bool RecorderProfilesXmlParser::ParseInternal(xmlNode *node)
106 {
107     containerFormatArray_.clear();
108     videoEncoderCapsArray_.clear();
109     audioEncoderCapsArray_.clear();
110     capabilityDataArray_.clear();
111 
112     xmlNode *currNode = node;
113     for (; currNode != nullptr; currNode = currNode->next) {
114         if (currNode->type == XML_ELEMENT_NODE) {
115             switch (GetNodeNameAsInt(currNode)) {
116                 case RecorderProfilesNodeName::RECORDER_CAPS: {
117                     ParseRecorderCapsData(currNode);
118                     break;
119                 }
120                 case RecorderProfilesNodeName::RECORDER_PROFILES: {
121                     ParseRecorderProfilesData(currNode);
122                     break;
123                 }
124                 default: {
125                     ParseInternal(currNode->children);
126                     break;
127                 }
128             }
129         }
130     }
131     return true;
132 }
133 
SetCapabilityIntData(std::unordered_map<std::string,int32_t &> dataMap,const std::string & capabilityKey,const std::string & capabilityValue) const134 bool RecorderProfilesXmlParser::SetCapabilityIntData(std::unordered_map<std::string, int32_t&> dataMap,
135     const std::string &capabilityKey, const std::string &capabilityValue) const
136 {
137     if (PROFILE_QUALITY_MAP.find(capabilityValue) != PROFILE_QUALITY_MAP.end()) {
138         dataMap.at(capabilityKey) = PROFILE_QUALITY_MAP.at(capabilityValue);
139     } else {
140         int32_t value = 0;
141         if (!StrToInt(capabilityValue, value)) {
142             MEDIA_LOGE("call StrToInt func false, input str is: %{public}s", capabilityValue.c_str());
143             return false;
144         }
145         dataMap.at(capabilityKey) = value;
146     }
147     return true;
148 }
149 
SetCapabilityVectorData(std::unordered_map<std::string,std::vector<int32_t> &> dataMap,const std::string & capabilityKey,const std::string & capabilityValue) const150 bool RecorderProfilesXmlParser::SetCapabilityVectorData(std::unordered_map<std::string, std::vector<int32_t>&> dataMap,
151     const std::string &capabilityKey, const std::string &capabilityValue) const
152 {
153     std::vector<std::string> spilt;
154     std::vector<int32_t> array;
155     bool ret = SpiltKeyList(capabilityValue, ",", spilt);
156     CHECK_AND_RETURN_RET_LOG(ret != false, false, "failed:can not split %{public}s", capabilityValue.c_str());
157     if (spilt.size() > 0) {
158         if (XmlParser::IsNumberArray(spilt)) {
159             array = TransStrAsIntegerArray(spilt);
160         } else {
161             MEDIA_LOGE("The value of %{public}s in the configuration file is incorrect.", capabilityValue.c_str());
162             return false;
163         }
164         dataMap.at(capabilityKey) = array;
165     }
166     MEDIA_LOGD("RecorderProfilesXmlParser::SetCapabilityVectorData end");
167     return true;
168 }
169 
ParseRecorderCapsData(xmlNode * node)170 bool RecorderProfilesXmlParser::ParseRecorderCapsData(xmlNode *node)
171 {
172     xmlNode *child = node->xmlChildrenNode;
173 
174     for (; child; child = child->next) {
175         if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("ContainerFormat")) == 0) {
176             bool ret = ParseRecorderContainerFormatData(child);
177             CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseRecorderContainerFormatData failed");
178         } else if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("VideoEncoderCaps")) == 0) {
179             bool ret = ParseRecorderEncodeCapsData(child, true);
180             CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseRecorderEncodeCapsData failed");
181         } else if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("AudioEncoderCaps")) == 0) {
182             bool ret = ParseRecorderEncodeCapsData(child, false);
183             CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseRecorderEncodeCapsData failed");
184         } else {
185             MEDIA_LOGE("not found node!");
186         }
187     }
188     PackageRecorderCaps();
189     MEDIA_LOGD("RecorderProfilesXmlParser::ParseRecorderCapsData end");
190     return true;
191 }
192 
ParseRecorderContainerFormatData(xmlNode * node)193 bool RecorderProfilesXmlParser::ParseRecorderContainerFormatData(xmlNode *node)
194 {
195     ContainerFormatInfo containerFormatInfo;
196 
197     for (auto it = capabilityKeys_.begin(); it != capabilityKeys_.end(); it++) {
198         std::string capabilityValue;
199         if (xmlHasProp(node, reinterpret_cast<xmlChar*>(const_cast<char*>((*it).c_str())))) {
200             capabilityValue = std::string(reinterpret_cast<char*>(xmlGetProp(node,
201                 reinterpret_cast<xmlChar*>(const_cast<char*>((*it).c_str())))));
202             bool ret = SetContainerFormat(containerFormatInfo, (*it), capabilityValue);
203             CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetContainerFormat failed");
204         }
205     }
206     containerFormatArray_.emplace_back(containerFormatInfo);
207     MEDIA_LOGD("RecorderProfilesXmlParser::ParseRecorderContainerFormatData end");
208     return true;
209 }
210 
ParseRecorderEncodeCapsData(xmlNode * node,bool isVideo)211 bool RecorderProfilesXmlParser::ParseRecorderEncodeCapsData(xmlNode *node, bool isVideo)
212 {
213     RecorderProfilesData capabilityData;
214 
215     for (auto it = capabilityKeys_.begin(); it != capabilityKeys_.end(); it++) {
216         std::string capabilityValue;
217         if (xmlHasProp(node, reinterpret_cast<xmlChar*>(const_cast<char*>((*it).c_str())))) {
218             capabilityValue = std::string(reinterpret_cast<char*>(xmlGetProp(node,
219                 reinterpret_cast<xmlChar*>(const_cast<char*>((*it).c_str())))));
220             bool ret = false;
221             if (isVideo) {
222                 ret = SetVideoRecorderCaps(capabilityData, (*it), capabilityValue);
223                 CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetVideoRecorderCaps failed");
224             } else {
225                 ret = SetAudioRecorderCaps(capabilityData, (*it), capabilityValue);
226                 CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetAudioRecorderCaps failed");
227             }
228         }
229     }
230 
231     if (isVideo) {
232         videoEncoderCapsArray_.emplace_back(capabilityData);
233     } else {
234         audioEncoderCapsArray_.emplace_back(capabilityData);
235     }
236     MEDIA_LOGD("RecorderProfilesXmlParser::ParseRecorderEncodeCapsData end");
237     return true;
238 }
239 
SetContainerFormat(ContainerFormatInfo & data,const std::string & capabilityKey,const std::string & capabilityValue)240 bool RecorderProfilesXmlParser::SetContainerFormat(ContainerFormatInfo &data, const std::string &capabilityKey,
241                                                    const std::string &capabilityValue)
242 {
243     std::unordered_map<std::string, std::string&> capabilityStringMap = {
244         {"name", data.name}, {"hasVideo", data.hasVideo}};
245 
246     bool ret = false;
247     if (capabilityStringMap.find(capabilityKey) != capabilityStringMap.end()) {
248         ret = SetCapabilityStringData(capabilityStringMap, capabilityKey, capabilityValue);
249         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityStringData failed");
250     } else {
251         CHECK_AND_RETURN_RET_LOG(ret != false, false, "can not find capabilityKey: %{public}s", capabilityKey.c_str());
252     }
253     MEDIA_LOGD("RecorderProfilesXmlParser::SetContainerFormat end");
254     return true;
255 }
256 
SetVideoRecorderCaps(RecorderProfilesData & data,const std::string & capabilityKey,const std::string & capabilityValue)257 bool RecorderProfilesXmlParser::SetVideoRecorderCaps(RecorderProfilesData &data, const std::string &capabilityKey,
258                                                      const std::string &capabilityValue)
259 {
260     std::unordered_map<std::string, std::string&> capabilityStringMap = {
261         {"codecMime", data.videoCaps.videoEncoderMime}};
262 
263     std::unordered_map<std::string, Range&> capabilityRangeMap = {
264         {"bitrate", data.videoCaps.videoBitrateRange}, {"width", data.videoCaps.videoWidthRange},
265         {"height", data.videoCaps.videoHeightRange}, {"frameRate", data.videoCaps.videoFramerateRange}};
266 
267     bool ret = false;
268     if (capabilityStringMap.find(capabilityKey) != capabilityStringMap.end()) {
269         ret = SetCapabilityStringData(capabilityStringMap, capabilityKey, capabilityValue);
270         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityStringData failed");
271     } else if (capabilityRangeMap.find(capabilityKey) != capabilityRangeMap.end()) {
272         ret = SetCapabilityRangeData(capabilityRangeMap, capabilityKey, capabilityValue);
273         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityRangeData failed");
274     } else {
275         CHECK_AND_RETURN_RET_LOG(ret != false, false, "can not find capabilityKey: %{public}s", capabilityKey.c_str());
276     }
277     MEDIA_LOGD("RecorderProfilesXmlParser::SetVideoRecorderCaps end");
278     return true;
279 }
280 
SetAudioRecorderCaps(RecorderProfilesData & data,const std::string & capabilityKey,const std::string & capabilityValue)281 bool RecorderProfilesXmlParser::SetAudioRecorderCaps(RecorderProfilesData &data, const std::string &capabilityKey,
282                                                      const std::string &capabilityValue)
283 {
284     std::unordered_map<std::string, std::string&> capabilityStringMap = {
285         {"codecMime", data.audioCaps.mimeType}};
286 
287     std::unordered_map<std::string, Range&> capabilityRangeMap = {
288         {"bitrate", data.audioCaps.bitrate}, {"channels", data.audioCaps.channels}};
289 
290     std::unordered_map<std::string, std::vector<int32_t>&> capabilityVectorMap = {
291         {"sampleRate", data.audioCaps.sampleRate}};
292 
293     bool ret = false;
294     if (capabilityStringMap.find(capabilityKey) != capabilityStringMap.end()) {
295         ret = SetCapabilityStringData(capabilityStringMap, capabilityKey, capabilityValue);
296         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityStringData failed");
297     } else if (capabilityRangeMap.find(capabilityKey) != capabilityRangeMap.end()) {
298         ret = SetCapabilityRangeData(capabilityRangeMap, capabilityKey, capabilityValue);
299         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityRangeData failed");
300     } else if (capabilityVectorMap.find(capabilityKey) != capabilityVectorMap.end()) {
301         ret = SetCapabilityVectorData(capabilityVectorMap, capabilityKey, capabilityValue);
302         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityVectorData failed");
303     } else {
304         CHECK_AND_RETURN_RET_LOG(ret != false, false, "can not find capabilityKey: %{public}s", capabilityKey.c_str());
305     }
306     MEDIA_LOGD("RecorderProfilesXmlParser::SetAudioRecorderCaps end");
307     return true;
308 }
309 
PackageRecorderCaps()310 void RecorderProfilesXmlParser::PackageRecorderCaps()
311 {
312     for (auto it = containerFormatArray_.begin(); it != containerFormatArray_.end(); it++) {
313         if ((*it).hasVideo == "true") {
314             PackageVideoRecorderCaps((*it).name);
315         } else {
316             PackageAudioRecorderCaps((*it).name);
317         }
318     }
319     MEDIA_LOGD("RecorderProfilesXmlParser::PackageRecorderCaps end");
320 }
321 
PackageVideoRecorderCaps(const std::string & formatType)322 void RecorderProfilesXmlParser::PackageVideoRecorderCaps(const std::string &formatType)
323 {
324     if ((CONTAINER_VIDEOCAPS_VIDEO_MAP.find(formatType) == CONTAINER_VIDEOCAPS_VIDEO_MAP.end()) ||
325         (CONTAINER_VIDEOCAPS_AUDIO_MAP.find(formatType) == CONTAINER_VIDEOCAPS_AUDIO_MAP.end())) {
326         MEDIA_LOGE("formatType not found in CONTAINER_VIDEOCAPS_VIDEO_MAP or CONTAINER_VIDEOCAPS_AUDIO_MAP");
327         return;
328     }
329     for (auto itVideo = videoEncoderCapsArray_.begin(); itVideo != videoEncoderCapsArray_.end(); itVideo++) {
330         (*itVideo).mediaProfileType = RECORDER_TYPE_VIDEO_CAPS;
331         (*itVideo).videoCaps.containerFormatType = formatType;
332         auto itVideoCodec = find(CONTAINER_VIDEOCAPS_VIDEO_MAP.at(formatType).begin(),
333             CONTAINER_VIDEOCAPS_VIDEO_MAP.at(formatType).end(), (*itVideo).videoCaps.videoEncoderMime);
334         if (itVideoCodec != CONTAINER_VIDEOCAPS_VIDEO_MAP.at(formatType).end()) {
335             PaddingVideoCapsByAudioCaps(formatType, (*itVideo));
336         }
337     }
338     MEDIA_LOGD("RecorderProfilesXmlParser::PackageVideoRecorderCaps end");
339 }
340 
PaddingVideoCapsByAudioCaps(const std::string & formatType,RecorderProfilesData & videoData)341 void RecorderProfilesXmlParser::PaddingVideoCapsByAudioCaps(
342     const std::string &formatType, RecorderProfilesData &videoData)
343 {
344     for (auto itAudio = audioEncoderCapsArray_.begin(); itAudio != audioEncoderCapsArray_.end(); itAudio++) {
345         auto itAudioCodec = find(CONTAINER_VIDEOCAPS_AUDIO_MAP.at(formatType).begin(),
346             CONTAINER_VIDEOCAPS_AUDIO_MAP.at(formatType).end(), (*itAudio).audioCaps.mimeType);
347         if (itAudioCodec != CONTAINER_VIDEOCAPS_AUDIO_MAP.at(formatType).end()) {
348             videoData.videoCaps.audioEncoderMime = (*itAudio).audioCaps.mimeType;
349             videoData.videoCaps.audioBitrateRange = (*itAudio).audioCaps.bitrate;
350             videoData.videoCaps.audioSampleRates = (*itAudio).audioCaps.sampleRate;
351             videoData.videoCaps.audioChannelRange = (*itAudio).audioCaps.channels;
352             capabilityDataArray_.emplace_back(videoData);
353         }
354     }
355     MEDIA_LOGD("RecorderProfilesXmlParser::PaddingVideoCapsByAudioCaps end");
356 }
357 
PackageAudioRecorderCaps(const std::string & formatType)358 void RecorderProfilesXmlParser::PackageAudioRecorderCaps(const std::string &formatType)
359 {
360     if (CONTAINER_AUDIOCAPS_AUDIO_MAP.find(formatType) == CONTAINER_AUDIOCAPS_AUDIO_MAP.end()) {
361         MEDIA_LOGE("formatType not found in CONTAINER_AUDIOCAPS_AUDIO_MAP");
362         return;
363     }
364     for (auto itAudio = audioEncoderCapsArray_.begin(); itAudio != audioEncoderCapsArray_.end(); itAudio++) {
365         (*itAudio).mediaProfileType = RECORDER_TYPE_AUDIO_CAPS;
366         (*itAudio).audioCaps.containerFormatType = formatType;
367         auto itAudioCodec = find(CONTAINER_AUDIOCAPS_AUDIO_MAP.at(formatType).begin(),
368             CONTAINER_AUDIOCAPS_AUDIO_MAP.at(formatType).end(), (*itAudio).audioCaps.mimeType);
369         if (itAudioCodec != CONTAINER_AUDIOCAPS_AUDIO_MAP.at(formatType).end()) {
370             capabilityDataArray_.emplace_back(*itAudio);
371         }
372     }
373     MEDIA_LOGD("RecorderProfilesXmlParser::PackageAudioRecorderCaps end");
374 }
375 
ParseRecorderProfilesData(xmlNode * node)376 bool RecorderProfilesXmlParser::ParseRecorderProfilesData(xmlNode *node)
377 {
378     xmlNode *child = node->xmlChildrenNode;
379 
380     for (; child; child = child->next) {
381         for (auto it = SOURCE_TYPE_ID_MAP.begin(); it != SOURCE_TYPE_ID_MAP.end(); it++) {
382             bool ret = ParseRecorderProfilesSourceData(it->first, child);
383             CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseRecorderProfilesSourceData failed");
384         }
385     }
386     MEDIA_LOGD("RecorderProfilesXmlParser::ParseRecorderProfilesData end");
387     return true;
388 }
389 
ParseRecorderProfilesSourceData(const std::string & sourceType,xmlNode * node)390 bool RecorderProfilesXmlParser::ParseRecorderProfilesSourceData(const std::string &sourceType, xmlNode *node)
391 {
392     if (xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>(sourceType.c_str())) == 0) {
393         std::string property = SOURCE_TYPE_ID_MAP.at(sourceType);
394         if (xmlHasProp(node, reinterpret_cast<xmlChar*>(const_cast<char*>(property.c_str())))) {
395             std::string capabilityValue = std::string(reinterpret_cast<char*>(xmlGetProp(node,
396                 reinterpret_cast<xmlChar*>(const_cast<char*>(property.c_str())))));
397             int32_t id = 0;
398             if (!StrToInt(capabilityValue, id)) {
399                 MEDIA_LOGE("call StrToInt func false, input str is: %{public}s", capabilityValue.c_str());
400                 return false;
401             }
402             if (SOURCE_TYPE_MAP.find(sourceType) == SOURCE_TYPE_MAP.end()) {
403                 MEDIA_LOGE("not found sourceType");
404                 return false;
405             }
406             uint32_t type = SOURCE_TYPE_MAP.at(sourceType);
407             RecorderProfilesData capabilityData;
408             // 8 : 8-15 bits indicates the type of source
409             capabilityData.sourceId = ((type & 0x000000ff) << 8) | (static_cast<uint32_t>(id) & 0x000000ff);
410             bool ret = ParseRecorderProfileSettingsData(node, capabilityData);
411             CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseRecorderProfileSettingsData failed");
412         }
413     }
414     return true;
415 }
416 
ParseRecorderProfileSettingsData(xmlNode * node,RecorderProfilesData & capabilityData)417 bool RecorderProfilesXmlParser::ParseRecorderProfileSettingsData(xmlNode *node, RecorderProfilesData &capabilityData)
418 {
419     xmlNode *child = node->xmlChildrenNode;
420     for (; child; child = child->next) {
421         if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("ProfileSettings")) == 0) {
422             bool ret = true;
423             for (auto it = capabilityKeys_.begin(); it != capabilityKeys_.end(); it++) {
424                 ret = ParseVideoRecorderProfiles(child, capabilityData, *it);
425                 CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseVideoRecorderProfiles failed");
426             }
427 
428             ret = ParseRecorderProfileVideoAudioData(child, capabilityData);
429             CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseRecorderProfileVideoAudioData failed");
430         }
431     }
432     MEDIA_LOGD("RecorderProfilesXmlParser::ParseRecorderProfileSettingsData end");
433     return true;
434 }
435 
ParseVideoRecorderProfiles(xmlNode * node,RecorderProfilesData & capabilityData,const std::string & capabilityKey)436 bool RecorderProfilesXmlParser::ParseVideoRecorderProfiles(
437     xmlNode *node, RecorderProfilesData &capabilityData, const std::string &capabilityKey)
438 {
439     if (xmlHasProp(node, reinterpret_cast<xmlChar*>(const_cast<char*>(capabilityKey.c_str())))) {
440         std::string capabilityValue = std::string(reinterpret_cast<char*>(xmlGetProp(node,
441             reinterpret_cast<xmlChar*>(const_cast<char*>(capabilityKey.c_str())))));
442         bool ret = SetVideoRecorderProfiles(capabilityData, capabilityKey, capabilityValue);
443         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetVideoRecorderProfiles failed");
444     }
445     return true;
446 }
447 
ParseRecorderProfileVideoAudioData(xmlNode * node,RecorderProfilesData & capabilityData)448 bool RecorderProfilesXmlParser::ParseRecorderProfileVideoAudioData(xmlNode *node,
449     RecorderProfilesData &capabilityData)
450 {
451     xmlNode *leafChild = node->xmlChildrenNode;
452     for (; leafChild; leafChild = leafChild->next) {
453         if (xmlStrcmp(leafChild->name, reinterpret_cast<const xmlChar*>("Video")) == 0) {
454             for (auto it = capabilityKeys_.begin(); it != capabilityKeys_.end(); it++) {
455                 bool ret = ParseVideoRecorderProfilesForVideoAudioData(leafChild, capabilityData, *it);
456                 CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseVideoRecorderProfilesForVideoAudioData failed");
457             }
458         } else if (xmlStrcmp(leafChild->name, reinterpret_cast<const xmlChar*>("Audio")) == 0) {
459             for (auto it = capabilityKeys_.begin(); it != capabilityKeys_.end(); it++) {
460                 bool ret = ParseAudioRecorderProfiles(leafChild, capabilityData, *it);
461                 CHECK_AND_RETURN_RET_LOG(ret != false, false, "ParseAudioRecorderProfiles failed");
462             }
463         } else {
464             MEDIA_LOGE("not found video or audio node!");
465         }
466     }
467     MEDIA_LOGD("RecorderProfilesXmlParser::ParseRecorderProfileVideoAudioData end");
468     capabilityDataArray_.emplace_back(capabilityData);
469     return true;
470 }
471 
ParseVideoRecorderProfilesForVideoAudioData(xmlNode * node,RecorderProfilesData & capabilityData,const std::string & capabilityKey)472 bool RecorderProfilesXmlParser::ParseVideoRecorderProfilesForVideoAudioData(
473     xmlNode *node, RecorderProfilesData &capabilityData, const std::string &capabilityKey)
474 {
475     if (xmlHasProp(node, reinterpret_cast<xmlChar*>(const_cast<char*>(capabilityKey.c_str())))) {
476         std::string capabilityValue = std::string(reinterpret_cast<char*>(xmlGetProp(node,
477             reinterpret_cast<xmlChar*>(const_cast<char*>(capabilityKey.c_str())))));
478         capabilityData.mediaProfileType = RECORDER_TYPE_PROFILE;
479         bool ret = SetVideoRecorderProfiles(capabilityData, capabilityKey, capabilityValue);
480         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetVideoRecorderProfiles failed");
481     }
482     return true;
483 }
484 
ParseAudioRecorderProfiles(xmlNode * node,RecorderProfilesData & capabilityData,const std::string & capabilityKey)485 bool RecorderProfilesXmlParser::ParseAudioRecorderProfiles(
486     xmlNode *node, RecorderProfilesData &capabilityData, const std::string &capabilityKey)
487 {
488     if (xmlHasProp(node, reinterpret_cast<xmlChar*>(const_cast<char*>(capabilityKey.c_str())))) {
489         std::string capabilityValue = std::string(reinterpret_cast<char*>(xmlGetProp(node,
490             reinterpret_cast<xmlChar*>(const_cast<char*>(capabilityKey.c_str())))));
491         bool ret = SetAudioRecorderProfiles(capabilityData, capabilityKey, capabilityValue);
492         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetAudioRecorderProfiles failed");
493     }
494     return true;
495 }
496 
SetVideoRecorderProfiles(RecorderProfilesData & data,const std::string & capabilityKey,const std::string & capabilityValue)497 bool RecorderProfilesXmlParser::SetVideoRecorderProfiles(RecorderProfilesData &data, const std::string &capabilityKey,
498                                                          const std::string &capabilityValue)
499 {
500     std::unordered_map<std::string, std::string&> capabilityStringMap = {
501         {"format", data.recorderProfile.containerFormatType}, {"codecMime", data.recorderProfile.videoCodec}};
502 
503     std::unordered_map<std::string, int32_t&> capabilityIntMap = {
504         {"duration", data.recorderProfile.durationTime}, {"bitrate", data.recorderProfile.videoBitrate},
505         {"width", data.recorderProfile.videoFrameWidth}, {"height", data.recorderProfile.videoFrameHeight},
506         {"frameRate", data.recorderProfile.videoFrameRate}, {"quality", data.recorderProfile.qualityLevel}};
507 
508     bool ret = false;
509     if (capabilityStringMap.find(capabilityKey) != capabilityStringMap.end()) {
510         ret = SetCapabilityStringData(capabilityStringMap, capabilityKey, capabilityValue);
511         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityStringData failed");
512     } else if (capabilityIntMap.find(capabilityKey) != capabilityIntMap.end()) {
513         ret = SetCapabilityIntData(capabilityIntMap, capabilityKey, capabilityValue);
514         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityIntData failed");
515     } else {
516         CHECK_AND_RETURN_RET_LOG(ret != false, false, "can not find capabilityKey: %{public}s", capabilityKey.c_str());
517     }
518     MEDIA_LOGD("RecorderProfilesXmlParser::SetVideoRecorderProfiles end");
519     return true;
520 }
521 
SetAudioRecorderProfiles(RecorderProfilesData & data,const std::string & capabilityKey,const std::string & capabilityValue)522 bool RecorderProfilesXmlParser::SetAudioRecorderProfiles(RecorderProfilesData &data, const std::string &capabilityKey,
523                                                          const std::string &capabilityValue)
524 {
525     std::unordered_map<std::string, std::string&> capabilityStringMap = {
526         {"format", data.recorderProfile.containerFormatType}, {"codecMime", data.recorderProfile.audioCodec}};
527 
528     std::unordered_map<std::string, int32_t&> capabilityIntMap = {
529         {"bitrate", data.recorderProfile.audioBitrate}, {"sampleRate", data.recorderProfile.audioSampleRate},
530         {"channels", data.recorderProfile.audioChannels}};
531 
532     bool ret = false;
533     if (capabilityStringMap.find(capabilityKey) != capabilityStringMap.end()) {
534         ret = SetCapabilityStringData(capabilityStringMap, capabilityKey, capabilityValue);
535         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityStringData failed");
536     } else if (capabilityIntMap.find(capabilityKey) != capabilityIntMap.end()) {
537         ret = SetCapabilityIntData(capabilityIntMap, capabilityKey, capabilityValue);
538         CHECK_AND_RETURN_RET_LOG(ret != false, false, "SetCapabilityIntData failed");
539     } else {
540         CHECK_AND_RETURN_RET_LOG(ret != false, false, "can not find capabilityKey: %{public}s", capabilityKey.c_str());
541     }
542     MEDIA_LOGD("RecorderProfilesXmlParser::SetAudioRecorderProfiles end");
543     return true;
544 }
545 
GetNodeNameAsInt(xmlNode * node)546 RecorderProfilesNodeName RecorderProfilesXmlParser::GetNodeNameAsInt(xmlNode *node)
547 {
548     if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("RecorderConfigurations"))) {
549         return RecorderProfilesNodeName::RECORDER_CONFIGURATIONS;
550     } else if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("RecorderCaps"))) {
551         return RecorderProfilesNodeName::RECORDER_CAPS;
552     } else if (!xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>("RecorderProfiles"))) {
553         return RecorderProfilesNodeName::RECORDER_PROFILES;
554     } else {
555         return RecorderProfilesNodeName::UNKNOWN;
556     }
557 }
558 
GetRecorderProfileDataArray()559 std::vector<RecorderProfilesData> RecorderProfilesXmlParser::GetRecorderProfileDataArray()
560 {
561     return this->capabilityDataArray_;
562 }
563 }  // namespace Media
564 }  // namespace OHOS