diff --git a/api/BUILD.gn b/api/BUILD.gn index 5c681bc15f..ffaa4aac90 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -92,6 +92,7 @@ rtc_source_set("rtp_packet_info") { ":rtp_headers", ":scoped_refptr", "..:webrtc_common", + "../rtc_base:deprecation", "../rtc_base:rtc_base_approved", "//third_party/abseil-cpp/absl/types:optional", ] diff --git a/api/rtp_headers.h b/api/rtp_headers.h index e5155f0d67..4415bd3736 100644 --- a/api/rtp_headers.h +++ b/api/rtp_headers.h @@ -79,6 +79,18 @@ struct AbsoluteCaptureTime { absl::optional estimated_capture_clock_offset; }; +inline bool operator==(const AbsoluteCaptureTime& lhs, + const AbsoluteCaptureTime& rhs) { + return (lhs.absolute_capture_timestamp == rhs.absolute_capture_timestamp) && + (lhs.estimated_capture_clock_offset == + rhs.estimated_capture_clock_offset); +} + +inline bool operator!=(const AbsoluteCaptureTime& lhs, + const AbsoluteCaptureTime& rhs) { + return !(lhs == rhs); +} + struct RTPHeaderExtension { RTPHeaderExtension(); RTPHeaderExtension(const RTPHeaderExtension& other); diff --git a/api/rtp_packet_info.cc b/api/rtp_packet_info.cc index efb78381e6..54e26b418b 100644 --- a/api/rtp_packet_info.cc +++ b/api/rtp_packet_info.cc @@ -18,16 +18,31 @@ namespace webrtc { RtpPacketInfo::RtpPacketInfo() : ssrc_(0), rtp_timestamp_(0), receive_time_ms_(-1) {} +RtpPacketInfo::RtpPacketInfo( + uint32_t ssrc, + std::vector csrcs, + uint32_t rtp_timestamp, + absl::optional audio_level, + absl::optional absolute_capture_time, + int64_t receive_time_ms) + : ssrc_(ssrc), + csrcs_(std::move(csrcs)), + rtp_timestamp_(rtp_timestamp), + audio_level_(audio_level), + absolute_capture_time_(absolute_capture_time), + receive_time_ms_(receive_time_ms) {} + RtpPacketInfo::RtpPacketInfo(uint32_t ssrc, std::vector csrcs, uint32_t rtp_timestamp, absl::optional audio_level, int64_t receive_time_ms) - : ssrc_(ssrc), - csrcs_(std::move(csrcs)), - rtp_timestamp_(rtp_timestamp), - audio_level_(audio_level), - receive_time_ms_(receive_time_ms) {} + : RtpPacketInfo(ssrc, + std::move(csrcs), + rtp_timestamp, + audio_level, + /*absolute_capture_time=*/absl::nullopt, + receive_time_ms) {} RtpPacketInfo::RtpPacketInfo(const RTPHeader& rtp_header, int64_t receive_time_ms) @@ -42,12 +57,15 @@ RtpPacketInfo::RtpPacketInfo(const RTPHeader& rtp_header, if (extension.hasAudioLevel) { audio_level_ = extension.audioLevel; } + + absolute_capture_time_ = extension.absolute_capture_time; } bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) { return (lhs.ssrc() == rhs.ssrc()) && (lhs.csrcs() == rhs.csrcs()) && (lhs.rtp_timestamp() == rhs.rtp_timestamp()) && (lhs.audio_level() == rhs.audio_level()) && + (lhs.absolute_capture_time() == rhs.absolute_capture_time()) && (lhs.receive_time_ms() == rhs.receive_time_ms()); } diff --git a/api/rtp_packet_info.h b/api/rtp_packet_info.h index a9e86553d4..6973027a31 100644 --- a/api/rtp_packet_info.h +++ b/api/rtp_packet_info.h @@ -17,6 +17,7 @@ #include "absl/types/optional.h" #include "api/rtp_headers.h" +#include "rtc_base/deprecation.h" namespace webrtc { @@ -29,6 +30,15 @@ class RtpPacketInfo { public: RtpPacketInfo(); + RtpPacketInfo(uint32_t ssrc, + std::vector csrcs, + uint32_t rtp_timestamp, + absl::optional audio_level, + absl::optional absolute_capture_time, + int64_t receive_time_ms); + + // TODO(bugs.webrtc.org/10739): Will be removed sometime after 2019-09-19. + RTC_DEPRECATED RtpPacketInfo(uint32_t ssrc, std::vector csrcs, uint32_t rtp_timestamp, @@ -54,6 +64,14 @@ class RtpPacketInfo { absl::optional audio_level() const { return audio_level_; } void set_audio_level(absl::optional value) { audio_level_ = value; } + const absl::optional& absolute_capture_time() const { + return absolute_capture_time_; + } + void set_absolute_capture_time( + const absl::optional& value) { + absolute_capture_time_ = value; + } + int64_t receive_time_ms() const { return receive_time_ms_; } void set_receive_time_ms(int64_t value) { receive_time_ms_ = value; } @@ -68,6 +86,10 @@ class RtpPacketInfo { // https://tools.ietf.org/html/rfc6464#section-3 absl::optional audio_level_; + // Fields from the Absolute Capture Time header extension: + // http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time + absl::optional absolute_capture_time_; + // Local |webrtc::Clock|-based timestamp of when the packet was received. int64_t receive_time_ms_; }; diff --git a/api/rtp_packet_info_unittest.cc b/api/rtp_packet_info_unittest.cc index 66cc2ed108..fe79f6df3c 100644 --- a/api/rtp_packet_info_unittest.cc +++ b/api/rtp_packet_info_unittest.cc @@ -37,7 +37,7 @@ TEST(RtpPacketInfoTest, Ssrc) { rhs = RtpPacketInfo(); EXPECT_NE(rhs.ssrc(), value); - rhs = RtpPacketInfo(value, {}, {}, {}, {}); + rhs = RtpPacketInfo(value, {}, {}, {}, {}, {}); EXPECT_EQ(rhs.ssrc(), value); } @@ -64,7 +64,7 @@ TEST(RtpPacketInfoTest, Csrcs) { rhs = RtpPacketInfo(); EXPECT_NE(rhs.csrcs(), value); - rhs = RtpPacketInfo({}, value, {}, {}, {}); + rhs = RtpPacketInfo({}, value, {}, {}, {}, {}); EXPECT_EQ(rhs.csrcs(), value); } @@ -91,7 +91,7 @@ TEST(RtpPacketInfoTest, RtpTimestamp) { rhs = RtpPacketInfo(); EXPECT_NE(rhs.rtp_timestamp(), value); - rhs = RtpPacketInfo({}, {}, value, {}, {}); + rhs = RtpPacketInfo({}, {}, value, {}, {}, {}); EXPECT_EQ(rhs.rtp_timestamp(), value); } @@ -118,10 +118,37 @@ TEST(RtpPacketInfoTest, AudioLevel) { rhs = RtpPacketInfo(); EXPECT_NE(rhs.audio_level(), value); - rhs = RtpPacketInfo({}, {}, {}, value, {}); + rhs = RtpPacketInfo({}, {}, {}, value, {}, {}); EXPECT_EQ(rhs.audio_level(), value); } +TEST(RtpPacketInfoTest, AbsoluteCaptureTime) { + const absl::optional value = AbsoluteCaptureTime{12, 34}; + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_absolute_capture_time(value); + EXPECT_EQ(rhs.absolute_capture_time(), value); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.absolute_capture_time(), value); + + rhs = RtpPacketInfo({}, {}, {}, {}, value, {}); + EXPECT_EQ(rhs.absolute_capture_time(), value); +} + TEST(RtpPacketInfoTest, ReceiveTimeMs) { const int64_t value = 8868963877546349045LL; @@ -145,7 +172,7 @@ TEST(RtpPacketInfoTest, ReceiveTimeMs) { rhs = RtpPacketInfo(); EXPECT_NE(rhs.receive_time_ms(), value); - rhs = RtpPacketInfo({}, {}, {}, {}, value); + rhs = RtpPacketInfo({}, {}, {}, {}, {}, value); EXPECT_EQ(rhs.receive_time_ms(), value); } diff --git a/api/rtp_packet_infos_unittest.cc b/api/rtp_packet_infos_unittest.cc index a14d4485f4..ce502ac378 100644 --- a/api/rtp_packet_infos_unittest.cc +++ b/api/rtp_packet_infos_unittest.cc @@ -27,9 +27,9 @@ RtpPacketInfos::vector_type ToVector(Iterator begin, Iterator end) { } // namespace TEST(RtpPacketInfosTest, BasicFunctionality) { - RtpPacketInfo p0(123, {1, 2}, 89, 5, 7); - RtpPacketInfo p1(456, {3, 4}, 89, 4, 1); - RtpPacketInfo p2(789, {5, 6}, 88, 1, 7); + RtpPacketInfo p0(123, {1, 2}, 89, 5, AbsoluteCaptureTime{45, 78}, 7); + RtpPacketInfo p1(456, {3, 4}, 89, 4, AbsoluteCaptureTime{13, 21}, 1); + RtpPacketInfo p2(789, {5, 6}, 88, 1, AbsoluteCaptureTime{99, 78}, 7); RtpPacketInfos x({p0, p1, p2}); @@ -52,9 +52,9 @@ TEST(RtpPacketInfosTest, BasicFunctionality) { } TEST(RtpPacketInfosTest, CopyShareData) { - RtpPacketInfo p0(123, {1, 2}, 89, 5, 7); - RtpPacketInfo p1(456, {3, 4}, 89, 4, 1); - RtpPacketInfo p2(789, {5, 6}, 88, 1, 7); + RtpPacketInfo p0(123, {1, 2}, 89, 5, AbsoluteCaptureTime{45, 78}, 7); + RtpPacketInfo p1(456, {3, 4}, 89, 4, AbsoluteCaptureTime{13, 21}, 1); + RtpPacketInfo p2(789, {5, 6}, 88, 1, AbsoluteCaptureTime{99, 78}, 7); RtpPacketInfos lhs({p0, p1, p2}); RtpPacketInfos rhs = lhs; diff --git a/modules/audio_coding/neteq/red_payload_splitter.cc b/modules/audio_coding/neteq/red_payload_splitter.cc index 7ff5679e72..1343690999 100644 --- a/modules/audio_coding/neteq/red_payload_splitter.cc +++ b/modules/audio_coding/neteq/red_payload_splitter.cc @@ -123,6 +123,7 @@ bool RedPayloadSplitter::SplitRed(PacketList* packet_list) { /*csrcs=*/std::vector(), /*rtp_timestamp=*/new_packet.timestamp, /*audio_level=*/absl::nullopt, + /*absolute_capture_time=*/absl::nullopt, /*receive_time_ms=*/red_packet.packet_info.receive_time_ms()); new_packets.push_front(std::move(new_packet)); payload_ptr += payload_length; diff --git a/modules/rtp_rtcp/source/source_tracker_unittest.cc b/modules/rtp_rtcp/source/source_tracker_unittest.cc index 23426978ad..55ae4d1a35 100644 --- a/modules/rtp_rtcp/source/source_tracker_unittest.cc +++ b/modules/rtp_rtcp/source/source_tracker_unittest.cc @@ -109,6 +109,7 @@ class SourceTrackerRandomTest for (size_t i = 0; i < count; ++i) { packet_infos.emplace_back(GenerateSsrc(), GenerateCsrcs(), GenerateRtpTimestamp(), GenerateAudioLevel(), + GenerateAbsoluteCaptureTime(), GenerateReceiveTimeMs()); } @@ -170,6 +171,26 @@ class SourceTrackerRandomTest std::uniform_int_distribution()(generator_)); } + absl::optional GenerateAbsoluteCaptureTime() { + if (std::bernoulli_distribution(0.25)(generator_)) { + return absl::nullopt; + } + + AbsoluteCaptureTime value; + + value.absolute_capture_timestamp = + std::uniform_int_distribution()(generator_); + + if (std::bernoulli_distribution(0.5)(generator_)) { + value.estimated_capture_clock_offset = absl::nullopt; + } else { + value.estimated_capture_clock_offset = + std::uniform_int_distribution()(generator_); + } + + return value; + } + int64_t GenerateReceiveTimeMs() { return std::uniform_int_distribution()(generator_); } @@ -223,13 +244,15 @@ TEST(SourceTrackerTest, OnFrameDeliveredRecordsSources) { constexpr uint32_t kCsrcs1 = 21; constexpr uint32_t kRtpTimestamp = 40; constexpr absl::optional kAudioLevel = 50; + constexpr absl::optional kAbsoluteCaptureTime = {}; constexpr int64_t kReceiveTimeMs = 60; SimulatedClock clock(1000000000000ULL); SourceTracker tracker(&clock); - tracker.OnFrameDelivered(RtpPacketInfos({RtpPacketInfo( - kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp, kAudioLevel, kReceiveTimeMs)})); + tracker.OnFrameDelivered(RtpPacketInfos( + {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp, kAudioLevel, + kAbsoluteCaptureTime, kReceiveTimeMs)})); int64_t timestamp_ms = clock.TimeInMilliseconds(); @@ -251,23 +274,24 @@ TEST(SourceTrackerTest, OnFrameDeliveredUpdatesSources) { constexpr uint32_t kRtpTimestamp1 = 41; constexpr absl::optional kAudioLevel0 = 50; constexpr absl::optional kAudioLevel1 = absl::nullopt; + constexpr absl::optional kAbsoluteCaptureTime = {}; constexpr int64_t kReceiveTimeMs0 = 60; constexpr int64_t kReceiveTimeMs1 = 61; SimulatedClock clock(1000000000000ULL); SourceTracker tracker(&clock); - tracker.OnFrameDelivered( - RtpPacketInfos({RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, - kAudioLevel0, kReceiveTimeMs0)})); + tracker.OnFrameDelivered(RtpPacketInfos( + {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, kAudioLevel0, + kAbsoluteCaptureTime, kReceiveTimeMs0)})); int64_t timestamp_ms_0 = clock.TimeInMilliseconds(); clock.AdvanceTimeMilliseconds(17); - tracker.OnFrameDelivered( - RtpPacketInfos({RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs2}, kRtpTimestamp1, - kAudioLevel1, kReceiveTimeMs1)})); + tracker.OnFrameDelivered(RtpPacketInfos( + {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs2}, kRtpTimestamp1, kAudioLevel1, + kAbsoluteCaptureTime, kReceiveTimeMs1)})); int64_t timestamp_ms_1 = clock.TimeInMilliseconds(); @@ -292,21 +316,22 @@ TEST(SourceTrackerTest, TimedOutSourcesAreRemoved) { constexpr uint32_t kRtpTimestamp1 = 41; constexpr absl::optional kAudioLevel0 = 50; constexpr absl::optional kAudioLevel1 = absl::nullopt; + constexpr absl::optional kAbsoluteCaptureTime = {}; constexpr int64_t kReceiveTimeMs0 = 60; constexpr int64_t kReceiveTimeMs1 = 61; SimulatedClock clock(1000000000000ULL); SourceTracker tracker(&clock); - tracker.OnFrameDelivered( - RtpPacketInfos({RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, - kAudioLevel0, kReceiveTimeMs0)})); + tracker.OnFrameDelivered(RtpPacketInfos( + {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, kAudioLevel0, + kAbsoluteCaptureTime, kReceiveTimeMs0)})); clock.AdvanceTimeMilliseconds(17); - tracker.OnFrameDelivered( - RtpPacketInfos({RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs2}, kRtpTimestamp1, - kAudioLevel1, kReceiveTimeMs1)})); + tracker.OnFrameDelivered(RtpPacketInfos( + {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs2}, kRtpTimestamp1, kAudioLevel1, + kAbsoluteCaptureTime, kReceiveTimeMs1)})); int64_t timestamp_ms_1 = clock.TimeInMilliseconds();