diff --git a/webrtc/modules/video_coding/frame_object.cc b/webrtc/modules/video_coding/frame_object.cc index 7b9ec0d283..650b65ff2c 100644 --- a/webrtc/modules/video_coding/frame_object.cc +++ b/webrtc/modules/video_coding/frame_object.cc @@ -24,10 +24,14 @@ FrameObject::FrameObject() RtpFrameObject::RtpFrameObject(PacketBuffer* packet_buffer, uint16_t first_seq_num, - uint16_t last_seq_num) + uint16_t last_seq_num, + size_t frame_size, + int times_nacked) : packet_buffer_(packet_buffer), first_seq_num_(first_seq_num), - last_seq_num_(last_seq_num) { + last_seq_num_(last_seq_num), + times_nacked_(times_nacked) { + size = frame_size; VCMPacket* packet = packet_buffer_->GetPacket(first_seq_num); if (packet) { frame_type_ = packet->frameType; @@ -47,6 +51,10 @@ uint16_t RtpFrameObject::last_seq_num() const { return last_seq_num_; } +int RtpFrameObject::times_nacked() const { + return times_nacked_; +} + FrameType RtpFrameObject::frame_type() const { return frame_type_; } diff --git a/webrtc/modules/video_coding/frame_object.h b/webrtc/modules/video_coding/frame_object.h index e8bb4811e6..02d7342842 100644 --- a/webrtc/modules/video_coding/frame_object.h +++ b/webrtc/modules/video_coding/frame_object.h @@ -36,6 +36,8 @@ class FrameObject { size_t num_references; uint16_t references[kMaxFrameReferences]; bool inter_layer_predicted; + + size_t size; }; class PacketBuffer; @@ -44,11 +46,14 @@ class RtpFrameObject : public FrameObject { public: RtpFrameObject(PacketBuffer* packet_buffer, uint16_t first_seq_num, - uint16_t last_seq_num); + uint16_t last_seq_num, + size_t frame_size, + int times_nacked); ~RtpFrameObject(); uint16_t first_seq_num() const; uint16_t last_seq_num() const; + int times_nacked() const; FrameType frame_type() const; VideoCodecType codec_type() const; bool GetBitstream(uint8_t* destination) const override; @@ -60,6 +65,10 @@ class RtpFrameObject : public FrameObject { VideoCodecType codec_type_; uint16_t first_seq_num_; uint16_t last_seq_num_; + + // Equal to times nacked of the packet with the highet times nacked + // belonging to this frame. + int times_nacked_; }; } // namespace video_coding diff --git a/webrtc/modules/video_coding/packet.cc b/webrtc/modules/video_coding/packet.cc index e25de2ed6c..e8c06a6977 100644 --- a/webrtc/modules/video_coding/packet.cc +++ b/webrtc/modules/video_coding/packet.cc @@ -24,6 +24,7 @@ VCMPacket::VCMPacket() dataPtr(NULL), sizeBytes(0), markerBit(false), + timesNacked(-1), frameType(kEmptyFrame), codec(kVideoCodecUnknown), isFirstPacket(false), @@ -43,6 +44,7 @@ VCMPacket::VCMPacket(const uint8_t* ptr, dataPtr(ptr), sizeBytes(size), markerBit(rtpHeader.header.markerBit), + timesNacked(-1), frameType(rtpHeader.frameType), codec(kVideoCodecUnknown), @@ -67,6 +69,7 @@ VCMPacket::VCMPacket(const uint8_t* ptr, dataPtr(ptr), sizeBytes(size), markerBit(mBit), + timesNacked(-1), frameType(kVideoFrameDelta), codec(kVideoCodecUnknown), @@ -85,6 +88,7 @@ void VCMPacket::Reset() { dataPtr = NULL; sizeBytes = 0; markerBit = false; + timesNacked = -1; frameType = kEmptyFrame; codec = kVideoCodecUnknown; isFirstPacket = false; diff --git a/webrtc/modules/video_coding/packet.h b/webrtc/modules/video_coding/packet.h index b77c1df039..bb62cb9ac5 100644 --- a/webrtc/modules/video_coding/packet.h +++ b/webrtc/modules/video_coding/packet.h @@ -39,6 +39,7 @@ class VCMPacket { const uint8_t* dataPtr; size_t sizeBytes; bool markerBit; + int timesNacked; FrameType frameType; VideoCodecType codec; diff --git a/webrtc/modules/video_coding/packet_buffer.cc b/webrtc/modules/video_coding/packet_buffer.cc index 09fb249907..ad0054fa84 100644 --- a/webrtc/modules/video_coding/packet_buffer.cc +++ b/webrtc/modules/video_coding/packet_buffer.cc @@ -137,18 +137,28 @@ void PacketBuffer::FindFrames(uint16_t seq_num) { // 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; + size_t frame_size = 0; + int max_nack_count = -1; uint16_t start_seq_num = seq_num; - while (!sequence_buffer_[start_index].frame_begin) { + // Find the start index by searching backward until the packet with + // the |frame_begin| flag is set. + int start_index = index; + while (true) { + frame_size += data_buffer_[start_index].sizeBytes; + max_nack_count = std::max( + max_nack_count, data_buffer_[start_index].timesNacked); sequence_buffer_[start_index].frame_created = true; + + if (sequence_buffer_[start_index].frame_begin) + break; + start_index = start_index > 0 ? start_index - 1 : size_ - 1; start_seq_num--; } - sequence_buffer_[start_index].frame_created = true; - std::unique_ptr frame( - new RtpFrameObject(this, start_seq_num, seq_num)); + std::unique_ptr frame(new RtpFrameObject( + this, start_seq_num, seq_num, frame_size, max_nack_count)); reference_finder_.ManageFrame(std::move(frame)); } diff --git a/webrtc/modules/video_coding/packet_buffer_unittest.cc b/webrtc/modules/video_coding/packet_buffer_unittest.cc index b50074d8f6..753b5b471b 100644 --- a/webrtc/modules/video_coding/packet_buffer_unittest.cc +++ b/webrtc/modules/video_coding/packet_buffer_unittest.cc @@ -265,12 +265,62 @@ TEST_F(TestPacketBuffer, InsertDuplicatePacket) { EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); } +TEST_F(TestPacketBuffer, NackCount) { + uint16_t seq_num = Rand(); + + VCMPacket packet; + packet.codec = kVideoCodecGeneric; + packet.seqNum = seq_num; + packet.frameType = kVideoFrameKey; + packet.isFirstPacket = true; + packet.markerBit = false; + packet.sizeBytes = 0; + packet.dataPtr = nullptr; + packet.timesNacked = 0; + + packet_buffer_->InsertPacket(packet); + + packet.seqNum++; + packet.isFirstPacket = false; + packet.timesNacked = 1; + packet_buffer_->InsertPacket(packet); + + packet.seqNum++; + packet.timesNacked = 3; + packet_buffer_->InsertPacket(packet); + + packet.seqNum++; + packet.markerBit = true; + packet.timesNacked = 1; + packet_buffer_->InsertPacket(packet); + + + ASSERT_EQ(1UL, frames_from_callback_.size()); + FrameObject* frame = frames_from_callback_.begin()->second.get(); + RtpFrameObject* rtp_frame = static_cast(frame); + EXPECT_EQ(3, rtp_frame->times_nacked()); +} + +TEST_F(TestPacketBuffer, FrameSize) { + uint16_t seq_num = Rand(); + uint8_t data[] = {1, 2, 3, 4, 5}; + + // seq_num , kf, frst, lst, size, data + InsertGeneric(seq_num , kT, kT , kF , 5 , data); + InsertGeneric(seq_num + 1, kT, kF , kF , 5 , data); + InsertGeneric(seq_num + 2, kT, kF , kF , 5 , data); + InsertGeneric(seq_num + 3, kT, kF , kT , 5 , data); + + ASSERT_EQ(1UL, frames_from_callback_.size()); + EXPECT_EQ(20UL, frames_from_callback_.begin()->second->size); +} + TEST_F(TestPacketBuffer, ExpandBuffer) { uint16_t seq_num = Rand(); for (int i = 0; i < kStartSize + 1; ++i) { // seq_num , kf, frst, lst - InsertGeneric(seq_num + i, kT , kT, kT); + InsertGeneric(seq_num + i, kT, kT , kT); } }