• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <webrtc/RTPSender.h>
18 
19 #include "Utils.h"
20 
21 #include <webrtc/RTPSocketHandler.h>
22 
23 #include <https/SafeCallbackable.h>
24 #include <https/Support.h>
25 
26 #include <random>
27 #include <unordered_set>
28 
29 #define SIMULATE_PACKET_LOSS    0
30 
RTPSender(std::shared_ptr<RunLoop> runLoop,RTPSocketHandler * parent,std::shared_ptr<Packetizer> videoPacketizer,std::shared_ptr<Packetizer> audioPacketizer)31 RTPSender::RTPSender(
32         std::shared_ptr<RunLoop> runLoop,
33         RTPSocketHandler *parent,
34         std::shared_ptr<Packetizer> videoPacketizer,
35         std::shared_ptr<Packetizer> audioPacketizer)
36     : mRunLoop(runLoop),
37       mParent(parent),
38       mVideoPacketizer(videoPacketizer),
39       mAudioPacketizer(audioPacketizer) {
40 }
41 
addSource(uint32_t ssrc)42 void RTPSender::addSource(uint32_t ssrc) {
43     CHECK(mSources.insert(
44                 std::make_pair(ssrc, SourceInfo())).second);
45 }
46 
addRetransInfo(uint32_t ssrc,uint8_t PT,uint32_t retransSSRC,uint8_t retransPT)47 void RTPSender::addRetransInfo(
48         uint32_t ssrc, uint8_t PT, uint32_t retransSSRC, uint8_t retransPT) {
49     auto it = mSources.find(ssrc);
50     CHECK(it != mSources.end());
51 
52     auto &info = it->second;
53 
54     CHECK(info.mRetrans.insert(
55                 std::make_pair(
56                     PT, std::make_pair(retransSSRC, retransPT))).second);
57 }
58 
injectRTCP(uint8_t * data,size_t size)59 int RTPSender::injectRTCP(uint8_t *data, size_t size) {
60     // LOG(INFO) << "RTPSender::injectRTCP";
61     // hexdump(data, size);
62 
63     while (size > 0) {
64         if (size < 8) {
65             return -EINVAL;
66         }
67 
68         if ((data[0] >> 6) != 2) {
69             // Wrong version.
70             return -EINVAL;
71         }
72 
73         size_t lengthInWords = U16_AT(&data[2]) + 1;
74 
75         bool hasPadding = (data[0] & 0x20);
76 
77         size_t headerSize = 4 * lengthInWords;
78 
79         if (size < headerSize) {
80             return -EINVAL;
81         }
82 
83         if (hasPadding) {
84             if (size != headerSize) {
85                 // Padding should only be added to the last packet in a compound
86                 // packet.
87                 return -EINVAL;
88             }
89 
90             size_t numPadBytes = data[headerSize - 1];
91             if (numPadBytes == 0 || (numPadBytes % 4) != 0) {
92                 return -EINVAL;
93             }
94 
95             headerSize -= numPadBytes;
96         }
97 
98         auto err = processRTCP(data, headerSize);
99 
100         if (err) {
101             return err;
102         }
103 
104         data += 4 * lengthInWords;
105         size -= 4 * lengthInWords;
106     }
107 
108     return 0;
109 }
110 
processRTCP(const uint8_t * data,size_t size)111 int RTPSender::processRTCP(const uint8_t *data, size_t size) {
112     static constexpr uint8_t RR = 201;     // RFC 3550
113     // static constexpr uint8_t SDES = 202;
114     // static constexpr uint8_t BYE = 203;
115     // static constexpr uint8_t APP = 204;
116     static constexpr uint8_t RTPFB = 205;  // RFC 4585
117     static constexpr uint8_t PSFB = 206;
118     static constexpr uint8_t XR = 207;  // RFC 3611
119 
120     unsigned PT = data[1];
121 
122     switch (PT) {
123         case RR:
124         {
125             unsigned RC = data[0] & 0x1f;
126             if (size != 8 + RC * 6 * 4) {
127                 return -EINVAL;
128             }
129 
130             auto senderSSRC = U32_AT(&data[4]);
131 
132             size_t offset = 8;
133             for (unsigned i = 0; i < RC; ++i) {
134                 auto SSRC = U32_AT(&data[offset]);
135                 auto fractionLost = data[offset + 4];
136                 auto cumPacketsLost = U32_AT(&data[offset + 4]) & 0xffffff;
137 
138                 if (fractionLost) {
139                     LOG(INFO)
140                         << "sender SSRC "
141                         << StringPrintf("0x%08x", senderSSRC)
142                         << " reports "
143                         << StringPrintf("%.2f %%", (double)fractionLost * 100.0 / 256.0)
144                         << " lost, cum. total: "
145                         << cumPacketsLost
146                         << " from SSRC "
147                         << StringPrintf("0x%08x", SSRC);
148                 }
149 
150                 offset += 6 * 4;
151             }
152             break;
153         }
154 
155         case RTPFB:
156         {
157             static constexpr uint8_t NACK = 1;
158 
159             if (size < 12) {
160                 return -EINVAL;
161             }
162 
163             unsigned fmt = data[0] & 0x1f;
164 
165             auto senderSSRC = U32_AT(&data[4]);
166             auto SSRC = U32_AT(&data[8]);
167 
168             switch (fmt) {
169                 case NACK:
170                 {
171                     size_t offset = 12;
172                     size_t n = (size - offset) / 4;
173                     for (size_t i = 0; i < n; ++i) {
174                         auto PID = U16_AT(&data[offset]);
175                         auto BLP = U16_AT(&data[offset + 2]);
176 
177                         LOG(INFO)
178                             << "SSRC "
179                             << StringPrintf("0x%08x", senderSSRC)
180                             << " reports NACK w/ PID="
181                             << StringPrintf("0x%04x", PID)
182                             << ", BLP="
183                             << StringPrintf("0x%04x", BLP)
184                             << " from SSRC "
185                             << StringPrintf("0x%08x", SSRC);
186 
187                         offset += 4;
188 
189                         retransmitPackets(SSRC, PID, BLP);
190                     }
191                     break;
192                 }
193 
194                 default:
195                 {
196                     LOG(WARNING) << "RTPSender::processRTCP unhandled RTPFB.";
197                     hexdump(data, size);
198                     break;
199                 }
200             }
201 
202             break;
203         }
204 
205         case PSFB:
206         {
207             static constexpr uint8_t FMT_PLI = 1;
208             static constexpr uint8_t FMT_SLI = 2;
209             static constexpr uint8_t FMT_AFB = 15;
210 
211             if (size < 12) {
212                 return -EINVAL;
213             }
214 
215             unsigned fmt = data[0] & 0x1f;
216 
217             auto SSRC = U32_AT(&data[4]);
218 
219             switch (fmt) {
220                 case FMT_PLI:
221                 {
222                     if (size != 12) {
223                         return -EINVAL;
224                     }
225 
226                     LOG(INFO)
227                         << "Received PLI from SSRC "
228                         << StringPrintf("0x%08x", SSRC);
229 
230                     if (mVideoPacketizer) {
231                         mVideoPacketizer->requestIDRFrame();
232                     }
233                     break;
234                 }
235 
236                 case FMT_SLI:
237                 {
238                     LOG(INFO)
239                         << "Received SLI from SSRC "
240                         << StringPrintf("0x%08x", SSRC);
241 
242                     break;
243                 }
244 
245                 case FMT_AFB:
246                     break;
247 
248                 default:
249                 {
250                     LOG(WARNING) << "RTPSender::processRTCP unhandled PSFB.";
251                     hexdump(data, size);
252                     break;
253                 }
254             }
255             break;
256         }
257 
258         case XR:
259         {
260             static constexpr uint8_t FMT_RRTRB = 4;
261 
262             if (size < 8) {
263                 return -EINVAL;
264             }
265 
266             auto senderSSRC = U32_AT(&data[4]);
267 
268             size_t offset = 8;
269             while (offset + 3 < size) {
270                 auto fmt = data[offset];
271                 auto blockLength = 4 * (1 + U16_AT(&data[offset + 2]));
272 
273                 if (offset + blockLength > size) {
274                     LOG(WARNING) << "Found incomplete XR report block.";
275                     break;
276                 }
277 
278                 switch (fmt) {
279                     case FMT_RRTRB:
280                     {
281                         if (blockLength != 12) {
282                             LOG(WARNING)
283                                 << "Found XR-RRTRB block of invalid length.";
284                             break;
285                         }
286 
287                         auto ntpHi = U32_AT(&data[offset + 4]);
288                         auto ntpLo = U32_AT(&data[offset + 8]);
289 
290                         queueDLRR(
291                                 0xdeadbeef /* localSSRC */,
292                                 senderSSRC,
293                                 ntpHi,
294                                 ntpLo);
295                         break;
296                     }
297 
298                     default:
299                     {
300                         LOG(WARNING)
301                             << "Ignoring unknown XR block type " << fmt;
302 
303                         break;
304                     }
305                 }
306 
307                 offset += blockLength;
308             }
309 
310             if (offset != size) {
311                 LOG(WARNING) << "Found trailing bytes in XR report.";
312             }
313             break;
314         }
315 
316         default:
317         {
318             LOG(WARNING) << "RTPSender::processRTCP unhandled packet type.";
319             hexdump(data, size);
320         }
321     }
322 
323     return 0;
324 }
325 
appendSR(std::vector<uint8_t> * buffer,uint32_t localSSRC)326 void RTPSender::appendSR(std::vector<uint8_t> *buffer, uint32_t localSSRC) {
327     static constexpr uint8_t SR = 200;
328 
329     auto it = mSources.find(localSSRC);
330     CHECK(it != mSources.end());
331 
332     const auto &info = it->second;
333 
334     const size_t kLengthInWords = 7;
335 
336     auto offset = buffer->size();
337     buffer->resize(offset + kLengthInWords * sizeof(uint32_t));
338 
339     uint8_t *data = buffer->data() + offset;
340 
341     data[0] = 0x80;
342     data[1] = SR;
343     SET_U16(&data[2], kLengthInWords - 1);
344     SET_U32(&data[4], localSSRC);
345 
346     auto now = std::chrono::system_clock::now();
347 
348     auto us_since_epoch =
349         std::chrono::duration_cast<std::chrono::microseconds>(
350             now.time_since_epoch()).count();
351 
352     // This assumes that sd::chrono::system_clock's epoch is unix epoch, i.e.
353     // 1/1/1970 midnight UTC.
354     // Microseconds between midnight 1/1/1970 and midnight 1/1/1900.
355     us_since_epoch += 2208988800ULL * 1000ull;
356 
357     uint64_t ntpHi = us_since_epoch / 1000000ll;
358     uint64_t ntpLo = ((1LL << 32) * (us_since_epoch % 1000000LL)) / 1000000LL;
359 
360     uint32_t rtpNow =
361         (localSSRC == 0xdeadbeef || localSSRC == 0xcafeb0b0)
362             ? mVideoPacketizer->rtpNow()
363             : mAudioPacketizer->rtpNow();
364 
365     SET_U32(&data[8], ntpHi);
366     SET_U32(&data[12], ntpLo);
367     SET_U32(&data[16], rtpNow);
368     SET_U32(&data[20], info.mNumPacketsSent);
369     SET_U32(&data[24], info.mNumBytesSent);
370 }
371 
appendSDES(std::vector<uint8_t> * buffer,uint32_t localSSRC)372 void RTPSender::appendSDES(std::vector<uint8_t> *buffer, uint32_t localSSRC) {
373     static constexpr uint8_t SDES = 202;
374 
375     static const char *const kCNAME = "myWebRTP";
376     static const size_t kCNAMELength = strlen(kCNAME);
377 
378     const size_t kLengthInWords = 2 + (2 + kCNAMELength + 1 + 3) / 4;
379 
380     auto offset = buffer->size();
381     buffer->resize(offset + kLengthInWords * sizeof(uint32_t));
382 
383     uint8_t *data = buffer->data() + offset;
384 
385     data[0] = 0x81;
386     data[1] = SDES;
387     SET_U16(&data[2], kLengthInWords - 1);
388     SET_U32(&data[4], localSSRC);
389 
390     data[8] = 1; // CNAME
391     data[9] = kCNAMELength;
392     memcpy(&data[10], kCNAME, kCNAMELength);
393     data[10 + kCNAMELength] = '\0';
394 }
395 
queueDLRR(uint32_t localSSRC,uint32_t remoteSSRC,uint32_t ntpHi,uint32_t ntpLo)396 void RTPSender::queueDLRR(
397         uint32_t localSSRC,
398         uint32_t remoteSSRC,
399         uint32_t ntpHi,
400         uint32_t ntpLo) {
401     std::vector<uint8_t> buffer;
402     appendDLRR(&buffer, localSSRC, remoteSSRC, ntpHi, ntpLo);
403 
404     mParent->queueRTCPDatagram(buffer.data(), buffer.size());
405 }
406 
appendDLRR(std::vector<uint8_t> * buffer,uint32_t localSSRC,uint32_t remoteSSRC,uint32_t ntpHi,uint32_t ntpLo)407 void RTPSender::appendDLRR(
408         std::vector<uint8_t> *buffer,
409         uint32_t localSSRC,
410         uint32_t remoteSSRC,
411         uint32_t ntpHi,
412         uint32_t ntpLo) {
413     static constexpr uint8_t XR = 207;
414 
415     static constexpr uint8_t FMT_DLRRRB = 5;
416 
417     const size_t kLengthInWords = 2 + 4;
418 
419     auto offset = buffer->size();
420     buffer->resize(offset + kLengthInWords * sizeof(uint32_t));
421 
422     uint8_t *data = buffer->data() + offset;
423 
424     data[0] = 0x80;
425     data[1] = XR;
426     SET_U16(&data[2], kLengthInWords - 1);
427     SET_U32(&data[4], localSSRC);
428 
429     data[8] = FMT_DLRRRB;
430     data[9] = 0x00;
431     SET_U16(&data[10], 3 /* block length */);
432     SET_U32(&data[12], remoteSSRC);
433     SET_U32(&data[16], (ntpHi << 16) | (ntpLo >> 16));
434     SET_U32(&data[20], 0 /* delay since last RR */);
435 }
436 
queueSR(uint32_t localSSRC)437 void RTPSender::queueSR(uint32_t localSSRC) {
438     std::vector<uint8_t> buffer;
439     appendSR(&buffer, localSSRC);
440     // appendSDES(&buffer, localSSRC);
441 
442     // LOG(INFO) << "RTPSender::queueSR";
443     // hexdump(buffer.data(), buffer.size());
444 
445     mParent->queueRTCPDatagram(buffer.data(), buffer.size());
446 }
447 
sendSR(uint32_t localSSRC)448 void RTPSender::sendSR(uint32_t localSSRC) {
449     // LOG(INFO) << "sending SR.";
450     queueSR(localSSRC);
451 
452     mRunLoop->postWithDelay(
453             std::chrono::seconds(1),
454             makeSafeCallback(this, &RTPSender::sendSR, localSSRC));
455 }
456 
run()457 void RTPSender::run() {
458     for (const auto &entry : mSources) {
459         sendSR(entry.first);
460     }
461 }
462 
queueRTPDatagram(std::vector<uint8_t> * packet)463 void RTPSender::queueRTPDatagram(std::vector<uint8_t> *packet) {
464     CHECK_GE(packet->size(), 12u);
465 
466     uint32_t SSRC = U32_AT(&packet->data()[8]);
467 
468     auto it = mSources.find(SSRC);
469     CHECK(it != mSources.end());
470 
471     auto &info = it->second;
472 
473     uint16_t seqNum = info.mNumPacketsSent;
474     SET_U16(packet->data() + 2, seqNum);
475 
476 #if SIMULATE_PACKET_LOSS
477     static std::random_device rd;
478     static std::mt19937 gen(rd());
479     static std::uniform_real_distribution<> dist(0.0, 1.0);
480     if (dist(gen) < 0.99) {
481 #endif
482         mParent->queueRTPDatagram(packet->data(), packet->size());
483 #if SIMULATE_PACKET_LOSS
484     } else {
485         LOG(WARNING)
486             << "dropping packet "
487             << StringPrintf("0x%04x", seqNum)
488             << " from SSRC "
489             << StringPrintf("0x%08x", SSRC);
490     }
491 #endif
492 
493     ++info.mNumPacketsSent;
494     info.mNumBytesSent += packet->size() - 12;  // does not include RTP header.
495 
496     if (!info.mRetrans.empty()) {
497         static constexpr size_t kMaxHistory = 512;
498         if (info.mRecentPackets.size() == kMaxHistory) {
499             info.mRecentPackets.pop_front();
500         }
501         // info.mRecentPackets.push_back(std::move(*packet));
502         info.mRecentPackets.push_back(*packet);
503     }
504 }
505 
retransmitPackets(uint32_t localSSRC,uint16_t PID,uint16_t BLP)506 void RTPSender::retransmitPackets(
507         uint32_t localSSRC, uint16_t PID, uint16_t BLP) {
508     auto it = mSources.find(localSSRC);
509     CHECK(it != mSources.end());
510 
511     const auto &info = it->second;
512 
513     if (!info.mRecentPackets.empty()) {
514         LOG(INFO) << "Recent packets cover range ["
515             << StringPrintf(
516                     "0x%04x", U16_AT(info.mRecentPackets.front().data() + 2))
517             << ";"
518             << StringPrintf(
519                     "0x%04x", U16_AT(info.mRecentPackets.back().data() + 2))
520             << "]";
521     } else {
522         LOG(INFO) << "Recent packets are EMPTY!";
523     }
524 
525     bool first = true;
526     while (first || BLP) {
527         if (first) {
528             first = false;
529         } else {
530             ++PID;
531             if (!(BLP & 1)) {
532                 BLP = BLP >> 1;
533                 continue;
534             }
535 
536             BLP = BLP >> 1;
537         }
538 
539         for (auto it = info.mRecentPackets.begin();
540                 it != info.mRecentPackets.end();
541                 ++it) {
542             const auto &origPacket = *it;
543             auto seqNum = U16_AT(origPacket.data() + 2);
544 
545             if (seqNum != PID) {
546                 continue;
547             }
548 
549             LOG(INFO) << "Retransmitting PID " << StringPrintf("0x%04x", PID);
550 
551             auto PT = origPacket[1] & 0x7f;
552             auto it2 = info.mRetrans.find(PT);
553             CHECK(it2 != info.mRetrans.end());
554 
555             auto [rtxSSRC, rtxPT] = it2->second;
556 
557             std::vector<uint8_t> packet(origPacket.size() + 2);
558 
559             // XXX This is very simplified and assumes that the original packet
560             // started with a standard 12-byte header, no extensions and no padding!
561             memcpy(packet.data(), origPacket.data(), 12);
562 
563             packet[1] = (origPacket[1] & 0x80) | (rtxPT & 0x7f);
564             SET_U32(packet.data() + 8, rtxSSRC);
565             SET_U16(packet.data() + 12, seqNum);
566 
567             memcpy(packet.data() + 14,
568                    origPacket.data() + 12,
569                    origPacket.size() - 12);
570 
571             // queueRTPDatagram will fill in the new seqNum.
572             queueRTPDatagram(&packet);
573         }
574     }
575 }
576 
requestIDRFrame()577 void RTPSender::requestIDRFrame() {
578     if (mVideoPacketizer) {
579         mVideoPacketizer->requestIDRFrame();
580     }
581 }
582 
583