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 "rtcp_context.h"
17 #include <netinet/in.h>
18 #include "common/common_macro.h"
19 #include "common/media_log.h"
20 #include "utils/utils.h"
21
22 namespace OHOS {
23 namespace Sharing {
OnRtp(uint16_t , uint32_t stamp, uint64_t ntpStampMs, uint32_t , size_t bytes)24 void RtcpContext::OnRtp(uint16_t /*seq*/, uint32_t stamp, uint64_t ntpStampMs, uint32_t /*sampleRate*/, size_t bytes)
25 {
26 ++packets_;
27 bytes_ += bytes;
28 lastRtpStamp_ = stamp;
29 lastNtpStampMs_ = ntpStampMs;
30 }
31
32 //------------------------------ RtcpSenderContext ------------------------------//
CreateRtcpSR(uint32_t rtcpSSRC)33 DataBuffer::Ptr RtcpSenderContext::CreateRtcpSR(uint32_t rtcpSSRC)
34 {
35 auto rtcp = RtcpSR::Create(0);
36 rtcp->SetNtpStamp(lastNtpStampMs_);
37 rtcp->rtpts_ = htonl(lastRtpStamp_);
38 rtcp->ssrc_ = htonl(rtcpSSRC);
39 rtcp->packetCount_ = htonl((uint32_t)packets_);
40 rtcp->octetCount_ = htonl((uint32_t)bytes_);
41
42 auto lastSrLsr =
43 ((ntohl(rtcp->ntpmsw_) & 0xFFFF) << 16) | ((ntohl(rtcp->ntplsw_) >> 16) & 0xFFFF); // 16:byte offset
44 senderReportNtp_[lastSrLsr] = GetCurrentMillisecond();
45 if (senderReportNtp_.size() >= 5) { // 5:fixed capacity
46 senderReportNtp_.erase(senderReportNtp_.begin());
47 }
48
49 DataBuffer::Ptr ret = std::make_shared<DataBuffer>();
50 ret->PushData((char *)rtcp.get(), rtcp->GetSize());
51 return ret;
52 }
53
OnRtcp(RtcpHeader *rtcp)54 void RtcpSenderContext::OnRtcp(RtcpHeader *rtcp)
55 {
56 RETURN_IF_NULL(rtcp);
57 switch ((RtcpType)rtcp->pt_) {
58 case RtcpType::RTCP_RR: {
59 auto rtcpRR = (RtcpRR *)rtcp;
60 for (auto &item : rtcpRR->GetItemList()) {
61 if (!item->lastSrStamp_) {
62 continue;
63 }
64 auto it = senderReportNtp_.find(item->lastSrStamp_);
65 if (it == senderReportNtp_.end()) {
66 continue;
67 }
68 // time: sender (send SR) -> receiver (recv SR) -> receiver (send RR) -> sender (recv RR)
69 auto msInc = GetCurrentMillisecond() - it->second;
70 // time: receiver (recv SR) -> receiver (send RR)
71 auto delayMs = (uint64_t)item->delaySinceLastSr_ * 1000 / 65536; // 1000:unit, 65536:max seq
72 // time: [sender (send SR) -> receiver (recv SR)] + [receiver (send RR) -> sender (recv RR)]
73 auto rtt = (int32_t)(msInc - delayMs);
74 if (rtt >= 0) {
75 rtt_[item->ssrc_] = rtt;
76 }
77 }
78 break;
79 }
80 case RtcpType::RTCP_XR: {
81 auto rtcp_xr = (RtcpXRRRTR *)rtcp;
82 if (rtcp_xr->bt_ == 4) { // 4:xrXrrtr
83 xrXrrtrRecvLastRr_[rtcp_xr->ssrc_] =
84 ((rtcp_xr->ntpmsw_ & 0xFFFF) << 16) | ((rtcp_xr->ntplsw_ >> 16) & 0xFFFF); // 16:byte offset
85 xrRrtrRecvSysStamp_[rtcp_xr->ssrc_] = GetCurrentMillisecond();
86 } else if (rtcp_xr->bt_ == 5) { // 5:dlrr
87 SHARING_LOGD("for sender not recive dlrr.");
88 } else {
89 SHARING_LOGD("not support xr bt.");
90 }
91 break;
92 }
93 default:
94 break;
95 }
96 }
97
CreateRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc)98 DataBuffer::Ptr RtcpSenderContext::CreateRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc)
99 {
100 return nullptr;
101 }
102
GetRtt(uint32_t ssrc) const103 uint32_t RtcpSenderContext::GetRtt(uint32_t ssrc) const
104 {
105 auto it = rtt_.find(ssrc);
106 if (it == rtt_.end()) {
107 return 0;
108 }
109
110 return it->second;
111 }
112
113 //------------------------------ RtcpReceiverContext ------------------------------//
OnRtp(uint16_t seq, uint32_t stamp, uint64_t ntpStampMs, uint32_t sampleRate, size_t bytes)114 void RtcpReceiverContext::OnRtp(uint16_t seq, uint32_t stamp, uint64_t ntpStampMs, uint32_t sampleRate, size_t bytes)
115 {
116 // the receiver performs complex statistical operations
117 auto sysStamp = GetCurrentMillisecond();
118 if (lastRtpSysStamp_) {
119 // calculate timestamp jitter value
120 double diff = double((int64_t(sysStamp) - int64_t(lastRtpSysStamp_)) * (sampleRate / double(1000.0)) -
121 (int64_t(stamp) - int64_t(lastRtpStamp_)));
122 if (diff < 0) {
123 diff = -diff;
124 }
125 // jitter unit: sampling numbers
126 jitter_ += (diff - jitter_) / 16.0; // 16.0:jitter unit
127 } else {
128 jitter_ = 0;
129 }
130
131 if (lastRtpSeq_ > 0xFF00 && seq < 0xFF && (!seqCycles_ || packets_ - lastCyclePackets_ > 0x1FFF)) {
132 // if the last seq > 0xff00 and the current seq < 0xff,
133 // and no loopback occurs or the interval from the last loopback exceeds 0x1fff packets,
134 // the loopback is considered
135 ++seqCycles_;
136 lastCyclePackets_ = packets_;
137 seqMax_ = seq;
138 } else if (seq > seqMax_) {
139 // maximum seq before loop back
140 seqMax_ = seq;
141 }
142
143 if (!seqBase_) {
144 // record the first rtp's seq
145 seqBase_ = seq;
146 } else if (!seqCycles_ && seq < seqBase_) {
147 // if no loopback occurs, the latest seq is taken as the base seq
148 seqBase_ = seq;
149 }
150
151 lastRtpSeq_ = seq;
152 lastRtpSysStamp_ = sysStamp;
153
154 RtcpContext::OnRtp(seq, stamp, ntpStampMs, sampleRate, bytes);
155 }
156
OnRtcp(RtcpHeader *rtcp)157 void RtcpReceiverContext::OnRtcp(RtcpHeader *rtcp)
158 {
159 RETURN_IF_NULL(rtcp);
160 switch ((RtcpType)rtcp->pt_) {
161 case RtcpType::RTCP_SR: {
162 auto rtcpSR = (RtcpSR *)rtcp;
163 // last SR timestamp (LSR): 32 bits
164 // The middle 32 bits out of 64 in the NTP timestamp (as explained in
165 // Section 4) received as part of the most recent RTCP sender report
166 // (SR) packet from source SSRC_n. If no SR has been received yet,
167 // the field is set to zero.
168 lastSrLsr_ = (((ntohl(rtcpSR->ntpmsw_) & 0xffff) << 16) | // 16:byte offset
169 ((ntohl(rtcpSR->ntplsw_) >> 16) & 0xffff)); // 16:byte offset
170 lastSrNtpSys_ = GetCurrentMillisecond();
171 break;
172 }
173 default:
174 break;
175 }
176 }
177
CreateRtcpRR(uint32_t rtcpSSRC, uint32_t rtpSSRC)178 DataBuffer::Ptr RtcpReceiverContext::CreateRtcpRR(uint32_t rtcpSSRC, uint32_t rtpSSRC)
179 {
180 auto rtcp = RtcpRR::Create(1);
181 if (rtcp == nullptr) {
182 return nullptr;
183 }
184
185 rtcp->ssrc_ = htonl(rtcpSSRC);
186
187 ReportItem *item = (ReportItem *)&rtcp->items_;
188 if (item == nullptr) {
189 return nullptr;
190 }
191
192 item->ssrc_ = htonl(rtpSSRC);
193
194 uint8_t fraction = 0;
195 auto expectedInterval = GetExpectedPacketsInterval();
196 if (expectedInterval != 0) {
197 fraction = uint8_t((GetLostInterval() << 8) / expectedInterval); // 8:byte offset
198 }
199
200 // fraction = packet loss rate (percentage) * 256
201 item->fractionLost_ = fraction;
202 item->cumulative_ = htonl(uint32_t(GetLost())) >> 8; // 8:byte offset
203 item->seqCycles_ = htons(seqCycles_);
204 item->seqMax_ = htons(seqMax_);
205 item->jitter_ = htonl(uint32_t(jitter_));
206 item->lastSrStamp_ = htonl(lastSrLsr_);
207
208 // now - recv Last SR time
209 auto delay = GetCurrentMillisecond() - lastSrNtpSys_;
210 // in units of 1/65536 seconds
211 auto dlsr = (uint32_t)(delay / 1000.0f * 65536); // 1000.0:unit, 65536:max seq
212 item->delaySinceLastSr_ = htonl(lastSrLsr_ ? dlsr : 0);
213
214 DataBuffer::Ptr ret = std::make_shared<DataBuffer>();
215 ret->PushData((char *)rtcp.get(), rtcp->GetSize());
216 return ret;
217 }
218
GetExpectedPackets() const219 size_t RtcpReceiverContext::GetExpectedPackets() const
220 {
221 return (seqCycles_ << 16) + seqMax_ - seqBase_ + 1; // 16:byte offset
222 }
223
GetExpectedPacketsInterval()224 size_t RtcpReceiverContext::GetExpectedPacketsInterval()
225 {
226 auto expected = GetExpectedPackets();
227 auto ret = expected - lastExpected_;
228 lastExpected_ = expected;
229 return ret;
230 }
231
GetLost()232 size_t RtcpReceiverContext::GetLost()
233 {
234 return GetExpectedPackets() - packets_;
235 }
236
GetLostInterval()237 size_t RtcpReceiverContext::GetLostInterval()
238 {
239 auto lost = GetLost();
240 auto ret = lost - lastLost_;
241 lastLost_ = lost;
242 return ret;
243 }
244
245 } // namespace Sharing
246 } // namespace OHOS