| OLD | NEW |
| (Empty) |
| 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/rpsi.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 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h" | |
| 17 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | |
| 18 | |
| 19 using webrtc::RtpUtility::Word32Align; | |
| 20 | |
| 21 namespace webrtc { | |
| 22 namespace rtcp { | |
| 23 constexpr uint8_t Rpsi::kFeedbackMessageType; | |
| 24 // RFC 4585: Feedback format. | |
| 25 // Reference picture selection indication (RPSI) (RFC 4585). | |
| 26 // | |
| 27 // 0 1 2 3 | |
| 28 // 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 | |
| 29 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 30 // |V=2|P| RPSI=3 | PT=PSFB=206 | length | | |
| 31 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 32 // 0 | SSRC of packet sender | | |
| 33 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 34 // 4 | SSRC of media source | | |
| 35 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 36 // 8 | Padding Bits | | |
| 37 // 9 |0| Payload Type| | |
| 38 // 10 | Native RPSI bit string : | |
| 39 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 40 // : defined per codec ... | Padding (0) | | |
| 41 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 42 namespace { | |
| 43 constexpr size_t kPaddingSizeOffset = 8; | |
| 44 constexpr size_t kPayloadTypeOffset = 9; | |
| 45 constexpr size_t kBitStringOffset = 10; | |
| 46 | |
| 47 constexpr size_t kPidBits = 7; | |
| 48 // Calculates number of bytes required to store given picture id. | |
| 49 uint8_t RequiredBytes(uint64_t picture_id) { | |
| 50 uint8_t required_bytes = 0; | |
| 51 uint64_t shifted_pid = picture_id; | |
| 52 do { | |
| 53 ++required_bytes; | |
| 54 shifted_pid >>= kPidBits; | |
| 55 } while (shifted_pid > 0); | |
| 56 | |
| 57 return required_bytes; | |
| 58 } | |
| 59 } // namespace | |
| 60 | |
| 61 Rpsi::Rpsi() | |
| 62 : payload_type_(0), | |
| 63 picture_id_(0), | |
| 64 block_length_(CalculateBlockLength(1)) {} | |
| 65 | |
| 66 bool Rpsi::Parse(const CommonHeader& packet) { | |
| 67 RTC_DCHECK_EQ(packet.type(), kPacketType); | |
| 68 RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType); | |
| 69 | |
| 70 if (packet.payload_size_bytes() < kCommonFeedbackLength + 4) { | |
| 71 LOG(LS_WARNING) << "Packet is too small to be a valid RPSI packet."; | |
| 72 return false; | |
| 73 } | |
| 74 | |
| 75 ParseCommonFeedback(packet.payload()); | |
| 76 | |
| 77 uint8_t padding_bits = packet.payload()[kPaddingSizeOffset]; | |
| 78 if (padding_bits % 8 != 0) { | |
| 79 LOG(LS_WARNING) << "Unknown rpsi packet with fractional number of bytes."; | |
| 80 return false; | |
| 81 } | |
| 82 size_t padding_bytes = padding_bits / 8; | |
| 83 if (padding_bytes + kBitStringOffset >= packet.payload_size_bytes()) { | |
| 84 LOG(LS_WARNING) << "Too many padding bytes in a RPSI packet."; | |
| 85 return false; | |
| 86 } | |
| 87 size_t padding_offset = packet.payload_size_bytes() - padding_bytes; | |
| 88 payload_type_ = packet.payload()[kPayloadTypeOffset] & 0x7f; | |
| 89 picture_id_ = 0; | |
| 90 for (size_t pos = kBitStringOffset; pos < padding_offset; ++pos) { | |
| 91 picture_id_ <<= kPidBits; | |
| 92 picture_id_ |= (packet.payload()[pos] & 0x7f); | |
| 93 } | |
| 94 // Required bytes might become less than came in the packet. | |
| 95 block_length_ = CalculateBlockLength(RequiredBytes(picture_id_)); | |
| 96 return true; | |
| 97 } | |
| 98 | |
| 99 bool Rpsi::Create(uint8_t* packet, | |
| 100 size_t* index, | |
| 101 size_t max_length, | |
| 102 RtcpPacket::PacketReadyCallback* callback) const { | |
| 103 while (*index + BlockLength() > max_length) { | |
| 104 if (!OnBufferFull(packet, index, callback)) | |
| 105 return false; | |
| 106 } | |
| 107 size_t index_end = *index + BlockLength(); | |
| 108 | |
| 109 CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet, | |
| 110 index); | |
| 111 CreateCommonFeedback(packet + *index); | |
| 112 *index += kCommonFeedbackLength; | |
| 113 | |
| 114 size_t bitstring_size_bytes = RequiredBytes(picture_id_); | |
| 115 size_t padding_bytes = | |
| 116 Word32Align(2 + bitstring_size_bytes) - (2 + bitstring_size_bytes); | |
| 117 packet[(*index)++] = padding_bytes * 8; | |
| 118 packet[(*index)++] = payload_type_; | |
| 119 | |
| 120 // Convert picture id to native bit string (defined by the video codec). | |
| 121 for (size_t i = bitstring_size_bytes - 1; i > 0; --i) { | |
| 122 packet[(*index)++] = | |
| 123 0x80 | static_cast<uint8_t>(picture_id_ >> (i * kPidBits)); | |
| 124 } | |
| 125 packet[(*index)++] = static_cast<uint8_t>(picture_id_ & 0x7f); | |
| 126 constexpr uint8_t kPadding = 0; | |
| 127 for (size_t i = 0; i < padding_bytes; ++i) | |
| 128 packet[(*index)++] = kPadding; | |
| 129 RTC_CHECK_EQ(*index, index_end); | |
| 130 return true; | |
| 131 } | |
| 132 | |
| 133 void Rpsi::SetPayloadType(uint8_t payload) { | |
| 134 RTC_DCHECK_LE(payload, 0x7f); | |
| 135 payload_type_ = payload; | |
| 136 } | |
| 137 | |
| 138 void Rpsi::SetPictureId(uint64_t picture_id) { | |
| 139 picture_id_ = picture_id; | |
| 140 block_length_ = CalculateBlockLength(RequiredBytes(picture_id_)); | |
| 141 } | |
| 142 | |
| 143 size_t Rpsi::CalculateBlockLength(uint8_t bitstring_size_bytes) { | |
| 144 return RtcpPacket::kHeaderLength + Psfb::kCommonFeedbackLength + | |
| 145 Word32Align(2 + bitstring_size_bytes); | |
| 146 } | |
| 147 } // namespace rtcp | |
| 148 } // namespace webrtc | |
| OLD | NEW |