Index: webrtc/modules/video_coding/rtp_frame_reference_finder.cc |
diff --git a/webrtc/modules/video_coding/packet_buffer.cc b/webrtc/modules/video_coding/rtp_frame_reference_finder.cc |
similarity index 64% |
copy from webrtc/modules/video_coding/packet_buffer.cc |
copy to webrtc/modules/video_coding/rtp_frame_reference_finder.cc |
index 71ab3e57d859fe20a5d518cb3a96856280c3fc1e..2ddfada74e5e7763d5810538d84230894437568f 100644 |
--- a/webrtc/modules/video_coding/packet_buffer.cc |
+++ b/webrtc/modules/video_coding/rtp_frame_reference_finder.cc |
@@ -8,7 +8,7 @@ |
* be found in the AUTHORS file in the root of the source tree. |
*/ |
-#include "webrtc/modules/video_coding/packet_buffer.h" |
+#include "webrtc/modules/video_coding/rtp_frame_reference_finder.h" |
#include <algorithm> |
#include <limits> |
@@ -16,199 +16,22 @@ |
#include "webrtc/base/checks.h" |
#include "webrtc/base/logging.h" |
#include "webrtc/modules/video_coding/frame_object.h" |
+#include "webrtc/modules/video_coding/packet_buffer.h" |
namespace webrtc { |
namespace video_coding { |
-PacketBuffer::PacketBuffer(size_t start_buffer_size, |
- size_t max_buffer_size, |
- OnCompleteFrameCallback* frame_callback) |
- : size_(start_buffer_size), |
- max_size_(max_buffer_size), |
- first_seq_num_(0), |
- last_seq_num_(0), |
- first_packet_received_(false), |
- data_buffer_(start_buffer_size), |
- sequence_buffer_(start_buffer_size), |
- frame_callback_(frame_callback), |
- last_picture_id_(-1), |
+RtpFrameReferenceFinder::RtpFrameReferenceFinder( |
+ OnCompleteFrameCallback* frame_callback) |
+ : last_picture_id_(-1), |
last_unwrap_(-1), |
- current_ss_idx_(0) { |
- RTC_DCHECK_LE(start_buffer_size, max_buffer_size); |
- // Buffer size must always be a power of 2. |
- RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); |
- RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); |
-} |
- |
-bool PacketBuffer::InsertPacket(const VCMPacket& packet) { |
- rtc::CritScope lock(&crit_); |
- uint16_t seq_num = packet.seqNum; |
- size_t index = seq_num % size_; |
- |
- if (!first_packet_received_) { |
- first_seq_num_ = seq_num - 1; |
- last_seq_num_ = seq_num; |
- first_packet_received_ = true; |
- } |
- |
- if (sequence_buffer_[index].used) { |
- // Duplicate packet, do nothing. |
- if (data_buffer_[index].seqNum == packet.seqNum) |
- return true; |
- |
- // The packet buffer is full, try to expand the buffer. |
- while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) { |
- } |
- index = seq_num % size_; |
- |
- // Packet buffer is still full. |
- if (sequence_buffer_[index].used) |
- return false; |
- } |
- |
- if (AheadOf(seq_num, last_seq_num_)) |
- last_seq_num_ = seq_num; |
- |
- sequence_buffer_[index].frame_begin = packet.isFirstPacket; |
- sequence_buffer_[index].frame_end = packet.markerBit; |
- sequence_buffer_[index].seq_num = packet.seqNum; |
- sequence_buffer_[index].continuous = false; |
- sequence_buffer_[index].frame_created = false; |
- sequence_buffer_[index].used = true; |
- data_buffer_[index] = packet; |
- |
- FindFrames(seq_num); |
- return true; |
-} |
+ current_ss_idx_(0), |
+ frame_callback_(frame_callback) {} |
-void PacketBuffer::ClearTo(uint16_t seq_num) { |
- rtc::CritScope lock(&crit_); |
- size_t index = first_seq_num_ % size_; |
- while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) { |
- index = (index + 1) % size_; |
- first_seq_num_ = Add<1 << 16>(first_seq_num_, 1); |
- sequence_buffer_[index].used = false; |
- } |
-} |
- |
-bool PacketBuffer::ExpandBufferSize() { |
- if (size_ == max_size_) |
- return false; |
- |
- size_t new_size = std::min(max_size_, 2 * size_); |
- std::vector<VCMPacket> new_data_buffer(new_size); |
- std::vector<ContinuityInfo> new_sequence_buffer(new_size); |
- for (size_t i = 0; i < size_; ++i) { |
- if (sequence_buffer_[i].used) { |
- size_t index = sequence_buffer_[i].seq_num % new_size; |
- new_sequence_buffer[index] = sequence_buffer_[i]; |
- new_data_buffer[index] = data_buffer_[i]; |
- } |
- } |
- size_ = new_size; |
- sequence_buffer_ = std::move(new_sequence_buffer); |
- data_buffer_ = std::move(new_data_buffer); |
- return true; |
-} |
- |
-bool PacketBuffer::IsContinuous(uint16_t seq_num) const { |
- size_t index = seq_num % size_; |
- int prev_index = index > 0 ? index - 1 : size_ - 1; |
- |
- if (!sequence_buffer_[index].used) |
- return false; |
- if (sequence_buffer_[index].frame_created) |
- return false; |
- if (sequence_buffer_[index].frame_begin) |
- return true; |
- if (!sequence_buffer_[prev_index].used) |
- return false; |
- if (sequence_buffer_[prev_index].seq_num != |
- static_cast<uint16_t>(seq_num - 1)) |
- return false; |
- if (sequence_buffer_[prev_index].continuous) |
- return true; |
- |
- return false; |
-} |
- |
-void PacketBuffer::FindFrames(uint16_t seq_num) { |
- size_t index = seq_num % size_; |
- while (IsContinuous(seq_num)) { |
- sequence_buffer_[index].continuous = true; |
- |
- // If all packets of the frame is continuous, find the first packet of the |
- // frame and create an RtpFrameObject. |
- if (sequence_buffer_[index].frame_end) { |
- int start_index = index; |
- uint16_t start_seq_num = seq_num; |
- |
- while (!sequence_buffer_[start_index].frame_begin) { |
- sequence_buffer_[start_index].frame_created = true; |
- start_index = start_index > 0 ? start_index - 1 : size_ - 1; |
- start_seq_num--; |
- } |
- sequence_buffer_[start_index].frame_created = true; |
- |
- std::unique_ptr<RtpFrameObject> frame( |
- new RtpFrameObject(this, start_seq_num, seq_num)); |
- ManageFrame(std::move(frame)); |
- } |
- |
- index = (index + 1) % size_; |
- ++seq_num; |
- } |
-} |
- |
-void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { |
- rtc::CritScope lock(&crit_); |
- size_t index = frame->first_seq_num() % size_; |
- size_t end = (frame->last_seq_num() + 1) % size_; |
- uint16_t seq_num = frame->first_seq_num(); |
- while (index != end) { |
- if (sequence_buffer_[index].seq_num == seq_num) |
- sequence_buffer_[index].used = false; |
- |
- index = (index + 1) % size_; |
- ++seq_num; |
- } |
- |
- index = first_seq_num_ % size_; |
- while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) && |
- !sequence_buffer_[index].used) { |
- ++first_seq_num_; |
- index = (index + 1) % size_; |
- } |
-} |
- |
-bool PacketBuffer::GetBitstream(const RtpFrameObject& frame, |
- uint8_t* destination) { |
+void RtpFrameReferenceFinder::ManageFrame( |
+ std::unique_ptr<RtpFrameObject> frame) { |
rtc::CritScope lock(&crit_); |
- |
- size_t index = frame.first_seq_num() % size_; |
- size_t end = (frame.last_seq_num() + 1) % size_; |
- uint16_t seq_num = frame.first_seq_num(); |
- while (index != end) { |
- if (!sequence_buffer_[index].used || |
- sequence_buffer_[index].seq_num != seq_num) { |
- return false; |
- } |
- |
- const uint8_t* source = data_buffer_[index].dataPtr; |
- size_t length = data_buffer_[index].sizeBytes; |
- memcpy(destination, source, length); |
- destination += length; |
- index = (index + 1) % size_; |
- ++seq_num; |
- } |
- return true; |
-} |
- |
-void PacketBuffer::ManageFrame(std::unique_ptr<RtpFrameObject> frame) { |
- size_t start_index = frame->first_seq_num() % size_; |
- VideoCodecType codec_type = data_buffer_[start_index].codec; |
- |
- switch (codec_type) { |
+ switch (frame->codec_type()) { |
case kVideoCodecULPFEC: |
case kVideoCodecRED: |
case kVideoCodecUnknown: |
@@ -228,7 +51,7 @@ void PacketBuffer::ManageFrame(std::unique_ptr<RtpFrameObject> frame) { |
} |
} |
-void PacketBuffer::RetryStashedFrames() { |
+void RtpFrameReferenceFinder::RetryStashedFrames() { |
size_t num_stashed_frames = stashed_frames_.size(); |
// Clean up stashed frames if there are too many. |
@@ -245,12 +68,9 @@ void PacketBuffer::RetryStashedFrames() { |
} |
} |
-void PacketBuffer::ManageFrameGeneric( |
+void RtpFrameReferenceFinder::ManageFrameGeneric( |
std::unique_ptr<RtpFrameObject> frame) { |
- size_t index = frame->first_seq_num() % size_; |
- const VCMPacket& packet = data_buffer_[index]; |
- |
- if (packet.frameType == kVideoFrameKey) |
+ if (frame->frame_type() == kVideoFrameKey) |
last_seq_num_gop_[frame->last_seq_num()] = frame->last_seq_num(); |
// We have received a frame but not yet a keyframe, stash this frame. |
@@ -272,7 +92,7 @@ void PacketBuffer::ManageFrameGeneric( |
// Make sure the packet sequence numbers are continuous, otherwise stash |
// this frame. |
- if (packet.frameType == kVideoFrameDelta) { |
+ if (frame->frame_type() == kVideoFrameDelta) { |
if (seq_num_it->second != |
static_cast<uint16_t>(frame->first_seq_num() - 1)) { |
stashed_frames_.emplace(std::move(frame)); |
@@ -282,11 +102,10 @@ void PacketBuffer::ManageFrameGeneric( |
RTC_DCHECK(AheadOrAt(frame->last_seq_num(), seq_num_it->first)); |
- // Since keyframes can cause reordering of the frames delivered from |
- // FindFrames() we can't simply assign the picture id according to some |
- // incrementing counter. |
+ // Since keyframes can cause reordering we can't simply assign the |
+ // picture id according to some incrementing counter. |
frame->picture_id = frame->last_seq_num(); |
- frame->num_references = packet.frameType == kVideoFrameDelta; |
+ frame->num_references = frame->frame_type() == kVideoFrameDelta; |
frame->references[0] = seq_num_it->second; |
seq_num_it->second = frame->picture_id; |
@@ -295,11 +114,13 @@ void PacketBuffer::ManageFrameGeneric( |
RetryStashedFrames(); |
} |
-void PacketBuffer::ManageFrameVp8(std::unique_ptr<RtpFrameObject> frame) { |
- size_t index = frame->first_seq_num() % size_; |
- const VCMPacket& packet = data_buffer_[index]; |
- const RTPVideoHeaderVP8& codec_header = |
- packet.codecSpecificHeader.codecHeader.VP8; |
+void RtpFrameReferenceFinder::ManageFrameVp8( |
+ std::unique_ptr<RtpFrameObject> frame) { |
+ RTPVideoTypeHeader* rtp_codec_header = frame->GetCodecHeader(); |
+ if (!rtp_codec_header) |
+ return; |
+ |
+ const RTPVideoHeaderVP8& codec_header = rtp_codec_header->VP8; |
if (codec_header.pictureId == kNoPictureId || |
codec_header.temporalIdx == kNoTemporalIdx || |
@@ -332,13 +153,13 @@ void PacketBuffer::ManageFrameVp8(std::unique_ptr<RtpFrameObject> frame) { |
layer_info_.erase(layer_info_.begin(), clean_layer_info_to); |
// Clean up info about not yet received frames that are too old. |
- uint16_t old_picture_id = Subtract<kPicIdLength>(frame->picture_id, |
- kMaxNotYetReceivedFrames); |
+ uint16_t old_picture_id = |
+ Subtract<kPicIdLength>(frame->picture_id, kMaxNotYetReceivedFrames); |
auto clean_frames_to = not_yet_received_frames_.lower_bound(old_picture_id); |
not_yet_received_frames_.erase(not_yet_received_frames_.begin(), |
clean_frames_to); |
- if (packet.frameType == kVideoFrameKey) { |
+ if (frame->frame_type() == kVideoFrameKey) { |
frame->num_references = 0; |
layer_info_[codec_header.tl0PicIdx].fill(-1); |
CompletedFrameVp8(std::move(frame)); |
@@ -386,7 +207,7 @@ void PacketBuffer::ManageFrameVp8(std::unique_ptr<RtpFrameObject> frame) { |
// If we have not yet received a frame between this frame and the referenced |
// frame then we have to wait for that frame to be completed first. |
auto not_received_frame_it = |
- not_yet_received_frames_.upper_bound(layer_info_it->second[layer]); |
+ not_yet_received_frames_.upper_bound(layer_info_it->second[layer]); |
if (not_received_frame_it != not_yet_received_frames_.end() && |
AheadOf<uint16_t, kPicIdLength>(frame->picture_id, |
*not_received_frame_it)) { |
@@ -401,11 +222,13 @@ void PacketBuffer::ManageFrameVp8(std::unique_ptr<RtpFrameObject> frame) { |
CompletedFrameVp8(std::move(frame)); |
} |
-void PacketBuffer::CompletedFrameVp8(std::unique_ptr<RtpFrameObject> frame) { |
- size_t index = frame->first_seq_num() % size_; |
- const VCMPacket& packet = data_buffer_[index]; |
- const RTPVideoHeaderVP8& codec_header = |
- packet.codecSpecificHeader.codecHeader.VP8; |
+void RtpFrameReferenceFinder::CompletedFrameVp8( |
+ std::unique_ptr<RtpFrameObject> frame) { |
+ RTPVideoTypeHeader* rtp_codec_header = frame->GetCodecHeader(); |
+ if (!rtp_codec_header) |
+ return; |
+ |
+ const RTPVideoHeaderVP8& codec_header = rtp_codec_header->VP8; |
uint8_t tl0_pic_idx = codec_header.tl0PicIdx; |
uint8_t temporal_index = codec_header.temporalIdx; |
@@ -435,11 +258,13 @@ void PacketBuffer::CompletedFrameVp8(std::unique_ptr<RtpFrameObject> frame) { |
RetryStashedFrames(); |
} |
-void PacketBuffer::ManageFrameVp9(std::unique_ptr<RtpFrameObject> frame) { |
- size_t index = frame->first_seq_num() % size_; |
- const VCMPacket& packet = data_buffer_[index]; |
- const RTPVideoHeaderVP9& codec_header = |
- packet.codecSpecificHeader.codecHeader.VP9; |
+void RtpFrameReferenceFinder::ManageFrameVp9( |
+ std::unique_ptr<RtpFrameObject> frame) { |
+ RTPVideoTypeHeader* rtp_codec_header = frame->GetCodecHeader(); |
+ if (!rtp_codec_header) |
+ return; |
+ |
+ const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9; |
if (codec_header.picture_id == kNoPictureId) { |
ManageFrameGeneric(std::move(frame)); |
@@ -488,7 +313,7 @@ void PacketBuffer::ManageFrameVp9(std::unique_ptr<RtpFrameObject> frame) { |
auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx); |
gof_info_.erase(gof_info_.begin(), clean_gof_info_to); |
- if (packet.frameType == kVideoFrameKey) { |
+ if (frame->frame_type() == kVideoFrameKey) { |
// When using GOF all keyframes must include the scalability structure. |
if (!codec_header.ss_data_available) |
LOG(LS_WARNING) << "Received keyframe without scalability structure"; |
@@ -566,8 +391,8 @@ void PacketBuffer::ManageFrameVp9(std::unique_ptr<RtpFrameObject> frame) { |
CompletedFrameVp9(std::move(frame)); |
} |
-bool PacketBuffer::MissingRequiredFrameVp9(uint16_t picture_id, |
- const GofInfoVP9& gof) { |
+bool RtpFrameReferenceFinder::MissingRequiredFrameVp9(uint16_t picture_id, |
+ const GofInfoVP9& gof) { |
size_t diff = ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, picture_id); |
size_t gof_idx = diff % gof.num_frames_in_gof; |
size_t temporal_idx = gof.temporal_idx[gof_idx]; |
@@ -590,8 +415,8 @@ bool PacketBuffer::MissingRequiredFrameVp9(uint16_t picture_id, |
return false; |
} |
-void PacketBuffer::FrameReceivedVp9(uint16_t picture_id, |
- const GofInfoVP9& gof) { |
+void RtpFrameReferenceFinder::FrameReceivedVp9(uint16_t picture_id, |
+ const GofInfoVP9& gof) { |
RTC_DCHECK_NE(-1, last_picture_id_); |
// If there is a gap, find which temporal layer the missing frames |
@@ -619,9 +444,9 @@ void PacketBuffer::FrameReceivedVp9(uint16_t picture_id, |
} |
} |
-bool PacketBuffer::UpSwitchInIntervalVp9(uint16_t picture_id, |
- uint8_t temporal_idx, |
- uint16_t pid_ref) { |
+bool RtpFrameReferenceFinder::UpSwitchInIntervalVp9(uint16_t picture_id, |
+ uint8_t temporal_idx, |
+ uint16_t pid_ref) { |
for (auto up_switch_it = up_switch_.upper_bound(pid_ref); |
up_switch_it != up_switch_.end() && |
AheadOf<uint16_t, kPicIdLength>(picture_id, up_switch_it->first); |
@@ -633,7 +458,8 @@ bool PacketBuffer::UpSwitchInIntervalVp9(uint16_t picture_id, |
return false; |
} |
-void PacketBuffer::CompletedFrameVp9(std::unique_ptr<RtpFrameObject> frame) { |
+void RtpFrameReferenceFinder::CompletedFrameVp9( |
+ std::unique_ptr<RtpFrameObject> frame) { |
for (size_t i = 0; i < frame->num_references; ++i) |
frame->references[i] = UnwrapPictureId(frame->references[i]); |
frame->picture_id = UnwrapPictureId(frame->picture_id); |
@@ -642,7 +468,7 @@ void PacketBuffer::CompletedFrameVp9(std::unique_ptr<RtpFrameObject> frame) { |
RetryStashedFrames(); |
} |
-uint16_t PacketBuffer::UnwrapPictureId(uint16_t picture_id) { |
+uint16_t RtpFrameReferenceFinder::UnwrapPictureId(uint16_t picture_id) { |
RTC_DCHECK_NE(-1, last_unwrap_); |
uint16_t unwrap_truncated = last_unwrap_ % kPicIdLength; |
@@ -656,18 +482,5 @@ uint16_t PacketBuffer::UnwrapPictureId(uint16_t picture_id) { |
return last_unwrap_; |
} |
-void PacketBuffer::Flush() { |
- rtc::CritScope lock(&crit_); |
- for (size_t i = 0; i < size_; ++i) |
- sequence_buffer_[i].used = false; |
- |
- last_seq_num_gop_.clear(); |
- while (!stashed_frames_.empty()) |
- stashed_frames_.pop(); |
- not_yet_received_frames_.clear(); |
- |
- first_packet_received_ = false; |
-} |
- |
} // namespace video_coding |
} // namespace webrtc |