• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
12 
13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h"
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
16 
17 using webrtc::RTCPUtility::RtcpCommonHeader;
18 
19 namespace webrtc {
20 namespace rtcp {
21 // RFC 4585: Feedback format.
22 //
23 // Common packet format:
24 //
25 //   0                   1                   2                   3
26 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
27 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 //  |V=2|P|   FMT   |       PT      |          length               |
29 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 //  |                  SSRC of packet sender                        |
31 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 //  |                  SSRC of media source                         |
33 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 //  :            Feedback Control Information (FCI)                 :
35 //  :                                                               :
36 //
37 // Slice loss indication (SLI) (RFC 4585).
38 // FCI:
39 //   0                   1                   2                   3
40 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
41 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 //  |            First        |        Number           | PictureID |
43 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Macroblocks(uint8_t picture_id,uint16_t first,uint16_t number)44 Sli::Macroblocks::Macroblocks(uint8_t picture_id,
45                               uint16_t first,
46                               uint16_t number) {
47   RTC_DCHECK_LE(first, 0x1fff);
48   RTC_DCHECK_LE(number, 0x1fff);
49   RTC_DCHECK_LE(picture_id, 0x3f);
50   item_ = (first << 19) | (number << 6) | picture_id;
51 }
52 
Parse(const uint8_t * buffer)53 void Sli::Macroblocks::Parse(const uint8_t* buffer) {
54   item_ = ByteReader<uint32_t>::ReadBigEndian(buffer);
55 }
56 
Create(uint8_t * buffer) const57 void Sli::Macroblocks::Create(uint8_t* buffer) const {
58   ByteWriter<uint32_t>::WriteBigEndian(buffer, item_);
59 }
60 
Parse(const RtcpCommonHeader & header,const uint8_t * payload)61 bool Sli::Parse(const RtcpCommonHeader& header, const uint8_t* payload) {
62   RTC_DCHECK(header.packet_type == kPacketType);
63   RTC_DCHECK(header.count_or_format == kFeedbackMessageType);
64 
65   if (header.payload_size_bytes <
66       kCommonFeedbackLength + Macroblocks::kLength) {
67     LOG(LS_WARNING) << "Packet is too small to be a valid SLI packet";
68     return false;
69   }
70 
71   size_t number_of_items =
72       (header.payload_size_bytes - kCommonFeedbackLength) /
73       Macroblocks::kLength;
74 
75   ParseCommonFeedback(payload);
76   items_.resize(number_of_items);
77 
78   const uint8_t* next_item = payload + kCommonFeedbackLength;
79   for (Macroblocks& item : items_) {
80     item.Parse(next_item);
81     next_item += Macroblocks::kLength;
82   }
83 
84   return true;
85 }
86 
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const87 bool Sli::Create(uint8_t* packet,
88                  size_t* index,
89                  size_t max_length,
90                  RtcpPacket::PacketReadyCallback* callback) const {
91   RTC_DCHECK(!items_.empty());
92   while (*index + BlockLength() > max_length) {
93     if (!OnBufferFull(packet, index, callback))
94       return false;
95   }
96   CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
97                index);
98   CreateCommonFeedback(packet + *index);
99   *index += kCommonFeedbackLength;
100   for (const Macroblocks& item : items_) {
101     item.Create(packet + *index);
102     *index += Macroblocks::kLength;
103   }
104   return true;
105 }
106 
107 }  // namespace rtcp
108 }  // namespace webrtc
109