Track last packet receive times in RtpVideoStreamReceiver instead of the PacketBuffer.
Bug: webrtc:12579 Change-Id: I4adb8c6ada913127b9e65d97ddce0dc71ec6ccee Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214784 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33713}
This commit is contained in:
@ -30,7 +30,6 @@
|
|||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/numerics/mod_ops.h"
|
#include "rtc_base/numerics/mod_ops.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace video_coding {
|
namespace video_coding {
|
||||||
@ -51,11 +50,8 @@ PacketBuffer::Packet::Packet(const RtpPacketReceived& rtp_packet,
|
|||||||
rtp_packet.GetExtension<AbsoluteCaptureTimeExtension>(),
|
rtp_packet.GetExtension<AbsoluteCaptureTimeExtension>(),
|
||||||
receive_time_ms) {}
|
receive_time_ms) {}
|
||||||
|
|
||||||
PacketBuffer::PacketBuffer(Clock* clock,
|
PacketBuffer::PacketBuffer(size_t start_buffer_size, size_t max_buffer_size)
|
||||||
size_t start_buffer_size,
|
: max_size_(max_buffer_size),
|
||||||
size_t max_buffer_size)
|
|
||||||
: clock_(clock),
|
|
||||||
max_size_(max_buffer_size),
|
|
||||||
first_seq_num_(0),
|
first_seq_num_(0),
|
||||||
first_packet_received_(false),
|
first_packet_received_(false),
|
||||||
is_cleared_to_first_seq_num_(false),
|
is_cleared_to_first_seq_num_(false),
|
||||||
@ -114,14 +110,6 @@ PacketBuffer::InsertResult PacketBuffer::InsertPacket(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
||||||
last_received_packet_ms_ = now_ms;
|
|
||||||
if (packet->video_header.frame_type == VideoFrameType::kVideoFrameKey ||
|
|
||||||
last_received_keyframe_rtp_timestamp_ == packet->timestamp) {
|
|
||||||
last_received_keyframe_packet_ms_ = now_ms;
|
|
||||||
last_received_keyframe_rtp_timestamp_ = packet->timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet->continuous = false;
|
packet->continuous = false;
|
||||||
buffer_[index] = std::move(packet);
|
buffer_[index] = std::move(packet);
|
||||||
|
|
||||||
@ -181,18 +169,10 @@ PacketBuffer::InsertResult PacketBuffer::InsertPadding(uint16_t seq_num) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
|
|
||||||
MutexLock lock(&mutex_);
|
|
||||||
return last_received_packet_ms_;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
|
|
||||||
MutexLock lock(&mutex_);
|
|
||||||
return last_received_keyframe_packet_ms_;
|
|
||||||
}
|
|
||||||
void PacketBuffer::ForceSpsPpsIdrIsH264Keyframe() {
|
void PacketBuffer::ForceSpsPpsIdrIsH264Keyframe() {
|
||||||
sps_pps_idr_is_h264_keyframe_ = true;
|
sps_pps_idr_is_h264_keyframe_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketBuffer::ClearInternal() {
|
void PacketBuffer::ClearInternal() {
|
||||||
for (auto& entry : buffer_) {
|
for (auto& entry : buffer_) {
|
||||||
entry = nullptr;
|
entry = nullptr;
|
||||||
@ -200,8 +180,6 @@ void PacketBuffer::ClearInternal() {
|
|||||||
|
|
||||||
first_packet_received_ = false;
|
first_packet_received_ = false;
|
||||||
is_cleared_to_first_seq_num_ = false;
|
is_cleared_to_first_seq_num_ = false;
|
||||||
last_received_packet_ms_.reset();
|
|
||||||
last_received_keyframe_packet_ms_.reset();
|
|
||||||
newest_inserted_seq_num_.reset();
|
newest_inserted_seq_num_.reset();
|
||||||
missing_packets_.clear();
|
missing_packets_.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,6 @@
|
|||||||
#include "rtc_base/numerics/sequence_number_util.h"
|
#include "rtc_base/numerics/sequence_number_util.h"
|
||||||
#include "rtc_base/synchronization/mutex.h"
|
#include "rtc_base/synchronization/mutex.h"
|
||||||
#include "rtc_base/thread_annotations.h"
|
#include "rtc_base/thread_annotations.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace video_coding {
|
namespace video_coding {
|
||||||
@ -76,7 +75,7 @@ class PacketBuffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Both |start_buffer_size| and |max_buffer_size| must be a power of 2.
|
// Both |start_buffer_size| and |max_buffer_size| must be a power of 2.
|
||||||
PacketBuffer(Clock* clock, size_t start_buffer_size, size_t max_buffer_size);
|
PacketBuffer(size_t start_buffer_size, size_t max_buffer_size);
|
||||||
~PacketBuffer();
|
~PacketBuffer();
|
||||||
|
|
||||||
ABSL_MUST_USE_RESULT InsertResult InsertPacket(std::unique_ptr<Packet> packet)
|
ABSL_MUST_USE_RESULT InsertResult InsertPacket(std::unique_ptr<Packet> packet)
|
||||||
@ -86,16 +85,9 @@ class PacketBuffer {
|
|||||||
void ClearTo(uint16_t seq_num) RTC_LOCKS_EXCLUDED(mutex_);
|
void ClearTo(uint16_t seq_num) RTC_LOCKS_EXCLUDED(mutex_);
|
||||||
void Clear() RTC_LOCKS_EXCLUDED(mutex_);
|
void Clear() RTC_LOCKS_EXCLUDED(mutex_);
|
||||||
|
|
||||||
// Timestamp (not RTP timestamp) of the last received packet/keyframe packet.
|
|
||||||
absl::optional<int64_t> LastReceivedPacketMs() const
|
|
||||||
RTC_LOCKS_EXCLUDED(mutex_);
|
|
||||||
absl::optional<int64_t> LastReceivedKeyframePacketMs() const
|
|
||||||
RTC_LOCKS_EXCLUDED(mutex_);
|
|
||||||
void ForceSpsPpsIdrIsH264Keyframe();
|
void ForceSpsPpsIdrIsH264Keyframe();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Clock* const clock_;
|
|
||||||
|
|
||||||
// Clears with |mutex_| taken.
|
// Clears with |mutex_| taken.
|
||||||
void ClearInternal() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
void ClearInternal() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||||
|
|
||||||
@ -132,13 +124,6 @@ class PacketBuffer {
|
|||||||
// determine continuity between them.
|
// determine continuity between them.
|
||||||
std::vector<std::unique_ptr<Packet>> buffer_ RTC_GUARDED_BY(mutex_);
|
std::vector<std::unique_ptr<Packet>> buffer_ RTC_GUARDED_BY(mutex_);
|
||||||
|
|
||||||
// Timestamp of the last received packet/keyframe packet.
|
|
||||||
absl::optional<int64_t> last_received_packet_ms_ RTC_GUARDED_BY(mutex_);
|
|
||||||
absl::optional<int64_t> last_received_keyframe_packet_ms_
|
|
||||||
RTC_GUARDED_BY(mutex_);
|
|
||||||
absl::optional<uint32_t> last_received_keyframe_rtp_timestamp_
|
|
||||||
RTC_GUARDED_BY(mutex_);
|
|
||||||
|
|
||||||
absl::optional<uint16_t> newest_inserted_seq_num_ RTC_GUARDED_BY(mutex_);
|
absl::optional<uint16_t> newest_inserted_seq_num_ RTC_GUARDED_BY(mutex_);
|
||||||
std::set<uint16_t, DescendingSeqNumComp<uint16_t>> missing_packets_
|
std::set<uint16_t, DescendingSeqNumComp<uint16_t>> missing_packets_
|
||||||
RTC_GUARDED_BY(mutex_);
|
RTC_GUARDED_BY(mutex_);
|
||||||
|
|||||||
@ -19,7 +19,6 @@
|
|||||||
#include "common_video/h264/h264_common.h"
|
#include "common_video/h264/h264_common.h"
|
||||||
#include "modules/video_coding/frame_object.h"
|
#include "modules/video_coding/frame_object.h"
|
||||||
#include "rtc_base/random.h"
|
#include "rtc_base/random.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
|
||||||
#include "test/field_trial.h"
|
#include "test/field_trial.h"
|
||||||
#include "test/gmock.h"
|
#include "test/gmock.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
@ -100,10 +99,7 @@ void PrintTo(const PacketBufferInsertResult& result, std::ostream* os) {
|
|||||||
|
|
||||||
class PacketBufferTest : public ::testing::Test {
|
class PacketBufferTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
PacketBufferTest()
|
PacketBufferTest() : rand_(0x7732213), packet_buffer_(kStartSize, kMaxSize) {}
|
||||||
: rand_(0x7732213),
|
|
||||||
clock_(0),
|
|
||||||
packet_buffer_(&clock_, kStartSize, kMaxSize) {}
|
|
||||||
|
|
||||||
uint16_t Rand() { return rand_.Rand<uint16_t>(); }
|
uint16_t Rand() { return rand_.Rand<uint16_t>(); }
|
||||||
|
|
||||||
@ -133,7 +129,6 @@ class PacketBufferTest : public ::testing::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Random rand_;
|
Random rand_;
|
||||||
SimulatedClock clock_;
|
|
||||||
PacketBuffer packet_buffer_;
|
PacketBuffer packet_buffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -616,67 +611,6 @@ TEST_F(PacketBufferTest, ContinuousSeqNumDoubleMarkerBit) {
|
|||||||
EXPECT_THAT(Insert(3, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
|
EXPECT_THAT(Insert(3, kKeyFrame, kNotFirst, kLast).packets, IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PacketBufferTest, PacketTimestamps) {
|
|
||||||
absl::optional<int64_t> packet_ms;
|
|
||||||
absl::optional<int64_t> packet_keyframe_ms;
|
|
||||||
|
|
||||||
packet_ms = packet_buffer_.LastReceivedPacketMs();
|
|
||||||
packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
|
|
||||||
EXPECT_FALSE(packet_ms);
|
|
||||||
EXPECT_FALSE(packet_keyframe_ms);
|
|
||||||
|
|
||||||
int64_t keyframe_ms = clock_.TimeInMilliseconds();
|
|
||||||
Insert(100, kKeyFrame, kFirst, kLast, {}, /*timestamp=*/1000);
|
|
||||||
packet_ms = packet_buffer_.LastReceivedPacketMs();
|
|
||||||
packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
|
|
||||||
EXPECT_TRUE(packet_ms);
|
|
||||||
EXPECT_TRUE(packet_keyframe_ms);
|
|
||||||
EXPECT_EQ(keyframe_ms, *packet_ms);
|
|
||||||
EXPECT_EQ(keyframe_ms, *packet_keyframe_ms);
|
|
||||||
|
|
||||||
clock_.AdvanceTimeMilliseconds(100);
|
|
||||||
int64_t delta_ms = clock_.TimeInMilliseconds();
|
|
||||||
Insert(101, kDeltaFrame, kFirst, kLast, {}, /*timestamp=*/2000);
|
|
||||||
packet_ms = packet_buffer_.LastReceivedPacketMs();
|
|
||||||
packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
|
|
||||||
EXPECT_TRUE(packet_ms);
|
|
||||||
EXPECT_TRUE(packet_keyframe_ms);
|
|
||||||
EXPECT_EQ(delta_ms, *packet_ms);
|
|
||||||
EXPECT_EQ(keyframe_ms, *packet_keyframe_ms);
|
|
||||||
|
|
||||||
packet_buffer_.Clear();
|
|
||||||
packet_ms = packet_buffer_.LastReceivedPacketMs();
|
|
||||||
packet_keyframe_ms = packet_buffer_.LastReceivedKeyframePacketMs();
|
|
||||||
EXPECT_FALSE(packet_ms);
|
|
||||||
EXPECT_FALSE(packet_keyframe_ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(PacketBufferTest,
|
|
||||||
LastReceivedKeyFrameReturnsReceiveTimeOfALastReceivedPacketOfAKeyFrame) {
|
|
||||||
clock_.AdvanceTimeMilliseconds(100);
|
|
||||||
Insert(/*seq_num=*/100, kKeyFrame, kFirst, kNotLast, {}, /*timestamp=*/1000);
|
|
||||||
EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
|
|
||||||
clock_.TimeInMilliseconds());
|
|
||||||
|
|
||||||
clock_.AdvanceTimeMilliseconds(100);
|
|
||||||
Insert(/*seq_num=*/102, kDeltaFrame, kNotFirst, kLast, {},
|
|
||||||
/*timestamp=*/1000);
|
|
||||||
EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
|
|
||||||
clock_.TimeInMilliseconds());
|
|
||||||
|
|
||||||
clock_.AdvanceTimeMilliseconds(100);
|
|
||||||
Insert(/*seq_num=*/101, kDeltaFrame, kNotFirst, kNotLast, {},
|
|
||||||
/*timestamp=*/1000);
|
|
||||||
EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
|
|
||||||
clock_.TimeInMilliseconds());
|
|
||||||
|
|
||||||
clock_.AdvanceTimeMilliseconds(100);
|
|
||||||
Insert(/*seq_num=*/103, kDeltaFrame, kFirst, kNotLast, {},
|
|
||||||
/*timestamp=*/2000);
|
|
||||||
EXPECT_EQ(packet_buffer_.LastReceivedKeyframePacketMs(),
|
|
||||||
clock_.TimeInMilliseconds() - 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(PacketBufferTest, IncomingCodecChange) {
|
TEST_F(PacketBufferTest, IncomingCodecChange) {
|
||||||
auto packet = std::make_unique<PacketBuffer::Packet>();
|
auto packet = std::make_unique<PacketBuffer::Packet>();
|
||||||
packet->video_header.is_first_packet_in_frame = true;
|
packet->video_header.is_first_packet_in_frame = true;
|
||||||
|
|||||||
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "modules/video_coding/frame_object.h"
|
#include "modules/video_coding/frame_object.h"
|
||||||
#include "modules/video_coding/packet_buffer.h"
|
#include "modules/video_coding/packet_buffer.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
|
||||||
#include "test/fuzzers/fuzz_data_helper.h"
|
#include "test/fuzzers/fuzz_data_helper.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -24,8 +23,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
|
|||||||
if (size > 200000) {
|
if (size > 200000) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SimulatedClock clock(0);
|
video_coding::PacketBuffer packet_buffer(8, 1024);
|
||||||
video_coding::PacketBuffer packet_buffer(&clock, 8, 1024);
|
|
||||||
test::FuzzDataHelper helper(rtc::ArrayView<const uint8_t>(data, size));
|
test::FuzzDataHelper helper(rtc::ArrayView<const uint8_t>(data, size));
|
||||||
|
|
||||||
while (helper.BytesLeft()) {
|
while (helper.BytesLeft()) {
|
||||||
|
|||||||
@ -164,6 +164,7 @@ rtc_source_set("video_legacy") {
|
|||||||
"../api:sequence_checker",
|
"../api:sequence_checker",
|
||||||
"../api/crypto:frame_decryptor_interface",
|
"../api/crypto:frame_decryptor_interface",
|
||||||
"../api/task_queue",
|
"../api/task_queue",
|
||||||
|
"../api/units:timestamp",
|
||||||
"../api/video:encoded_image",
|
"../api/video:encoded_image",
|
||||||
"../api/video:recordable_encoded_frame",
|
"../api/video:recordable_encoded_frame",
|
||||||
"../api/video:video_frame",
|
"../api/video:video_frame",
|
||||||
|
|||||||
@ -271,7 +271,7 @@ RtpVideoStreamReceiver::RtpVideoStreamReceiver(
|
|||||||
// TODO(bugs.webrtc.org/10336): Let |rtcp_feedback_buffer_| communicate
|
// TODO(bugs.webrtc.org/10336): Let |rtcp_feedback_buffer_| communicate
|
||||||
// directly with |rtp_rtcp_|.
|
// directly with |rtp_rtcp_|.
|
||||||
rtcp_feedback_buffer_(this, nack_sender, this),
|
rtcp_feedback_buffer_(this, nack_sender, this),
|
||||||
packet_buffer_(clock_, kPacketBufferStartSize, PacketBufferMaxSize()),
|
packet_buffer_(kPacketBufferStartSize, PacketBufferMaxSize()),
|
||||||
has_received_frame_(false),
|
has_received_frame_(false),
|
||||||
frames_decryptable_(false),
|
frames_decryptable_(false),
|
||||||
absolute_capture_time_receiver_(clock) {
|
absolute_capture_time_receiver_(clock) {
|
||||||
@ -384,11 +384,11 @@ absl::optional<Syncable::Info> RtpVideoStreamReceiver::GetSyncInfo() const {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
MutexLock lock(&sync_info_lock_);
|
MutexLock lock(&sync_info_lock_);
|
||||||
if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_ms_) {
|
if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_) {
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
|
info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
|
||||||
info.latest_receive_time_ms = *last_received_rtp_system_time_ms_;
|
info.latest_receive_time_ms = last_received_rtp_system_time_->ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leaves info.current_delay_ms uninitialized.
|
// Leaves info.current_delay_ms uninitialized.
|
||||||
@ -543,6 +543,12 @@ void RtpVideoStreamReceiver::OnReceivedPayloadData(
|
|||||||
|
|
||||||
ParseGenericDependenciesResult generic_descriptor_state =
|
ParseGenericDependenciesResult generic_descriptor_state =
|
||||||
ParseGenericDependenciesExtension(rtp_packet, &video_header);
|
ParseGenericDependenciesExtension(rtp_packet, &video_header);
|
||||||
|
|
||||||
|
if (!rtp_packet.recovered()) {
|
||||||
|
UpdatePacketReceiveTimestamps(
|
||||||
|
rtp_packet, video_header.frame_type == VideoFrameType::kVideoFrameKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (generic_descriptor_state == kDropPacket)
|
if (generic_descriptor_state == kDropPacket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -671,35 +677,6 @@ void RtpVideoStreamReceiver::OnRtpPacket(const RtpPacketReceived& packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!packet.recovered()) {
|
|
||||||
// TODO(nisse): Exclude out-of-order packets?
|
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
||||||
{
|
|
||||||
MutexLock lock(&sync_info_lock_);
|
|
||||||
last_received_rtp_timestamp_ = packet.Timestamp();
|
|
||||||
last_received_rtp_system_time_ms_ = now_ms;
|
|
||||||
}
|
|
||||||
// Periodically log the RTP header of incoming packets.
|
|
||||||
if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) {
|
|
||||||
rtc::StringBuilder ss;
|
|
||||||
ss << "Packet received on SSRC: " << packet.Ssrc()
|
|
||||||
<< " with payload type: " << static_cast<int>(packet.PayloadType())
|
|
||||||
<< ", timestamp: " << packet.Timestamp()
|
|
||||||
<< ", sequence number: " << packet.SequenceNumber()
|
|
||||||
<< ", arrival time: " << packet.arrival_time_ms();
|
|
||||||
int32_t time_offset;
|
|
||||||
if (packet.GetExtension<TransmissionOffset>(&time_offset)) {
|
|
||||||
ss << ", toffset: " << time_offset;
|
|
||||||
}
|
|
||||||
uint32_t send_time;
|
|
||||||
if (packet.GetExtension<AbsoluteSendTime>(&send_time)) {
|
|
||||||
ss << ", abs send time: " << send_time;
|
|
||||||
}
|
|
||||||
RTC_LOG(LS_INFO) << ss.str();
|
|
||||||
last_packet_log_ms_ = now_ms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceivePacket(packet);
|
ReceivePacket(packet);
|
||||||
|
|
||||||
// Update receive statistics after ReceivePacket.
|
// Update receive statistics after ReceivePacket.
|
||||||
@ -942,12 +919,21 @@ void RtpVideoStreamReceiver::UpdateRtt(int64_t max_rtt_ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<int64_t> RtpVideoStreamReceiver::LastReceivedPacketMs() const {
|
absl::optional<int64_t> RtpVideoStreamReceiver::LastReceivedPacketMs() const {
|
||||||
return packet_buffer_.LastReceivedPacketMs();
|
MutexLock lock(&sync_info_lock_);
|
||||||
|
if (last_received_rtp_system_time_) {
|
||||||
|
return absl::optional<int64_t>(last_received_rtp_system_time_->ms());
|
||||||
|
}
|
||||||
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<int64_t> RtpVideoStreamReceiver::LastReceivedKeyframePacketMs()
|
absl::optional<int64_t> RtpVideoStreamReceiver::LastReceivedKeyframePacketMs()
|
||||||
const {
|
const {
|
||||||
return packet_buffer_.LastReceivedKeyframePacketMs();
|
MutexLock lock(&sync_info_lock_);
|
||||||
|
if (last_received_keyframe_rtp_system_time_) {
|
||||||
|
return absl::optional<int64_t>(
|
||||||
|
last_received_keyframe_rtp_system_time_->ms());
|
||||||
|
}
|
||||||
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpVideoStreamReceiver::AddSecondarySink(RtpPacketSinkInterface* sink) {
|
void RtpVideoStreamReceiver::AddSecondarySink(RtpPacketSinkInterface* sink) {
|
||||||
@ -1183,4 +1169,38 @@ void RtpVideoStreamReceiver::InsertSpsPpsIntoTracker(uint8_t payload_type) {
|
|||||||
sprop_decoder.pps_nalu());
|
sprop_decoder.pps_nalu());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtpVideoStreamReceiver::UpdatePacketReceiveTimestamps(
|
||||||
|
const RtpPacketReceived& packet,
|
||||||
|
bool is_keyframe) {
|
||||||
|
Timestamp now = clock_->CurrentTime();
|
||||||
|
{
|
||||||
|
MutexLock lock(&sync_info_lock_);
|
||||||
|
if (is_keyframe) {
|
||||||
|
last_received_keyframe_rtp_system_time_ = now;
|
||||||
|
}
|
||||||
|
last_received_rtp_system_time_ = now;
|
||||||
|
last_received_rtp_timestamp_ = packet.Timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Periodically log the RTP header of incoming packets.
|
||||||
|
if (now.ms() - last_packet_log_ms_ > kPacketLogIntervalMs) {
|
||||||
|
rtc::StringBuilder ss;
|
||||||
|
ss << "Packet received on SSRC: " << packet.Ssrc()
|
||||||
|
<< " with payload type: " << static_cast<int>(packet.PayloadType())
|
||||||
|
<< ", timestamp: " << packet.Timestamp()
|
||||||
|
<< ", sequence number: " << packet.SequenceNumber()
|
||||||
|
<< ", arrival time: " << packet.arrival_time_ms();
|
||||||
|
int32_t time_offset;
|
||||||
|
if (packet.GetExtension<TransmissionOffset>(&time_offset)) {
|
||||||
|
ss << ", toffset: " << time_offset;
|
||||||
|
}
|
||||||
|
uint32_t send_time;
|
||||||
|
if (packet.GetExtension<AbsoluteSendTime>(&send_time)) {
|
||||||
|
ss << ", abs send time: " << send_time;
|
||||||
|
}
|
||||||
|
RTC_LOG(LS_INFO) << ss.str();
|
||||||
|
last_packet_log_ms_ = now.ms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include "api/array_view.h"
|
#include "api/array_view.h"
|
||||||
#include "api/crypto/frame_decryptor_interface.h"
|
#include "api/crypto/frame_decryptor_interface.h"
|
||||||
#include "api/sequence_checker.h"
|
#include "api/sequence_checker.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
#include "api/video/color_space.h"
|
#include "api/video/color_space.h"
|
||||||
#include "api/video_codecs/video_codec.h"
|
#include "api/video_codecs/video_codec.h"
|
||||||
#include "call/rtp_packet_sink_interface.h"
|
#include "call/rtp_packet_sink_interface.h"
|
||||||
@ -303,6 +304,9 @@ class RtpVideoStreamReceiver : public LossNotificationSender,
|
|||||||
const RtpPacketReceived& rtp_packet,
|
const RtpPacketReceived& rtp_packet,
|
||||||
RTPVideoHeader* video_header) RTC_RUN_ON(worker_task_checker_);
|
RTPVideoHeader* video_header) RTC_RUN_ON(worker_task_checker_);
|
||||||
void OnAssembledFrame(std::unique_ptr<RtpFrameObject> frame);
|
void OnAssembledFrame(std::unique_ptr<RtpFrameObject> frame);
|
||||||
|
void UpdatePacketReceiveTimestamps(const RtpPacketReceived& packet,
|
||||||
|
bool is_keyframe)
|
||||||
|
RTC_RUN_ON(worker_task_checker_);
|
||||||
|
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
// Ownership of this object lies with VideoReceiveStream, which owns |this|.
|
// Ownership of this object lies with VideoReceiveStream, which owns |this|.
|
||||||
@ -378,7 +382,9 @@ class RtpVideoStreamReceiver : public LossNotificationSender,
|
|||||||
mutable Mutex sync_info_lock_;
|
mutable Mutex sync_info_lock_;
|
||||||
absl::optional<uint32_t> last_received_rtp_timestamp_
|
absl::optional<uint32_t> last_received_rtp_timestamp_
|
||||||
RTC_GUARDED_BY(sync_info_lock_);
|
RTC_GUARDED_BY(sync_info_lock_);
|
||||||
absl::optional<int64_t> last_received_rtp_system_time_ms_
|
absl::optional<Timestamp> last_received_rtp_system_time_
|
||||||
|
RTC_GUARDED_BY(sync_info_lock_);
|
||||||
|
absl::optional<Timestamp> last_received_keyframe_rtp_system_time_
|
||||||
RTC_GUARDED_BY(sync_info_lock_);
|
RTC_GUARDED_BY(sync_info_lock_);
|
||||||
|
|
||||||
// Used to validate the buffered frame decryptor is always run on the correct
|
// Used to validate the buffered frame decryptor is always run on the correct
|
||||||
|
|||||||
@ -250,7 +250,7 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
|
|||||||
clock_,
|
clock_,
|
||||||
&rtcp_feedback_buffer_,
|
&rtcp_feedback_buffer_,
|
||||||
&rtcp_feedback_buffer_)),
|
&rtcp_feedback_buffer_)),
|
||||||
packet_buffer_(clock_, kPacketBufferStartSize, PacketBufferMaxSize()),
|
packet_buffer_(kPacketBufferStartSize, PacketBufferMaxSize()),
|
||||||
has_received_frame_(false),
|
has_received_frame_(false),
|
||||||
frames_decryptable_(false),
|
frames_decryptable_(false),
|
||||||
absolute_capture_time_receiver_(clock) {
|
absolute_capture_time_receiver_(clock) {
|
||||||
@ -353,11 +353,11 @@ absl::optional<Syncable::Info> RtpVideoStreamReceiver2::GetSyncInfo() const {
|
|||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_ms_) {
|
if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_) {
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
|
info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
|
||||||
info.latest_receive_time_ms = *last_received_rtp_system_time_ms_;
|
info.latest_receive_time_ms = last_received_rtp_system_time_->ms();
|
||||||
|
|
||||||
// Leaves info.current_delay_ms uninitialized.
|
// Leaves info.current_delay_ms uninitialized.
|
||||||
return info;
|
return info;
|
||||||
@ -511,6 +511,12 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData(
|
|||||||
|
|
||||||
ParseGenericDependenciesResult generic_descriptor_state =
|
ParseGenericDependenciesResult generic_descriptor_state =
|
||||||
ParseGenericDependenciesExtension(rtp_packet, &video_header);
|
ParseGenericDependenciesExtension(rtp_packet, &video_header);
|
||||||
|
|
||||||
|
if (!rtp_packet.recovered()) {
|
||||||
|
UpdatePacketReceiveTimestamps(
|
||||||
|
rtp_packet, video_header.frame_type == VideoFrameType::kVideoFrameKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (generic_descriptor_state == kDropPacket)
|
if (generic_descriptor_state == kDropPacket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -639,34 +645,6 @@ void RtpVideoStreamReceiver2::OnRtpPacket(const RtpPacketReceived& packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!packet.recovered()) {
|
|
||||||
// TODO(nisse): Exclude out-of-order packets?
|
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
||||||
|
|
||||||
last_received_rtp_timestamp_ = packet.Timestamp();
|
|
||||||
last_received_rtp_system_time_ms_ = now_ms;
|
|
||||||
|
|
||||||
// Periodically log the RTP header of incoming packets.
|
|
||||||
if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) {
|
|
||||||
rtc::StringBuilder ss;
|
|
||||||
ss << "Packet received on SSRC: " << packet.Ssrc()
|
|
||||||
<< " with payload type: " << static_cast<int>(packet.PayloadType())
|
|
||||||
<< ", timestamp: " << packet.Timestamp()
|
|
||||||
<< ", sequence number: " << packet.SequenceNumber()
|
|
||||||
<< ", arrival time: " << packet.arrival_time_ms();
|
|
||||||
int32_t time_offset;
|
|
||||||
if (packet.GetExtension<TransmissionOffset>(&time_offset)) {
|
|
||||||
ss << ", toffset: " << time_offset;
|
|
||||||
}
|
|
||||||
uint32_t send_time;
|
|
||||||
if (packet.GetExtension<AbsoluteSendTime>(&send_time)) {
|
|
||||||
ss << ", abs send time: " << send_time;
|
|
||||||
}
|
|
||||||
RTC_LOG(LS_INFO) << ss.str();
|
|
||||||
last_packet_log_ms_ = now_ms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceivePacket(packet);
|
ReceivePacket(packet);
|
||||||
|
|
||||||
// Update receive statistics after ReceivePacket.
|
// Update receive statistics after ReceivePacket.
|
||||||
@ -915,12 +893,20 @@ void RtpVideoStreamReceiver2::UpdateRtt(int64_t max_rtt_ms) {
|
|||||||
|
|
||||||
absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const {
|
absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const {
|
||||||
RTC_DCHECK_RUN_ON(&worker_task_checker_);
|
RTC_DCHECK_RUN_ON(&worker_task_checker_);
|
||||||
return last_received_rtp_system_time_ms_;
|
if (last_received_rtp_system_time_) {
|
||||||
|
return absl::optional<int64_t>(last_received_rtp_system_time_->ms());
|
||||||
|
}
|
||||||
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
|
absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedKeyframePacketMs()
|
||||||
const {
|
const {
|
||||||
return packet_buffer_.LastReceivedKeyframePacketMs();
|
RTC_DCHECK_RUN_ON(&worker_task_checker_);
|
||||||
|
if (last_received_keyframe_rtp_system_time_) {
|
||||||
|
return absl::optional<int64_t>(
|
||||||
|
last_received_keyframe_rtp_system_time_->ms());
|
||||||
|
}
|
||||||
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpVideoStreamReceiver2::ManageFrame(
|
void RtpVideoStreamReceiver2::ManageFrame(
|
||||||
@ -1137,4 +1123,35 @@ void RtpVideoStreamReceiver2::InsertSpsPpsIntoTracker(uint8_t payload_type) {
|
|||||||
sprop_decoder.pps_nalu());
|
sprop_decoder.pps_nalu());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtpVideoStreamReceiver2::UpdatePacketReceiveTimestamps(
|
||||||
|
const RtpPacketReceived& packet,
|
||||||
|
bool is_keyframe) {
|
||||||
|
Timestamp now = clock_->CurrentTime();
|
||||||
|
if (is_keyframe) {
|
||||||
|
last_received_keyframe_rtp_system_time_ = now;
|
||||||
|
}
|
||||||
|
last_received_rtp_system_time_ = now;
|
||||||
|
last_received_rtp_timestamp_ = packet.Timestamp();
|
||||||
|
|
||||||
|
// Periodically log the RTP header of incoming packets.
|
||||||
|
if (now.ms() - last_packet_log_ms_ > kPacketLogIntervalMs) {
|
||||||
|
rtc::StringBuilder ss;
|
||||||
|
ss << "Packet received on SSRC: " << packet.Ssrc()
|
||||||
|
<< " with payload type: " << static_cast<int>(packet.PayloadType())
|
||||||
|
<< ", timestamp: " << packet.Timestamp()
|
||||||
|
<< ", sequence number: " << packet.SequenceNumber()
|
||||||
|
<< ", arrival time: " << packet.arrival_time_ms();
|
||||||
|
int32_t time_offset;
|
||||||
|
if (packet.GetExtension<TransmissionOffset>(&time_offset)) {
|
||||||
|
ss << ", toffset: " << time_offset;
|
||||||
|
}
|
||||||
|
uint32_t send_time;
|
||||||
|
if (packet.GetExtension<AbsoluteSendTime>(&send_time)) {
|
||||||
|
ss << ", abs send time: " << send_time;
|
||||||
|
}
|
||||||
|
RTC_LOG(LS_INFO) << ss.str();
|
||||||
|
last_packet_log_ms_ = now.ms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/crypto/frame_decryptor_interface.h"
|
#include "api/crypto/frame_decryptor_interface.h"
|
||||||
#include "api/sequence_checker.h"
|
#include "api/sequence_checker.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
#include "api/video/color_space.h"
|
#include "api/video/color_space.h"
|
||||||
#include "api/video_codecs/video_codec.h"
|
#include "api/video_codecs/video_codec.h"
|
||||||
#include "call/rtp_packet_sink_interface.h"
|
#include "call/rtp_packet_sink_interface.h"
|
||||||
@ -260,6 +261,9 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender,
|
|||||||
const RtpPacketReceived& rtp_packet,
|
const RtpPacketReceived& rtp_packet,
|
||||||
RTPVideoHeader* video_header) RTC_RUN_ON(worker_task_checker_);
|
RTPVideoHeader* video_header) RTC_RUN_ON(worker_task_checker_);
|
||||||
void OnAssembledFrame(std::unique_ptr<RtpFrameObject> frame);
|
void OnAssembledFrame(std::unique_ptr<RtpFrameObject> frame);
|
||||||
|
void UpdatePacketReceiveTimestamps(const RtpPacketReceived& packet,
|
||||||
|
bool is_keyframe)
|
||||||
|
RTC_RUN_ON(worker_task_checker_);
|
||||||
|
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
// Ownership of this object lies with VideoReceiveStream, which owns |this|.
|
// Ownership of this object lies with VideoReceiveStream, which owns |this|.
|
||||||
@ -331,7 +335,9 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender,
|
|||||||
|
|
||||||
absl::optional<uint32_t> last_received_rtp_timestamp_
|
absl::optional<uint32_t> last_received_rtp_timestamp_
|
||||||
RTC_GUARDED_BY(worker_task_checker_);
|
RTC_GUARDED_BY(worker_task_checker_);
|
||||||
absl::optional<int64_t> last_received_rtp_system_time_ms_
|
absl::optional<Timestamp> last_received_rtp_system_time_
|
||||||
|
RTC_GUARDED_BY(worker_task_checker_);
|
||||||
|
absl::optional<Timestamp> last_received_keyframe_rtp_system_time_
|
||||||
RTC_GUARDED_BY(worker_task_checker_);
|
RTC_GUARDED_BY(worker_task_checker_);
|
||||||
|
|
||||||
// Handles incoming encrypted frames and forwards them to the
|
// Handles incoming encrypted frames and forwards them to the
|
||||||
|
|||||||
Reference in New Issue
Block a user