Pass and store PacketBuffer::Packet by unique_ptr

to avoid expensive move of the Packet and prepare PacketBuffer
to return list of packets as a frame.

Bug: None
Change-Id: I19f0452c52238228bbe28284ebb197491eb2bf4e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/167063
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30404}
This commit is contained in:
Danil Chapovalov
2020-01-24 16:04:35 +01:00
committed by Commit Bot
parent d7fade5738
commit 97ffbefdab
5 changed files with 246 additions and 220 deletions

View File

@ -79,7 +79,7 @@ PacketBuffer::~PacketBuffer() {
}
PacketBuffer::InsertResult PacketBuffer::InsertPacket(
PacketBuffer::Packet* packet) {
std::unique_ptr<PacketBuffer::Packet> packet) {
PacketBuffer::InsertResult result;
rtc::CritScope lock(&crit_);
@ -99,19 +99,19 @@ PacketBuffer::InsertResult PacketBuffer::InsertPacket(
first_seq_num_ = seq_num;
}
if (buffer_[index].used) {
if (buffer_[index].used()) {
// Duplicate packet, just delete the payload.
if (buffer_[index].seq_num() == packet->seq_num) {
return result;
}
// The packet buffer is full, try to expand the buffer.
while (ExpandBufferSize() && buffer_[seq_num % buffer_.size()].used) {
while (ExpandBufferSize() && buffer_[seq_num % buffer_.size()].used()) {
}
index = seq_num % buffer_.size();
// Packet buffer is still full since we were unable to expand the buffer.
if (buffer_[index].used) {
if (buffer_[index].used()) {
// Clear the buffer, delete payload, and return false to signal that a
// new keyframe is needed.
RTC_LOG(LS_WARNING) << "Clear PacketBuffer and request key frame.";
@ -131,8 +131,7 @@ PacketBuffer::InsertResult PacketBuffer::InsertPacket(
StoredPacket& new_entry = buffer_[index];
new_entry.continuous = false;
new_entry.used = true;
new_entry.data = std::move(*packet);
new_entry.packet = std::move(packet);
UpdateMissingPackets(seq_num);
@ -158,10 +157,9 @@ void PacketBuffer::ClearTo(uint16_t seq_num) {
size_t diff = ForwardDiff<uint16_t>(first_seq_num_, seq_num);
size_t iterations = std::min(diff, buffer_.size());
for (size_t i = 0; i < iterations; ++i) {
size_t index = first_seq_num_ % buffer_.size();
if (AheadOf<uint16_t>(seq_num, buffer_[index].seq_num())) {
buffer_[index].data.video_payload = {};
buffer_[index].used = false;
StoredPacket& stored = buffer_[first_seq_num_ % buffer_.size()];
if (stored.used() && AheadOf<uint16_t>(seq_num, stored.seq_num())) {
stored.packet = nullptr;
}
++first_seq_num_;
}
@ -186,8 +184,7 @@ void PacketBuffer::ClearInterval(uint16_t start_seq_num,
for (size_t i = 0; i < iterations; ++i) {
size_t index = seq_num % buffer_.size();
RTC_DCHECK_EQ(buffer_[index].seq_num(), seq_num);
buffer_[index].data.video_payload = {};
buffer_[index].used = false;
buffer_[index].packet = nullptr;
++seq_num;
}
@ -196,8 +193,7 @@ void PacketBuffer::ClearInterval(uint16_t start_seq_num,
void PacketBuffer::Clear() {
rtc::CritScope lock(&crit_);
for (StoredPacket& entry : buffer_) {
entry.data.video_payload = {};
entry.used = false;
entry.packet = nullptr;
}
first_packet_received_ = false;
@ -236,7 +232,7 @@ bool PacketBuffer::ExpandBufferSize() {
size_t new_size = std::min(max_size_, 2 * buffer_.size());
std::vector<StoredPacket> new_buffer(new_size);
for (StoredPacket& entry : buffer_) {
if (entry.used) {
if (entry.used()) {
new_buffer[entry.seq_num() % new_size] = std::move(entry);
}
}
@ -251,17 +247,17 @@ bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
const StoredPacket& entry = buffer_[index];
const StoredPacket& prev_entry = buffer_[prev_index];
if (!entry.used)
if (!entry.used())
return false;
if (entry.seq_num() != seq_num)
return false;
if (entry.frame_begin())
return true;
if (!prev_entry.used)
if (!prev_entry.used())
return false;
if (prev_entry.seq_num() != static_cast<uint16_t>(entry.seq_num() - 1))
return false;
if (prev_entry.data.timestamp != entry.data.timestamp)
if (prev_entry.packet->timestamp != entry.packet->timestamp)
return false;
if (prev_entry.continuous)
return true;
@ -285,10 +281,10 @@ std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
// the |frame_begin| flag is set.
int start_index = index;
size_t tested_packets = 0;
int64_t frame_timestamp = buffer_[start_index].data.timestamp;
int64_t frame_timestamp = buffer_[start_index].packet->timestamp;
// Identify H.264 keyframes by means of SPS, PPS, and IDR.
bool is_h264 = buffer_[start_index].data.codec() == kVideoCodecH264;
bool is_h264 = buffer_[start_index].packet->codec() == kVideoCodecH264;
bool has_h264_sps = false;
bool has_h264_pps = false;
bool has_h264_idr = false;
@ -303,7 +299,7 @@ std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
if (is_h264) {
const auto* h264_header = absl::get_if<RTPVideoHeaderH264>(
&buffer_[start_index].data.video_header.video_type_header);
&buffer_[start_index].packet->video_header.video_type_header);
if (!h264_header || h264_header->nalus_length >= kMaxNalusPerPacket)
return found_frames;
@ -324,10 +320,10 @@ std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
// smallest index and valid resolution; typically its IDR or SPS
// packet; there may be packet preceeding this packet, IDR's
// resolution will be applied to them.
if (buffer_[start_index].data.width() > 0 &&
buffer_[start_index].data.height() > 0) {
idr_width = buffer_[start_index].data.width();
idr_height = buffer_[start_index].data.height();
if (buffer_[start_index].packet->width() > 0 &&
buffer_[start_index].packet->height() > 0) {
idr_width = buffer_[start_index].packet->width();
idr_height = buffer_[start_index].packet->height();
}
}
}
@ -344,8 +340,8 @@ std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
// the PacketBuffer to hand out incomplete frames.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
if (is_h264 &&
(!buffer_[start_index].used ||
buffer_[start_index].data.timestamp != frame_timestamp)) {
(!buffer_[start_index].used() ||
buffer_[start_index].packet->timestamp != frame_timestamp)) {
break;
}
@ -369,23 +365,27 @@ std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
// determines if the RtpFrameObject is a key frame or delta frame.
const size_t first_packet_index = start_seq_num % buffer_.size();
if (is_h264_keyframe) {
buffer_[first_packet_index].data.video_header.frame_type =
buffer_[first_packet_index].packet->video_header.frame_type =
VideoFrameType::kVideoFrameKey;
if (idr_width > 0 && idr_height > 0) {
// IDR frame was finalized and we have the correct resolution for
// IDR; update first packet to have same resolution as IDR.
buffer_[first_packet_index].data.video_header.width = idr_width;
buffer_[first_packet_index].data.video_header.height = idr_height;
buffer_[first_packet_index].packet->video_header.width = idr_width;
buffer_[first_packet_index].packet->video_header.height =
idr_height;
}
} else {
buffer_[first_packet_index].data.video_header.frame_type =
buffer_[first_packet_index].packet->video_header.frame_type =
VideoFrameType::kVideoFrameDelta;
}
// With IPPP, if this is not a keyframe, make sure there are no gaps
// in the packet sequence numbers up until this point.
const uint8_t h264tid =
buffer_[start_index].data.video_header.frame_marking.temporal_id;
buffer_[start_index].used()
? buffer_[start_index]
.packet->video_header.frame_marking.temporal_id
: kNoTemporalIdx;
if (h264tid == kNoTemporalIdx && !is_h264_keyframe &&
missing_packets_.upper_bound(start_seq_num) !=
missing_packets_.begin()) {
@ -480,9 +480,9 @@ std::unique_ptr<RtpFrameObject> PacketBuffer::AssembleFrame(
const PacketBuffer::Packet& PacketBuffer::GetPacket(uint16_t seq_num) const {
const StoredPacket& entry = buffer_[seq_num % buffer_.size()];
RTC_DCHECK(entry.used);
RTC_DCHECK(entry.used());
RTC_DCHECK_EQ(seq_num, entry.seq_num());
return entry.data;
return *entry.packet;
}
void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {