1e0e9324cSopenharmony_ci/*
2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License.
5e0e9324cSopenharmony_ci * You may obtain a copy of the License at
6e0e9324cSopenharmony_ci *
7e0e9324cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0e9324cSopenharmony_ci *
9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and
13e0e9324cSopenharmony_ci * limitations under the License.
14e0e9324cSopenharmony_ci */
15e0e9324cSopenharmony_ci
16e0e9324cSopenharmony_ci#include "wfd_message.h"
17e0e9324cSopenharmony_ci#include <iomanip>
18e0e9324cSopenharmony_ci#include <iostream>
19e0e9324cSopenharmony_ci#include <sstream>
20e0e9324cSopenharmony_ci#include <cstdio>
21e0e9324cSopenharmony_ci#include "common/sharing_log.h"
22e0e9324cSopenharmony_ci
23e0e9324cSopenharmony_cinamespace OHOS {
24e0e9324cSopenharmony_cinamespace Sharing {
25e0e9324cSopenharmony_ciconstexpr int32_t BIT_OFFSET_TWO = 2;
26e0e9324cSopenharmony_ciconstexpr int32_t BIT_OFFSET_THREE = 3;
27e0e9324cSopenharmony_ciconstexpr int32_t BIT_OFFSET_EIGHT = 8;
28e0e9324cSopenharmony_ci
29e0e9324cSopenharmony_ciWfdRtspM1Response::WfdRtspM1Response(int32_t cseq, int32_t status) : RtspResponseOptions(cseq, status)
30e0e9324cSopenharmony_ci{
31e0e9324cSopenharmony_ci    std::stringstream ss;
32e0e9324cSopenharmony_ci    ss << RTSP_METHOD_WFD << "," << RTSP_SP << RTSP_METHOD_SET_PARAMETER << "," << RTSP_SP << RTSP_METHOD_GET_PARAMETER;
33e0e9324cSopenharmony_ci    SetPublicItems(ss.str());
34e0e9324cSopenharmony_ci}
35e0e9324cSopenharmony_ci
36e0e9324cSopenharmony_ciRtspError WfdRtspM3Response::Parse(const std::string &response)
37e0e9324cSopenharmony_ci{
38e0e9324cSopenharmony_ci    auto res = RtspResponse::Parse(response);
39e0e9324cSopenharmony_ci    if (res.code != RtspErrorType::OK) {
40e0e9324cSopenharmony_ci        return res;
41e0e9324cSopenharmony_ci    }
42e0e9324cSopenharmony_ci
43e0e9324cSopenharmony_ci    RtspCommon::SplitParameter(body_, params_);
44e0e9324cSopenharmony_ci    return {};
45e0e9324cSopenharmony_ci}
46e0e9324cSopenharmony_ci
47e0e9324cSopenharmony_cistd::string WfdRtspM3Response::Stringify()
48e0e9324cSopenharmony_ci{
49e0e9324cSopenharmony_ci    std::stringstream body;
50e0e9324cSopenharmony_ci    std::stringstream ss;
51e0e9324cSopenharmony_ci
52e0e9324cSopenharmony_ci    for (auto &param : params_) {
53e0e9324cSopenharmony_ci        body << param.first << ":" << RTSP_SP << param.second << RTSP_CRLF;
54e0e9324cSopenharmony_ci    }
55e0e9324cSopenharmony_ci
56e0e9324cSopenharmony_ci    ss << RTSP_TOKEN_CONTENT_TYPE << ":" << RTSP_SP << "text/parameters" << RTSP_CRLF;
57e0e9324cSopenharmony_ci    ss << RTSP_TOKEN_CONTENT_LENGTH << ":" << RTSP_SP << body.str().length();
58e0e9324cSopenharmony_ci
59e0e9324cSopenharmony_ci    ClearCustomHeader();
60e0e9324cSopenharmony_ci    AddCustomHeader(ss.str());
61e0e9324cSopenharmony_ci
62e0e9324cSopenharmony_ci    if (body.str().empty()) {
63e0e9324cSopenharmony_ci        return RtspResponse::Stringify();
64e0e9324cSopenharmony_ci    }
65e0e9324cSopenharmony_ci
66e0e9324cSopenharmony_ci    return RtspResponse::Stringify() + body.str();
67e0e9324cSopenharmony_ci}
68e0e9324cSopenharmony_ci
69e0e9324cSopenharmony_civoid WfdRtspM3Response::SetVideoFormats(VideoFormat format)
70e0e9324cSopenharmony_ci{
71e0e9324cSopenharmony_ci    std::stringstream ss;
72e0e9324cSopenharmony_ci    std::stringstream sinkVideoList;
73e0e9324cSopenharmony_ci
74e0e9324cSopenharmony_ci    uint8_t native = 0;
75e0e9324cSopenharmony_ci    uint8_t h264Profile = (1 << (uint8_t)WfdH264Profile::PROFILE_CHP);
76e0e9324cSopenharmony_ci    uint8_t h264Level = (1 << (uint8_t)WfdH264Level::LEVEL_42);
77e0e9324cSopenharmony_ci    uint32_t ceaResolutionIndex = 0;
78e0e9324cSopenharmony_ci    uint32_t vesaResolutionIndex = 0;
79e0e9324cSopenharmony_ci    uint32_t hhResolutionIndex = 0;
80e0e9324cSopenharmony_ci
81e0e9324cSopenharmony_ci    switch (format) {
82e0e9324cSopenharmony_ci        case VIDEO_1920X1080_30:
83e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P30 << BIT_OFFSET_THREE);
84e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1920_1080_P30);
85e0e9324cSopenharmony_ci            break;
86e0e9324cSopenharmony_ci        case VIDEO_1920X1080_25:
87e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P25 << BIT_OFFSET_THREE);
88e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1920_1080_P25);
89e0e9324cSopenharmony_ci            break;
90e0e9324cSopenharmony_ci        case VIDEO_1280X720_30:
91e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P30 << BIT_OFFSET_THREE);
92e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1280_720_P30);
93e0e9324cSopenharmony_ci            break;
94e0e9324cSopenharmony_ci        case VIDEO_1280X720_25:
95e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P25 << BIT_OFFSET_THREE);
96e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1280_720_P25);
97e0e9324cSopenharmony_ci            break;
98e0e9324cSopenharmony_ci        case VIDEO_640X480_60:
99e0e9324cSopenharmony_ci        default:
100e0e9324cSopenharmony_ci            native =
101e0e9324cSopenharmony_ci                (uint8_t)WfdResolutionType::RESOLUTION_CEA | (WfdCeaResolution::CEA_640_480_P60 << BIT_OFFSET_THREE);
102e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_640_480_P60);
103e0e9324cSopenharmony_ci            break;
104e0e9324cSopenharmony_ci    }
105e0e9324cSopenharmony_ci
106e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << (int32_t)native << RTSP_SP << "00" << RTSP_SP;
107e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << (int32_t)h264Profile << RTSP_SP;
108e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << (int32_t)h264Level << RTSP_SP;
109e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << ceaResolutionIndex << RTSP_SP;
110e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << vesaResolutionIndex << RTSP_SP;
111e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << hhResolutionIndex << RTSP_SP;
112e0e9324cSopenharmony_ci
113e0e9324cSopenharmony_ci    ss << "00 0000 0000 00 none none";
114e0e9324cSopenharmony_ci
115e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_VIDEO_FORMATS, ss.str());
116e0e9324cSopenharmony_ci}
117e0e9324cSopenharmony_ci
118e0e9324cSopenharmony_civoid WfdRtspM3Response::SetAudioCodecs(AudioFormat format)
119e0e9324cSopenharmony_ci{
120e0e9324cSopenharmony_ci    std::stringstream ss;
121e0e9324cSopenharmony_ci    switch (format) {
122e0e9324cSopenharmony_ci        case AUDIO_44100_8_2:
123e0e9324cSopenharmony_ci            ss << "LPCM" << RTSP_SP << "00000001 00";
124e0e9324cSopenharmony_ci            break;
125e0e9324cSopenharmony_ci        case AUDIO_44100_16_2:
126e0e9324cSopenharmony_ci            ss << "LPCM" << RTSP_SP << "00000002 00";
127e0e9324cSopenharmony_ci            break;
128e0e9324cSopenharmony_ci        case AUDIO_48000_16_2:
129e0e9324cSopenharmony_ci            ss << "AAC" << RTSP_SP << "00000001 00";
130e0e9324cSopenharmony_ci            break;
131e0e9324cSopenharmony_ci        default:
132e0e9324cSopenharmony_ci            ss << "AAC" << RTSP_SP << "00000001 00";
133e0e9324cSopenharmony_ci            break;
134e0e9324cSopenharmony_ci    }
135e0e9324cSopenharmony_ci
136e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_AUDIO_CODECS, ss.str());
137e0e9324cSopenharmony_ci}
138e0e9324cSopenharmony_ci
139e0e9324cSopenharmony_civoid WfdRtspM3Response::SetClientRtpPorts(int32_t port)
140e0e9324cSopenharmony_ci{
141e0e9324cSopenharmony_ci    std::stringstream ss;
142e0e9324cSopenharmony_ci    ss << "RTP/AVP/UDP;unicast" << RTSP_SP << port << RTSP_SP << 0 << RTSP_SP << "mode=play";
143e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_RTP_PORTS, ss.str());
144e0e9324cSopenharmony_ci}
145e0e9324cSopenharmony_ci
146e0e9324cSopenharmony_civoid WfdRtspM3Response::SetContentProtection(const std::string &value)
147e0e9324cSopenharmony_ci{
148e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_CONTENT_PROTECTION, value);
149e0e9324cSopenharmony_ci}
150e0e9324cSopenharmony_ci
151e0e9324cSopenharmony_civoid WfdRtspM3Response::SetCoupledSink(const std::string &value)
152e0e9324cSopenharmony_ci{
153e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_COUPLED_SINK, value);
154e0e9324cSopenharmony_ci}
155e0e9324cSopenharmony_ci
156e0e9324cSopenharmony_civoid WfdRtspM3Response::SetUibcCapability(const std::string &value)
157e0e9324cSopenharmony_ci{
158e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_UIBC_CAPABILITY, value);
159e0e9324cSopenharmony_ci}
160e0e9324cSopenharmony_ci
161e0e9324cSopenharmony_civoid WfdRtspM3Response::SetStandbyResumeCapability(const std::string &value)
162e0e9324cSopenharmony_ci{
163e0e9324cSopenharmony_ci    params_.emplace_back(WFD_PARAM_UIBC_CAPABILITY, value);
164e0e9324cSopenharmony_ci}
165e0e9324cSopenharmony_ci
166e0e9324cSopenharmony_civoid WfdRtspM3Response::SetCustomParam(const std::string &key, const std::string &value)
167e0e9324cSopenharmony_ci{
168e0e9324cSopenharmony_ci    params_.emplace_back(key, value);
169e0e9324cSopenharmony_ci}
170e0e9324cSopenharmony_ci
171e0e9324cSopenharmony_ciint32_t WfdRtspM3Response::GetClientRtpPorts()
172e0e9324cSopenharmony_ci{
173e0e9324cSopenharmony_ci    int32_t port0 = -1;
174e0e9324cSopenharmony_ci    int32_t port1 = -1;
175e0e9324cSopenharmony_ci    std::string profile = "RTP/AVP/UDP;unicast";
176e0e9324cSopenharmony_ci    std::string mode = "mode=play";
177e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_RTP_PORTS);
178e0e9324cSopenharmony_ci    std::stringstream ss(value);
179e0e9324cSopenharmony_ci    ss >> profile >> port0 >> port1 >> mode;
180e0e9324cSopenharmony_ci    return port0;
181e0e9324cSopenharmony_ci}
182e0e9324cSopenharmony_ci
183e0e9324cSopenharmony_cistd::string WfdRtspM3Response::GetUibcCapability()
184e0e9324cSopenharmony_ci{
185e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_UIBC_CAPABILITY);
186e0e9324cSopenharmony_ci    return value;
187e0e9324cSopenharmony_ci}
188e0e9324cSopenharmony_ci
189e0e9324cSopenharmony_ciAudioFormat WfdRtspM3Response::GetAudioCodecs(WfdAudioCodec &codec)
190e0e9324cSopenharmony_ci{
191e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_AUDIO_CODECS);
192e0e9324cSopenharmony_ci    int32_t audioFormat0 = -1;
193e0e9324cSopenharmony_ci    int32_t audioFormat1 = -1;
194e0e9324cSopenharmony_ci    std::string format;
195e0e9324cSopenharmony_ci    auto audioCaps = RtspCommon::Split(value, ", ");
196e0e9324cSopenharmony_ci    for (size_t i = 0; i < audioCaps.size(); i++) {
197e0e9324cSopenharmony_ci        std::string audioCap = audioCaps[i];
198e0e9324cSopenharmony_ci        std::stringstream ss(audioCap);
199e0e9324cSopenharmony_ci        ss >> format >> audioFormat0 >> audioFormat1;
200e0e9324cSopenharmony_ci        if (format == "LPCM") { // LPCM
201e0e9324cSopenharmony_ci            if (codec.codecId != CODEC_AAC && audioFormat0 > 1) {
202e0e9324cSopenharmony_ci                codec.codecId = CODEC_PCM;
203e0e9324cSopenharmony_ci                codec.format = AUDIO_48000_16_2;
204e0e9324cSopenharmony_ci            }
205e0e9324cSopenharmony_ci        } else if (format == "AAC") { // AAC
206e0e9324cSopenharmony_ci            codec.codecId = CODEC_AAC;
207e0e9324cSopenharmony_ci            codec.format = AUDIO_48000_16_2;
208e0e9324cSopenharmony_ci        } else if (format == "AC3") { // AC3
209e0e9324cSopenharmony_ci            if (audioFormat0 == 1) {
210e0e9324cSopenharmony_ci            }
211e0e9324cSopenharmony_ci            continue;
212e0e9324cSopenharmony_ci        }
213e0e9324cSopenharmony_ci    }
214e0e9324cSopenharmony_ci
215e0e9324cSopenharmony_ci    return codec.format;
216e0e9324cSopenharmony_ci}
217e0e9324cSopenharmony_ci
218e0e9324cSopenharmony_cistd::string WfdRtspM3Response::GetCoupledSink()
219e0e9324cSopenharmony_ci{
220e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_COUPLED_SINK);
221e0e9324cSopenharmony_ci    return value;
222e0e9324cSopenharmony_ci}
223e0e9324cSopenharmony_ci
224e0e9324cSopenharmony_cistd::string WfdRtspM3Response::GetContentProtection()
225e0e9324cSopenharmony_ci{
226e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_CONTENT_PROTECTION);
227e0e9324cSopenharmony_ci    return value;
228e0e9324cSopenharmony_ci}
229e0e9324cSopenharmony_ci
230e0e9324cSopenharmony_ciVideoFormat WfdRtspM3Response::GetVideoFormatsByCea(int index)
231e0e9324cSopenharmony_ci{
232e0e9324cSopenharmony_ci    WfdCeaResolution res = static_cast<WfdCeaResolution>(index);
233e0e9324cSopenharmony_ci    switch (res) {
234e0e9324cSopenharmony_ci        case CEA_640_480_P60:
235e0e9324cSopenharmony_ci            return VIDEO_640X480_60;
236e0e9324cSopenharmony_ci        case CEA_1280_720_P30:
237e0e9324cSopenharmony_ci            return VIDEO_1280X720_30;
238e0e9324cSopenharmony_ci        case CEA_1280_720_P60:
239e0e9324cSopenharmony_ci            return VIDEO_1280X720_60;
240e0e9324cSopenharmony_ci        case CEA_1920_1080_P25:
241e0e9324cSopenharmony_ci            return VIDEO_1920X1080_25;
242e0e9324cSopenharmony_ci        case CEA_1920_1080_P30:
243e0e9324cSopenharmony_ci            return VIDEO_1920X1080_30;
244e0e9324cSopenharmony_ci        case CEA_1920_1080_P60:
245e0e9324cSopenharmony_ci            return VIDEO_1920X1080_60;
246e0e9324cSopenharmony_ci        default:
247e0e9324cSopenharmony_ci            return VIDEO_640X480_60;
248e0e9324cSopenharmony_ci    }
249e0e9324cSopenharmony_ci}
250e0e9324cSopenharmony_ci
251e0e9324cSopenharmony_ciVideoFormat WfdRtspM3Response::GetVideoFormats()
252e0e9324cSopenharmony_ci{
253e0e9324cSopenharmony_ci    // wfd_video_formats:
254e0e9324cSopenharmony_ci    // 1 byte "native"
255e0e9324cSopenharmony_ci    // 1 byte "preferred-display-mode-supported" 0 or 1
256e0e9324cSopenharmony_ci    // one or more avc codec structures
257e0e9324cSopenharmony_ci    //   1 byte profile
258e0e9324cSopenharmony_ci    //   1 byte level
259e0e9324cSopenharmony_ci    //   4 byte CEA mask
260e0e9324cSopenharmony_ci    //   4 byte VESA mask
261e0e9324cSopenharmony_ci    //   4 byte HH mask
262e0e9324cSopenharmony_ci    //   1 byte latency
263e0e9324cSopenharmony_ci    //   2 byte min-slice-slice
264e0e9324cSopenharmony_ci    //   2 byte slice-enc-params
265e0e9324cSopenharmony_ci    //   1 byte framerate-control-support
266e0e9324cSopenharmony_ci    //   max-hres (none or 2 byte)
267e0e9324cSopenharmony_ci    //   max-vres (none or 2 byte)
268e0e9324cSopenharmony_ci    /**
269e0e9324cSopenharmony_ci     * native:  2*2HEXDIG
270e0e9324cSopenharmony_ci     * preferred-display-mode-supported: 2*2HEXDIG; 0-not supported, 1-supported, 2-255 reserved
271e0e9324cSopenharmony_ci     * profile: 2*2HEXDIG, only one bit set
272e0e9324cSopenharmony_ci     * level:   2*2HEXDIG, only one bit set
273e0e9324cSopenharmony_ci     * CEA-Support: 8*8HEXDIG, 0-ignore
274e0e9324cSopenharmony_ci     * VESA-Support:8*8HEXDIG, 0-ignore
275e0e9324cSopenharmony_ci     * HH-Support:  8*8HEXDIG, 0-ignore
276e0e9324cSopenharmony_ci     * latency:     2*2HEXDIG, decoder latency in units of 5 msecs
277e0e9324cSopenharmony_ci     * min-slice-size: 4*4HEXDIG, number of macroblocks
278e0e9324cSopenharmony_ci     * slice-enc-params: 4*4HEXDIG,
279e0e9324cSopenharmony_ci     * frame-rate-control-support: 4*4HEXDIG
280e0e9324cSopenharmony_ci     * max-hres: 4*4HEXDIG, "none" if preferred-display-mode-supported is 0
281e0e9324cSopenharmony_ci     * max-vres: 4*4HEXDIG, "none" if preferred-display-mode-supported is 0
282e0e9324cSopenharmony_ci     **/
283e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_VIDEO_FORMATS);
284e0e9324cSopenharmony_ci    if (value.size() < MINIMAL_VIDEO_FORMAT_SIZE) {
285e0e9324cSopenharmony_ci        return VIDEO_640X480_60;
286e0e9324cSopenharmony_ci    }
287e0e9324cSopenharmony_ci
288e0e9324cSopenharmony_ci    std::string head = value.substr(0, 5); // 5: fix offset
289e0e9324cSopenharmony_ci    uint16_t native = 0;
290e0e9324cSopenharmony_ci    uint16_t preferredDisplayMode = 0;
291e0e9324cSopenharmony_ci    int index = 0;
292e0e9324cSopenharmony_ci    std::string temp = "";
293e0e9324cSopenharmony_ci    bool run = true;
294e0e9324cSopenharmony_ci    std::stringstream ss(head);
295e0e9324cSopenharmony_ci    ss >> std::hex >> native >> std::hex >> preferredDisplayMode;
296e0e9324cSopenharmony_ci    value = value.substr(5); // 5: fix offset
297e0e9324cSopenharmony_ci
298e0e9324cSopenharmony_ci    while (run) {
299e0e9324cSopenharmony_ci        auto nPos = value.find_first_of(",", index + 1);
300e0e9324cSopenharmony_ci        if (nPos != std::string::npos) {
301e0e9324cSopenharmony_ci            index = nPos;
302e0e9324cSopenharmony_ci            temp = value.substr(0, index);
303e0e9324cSopenharmony_ci        } else {
304e0e9324cSopenharmony_ci            temp = value.substr(index + 1);
305e0e9324cSopenharmony_ci            run = false;
306e0e9324cSopenharmony_ci        }
307e0e9324cSopenharmony_ci        std::stringstream sss(temp);
308e0e9324cSopenharmony_ci        WfdVideoFormatsInfo wfdVideoFormatsInfo;
309e0e9324cSopenharmony_ci        wfdVideoFormatsInfo.native = native;
310e0e9324cSopenharmony_ci        wfdVideoFormatsInfo.preferredDisplayMode = preferredDisplayMode;
311e0e9324cSopenharmony_ci        sss >> std::hex >> wfdVideoFormatsInfo.profile >> std::hex >> wfdVideoFormatsInfo.level >> std::hex >>
312e0e9324cSopenharmony_ci            wfdVideoFormatsInfo.ceaMask >> std::hex >> wfdVideoFormatsInfo.veaMask >> std::hex >>
313e0e9324cSopenharmony_ci            wfdVideoFormatsInfo.hhMask >> std::hex >> wfdVideoFormatsInfo.latency >> std::hex >>
314e0e9324cSopenharmony_ci            wfdVideoFormatsInfo.minSlice >> std::hex >> wfdVideoFormatsInfo.sliceEncParam >> std::hex >>
315e0e9324cSopenharmony_ci            wfdVideoFormatsInfo.frameRateCtlSupport;
316e0e9324cSopenharmony_ci        vWfdVideoFormatsInfo_.push_back(wfdVideoFormatsInfo);
317e0e9324cSopenharmony_ci    }
318e0e9324cSopenharmony_ci
319e0e9324cSopenharmony_ci    uint8_t tableSelection = vWfdVideoFormatsInfo_[0].native & 0x7;
320e0e9324cSopenharmony_ci    index = vWfdVideoFormatsInfo_[0].native >> BIT_OFFSET_THREE;
321e0e9324cSopenharmony_ci    switch (tableSelection) {
322e0e9324cSopenharmony_ci        case 0:
323e0e9324cSopenharmony_ci            return GetVideoFormatsByCea(index);
324e0e9324cSopenharmony_ci        default:
325e0e9324cSopenharmony_ci            return VIDEO_640X480_60;
326e0e9324cSopenharmony_ci    }
327e0e9324cSopenharmony_ci    return VIDEO_640X480_60;
328e0e9324cSopenharmony_ci}
329e0e9324cSopenharmony_ci
330e0e9324cSopenharmony_cistd::string WfdRtspM3Response::GetStandbyResumeCapability()
331e0e9324cSopenharmony_ci{
332e0e9324cSopenharmony_ci    std::string value = GetCustomParam(WFD_PARAM_STANDBY_RESUME);
333e0e9324cSopenharmony_ci    return value;
334e0e9324cSopenharmony_ci}
335e0e9324cSopenharmony_ci
336e0e9324cSopenharmony_cistd::string WfdRtspM3Response::GetCustomParam(const std::string &key)
337e0e9324cSopenharmony_ci{
338e0e9324cSopenharmony_ci    auto it = std::find_if(params_.begin(), params_.end(),
339e0e9324cSopenharmony_ci                           [=](std::pair<std::string, std::string> value) { return value.first == key; });
340e0e9324cSopenharmony_ci    if (it != params_.end()) {
341e0e9324cSopenharmony_ci        return it->second;
342e0e9324cSopenharmony_ci    }
343e0e9324cSopenharmony_ci
344e0e9324cSopenharmony_ci    return "";
345e0e9324cSopenharmony_ci}
346e0e9324cSopenharmony_ci
347e0e9324cSopenharmony_civoid WfdRtspM4Request::SetClientRtpPorts(int32_t port)
348e0e9324cSopenharmony_ci{
349e0e9324cSopenharmony_ci    std::stringstream ss;
350e0e9324cSopenharmony_ci    ss << WFD_PARAM_RTP_PORTS << ":" << RTSP_SP << "RTP/AVP/UDP;unicast" << RTSP_SP << port << RTSP_SP << 0 << RTSP_SP
351e0e9324cSopenharmony_ci       << "mode=play";
352e0e9324cSopenharmony_ci    AddBodyItem(ss.str());
353e0e9324cSopenharmony_ci}
354e0e9324cSopenharmony_ci
355e0e9324cSopenharmony_civoid WfdRtspM4Request::SetAudioCodecs(WfdAudioCodec &codec)
356e0e9324cSopenharmony_ci{
357e0e9324cSopenharmony_ci    std::stringstream ss;
358e0e9324cSopenharmony_ci    ss << WFD_PARAM_AUDIO_CODECS << ":" << RTSP_SP;
359e0e9324cSopenharmony_ci
360e0e9324cSopenharmony_ci    switch (codec.codecId) {
361e0e9324cSopenharmony_ci        case CODEC_PCM:
362e0e9324cSopenharmony_ci            ss << "LPCM" << RTSP_SP << "00000002 00";
363e0e9324cSopenharmony_ci            break;
364e0e9324cSopenharmony_ci        case CODEC_AAC:
365e0e9324cSopenharmony_ci            ss << "AAC" << RTSP_SP << "00000001 00";
366e0e9324cSopenharmony_ci            break;
367e0e9324cSopenharmony_ci        default:
368e0e9324cSopenharmony_ci            ss << "AAC" << RTSP_SP << "00000001 00";
369e0e9324cSopenharmony_ci            break;
370e0e9324cSopenharmony_ci    }
371e0e9324cSopenharmony_ci
372e0e9324cSopenharmony_ci    AddBodyItem(ss.str());
373e0e9324cSopenharmony_ci}
374e0e9324cSopenharmony_ci
375e0e9324cSopenharmony_civoid WfdRtspM4Request::SetPresentationUrl(const std::string &ip)
376e0e9324cSopenharmony_ci{
377e0e9324cSopenharmony_ci    std::stringstream ss;
378e0e9324cSopenharmony_ci    ss << WFD_PARAM_PRESENTATION_URL << ":" << RTSP_SP << "rtsp://" << ip.c_str() << "/wfd1.0/streamid=0 none";
379e0e9324cSopenharmony_ci    AddBodyItem(ss.str());
380e0e9324cSopenharmony_ci}
381e0e9324cSopenharmony_ci
382e0e9324cSopenharmony_civoid WfdRtspM4Request::SetVideoFormats(const WfdVideoFormatsInfo &wfdVideoFormatsInfo, VideoFormat format)
383e0e9324cSopenharmony_ci{
384e0e9324cSopenharmony_ci    std::stringstream ss;
385e0e9324cSopenharmony_ci    uint32_t native = wfdVideoFormatsInfo.native;
386e0e9324cSopenharmony_ci    uint32_t h264Profile = wfdVideoFormatsInfo.profile;
387e0e9324cSopenharmony_ci    uint32_t h264Level = wfdVideoFormatsInfo.level;
388e0e9324cSopenharmony_ci    uint32_t ceaResolutionIndex = 0;
389e0e9324cSopenharmony_ci    uint32_t vesaResolutionIndex = 0;
390e0e9324cSopenharmony_ci    uint32_t hhResolutionIndex = 0;
391e0e9324cSopenharmony_ci    (void)ceaResolutionIndex;
392e0e9324cSopenharmony_ci    (void)vesaResolutionIndex;
393e0e9324cSopenharmony_ci    (void)hhResolutionIndex;
394e0e9324cSopenharmony_ci    (void)h264Profile;
395e0e9324cSopenharmony_ci    (void)h264Level;
396e0e9324cSopenharmony_ci
397e0e9324cSopenharmony_ci    switch (format) {
398e0e9324cSopenharmony_ci        case VIDEO_1920X1080_60:
399e0e9324cSopenharmony_ci        case VIDEO_1920X1080_30:
400e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P30 << BIT_OFFSET_THREE);
401e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1920_1080_P30);
402e0e9324cSopenharmony_ci            break;
403e0e9324cSopenharmony_ci        case VIDEO_1920X1080_25:
404e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1920_1080_P25 << BIT_OFFSET_THREE);
405e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1920_1080_P25);
406e0e9324cSopenharmony_ci            break;
407e0e9324cSopenharmony_ci        case VIDEO_1280X720_30:
408e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P30 << BIT_OFFSET_THREE);
409e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1280_720_P30);
410e0e9324cSopenharmony_ci            break;
411e0e9324cSopenharmony_ci        case VIDEO_1280X720_25:
412e0e9324cSopenharmony_ci            native = (uint8_t)WfdResolutionType::RESOLUTION_CEA | (CEA_1280_720_P25 << BIT_OFFSET_THREE);
413e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_1280_720_P25);
414e0e9324cSopenharmony_ci            break;
415e0e9324cSopenharmony_ci        case VIDEO_640X480_60:
416e0e9324cSopenharmony_ci        default:
417e0e9324cSopenharmony_ci            native =
418e0e9324cSopenharmony_ci                (uint8_t)WfdResolutionType::RESOLUTION_CEA | (WfdCeaResolution::CEA_640_480_P60 << BIT_OFFSET_THREE);
419e0e9324cSopenharmony_ci            ceaResolutionIndex = (1 << CEA_640_480_P60);
420e0e9324cSopenharmony_ci            break;
421e0e9324cSopenharmony_ci    }
422e0e9324cSopenharmony_ci
423e0e9324cSopenharmony_ci    ss << WFD_PARAM_VIDEO_FORMATS << ":" << RTSP_SP;
424e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << native << RTSP_SP << "00" << RTSP_SP;
425e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << h264Profile << RTSP_SP;
426e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_TWO) << std::hex << h264Level << RTSP_SP;
427e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << ceaResolutionIndex << RTSP_SP;
428e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << vesaResolutionIndex << RTSP_SP;
429e0e9324cSopenharmony_ci    ss << std::setfill('0') << std::setw(BIT_OFFSET_EIGHT) << std::hex << hhResolutionIndex << RTSP_SP;
430e0e9324cSopenharmony_ci    ss << "00 0000 0000 00 none none";
431e0e9324cSopenharmony_ci    AddBodyItem(ss.str());
432e0e9324cSopenharmony_ci}
433e0e9324cSopenharmony_ci
434e0e9324cSopenharmony_ciRtspError WfdRtspM4Request::Parse(const std::string &request)
435e0e9324cSopenharmony_ci{
436e0e9324cSopenharmony_ci    auto res = RtspRequest::Parse(request);
437e0e9324cSopenharmony_ci    if (res.code != RtspErrorType::OK) {
438e0e9324cSopenharmony_ci        return res;
439e0e9324cSopenharmony_ci    }
440e0e9324cSopenharmony_ci
441e0e9324cSopenharmony_ci    RtspCommon::SplitParameter(body_, params_);
442e0e9324cSopenharmony_ci    return {};
443e0e9324cSopenharmony_ci}
444e0e9324cSopenharmony_ci
445e0e9324cSopenharmony_cistd::string WfdRtspM4Request::GetParameterValue(const std::string &param)
446e0e9324cSopenharmony_ci{
447e0e9324cSopenharmony_ci    auto it = std::find_if(params_.begin(), params_.end(),
448e0e9324cSopenharmony_ci                           [=](std::pair<std::string, std::string> value) { return value.first == param; });
449e0e9324cSopenharmony_ci    if (it != params_.end()) {
450e0e9324cSopenharmony_ci        return it->second;
451e0e9324cSopenharmony_ci    }
452e0e9324cSopenharmony_ci
453e0e9324cSopenharmony_ci    return "";
454e0e9324cSopenharmony_ci}
455e0e9324cSopenharmony_ci
456e0e9324cSopenharmony_cistd::string WfdRtspM4Request::GetPresentationUrl()
457e0e9324cSopenharmony_ci{
458e0e9324cSopenharmony_ci    std::string urls = GetParameterValue(WFD_PARAM_PRESENTATION_URL);
459e0e9324cSopenharmony_ci    if (urls.empty()) {
460e0e9324cSopenharmony_ci        return "";
461e0e9324cSopenharmony_ci    }
462e0e9324cSopenharmony_ci
463e0e9324cSopenharmony_ci    auto urlVec = RtspCommon::Split(urls, " ");
464e0e9324cSopenharmony_ci    if (!urlVec.empty()) {
465e0e9324cSopenharmony_ci        return urlVec[0];
466e0e9324cSopenharmony_ci    }
467e0e9324cSopenharmony_ci
468e0e9324cSopenharmony_ci    return "";
469e0e9324cSopenharmony_ci}
470e0e9324cSopenharmony_ci
471e0e9324cSopenharmony_ciint32_t WfdRtspM4Request::GetRtpPort()
472e0e9324cSopenharmony_ci{
473e0e9324cSopenharmony_ci    auto ports = GetParameterValue(WFD_PARAM_RTP_PORTS);
474e0e9324cSopenharmony_ci    auto resVec = RtspCommon::Split(ports, " ");
475e0e9324cSopenharmony_ci    if (resVec.size() > 2) { // 2: fix offset
476e0e9324cSopenharmony_ci        return atoi(resVec[1].c_str());
477e0e9324cSopenharmony_ci    }
478e0e9324cSopenharmony_ci
479e0e9324cSopenharmony_ci    return 0;
480e0e9324cSopenharmony_ci}
481e0e9324cSopenharmony_ci
482e0e9324cSopenharmony_civoid WfdRtspM5Request::SetTriggerMethod(const std::string &method)
483e0e9324cSopenharmony_ci{
484e0e9324cSopenharmony_ci    std::stringstream ss;
485e0e9324cSopenharmony_ci    ss << WFD_PARAM_TRIGGER << ":" << RTSP_SP << method;
486e0e9324cSopenharmony_ci
487e0e9324cSopenharmony_ci    body_.emplace_back(ss.str());
488e0e9324cSopenharmony_ci}
489e0e9324cSopenharmony_ci
490e0e9324cSopenharmony_cistd::string WfdRtspM5Request::GetTriggerMethod()
491e0e9324cSopenharmony_ci{
492e0e9324cSopenharmony_ci    std::list<std::pair<std::string, std::string>> params;
493e0e9324cSopenharmony_ci    RtspCommon::SplitParameter(body_, params);
494e0e9324cSopenharmony_ci
495e0e9324cSopenharmony_ci    auto it = std::find_if(params.begin(), params.end(),
496e0e9324cSopenharmony_ci                           [](std::pair<std::string, std::string> value) { return value.first == WFD_PARAM_TRIGGER; });
497e0e9324cSopenharmony_ci    if (it != params.end()) {
498e0e9324cSopenharmony_ci        return it->second;
499e0e9324cSopenharmony_ci    }
500e0e9324cSopenharmony_ci
501e0e9324cSopenharmony_ci    return {};
502e0e9324cSopenharmony_ci}
503e0e9324cSopenharmony_ci
504e0e9324cSopenharmony_ciint32_t WfdRtspM6Response::GetClientPort()
505e0e9324cSopenharmony_ci{
506e0e9324cSopenharmony_ci    auto transport = GetToken(RTSP_TOKEN_TRANSPORT);
507e0e9324cSopenharmony_ci    if (transport.empty()) {
508e0e9324cSopenharmony_ci        return 0;
509e0e9324cSopenharmony_ci    }
510e0e9324cSopenharmony_ci
511e0e9324cSopenharmony_ci    auto tsVec = RtspCommon::Split(transport, ";");
512e0e9324cSopenharmony_ci    for (auto &item : tsVec) {
513e0e9324cSopenharmony_ci        if (item.find("client_port=") != std::string::npos) {
514e0e9324cSopenharmony_ci            auto val = item.substr(item.find('=') + 1);
515e0e9324cSopenharmony_ci            return atoi(val.c_str());
516e0e9324cSopenharmony_ci        }
517e0e9324cSopenharmony_ci    }
518e0e9324cSopenharmony_ci
519e0e9324cSopenharmony_ci    return 0;
520e0e9324cSopenharmony_ci}
521e0e9324cSopenharmony_ci
522e0e9324cSopenharmony_ciint32_t WfdRtspM6Response::GetServerPort()
523e0e9324cSopenharmony_ci{
524e0e9324cSopenharmony_ci    auto transport = GetToken(RTSP_TOKEN_TRANSPORT);
525e0e9324cSopenharmony_ci    if (transport.empty()) {
526e0e9324cSopenharmony_ci        return 0;
527e0e9324cSopenharmony_ci    }
528e0e9324cSopenharmony_ci
529e0e9324cSopenharmony_ci    auto tsVec = RtspCommon::Split(transport, ";");
530e0e9324cSopenharmony_ci    for (auto &item : tsVec) {
531e0e9324cSopenharmony_ci        if (item.find("server_port=") != std::string::npos) {
532e0e9324cSopenharmony_ci            auto val = item.substr(item.find('=') + 1);
533e0e9324cSopenharmony_ci            return atoi(val.c_str());
534e0e9324cSopenharmony_ci        }
535e0e9324cSopenharmony_ci    }
536e0e9324cSopenharmony_ci
537e0e9324cSopenharmony_ci    return 0;
538e0e9324cSopenharmony_ci}
539e0e9324cSopenharmony_ci
540e0e9324cSopenharmony_civoid WfdRtspM6Response::SetClientPort(int port)
541e0e9324cSopenharmony_ci{
542e0e9324cSopenharmony_ci    clientPort_ = port;
543e0e9324cSopenharmony_ci}
544e0e9324cSopenharmony_ci
545e0e9324cSopenharmony_civoid WfdRtspM6Response::SetServerPort(int port)
546e0e9324cSopenharmony_ci{
547e0e9324cSopenharmony_ci    serverPort_ = port;
548e0e9324cSopenharmony_ci}
549e0e9324cSopenharmony_ci
550e0e9324cSopenharmony_cistd::string WfdRtspM6Response::StringifyEx()
551e0e9324cSopenharmony_ci{
552e0e9324cSopenharmony_ci    std::stringstream ss;
553e0e9324cSopenharmony_ci    auto message = Stringify();
554e0e9324cSopenharmony_ci    std::string temp = RTSP_CRLF;
555e0e9324cSopenharmony_ci    auto nPos = message.find_last_of(RTSP_CRLF);
556e0e9324cSopenharmony_ci    if (nPos != std::string::npos) {
557e0e9324cSopenharmony_ci        message = message.substr(0, message.size() - temp.size());
558e0e9324cSopenharmony_ci    }
559e0e9324cSopenharmony_ci    ss << message << "Transport: RTP/AVP/UDP;unicast;client_port=" << clientPort_ << ";server_port=" << serverPort_
560e0e9324cSopenharmony_ci       << RTSP_CRLF;
561e0e9324cSopenharmony_ci    ss << RTSP_CRLF;
562e0e9324cSopenharmony_ci    return ss.str();
563e0e9324cSopenharmony_ci}
564e0e9324cSopenharmony_ci
565e0e9324cSopenharmony_cistd::string WfdRtspM7Response::StringifyEx()
566e0e9324cSopenharmony_ci{
567e0e9324cSopenharmony_ci    std::stringstream ss;
568e0e9324cSopenharmony_ci    auto message = Stringify();
569e0e9324cSopenharmony_ci    std::string temp = RTSP_CRLF;
570e0e9324cSopenharmony_ci    auto nPos = message.find_last_of(RTSP_CRLF);
571e0e9324cSopenharmony_ci    if (nPos != std::string::npos) {
572e0e9324cSopenharmony_ci        message = message.substr(0, message.size() - temp.size());
573e0e9324cSopenharmony_ci    }
574e0e9324cSopenharmony_ci    ss << message << "Range: npt=now-" << RTSP_CRLF;
575e0e9324cSopenharmony_ci    ss << RTSP_CRLF;
576e0e9324cSopenharmony_ci    return ss.str();
577e0e9324cSopenharmony_ci}
578e0e9324cSopenharmony_ci
579e0e9324cSopenharmony_ci} // namespace Sharing
580e0e9324cSopenharmony_ci} // namespace OHOS
581