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