• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "wfd_message.h"
17 #include <cstdio>
18 #include <iomanip>
19 #include <iostream>
20 #include <securec.h>
21 #include <sstream>
22 #include "common/sharing_log.h"
23 
24 namespace OHOS {
25 namespace Sharing {
26 constexpr int32_t BIT_OFFSET_TWO = 2;
27 constexpr int32_t BIT_OFFSET_THREE = 3;
28 constexpr int32_t BIT_OFFSET_FOUR = 4;
29 constexpr int32_t BIT_OFFSET_EIGHT = 8;
30 constexpr int32_t BIT_OFFSET_TWELVE = 12;
31 
WfdRtspM1Response(int32_t cseq,int32_t status)32 WfdRtspM1Response::WfdRtspM1Response(int32_t cseq, int32_t status) : RtspResponseOptions(cseq, status)
33 {
34     std::stringstream ss;
35     ss << RTSP_METHOD_WFD << "," << RTSP_SP << RTSP_METHOD_SET_PARAMETER << "," << RTSP_SP << RTSP_METHOD_GET_PARAMETER;
36     SetPublicItems(ss.str());
37 }
38 
Parse(const std::string & response)39 RtspError WfdRtspM3Response::Parse(const std::string &response)
40 {
41     auto res = RtspResponse::Parse(response);
42     if (res.code != RtspErrorType::OK) {
43         return res;
44     }
45 
46     RtspCommon::SplitParameter(body_, params_);
47     return {};
48 }
49 
Stringify()50 std::string WfdRtspM3Response::Stringify()
51 {
52     std::stringstream body;
53     std::stringstream ss;
54 
55     for (auto &param : params_) {
56         body << param.first << ":" << RTSP_SP << param.second << RTSP_CRLF;
57     }
58 
59     ss << RTSP_TOKEN_CONTENT_TYPE << ":" << RTSP_SP << "text/parameters" << RTSP_CRLF;
60     ss << RTSP_TOKEN_CONTENT_LENGTH << ":" << RTSP_SP << body.str().length();
61 
62     ClearCustomHeader();
63     AddCustomHeader(ss.str());
64 
65     if (body.str().empty()) {
66         return RtspResponse::Stringify();
67     }
68 
69     return RtspResponse::Stringify() + body.str();
70 }
71 
SetVideoFormats(VideoFormat format)72 void WfdRtspM3Response::SetVideoFormats(VideoFormat format)
73 {
74     std::stringstream ss;
75     std::stringstream sinkVideoList;
76 
77     uint8_t native = 0;
78     uint8_t h264Profile = (1 << (uint8_t)WfdH264Profile::PROFILE_CHP);
79     uint8_t h264Level = (1 << (uint8_t)WfdH264Level::LEVEL_42);
80     uint32_t ceaResolutionIndex = 0;
81     uint32_t vesaResolutionIndex = 0;
82     uint32_t hhResolutionIndex = 0;
83     if (format == VIDEO_NONE) {
84         ceaResolutionIndex =
85             GetSupportVideoResolution(VIDEO_R1_RESOLUTION_SIZE, std::string(MediaAVCodec::CodecMimeType::VIDEO_AVC));
86     } else {
87         ceaResolutionIndex = GetVideoFormatResolution(format);
88         native = static_cast<uint8_t>(WfdResolutionType::RESOLUTION_CEA) | (ceaResolutionIndex << BIT_OFFSET_THREE);
89     }
90     if (ceaResolutionIndex == 0) {
91         ceaResolutionIndex = (1 << CEA_640_480_P60);
92     }
93     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << (int32_t)native << RTSP_SP << "00" << RTSP_SP;
94     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << (int32_t)h264Profile << RTSP_SP;
95     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << (int32_t)h264Level << RTSP_SP;
96     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << ceaResolutionIndex << RTSP_SP;
97     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << vesaResolutionIndex << RTSP_SP;
98     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << hhResolutionIndex << RTSP_SP;
99 
100     ss << "00 0000 0000 00 none none";
101     params_.emplace_back(WFD_PARAM_VIDEO_FORMATS, ss.str());
102 }
103 
GetVideoFormatResolution(VideoFormat format)104 uint32_t WfdRtspM3Response::GetVideoFormatResolution(VideoFormat format)
105 {
106     uint32_t ceaResolutionIndex = 0;
107     switch (format) {
108         case VIDEO_1920X1080_60:
109             ceaResolutionIndex = CEA_1920_1080_P60;
110             break;
111         case VIDEO_1920X1080_30:
112             ceaResolutionIndex = CEA_1920_1080_P30;
113             break;
114         case VIDEO_1920X1080_25:
115             ceaResolutionIndex = CEA_1920_1080_P25;
116             break;
117         case VIDEO_1280X720_60:
118             ceaResolutionIndex = CEA_1280_720_P60;
119             break;
120         case VIDEO_1280X720_30:
121             ceaResolutionIndex = CEA_1280_720_P30;
122             break;
123         case VIDEO_1280X720_25:
124             ceaResolutionIndex = CEA_1280_720_P25;
125             break;
126         case VIDEO_640X480_60:
127         default:
128             ceaResolutionIndex = CEA_640_480_P60;
129             break;
130     }
131 
132     std::shared_ptr<MediaAVCodec::AVCodecList> avCodecList = MediaAVCodec::AVCodecListFactory::CreateAVCodecList();
133     if (avCodecList != nullptr) {
134         MediaAVCodec::CapabilityData *capData = avCodecList->GetCapability(
135             std::string(MediaAVCodec::CodecMimeType::VIDEO_AVC), false, MediaAVCodec::AVCodecCategory::AVCODEC_NONE);
136         std::shared_ptr<MediaAVCodec::VideoCaps> codecInfo = std::make_shared<MediaAVCodec::VideoCaps>(capData);
137         ceaResolutionIndex =
138             IsVideoResolutionSupport(codecInfo, ceaResolutionIndex) ? ceaResolutionIndex : CEA_640_480_P60;
139     }
140     return (1 << ceaResolutionIndex);
141 }
142 
GetSupportVideoResolution(int32_t maxIndex,std::string mimeType)143 uint32_t WfdRtspM3Response::GetSupportVideoResolution(int32_t maxIndex, std::string mimeType)
144 {
145     uint32_t ceaResolutionIndex = 0;
146     std::shared_ptr<MediaAVCodec::AVCodecList> avCodecList = MediaAVCodec::AVCodecListFactory::CreateAVCodecList();
147     if (avCodecList != nullptr) {
148         MediaAVCodec::CapabilityData *capData =
149             avCodecList->GetCapability(mimeType, false, MediaAVCodec::AVCodecCategory::AVCODEC_NONE);
150         std::shared_ptr<MediaAVCodec::VideoCaps> codecInfo = std::make_shared<MediaAVCodec::VideoCaps>(capData);
151         for (int32_t i = 0; i < maxIndex; i++) {
152             if (IsVideoResolutionSupport(codecInfo, i)) {
153                 ceaResolutionIndex = ceaResolutionIndex | (1 << i);
154             }
155         }
156     } else {
157         ceaResolutionIndex = (1 << CEA_640_480_P60);
158     }
159     return ceaResolutionIndex;
160 }
161 
IsVideoResolutionSupport(std::shared_ptr<MediaAVCodec::VideoCaps> codecInfo,uint32_t index)162 bool WfdRtspM3Response::IsVideoResolutionSupport(std::shared_ptr<MediaAVCodec::VideoCaps> codecInfo, uint32_t index)
163 {
164     if (codecInfo == nullptr) {
165         SHARING_LOGE("codecInfo is null");
166         return false;
167     }
168     if (index < 0 || index >= VIDEO_RESOLUTION_TABLE_LENGTH) {
169         SHARING_LOGE("invalid index");
170         return false;
171     }
172     const VideoConfigTable *config = &VIDEO_RESOLUTION_TABLE[TYPE_CEA][index];
173     if (config == nullptr || config->width == 0) {
174         return false;
175     }
176     return codecInfo->IsSizeAndRateSupported(config->width, config->height, config->frameRate);
177 }
178 
SetAudioCodecs(AudioFormat format)179 void WfdRtspM3Response::SetAudioCodecs(AudioFormat format)
180 {
181     std::string audioCodec;
182     if (format == AUDIO_NONE) {
183         audioCodec = GetSupportAudioCodecList();
184     } else {
185         audioCodec = GetAudioFormat(format);
186     }
187     params_.emplace_back(WFD_PARAM_AUDIO_CODECS, audioCodec);
188 }
189 
GetAudioFormat(AudioFormat format)190 std::string WfdRtspM3Response::GetAudioFormat(AudioFormat format)
191 {
192     std::stringstream ss;
193     uint32_t type = TYPE_AAC;
194     uint32_t mode;
195     std::string codec = AAC;
196     switch (format) {
197         case AUDIO_44100_8_2:
198             type = TYPE_LPCM;
199             ss << "LPCM" << RTSP_SP << "00000001 00";
200             break;
201         case AUDIO_44100_16_2:
202             type = TYPE_LPCM;
203             ss << "LPCM" << RTSP_SP << "00000002 00";
204             break;
205         case AUDIO_48000_16_2:
206             mode = AAC_48000_16_2;
207             break;
208         case AUDIO_48000_16_4:
209             mode = AAC_48000_16_4;
210             break;
211         case AUDIO_48000_16_6:
212             mode = AAC_48000_16_6;
213             break;
214         case AUDIO_48000_16_8:
215             mode = AAC_48000_16_8;
216             break;
217         default:
218             mode = AAC_48000_16_2;
219             break;
220     }
221     if (type == TYPE_AAC) {
222         std::shared_ptr<MediaAVCodec::AVCodecList> avCodecList = MediaAVCodec::AVCodecListFactory::CreateAVCodecList();
223         MediaAVCodec::CapabilityData *capData = avCodecList->GetCapability(
224             std::string(MediaAVCodec::CodecMimeType::AUDIO_AAC), false, MediaAVCodec::AVCodecCategory::AVCODEC_NONE);
225         mode = IsSupportAudioModes(TYPE_AAC, mode, capData) ? mode : AAC_48000_16_2;
226         mode = (1 << mode);
227         ss << codec << RTSP_SP << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << mode << RTSP_SP
228            << "00";
229     }
230     return ss.str();
231 }
232 
GetSupportAudioCodecList()233 std::string WfdRtspM3Response::GetSupportAudioCodecList()
234 {
235     std::shared_ptr<MediaAVCodec::AVCodecList> avCodecList = MediaAVCodec::AVCodecListFactory::CreateAVCodecList();
236     if (avCodecList == nullptr) {
237         return "";
238     }
239     const std::vector<std::string> coderName = {std::string(MediaAVCodec::CodecMimeType::AUDIO_AAC)};
240     std::stringstream ss;
241     bool isFirst = true;
242     for (auto &coder : coderName) {
243         MediaAVCodec::CapabilityData *capData =
244             avCodecList->GetCapability(coder, false, MediaAVCodec::AVCodecCategory::AVCODEC_NONE);
245         if (capData != nullptr) {
246             int32_t audioCodecType;
247             int32_t length;
248             std::string codec;
249             if (capData->codecName == MediaAVCodec::AVCodecCodecName::AUDIO_DECODER_AAC_NAME) {
250                 audioCodecType = TYPE_AAC;
251                 codec = AAC;
252                 length = AUDIO_AAC_MODE_LENGTH;
253             } else {
254                 SHARING_LOGE("audioCodecType is unknown codecName = %{public}s", capData->codecName.c_str());
255                 continue;
256             }
257             std::string modes = GetSupportAudioModes(audioCodecType, capData, length);
258             if (!isFirst) {
259                 ss << "," << RTSP_SP;
260             }
261             ss << codec << RTSP_SP << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex
262                << std::stoi(modes.c_str(), nullptr, BIT_OFFSET_TWO) << RTSP_SP << "00";
263         }
264         isFirst = false;
265     }
266     if (ss.str().empty()) {
267         ss << "AAC" << RTSP_SP << "00000001 00";
268     }
269     return ss.str();
270 }
271 
GetSupportAudioModes(int32_t type,MediaAVCodec::CapabilityData * capData,int32_t length)272 std::string WfdRtspM3Response::GetSupportAudioModes(int32_t type, MediaAVCodec::CapabilityData *capData, int32_t length)
273 {
274     char audioModes[length + 1];
275     audioModes[length] = '\0';
276     if (memset_s(audioModes, sizeof(audioModes), '0', length) != EOK) {
277         SHARING_LOGI("call memset_s failed");
278     }
279     for (int32_t i = 0; i < length; i++) {
280         if (IsSupportAudioModes(type, i, capData)) {
281             audioModes[length - i - 1] = '1';
282         }
283     }
284     return audioModes;
285 }
286 
IsSupportAudioModes(int32_t type,int32_t index,MediaAVCodec::CapabilityData * capData)287 bool WfdRtspM3Response::IsSupportAudioModes(int32_t type, int32_t index, MediaAVCodec::CapabilityData *capData)
288 {
289     const AudioConfigTable *config = &AUDIO_CONFIG_TABLE[type][index];
290     if (config == nullptr || config->sampleRate == 0) {
291         return false;
292     }
293     bool isChannelsSupport =
294         config->channels >= capData->channels.minVal && config->channels <= capData->channels.maxVal;
295     bool isSampleRateSupport = std::find(capData->sampleRate.begin(), capData->sampleRate.end(), config->sampleRate) !=
296                                capData->sampleRate.end();
297     return isChannelsSupport && isSampleRateSupport;
298 }
299 
SetVideoFormats2FromSystem()300 void WfdRtspM3Response::SetVideoFormats2FromSystem()
301 {
302     uint32_t h264Profile = (1 << static_cast<uint32_t>(WfdH264Profile::PROFILE_CHP));
303     uint32_t h264Level = (1 << static_cast<uint32_t>(WfdH264Level::LEVEL_51));
304     uint32_t h264CodecType = (1 << static_cast<uint32_t>(WfdVideoCodec::CODEC_H264));
305     uint64_t ceaResolutionIndex =
306         GetSupportVideoResolution(VIDEO_R2_RESOLUTION_SIZE, std::string(MediaAVCodec::CodecMimeType::VIDEO_AVC));
307 
308     std::stringstream ss;
309     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << std::uppercase << 0 << RTSP_SP;
310     std::string videoAvcCap = GetVideo2Cap(h264CodecType, h264Profile, h264Level, ceaResolutionIndex);
311     ss << videoAvcCap << RTSP_SP << "00";
312 
313     params_.emplace_back(WFD_PARAM_VIDEO_FORMATS_2, ss.str());
314 }
315 
GetVideo2Cap(uint32_t codecType,uint32_t profile,uint32_t level,uint64_t ceaResolution)316 std::string WfdRtspM3Response::GetVideo2Cap(uint32_t codecType, uint32_t profile, uint32_t level,
317                                             uint64_t ceaResolution)
318 {
319     std::stringstream ss;
320     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << std::uppercase << codecType << RTSP_SP;
321     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << std::uppercase << profile << RTSP_SP;
322     ss << std::setfill('0') << std::setw(BIT_OFFSET_FOUR) << std::hex << std::uppercase << level << RTSP_SP;
323     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWELVE) << std::hex << std::uppercase << ceaResolution << RTSP_SP;
324     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWELVE) << std::hex << std::uppercase << 0 << RTSP_SP;
325     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWELVE) << std::hex << std::uppercase << 0 << RTSP_SP;
326     ss << "00 0000 0000 00";
327     return ss.str();
328 }
329 
SetAudioCodec2FromSystem()330 void WfdRtspM3Response::SetAudioCodec2FromSystem()
331 {
332     std::string audioCodec = GetSupportAudioCodecList();
333     params_.emplace_back(WFD_PARAM_AUDIO_CODECS_2, audioCodec);
334 }
335 
SetClientRtpPorts(int32_t port)336 void WfdRtspM3Response::SetClientRtpPorts(int32_t port)
337 {
338     std::stringstream ss;
339     ss << "RTP/AVP/UDP;unicast" << RTSP_SP << port << RTSP_SP << 0 << RTSP_SP << "mode=play";
340     params_.emplace_back(WFD_PARAM_RTP_PORTS, ss.str());
341 }
342 
SetContentProtection(const std::string & value)343 void WfdRtspM3Response::SetContentProtection(const std::string &value)
344 {
345     params_.emplace_back(WFD_PARAM_CONTENT_PROTECTION, value);
346 }
347 
SetCoupledSink(const std::string & value)348 void WfdRtspM3Response::SetCoupledSink(const std::string &value)
349 {
350     params_.emplace_back(WFD_PARAM_COUPLED_SINK, value);
351 }
352 
SetUibcCapability(const std::string & value)353 void WfdRtspM3Response::SetUibcCapability(const std::string &value)
354 {
355     params_.emplace_back(WFD_PARAM_UIBC_CAPABILITY, value);
356 }
357 
SetStandbyResumeCapability(const std::string & value)358 void WfdRtspM3Response::SetStandbyResumeCapability(const std::string &value)
359 {
360     params_.emplace_back(WFD_PARAM_UIBC_CAPABILITY, value);
361 }
362 
SetCustomParam(const std::string & key,const std::string & value)363 void WfdRtspM3Response::SetCustomParam(const std::string &key, const std::string &value)
364 {
365     params_.emplace_back(key, value);
366 }
367 
GetClientRtpPorts()368 int32_t WfdRtspM3Response::GetClientRtpPorts()
369 {
370     int32_t port0 = -1;
371     int32_t port1 = -1;
372     std::string profile = "RTP/AVP/UDP;unicast";
373     std::string mode = "mode=play";
374     std::string value = GetCustomParam(WFD_PARAM_RTP_PORTS);
375     std::stringstream ss(value);
376     ss >> profile >> port0 >> port1 >> mode;
377     return port0;
378 }
379 
GetUibcCapability()380 std::string WfdRtspM3Response::GetUibcCapability()
381 {
382     std::string value = GetCustomParam(WFD_PARAM_UIBC_CAPABILITY);
383     return value;
384 }
385 
GetAudioCodecs(WfdAudioCodec & codec)386 AudioFormat WfdRtspM3Response::GetAudioCodecs(WfdAudioCodec &codec)
387 {
388     std::string value = GetCustomParam(WFD_PARAM_AUDIO_CODECS);
389     int32_t audioFormat0 = -1;
390     int32_t audioFormat1 = -1;
391     std::string format;
392     auto audioCaps = RtspCommon::Split(value, ", ");
393     for (size_t i = 0; i < audioCaps.size(); i++) {
394         std::string audioCap = audioCaps[i];
395         std::stringstream ss(audioCap);
396         ss >> format >> audioFormat0 >> audioFormat1;
397         if (format == "LPCM") { // LPCM
398             if (codec.codecId != CODEC_AAC && audioFormat0 > 1) {
399                 codec.codecId = CODEC_PCM;
400                 codec.format = AUDIO_48000_16_2;
401             }
402         } else if (format == "AAC") { // AAC
403             codec.codecId = CODEC_AAC;
404             codec.format = AUDIO_48000_16_2;
405         } else if (format == "AC3") { // AC3
406             if (audioFormat0 == 1) {
407             }
408             continue;
409         }
410     }
411 
412     return codec.format;
413 }
414 
GetCoupledSink()415 std::string WfdRtspM3Response::GetCoupledSink()
416 {
417     std::string value = GetCustomParam(WFD_PARAM_COUPLED_SINK);
418     return value;
419 }
420 
GetContentProtection()421 std::string WfdRtspM3Response::GetContentProtection()
422 {
423     std::string value = GetCustomParam(WFD_PARAM_CONTENT_PROTECTION);
424     return value;
425 }
426 
GetVideoFormatsByCea(int index)427 VideoFormat WfdRtspM3Response::GetVideoFormatsByCea(int index)
428 {
429     WfdCeaResolution res = static_cast<WfdCeaResolution>(index);
430     switch (res) {
431         case CEA_640_480_P60:
432             return VIDEO_640X480_60;
433         case CEA_1280_720_P30:
434             return VIDEO_1280X720_30;
435         case CEA_1280_720_P60:
436             return VIDEO_1280X720_60;
437         case CEA_1920_1080_P25:
438             return VIDEO_1920X1080_25;
439         case CEA_1920_1080_P30:
440             return VIDEO_1920X1080_30;
441         case CEA_1920_1080_P60:
442             return VIDEO_1920X1080_60;
443         default:
444             return VIDEO_640X480_60;
445     }
446 }
447 
GetVideoFormats()448 VideoFormat WfdRtspM3Response::GetVideoFormats()
449 {
450     // wfd_video_formats:
451     // 1 byte "native"
452     // 1 byte "preferred-display-mode-supported" 0 or 1
453     // one or more avc codec structures
454     //   1 byte profile
455     //   1 byte level
456     //   4 byte CEA mask
457     //   4 byte VESA mask
458     //   4 byte HH mask
459     //   1 byte latency
460     //   2 byte min-slice-slice
461     //   2 byte slice-enc-params
462     //   1 byte framerate-control-support
463     //   max-hres (none or 2 byte)
464     //   max-vres (none or 2 byte)
465     /**
466      * native:  2*2HEXDIG
467      * preferred-display-mode-supported: 2*2HEXDIG; 0-not supported, 1-supported, 2-255 reserved
468      * profile: 2*2HEXDIG, only one bit set
469      * level:   2*2HEXDIG, only one bit set
470      * CEA-Support: 8*8HEXDIG, 0-ignore
471      * VESA-Support:8*8HEXDIG, 0-ignore
472      * HH-Support:  8*8HEXDIG, 0-ignore
473      * latency:     2*2HEXDIG, decoder latency in units of 5 msecs
474      * min-slice-size: 4*4HEXDIG, number of macroblocks
475      * slice-enc-params: 4*4HEXDIG,
476      * frame-rate-control-support: 4*4HEXDIG
477      * max-hres: 4*4HEXDIG, "none" if preferred-display-mode-supported is 0
478      * max-vres: 4*4HEXDIG, "none" if preferred-display-mode-supported is 0
479      **/
480     std::string value = GetCustomParam(WFD_PARAM_VIDEO_FORMATS);
481     if (value.size() < MINIMAL_VIDEO_FORMAT_SIZE) {
482         return VIDEO_640X480_60;
483     }
484 
485     std::string head = value.substr(0, 5); // 5: fix offset
486     uint16_t native = 0;
487     uint16_t preferredDisplayMode = 0;
488     int index = 0;
489     std::string temp = "";
490     bool run = true;
491     std::stringstream ss(head);
492     ss >> std::hex >> native >> std::hex >> preferredDisplayMode;
493     value = value.substr(5); // 5: fix offset
494 
495     while (run) {
496         auto nPos = value.find_first_of(",", index + 1);
497         if (nPos != std::string::npos) {
498             index = static_cast<int>(nPos);
499             temp = value.substr(0, index);
500         } else {
501             temp = value.substr(index + 1);
502             run = false;
503         }
504         std::stringstream sss(temp);
505         WfdVideoFormatsInfo wfdVideoFormatsInfo;
506         wfdVideoFormatsInfo.native = native;
507         wfdVideoFormatsInfo.preferredDisplayMode = preferredDisplayMode;
508         sss >> std::hex >> wfdVideoFormatsInfo.profile >> std::hex >> wfdVideoFormatsInfo.level >> std::hex >>
509             wfdVideoFormatsInfo.ceaMask >> std::hex >> wfdVideoFormatsInfo.veaMask >> std::hex >>
510             wfdVideoFormatsInfo.hhMask >> std::hex >> wfdVideoFormatsInfo.latency >> std::hex >>
511             wfdVideoFormatsInfo.minSlice >> std::hex >> wfdVideoFormatsInfo.sliceEncParam >> std::hex >>
512             wfdVideoFormatsInfo.frameRateCtlSupport;
513         vWfdVideoFormatsInfo_.push_back(wfdVideoFormatsInfo);
514     }
515 
516     uint8_t tableSelection = vWfdVideoFormatsInfo_[0].native & 0x7;
517     index = vWfdVideoFormatsInfo_[0].native >> BIT_OFFSET_THREE;
518     switch (tableSelection) {
519         case 0:
520             return GetVideoFormatsByCea(index);
521         default:
522             return VIDEO_640X480_60;
523     }
524     return VIDEO_640X480_60;
525 }
526 
GetStandbyResumeCapability()527 std::string WfdRtspM3Response::GetStandbyResumeCapability()
528 {
529     std::string value = GetCustomParam(WFD_PARAM_STANDBY_RESUME);
530     return value;
531 }
532 
GetCustomParam(const std::string & key)533 std::string WfdRtspM3Response::GetCustomParam(const std::string &key)
534 {
535     auto it = std::find_if(params_.begin(), params_.end(),
536                            [=](std::pair<std::string, std::string> value) { return value.first == key; });
537     if (it != params_.end()) {
538         return it->second;
539     }
540 
541     return "";
542 }
543 
SetClientRtpPorts(int32_t port)544 void WfdRtspM4Request::SetClientRtpPorts(int32_t port)
545 {
546     std::stringstream ss;
547     ss << WFD_PARAM_RTP_PORTS << ":" << RTSP_SP << "RTP/AVP/UDP;unicast" << RTSP_SP << port << RTSP_SP << 0 << RTSP_SP
548        << "mode=play";
549     AddBodyItem(ss.str());
550 }
551 
SetAudioCodecs(WfdAudioCodec & codec)552 void WfdRtspM4Request::SetAudioCodecs(WfdAudioCodec &codec)
553 {
554     std::stringstream ss;
555     ss << WFD_PARAM_AUDIO_CODECS << ":" << RTSP_SP;
556 
557     switch (codec.codecId) {
558         case CODEC_PCM:
559             ss << "LPCM" << RTSP_SP << "00000002 00";
560             break;
561         case CODEC_AAC:
562             ss << "AAC" << RTSP_SP << "00000001 00";
563             break;
564         default:
565             ss << "AAC" << RTSP_SP << "00000001 00";
566             break;
567     }
568 
569     AddBodyItem(ss.str());
570 }
571 
SetPresentationUrl(const std::string & ip)572 void WfdRtspM4Request::SetPresentationUrl(const std::string &ip)
573 {
574     std::stringstream ss;
575     ss << WFD_PARAM_PRESENTATION_URL << ":" << RTSP_SP << "rtsp://" << ip.c_str() << "/wfd1.0/streamid=0 none";
576     AddBodyItem(ss.str());
577 }
578 
SetVideoFormats(const WfdVideoFormatsInfo & wfdVideoFormatsInfo,VideoFormat format)579 void WfdRtspM4Request::SetVideoFormats(const WfdVideoFormatsInfo &wfdVideoFormatsInfo, VideoFormat format)
580 {
581     std::stringstream ss;
582     uint32_t native = wfdVideoFormatsInfo.native;
583     uint32_t h264Profile = wfdVideoFormatsInfo.profile;
584     uint32_t h264Level = wfdVideoFormatsInfo.level;
585     uint32_t ceaResolutionIndex = 0;
586     uint32_t vesaResolutionIndex = 0;
587     uint32_t hhResolutionIndex = 0;
588     (void)ceaResolutionIndex;
589     (void)vesaResolutionIndex;
590     (void)hhResolutionIndex;
591     (void)h264Profile;
592     (void)h264Level;
593 
594     switch (format) {
595         case VIDEO_1920X1080_60:
596         case VIDEO_1920X1080_30:
597             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P30 << BIT_OFFSET_THREE);
598             ceaResolutionIndex = (1 << CEA_1920_1080_P30);
599             break;
600         case VIDEO_1920X1080_25:
601             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P25 << BIT_OFFSET_THREE);
602             ceaResolutionIndex = (1 << CEA_1920_1080_P25);
603             break;
604         case VIDEO_1280X720_30:
605             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P30 << BIT_OFFSET_THREE);
606             ceaResolutionIndex = (1 << CEA_1280_720_P30);
607             break;
608         case VIDEO_1280X720_25:
609             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P25 << BIT_OFFSET_THREE);
610             ceaResolutionIndex = (1 << CEA_1280_720_P25);
611             break;
612         case VIDEO_640X480_60:
613         default:
614             native =
615                 (uint8_t)WfdResolutionType::RESOLUTION_CEA | (WfdCeaResolution::CEA_640_480_P60 << BIT_OFFSET_THREE);
616             ceaResolutionIndex = (1 << CEA_640_480_P60);
617             break;
618     }
619 
620     ss << WFD_PARAM_VIDEO_FORMATS << ":" << RTSP_SP;
621     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << native << RTSP_SP << "00" << RTSP_SP;
622     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << h264Profile << RTSP_SP;
623     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << h264Level << RTSP_SP;
624     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << ceaResolutionIndex << RTSP_SP;
625     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << vesaResolutionIndex << RTSP_SP;
626     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << hhResolutionIndex << RTSP_SP;
627     ss << "00 0000 0000 00 none none";
628     AddBodyItem(ss.str());
629 }
630 
Parse(const std::string & request)631 RtspError WfdRtspM4Request::Parse(const std::string &request)
632 {
633     auto res = RtspRequest::Parse(request);
634     if (res.code != RtspErrorType::OK) {
635         return res;
636     }
637 
638     RtspCommon::SplitParameter(body_, params_);
639     return {};
640 }
641 
GetParameterValue(const std::string & param)642 std::string WfdRtspM4Request::GetParameterValue(const std::string &param)
643 {
644     auto it = std::find_if(params_.begin(), params_.end(),
645                            [=](std::pair<std::string, std::string> value) { return value.first == param; });
646     if (it != params_.end()) {
647         return it->second;
648     }
649 
650     return "";
651 }
652 
GetPresentationUrl()653 std::string WfdRtspM4Request::GetPresentationUrl()
654 {
655     std::string urls = GetParameterValue(WFD_PARAM_PRESENTATION_URL);
656     if (urls.empty()) {
657         return "";
658     }
659 
660     auto urlVec = RtspCommon::Split(urls, " ");
661     if (!urlVec.empty()) {
662         return urlVec[0];
663     }
664 
665     return "";
666 }
667 
GetRtpPort()668 int32_t WfdRtspM4Request::GetRtpPort()
669 {
670     auto ports = GetParameterValue(WFD_PARAM_RTP_PORTS);
671     auto resVec = RtspCommon::Split(ports, " ");
672     if (resVec.size() > 2) { // 2: fix offset
673         return atoi(resVec[1].c_str());
674     }
675 
676     return 0;
677 }
678 
GetVideoTrack(VideoTrack & videoTrack)679 void WfdRtspM4Request::GetVideoTrack(VideoTrack &videoTrack)
680 {
681     std::string wfdVideoFormatParam = GetParameterValue(WFD_PARAM_VIDEO_FORMATS_2);
682     if (wfdVideoFormatParam.empty()) {
683         wfdVideoFormatParam = GetParameterValue(WFD_PARAM_VIDEO_FORMATS);
684     }
685     if (wfdVideoFormatParam.empty()) {
686         SHARING_LOGE("wfdVideoFormatParam is null.");
687         return;
688     }
689     std::vector<std::string> videoFormats = RtspCommon::Split(wfdVideoFormatParam, "\\s+");
690     if (videoFormats.size() <= INDEX_HH) {
691         SHARING_LOGE("video formats is invalid.");
692         return;
693     }
694     SHARING_LOGD("wfdVideoFormats native:%{public}s", videoFormats.at(0).c_str());
695     errno = 0;
696     char *endPtr = nullptr;
697     int nativeValue = std::strtol(videoFormats.front().c_str(), &endPtr, HEX_LENGTH);
698     if (errno == ERANGE || endPtr == videoFormats.front().c_str() || *endPtr != '\0') {
699         SHARING_LOGE("%{public}s error : %{public}s!", __FUNCTION__, strerror(errno));
700         return;
701     }
702 
703     std::string resolutionStr = {""};
704     nativeValue = (int32_t)((uint32_t)nativeValue & 0x07);
705     if (nativeValue == TYPE_CEA) {
706         resolutionStr = videoFormats.at(INDEX_CEA);
707     } else if (nativeValue == TYPE_VESA) {
708         resolutionStr = videoFormats.at(INDEX_VESA);
709     } else if (nativeValue == TYPE_HH) {
710         resolutionStr = videoFormats.at(INDEX_HH);
711     } else {
712         SHARING_LOGE("get wfd_video_formats error.");
713         return;
714     }
715     GetVideoResolution(videoTrack, resolutionStr, nativeValue);
716 }
717 
GetVideoResolution(VideoTrack & videoTrack,std::string resolutionStr,int type)718 void WfdRtspM4Request::GetVideoResolution(VideoTrack &videoTrack, std::string resolutionStr, int type)
719 {
720     uint32_t result = (uint32_t)strtol(resolutionStr.c_str(), nullptr, HEX_LENGTH);
721     if (result <= 0) {
722         SHARING_LOGE("get video resolution failed.");
723         return;
724     }
725     uint32_t index = log(result) / log(LOG_BASE);
726     if ((type == TYPE_CEA && index > MAX_CEA_INDEX) || (type == TYPE_VESA && index > MAX_VESA_INDEX) ||
727         (type == TYPE_HH && index > MAX_HH_INDEX)) {
728         SHARING_LOGE("get video resolution index error.");
729     }
730     const VideoConfigTable *config = &VIDEO_RESOLUTION_TABLE[type][index];
731     videoTrack.codecId = CODEC_H264;
732     videoTrack.width = config->width;
733     videoTrack.height = config->height;
734     videoTrack.frameRate = config->frameRate;
735     SHARING_LOGI("get video resolution width: %{public}d, height: %{public}d, frameRate: %{public}d,", videoTrack.width,
736                  videoTrack.height, videoTrack.frameRate);
737 }
738 
GetAudioTrack(AudioTrack & audioTrack)739 void WfdRtspM4Request::GetAudioTrack(AudioTrack &audioTrack)
740 {
741     std::string wfdAudioFormatParam = GetParameterValue(WFD_PARAM_AUDIO_CODECS_2);
742     if (wfdAudioFormatParam.empty()) {
743         wfdAudioFormatParam = GetParameterValue(WFD_PARAM_AUDIO_CODECS);
744     }
745     if (wfdAudioFormatParam.empty()) {
746         SHARING_LOGE("wfdAudioFormatParam is null.");
747         return;
748     }
749     std::vector<std::string> audioFormats = RtspCommon::Split(wfdAudioFormatParam, "\\s+");
750     if (audioFormats.size() <= AUDIO_MODE_INDEX) {
751         SHARING_LOGE("audioFormats is error.");
752         return;
753     }
754     int32_t type;
755     std::string format = audioFormats.at(AUDIO_TYPE_INDEX);
756     if (format == LPCM) {
757         type = TYPE_LPCM;
758     } else if (format == AAC) {
759         type = TYPE_AAC;
760     } else if (format == AC3) {
761         type = TYPE_AC3;
762     } else {
763         type = TYPE_AAC;
764     }
765     int32_t result = std::strtol(audioFormats.at(AUDIO_MODE_INDEX).c_str(), nullptr, HEX_LENGTH);
766     if (result <= 0) {
767         SHARING_LOGE("get mode failed.");
768         return;
769     }
770     int32_t index = log(result) / log(LOG_BASE);
771     const AudioConfigTable *config = &AUDIO_CONFIG_TABLE[type][index];
772     audioTrack.codecId = CodecId::CODEC_AAC;
773     audioTrack.sampleRate = config->sampleRate;
774     audioTrack.sampleFormat = config->sampleFormat;
775     audioTrack.channels = config->channels;
776     SHARING_LOGI("get audio format sampleRate: %{public}d, sampleFormat: %{public}d, channels: %{public}d,",
777                  audioTrack.sampleRate, audioTrack.sampleFormat, audioTrack.channels);
778 }
779 
SetTriggerMethod(const std::string & method)780 void WfdRtspM5Request::SetTriggerMethod(const std::string &method)
781 {
782     std::stringstream ss;
783     ss << WFD_PARAM_TRIGGER << ":" << RTSP_SP << method;
784 
785     body_.emplace_back(ss.str());
786 }
787 
GetTriggerMethod()788 std::string WfdRtspM5Request::GetTriggerMethod()
789 {
790     std::list<std::pair<std::string, std::string>> params;
791     RtspCommon::SplitParameter(body_, params);
792 
793     auto it = std::find_if(params.begin(), params.end(),
794                            [](std::pair<std::string, std::string> value) { return value.first == WFD_PARAM_TRIGGER; });
795     if (it != params.end()) {
796         return it->second;
797     }
798 
799     return {};
800 }
801 
GetClientPort()802 int32_t WfdRtspM6Response::GetClientPort()
803 {
804     auto transport = GetToken(RTSP_TOKEN_TRANSPORT);
805     if (transport.empty()) {
806         return 0;
807     }
808 
809     auto tsVec = RtspCommon::Split(transport, ";");
810     for (auto &item : tsVec) {
811         if (item.find("client_port=") != std::string::npos) {
812             auto val = item.substr(item.find('=') + 1);
813             return atoi(val.c_str());
814         }
815     }
816 
817     return 0;
818 }
819 
GetServerPort()820 int32_t WfdRtspM6Response::GetServerPort()
821 {
822     auto transport = GetToken(RTSP_TOKEN_TRANSPORT);
823     if (transport.empty()) {
824         return 0;
825     }
826 
827     auto tsVec = RtspCommon::Split(transport, ";");
828     for (auto &item : tsVec) {
829         if (item.find("server_port=") != std::string::npos) {
830             auto val = item.substr(item.find('=') + 1);
831             return atoi(val.c_str());
832         }
833     }
834 
835     return 0;
836 }
837 
SetClientPort(int port)838 void WfdRtspM6Response::SetClientPort(int port)
839 {
840     clientPort_ = port;
841 }
842 
SetServerPort(int port)843 void WfdRtspM6Response::SetServerPort(int port)
844 {
845     serverPort_ = port;
846 }
847 
StringifyEx()848 std::string WfdRtspM6Response::StringifyEx()
849 {
850     std::stringstream ss;
851     auto message = Stringify();
852     std::string temp = RTSP_CRLF;
853     auto nPos = message.find_last_of(RTSP_CRLF);
854     if (nPos != std::string::npos) {
855         message = message.substr(0, message.size() - temp.size());
856     }
857     ss << message << "Transport: RTP/AVP/UDP;unicast;client_port=" << clientPort_ << ";server_port=" << serverPort_
858        << RTSP_CRLF;
859     ss << RTSP_CRLF;
860     return ss.str();
861 }
862 
StringifyEx()863 std::string WfdRtspM7Response::StringifyEx()
864 {
865     std::stringstream ss;
866     auto message = Stringify();
867     std::string temp = RTSP_CRLF;
868     auto nPos = message.find_last_of(RTSP_CRLF);
869     if (nPos != std::string::npos) {
870         message = message.substr(0, message.size() - temp.size());
871     }
872     ss << message << "Range: npt=now-" << RTSP_CRLF;
873     ss << RTSP_CRLF;
874     return ss.str();
875 }
876 
877 } // namespace Sharing
878 } // namespace OHOS
879