in RtpPacketizerVp8 factor out payload splitter function
so that it can be shared between different packetizers
and thus easier to extend
Bug: webrtc:9680
Change-Id: Ie5e904ad27afb8dd2ed35ef9e009f7f408017b2f
Reviewed-on: https://webrtc-review.googlesource.com/97661
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24555}
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index 49ccafe..4f36a2e 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -225,6 +225,7 @@
"../../system_wrappers:metrics_api",
"../audio_coding:audio_format_conversion",
"../remote_bitrate_estimator",
+ "//third_party/abseil-cpp/absl/container:inlined_vector",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:optional",
]
@@ -393,6 +394,7 @@
"source/rtcp_transceiver_unittest.cc",
"source/rtp_fec_unittest.cc",
"source/rtp_format_h264_unittest.cc",
+ "source/rtp_format_unittest.cc",
"source/rtp_format_video_generic_unittest.cc",
"source/rtp_format_vp8_test_helper.cc",
"source/rtp_format_vp8_test_helper.h",
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index 72beb17..bddec73 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -17,6 +17,7 @@
#include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
+#include "rtc_base/checks.h"
namespace webrtc {
@@ -61,6 +62,47 @@
}
}
+std::vector<size_t> RtpPacketizer::SplitAboutEqually(
+ size_t payload_len,
+ const PayloadSizeLimits& limits) {
+ RTC_CHECK_GT(limits.max_payload_len, limits.last_packet_reduction_len);
+
+ // Last packet can be smaller. Pretend that it's the same size, but we must
+ // write more payload to it.
+ size_t total_bytes = payload_len + limits.last_packet_reduction_len;
+ // Integer divisions with rounding up.
+ size_t num_packets_left =
+ (total_bytes + limits.max_payload_len - 1) / limits.max_payload_len;
+ size_t bytes_per_packet = total_bytes / num_packets_left;
+ size_t num_larger_packets = total_bytes % num_packets_left;
+ size_t remaining_data = payload_len;
+
+ std::vector<size_t> result;
+ result.reserve(num_packets_left);
+ while (remaining_data > 0) {
+ // Last num_larger_packets are 1 byte wider than the rest. Increase
+ // per-packet payload size when needed.
+ if (num_packets_left == num_larger_packets)
+ ++bytes_per_packet;
+ size_t current_packet_bytes = bytes_per_packet;
+ if (current_packet_bytes > remaining_data) {
+ current_packet_bytes = remaining_data;
+ }
+ // This is not the last packet in the whole payload, but there's no data
+ // left for the last packet. Leave at least one byte for the last packet.
+ if (num_packets_left == 2 && current_packet_bytes == remaining_data) {
+ --current_packet_bytes;
+ }
+
+ result.push_back(current_packet_bytes);
+
+ remaining_data -= current_packet_bytes;
+ --num_packets_left;
+ }
+
+ return result;
+}
+
RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) {
switch (type) {
case kVideoCodecH264:
diff --git a/modules/rtp_rtcp/source/rtp_format.h b/modules/rtp_rtcp/source/rtp_format.h
index 007ddbc..f945d24 100644
--- a/modules/rtp_rtcp/source/rtp_format.h
+++ b/modules/rtp_rtcp/source/rtp_format.h
@@ -13,6 +13,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "api/array_view.h"
#include "common_types.h" // NOLINT(build/include)
@@ -47,6 +48,10 @@
// Write payload and set marker bit of the |packet|.
// Returns true on success, false otherwise.
virtual bool NextPacket(RtpPacketToSend* packet) = 0;
+
+ // Split payload_len into sum of integers with respect to |limits|.
+ static std::vector<size_t> SplitAboutEqually(size_t payload_len,
+ const PayloadSizeLimits& limits);
};
// TODO(sprang): Update the depacketizer to return a std::unqie_ptr with a copy
diff --git a/modules/rtp_rtcp/source/rtp_format_unittest.cc b/modules/rtp_rtcp/source/rtp_format_unittest.cc
new file mode 100644
index 0000000..6b83432
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtp_format_unittest.cc
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2018 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 "modules/rtp_rtcp/source/rtp_format.h"
+
+#include <memory>
+#include <numeric>
+
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::ElementsAre;
+using ::testing::Le;
+using ::testing::Each;
+using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::SizeIs;
+
+// Calculate difference between largest and smallest packets respecting sizes
+// adjustement provided by limits,
+// i.e. last packet expected to be smaller than 'average' by reduction_len.
+int EffectivePacketsSizeDifference(
+ std::vector<size_t> sizes,
+ const RtpPacketizer::PayloadSizeLimits& limits) {
+ // Account for larger last packet header.
+ sizes.back() += limits.last_packet_reduction_len;
+
+ auto minmax = std::minmax_element(sizes.begin(), sizes.end());
+ // MAX-MIN
+ return *minmax.second - *minmax.first;
+}
+
+size_t Sum(const std::vector<size_t>& sizes) {
+ return std::accumulate(sizes.begin(), sizes.end(), 0);
+}
+
+TEST(RtpPacketizerSplitAboutEqually, AllPacketsAreEqualSumToPayloadLen) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 5;
+ limits.last_packet_reduction_len = 2;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(13, limits);
+
+ EXPECT_THAT(Sum(payload_sizes), 13);
+}
+
+TEST(RtpPacketizerSplitAboutEqually, AllPacketsAreEqualRespectsMaxPayloadSize) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 5;
+ limits.last_packet_reduction_len = 2;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(13, limits);
+
+ EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
+}
+
+TEST(RtpPacketizerSplitAboutEqually,
+ AllPacketsAreEqualRespectsLastPacketReductionLength) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 5;
+ limits.last_packet_reduction_len = 2;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(13, limits);
+
+ ASSERT_THAT(payload_sizes, Not(IsEmpty()));
+ EXPECT_LE(payload_sizes.back() + limits.last_packet_reduction_len,
+ limits.max_payload_len);
+}
+
+TEST(RtpPacketizerSplitAboutEqually, AllPacketsAreEqualInSize) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 5;
+ limits.last_packet_reduction_len = 2;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(13, limits);
+
+ EXPECT_EQ(EffectivePacketsSizeDifference(payload_sizes, limits), 0);
+}
+
+TEST(RtpPacketizerSplitAboutEqually,
+ AllPacketsAreEqualGeneratesMinimumNumberOfPackets) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 5;
+ limits.last_packet_reduction_len = 2;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(13, limits);
+ // Computed by hand. 3 packets would have exactly capacity 3*5-2=13
+ // (max length - for each packet minus last packet reduction).
+ EXPECT_THAT(payload_sizes, SizeIs(3));
+}
+
+TEST(RtpPacketizerSplitAboutEqually, SomePacketsAreSmallerSumToPayloadLen) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 7;
+ limits.last_packet_reduction_len = 5;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(28, limits);
+
+ EXPECT_THAT(Sum(payload_sizes), 28);
+}
+
+TEST(RtpPacketizerVideoGeneric, SomePacketsAreSmallerRespectsMaxPayloadSize) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 7;
+ limits.last_packet_reduction_len = 5;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(28, limits);
+
+ EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
+}
+
+TEST(RtpPacketizerVideoGeneric,
+ SomePacketsAreSmallerRespectsLastPacketReductionLength) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 7;
+ limits.last_packet_reduction_len = 5;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(28, limits);
+
+ EXPECT_LE(payload_sizes.back(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+
+TEST(RtpPacketizerVideoGeneric, SomePacketsAreSmallerPacketsAlmostEqualInSize) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 7;
+ limits.last_packet_reduction_len = 5;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(28, limits);
+
+ EXPECT_LE(EffectivePacketsSizeDifference(payload_sizes, limits), 1);
+}
+
+TEST(RtpPacketizerVideoGeneric,
+ SomePacketsAreSmallerGeneratesMinimumNumberOfPackets) {
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 7;
+ limits.last_packet_reduction_len = 5;
+
+ std::vector<size_t> payload_sizes =
+ RtpPacketizer::SplitAboutEqually(24, limits);
+ // Computed by hand. 4 packets would have capacity 4*7-5=23 (max length -
+ // for each packet minus last packet reduction).
+ // 5 packets is enough for kPayloadSize.
+ EXPECT_THAT(payload_sizes, SizeIs(5));
+}
+
+} // namespace
+} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8.cc b/modules/rtp_rtcp/source/rtp_format_vp8.cc
index 4a511fc..b219dac 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp8.cc
@@ -23,8 +23,15 @@
namespace webrtc {
namespace {
-// Length of VP8 payload descriptors' fixed part.
-constexpr int kVp8FixedPayloadDescriptorSize = 1;
+constexpr int kXBit = 0x80;
+constexpr int kNBit = 0x20;
+constexpr int kSBit = 0x10;
+constexpr int kKeyIdxField = 0x1F;
+constexpr int kIBit = 0x80;
+constexpr int kLBit = 0x40;
+constexpr int kTBit = 0x20;
+constexpr int kKBit = 0x10;
+constexpr int kYBit = 0x20;
int ParseVP8PictureID(RTPVideoHeaderVP8* vp8,
const uint8_t** data,
@@ -165,259 +172,113 @@
RtpPacketizerVp8::RtpPacketizerVp8(rtc::ArrayView<const uint8_t> payload,
PayloadSizeLimits limits,
const RTPVideoHeaderVP8& hdr_info)
- : payload_data_(payload.data()), hdr_info_(hdr_info), limits_(limits) {
- RTC_DCHECK(ValidateHeader(hdr_info));
- GeneratePackets(payload.size());
+ : hdr_(BuildHeader(hdr_info)), remaining_payload_(payload) {
+ if (limits.max_payload_len - limits.last_packet_reduction_len <
+ hdr_.size() + 1) {
+ // The provided payload length is not long enough for the payload
+ // descriptor and one payload byte in the last packet.
+ current_packet_ = payload_sizes_.begin();
+ return;
+ }
+ limits.max_payload_len -= hdr_.size();
+ payload_sizes_ = SplitAboutEqually(payload.size(), limits);
+ current_packet_ = payload_sizes_.begin();
}
RtpPacketizerVp8::~RtpPacketizerVp8() = default;
size_t RtpPacketizerVp8::NumPackets() const {
- return packets_.size();
+ return payload_sizes_.end() - current_packet_;
}
bool RtpPacketizerVp8::NextPacket(RtpPacketToSend* packet) {
RTC_DCHECK(packet);
- if (packets_.empty()) {
+ if (current_packet_ == payload_sizes_.end()) {
return false;
}
- InfoStruct packet_info = packets_.front();
- packets_.pop();
- size_t packet_payload_len =
- packets_.empty()
- ? limits_.max_payload_len - limits_.last_packet_reduction_len
- : limits_.max_payload_len;
- uint8_t* buffer = packet->AllocatePayload(packet_payload_len);
- int bytes = WriteHeaderAndPayload(packet_info, buffer, packet_payload_len);
- if (bytes < 0) {
- return false;
- }
- packet->SetPayloadSize(bytes);
- packet->SetMarker(packets_.empty());
+ size_t packet_payload_len = *current_packet_;
+ ++current_packet_;
+
+ uint8_t* buffer = packet->AllocatePayload(hdr_.size() + packet_payload_len);
+ RTC_CHECK(buffer);
+
+ memcpy(buffer, hdr_.data(), hdr_.size());
+ memcpy(buffer + hdr_.size(), remaining_payload_.data(), packet_payload_len);
+
+ remaining_payload_ = remaining_payload_.subview(packet_payload_len);
+ hdr_[0] &= (~kSBit); // Clear 'Start of partition' bit.
+ packet->SetMarker(current_packet_ == payload_sizes_.end());
return true;
}
-void RtpPacketizerVp8::GeneratePackets(size_t payload_len) {
- if (limits_.max_payload_len - limits_.last_packet_reduction_len <
- kVp8FixedPayloadDescriptorSize + PayloadDescriptorExtraLength() + 1) {
- // The provided payload length is not long enough for the payload
- // descriptor and one payload byte in the last packet.
- return;
+// Write the VP8 payload descriptor.
+// 0
+// 0 1 2 3 4 5 6 7 8
+// +-+-+-+-+-+-+-+-+-+
+// |X| |N|S| PART_ID |
+// +-+-+-+-+-+-+-+-+-+
+// X: |I|L|T|K| | (mandatory if any of the below are used)
+// +-+-+-+-+-+-+-+-+-+
+// I: |PictureID (16b)| (optional)
+// +-+-+-+-+-+-+-+-+-+
+// L: | TL0PIC_IDX | (optional)
+// +-+-+-+-+-+-+-+-+-+
+// T/K: |TID:Y| KEYIDX | (optional)
+// +-+-+-+-+-+-+-+-+-+
+RtpPacketizerVp8::RawHeader RtpPacketizerVp8::BuildHeader(
+ const RTPVideoHeaderVP8& header) {
+ RTC_DCHECK(ValidateHeader(header));
+
+ RawHeader result;
+ bool tid_present = header.temporalIdx != kNoTemporalIdx;
+ bool keyid_present = header.keyIdx != kNoKeyIdx;
+ bool tl0_pid_present = header.tl0PicIdx != kNoTl0PicIdx;
+ bool pid_present = header.pictureId != kNoPictureId;
+ uint8_t x_field = 0;
+ if (pid_present)
+ x_field |= kIBit;
+ if (tl0_pid_present)
+ x_field |= kLBit;
+ if (tid_present)
+ x_field |= kTBit;
+ if (keyid_present)
+ x_field |= kKBit;
+
+ uint8_t flags = 0;
+ if (x_field != 0)
+ flags |= kXBit;
+ if (header.nonReference)
+ flags |= kNBit;
+ // Create header as first packet in the frame. NextPacket() will clear it
+ // after first use.
+ flags |= kSBit;
+ result.push_back(flags);
+ if (x_field == 0) {
+ return result;
}
-
- size_t capacity = limits_.max_payload_len - (kVp8FixedPayloadDescriptorSize +
- PayloadDescriptorExtraLength());
-
- // Last packet of the last partition is smaller. Pretend that it's the same
- // size, but we must write more payload to it.
- size_t total_bytes = payload_len + limits_.last_packet_reduction_len;
- // Integer divisions with rounding up.
- size_t num_packets_left = (total_bytes + capacity - 1) / capacity;
- size_t bytes_per_packet = total_bytes / num_packets_left;
- size_t num_larger_packets = total_bytes % num_packets_left;
- size_t remaining_data = payload_len;
- while (remaining_data > 0) {
- // Last num_larger_packets are 1 byte wider than the rest. Increase
- // per-packet payload size when needed.
- if (num_packets_left == num_larger_packets)
- ++bytes_per_packet;
- size_t current_packet_bytes = bytes_per_packet;
- if (current_packet_bytes > remaining_data) {
- current_packet_bytes = remaining_data;
+ result.push_back(x_field);
+ if (pid_present) {
+ const uint16_t pic_id = static_cast<uint16_t>(header.pictureId);
+ result.push_back(0x80 | ((pic_id >> 8) & 0x7F));
+ result.push_back(pic_id & 0xFF);
+ }
+ if (tl0_pid_present) {
+ result.push_back(header.tl0PicIdx);
+ }
+ if (tid_present || keyid_present) {
+ uint8_t data_field = 0;
+ if (tid_present) {
+ data_field |= header.temporalIdx << 6;
+ if (header.layerSync)
+ data_field |= kYBit;
}
- // This is not the last packet in the whole payload, but there's no data
- // left for the last packet. Leave at least one byte for the last packet.
- if (num_packets_left == 2 && current_packet_bytes == remaining_data) {
- --current_packet_bytes;
+ if (keyid_present) {
+ data_field |= (header.keyIdx & kKeyIdxField);
}
- QueuePacket(payload_len - remaining_data, current_packet_bytes,
- /*first_packet=*/remaining_data == payload_len);
- remaining_data -= current_packet_bytes;
- --num_packets_left;
+ result.push_back(data_field);
}
-}
-
-void RtpPacketizerVp8::QueuePacket(size_t start_pos,
- size_t packet_size,
- bool first_packet) {
- // Write info to packet info struct and store in packet info queue.
- InfoStruct packet_info;
- packet_info.payload_start_pos = start_pos;
- packet_info.size = packet_size;
- packet_info.first_packet = first_packet;
- packets_.push(packet_info);
-}
-
-int RtpPacketizerVp8::WriteHeaderAndPayload(const InfoStruct& packet_info,
- uint8_t* buffer,
- size_t buffer_length) const {
- // Write the VP8 payload descriptor.
- // 0
- // 0 1 2 3 4 5 6 7 8
- // +-+-+-+-+-+-+-+-+-+
- // |X| |N|S| PART_ID |
- // +-+-+-+-+-+-+-+-+-+
- // X: |I|L|T|K| | (mandatory if any of the below are used)
- // +-+-+-+-+-+-+-+-+-+
- // I: |PictureID (8/16b)| (optional)
- // +-+-+-+-+-+-+-+-+-+
- // L: | TL0PIC_IDX | (optional)
- // +-+-+-+-+-+-+-+-+-+
- // T/K: |TID:Y| KEYIDX | (optional)
- // +-+-+-+-+-+-+-+-+-+
-
- RTC_DCHECK_GT(packet_info.size, 0);
- buffer[0] = 0;
- if (XFieldPresent())
- buffer[0] |= kXBit;
- if (hdr_info_.nonReference)
- buffer[0] |= kNBit;
- if (packet_info.first_packet)
- buffer[0] |= kSBit;
-
- const int extension_length = WriteExtensionFields(buffer, buffer_length);
- if (extension_length < 0)
- return -1;
-
- memcpy(&buffer[kVp8FixedPayloadDescriptorSize + extension_length],
- &payload_data_[packet_info.payload_start_pos], packet_info.size);
-
- // Return total length of written data.
- return packet_info.size + kVp8FixedPayloadDescriptorSize + extension_length;
-}
-
-int RtpPacketizerVp8::WriteExtensionFields(uint8_t* buffer,
- size_t buffer_length) const {
- size_t extension_length = 0;
- if (XFieldPresent()) {
- uint8_t* x_field = buffer + kVp8FixedPayloadDescriptorSize;
- *x_field = 0;
- extension_length = 1; // One octet for the X field.
- if (PictureIdPresent()) {
- if (WritePictureIDFields(x_field, buffer, buffer_length,
- &extension_length) < 0) {
- return -1;
- }
- }
- if (TL0PicIdxFieldPresent()) {
- if (WriteTl0PicIdxFields(x_field, buffer, buffer_length,
- &extension_length) < 0) {
- return -1;
- }
- }
- if (TIDFieldPresent() || KeyIdxFieldPresent()) {
- if (WriteTIDAndKeyIdxFields(x_field, buffer, buffer_length,
- &extension_length) < 0) {
- return -1;
- }
- }
- RTC_DCHECK_EQ(extension_length, PayloadDescriptorExtraLength());
- }
- return static_cast<int>(extension_length);
-}
-
-int RtpPacketizerVp8::WritePictureIDFields(uint8_t* x_field,
- uint8_t* buffer,
- size_t buffer_length,
- size_t* extension_length) const {
- *x_field |= kIBit;
- RTC_DCHECK_GE(buffer_length,
- kVp8FixedPayloadDescriptorSize + *extension_length);
- const int pic_id_length = WritePictureID(
- buffer + kVp8FixedPayloadDescriptorSize + *extension_length,
- buffer_length - kVp8FixedPayloadDescriptorSize - *extension_length);
- if (pic_id_length < 0)
- return -1;
- *extension_length += pic_id_length;
- return 0;
-}
-
-int RtpPacketizerVp8::WritePictureID(uint8_t* buffer,
- size_t buffer_length) const {
- const uint16_t pic_id = static_cast<uint16_t>(hdr_info_.pictureId);
- size_t picture_id_len = PictureIdLength();
- if (picture_id_len > buffer_length)
- return -1;
- if (picture_id_len == 2) {
- buffer[0] = 0x80 | ((pic_id >> 8) & 0x7F);
- buffer[1] = pic_id & 0xFF;
- } else if (picture_id_len == 1) {
- buffer[0] = pic_id & 0x7F;
- }
- return static_cast<int>(picture_id_len);
-}
-
-int RtpPacketizerVp8::WriteTl0PicIdxFields(uint8_t* x_field,
- uint8_t* buffer,
- size_t buffer_length,
- size_t* extension_length) const {
- if (buffer_length < kVp8FixedPayloadDescriptorSize + *extension_length + 1) {
- return -1;
- }
- *x_field |= kLBit;
- buffer[kVp8FixedPayloadDescriptorSize + *extension_length] =
- hdr_info_.tl0PicIdx;
- ++*extension_length;
- return 0;
-}
-
-int RtpPacketizerVp8::WriteTIDAndKeyIdxFields(uint8_t* x_field,
- uint8_t* buffer,
- size_t buffer_length,
- size_t* extension_length) const {
- if (buffer_length < kVp8FixedPayloadDescriptorSize + *extension_length + 1) {
- return -1;
- }
- uint8_t* data_field =
- &buffer[kVp8FixedPayloadDescriptorSize + *extension_length];
- *data_field = 0;
- if (TIDFieldPresent()) {
- *x_field |= kTBit;
- *data_field |= hdr_info_.temporalIdx << 6;
- *data_field |= hdr_info_.layerSync ? kYBit : 0;
- }
- if (KeyIdxFieldPresent()) {
- *x_field |= kKBit;
- *data_field |= (hdr_info_.keyIdx & kKeyIdxField);
- }
- ++*extension_length;
- return 0;
-}
-
-size_t RtpPacketizerVp8::PayloadDescriptorExtraLength() const {
- size_t length_bytes = PictureIdLength();
- if (TL0PicIdxFieldPresent())
- ++length_bytes;
- if (TIDFieldPresent() || KeyIdxFieldPresent())
- ++length_bytes;
- if (length_bytes > 0)
- ++length_bytes; // Include the extension field.
- return length_bytes;
-}
-
-size_t RtpPacketizerVp8::PictureIdLength() const {
- if (hdr_info_.pictureId == kNoPictureId) {
- return 0;
- }
- return 2;
-}
-
-bool RtpPacketizerVp8::XFieldPresent() const {
- return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent() ||
- KeyIdxFieldPresent());
-}
-
-bool RtpPacketizerVp8::TIDFieldPresent() const {
- return (hdr_info_.temporalIdx != kNoTemporalIdx);
-}
-
-bool RtpPacketizerVp8::KeyIdxFieldPresent() const {
- return (hdr_info_.keyIdx != kNoKeyIdx);
-}
-
-bool RtpPacketizerVp8::TL0PicIdxFieldPresent() const {
- return (hdr_info_.tl0PicIdx != kNoTl0PicIdx);
+ return result;
}
//
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8.h b/modules/rtp_rtcp/source/rtp_format_vp8.h
index dd66762..2fdd6c5 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8.h
+++ b/modules/rtp_rtcp/source/rtp_format_vp8.h
@@ -25,10 +25,11 @@
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_
#define MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_
-#include <queue>
#include <string>
#include <vector>
+#include "absl/container/inlined_vector.h"
+#include "api/array_view.h"
#include "modules/include/module_common_types.h"
#include "modules/rtp_rtcp/source/rtp_format.h"
#include "rtc_base/constructormagic.h"
@@ -54,88 +55,14 @@
bool NextPacket(RtpPacketToSend* packet) override;
private:
- typedef struct {
- size_t payload_start_pos;
- size_t size;
- bool first_packet;
- } InfoStruct;
- typedef std::queue<InfoStruct> InfoQueue;
+ // VP8 header can use up to 6 bytes.
+ using RawHeader = absl::InlinedVector<uint8_t, 6>;
+ static RawHeader BuildHeader(const RTPVideoHeaderVP8& header);
- static const int kXBit = 0x80;
- static const int kNBit = 0x20;
- static const int kSBit = 0x10;
- static const int kPartIdField = 0x0F;
- static const int kKeyIdxField = 0x1F;
- static const int kIBit = 0x80;
- static const int kLBit = 0x40;
- static const int kTBit = 0x20;
- static const int kKBit = 0x10;
- static const int kYBit = 0x20;
-
- // Calculate all packet sizes and load to packet info queue.
- void GeneratePackets(size_t payload_len);
-
- // Insert packet into packet queue.
- void QueuePacket(size_t start_pos, size_t packet_size, bool first_packet);
-
- // Write the payload header and copy the payload to the buffer.
- // The info in packet_info determines which part of the payload is written
- // and what to write in the header fields.
- int WriteHeaderAndPayload(const InfoStruct& packet_info,
- uint8_t* buffer,
- size_t buffer_length) const;
-
- // Write the X field and the appropriate extension fields to buffer.
- // The function returns the extension length (including X field), or -1
- // on error.
- int WriteExtensionFields(uint8_t* buffer, size_t buffer_length) const;
-
- // Set the I bit in the x_field, and write PictureID to the appropriate
- // position in buffer. The function returns 0 on success, -1 otherwise.
- int WritePictureIDFields(uint8_t* x_field,
- uint8_t* buffer,
- size_t buffer_length,
- size_t* extension_length) const;
-
- // Set the L bit in the x_field, and write Tl0PicIdx to the appropriate
- // position in buffer. The function returns 0 on success, -1 otherwise.
- int WriteTl0PicIdxFields(uint8_t* x_field,
- uint8_t* buffer,
- size_t buffer_length,
- size_t* extension_length) const;
-
- // Set the T and K bits in the x_field, and write TID, Y and KeyIdx to the
- // appropriate position in buffer. The function returns 0 on success,
- // -1 otherwise.
- int WriteTIDAndKeyIdxFields(uint8_t* x_field,
- uint8_t* buffer,
- size_t buffer_length,
- size_t* extension_length) const;
-
- // Write the PictureID from codec_specific_info_ to buffer. One or two
- // bytes are written, depending on magnitude of PictureID. The function
- // returns the number of bytes written.
- int WritePictureID(uint8_t* buffer, size_t buffer_length) const;
-
- // Calculate and return length (octets) of the variable header fields in
- // the next header (i.e., header length in addition to vp8_header_bytes_).
- size_t PayloadDescriptorExtraLength() const;
-
- // Calculate and return length (octets) of PictureID field in the next
- // header. Can be 0, 1, or 2.
- size_t PictureIdLength() const;
-
- // Check whether each of the optional fields will be included in the header.
- bool XFieldPresent() const;
- bool TIDFieldPresent() const;
- bool KeyIdxFieldPresent() const;
- bool TL0PicIdxFieldPresent() const;
- bool PictureIdPresent() const { return (PictureIdLength() > 0); }
-
- const uint8_t* payload_data_;
- const RTPVideoHeaderVP8 hdr_info_;
- const PayloadSizeLimits limits_;
- InfoQueue packets_;
+ RawHeader hdr_;
+ rtc::ArrayView<const uint8_t> remaining_payload_;
+ std::vector<size_t> payload_sizes_;
+ std::vector<size_t>::const_iterator current_packet_;
RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerVp8);
};