Report timing frames info in GetStats.
Some frames are already marked as 'timing frames' via video-timing RTP header extension. Timestamps along full WebRTC pipeline are gathered for these frames. This CL implements reporting of these timestamps for a single timing frame since the last GetStats(). The frame with the longest end-to-end delay between two consecutive GetStats calls is reported. The purpose of this timing information is not to provide a realtime statistics but to provide debugging information as it will help identify problematic places in video pipeline for outliers (frames which took longest to process). BUG=webrtc:7594 Review-Url: https://codereview.webrtc.org/2946413002 Cr-Commit-Position: refs/heads/master@{#18909}
This commit is contained in:
@ -266,40 +266,41 @@ constexpr uint8_t VideoTimingExtension::kValueSizeBytes;
|
||||
constexpr const char* VideoTimingExtension::kUri;
|
||||
|
||||
bool VideoTimingExtension::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
VideoTiming* timing) {
|
||||
VideoSendTiming* timing) {
|
||||
RTC_DCHECK(timing);
|
||||
if (data.size() != kValueSizeBytes)
|
||||
return false;
|
||||
timing->encode_start_delta_ms =
|
||||
ByteReader<uint16_t>::ReadBigEndian(data.data());
|
||||
timing->encode_finish_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
|
||||
data.data() + 2 * VideoTiming::kEncodeFinishDeltaIdx);
|
||||
data.data() + 2 * VideoSendTiming::kEncodeFinishDeltaIdx);
|
||||
timing->packetization_finish_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
|
||||
data.data() + 2 * VideoTiming::kPacketizationFinishDeltaIdx);
|
||||
data.data() + 2 * VideoSendTiming::kPacketizationFinishDeltaIdx);
|
||||
timing->pacer_exit_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
|
||||
data.data() + 2 * VideoTiming::kPacerExitDeltaIdx);
|
||||
data.data() + 2 * VideoSendTiming::kPacerExitDeltaIdx);
|
||||
timing->network_timstamp_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
|
||||
data.data() + 2 * VideoTiming::kNetworkTimestampDeltaIdx);
|
||||
data.data() + 2 * VideoSendTiming::kNetworkTimestampDeltaIdx);
|
||||
timing->network2_timstamp_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
|
||||
data.data() + 2 * VideoTiming::kNetwork2TimestampDeltaIdx);
|
||||
data.data() + 2 * VideoSendTiming::kNetwork2TimestampDeltaIdx);
|
||||
timing->is_timing_frame = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VideoTimingExtension::Write(uint8_t* data, const VideoTiming& timing) {
|
||||
bool VideoTimingExtension::Write(uint8_t* data, const VideoSendTiming& timing) {
|
||||
ByteWriter<uint16_t>::WriteBigEndian(data, timing.encode_start_delta_ms);
|
||||
ByteWriter<uint16_t>::WriteBigEndian(
|
||||
data + 2 * VideoTiming::kEncodeFinishDeltaIdx,
|
||||
data + 2 * VideoSendTiming::kEncodeFinishDeltaIdx,
|
||||
timing.encode_finish_delta_ms);
|
||||
ByteWriter<uint16_t>::WriteBigEndian(
|
||||
data + 2 * VideoTiming::kPacketizationFinishDeltaIdx,
|
||||
data + 2 * VideoSendTiming::kPacketizationFinishDeltaIdx,
|
||||
timing.packetization_finish_delta_ms);
|
||||
ByteWriter<uint16_t>::WriteBigEndian(
|
||||
data + 2 * VideoTiming::kPacerExitDeltaIdx, timing.pacer_exit_delta_ms);
|
||||
data + 2 * VideoSendTiming::kPacerExitDeltaIdx,
|
||||
timing.pacer_exit_delta_ms);
|
||||
ByteWriter<uint16_t>::WriteBigEndian(
|
||||
data + 2 * VideoTiming::kNetworkTimestampDeltaIdx, 0); // reserved
|
||||
data + 2 * VideoSendTiming::kNetworkTimestampDeltaIdx, 0); // reserved
|
||||
ByteWriter<uint16_t>::WriteBigEndian(
|
||||
data + 2 * VideoTiming::kNetwork2TimestampDeltaIdx, 0); // reserved
|
||||
data + 2 * VideoSendTiming::kNetwork2TimestampDeltaIdx, 0); // reserved
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -134,9 +134,10 @@ class VideoTimingExtension {
|
||||
static constexpr const char* kUri =
|
||||
"http://www.webrtc.org/experiments/rtp-hdrext/video-timing";
|
||||
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data, VideoTiming* timing);
|
||||
static size_t ValueSize(const VideoTiming&) { return kValueSizeBytes; }
|
||||
static bool Write(uint8_t* data, const VideoTiming& timing);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data,
|
||||
VideoSendTiming* timing);
|
||||
static size_t ValueSize(const VideoSendTiming&) { return kValueSizeBytes; }
|
||||
static bool Write(uint8_t* data, const VideoSendTiming& timing);
|
||||
|
||||
static size_t ValueSize(uint16_t time_delta_ms, uint8_t idx) {
|
||||
return kValueSizeBytes;
|
||||
|
||||
@ -32,26 +32,26 @@ class RtpPacketToSend : public rtp::Packet {
|
||||
|
||||
void set_packetization_finish_time_ms(int64_t time) {
|
||||
SetExtension<VideoTimingExtension>(
|
||||
VideoTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoTiming::kPacketizationFinishDeltaIdx);
|
||||
VideoSendTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoSendTiming::kPacketizationFinishDeltaIdx);
|
||||
}
|
||||
|
||||
void set_pacer_exit_time_ms(int64_t time) {
|
||||
SetExtension<VideoTimingExtension>(
|
||||
VideoTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoTiming::kPacerExitDeltaIdx);
|
||||
VideoSendTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoSendTiming::kPacerExitDeltaIdx);
|
||||
}
|
||||
|
||||
void set_network_time_ms(int64_t time) {
|
||||
SetExtension<VideoTimingExtension>(
|
||||
VideoTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoTiming::kNetworkTimestampDeltaIdx);
|
||||
VideoSendTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoSendTiming::kNetworkTimestampDeltaIdx);
|
||||
}
|
||||
|
||||
void set_network2_time_ms(int64_t time) {
|
||||
SetExtension<VideoTimingExtension>(
|
||||
VideoTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoTiming::kNetwork2TimestampDeltaIdx);
|
||||
VideoSendTiming::GetDeltaCappedMs(capture_time_ms_, time),
|
||||
VideoSendTiming::kNetwork2TimestampDeltaIdx);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -473,7 +473,7 @@ TEST_P(RtpSenderTestWithoutPacer, WritesTimestampToTimingExtension) {
|
||||
packet->SetMarker(true);
|
||||
packet->SetTimestamp(kTimestamp);
|
||||
packet->set_capture_time_ms(capture_time_ms);
|
||||
const VideoTiming kVideoTiming = {0u, 0u, 0u, 0u, 0u, 0u, true};
|
||||
const VideoSendTiming kVideoTiming = {0u, 0u, 0u, 0u, 0u, 0u, true};
|
||||
packet->SetExtension<VideoTimingExtension>(kVideoTiming);
|
||||
EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
||||
size_t packet_size = packet->size();
|
||||
@ -1578,7 +1578,7 @@ TEST_P(RtpSenderVideoTest, TimingFrameHasPacketizationTimstampSet) {
|
||||
rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload,
|
||||
kTimestamp, kCaptureTimestamp, kFrame,
|
||||
sizeof(kFrame), nullptr, &hdr);
|
||||
VideoTiming timing;
|
||||
VideoSendTiming timing;
|
||||
EXPECT_TRUE(transport_.last_sent_packet().GetExtension<VideoTimingExtension>(
|
||||
&timing));
|
||||
EXPECT_EQ(kPacketizationTimeMs, timing.packetization_finish_delta_ms);
|
||||
|
||||
Reference in New Issue
Block a user