Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_packet.cc

Issue 1841453004: RtpPacket class introduced. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: added empty lines Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/rtp_packet.h"
12
13 #include <cstring>
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/base/random.h"
18 #include "webrtc/common_types.h"
19 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
22
23 namespace webrtc {
24 namespace rtp {
25 namespace {
26 constexpr size_t kFixedHeaderSize = 12;
27 constexpr uint8_t kRtpVersion = 2;
28 constexpr uint16_t kOneByteExtensionId = 0xBEDE;
29 constexpr size_t kOneByteHeaderSize = 1;
30 constexpr size_t kDefaultPacketSize = 1500;
31 } // namespace
32 // 0 1 2 3
33 // 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
34 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 // |V=2|P|X| CC |M| PT | sequence number |
36 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 // | timestamp |
38 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 // | synchronization source (SSRC) identifier |
40 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
41 // | Contributing source (CSRC) identifiers |
42 // | .... |
43 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
44 // |One-byte eXtensions id = 0xbede| length in 32bits |
45 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 // | Extensions |
47 // | .... |
48 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
49 // | Payload |
50 // | .... : padding... |
51 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 // | padding | Padding size |
53 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 Packet::Packet(const ExtensionManager* extensions)
55 : extensions_(extensions), buffer_(kDefaultPacketSize) {
56 Clear();
57 }
58
59 Packet::Packet(const ExtensionManager* extensions, size_t capacity)
60 : extensions_(extensions), buffer_(capacity) {
61 RTC_DCHECK_GE(capacity, kFixedHeaderSize);
62 Clear();
63 }
64
65 Packet::~Packet() {}
66
67 void Packet::IdentifyExtensions(const ExtensionManager* extensions) {
68 RTC_DCHECK(extensions);
69 extensions_ = extensions;
70 for (size_t i = 0; i < num_extensions_; ++i) {
71 uint8_t id = data()[extension_entries_[i].offset - 1] >> 4;
72 extension_entries_[i].type = extensions_->GetType(id);
73 }
74 }
75
76 bool Packet::Parse(const uint8_t* buffer, size_t buffer_size) {
77 if (!ParseBuffer(buffer, buffer_size)) {
78 Clear();
79 return false;
80 }
81 RTC_DCHECK_EQ(size(), buffer_size);
82 buffer_.SetData(buffer, buffer_size);
83 return true;
84 }
85
86 bool Packet::Parse(rtc::Buffer buffer) {
87 if (!ParseBuffer(buffer.data(), buffer.size())) {
88 Clear();
89 return false;
90 }
91 RTC_DCHECK_EQ(size(), buffer.size());
92 buffer_ = std::move(buffer);
93 return true;
94 }
95
96 bool Packet::Marker() const {
97 RTC_DCHECK_EQ(marker_, (data()[1] & 0x80) != 0);
98 return marker_;
99 }
100
101 uint8_t Packet::PayloadType() const {
102 RTC_DCHECK_EQ(payload_type_, data()[1] & 0x7f);
103 return payload_type_;
104 }
105
106 uint16_t Packet::SequenceNumber() const {
107 RTC_DCHECK_EQ(sequence_number_,
108 ByteReader<uint16_t>::ReadBigEndian(data() + 2));
109 return sequence_number_;
110 }
111
112 uint32_t Packet::Timestamp() const {
113 RTC_DCHECK_EQ(timestamp_, ByteReader<uint32_t>::ReadBigEndian(data() + 4));
114 return timestamp_;
115 }
116
117 uint32_t Packet::Ssrc() const {
118 RTC_DCHECK_EQ(ssrc_, ByteReader<uint32_t>::ReadBigEndian(data() + 8));
119 return ssrc_;
120 }
121
122 std::vector<uint32_t> Packet::Csrcs() const {
123 size_t num_csrc = data()[0] & 0x0F;
124 RTC_DCHECK_GE(capacity(), kFixedHeaderSize + num_csrc * 4);
125 std::vector<uint32_t> csrcs(num_csrc);
126 for (size_t i = 0; i < num_csrc; ++i) {
127 csrcs[i] =
128 ByteReader<uint32_t>::ReadBigEndian(&data()[kFixedHeaderSize + i * 4]);
129 }
130 return csrcs;
131 }
132
133 void Packet::GetHeader(RTPHeader* header) const {
134 header->markerBit = Marker();
135 header->payloadType = PayloadType();
136 header->sequenceNumber = SequenceNumber();
137 header->timestamp = Timestamp();
138 header->ssrc = Ssrc();
139 std::vector<uint32_t> csrcs = Csrcs();
140 header->numCSRCs = csrcs.size();
141 for (size_t i = 0; i < csrcs.size(); ++i) {
142 header->arrOfCSRCs[i] = csrcs[i];
143 }
144 header->paddingLength = padding_size();
145 header->headerLength = headers_size();
146 header->payload_type_frequency = 0;
147 header->extension.hasTransmissionTimeOffset =
148 GetExtension<TransmissionOffset>(
149 &header->extension.transmissionTimeOffset);
150 header->extension.hasAbsoluteSendTime =
151 GetExtension<AbsoluteSendTime>(&header->extension.absoluteSendTime);
152 header->extension.hasTransportSequenceNumber =
153 GetExtension<TransportSequenceNumber>(
154 &header->extension.transportSequenceNumber);
155 header->extension.hasAudioLevel = GetExtension<AudioLevel>(
156 &header->extension.voiceActivity, &header->extension.audioLevel);
157 header->extension.hasVideoRotation =
158 GetExtension<VideoOrientation>(&header->extension.videoRotation);
159 }
160
161 size_t Packet::headers_size() const {
162 return payload_offset_;
163 }
164
165 size_t Packet::payload_size() const {
166 return payload_size_;
167 }
168
169 size_t Packet::padding_size() const {
170 return padding_size_;
171 }
172
173 const uint8_t* Packet::payload() const {
174 return data() + payload_offset_;
175 }
176
177 size_t Packet::capacity() const {
178 return buffer_.size();
179 }
180
181 size_t Packet::size() const {
182 return payload_offset_ + payload_size_ + padding_size_;
183 }
184
185 const uint8_t* Packet::data() const {
186 return buffer_.data();
187 }
188
189 size_t Packet::FreeCapacity() const {
190 return capacity() - size();
191 }
192
193 size_t Packet::MaxPayloadSize() const {
194 return capacity() - payload_offset_;
195 }
196
197 void Packet::CopyHeader(const Packet& packet) {
198 RTC_DCHECK_GE(capacity(), packet.headers_size());
199
200 marker_ = packet.marker_;
201 payload_type_ = packet.payload_type_;
202 sequence_number_ = packet.sequence_number_;
203 timestamp_ = packet.timestamp_;
204 ssrc_ = packet.ssrc_;
205 payload_offset_ = packet.payload_offset_;
206 num_extensions_ = packet.num_extensions_;
207 for (size_t i = 0; i < num_extensions_; ++i) {
208 extension_entries_[i] = packet.extension_entries_[i];
209 }
210 extensions_size_ = packet.extensions_size_;
211 buffer_.SetData(packet.data(), packet.headers_size());
212 // Reset payload and padding.
213 payload_size_ = 0;
214 padding_size_ = 0;
215 }
216
217 void Packet::SetMarker(bool marker_bit) {
218 marker_ = marker_bit;
219 if (marker_) {
220 WriteAt(1, data()[1] | 0x80);
221 } else {
222 WriteAt(1, data()[1] & 0x7F);
223 }
224 }
225
226 void Packet::SetPayloadType(uint8_t payload_type) {
227 RTC_DCHECK_LE(payload_type, 0x7Fu);
228 payload_type_ = payload_type;
229 WriteAt(1, (data()[1] & 0x80) | payload_type);
230 }
231
232 void Packet::SetSequenceNumber(uint16_t seq_no) {
233 sequence_number_ = seq_no;
234 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(2), seq_no);
235 }
236
237 void Packet::SetTimestamp(uint32_t timestamp) {
238 timestamp_ = timestamp;
239 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(4), timestamp);
240 }
241
242 void Packet::SetSsrc(uint32_t ssrc) {
243 ssrc_ = ssrc;
244 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(8), ssrc);
245 }
246
247 void Packet::SetCsrcs(const std::vector<uint32_t>& csrcs) {
248 RTC_DCHECK_EQ(num_extensions_, 0u);
249 RTC_DCHECK_EQ(payload_size_, 0u);
250 RTC_DCHECK_EQ(padding_size_, 0u);
251 RTC_DCHECK_LE(csrcs.size(), 0x0fu);
252 RTC_DCHECK_LE(kFixedHeaderSize + 4 * csrcs.size(), capacity());
253 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();
254 WriteAt(0, (data()[0] & 0xF0) | csrcs.size());
255 size_t offset = kFixedHeaderSize;
256 for (uint32_t csrc : csrcs) {
257 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc);
258 offset += 4;
259 }
260 }
261
262 uint8_t* Packet::AllocatePayload(size_t size_bytes) {
263 RTC_DCHECK_EQ(padding_size_, 0u);
264 if (payload_offset_ + size_bytes > capacity()) {
265 LOG(LS_WARNING) << "Cannot set payload, not enough space in buffer.";
266 return nullptr;
267 }
268 payload_size_ = size_bytes;
269 return WriteAt(payload_offset_);
270 }
271
272 void Packet::SetPayloadSize(size_t size_bytes) {
273 RTC_DCHECK_EQ(padding_size_, 0u);
274 RTC_DCHECK_LE(size_bytes, payload_size_);
275 payload_size_ = size_bytes;
276 }
277
278 bool Packet::SetPadding(uint8_t size_bytes, Random* random) {
279 RTC_DCHECK(random);
280 if (payload_offset_ + payload_size_ + size_bytes > capacity()) {
281 LOG(LS_WARNING) << "Cannot set padding size " << size_bytes << ", only "
282 << (capacity() - payload_offset_ - payload_size_)
283 << " bytes left in buffer.";
284 return false;
285 }
286 padding_size_ = size_bytes;
287 if (padding_size_ > 0) {
288 size_t padding_offset = payload_offset_ + payload_size_;
289 size_t padding_end = padding_offset + padding_size_;
290 for (size_t offset = padding_offset; offset < padding_end - 1; ++offset) {
291 WriteAt(offset, random->Rand<uint8_t>());
292 }
293 WriteAt(padding_end - 1, padding_size_);
294 WriteAt(0, data()[0] | 0x20); // Set padding bit.
295 } else {
296 WriteAt(0, data()[0] & ~0x20); // Clear padding bit.
297 }
298 return true;
299 }
300
301 void Packet::Clear() {
302 marker_ = false;
303 payload_type_ = 0;
304 sequence_number_ = 0;
305 timestamp_ = 0;
306 ssrc_ = 0;
307 payload_offset_ = kFixedHeaderSize;
308 payload_size_ = 0;
309 padding_size_ = 0;
310 num_extensions_ = 0;
311 extensions_size_ = 0;
312
313 memset(WriteAt(0), 0, kFixedHeaderSize);
314 WriteAt(0, kRtpVersion << 6);
315 }
316
317 bool Packet::ParseBuffer(const uint8_t* buffer, size_t size) {
318 if (size < kFixedHeaderSize) {
319 return false;
320 }
321 const uint8_t version = buffer[0] >> 6;
322 if (version != kRtpVersion) {
323 return false;
324 }
325 const bool has_padding = (buffer[0] & 0x20) != 0;
326 const bool has_extension = (buffer[0] & 0x10) != 0;
327 const uint8_t number_of_crcs = buffer[0] & 0x0f;
328 marker_ = (buffer[1] & 0x80) != 0;
329 payload_type_ = buffer[1] & 0x7f;
330
331 sequence_number_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]);
332 timestamp_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
333 ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
334 if (size < kFixedHeaderSize + number_of_crcs * 4) {
335 return false;
336 }
337 payload_offset_ = kFixedHeaderSize + number_of_crcs * 4;
338
339 if (has_padding) {
340 padding_size_ = buffer[size - 1];
341 if (padding_size_ == 0) {
342 LOG(LS_WARNING) << "Padding was set, but padding size is zero";
343 return false;
344 }
345 } else {
346 padding_size_ = 0;
347 }
348
349 num_extensions_ = 0;
350 extensions_size_ = 0;
351 if (has_extension) {
352 /* RTP header extension, RFC 3550.
353 0 1 2 3
354 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
355 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356 | defined by profile | length |
357 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358 | header extension |
359 | .... |
360 */
361 size_t extension_offset = payload_offset_ + 4;
362 if (extension_offset > size) {
363 return false;
364 }
365 uint16_t profile =
366 ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_]);
367 size_t extensions_capacity =
368 ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_ + 2]);
369 extensions_capacity *= 4;
370 if (extension_offset + extensions_capacity > size) {
371 return false;
372 }
373 if (profile != kOneByteExtensionId) {
374 LOG(LS_WARNING) << "Unsupported rtp extension " << profile;
375 } else {
376 constexpr uint8_t kPaddingId = 0;
377 constexpr uint8_t kReservedId = 15;
378 while (extensions_size_ + kOneByteHeaderSize < extensions_capacity) {
379 uint8_t id = buffer[extension_offset + extensions_size_] >> 4;
380 if (id == kReservedId) {
381 break;
382 } else if (id == kPaddingId) {
383 extensions_size_++;
384 continue;
385 }
386 uint8_t length =
387 1 + (buffer[extension_offset + extensions_size_] & 0xf);
388 extensions_size_ += kOneByteHeaderSize;
389 if (num_extensions_ >= kMaxExtensionHeaders) {
390 LOG(LS_WARNING) << "Too many extensions.";
391 return false;
392 }
393 extension_entries_[num_extensions_].type =
394 extensions_ ? extensions_->GetType(id)
395 : ExtensionManager::kInvalidType;
396 extension_entries_[num_extensions_].length = length;
397 extension_entries_[num_extensions_].offset =
398 extension_offset + extensions_size_;
399 num_extensions_++;
400 extensions_size_ += length;
401 }
402 }
403 payload_offset_ = extension_offset + extensions_capacity;
404 }
405
406 if (payload_offset_ + padding_size_ > size) {
407 return false;
408 }
409 payload_size_ = size - payload_offset_ - padding_size_;
410 return true;
411 }
412
413 bool Packet::FindExtension(ExtensionType type,
414 uint8_t length,
415 uint16_t* offset) const {
416 RTC_DCHECK(offset);
417 for (size_t i = 0; i < num_extensions_; ++i) {
418 if (extension_entries_[i].type == type) {
419 RTC_CHECK_EQ(length, extension_entries_[i].length)
420 << "Length mismatch for extension '" << type << "'"
421 << "should be " << length << ", received "
422 << extension_entries_[i].length;
423 *offset = extension_entries_[i].offset;
424 return true;
425 }
426 }
427 return false;
428 }
429
430 bool Packet::AllocateExtension(ExtensionType type,
431 uint8_t length,
432 uint16_t* offset) {
433 if (!extensions_) {
434 return false;
435 }
436 if (FindExtension(type, length, offset)) {
437 return true;
438 }
439
440 // Can't add new extension after payload/padding was set.
441 if (payload_size_ > 0) {
442 return false;
443 }
444 if (padding_size_ > 0) {
445 return false;
446 }
447
448 uint8_t extension_id = extensions_->GetId(type);
449 if (extension_id == ExtensionManager::kInvalidId) {
450 return false;
451 }
452 RTC_DCHECK_GT(length, 0u);
453 RTC_DCHECK_LE(length, 16u);
454
455 size_t num_csrc = data()[0] & 0x0F;
456 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
457 if (extensions_offset + extensions_size_ + kOneByteHeaderSize + length >
458 capacity()) {
459 LOG(LS_WARNING) << "Extension cannot be registered: "
460 "Not enough space left in buffer.";
461 return false;
462 }
463
464 uint16_t new_extensions_size =
465 extensions_size_ + kOneByteHeaderSize + length;
466 uint16_t extensions_words =
467 (new_extensions_size + 3) / 4; // Wrap up to 32bit.
468
469 // All checks passed, write down the extension.
470 if (num_extensions_ == 0) {
471 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4));
472 RTC_DCHECK_EQ(extensions_size_, 0);
473 WriteAt(0, data()[0] | 0x10); // Set extension bit.
474 // Profile specific ID always set to OneByteExtensionHeader.
475 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
476 kOneByteExtensionId);
477 }
478
479 WriteAt(extensions_offset + extensions_size_,
480 (extension_id << 4) | (length - 1));
481 RTC_DCHECK(num_extensions_ < kMaxExtensionHeaders);
482 extension_entries_[num_extensions_].type = type;
483 extension_entries_[num_extensions_].length = length;
484 *offset = extensions_offset + kOneByteHeaderSize + extensions_size_;
485 extension_entries_[num_extensions_].offset = *offset;
486 ++num_extensions_;
487 extensions_size_ = new_extensions_size;
488
489 // Update header length field.
490 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2),
491 extensions_words);
492 // Fill extension padding place with zeroes.
493 size_t extension_padding_size = 4 * extensions_words - extensions_size_;
494 memset(WriteAt(extensions_offset + extensions_size_), 0,
495 extension_padding_size);
496 payload_offset_ = extensions_offset + 4 * extensions_words;
497 return true;
498 }
499
500 uint8_t* Packet::WriteAt(size_t offset) {
501 return buffer_.data() + offset;
502 }
503
504 void Packet::WriteAt(size_t offset, uint8_t byte) {
505 buffer_.data()[offset] = byte;
506 }
507
508 } // namespace rtp
509 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_packet.h ('k') | webrtc/modules/rtp_rtcp/source/rtp_packet_received.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698