Propagate absolute capture time through video receiving side.

Prototype link:
https://webrtc-review.googlesource.com/c/src/+/158520


Bug: webrtc:10739
Change-Id: I8d30b729ac5bca484608af7f0378998987df7d53
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160341
Commit-Queue: Ruslan Burakov <kuddai@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29939}
This commit is contained in:
Ruslan Burakov 2019-11-27 16:49:10 +01:00 committed by Commit Bot
parent 7968530418
commit d08bb1e12f
3 changed files with 110 additions and 1 deletions

View File

@ -214,7 +214,8 @@ RtpVideoStreamReceiver::RtpVideoStreamReceiver(
rtcp_feedback_buffer_(this, nack_sender, this),
packet_buffer_(clock_, kPacketBufferStartSize, PacketBufferMaxSize()),
has_received_frame_(false),
frames_decryptable_(false) {
frames_decryptable_(false),
absolute_capture_time_receiver_(clock) {
constexpr bool remb_candidate = true;
if (packet_router_)
packet_router_->AddReceiveRtpModule(rtp_rtcp_.get(), remb_candidate);
@ -331,6 +332,18 @@ void RtpVideoStreamReceiver::OnReceivedPayloadData(
rtp_packet, video, ntp_estimator_.Estimate(rtp_packet.Timestamp()),
clock_->TimeInMilliseconds());
// Try to extrapolate absolute capture time if it is missing.
// TODO(bugs.webrtc.org/10739): Add support for estimated capture clock
// offset.
packet.packet_info.set_absolute_capture_time(
absolute_capture_time_receiver_.OnReceivePacket(
AbsoluteCaptureTimeReceiver::GetSource(packet.packet_info.ssrc(),
packet.packet_info.csrcs()),
packet.packet_info.rtp_timestamp(),
// Assume frequency is the same one for all video frames.
kVideoPayloadTypeFrequency,
packet.packet_info.absolute_capture_time()));
RTPVideoHeader& video_header = packet.video_header;
video_header.rotation = kVideoRotation_0;
video_header.content_type = VideoContentType::UNSPECIFIED;

View File

@ -31,6 +31,7 @@
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/absolute_capture_time_receiver.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/rtp_rtcp/source/rtp_video_header.h"
#include "modules/video_coding/h264_sps_pps_tracker.h"
@ -319,6 +320,9 @@ class RtpVideoStreamReceiver : public LossNotificationSender,
std::atomic<bool> frames_decryptable_;
absl::optional<ColorSpace> last_color_space_;
AbsoluteCaptureTimeReceiver absolute_capture_time_receiver_
RTC_GUARDED_BY(worker_task_checker_);
int64_t last_completed_picture_id_ = 0;
};

View File

@ -36,6 +36,7 @@
#include "test/gtest.h"
using ::testing::_;
using ::testing::ElementsAre;
using ::testing::Invoke;
using ::testing::SizeIs;
using ::testing::Values;
@ -46,6 +47,18 @@ namespace {
const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
std::vector<uint64_t> GetAbsoluteCaptureTimestamps(
const video_coding::EncodedFrame* frame) {
std::vector<uint64_t> result;
for (const auto& packet_info : frame->PacketInfos()) {
if (packet_info.absolute_capture_time()) {
result.push_back(
packet_info.absolute_capture_time()->absolute_capture_timestamp);
}
}
return result;
}
class MockTransport : public Transport {
public:
MOCK_METHOD3(SendRtp,
@ -342,6 +355,85 @@ TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
video_header);
}
TEST_F(RtpVideoStreamReceiverTest, PacketInfoIsPropagatedIntoVideoFrames) {
constexpr uint64_t kAbsoluteCaptureTimestamp = 12;
constexpr int kId0 = 1;
RtpHeaderExtensionMap extension_map;
extension_map.Register<AbsoluteCaptureTimeExtension>(kId0);
RtpPacketReceived rtp_packet(&extension_map);
RTPVideoHeader video_header;
const std::vector<uint8_t> data({1, 2, 3, 4});
rtp_packet.SetSequenceNumber(1);
rtp_packet.SetTimestamp(1);
rtp_packet.SetSsrc(kSsrc);
rtp_packet.SetExtension<AbsoluteCaptureTimeExtension>(
AbsoluteCaptureTime{kAbsoluteCaptureTimestamp,
/*estimated_capture_clock_offset=*/absl::nullopt});
video_header.is_first_packet_in_frame = true;
video_header.is_last_packet_in_frame = true;
video_header.codec = kVideoCodecGeneric;
video_header.frame_type = VideoFrameType::kVideoFrameKey;
mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
data.size());
EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
.WillOnce(Invoke(
[kAbsoluteCaptureTimestamp](video_coding::EncodedFrame* frame) {
EXPECT_THAT(GetAbsoluteCaptureTimestamps(frame),
ElementsAre(kAbsoluteCaptureTimestamp));
}));
rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
video_header);
}
TEST_F(RtpVideoStreamReceiverTest,
MissingAbsoluteCaptureTimeIsFilledWithExtrapolatedValue) {
constexpr uint64_t kAbsoluteCaptureTimestamp = 12;
constexpr int kId0 = 1;
RtpHeaderExtensionMap extension_map;
extension_map.Register<AbsoluteCaptureTimeExtension>(kId0);
RtpPacketReceived rtp_packet(&extension_map);
RTPVideoHeader video_header;
const std::vector<uint8_t> data({1, 2, 3, 4});
uint16_t sequence_number = 1;
uint32_t rtp_timestamp = 1;
rtp_packet.SetSequenceNumber(sequence_number);
rtp_packet.SetTimestamp(rtp_timestamp);
rtp_packet.SetSsrc(kSsrc);
rtp_packet.SetExtension<AbsoluteCaptureTimeExtension>(
AbsoluteCaptureTime{kAbsoluteCaptureTimestamp,
/*estimated_capture_clock_offset=*/absl::nullopt});
video_header.is_first_packet_in_frame = true;
video_header.is_last_packet_in_frame = true;
video_header.codec = kVideoCodecGeneric;
video_header.frame_type = VideoFrameType::kVideoFrameKey;
mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
data.size());
EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
video_header);
// Rtp packet without absolute capture time.
rtp_packet = RtpPacketReceived(&extension_map);
rtp_packet.SetSequenceNumber(++sequence_number);
rtp_packet.SetTimestamp(++rtp_timestamp);
rtp_packet.SetSsrc(kSsrc);
// There is no absolute capture time in the second packet.
// Expect rtp video stream receiver to extrapolate it for the resulting video
// frame using absolute capture time from the previous packet.
EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
.WillOnce(Invoke([](video_coding::EncodedFrame* frame) {
EXPECT_THAT(GetAbsoluteCaptureTimestamps(frame), SizeIs(1));
}));
rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
video_header);
}
TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
const uint8_t kRedPayloadType = 125;
VideoCodec codec;