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 ¶m : 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 ¶m)
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