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 "rtcp.h"
17e0e9324cSopenharmony_ci#include <cstring>
18e0e9324cSopenharmony_ci#include <ctime>
19e0e9324cSopenharmony_ci#include <netinet/in.h>
20e0e9324cSopenharmony_ci#include <securec.h>
21e0e9324cSopenharmony_ci#include "common/common_macro.h"
22e0e9324cSopenharmony_ci#include "common/media_log.h"
23e0e9324cSopenharmony_ci
24e0e9324cSopenharmony_cinamespace OHOS {
25e0e9324cSopenharmony_cinamespace Sharing {
26e0e9324cSopenharmony_ci
27e0e9324cSopenharmony_ci//------------------------------ RtcpHeader ------------------------------//
28e0e9324cSopenharmony_ci
29e0e9324cSopenharmony_ciint32_t RtcpHeader::GetSize() const
30e0e9324cSopenharmony_ci{
31e0e9324cSopenharmony_ci    return (1 + ntohs(length_)) << 2; // 2:byte offset
32e0e9324cSopenharmony_ci}
33e0e9324cSopenharmony_ci
34e0e9324cSopenharmony_civoid RtcpHeader::SetSize(int32_t size)
35e0e9324cSopenharmony_ci{
36e0e9324cSopenharmony_ci    length_ = htons((size >> 2) - 1); // 2:byte offset
37e0e9324cSopenharmony_ci}
38e0e9324cSopenharmony_ci
39e0e9324cSopenharmony_ciint32_t RtcpHeader::GetPaddingSize() const
40e0e9324cSopenharmony_ci{
41e0e9324cSopenharmony_ci    if (!padding_) {
42e0e9324cSopenharmony_ci        return 0;
43e0e9324cSopenharmony_ci    }
44e0e9324cSopenharmony_ci
45e0e9324cSopenharmony_ci    return ((uint8_t *)this)[GetSize() - 1];
46e0e9324cSopenharmony_ci}
47e0e9324cSopenharmony_ci
48e0e9324cSopenharmony_ci//------------------------------ common ------------------------------//
49e0e9324cSopenharmony_ci
50e0e9324cSopenharmony_cistatic inline int32_t AlignSize(int32_t bytes)
51e0e9324cSopenharmony_ci{
52e0e9324cSopenharmony_ci    return static_cast<int32_t>(((bytes + 3) >> 2) << 2); // 2:byte offset, 3:byte length
53e0e9324cSopenharmony_ci}
54e0e9324cSopenharmony_ci
55e0e9324cSopenharmony_cistatic void SetupHeader(RtcpHeader *rtcp, RtcpType type, int32_t reportCount, int32_t totalBytes)
56e0e9324cSopenharmony_ci{
57e0e9324cSopenharmony_ci    RETURN_IF_NULL(rtcp);
58e0e9324cSopenharmony_ci    rtcp->version_ = 2; // 2:byte offset
59e0e9324cSopenharmony_ci    rtcp->padding_ = 0;
60e0e9324cSopenharmony_ci    if (reportCount > 0x1F) {
61e0e9324cSopenharmony_ci        SHARING_LOGD("reportCount is too large.");
62e0e9324cSopenharmony_ci    }
63e0e9324cSopenharmony_ci
64e0e9324cSopenharmony_ci    rtcp->reportCount_ = reportCount;
65e0e9324cSopenharmony_ci    rtcp->pt_ = (uint8_t)type;
66e0e9324cSopenharmony_ci    rtcp->SetSize(totalBytes);
67e0e9324cSopenharmony_ci}
68e0e9324cSopenharmony_ci
69e0e9324cSopenharmony_cistatic void SetupPadding(RtcpHeader *rtcp, size_t paddingSize)
70e0e9324cSopenharmony_ci{
71e0e9324cSopenharmony_ci    RETURN_IF_NULL(rtcp);
72e0e9324cSopenharmony_ci
73e0e9324cSopenharmony_ci    if (paddingSize) {
74e0e9324cSopenharmony_ci        rtcp->padding_ = 1;
75e0e9324cSopenharmony_ci        ((uint8_t *)rtcp)[rtcp->GetSize() - 1] = paddingSize & 0xFF;
76e0e9324cSopenharmony_ci    } else {
77e0e9324cSopenharmony_ci        rtcp->padding_ = 0;
78e0e9324cSopenharmony_ci    }
79e0e9324cSopenharmony_ci}
80e0e9324cSopenharmony_ci
81e0e9324cSopenharmony_ci//------------------------------ RtcpSR ------------------------------//
82e0e9324cSopenharmony_ci
83e0e9324cSopenharmony_cistd::shared_ptr<RtcpSR> RtcpSR::Create(int32_t itemCount)
84e0e9324cSopenharmony_ci{
85e0e9324cSopenharmony_ci    auto realSize = sizeof(RtcpSR) - sizeof(ReportItem) + itemCount * sizeof(ReportItem);
86e0e9324cSopenharmony_ci    auto bytes = AlignSize(realSize);
87e0e9324cSopenharmony_ci    if (bytes == 0 || bytes < 0) {
88e0e9324cSopenharmony_ci        return nullptr;
89e0e9324cSopenharmony_ci    }
90e0e9324cSopenharmony_ci    auto ptr = (RtcpSR *)new char[bytes];
91e0e9324cSopenharmony_ci    if (ptr == nullptr) {
92e0e9324cSopenharmony_ci        return nullptr;
93e0e9324cSopenharmony_ci    }
94e0e9324cSopenharmony_ci    SetupHeader(ptr, RtcpType::RTCP_SR, itemCount, bytes);
95e0e9324cSopenharmony_ci    SetupPadding(ptr, bytes - realSize);
96e0e9324cSopenharmony_ci
97e0e9324cSopenharmony_ci    return std::shared_ptr<RtcpSR>(ptr, [](RtcpSR *ptr) { delete[] (char *)ptr; });
98e0e9324cSopenharmony_ci}
99e0e9324cSopenharmony_ci
100e0e9324cSopenharmony_ciRtcpSR &RtcpSR::SetNtpStamp(timeval tv)
101e0e9324cSopenharmony_ci{
102e0e9324cSopenharmony_ci    ntpmsw_ = htonl(tv.tv_sec + 0x83AA7E80); /* 0x83AA7E80 is the number of seconds from 1900 to 1970 */
103e0e9324cSopenharmony_ci    ntplsw_ = htonl((uint32_t)((double)tv.tv_usec * (double)(((uint64_t)1) << 32) * 1.0e-6)); // 32:byte offset
104e0e9324cSopenharmony_ci    return *this;
105e0e9324cSopenharmony_ci}
106e0e9324cSopenharmony_ci
107e0e9324cSopenharmony_ciRtcpSR &RtcpSR::SetNtpStamp(uint64_t unixStampMs)
108e0e9324cSopenharmony_ci{
109e0e9324cSopenharmony_ci    timeval tv;
110e0e9324cSopenharmony_ci    tv.tv_sec = unixStampMs / 1000;           // 1000:unit
111e0e9324cSopenharmony_ci    tv.tv_usec = (unixStampMs % 1000) * 1000; // 1000:unit
112e0e9324cSopenharmony_ci    return SetNtpStamp(tv);
113e0e9324cSopenharmony_ci}
114e0e9324cSopenharmony_ci
115e0e9324cSopenharmony_cistd::string RtcpSR::GetNtpStamp() const
116e0e9324cSopenharmony_ci{
117e0e9324cSopenharmony_ci    struct timeval tv;
118e0e9324cSopenharmony_ci    tv.tv_sec = ntpmsw_ - 0x83AA7E80;
119e0e9324cSopenharmony_ci    tv.tv_usec = (decltype(tv.tv_usec))(ntplsw_ / ((double)(((uint64_t)1) << 32) * 1.0e-6)); // 32:byte offset, 6:-
120e0e9324cSopenharmony_ci
121e0e9324cSopenharmony_ci    char ts[30] = {0};
122e0e9324cSopenharmony_ci    auto tm = localtime(&tv.tv_sec);
123e0e9324cSopenharmony_ci    if (tm == nullptr) {
124e0e9324cSopenharmony_ci        return {};
125e0e9324cSopenharmony_ci    }
126e0e9324cSopenharmony_ci    if (strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", tm) < 0) {
127e0e9324cSopenharmony_ci        return {};
128e0e9324cSopenharmony_ci    }
129e0e9324cSopenharmony_ci    if (sprintf_s(ts + strlen(ts), sizeof(ts) - strlen(ts), ".%06lld", static_cast<long long>(tv.tv_usec)) < 0) {
130e0e9324cSopenharmony_ci        return {};
131e0e9324cSopenharmony_ci    }
132e0e9324cSopenharmony_ci    // format: "2022-09-02 17:27:04.021154"
133e0e9324cSopenharmony_ci    return std::string(ts);
134e0e9324cSopenharmony_ci}
135e0e9324cSopenharmony_ci
136e0e9324cSopenharmony_ciuint64_t RtcpSR::GetNtpUnixStampMS() const
137e0e9324cSopenharmony_ci{
138e0e9324cSopenharmony_ci    if (ntpmsw_ < 0x83AA7E80 /*1970 year*/) {
139e0e9324cSopenharmony_ci        return 0;
140e0e9324cSopenharmony_ci    }
141e0e9324cSopenharmony_ci    struct timeval tv;
142e0e9324cSopenharmony_ci    tv.tv_sec = ntpmsw_ - 0x83AA7E80;
143e0e9324cSopenharmony_ci    tv.tv_usec = (decltype(tv.tv_usec))(ntplsw_ / ((double)(((uint64_t)1) << 32) * 1.0e-6)); // 32:byte offset, 6:-
144e0e9324cSopenharmony_ci
145e0e9324cSopenharmony_ci    return 1000 * tv.tv_sec + tv.tv_usec / 1000; // 1000:unit
146e0e9324cSopenharmony_ci}
147e0e9324cSopenharmony_ci
148e0e9324cSopenharmony_ciRtcpSR &RtcpSR::SetSsrc(uint32_t ssrc)
149e0e9324cSopenharmony_ci{
150e0e9324cSopenharmony_ci    ssrc_ = htonl(ssrc);
151e0e9324cSopenharmony_ci    return *this;
152e0e9324cSopenharmony_ci}
153e0e9324cSopenharmony_ci
154e0e9324cSopenharmony_ciuint32_t RtcpSR::GetSsrc() const
155e0e9324cSopenharmony_ci{
156e0e9324cSopenharmony_ci    return ntohl(ssrc_);
157e0e9324cSopenharmony_ci}
158e0e9324cSopenharmony_ci
159e0e9324cSopenharmony_ciRtcpSR &RtcpSR::SetPacketCount(uint32_t count)
160e0e9324cSopenharmony_ci{
161e0e9324cSopenharmony_ci    packetCount_ = htonl(count);
162e0e9324cSopenharmony_ci    return *this;
163e0e9324cSopenharmony_ci}
164e0e9324cSopenharmony_ci
165e0e9324cSopenharmony_ciuint32_t RtcpSR::GetPacketCount() const
166e0e9324cSopenharmony_ci{
167e0e9324cSopenharmony_ci    return ntohl(packetCount_);
168e0e9324cSopenharmony_ci}
169e0e9324cSopenharmony_ci
170e0e9324cSopenharmony_cistd::vector<ReportItem *> RtcpSR::GetItemList()
171e0e9324cSopenharmony_ci{
172e0e9324cSopenharmony_ci    std::vector<ReportItem *> list;
173e0e9324cSopenharmony_ci    ReportItem *ptr = &items_;
174e0e9324cSopenharmony_ci    for (int32_t i = 0; i < (int32_t)reportCount_; ++i) {
175e0e9324cSopenharmony_ci        list.emplace_back(ptr);
176e0e9324cSopenharmony_ci        ++ptr;
177e0e9324cSopenharmony_ci    }
178e0e9324cSopenharmony_ci
179e0e9324cSopenharmony_ci    return list;
180e0e9324cSopenharmony_ci}
181e0e9324cSopenharmony_ci
182e0e9324cSopenharmony_ci//------------------------------ RtcpRR ------------------------------//
183e0e9324cSopenharmony_ci
184e0e9324cSopenharmony_cistd::shared_ptr<RtcpRR> RtcpRR::Create(size_t itemCount)
185e0e9324cSopenharmony_ci{
186e0e9324cSopenharmony_ci    auto realSize = sizeof(RtcpRR) - sizeof(ReportItem) + itemCount * sizeof(ReportItem);
187e0e9324cSopenharmony_ci    auto bytes = AlignSize(realSize);
188e0e9324cSopenharmony_ci    if (bytes == 0 || bytes < 0) {
189e0e9324cSopenharmony_ci        return nullptr;
190e0e9324cSopenharmony_ci    }
191e0e9324cSopenharmony_ci    auto ptr = (RtcpRR *)new char[bytes];
192e0e9324cSopenharmony_ci    if (ptr == nullptr) {
193e0e9324cSopenharmony_ci        return nullptr;
194e0e9324cSopenharmony_ci    }
195e0e9324cSopenharmony_ci    SetupHeader(ptr, RtcpType::RTCP_RR, itemCount, bytes);
196e0e9324cSopenharmony_ci    SetupPadding(ptr, bytes - realSize);
197e0e9324cSopenharmony_ci    return std::shared_ptr<RtcpRR>(ptr, [](RtcpRR *ptr) { delete[] (char *)ptr; });
198e0e9324cSopenharmony_ci}
199e0e9324cSopenharmony_ci
200e0e9324cSopenharmony_cistd::vector<ReportItem *> RtcpRR::GetItemList()
201e0e9324cSopenharmony_ci{
202e0e9324cSopenharmony_ci    std::vector<ReportItem *> list;
203e0e9324cSopenharmony_ci    ReportItem *ptr = &items_;
204e0e9324cSopenharmony_ci    for (int32_t i = 0; i < (int32_t)reportCount_; ++i) {
205e0e9324cSopenharmony_ci        list.emplace_back(ptr);
206e0e9324cSopenharmony_ci        ++ptr;
207e0e9324cSopenharmony_ci    }
208e0e9324cSopenharmony_ci
209e0e9324cSopenharmony_ci    return list;
210e0e9324cSopenharmony_ci}
211e0e9324cSopenharmony_ci
212e0e9324cSopenharmony_ci//------------------------------ RtcpSdes ------------------------------//
213e0e9324cSopenharmony_ci
214e0e9324cSopenharmony_cisize_t SdesChunk::TotalBytes() const
215e0e9324cSopenharmony_ci{
216e0e9324cSopenharmony_ci    return AlignSize(MinSize() + txtLen_);
217e0e9324cSopenharmony_ci}
218e0e9324cSopenharmony_ci
219e0e9324cSopenharmony_ci// chunk length without variable length information
220e0e9324cSopenharmony_cisize_t SdesChunk::MinSize()
221e0e9324cSopenharmony_ci{
222e0e9324cSopenharmony_ci    return sizeof(SdesChunk) - sizeof(text_);
223e0e9324cSopenharmony_ci}
224e0e9324cSopenharmony_ci
225e0e9324cSopenharmony_cistd::shared_ptr<RtcpSdes> RtcpSdes::Create(const std::vector<std::string> &itemText)
226e0e9324cSopenharmony_ci{
227e0e9324cSopenharmony_ci    size_t itemTotalSize = 0;
228e0e9324cSopenharmony_ci    for (auto &text : itemText) {
229e0e9324cSopenharmony_ci        itemTotalSize += AlignSize(SdesChunk::MinSize() + (0xFF & text.size()));
230e0e9324cSopenharmony_ci    }
231e0e9324cSopenharmony_ci    auto realSize = sizeof(RtcpSdes) - sizeof(SdesChunk) + itemTotalSize;
232e0e9324cSopenharmony_ci    auto bytes = AlignSize(realSize);
233e0e9324cSopenharmony_ci    if (bytes == 0 || bytes < 0) {
234e0e9324cSopenharmony_ci        return nullptr;
235e0e9324cSopenharmony_ci    }
236e0e9324cSopenharmony_ci    auto ptr = (RtcpSdes *)new char[bytes];
237e0e9324cSopenharmony_ci    if (ptr == nullptr) {
238e0e9324cSopenharmony_ci        return nullptr;
239e0e9324cSopenharmony_ci    }
240e0e9324cSopenharmony_ci    memset_s(ptr, bytes, 0, bytes);
241e0e9324cSopenharmony_ci
242e0e9324cSopenharmony_ci    auto itemPtr = &ptr->chunks_;
243e0e9324cSopenharmony_ci    for (auto &text : itemText) {
244e0e9324cSopenharmony_ci        itemPtr->txtLen_ = (0xFF & text.size());
245e0e9324cSopenharmony_ci        auto ret = memcpy_s(itemPtr->text_, itemPtr->txtLen_ + 1, text.data(), itemPtr->txtLen_ + 1);
246e0e9324cSopenharmony_ci        if (ret != EOK) {
247e0e9324cSopenharmony_ci            return nullptr;
248e0e9324cSopenharmony_ci        }
249e0e9324cSopenharmony_ci        itemPtr = (SdesChunk *)((char *)itemPtr + itemPtr->TotalBytes());
250e0e9324cSopenharmony_ci    }
251e0e9324cSopenharmony_ci
252e0e9324cSopenharmony_ci    SetupHeader(ptr, RtcpType::RTCP_SDES, itemText.size(), bytes);
253e0e9324cSopenharmony_ci    SetupPadding(ptr, bytes - realSize);
254e0e9324cSopenharmony_ci    return std::shared_ptr<RtcpSdes>(ptr, [](RtcpSdes *ptr) { delete[] (char *)ptr; });
255e0e9324cSopenharmony_ci}
256e0e9324cSopenharmony_ci
257e0e9324cSopenharmony_cistd::vector<SdesChunk *> RtcpSdes::GetChunkList()
258e0e9324cSopenharmony_ci{
259e0e9324cSopenharmony_ci    std::vector<SdesChunk *> list;
260e0e9324cSopenharmony_ci    SdesChunk *ptr = &chunks_;
261e0e9324cSopenharmony_ci    for (int32_t i = 0; i < (int32_t)reportCount_; ++i) {
262e0e9324cSopenharmony_ci        list.emplace_back(ptr);
263e0e9324cSopenharmony_ci        ptr = (SdesChunk *)((char *)ptr + ptr->TotalBytes());
264e0e9324cSopenharmony_ci    }
265e0e9324cSopenharmony_ci
266e0e9324cSopenharmony_ci    return list;
267e0e9324cSopenharmony_ci}
268e0e9324cSopenharmony_ci
269e0e9324cSopenharmony_ci//------------------------------ RtcpFB ------------------------------//
270e0e9324cSopenharmony_ci
271e0e9324cSopenharmony_cistd::shared_ptr<RtcpFB> RtcpFB::Create(PsfbType fmt, const void *fci, size_t fciLen)
272e0e9324cSopenharmony_ci{
273e0e9324cSopenharmony_ci    return RtcpFB::CreateInner(RtcpType::RTCP_PSFB, (int32_t)fmt, fci, fciLen);
274e0e9324cSopenharmony_ci}
275e0e9324cSopenharmony_ci
276e0e9324cSopenharmony_cistd::shared_ptr<RtcpFB> RtcpFB::Create(RtpfbType fmt, const void *fci, size_t fciLen)
277e0e9324cSopenharmony_ci{
278e0e9324cSopenharmony_ci    return RtcpFB::CreateInner(RtcpType::RTCP_RTPFB, (int32_t)fmt, fci, fciLen);
279e0e9324cSopenharmony_ci}
280e0e9324cSopenharmony_ci
281e0e9324cSopenharmony_ciconst uint8_t *RtcpFB::GetFciPtr() const
282e0e9324cSopenharmony_ci{
283e0e9324cSopenharmony_ci    return (uint8_t *)&ssrcMedia_ + sizeof(ssrcMedia_);
284e0e9324cSopenharmony_ci}
285e0e9324cSopenharmony_ci
286e0e9324cSopenharmony_ciint32_t RtcpFB::GetFciSize() const
287e0e9324cSopenharmony_ci{
288e0e9324cSopenharmony_ci    return GetSize() - GetPaddingSize() - sizeof(RtcpFB);
289e0e9324cSopenharmony_ci}
290e0e9324cSopenharmony_ci
291e0e9324cSopenharmony_cistd::shared_ptr<RtcpFB> RtcpFB::CreateInner(RtcpType type, int32_t fmt, const void *fci, size_t fciLen)
292e0e9324cSopenharmony_ci{
293e0e9324cSopenharmony_ci    if (!fci) {
294e0e9324cSopenharmony_ci        fciLen = 0;
295e0e9324cSopenharmony_ci    }
296e0e9324cSopenharmony_ci
297e0e9324cSopenharmony_ci    auto realSize = sizeof(RtcpFB) + fciLen;
298e0e9324cSopenharmony_ci    auto bytes = AlignSize(realSize);
299e0e9324cSopenharmony_ci    if (bytes == 0 || bytes < 0) {
300e0e9324cSopenharmony_ci        return nullptr;
301e0e9324cSopenharmony_ci    }
302e0e9324cSopenharmony_ci    auto ptr = (RtcpFB *)new char[bytes];
303e0e9324cSopenharmony_ci    if (fci && fciLen) {
304e0e9324cSopenharmony_ci        auto ret = memcpy_s((char *)ptr + sizeof(RtcpFB), fciLen, fci, fciLen);
305e0e9324cSopenharmony_ci        if (ret != EOK) {
306e0e9324cSopenharmony_ci            return nullptr;
307e0e9324cSopenharmony_ci        }
308e0e9324cSopenharmony_ci    }
309e0e9324cSopenharmony_ci    SetupHeader(ptr, type, fmt, bytes);
310e0e9324cSopenharmony_ci    SetupPadding(ptr, bytes - realSize);
311e0e9324cSopenharmony_ci    return std::shared_ptr<RtcpFB>((RtcpFB *)ptr, [](RtcpFB *ptr) { delete[] (char *)ptr; });
312e0e9324cSopenharmony_ci}
313e0e9324cSopenharmony_ci
314e0e9324cSopenharmony_ci//------------------------------ RtcpBye ------------------------------//
315e0e9324cSopenharmony_ci
316e0e9324cSopenharmony_cistd::shared_ptr<RtcpBye> RtcpBye::Create(const std::vector<uint32_t> &ssrcs, const std::string &reason)
317e0e9324cSopenharmony_ci{
318e0e9324cSopenharmony_ci    auto realSize = sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size() + 1 + reason.size();
319e0e9324cSopenharmony_ci    auto bytes = AlignSize(realSize);
320e0e9324cSopenharmony_ci    if (bytes == 0 || bytes < 0) {
321e0e9324cSopenharmony_ci        return nullptr;
322e0e9324cSopenharmony_ci    }
323e0e9324cSopenharmony_ci    auto ptr = (RtcpBye *)new char[bytes];
324e0e9324cSopenharmony_ci    if (ptr == nullptr) {
325e0e9324cSopenharmony_ci        return nullptr;
326e0e9324cSopenharmony_ci    }
327e0e9324cSopenharmony_ci    SetupHeader(ptr, RtcpType::RTCP_BYE, ssrcs.size(), bytes);
328e0e9324cSopenharmony_ci    SetupPadding(ptr, bytes - realSize);
329e0e9324cSopenharmony_ci
330e0e9324cSopenharmony_ci    int32_t i = 0;
331e0e9324cSopenharmony_ci    for (auto ssrc : ssrcs) {
332e0e9324cSopenharmony_ci        ((RtcpBye *)ptr)->ssrc_[i++] = htonl(ssrc);
333e0e9324cSopenharmony_ci    }
334e0e9324cSopenharmony_ci
335e0e9324cSopenharmony_ci    if (!reason.empty()) {
336e0e9324cSopenharmony_ci        uint8_t *reasonLenPtr = (uint8_t *)ptr + sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size();
337e0e9324cSopenharmony_ci        *reasonLenPtr = reason.size() & 0xFF;
338e0e9324cSopenharmony_ci        auto ret = memcpy_s(reasonLenPtr + 1, *reasonLenPtr, reason.data(), *reasonLenPtr);
339e0e9324cSopenharmony_ci        if (ret != EOK) {
340e0e9324cSopenharmony_ci            return nullptr;
341e0e9324cSopenharmony_ci        }
342e0e9324cSopenharmony_ci    }
343e0e9324cSopenharmony_ci
344e0e9324cSopenharmony_ci    return std::shared_ptr<RtcpBye>(ptr, [](RtcpBye *ptr) { delete[] (char *)ptr; });
345e0e9324cSopenharmony_ci}
346e0e9324cSopenharmony_ci
347e0e9324cSopenharmony_cistd::vector<uint32_t> RtcpBye::GetSSRC() const
348e0e9324cSopenharmony_ci{
349e0e9324cSopenharmony_ci    std::vector<uint32_t> ret;
350e0e9324cSopenharmony_ci    for (size_t i = 0; i < reportCount_; ++i) {
351e0e9324cSopenharmony_ci        ret.emplace_back(ntohl(ssrc_[i]));
352e0e9324cSopenharmony_ci    }
353e0e9324cSopenharmony_ci
354e0e9324cSopenharmony_ci    return ret;
355e0e9324cSopenharmony_ci}
356e0e9324cSopenharmony_ci
357e0e9324cSopenharmony_cistd::string RtcpBye::GetReason() const
358e0e9324cSopenharmony_ci{
359e0e9324cSopenharmony_ci    auto *reasonLenPtr = (uint8_t *)ssrc_ + sizeof(uint32_t) * reportCount_;
360e0e9324cSopenharmony_ci    if (reasonLenPtr + 1 >= (uint8_t *)this + GetSize()) {
361e0e9324cSopenharmony_ci        return "";
362e0e9324cSopenharmony_ci    }
363e0e9324cSopenharmony_ci
364e0e9324cSopenharmony_ci    return std::string((char *)reasonLenPtr + 1, *reasonLenPtr);
365e0e9324cSopenharmony_ci}
366e0e9324cSopenharmony_ci
367e0e9324cSopenharmony_ci//-----------------------------------------------------------------------------
368e0e9324cSopenharmony_ci
369e0e9324cSopenharmony_cistd::shared_ptr<RtcpXRDLRR> RtcpXRDLRR::Create(size_t itemCount)
370e0e9324cSopenharmony_ci{
371e0e9324cSopenharmony_ci    auto realSize = sizeof(RtcpXRDLRR) - sizeof(RtcpXRDLRRReportItem) + itemCount * sizeof(RtcpXRDLRRReportItem);
372e0e9324cSopenharmony_ci    auto bytes = AlignSize(realSize);
373e0e9324cSopenharmony_ci    if (bytes == 0 || bytes < 0) {
374e0e9324cSopenharmony_ci        return nullptr;
375e0e9324cSopenharmony_ci    }
376e0e9324cSopenharmony_ci    auto ptr = (RtcpXRDLRR *)new char[bytes];
377e0e9324cSopenharmony_ci    if (ptr == nullptr) {
378e0e9324cSopenharmony_ci        return nullptr;
379e0e9324cSopenharmony_ci    }
380e0e9324cSopenharmony_ci    SetupHeader(ptr, RtcpType::RTCP_XR, 0, bytes);
381e0e9324cSopenharmony_ci    SetupPadding(ptr, bytes - realSize);
382e0e9324cSopenharmony_ci    return std::shared_ptr<RtcpXRDLRR>(ptr, [](RtcpXRDLRR *ptr) { delete[] (char *)ptr; });
383e0e9324cSopenharmony_ci}
384e0e9324cSopenharmony_ci
385e0e9324cSopenharmony_cistd::vector<RtcpXRDLRRReportItem *> RtcpXRDLRR::GetItemList()
386e0e9324cSopenharmony_ci{
387e0e9324cSopenharmony_ci    auto count = blockLength_ / 3;
388e0e9324cSopenharmony_ci    RtcpXRDLRRReportItem *ptr = &items_;
389e0e9324cSopenharmony_ci    std::vector<RtcpXRDLRRReportItem *> list;
390e0e9324cSopenharmony_ci    for (int32_t i = 0; i < (int32_t)count; ++i) {
391e0e9324cSopenharmony_ci        list.emplace_back(ptr);
392e0e9324cSopenharmony_ci        ++ptr;
393e0e9324cSopenharmony_ci    }
394e0e9324cSopenharmony_ci
395e0e9324cSopenharmony_ci    return list;
396e0e9324cSopenharmony_ci}
397e0e9324cSopenharmony_ci
398e0e9324cSopenharmony_ci} // namespace Sharing
399e0e9324cSopenharmony_ci} // namespace OHOS