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

Unified Diff: webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc

Issue 2871173008: Fix packetization logic to leave space for extensions in the last packet (Closed)
Patch Set: Impelemented Danilchap@ comments Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc
index 4c8f7954f4ccb97358b176233044e1955c18937e..7bfa69c8a62ad59d6eefde1d62cfe84064291be1 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc
@@ -30,10 +30,6 @@ namespace {
// Length of VP9 payload descriptors' fixed part.
const size_t kFixedPayloadDescriptorBytes = 1;
-// Packet fragmentation mode. If true, packets are split into (almost) equal
-// sizes. Otherwise, as many bytes as possible are fit into one packet.
-const bool kBalancedMode = true;
-
const uint32_t kReservedBitValue0 = 0;
uint8_t TemporalIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) {
@@ -462,29 +458,16 @@ bool ParseSsData(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) {
}
return true;
}
-
-// Gets the size of next payload chunk to send. Returns 0 on error.
-size_t CalcNextSize(size_t max_length, size_t rem_bytes) {
- if (max_length == 0 || rem_bytes == 0) {
- return 0;
- }
- if (kBalancedMode) {
- size_t num_frags = std::ceil(static_cast<double>(rem_bytes) / max_length);
- return static_cast<size_t>(
- static_cast<double>(rem_bytes) / num_frags + 0.5);
- }
- return max_length >= rem_bytes ? rem_bytes : max_length;
-}
} // namespace
-
RtpPacketizerVp9::RtpPacketizerVp9(const RTPVideoHeaderVP9& hdr,
- size_t max_payload_length)
+ size_t max_payload_length,
+ size_t last_packet_reduction_len)
: hdr_(hdr),
max_payload_length_(max_payload_length),
payload_(nullptr),
- payload_size_(0) {
-}
+ payload_size_(0),
+ last_packet_reduction_len_(last_packet_reduction_len) {}
RtpPacketizerVp9::~RtpPacketizerVp9() {
}
@@ -511,54 +494,88 @@ std::string RtpPacketizerVp9::ToString() {
return "RtpPacketizerVp9";
}
-void RtpPacketizerVp9::SetPayloadData(
+size_t RtpPacketizerVp9::SetPayloadData(
const uint8_t* payload,
size_t payload_size,
const RTPFragmentationHeader* fragmentation) {
payload_ = payload;
payload_size_ = payload_size;
GeneratePackets();
+ return packets_.size();
}
+// Splits payload in minimal number of roughly equal in size packets.
void RtpPacketizerVp9::GeneratePackets() {
if (max_payload_length_ < PayloadDescriptorLength(hdr_) + 1) {
- LOG(LS_ERROR) << "Payload header and one payload byte won't fit.";
+ LOG(LS_ERROR) << "Payload header and one payload byte won't fit in packet.";
danilchap 2017/05/16 10:25:11 may be 'in the first packet' (since only 1st packe
ilnik 2017/05/16 12:24:08 Done.
return;
}
+ if (max_payload_length_ < PayloadDescriptorLengthMinusSsData(hdr_) + 1 +
+ last_packet_reduction_len_) {
+ LOG(LS_ERROR) << "Payload header and one payload byte won't fit in the last"
+ " packet.";
+ return;
+ }
+
+ // Instead of making last packet smaller, we pretend that we must write
danilchap 2017/05/16 10:25:11 may be also mention 1st packet that has extra SS h
ilnik 2017/05/16 12:24:08 Done.
+ // additional data into it. We account for this virtual payload while
danilchap 2017/05/16 10:25:11 single space between 'this' and 'virtual'
ilnik 2017/05/16 12:24:08 Done.
+ // calculating packets number and sizes.
+
+ // Payload, virtual payload and SS hdr data in the first packet together.
+ size_t total_bytes =
+ payload_size_ + last_packet_reduction_len_ + SsDataLength(hdr_);
danilchap 2017/05/16 10:25:11 nit: may be reorder terms in the order closer to h
ilnik 2017/05/16 12:24:08 Done.
+ // Now all packets will have the same lenght of vp9 headers.
+ size_t capacity =
+ max_payload_length_ - PayloadDescriptorLengthMinusSsData(hdr_);
+ // Integer divisions rounding up.
+ size_t num_packets = (total_bytes + capacity - 1) / capacity;
+ size_t per_packet_data = (total_bytes + num_packets - 1) / num_packets;
+ // Several last packets are 1 byte smaller than the rest.
+ // i.e. if 14 bytes were splitted between 4 packets, it would be 4+4+3+3.
+ size_t smaller_packets = num_packets - total_bytes % num_packets;
+ // If all packets are the same size, we assume 0 packets are smaller.
+ if (smaller_packets == num_packets)
+ smaller_packets = 0;
size_t bytes_processed = 0;
+ size_t packets_left = num_packets;
while (bytes_processed < payload_size_) {
+ if (packets_left == smaller_packets)
+ per_packet_data--;
+ size_t packet_bytes = per_packet_data;
+ // First packet also has SS hdr data.
+ if (bytes_processed == 0)
+ packet_bytes -= SsDataLength(hdr_);
danilchap 2017/05/16 10:25:11 can packet_bytes become negative?
ilnik 2017/05/16 12:24:08 Actually, in some extreme cases, it can. The fix f
danilchap 2017/05/17 10:31:19 Can you also add a test for this scenario. (btw, p
ilnik 2017/05/17 12:30:55 Yep, my mistake about unsignedness. Thanks for cat
size_t rem_bytes = payload_size_ - bytes_processed;
- size_t rem_payload_len = max_payload_length_ -
- (bytes_processed ? PayloadDescriptorLengthMinusSsData(hdr_)
- : PayloadDescriptorLength(hdr_));
-
- size_t packet_bytes = CalcNextSize(rem_payload_len, rem_bytes);
- if (packet_bytes == 0) {
- LOG(LS_ERROR) << "Failed to generate VP9 packets.";
- while (!packets_.empty())
- packets_.pop();
- return;
+ if (packet_bytes >= rem_bytes) {
+ // All remaining payload fits into this packet.
+ packet_bytes = rem_bytes;
+ // If this is the pre-last packet, leave at least 1 byte of payload for
+ // the last packet.
+ if (packets_left == 2)
+ packet_bytes--;
danilchap 2017/05/16 10:25:11 can packet_bytes be zero before decrement?
ilnik 2017/05/16 12:24:08 Now it can't due to the fix above. There's still
}
QueuePacket(bytes_processed, packet_bytes, bytes_processed == 0,
rem_bytes == packet_bytes, &packets_);
+ packets_left--;
bytes_processed += packet_bytes;
+ // Last packet should be smaller
+ RTC_DCHECK(packets_left > 0 ||
+ capacity >= packet_bytes + last_packet_reduction_len_);
}
assert(bytes_processed == payload_size_);
}
-bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet, bool* last_packet) {
+bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet) {
RTC_DCHECK(packet);
- RTC_DCHECK(last_packet);
if (packets_.empty()) {
return false;
}
PacketInfo packet_info = packets_.front();
packets_.pop();
- if (!WriteHeaderAndPayload(packet_info, packet)) {
+ if (!WriteHeaderAndPayload(packet_info, packet, packets_.empty())) {
return false;
}
- *last_packet = packets_.empty();
packet->SetMarker(packets_.empty() &&
(hdr_.spatial_idx == kNoSpatialIdx ||
hdr_.spatial_idx == hdr_.num_spatial_layers - 1));
@@ -602,8 +619,11 @@ bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet, bool* last_packet) {
// +-+-+-+-+-+-+-+-+
bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info,
- RtpPacketToSend* packet) const {
- uint8_t* buffer = packet->AllocatePayload(max_payload_length_);
+ RtpPacketToSend* packet,
+ bool last) const {
+ uint8_t* buffer = packet->AllocatePayload(
+ last ? max_payload_length_ - last_packet_reduction_len_
+ : max_payload_length_);
RTC_DCHECK(buffer);
size_t header_length;
if (!WriteHeader(packet_info, buffer, &header_length))

Powered by Google App Engine
This is Rietveld 408576698