Commit d589cbb0 authored by hubbe's avatar hubbe Committed by Commit bot

Cast: Logging estimates clock difference based on packets

Makes the clock offset estimator more accurate and reacts faster.
This comes from issue 519163002 (but without the tracing.)

Review URL: https://codereview.chromium.org/556693002

Cr-Commit-Position: refs/heads/master@{#294325}
parent 72d3e5c0
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CAST_COMMON_MOD_UTIL_H_
#define MEDIA_CAST_COMMON_MOD_UTIL_H_
#include <map>
#include "base/logging.h"
namespace media {
namespace cast {
// MAP is a map<uint??, ...> where the unsigned integer is
// assumed to wrap around, but only a small range is used at a time.
// Return the oldest entry in the map.
template<class MAP>
typename MAP::iterator ModMapOldest(MAP* map) {
typename MAP::iterator ret = map->begin();
if (ret != map->end()) {
typename MAP::key_type lower_quarter = 0;
lower_quarter--;
lower_quarter >>= 1;
if (ret->first < lower_quarter) {
typename MAP::iterator tmp = map->upper_bound(lower_quarter * 3);
if (tmp != map->end())
ret = tmp;
}
}
return ret;
}
// MAP is a map<uint??, ...> where the unsigned integer is
// assumed to wrap around, but only a small range is used at a time.
// Returns the previous entry in the map.
template<class MAP>
typename MAP::iterator ModMapPrevious(MAP* map, typename MAP::iterator i) {
DCHECK(!map->empty());
typename MAP::iterator ret = i;
if (i == map->begin()) {
ret = map->end();
}
ret--;
if (i == ret)
return map->end();
if ((i->first - ret->first) > ((typename MAP::key_type(0) - 1)) >> 1)
return map->end();
return ret;
}
} // namespace cast
} // namespace media
#endif
...@@ -53,8 +53,7 @@ RawEventSubscriberBundle::~RawEventSubscriberBundle() { ...@@ -53,8 +53,7 @@ RawEventSubscriberBundle::~RawEventSubscriberBundle() {
void RawEventSubscriberBundle::AddEventSubscribers(bool is_audio) { void RawEventSubscriberBundle::AddEventSubscribers(bool is_audio) {
if (!receiver_offset_estimator_.get()) { if (!receiver_offset_estimator_.get()) {
receiver_offset_estimator_.reset( receiver_offset_estimator_.reset(new ReceiverTimeOffsetEstimatorImpl);
new ReceiverTimeOffsetEstimatorImpl(cast_environment_->Clock()));
cast_environment_->Logging()->AddRawEventSubscriber( cast_environment_->Logging()->AddRawEventSubscriber(
receiver_offset_estimator_.get()); receiver_offset_estimator_.get());
} }
......
...@@ -12,140 +12,134 @@ ...@@ -12,140 +12,134 @@
namespace media { namespace media {
namespace cast { namespace cast {
// This should be large enough so that we can collect all 3 events before ReceiverTimeOffsetEstimatorImpl::BoundCalculator::BoundCalculator()
// the entry gets removed from the map. : has_bound_(false) {}
const size_t kMaxEventTimesMapSize = 100; ReceiverTimeOffsetEstimatorImpl::BoundCalculator::~BoundCalculator() {}
ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl( void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetSent(
base::TickClock* clock) uint32 rtp,
: bounded_(false), uint32 packet_id,
clock_(clock), bool audio,
offset_bounds_valid_(false), base::TimeTicks t) {
last_reset_time_(clock_->NowTicks()) { uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) |
static_cast<uint64>(audio);
events_[key].first = t;
CheckUpdate(key);
}
void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetReceived(
uint32 rtp,
uint16 packet_id,
bool audio,
base::TimeTicks t) {
uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) |
static_cast<uint64>(audio);
events_[key].second = t;
CheckUpdate(key);
}
void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::UpdateBound(
base::TimeTicks sent, base::TimeTicks received) {
base::TimeDelta delta = received - sent;
if (has_bound_) {
if (delta < bound_) {
bound_ = delta;
} else {
bound_ += (delta - bound_) / kClockDriftSpeed;
}
} else {
bound_ = delta;
}
has_bound_ = true;
}
void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::CheckUpdate(
uint64 key) {
const TimeTickPair& ticks = events_[key];
if (!ticks.first.is_null() && !ticks.second.is_null()) {
UpdateBound(ticks.first, ticks.second);
events_.erase(key);
return;
}
if (events_.size() > kMaxEventTimesMapSize) {
EventMap::iterator i = ModMapOldest(&events_);
if (i != events_.end()) {
events_.erase(i);
}
}
}
ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl() {
} }
ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() { ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
} }
void ReceiverTimeOffsetEstimatorImpl::OnReceiveFrameEvent( void ReceiverTimeOffsetEstimatorImpl::OnReceiveFrameEvent(
const FrameEvent& frame_event) { const FrameEvent& frame_event) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
switch (frame_event.type) {
if (frame_event.media_type != VIDEO_EVENT)
return;
CastLoggingEvent event = frame_event.type;
if (event != FRAME_ENCODED && event != FRAME_ACK_SENT &&
event != FRAME_ACK_RECEIVED)
return;
EventTimesMap::iterator it = event_times_map_.find(frame_event.rtp_timestamp);
if (it == event_times_map_.end()) {
EventTimes event_times;
it = event_times_map_.insert(std::make_pair(frame_event.rtp_timestamp,
event_times)).first;
}
switch (event) {
case FRAME_ENCODED:
// Encode is supposed to happen only once. If we see duplicate event,
// throw away the entry.
if (it->second.event_a_time.is_null()) {
it->second.event_a_time = frame_event.timestamp;
} else {
event_times_map_.erase(it);
return;
}
break;
case FRAME_ACK_SENT: case FRAME_ACK_SENT:
if (it->second.event_b_time.is_null()) { lower_bound_.SetSent(frame_event.rtp_timestamp,
it->second.event_b_time = frame_event.timestamp; 0,
} else if (it->second.event_b_time != frame_event.timestamp) { frame_event.media_type == AUDIO_EVENT,
// Duplicate ack sent events are normal due to RTCP redundancy, frame_event.timestamp);
// but they must have the same event timestamp.
event_times_map_.erase(it);
return;
}
break; break;
case FRAME_ACK_RECEIVED: case FRAME_ACK_RECEIVED:
// If there are duplicate ack received events, pick the one with the lower_bound_.SetReceived(frame_event.rtp_timestamp,
// smallest event timestamp so we can get a better bound. 0,
if (it->second.event_c_time.is_null()) { frame_event.media_type == AUDIO_EVENT,
it->second.event_c_time = frame_event.timestamp; frame_event.timestamp);
} else {
it->second.event_c_time =
std::min(frame_event.timestamp, it->second.event_c_time);
}
break; break;
default: default:
NOTREACHED(); // Ignored
} break;
if (!it->second.event_a_time.is_null() &&
!it->second.event_b_time.is_null() &&
!it->second.event_c_time.is_null()) {
UpdateOffsetBounds(it->second);
event_times_map_.erase(it);
} }
// Keep the map size at most |kMaxEventTimesMapSize|.
if (event_times_map_.size() > kMaxEventTimesMapSize)
event_times_map_.erase(event_times_map_.begin());
} }
bool ReceiverTimeOffsetEstimatorImpl::GetReceiverOffsetBounds( bool ReceiverTimeOffsetEstimatorImpl::GetReceiverOffsetBounds(
base::TimeDelta* lower_bound, base::TimeDelta* lower_bound,
base::TimeDelta* upper_bound) { base::TimeDelta* upper_bound) {
if (!bounded_) if (!lower_bound_.has_bound() || !upper_bound_.has_bound())
return false; return false;
*lower_bound = prev_offset_lower_bound_; *lower_bound = -lower_bound_.bound();
*upper_bound = prev_offset_upper_bound_; *upper_bound = upper_bound_.bound();
// Sanitize the output, we don't want the upper bound to be
// lower than the lower bound, make them the same.
if (upper_bound < lower_bound) {
lower_bound += (lower_bound - upper_bound) / 2;
upper_bound = lower_bound;
}
return true; return true;
} }
void ReceiverTimeOffsetEstimatorImpl::OnReceivePacketEvent( void ReceiverTimeOffsetEstimatorImpl::OnReceivePacketEvent(
const PacketEvent& packet_event) { const PacketEvent& packet_event) {
// Not interested in packet events.
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
} switch (packet_event.type) {
case PACKET_SENT_TO_NETWORK:
void ReceiverTimeOffsetEstimatorImpl::UpdateOffsetBounds( upper_bound_.SetSent(packet_event.rtp_timestamp,
const EventTimes& event) { packet_event.packet_id,
base::TimeDelta lower_bound = event.event_b_time - event.event_c_time; packet_event.media_type == AUDIO_EVENT,
base::TimeDelta upper_bound = event.event_b_time - event.event_a_time; packet_event.timestamp);
break;
if (offset_bounds_valid_) { case PACKET_RECEIVED:
lower_bound = std::max(lower_bound, offset_lower_bound_); upper_bound_.SetReceived(packet_event.rtp_timestamp,
upper_bound = std::min(upper_bound, offset_upper_bound_); packet_event.packet_id,
} packet_event.media_type == AUDIO_EVENT,
packet_event.timestamp);
if (lower_bound > upper_bound) { break;
VLOG(2) << "Got bogus offset bound values [" << lower_bound.InMilliseconds() default:
<< ", " << upper_bound.InMilliseconds() << "]."; // Ignored
return; break;
}
offset_lower_bound_ = lower_bound;
offset_upper_bound_ = upper_bound;
offset_bounds_valid_ = true;
if (!bounded_ ||
offset_upper_bound_ - offset_lower_bound_ <
base::TimeDelta::FromMilliseconds(20)) {
prev_offset_lower_bound_ = offset_lower_bound_;
prev_offset_upper_bound_ = offset_upper_bound_;
}
base::TimeTicks now = clock_->NowTicks();
if (now - last_reset_time_ > base::TimeDelta::FromSeconds(20)) {
last_reset_time_ = now;
offset_lower_bound_ = base::TimeDelta();
offset_upper_bound_ = base::TimeDelta();
offset_bounds_valid_ = false;
} }
bounded_ = true;
} }
} // namespace cast } // namespace cast
} // namespace media } // namespace media
...@@ -5,30 +5,36 @@ ...@@ -5,30 +5,36 @@
#ifndef MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_ #ifndef MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_
#define MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_ #define MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_
#include <map>
#include "base/time/time.h" #include "base/time/time.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "media/cast/common/mod_util.h"
#include "media/cast/logging/logging_defines.h" #include "media/cast/logging/logging_defines.h"
#include "media/cast/logging/receiver_time_offset_estimator.h" #include "media/cast/logging/receiver_time_offset_estimator.h"
namespace base {
class TickClock;
}
namespace media { namespace media {
namespace cast { namespace cast {
// This implementation listens to three types of video events:
// 1. FRAME_ENCODED (sender side) // This should be large enough so that we can collect all 3 events before
// 2. FRAME_ACK_SENT (receiver side) // the entry gets removed from the map.
// 3. FRAME_ACK_RECEIVED (sender side) const size_t kMaxEventTimesMapSize = 500;
// The lower, this is, the faster we adjust to clock drift.
// (But with more jitter.)
const size_t kClockDriftSpeed = 500;
// This implementation listens to two pair of events
// 1. FRAME_ACK_SENT / FRAME_ACK_RECEIVED (receiver->sender)
// 2. PACKET_SENT_TO_NETWORK / PACKET_RECEIVED (sender->receiver)
// There is a causal relationship between these events in that these events // There is a causal relationship between these events in that these events
// must happen in order. This class obtains the lower and upper bounds for // must happen in order. This class obtains the lower and upper bounds for
// the offset by taking the difference of timestamps (2) - (1) and (2) - (3), // the offset by taking the difference of timestamps.
// respectively.
// The bound will become better as the latency between the events decreases.
class ReceiverTimeOffsetEstimatorImpl : public ReceiverTimeOffsetEstimator { class ReceiverTimeOffsetEstimatorImpl : public ReceiverTimeOffsetEstimator {
public: public:
ReceiverTimeOffsetEstimatorImpl(base::TickClock* clock); ReceiverTimeOffsetEstimatorImpl();
virtual ~ReceiverTimeOffsetEstimatorImpl(); virtual ~ReceiverTimeOffsetEstimatorImpl();
...@@ -41,28 +47,47 @@ class ReceiverTimeOffsetEstimatorImpl : public ReceiverTimeOffsetEstimator { ...@@ -41,28 +47,47 @@ class ReceiverTimeOffsetEstimatorImpl : public ReceiverTimeOffsetEstimator {
base::TimeDelta* upper_bound) OVERRIDE; base::TimeDelta* upper_bound) OVERRIDE;
private: private:
struct EventTimes { // This helper uses the difference between sent and recived event
base::TimeTicks event_a_time; // to calculate an upper bound on the difference between the clocks
base::TimeTicks event_b_time; // on the sender and receiver. Note that this difference can take
base::TimeTicks event_c_time; // very large positive or negative values, but the smaller value is
// always the better estimate, since a receive event cannot possibly
// happen before a send event. Note that we use this to calculate
// both upper and lower bounds by reversing the sender/receiver
// relationship.
class BoundCalculator {
public:
typedef std::pair<base::TimeTicks, base::TimeTicks> TimeTickPair;
typedef std::map<uint64, TimeTickPair> EventMap;
BoundCalculator();
~BoundCalculator();
bool has_bound() const { return has_bound_; }
base::TimeDelta bound() const { return bound_; }
void SetSent(uint32 rtp,
uint32 packet_id,
bool audio,
base::TimeTicks t);
void SetReceived(uint32 rtp,
uint16 packet_id,
bool audio,
base::TimeTicks t);
private:
void UpdateBound(base::TimeTicks a, base::TimeTicks b);
void CheckUpdate(uint64 key);
private:
EventMap events_;
bool has_bound_;
base::TimeDelta bound_;
}; };
typedef std::map<RtpTimestamp, EventTimes> EventTimesMap;
void UpdateOffsetBounds(const EventTimes& event);
// Fixed size storage to store event times for recent frames. // Fixed size storage to store event times for recent frames.
EventTimesMap event_times_map_; BoundCalculator upper_bound_;
BoundCalculator lower_bound_;
bool bounded_;
base::TickClock* clock_; // Not owned by this class.
bool offset_bounds_valid_;
base::TimeDelta offset_lower_bound_;
base::TimeDelta offset_upper_bound_;
base::TimeDelta prev_offset_lower_bound_;
base::TimeDelta prev_offset_upper_bound_;
base::TimeTicks last_reset_time_;
base::ThreadChecker thread_checker_; base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(ReceiverTimeOffsetEstimatorImpl); DISALLOW_COPY_AND_ASSIGN(ReceiverTimeOffsetEstimatorImpl);
......
...@@ -24,8 +24,7 @@ class ReceiverTimeOffsetEstimatorImplTest : public ::testing::Test { ...@@ -24,8 +24,7 @@ class ReceiverTimeOffsetEstimatorImplTest : public ::testing::Test {
scoped_ptr<base::TickClock>(sender_clock_).Pass(), scoped_ptr<base::TickClock>(sender_clock_).Pass(),
task_runner_, task_runner_,
task_runner_, task_runner_,
task_runner_)), task_runner_)) {
estimator_(cast_environment_->Clock()) {
cast_environment_->Logging()->AddRawEventSubscriber(&estimator_); cast_environment_->Logging()->AddRawEventSubscriber(&estimator_);
} }
...@@ -73,6 +72,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EstimateOffset) { ...@@ -73,6 +72,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EstimateOffset) {
true, true,
5678); 5678);
cast_environment_->Logging()->InsertPacketEvent(
sender_clock_->NowTicks(),
PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
rtp_timestamp,
frame_id,
56, 78, 1500);
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
...@@ -80,6 +86,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EstimateOffset) { ...@@ -80,6 +86,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EstimateOffset) {
receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
rtp_timestamp, frame_id); rtp_timestamp, frame_id);
cast_environment_->Logging()->InsertPacketEvent(
receiver_clock_.NowTicks(),
PACKET_RECEIVED, VIDEO_EVENT,
rtp_timestamp,
frame_id,
56, 78, 1500);
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
...@@ -122,6 +135,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) { ...@@ -122,6 +135,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) {
true, true,
5678); 5678);
cast_environment_->Logging()->InsertPacketEvent(
sender_clock_->NowTicks(),
PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
rtp_timestamp,
frame_id,
56, 78, 1500);
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
...@@ -134,6 +154,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) { ...@@ -134,6 +154,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) {
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
cast_environment_->Logging()->InsertPacketEvent(
event_b_time,
PACKET_RECEIVED, VIDEO_EVENT,
rtp_timestamp,
frame_id,
56, 78, 1500);
cast_environment_->Logging()->InsertFrameEvent( cast_environment_->Logging()->InsertFrameEvent(
event_b_time, FRAME_ACK_SENT, VIDEO_EVENT, rtp_timestamp, frame_id); event_b_time, FRAME_ACK_SENT, VIDEO_EVENT, rtp_timestamp, frame_id);
...@@ -176,6 +203,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) { ...@@ -176,6 +203,13 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) {
true, true,
5678); 5678);
cast_environment_->Logging()->InsertPacketEvent(
sender_clock_->NowTicks(),
PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
rtp_timestamp_a,
frame_id_a,
56, 78, 1500);
AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
cast_environment_->Logging()->InsertEncodedFrameEvent( cast_environment_->Logging()->InsertEncodedFrameEvent(
sender_clock_->NowTicks(), sender_clock_->NowTicks(),
...@@ -185,11 +219,27 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) { ...@@ -185,11 +219,27 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) {
1234, 1234,
true, true,
5678); 5678);
cast_environment_->Logging()->InsertPacketEvent(
sender_clock_->NowTicks(),
PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
rtp_timestamp_b,
frame_id_b,
56, 78, 1500);
cast_environment_->Logging()->InsertFrameEvent( cast_environment_->Logging()->InsertFrameEvent(
receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
rtp_timestamp_a, frame_id_a); rtp_timestamp_a, frame_id_a);
AdvanceClocks(base::TimeDelta::FromMilliseconds(20)); AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
cast_environment_->Logging()->InsertPacketEvent(
receiver_clock_.NowTicks(),
PACKET_RECEIVED, VIDEO_EVENT,
rtp_timestamp_b,
frame_id_b,
56, 78, 1500);
cast_environment_->Logging()->InsertFrameEvent( cast_environment_->Logging()->InsertFrameEvent(
receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
rtp_timestamp_b, frame_id_b); rtp_timestamp_b, frame_id_b);
...@@ -218,7 +268,21 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) { ...@@ -218,7 +268,21 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) {
true, true,
5678); 5678);
cast_environment_->Logging()->InsertPacketEvent(
sender_clock_->NowTicks(),
PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
rtp_timestamp_c,
frame_id_c,
56, 78, 1500);
AdvanceClocks(base::TimeDelta::FromMilliseconds(3)); AdvanceClocks(base::TimeDelta::FromMilliseconds(3));
cast_environment_->Logging()->InsertPacketEvent(
receiver_clock_.NowTicks(),
PACKET_RECEIVED, VIDEO_EVENT,
rtp_timestamp_c,
frame_id_c,
56, 78, 1500);
cast_environment_->Logging()->InsertFrameEvent( cast_environment_->Logging()->InsertFrameEvent(
receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT, receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
rtp_timestamp_c, frame_id_c); rtp_timestamp_c, frame_id_c);
...@@ -233,10 +297,10 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) { ...@@ -233,10 +297,10 @@ TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) {
EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound)); EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
int64 lower_bound_ms = lower_bound.InMilliseconds(); int64 lower_bound_ms = lower_bound.InMilliseconds();
int64 upper_bound_ms = upper_bound.InMilliseconds(); int64 upper_bound_ms = upper_bound.InMilliseconds();
EXPECT_EQ(95, lower_bound_ms); EXPECT_GT(lower_bound_ms, 90);
EXPECT_EQ(103, upper_bound_ms); EXPECT_LE(lower_bound_ms, true_offset_ms);
EXPECT_GE(true_offset_ms, lower_bound_ms); EXPECT_LT(upper_bound_ms, 150);
EXPECT_LE(true_offset_ms, upper_bound_ms); EXPECT_GT(upper_bound_ms, true_offset_ms);
} }
} // namespace cast } // namespace cast
......
...@@ -356,8 +356,7 @@ int main(int argc, char** argv) { ...@@ -356,8 +356,7 @@ int main(int argc, char** argv) {
// Subscribers for stats. // Subscribers for stats.
scoped_ptr<media::cast::ReceiverTimeOffsetEstimatorImpl> offset_estimator( scoped_ptr<media::cast::ReceiverTimeOffsetEstimatorImpl> offset_estimator(
new media::cast::ReceiverTimeOffsetEstimatorImpl( new media::cast::ReceiverTimeOffsetEstimatorImpl());
cast_environment->Clock()));
cast_environment->Logging()->AddRawEventSubscriber(offset_estimator.get()); cast_environment->Logging()->AddRawEventSubscriber(offset_estimator.get());
scoped_ptr<media::cast::StatsEventSubscriber> video_stats_subscriber( scoped_ptr<media::cast::StatsEventSubscriber> video_stats_subscriber(
new media::cast::StatsEventSubscriber(media::cast::VIDEO_EVENT, new media::cast::StatsEventSubscriber(media::cast::VIDEO_EVENT,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment