
Clean some logs and add asserts in the way. BUG=3153 R=mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/11129004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5861 4adac7df-926f-26a2-2b94-8c16560cd09d
303 lines
12 KiB
C++
303 lines
12 KiB
C++
/*
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
|
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
|
#include "webrtc/system_wrappers/interface/logging.h"
|
|
|
|
namespace webrtc {
|
|
namespace rtcp {
|
|
namespace {
|
|
void AssignUWord8(uint8_t* buffer, uint16_t* offset, uint8_t value) {
|
|
buffer[(*offset)++] = value;
|
|
}
|
|
void AssignUWord16(uint8_t* buffer, uint16_t* offset, uint16_t value) {
|
|
ModuleRTPUtility::AssignUWord16ToBuffer(buffer + *offset, value);
|
|
*offset += 2;
|
|
}
|
|
void AssignUWord24(uint8_t* buffer, uint16_t* offset, uint32_t value) {
|
|
ModuleRTPUtility::AssignUWord24ToBuffer(buffer + *offset, value);
|
|
*offset += 3;
|
|
}
|
|
void AssignUWord32(uint8_t* buffer, uint16_t* offset, uint32_t value) {
|
|
ModuleRTPUtility::AssignUWord32ToBuffer(buffer + *offset, value);
|
|
*offset += 4;
|
|
}
|
|
|
|
// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
|
|
//
|
|
// Sender report
|
|
// 0 1 2 3
|
|
// 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
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// |V=2|P| RC | PT=SR=200 | length |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | SSRC of sender |
|
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
// | NTP timestamp, most significant word |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | NTP timestamp, least significant word |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | RTP timestamp |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | sender's packet count |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | sender's octet count |
|
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
|
|
void CreateSenderReport(const RTCPUtility::RTCPPacketSR& sr,
|
|
uint8_t* buffer,
|
|
uint16_t* pos) {
|
|
const uint16_t kLength = 6 + (6 * sr.NumberOfReportBlocks);
|
|
AssignUWord8(buffer, pos, 0x80 + sr.NumberOfReportBlocks);
|
|
AssignUWord8(buffer, pos, RTCPUtility::PT_SR);
|
|
AssignUWord16(buffer, pos, kLength);
|
|
AssignUWord32(buffer, pos, sr.SenderSSRC);
|
|
AssignUWord32(buffer, pos, sr.NTPMostSignificant);
|
|
AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
|
|
AssignUWord32(buffer, pos, sr.RTPTimestamp);
|
|
AssignUWord32(buffer, pos, sr.SenderPacketCount);
|
|
AssignUWord32(buffer, pos, sr.SenderOctetCount);
|
|
}
|
|
|
|
// Receiver report, header (RFC 3550).
|
|
//
|
|
// 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
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// |V=2|P| RC | PT=RR=201 | length |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | SSRC of packet sender |
|
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
|
|
void CreateReceiverReport(const RTCPUtility::RTCPPacketRR& rr,
|
|
uint8_t* buffer,
|
|
uint16_t* pos) {
|
|
const uint16_t kLength = 1 + (6 * rr.NumberOfReportBlocks);
|
|
AssignUWord8(buffer, pos, 0x80 + rr.NumberOfReportBlocks);
|
|
AssignUWord8(buffer, pos, RTCPUtility::PT_RR);
|
|
AssignUWord16(buffer, pos, kLength);
|
|
AssignUWord32(buffer, pos, rr.SenderSSRC);
|
|
}
|
|
|
|
// Report block (RFC 3550).
|
|
//
|
|
// 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
|
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
// | SSRC_1 (SSRC of first source) |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | fraction lost | cumulative number of packets lost |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | extended highest sequence number received |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | interarrival jitter |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | last SR (LSR) |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | delay since last SR (DLSR) |
|
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
|
|
void CreateReportBlock(
|
|
const RTCPUtility::RTCPPacketReportBlockItem& report_block,
|
|
uint8_t* buffer,
|
|
uint16_t* pos) {
|
|
AssignUWord32(buffer, pos, report_block.SSRC);
|
|
AssignUWord8(buffer, pos, report_block.FractionLost);
|
|
AssignUWord24(buffer, pos, report_block.CumulativeNumOfPacketsLost);
|
|
AssignUWord32(buffer, pos, report_block.ExtendedHighestSequenceNumber);
|
|
AssignUWord32(buffer, pos, report_block.Jitter);
|
|
AssignUWord32(buffer, pos, report_block.LastSR);
|
|
AssignUWord32(buffer, pos, report_block.DelayLastSR);
|
|
}
|
|
|
|
// Bye packet (BYE) (RFC 3550).
|
|
//
|
|
// 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
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// |V=2|P| SC | PT=BYE=203 | length |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | SSRC/CSRC |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// : ... :
|
|
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
// (opt) | length | reason for leaving ...
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
void CreateBye(const RTCPUtility::RTCPPacketBYE& bye,
|
|
const std::vector<uint32_t>& csrcs,
|
|
uint8_t* buffer,
|
|
uint16_t* pos) {
|
|
const uint8_t kNumSsrcAndCsrcs = 1 + csrcs.size();
|
|
AssignUWord8(buffer, pos, 0x80 + kNumSsrcAndCsrcs);
|
|
AssignUWord8(buffer, pos, RTCPUtility::PT_BYE);
|
|
AssignUWord16(buffer, pos, kNumSsrcAndCsrcs);
|
|
AssignUWord32(buffer, pos, bye.SenderSSRC);
|
|
for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
|
|
it != csrcs.end(); ++it) {
|
|
AssignUWord32(buffer, pos, *it);
|
|
}
|
|
}
|
|
|
|
// RFC 4585: Feedback format.
|
|
//
|
|
// Common packet format:
|
|
//
|
|
// 0 1 2 3
|
|
// 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
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// |V=2|P| FMT | PT | length |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | SSRC of packet sender |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | SSRC of media source |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// : Feedback Control Information (FCI) :
|
|
// :
|
|
//
|
|
// Full intra request (FIR) (RFC 5104).
|
|
//
|
|
// FCI:
|
|
//
|
|
// 0 1 2 3
|
|
// 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
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | SSRC |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | Seq nr. | Reserved |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
void CreateFirRequest(const RTCPUtility::RTCPPacketPSFBFIR& fir,
|
|
const RTCPUtility::RTCPPacketPSFBFIRItem& fir_item,
|
|
uint8_t* buffer,
|
|
uint16_t* pos) {
|
|
const uint16_t kLength = 4;
|
|
const uint8_t kFmt = 4;
|
|
AssignUWord8(buffer, pos, 0x80 + kFmt);
|
|
AssignUWord8(buffer, pos, RTCPUtility::PT_PSFB);
|
|
AssignUWord16(buffer, pos, kLength);
|
|
AssignUWord32(buffer, pos, fir.SenderSSRC);
|
|
AssignUWord32(buffer, pos, 0);
|
|
AssignUWord32(buffer, pos, fir_item.SSRC);
|
|
AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
|
|
AssignUWord24(buffer, pos, 0);
|
|
}
|
|
|
|
void AppendReportBlocks(const std::vector<ReportBlock*>& report_blocks,
|
|
uint8_t* buffer,
|
|
uint16_t* pos) {
|
|
for (std::vector<ReportBlock*>::const_iterator it = report_blocks.begin();
|
|
it != report_blocks.end(); ++it) {
|
|
(*it)->Create(buffer, pos);
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
void RtcpPacket::Append(RtcpPacket* packet) {
|
|
assert(packet);
|
|
appended_packets_.push_back(packet);
|
|
}
|
|
|
|
RawPacket RtcpPacket::Build() const {
|
|
uint16_t len = 0;
|
|
uint8_t packet[IP_PACKET_SIZE];
|
|
CreateAndAddAppended(packet, &len, IP_PACKET_SIZE);
|
|
return RawPacket(packet, len);
|
|
}
|
|
|
|
void RtcpPacket::Build(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
|
|
*len = 0;
|
|
CreateAndAddAppended(packet, len, max_len);
|
|
}
|
|
|
|
void RtcpPacket::CreateAndAddAppended(uint8_t* packet,
|
|
uint16_t* len,
|
|
uint16_t max_len) const {
|
|
Create(packet, len, max_len);
|
|
for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
|
|
it != appended_packets_.end(); ++it) {
|
|
(*it)->CreateAndAddAppended(packet, len, max_len);
|
|
}
|
|
}
|
|
|
|
void Empty::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
|
|
}
|
|
|
|
void SenderReport::Create(uint8_t* packet,
|
|
uint16_t* len,
|
|
uint16_t max_len) const {
|
|
if (*len + Length() > max_len) {
|
|
LOG(LS_WARNING) << "Max packet size reached.";
|
|
return;
|
|
}
|
|
CreateSenderReport(sr_, packet, len);
|
|
AppendReportBlocks(report_blocks_, packet, len);
|
|
}
|
|
|
|
void SenderReport::WithReportBlock(ReportBlock* block) {
|
|
assert(block);
|
|
if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
|
|
LOG(LS_WARNING) << "Max report blocks reached.";
|
|
return;
|
|
}
|
|
report_blocks_.push_back(block);
|
|
sr_.NumberOfReportBlocks = report_blocks_.size();
|
|
}
|
|
|
|
void ReceiverReport::Create(uint8_t* packet,
|
|
uint16_t* len,
|
|
uint16_t max_len) const {
|
|
if (*len + Length() > max_len) {
|
|
LOG(LS_WARNING) << "Max packet size reached.";
|
|
return;
|
|
}
|
|
CreateReceiverReport(rr_, packet, len);
|
|
AppendReportBlocks(report_blocks_, packet, len);
|
|
}
|
|
|
|
void ReceiverReport::WithReportBlock(ReportBlock* block) {
|
|
assert(block);
|
|
if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
|
|
LOG(LS_WARNING) << "Max report blocks reached.";
|
|
return;
|
|
}
|
|
report_blocks_.push_back(block);
|
|
rr_.NumberOfReportBlocks = report_blocks_.size();
|
|
}
|
|
|
|
void Bye::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
|
|
if (*len + Length() > max_len) {
|
|
LOG(LS_WARNING) << "Max packet size reached.";
|
|
return;
|
|
}
|
|
CreateBye(bye_, csrcs_, packet, len);
|
|
}
|
|
|
|
void Bye::WithCsrc(uint32_t csrc) {
|
|
if (csrcs_.size() >= kMaxNumberOfCsrcs) {
|
|
LOG(LS_WARNING) << "Max CSRC size reached.";
|
|
return;
|
|
}
|
|
csrcs_.push_back(csrc);
|
|
}
|
|
|
|
void Fir::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
|
|
if (*len + Length() > max_len) {
|
|
LOG(LS_WARNING) << "Max packet size reached.";
|
|
return;
|
|
}
|
|
CreateFirRequest(fir_, fir_item_, packet, len);
|
|
}
|
|
|
|
void ReportBlock::Create(uint8_t* packet, uint16_t* len) const {
|
|
CreateReportBlock(report_block_, packet, len);
|
|
}
|
|
} // namespace rtcp
|
|
} // namespace webrtc
|