• 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 >= 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 = AAC_48000_16_2;
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     bool isSupportAAC = false;
393     bool isSupportPCM = false;
394     auto audioCaps = RtspCommon::Split(value, ", ");
395     for (size_t i = 0; i < audioCaps.size(); i++) {
396         std::string audioCap = audioCaps[i];
397         std::stringstream ss(audioCap);
398         ss >> format >> audioFormat0 >> audioFormat1;
399         if (format == "LPCM" && audioFormat0 > 1) { // LPCM
400             isSupportPCM = true;
401             continue;
402         }
403         if (format == "AAC") { // AAC
404             isSupportAAC = true;
405             continue;
406         }
407     }
408     if (isSupportPCM && !isSupportAAC) {
409         codec.codecId = CODEC_PCM;
410         codec.format = AUDIO_48000_16_2;
411     } else {
412         codec.codecId = CODEC_AAC;
413         codec.format = AUDIO_48000_16_2;
414     }
415 
416     return codec.format;
417 }
418 
GetCoupledSink()419 std::string WfdRtspM3Response::GetCoupledSink()
420 {
421     std::string value = GetCustomParam(WFD_PARAM_COUPLED_SINK);
422     return value;
423 }
424 
GetContentProtection()425 std::string WfdRtspM3Response::GetContentProtection()
426 {
427     std::string value = GetCustomParam(WFD_PARAM_CONTENT_PROTECTION);
428     return value;
429 }
430 
GetVideoFormatsByCea(int index)431 VideoFormat WfdRtspM3Response::GetVideoFormatsByCea(int index)
432 {
433     WfdCeaResolution res = static_cast<WfdCeaResolution>(index);
434     switch (res) {
435         case CEA_640_480_P60:
436             return VIDEO_640X480_60;
437         case CEA_1280_720_P30:
438             return VIDEO_1280X720_30;
439         case CEA_1280_720_P60:
440             return VIDEO_1280X720_60;
441         case CEA_1920_1080_P25:
442             return VIDEO_1920X1080_25;
443         case CEA_1920_1080_P30:
444             return VIDEO_1920X1080_30;
445         case CEA_1920_1080_P60:
446             return VIDEO_1920X1080_60;
447         default:
448             return VIDEO_640X480_60;
449     }
450 }
451 
GetVideoFormats()452 VideoFormat WfdRtspM3Response::GetVideoFormats()
453 {
454     // wfd_video_formats:
455     // 1 byte "native"
456     // 1 byte "preferred-display-mode-supported" 0 or 1
457     // one or more avc codec structures
458     //   1 byte profile
459     //   1 byte level
460     //   4 byte CEA mask
461     //   4 byte VESA mask
462     //   4 byte HH mask
463     //   1 byte latency
464     //   2 byte min-slice-slice
465     //   2 byte slice-enc-params
466     //   1 byte framerate-control-support
467     //   max-hres (none or 2 byte)
468     //   max-vres (none or 2 byte)
469     /**
470      * native:  2*2HEXDIG
471      * preferred-display-mode-supported: 2*2HEXDIG; 0-not supported, 1-supported, 2-255 reserved
472      * profile: 2*2HEXDIG, only one bit set
473      * level:   2*2HEXDIG, only one bit set
474      * CEA-Support: 8*8HEXDIG, 0-ignore
475      * VESA-Support:8*8HEXDIG, 0-ignore
476      * HH-Support:  8*8HEXDIG, 0-ignore
477      * latency:     2*2HEXDIG, decoder latency in units of 5 msecs
478      * min-slice-size: 4*4HEXDIG, number of macroblocks
479      * slice-enc-params: 4*4HEXDIG,
480      * frame-rate-control-support: 4*4HEXDIG
481      * max-hres: 4*4HEXDIG, "none" if preferred-display-mode-supported is 0
482      * max-vres: 4*4HEXDIG, "none" if preferred-display-mode-supported is 0
483      **/
484     std::string value = GetCustomParam(WFD_PARAM_VIDEO_FORMATS);
485     if (value.size() < MINIMAL_VIDEO_FORMAT_SIZE) {
486         return VIDEO_640X480_60;
487     }
488 
489     std::string head = value.substr(0, 5); // 5: fix offset
490     uint16_t native = 0;
491     uint16_t preferredDisplayMode = 0;
492     int index = 0;
493     std::string temp = "";
494     bool run = true;
495     std::stringstream ss(head);
496     ss >> std::hex >> native >> std::hex >> preferredDisplayMode;
497     value = value.substr(5); // 5: fix offset
498 
499     while (run) {
500         auto nPos = value.find_first_of(",", index + 1);
501         if (nPos != std::string::npos) {
502             index = static_cast<int>(nPos);
503             temp = value.substr(0, index);
504         } else {
505             temp = value.substr(index + 1);
506             run = false;
507         }
508         std::stringstream sss(temp);
509         WfdVideoFormatsInfo wfdVideoFormatsInfo;
510         wfdVideoFormatsInfo.native = native;
511         wfdVideoFormatsInfo.preferredDisplayMode = preferredDisplayMode;
512         sss >> std::hex >> wfdVideoFormatsInfo.profile >> std::hex >> wfdVideoFormatsInfo.level >> std::hex >>
513             wfdVideoFormatsInfo.ceaMask >> std::hex >> wfdVideoFormatsInfo.veaMask >> std::hex >>
514             wfdVideoFormatsInfo.hhMask >> std::hex >> wfdVideoFormatsInfo.latency >> std::hex >>
515             wfdVideoFormatsInfo.minSlice >> std::hex >> wfdVideoFormatsInfo.sliceEncParam >> std::hex >>
516             wfdVideoFormatsInfo.frameRateCtlSupport;
517         vWfdVideoFormatsInfo_.push_back(wfdVideoFormatsInfo);
518     }
519 
520     uint8_t tableSelection = vWfdVideoFormatsInfo_[0].native & 0x7;
521     index = vWfdVideoFormatsInfo_[0].native >> BIT_OFFSET_THREE;
522     switch (tableSelection) {
523         case 0:
524             return GetVideoFormatsByCea(index);
525         default:
526             return VIDEO_640X480_60;
527     }
528     return VIDEO_640X480_60;
529 }
530 
GetStandbyResumeCapability()531 std::string WfdRtspM3Response::GetStandbyResumeCapability()
532 {
533     std::string value = GetCustomParam(WFD_PARAM_STANDBY_RESUME);
534     return value;
535 }
536 
GetCustomParam(const std::string & key)537 std::string WfdRtspM3Response::GetCustomParam(const std::string &key)
538 {
539     auto it = std::find_if(params_.begin(), params_.end(),
540                            [=](std::pair<std::string, std::string> value) { return value.first == key; });
541     if (it != params_.end()) {
542         return it->second;
543     }
544 
545     return "";
546 }
547 
SetClientRtpPorts(int32_t port)548 void WfdRtspM4Request::SetClientRtpPorts(int32_t port)
549 {
550     std::stringstream ss;
551     ss << WFD_PARAM_RTP_PORTS << ":" << RTSP_SP << "RTP/AVP/UDP;unicast" << RTSP_SP << port << RTSP_SP << 0 << RTSP_SP
552        << "mode=play";
553     AddBodyItem(ss.str());
554 }
555 
SetAudioCodecs(WfdAudioCodec & codec)556 void WfdRtspM4Request::SetAudioCodecs(WfdAudioCodec &codec)
557 {
558     std::stringstream ss;
559     ss << WFD_PARAM_AUDIO_CODECS << ":" << RTSP_SP;
560 
561     switch (codec.codecId) {
562         case CODEC_PCM:
563             ss << "LPCM" << RTSP_SP << "00000002 00";
564             break;
565         case CODEC_AAC:
566             ss << "AAC" << RTSP_SP << "00000001 00";
567             break;
568         default:
569             ss << "AAC" << RTSP_SP << "00000001 00";
570             break;
571     }
572 
573     AddBodyItem(ss.str());
574 }
575 
SetPresentationUrl(const std::string & ip)576 void WfdRtspM4Request::SetPresentationUrl(const std::string &ip)
577 {
578     std::stringstream ss;
579     ss << WFD_PARAM_PRESENTATION_URL << ":" << RTSP_SP << "rtsp://" << ip.c_str() << "/wfd1.0/streamid=0 none";
580     AddBodyItem(ss.str());
581 }
582 
SetVideoFormats(const WfdVideoFormatsInfo & wfdVideoFormatsInfo,VideoFormat format)583 void WfdRtspM4Request::SetVideoFormats(const WfdVideoFormatsInfo &wfdVideoFormatsInfo, VideoFormat format)
584 {
585     std::stringstream ss;
586     uint32_t native = wfdVideoFormatsInfo.native;
587     uint32_t h264Profile = wfdVideoFormatsInfo.profile;
588     uint32_t h264Level = wfdVideoFormatsInfo.level;
589     uint32_t ceaResolutionIndex = 0;
590     uint32_t vesaResolutionIndex = 0;
591     uint32_t hhResolutionIndex = 0;
592     (void)ceaResolutionIndex;
593     (void)vesaResolutionIndex;
594     (void)hhResolutionIndex;
595     (void)h264Profile;
596     (void)h264Level;
597 
598     switch (format) {
599         case VIDEO_1920X1080_60:
600         case VIDEO_1920X1080_30:
601             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P30 << BIT_OFFSET_THREE);
602             ceaResolutionIndex = (1 << CEA_1920_1080_P30);
603             break;
604         case VIDEO_1920X1080_25:
605             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P25 << BIT_OFFSET_THREE);
606             ceaResolutionIndex = (1 << CEA_1920_1080_P25);
607             break;
608         case VIDEO_1280X720_30:
609             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P30 << BIT_OFFSET_THREE);
610             ceaResolutionIndex = (1 << CEA_1280_720_P30);
611             break;
612         case VIDEO_1280X720_25:
613             native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P25 << BIT_OFFSET_THREE);
614             ceaResolutionIndex = (1 << CEA_1280_720_P25);
615             break;
616         case VIDEO_640X480_60:
617         default:
618             native =
619                 (uint8_t)WfdResolutionType::RESOLUTION_CEA | (WfdCeaResolution::CEA_640_480_P60 << BIT_OFFSET_THREE);
620             ceaResolutionIndex = (1 << CEA_640_480_P60);
621             break;
622     }
623 
624     ss << WFD_PARAM_VIDEO_FORMATS << ":" << RTSP_SP;
625     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << native << RTSP_SP << "00" << RTSP_SP;
626     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << h264Profile << RTSP_SP;
627     ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << h264Level << RTSP_SP;
628     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << ceaResolutionIndex << RTSP_SP;
629     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << vesaResolutionIndex << RTSP_SP;
630     ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << hhResolutionIndex << RTSP_SP;
631     ss << "00 0000 0000 00 none none";
632     AddBodyItem(ss.str());
633 }
634 
Parse(const std::string & request)635 RtspError WfdRtspM4Request::Parse(const std::string &request)
636 {
637     auto res = RtspRequest::Parse(request);
638     if (res.code != RtspErrorType::OK) {
639         return res;
640     }
641 
642     RtspCommon::SplitParameter(body_, params_);
643     return {};
644 }
645 
GetParameterValue(const std::string & param)646 std::string WfdRtspM4Request::GetParameterValue(const std::string &param)
647 {
648     auto it = std::find_if(params_.begin(), params_.end(),
649                            [=](std::pair<std::string, std::string> value) { return value.first == param; });
650     if (it != params_.end()) {
651         return it->second;
652     }
653 
654     return "";
655 }
656 
GetPresentationUrl()657 std::string WfdRtspM4Request::GetPresentationUrl()
658 {
659     std::string urls = GetParameterValue(WFD_PARAM_PRESENTATION_URL);
660     if (urls.empty()) {
661         return "";
662     }
663 
664     auto urlVec = RtspCommon::Split(urls, " ");
665     if (!urlVec.empty()) {
666         return urlVec[0];
667     }
668 
669     return "";
670 }
671 
GetRtpPort()672 int32_t WfdRtspM4Request::GetRtpPort()
673 {
674     auto ports = GetParameterValue(WFD_PARAM_RTP_PORTS);
675     auto resVec = RtspCommon::Split(ports, " ");
676     if (resVec.size() > 2) { // 2: fix offset
677         return atoi(resVec[1].c_str());
678     }
679 
680     return 0;
681 }
682 
GetVideoTrack(VideoTrack & videoTrack)683 void WfdRtspM4Request::GetVideoTrack(VideoTrack &videoTrack)
684 {
685     std::string wfdVideoFormatParam = GetParameterValue(WFD_PARAM_VIDEO_FORMATS_2);
686     if (wfdVideoFormatParam.empty()) {
687         wfdVideoFormatParam = GetParameterValue(WFD_PARAM_VIDEO_FORMATS);
688     }
689     if (wfdVideoFormatParam.empty()) {
690         SHARING_LOGE("wfdVideoFormatParam is null.");
691         return;
692     }
693     std::vector<std::string> videoFormats = RtspCommon::Split(wfdVideoFormatParam, "\\s+");
694     if (videoFormats.size() <= INDEX_HH) {
695         SHARING_LOGE("video formats is invalid.");
696         return;
697     }
698     SHARING_LOGD("wfdVideoFormats native:%{public}s", videoFormats.at(0).c_str());
699     errno = 0;
700     char *endPtr = nullptr;
701     int nativeValue = std::strtol(videoFormats.front().c_str(), &endPtr, HEX_LENGTH);
702     if (errno == ERANGE || endPtr == videoFormats.front().c_str() || *endPtr != '\0') {
703         char errmsg[256] = {0};
704         strerror_r(errno, errmsg, sizeof(errmsg));
705         SHARING_LOGE("%{public}s error : %{public}s!", __FUNCTION__, errmsg);
706         return;
707     }
708 
709     std::string resolutionStr = {""};
710     nativeValue = (int32_t)((uint32_t)nativeValue & 0x07);
711     if (nativeValue == TYPE_CEA) {
712         resolutionStr = videoFormats.at(INDEX_CEA);
713     } else if (nativeValue == TYPE_VESA) {
714         resolutionStr = videoFormats.at(INDEX_VESA);
715     } else if (nativeValue == TYPE_HH) {
716         resolutionStr = videoFormats.at(INDEX_HH);
717     } else {
718         SHARING_LOGE("get wfd_video_formats error.");
719         return;
720     }
721     GetVideoResolution(videoTrack, resolutionStr, nativeValue);
722 }
723 
GetVideoResolution(VideoTrack & videoTrack,std::string resolutionStr,int type)724 void WfdRtspM4Request::GetVideoResolution(VideoTrack &videoTrack, std::string resolutionStr, int type)
725 {
726     uint32_t result = (uint32_t)strtol(resolutionStr.c_str(), nullptr, HEX_LENGTH);
727     if (result <= 0) {
728         SHARING_LOGE("get video resolution failed.");
729         return;
730     }
731     uint32_t index = log(result) / log(LOG_BASE);
732     if ((type == TYPE_CEA && index > MAX_CEA_INDEX) || (type == TYPE_VESA && index > MAX_VESA_INDEX) ||
733         (type == TYPE_HH && index > MAX_HH_INDEX)) {
734         SHARING_LOGE("get video resolution index error.");
735     }
736     const VideoConfigTable *config = &VIDEO_RESOLUTION_TABLE[type][index];
737     videoTrack.codecId = CODEC_H264;
738     videoTrack.width = config->width;
739     videoTrack.height = config->height;
740     videoTrack.frameRate = config->frameRate;
741     SHARING_LOGI("get video resolution width: %{public}d, height: %{public}d, frameRate: %{public}d,", videoTrack.width,
742                  videoTrack.height, videoTrack.frameRate);
743 }
744 
GetAudioTrack(AudioTrack & audioTrack)745 void WfdRtspM4Request::GetAudioTrack(AudioTrack &audioTrack)
746 {
747     std::string wfdAudioFormatParam = GetParameterValue(WFD_PARAM_AUDIO_CODECS_2);
748     if (wfdAudioFormatParam.empty()) {
749         wfdAudioFormatParam = GetParameterValue(WFD_PARAM_AUDIO_CODECS);
750     }
751     if (wfdAudioFormatParam.empty()) {
752         SHARING_LOGE("wfdAudioFormatParam is null.");
753         return;
754     }
755     std::vector<std::string> audioFormats = RtspCommon::Split(wfdAudioFormatParam, "\\s+");
756     if (audioFormats.size() <= AUDIO_MODE_INDEX) {
757         SHARING_LOGE("audioFormats is error.");
758         return;
759     }
760     int32_t type;
761     std::string format = audioFormats.at(AUDIO_TYPE_INDEX);
762     if (format == LPCM) {
763         type = TYPE_LPCM;
764     } else if (format == AAC) {
765         type = TYPE_AAC;
766     } else if (format == AC3) {
767         type = TYPE_AC3;
768     } else {
769         type = TYPE_AAC;
770     }
771     int32_t result = std::strtol(audioFormats.at(AUDIO_MODE_INDEX).c_str(), nullptr, HEX_LENGTH);
772     if (result <= 0) {
773         SHARING_LOGE("get mode failed.");
774         return;
775     }
776     int32_t index = log(result) / log(LOG_BASE);
777     const AudioConfigTable *config = &AUDIO_CONFIG_TABLE[type][index];
778     audioTrack.codecId = CodecId::CODEC_AAC;
779     audioTrack.sampleRate = config->sampleRate;
780     audioTrack.sampleFormat = config->sampleFormat;
781     audioTrack.channels = config->channels;
782     SHARING_LOGI("get audio format sampleRate: %{public}d, sampleFormat: %{public}d, channels: %{public}d,",
783                  audioTrack.sampleRate, audioTrack.sampleFormat, audioTrack.channels);
784 }
785 
SetTriggerMethod(const std::string & method)786 void WfdRtspM5Request::SetTriggerMethod(const std::string &method)
787 {
788     std::stringstream ss;
789     ss << WFD_PARAM_TRIGGER << ":" << RTSP_SP << method;
790 
791     body_.emplace_back(ss.str());
792 }
793 
GetTriggerMethod()794 std::string WfdRtspM5Request::GetTriggerMethod()
795 {
796     std::list<std::pair<std::string, std::string>> params;
797     RtspCommon::SplitParameter(body_, params);
798 
799     auto it = std::find_if(params.begin(), params.end(),
800                            [](std::pair<std::string, std::string> value) { return value.first == WFD_PARAM_TRIGGER; });
801     if (it != params.end()) {
802         return it->second;
803     }
804 
805     return {};
806 }
807 
GetClientPort()808 int32_t WfdRtspM6Response::GetClientPort()
809 {
810     auto transport = GetToken(RTSP_TOKEN_TRANSPORT);
811     if (transport.empty()) {
812         return 0;
813     }
814 
815     auto tsVec = RtspCommon::Split(transport, ";");
816     for (auto &item : tsVec) {
817         if (item.find("client_port=") != std::string::npos) {
818             auto val = item.substr(item.find('=') + 1);
819             return atoi(val.c_str());
820         }
821     }
822 
823     return 0;
824 }
825 
GetServerPort()826 int32_t WfdRtspM6Response::GetServerPort()
827 {
828     auto transport = GetToken(RTSP_TOKEN_TRANSPORT);
829     if (transport.empty()) {
830         return 0;
831     }
832 
833     auto tsVec = RtspCommon::Split(transport, ";");
834     for (auto &item : tsVec) {
835         if (item.find("server_port=") != std::string::npos) {
836             auto val = item.substr(item.find('=') + 1);
837             return atoi(val.c_str());
838         }
839     }
840 
841     return 0;
842 }
843 
SetClientPort(int port)844 void WfdRtspM6Response::SetClientPort(int port)
845 {
846     clientPort_ = port;
847 }
848 
SetServerPort(int port)849 void WfdRtspM6Response::SetServerPort(int port)
850 {
851     serverPort_ = port;
852 }
853 
StringifyEx()854 std::string WfdRtspM6Response::StringifyEx()
855 {
856     std::stringstream ss;
857     auto message = Stringify();
858     std::string temp = RTSP_CRLF;
859     auto nPos = message.find_last_of(RTSP_CRLF);
860     if (nPos != std::string::npos) {
861         message = message.substr(0, message.size() - temp.size());
862     }
863     ss << message << "Transport: RTP/AVP/UDP;unicast;client_port=" << clientPort_ << ";server_port=" << serverPort_
864        << RTSP_CRLF;
865     ss << RTSP_CRLF;
866     return ss.str();
867 }
868 
StringifyEx()869 std::string WfdRtspM7Response::StringifyEx()
870 {
871     std::stringstream ss;
872     auto message = Stringify();
873     std::string temp = RTSP_CRLF;
874     auto nPos = message.find_last_of(RTSP_CRLF);
875     if (nPos != std::string::npos) {
876         message = message.substr(0, message.size() - temp.size());
877     }
878     ss << message << "Range: npt=now-" << RTSP_CRLF;
879     ss << RTSP_CRLF;
880     return ss.str();
881 }
882 
883 } // namespace Sharing
884 } // namespace OHOS
885