summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorimcheng@chromium.org <imcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-19 06:36:51 +0000
committerimcheng@chromium.org <imcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-19 06:36:51 +0000
commit3c80d5d4956550075b3606c8c8683fc79dc32713 (patch)
tree69c4b9cd0b77d488d8e4c921361c1fdf086a8310 /media
parentb72c7323d961ae81d513500da16265824f79be8a (diff)
downloadchromium_src-3c80d5d4956550075b3606c8c8683fc79dc32713.zip
chromium_src-3c80d5d4956550075b3606c8c8683fc79dc32713.tar.gz
chromium_src-3c80d5d4956550075b3606c8c8683fc79dc32713.tar.bz2
Cast: Implemented relative RTP timestamp in EncodingEventSubscriber.
- RTP timestamps in the maps of EncodingEventSubscribers (map keys, rtp timestamp fields in protos) are now relative to the first RTP timestamp seen since last Reset(). - The two GetXXXEventsAndReset() functions have been combined into one. In addition, it will now return the first RTP timestamp seen since the last Reset(). It will also reset the first RTP timestamp seen. - There are two motivations for this change: -- 1. RTP timestamps wrap around easily - around every 12 hours or so. If we do not use relative RTP timestamps, the ordering in the map, as well as general order of the events by frame, will be messed up. -- 2. Using relative values will be more compact in variable-length encoding of the RTP timestamp fields. Review URL: https://codereview.chromium.org/168933002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251973 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/cast/logging/encoding_event_subscriber.cc61
-rw-r--r--media/cast/logging/encoding_event_subscriber.h32
-rw-r--r--media/cast/logging/encoding_event_subscriber_unittest.cc164
3 files changed, 182 insertions, 75 deletions
diff --git a/media/cast/logging/encoding_event_subscriber.cc b/media/cast/logging/encoding_event_subscriber.cc
index 265e39d..5262e49 100644
--- a/media/cast/logging/encoding_event_subscriber.cc
+++ b/media/cast/logging/encoding_event_subscriber.cc
@@ -20,8 +20,12 @@ namespace media {
namespace cast {
EncodingEventSubscriber::EncodingEventSubscriber(
- EventMediaType event_media_type, size_t max_frames)
- : event_media_type_(event_media_type), max_frames_(max_frames) {}
+ EventMediaType event_media_type,
+ size_t max_frames)
+ : event_media_type_(event_media_type),
+ max_frames_(max_frames),
+ seen_first_rtp_timestamp_(false),
+ first_rtp_timestamp_(0u) {}
EncodingEventSubscriber::~EncodingEventSubscriber() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -32,16 +36,17 @@ void EncodingEventSubscriber::OnReceiveFrameEvent(
DCHECK(thread_checker_.CalledOnValidThread());
if (ShouldProcessEvent(frame_event.type)) {
- FrameEventMap::iterator it =
- frame_event_map_.find(frame_event.rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp =
+ GetRelativeRtpTimestamp(frame_event.rtp_timestamp);
+ FrameEventMap::iterator it = frame_event_map_.find(relative_rtp_timestamp);
linked_ptr<AggregatedFrameEvent> event_proto;
// Look up existing entry. If not found, create a new entry and add to map.
if (it == frame_event_map_.end()) {
event_proto.reset(new AggregatedFrameEvent);
- event_proto->set_rtp_timestamp(frame_event.rtp_timestamp);
+ event_proto->set_rtp_timestamp(relative_rtp_timestamp);
frame_event_map_.insert(
- std::make_pair(frame_event.rtp_timestamp, event_proto));
+ std::make_pair(relative_rtp_timestamp, event_proto));
} else {
event_proto = it->second;
}
@@ -69,17 +74,19 @@ void EncodingEventSubscriber::OnReceivePacketEvent(
DCHECK(thread_checker_.CalledOnValidThread());
if (ShouldProcessEvent(packet_event.type)) {
+ RtpTimestamp relative_rtp_timestamp =
+ GetRelativeRtpTimestamp(packet_event.rtp_timestamp);
PacketEventMap::iterator it =
- packet_event_map_.find(packet_event.rtp_timestamp);
+ packet_event_map_.find(relative_rtp_timestamp);
linked_ptr<AggregatedPacketEvent> event_proto;
BasePacketEvent* base_packet_event_proto = NULL;
// Look up existing entry. If not found, create a new entry and add to map.
if (it == packet_event_map_.end()) {
event_proto.reset(new AggregatedPacketEvent);
- event_proto->set_rtp_timestamp(packet_event.rtp_timestamp);
+ event_proto->set_rtp_timestamp(relative_rtp_timestamp);
packet_event_map_.insert(
- std::make_pair(packet_event.rtp_timestamp, event_proto));
+ std::make_pair(relative_rtp_timestamp, event_proto));
base_packet_event_proto = event_proto->add_base_packet_event();
base_packet_event_proto->set_packet_id(packet_event.packet_id);
} else {
@@ -120,21 +127,18 @@ void EncodingEventSubscriber::OnReceiveGenericEvent(
// Do nothing, there are no generic events we are interested in.
}
-void EncodingEventSubscriber::GetFrameEventsAndReset(
- FrameEventMap* frame_event_map) {
+void EncodingEventSubscriber::GetEventsAndReset(
+ FrameEventMap* frame_events,
+ PacketEventMap* packet_events,
+ RtpTimestamp* first_rtp_timestamp) {
DCHECK(thread_checker_.CalledOnValidThread());
- frame_event_map->swap(frame_event_map_);
- frame_event_map_.clear();
-}
-void EncodingEventSubscriber::GetPacketEventsAndReset(
- PacketEventMap* packet_event_map) {
- DCHECK(thread_checker_.CalledOnValidThread());
- packet_event_map->swap(packet_event_map_);
- packet_event_map_.clear();
+ frame_events->swap(frame_event_map_);
+ packet_events->swap(packet_event_map_);
+ *first_rtp_timestamp = first_rtp_timestamp_;
+ Reset();
}
-
bool EncodingEventSubscriber::ShouldProcessEvent(CastLoggingEvent event) {
return GetEventMediaType(event) == event_media_type_;
}
@@ -153,5 +157,22 @@ void EncodingEventSubscriber::TruncatePacketEventMapIfNeeded() {
packet_event_map_.erase(packet_event_map_.begin());
}
+RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp(
+ RtpTimestamp rtp_timestamp) {
+ if (!seen_first_rtp_timestamp_) {
+ seen_first_rtp_timestamp_ = true;
+ first_rtp_timestamp_ = rtp_timestamp;
+ }
+
+ return rtp_timestamp - first_rtp_timestamp_;
+}
+
+void EncodingEventSubscriber::Reset() {
+ frame_event_map_.clear();
+ packet_event_map_.clear();
+ seen_first_rtp_timestamp_ = false;
+ first_rtp_timestamp_ = 0u;
+}
+
} // namespace cast
} // namespace media
diff --git a/media/cast/logging/encoding_event_subscriber.h b/media/cast/logging/encoding_event_subscriber.h
index acd1d14..5766e7b 100644
--- a/media/cast/logging/encoding_event_subscriber.h
+++ b/media/cast/logging/encoding_event_subscriber.h
@@ -46,13 +46,18 @@ class EncodingEventSubscriber : public RawEventSubscriber {
virtual void OnReceiveGenericEvent(const GenericEvent& generic_event)
OVERRIDE;
- // Assigns frame events received so far to |frame_events| and clears them
- // from this object.
- void GetFrameEventsAndReset(FrameEventMap* frame_events);
-
- // Assigns packet events received so far to |packet_events| and clears them
- // from this object.
- void GetPacketEventsAndReset(PacketEventMap* packet_events);
+ // Assigns frame events and packet events received so far to |frame_events|
+ // and clears them |packet_events| respectively, assigns the first seen RTP
+ // timestamp (which is used as a reference for all event entries) to
+ // |first_rtp_timestamp|, and reset this object's internal states.
+ // All RTP timestamp values returned in the maps are relative to
+ // |first_rtp_timestamp|, i.e. suppose |first_rtp_timestamp| is X,
+ // then the first event will be recorded with a relative
+ // RTP timestamp value of 0. If the next event has original RTP timestamp
+ // X+20, it will be recorded with a relative RTP timestamp of 20.
+ void GetEventsAndReset(FrameEventMap* frame_events,
+ PacketEventMap* packet_events,
+ RtpTimestamp* first_rtp_timestamp);
private:
bool ShouldProcessEvent(CastLoggingEvent event);
@@ -63,6 +68,13 @@ class EncodingEventSubscriber : public RawEventSubscriber {
// Removes oldest entry from |packet_event_map_| (ordered by RTP timestamp).
void TruncatePacketEventMapIfNeeded();
+ // Returns the difference between |rtp_timestamp| and |first_rtp_timestamp_|.
+ // Sets |first_rtp_timestamp_| if it is not already set.
+ RtpTimestamp GetRelativeRtpTimestamp(RtpTimestamp rtp_timestamp);
+
+ // Clears the maps and first RTP timestamp seen.
+ void Reset();
+
const EventMediaType event_media_type_;
const size_t max_frames_;
@@ -72,6 +84,12 @@ class EncodingEventSubscriber : public RawEventSubscriber {
// All functions must be called on the main thread.
base::ThreadChecker thread_checker_;
+ // Set to true on first event encountered after a |Reset()|.
+ bool seen_first_rtp_timestamp_;
+
+ // Set to RTP timestamp of first event encountered after a |Reset()|.
+ RtpTimestamp first_rtp_timestamp_;
+
DISALLOW_COPY_AND_ASSIGN(EncodingEventSubscriber);
};
diff --git a/media/cast/logging/encoding_event_subscriber_unittest.cc b/media/cast/logging/encoding_event_subscriber_unittest.cc
index 1194ed9..3b45837 100644
--- a/media/cast/logging/encoding_event_subscriber_unittest.cc
+++ b/media/cast/logging/encoding_event_subscriber_unittest.cc
@@ -32,7 +32,8 @@ class EncodingEventSubscriberTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_,
- GetLoggingConfigWithRawEventsAndStatsEnabled())) {}
+ GetLoggingConfigWithRawEventsAndStatsEnabled())),
+ first_rtp_timestamp(0) {}
void Init(EventMediaType event_media_type) {
DCHECK(!event_subscriber_);
@@ -48,10 +49,18 @@ class EncodingEventSubscriberTest : public ::testing::Test {
}
}
+ void GetEventsAndReset() {
+ event_subscriber_->GetEventsAndReset(
+ &frame_events, &packet_events, &first_rtp_timestamp);
+ }
+
base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
scoped_refptr<CastEnvironment> cast_environment_;
scoped_ptr<EncodingEventSubscriber> event_subscriber_;
+ FrameEventMap frame_events;
+ PacketEventMap packet_events;
+ RtpTimestamp first_rtp_timestamp;
};
TEST_F(EncodingEventSubscriberTest, FrameEventTruncating) {
@@ -71,8 +80,7 @@ TEST_F(EncodingEventSubscriberTest, FrameEventTruncating) {
/*frame_id*/ 0);
}
- FrameEventMap frame_events;
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
ASSERT_EQ(10u, frame_events.size());
EXPECT_EQ(100u, frame_events.begin()->first);
@@ -95,8 +103,7 @@ TEST_F(EncodingEventSubscriberTest, PacketEventTruncating) {
/*size*/ 123);
}
- PacketEventMap packet_events;
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
ASSERT_EQ(10u, packet_events.size());
EXPECT_EQ(100u, packet_events.begin()->first);
@@ -119,10 +126,9 @@ TEST_F(EncodingEventSubscriberTest, EventFiltering) {
rtp_timestamp,
/*frame_id*/ 0);
- FrameEventMap frame_events;
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
- FrameEventMap::iterator frame_it = frame_events.find(rtp_timestamp);
+ FrameEventMap::iterator frame_it = frame_events.find(0);
ASSERT_TRUE(frame_it != frame_events.end());
linked_ptr<AggregatedFrameEvent> frame_event = frame_it->second;
@@ -131,8 +137,8 @@ TEST_F(EncodingEventSubscriberTest, EventFiltering) {
EXPECT_EQ(media::cast::proto::VIDEO_FRAME_DECODED,
frame_event->event_type(0));
- PacketEventMap packet_events;
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
+
EXPECT_TRUE(packet_events.empty());
}
@@ -144,17 +150,17 @@ TEST_F(EncodingEventSubscriberTest, FrameEvent) {
rtp_timestamp,
/*frame_id*/ 0);
- FrameEventMap frame_events;
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
ASSERT_EQ(1u, frame_events.size());
- FrameEventMap::iterator it = frame_events.find(rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp - first_rtp_timestamp;
+ FrameEventMap::iterator it = frame_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != frame_events.end());
linked_ptr<AggregatedFrameEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->event_type_size());
EXPECT_EQ(media::cast::proto::VIDEO_FRAME_DECODED, event->event_type(0));
@@ -164,7 +170,7 @@ TEST_F(EncodingEventSubscriberTest, FrameEvent) {
EXPECT_EQ(0, event->encoded_frame_size());
EXPECT_EQ(0, event->delay_millis());
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
EXPECT_TRUE(frame_events.empty());
}
@@ -177,17 +183,17 @@ TEST_F(EncodingEventSubscriberTest, FrameEventDelay) {
now, kAudioPlayoutDelay, rtp_timestamp,
/*frame_id*/ 0, base::TimeDelta::FromMilliseconds(delay_ms));
- FrameEventMap frame_events;
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
ASSERT_EQ(1u, frame_events.size());
- FrameEventMap::iterator it = frame_events.find(rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp - first_rtp_timestamp;
+ FrameEventMap::iterator it = frame_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != frame_events.end());
linked_ptr<AggregatedFrameEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->event_type_size());
EXPECT_EQ(media::cast::proto::AUDIO_PLAYOUT_DELAY, event->event_type(0));
@@ -207,17 +213,17 @@ TEST_F(EncodingEventSubscriberTest, FrameEventSize) {
now, kVideoFrameEncoded, rtp_timestamp,
/*frame_id*/ 0, size);
- FrameEventMap frame_events;
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
ASSERT_EQ(1u, frame_events.size());
- FrameEventMap::iterator it = frame_events.find(rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp - first_rtp_timestamp;
+ FrameEventMap::iterator it = frame_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != frame_events.end());
linked_ptr<AggregatedFrameEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->event_type_size());
EXPECT_EQ(media::cast::proto::VIDEO_FRAME_ENCODED, event->event_type(0));
@@ -248,17 +254,17 @@ TEST_F(EncodingEventSubscriberTest, MultipleFrameEvents) {
cast_environment_->Logging()->InsertFrameEvent(
now3, kAudioFrameDecoded, rtp_timestamp1, /*frame_id*/ 0);
- FrameEventMap frame_events;
- event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ GetEventsAndReset();
ASSERT_EQ(2u, frame_events.size());
- FrameEventMap::iterator it = frame_events.find(100);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp1 - first_rtp_timestamp;
+ FrameEventMap::iterator it = frame_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != frame_events.end());
linked_ptr<AggregatedFrameEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp1, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(2, event->event_type_size());
EXPECT_EQ(media::cast::proto::AUDIO_PLAYOUT_DELAY, event->event_type(0));
@@ -268,12 +274,13 @@ TEST_F(EncodingEventSubscriberTest, MultipleFrameEvents) {
EXPECT_EQ(now1.ToInternalValue(), event->event_timestamp_micros(0));
EXPECT_EQ(now3.ToInternalValue(), event->event_timestamp_micros(1));
- it = frame_events.find(200);
+ relative_rtp_timestamp = rtp_timestamp2 - first_rtp_timestamp;
+ it = frame_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != frame_events.end());
event = it->second;
- EXPECT_EQ(rtp_timestamp2, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->event_type_size());
EXPECT_EQ(media::cast::proto::AUDIO_FRAME_ENCODED, event->event_type(0));
@@ -292,17 +299,17 @@ TEST_F(EncodingEventSubscriberTest, PacketEvent) {
now, kAudioPacketReceived, rtp_timestamp, /*frame_id*/ 0, packet_id,
/*max_packet_id*/ 10, size);
- PacketEventMap packet_events;
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
ASSERT_EQ(1u, packet_events.size());
- PacketEventMap::iterator it = packet_events.find(rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp - first_rtp_timestamp;
+ PacketEventMap::iterator it = packet_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != packet_events.end());
linked_ptr<AggregatedPacketEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->base_packet_event_size());
const BasePacketEvent& base_event = event->base_packet_event(0);
@@ -313,7 +320,7 @@ TEST_F(EncodingEventSubscriberTest, PacketEvent) {
ASSERT_EQ(1, base_event.event_timestamp_micros_size());
EXPECT_EQ(now.ToInternalValue(), base_event.event_timestamp_micros(0));
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
EXPECT_TRUE(packet_events.empty());
}
@@ -333,17 +340,17 @@ TEST_F(EncodingEventSubscriberTest, MultiplePacketEventsForPacket) {
now2, kPacketSentToNetwork, rtp_timestamp, /*frame_id*/ 0, packet_id,
/*max_packet_id*/ 10, size);
- PacketEventMap packet_events;
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
ASSERT_EQ(1u, packet_events.size());
- PacketEventMap::iterator it = packet_events.find(rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp - first_rtp_timestamp;
+ PacketEventMap::iterator it = packet_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != packet_events.end());
linked_ptr<AggregatedPacketEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->base_packet_event_size());
const BasePacketEvent& base_event = event->base_packet_event(0);
@@ -374,17 +381,17 @@ TEST_F(EncodingEventSubscriberTest, MultiplePacketEventsForFrame) {
now2, kPacketRetransmitted, rtp_timestamp, /*frame_id*/ 0, packet_id_2,
/*max_packet_id*/ 10, size);
- PacketEventMap packet_events;
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
ASSERT_EQ(1u, packet_events.size());
- PacketEventMap::iterator it = packet_events.find(rtp_timestamp);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp - first_rtp_timestamp;
+ PacketEventMap::iterator it = packet_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != packet_events.end());
linked_ptr<AggregatedPacketEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(2, event->base_packet_event_size());
const BasePacketEvent& base_event = event->base_packet_event(0);
@@ -421,17 +428,17 @@ TEST_F(EncodingEventSubscriberTest, MultiplePacketEvents) {
now2, kPacketRetransmitted, rtp_timestamp_2, /*frame_id*/ 0, packet_id_2,
/*max_packet_id*/ 10, size);
- PacketEventMap packet_events;
- event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ GetEventsAndReset();
ASSERT_EQ(2u, packet_events.size());
- PacketEventMap::iterator it = packet_events.find(rtp_timestamp_1);
+ RtpTimestamp relative_rtp_timestamp = rtp_timestamp_1 - first_rtp_timestamp;
+ PacketEventMap::iterator it = packet_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != packet_events.end());
linked_ptr<AggregatedPacketEvent> event = it->second;
- EXPECT_EQ(rtp_timestamp_1, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->base_packet_event_size());
const BasePacketEvent& base_event = event->base_packet_event(0);
@@ -441,12 +448,13 @@ TEST_F(EncodingEventSubscriberTest, MultiplePacketEvents) {
ASSERT_EQ(1, base_event.event_timestamp_micros_size());
EXPECT_EQ(now1.ToInternalValue(), base_event.event_timestamp_micros(0));
- it = packet_events.find(rtp_timestamp_2);
+ relative_rtp_timestamp = rtp_timestamp_2 - first_rtp_timestamp;
+ it = packet_events.find(relative_rtp_timestamp);
ASSERT_TRUE(it != packet_events.end());
event = it->second;
- EXPECT_EQ(rtp_timestamp_2, event->rtp_timestamp());
+ EXPECT_EQ(relative_rtp_timestamp, event->rtp_timestamp());
ASSERT_EQ(1, event->base_packet_event_size());
const BasePacketEvent& base_event_2 = event->base_packet_event(0);
@@ -458,5 +466,65 @@ TEST_F(EncodingEventSubscriberTest, MultiplePacketEvents) {
EXPECT_EQ(now2.ToInternalValue(), base_event_2.event_timestamp_micros(0));
}
+TEST_F(EncodingEventSubscriberTest, FirstRtpTimestamp) {
+ Init(VIDEO_EVENT);
+ RtpTimestamp rtp_timestamp = 12345;
+ base::TimeTicks now(testing_clock_->NowTicks());
+
+ cast_environment_->Logging()->InsertFrameEvent(now,
+ kVideoFrameCaptured,
+ rtp_timestamp,
+ /*frame_id*/ 0);
+
+ cast_environment_->Logging()->InsertFrameEvent(now,
+ kVideoFrameReceived,
+ rtp_timestamp + 30,
+ /*frame_id*/ 1);
+
+ GetEventsAndReset();
+
+ EXPECT_EQ(rtp_timestamp, first_rtp_timestamp);
+ FrameEventMap::iterator it = frame_events.find(0);
+ ASSERT_NE(frame_events.end(), it);
+
+ it = frame_events.find(30);
+ ASSERT_NE(frame_events.end(), it);
+
+ rtp_timestamp = 67890;
+
+ cast_environment_->Logging()->InsertFrameEvent(now,
+ kVideoFrameCaptured,
+ rtp_timestamp,
+ /*frame_id*/ 0);
+ GetEventsAndReset();
+
+ EXPECT_EQ(rtp_timestamp, first_rtp_timestamp);
+}
+
+TEST_F(EncodingEventSubscriberTest, RelativeRtpTimestampWrapAround) {
+ Init(VIDEO_EVENT);
+ RtpTimestamp rtp_timestamp = 0xffffffff - 20;
+ base::TimeTicks now(testing_clock_->NowTicks());
+
+ cast_environment_->Logging()->InsertFrameEvent(now,
+ kVideoFrameCaptured,
+ rtp_timestamp,
+ /*frame_id*/ 0);
+
+ // RtpTimestamp has now wrapped around.
+ cast_environment_->Logging()->InsertFrameEvent(now,
+ kVideoFrameReceived,
+ rtp_timestamp + 30,
+ /*frame_id*/ 1);
+
+ GetEventsAndReset();
+
+ FrameEventMap::iterator it = frame_events.find(0);
+ ASSERT_NE(frame_events.end(), it);
+
+ it = frame_events.find(30);
+ ASSERT_NE(frame_events.end(), it);
+}
+
} // namespace cast
} // namespace media