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