| Index: media/cast/video_receiver/video_receiver_unittest.cc | 
| diff --git a/media/cast/video_receiver/video_receiver_unittest.cc b/media/cast/video_receiver/video_receiver_unittest.cc | 
| index 7bea5013201821f60e934d4451c6f3bd11a214c9..4fe834ce889fb4d7b7f875c12422995dfcb86094 100644 | 
| --- a/media/cast/video_receiver/video_receiver_unittest.cc | 
| +++ b/media/cast/video_receiver/video_receiver_unittest.cc | 
| @@ -2,8 +2,6 @@ | 
| // Use of this source code is governed by a BSD-style license that can be | 
| // found in the LICENSE file. | 
|  | 
| -#include <stdint.h> | 
| - | 
| #include "base/bind.h" | 
| #include "base/memory/ref_counted.h" | 
| #include "base/memory/scoped_ptr.h" | 
| @@ -16,45 +14,47 @@ | 
| #include "media/cast/video_receiver/video_receiver.h" | 
| #include "testing/gmock/include/gmock/gmock.h" | 
|  | 
| -static const int kPacketSize = 1500; | 
| -static const int64 kStartMillisecond = INT64_C(12345678900000); | 
| - | 
| namespace media { | 
| namespace cast { | 
|  | 
| -using testing::_; | 
| +using ::testing::_; | 
|  | 
| namespace { | 
| -// Was thread counted thread safe. | 
| -class TestVideoReceiverCallback | 
| -    : public base::RefCountedThreadSafe<TestVideoReceiverCallback> { | 
| + | 
| +const int kPacketSize = 1500; | 
| +const int64 kStartMillisecond = INT64_C(12345678900000); | 
| +const uint32 kFirstFrameId = 1234; | 
| + | 
| +class FakeVideoClient { | 
| public: | 
| -  TestVideoReceiverCallback() : num_called_(0) {} | 
| +  FakeVideoClient() : num_called_(0) {} | 
| +  virtual ~FakeVideoClient() {} | 
|  | 
| -  // TODO(mikhal): Set and check expectations. | 
| -  void DecodeComplete(const scoped_refptr<media::VideoFrame>& video_frame, | 
| -                      const base::TimeTicks& render_time) { | 
| -    ++num_called_; | 
| +  void SetNextExpectedResult(uint32 expected_frame_id, | 
| +                             const base::TimeTicks& expected_playout_time) { | 
| +    expected_frame_id_ = expected_frame_id; | 
| +    expected_playout_time_ = expected_playout_time; | 
| } | 
|  | 
| -  void FrameToDecode(scoped_ptr<transport::EncodedVideoFrame> video_frame, | 
| -                     const base::TimeTicks& render_time) { | 
| -    EXPECT_TRUE(video_frame->key_frame); | 
| +  void DeliverEncodedVideoFrame( | 
| +      scoped_ptr<transport::EncodedVideoFrame> video_frame, | 
| +      const base::TimeTicks& playout_time) { | 
| +    ASSERT_FALSE(!video_frame) | 
| +        << "If at shutdown: There were unsatisfied requests enqueued."; | 
| +    EXPECT_EQ(expected_frame_id_, video_frame->frame_id); | 
| EXPECT_EQ(transport::kVp8, video_frame->codec); | 
| +    EXPECT_EQ(expected_playout_time_, playout_time); | 
| ++num_called_; | 
| } | 
|  | 
| int number_times_called() const { return num_called_; } | 
|  | 
| - protected: | 
| -  virtual ~TestVideoReceiverCallback() {} | 
| - | 
| private: | 
| -  friend class base::RefCountedThreadSafe<TestVideoReceiverCallback>; | 
| - | 
| int num_called_; | 
| +  uint32 expected_frame_id_; | 
| +  base::TimeTicks expected_playout_time_; | 
|  | 
| -  DISALLOW_COPY_AND_ASSIGN(TestVideoReceiverCallback); | 
| +  DISALLOW_COPY_AND_ASSIGN(FakeVideoClient); | 
| }; | 
| }  // namespace | 
|  | 
| @@ -62,88 +62,85 @@ class VideoReceiverTest : public ::testing::Test { | 
| protected: | 
| VideoReceiverTest() { | 
| // Configure to use vp8 software implementation. | 
| -    config_.codec = transport::kVp8; | 
| +    config_.rtp_max_delay_ms = 100; | 
| config_.use_external_decoder = false; | 
| +    // Note: Frame rate must divide 1000 without remainder so the test code | 
| +    // doesn't have to account for rounding errors. | 
| +    config_.max_frame_rate = 25; | 
| +    config_.codec = transport::kVp8; | 
| testing_clock_ = new base::SimpleTestTickClock(); | 
| +    testing_clock_->Advance( | 
| +        base::TimeDelta::FromMilliseconds(kStartMillisecond)); | 
| task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); | 
| + | 
| cast_environment_ = | 
| new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(), | 
| task_runner_, | 
| task_runner_, | 
| task_runner_); | 
| + | 
| receiver_.reset(new VideoReceiver( | 
| -        cast_environment_, config_, &mock_transport_, target_delay_cb_)); | 
| -    testing_clock_->Advance( | 
| -        base::TimeDelta::FromMilliseconds(kStartMillisecond)); | 
| -    video_receiver_callback_ = new TestVideoReceiverCallback(); | 
| +        cast_environment_, config_, &mock_transport_)); | 
| +  } | 
|  | 
| +  virtual ~VideoReceiverTest() {} | 
| + | 
| +  virtual void SetUp() { | 
| payload_.assign(kPacketSize, 0); | 
|  | 
| // Always start with a key frame. | 
| rtp_header_.is_key_frame = true; | 
| -    rtp_header_.frame_id = 1234; | 
| +    rtp_header_.frame_id = kFirstFrameId; | 
| rtp_header_.packet_id = 0; | 
| rtp_header_.max_packet_id = 0; | 
| rtp_header_.is_reference = false; | 
| rtp_header_.reference_frame_id = 0; | 
| -    rtp_header_.webrtc.header.timestamp = 9000; | 
| +    rtp_header_.webrtc.header.timestamp = 0; | 
| } | 
|  | 
| -  virtual ~VideoReceiverTest() {} | 
| +  void FeedOneFrameIntoReceiver() { | 
| +    receiver_->OnReceivedPayloadData( | 
| +        payload_.data(), payload_.size(), rtp_header_); | 
| +  } | 
|  | 
| -  transport::MockPacedPacketSender mock_transport_; | 
| VideoReceiverConfig config_; | 
| -  scoped_ptr<VideoReceiver> receiver_; | 
| std::vector<uint8> payload_; | 
| RtpCastHeader rtp_header_; | 
| base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment. | 
| - | 
| +  transport::MockPacedPacketSender mock_transport_; | 
| scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 
| scoped_refptr<CastEnvironment> cast_environment_; | 
| -  scoped_refptr<TestVideoReceiverCallback> video_receiver_callback_; | 
| -  SetTargetDelayCallback target_delay_cb_; | 
| +  FakeVideoClient fake_video_client_; | 
| + | 
| +  // Important for the VideoReceiver to be declared last, since its dependencies | 
| +  // must remain alive until after its destruction. | 
| +  scoped_ptr<VideoReceiver> receiver_; | 
|  | 
| DISALLOW_COPY_AND_ASSIGN(VideoReceiverTest); | 
| }; | 
|  | 
| -TEST_F(VideoReceiverTest, GetOnePacketEncodedframe) { | 
| -  EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 
| -      .WillRepeatedly(testing::Return(true)); | 
| -  receiver_->OnReceivedPayloadData( | 
| -      payload_.data(), payload_.size(), rtp_header_); | 
| - | 
| -  VideoFrameEncodedCallback frame_to_decode_callback = base::Bind( | 
| -      &TestVideoReceiverCallback::FrameToDecode, video_receiver_callback_); | 
| - | 
| -  receiver_->GetEncodedVideoFrame(frame_to_decode_callback); | 
| -  task_runner_->RunTasks(); | 
| -  EXPECT_EQ(video_receiver_callback_->number_times_called(), 1); | 
| -} | 
| - | 
| -TEST_F(VideoReceiverTest, MultiplePackets) { | 
| +TEST_F(VideoReceiverTest, GetOnePacketEncodedFrame) { | 
| SimpleEventSubscriber event_subscriber; | 
| cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); | 
|  | 
| EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 
| .WillRepeatedly(testing::Return(true)); | 
| -  rtp_header_.max_packet_id = 2; | 
| -  receiver_->OnReceivedPayloadData( | 
| -      payload_.data(), payload_.size(), rtp_header_); | 
| -  ++rtp_header_.packet_id; | 
| -  ++rtp_header_.webrtc.header.sequenceNumber; | 
| -  receiver_->OnReceivedPayloadData( | 
| -      payload_.data(), payload_.size(), rtp_header_); | 
| -  ++rtp_header_.packet_id; | 
| -  receiver_->OnReceivedPayloadData( | 
| -      payload_.data(), payload_.size(), rtp_header_); | 
| - | 
| -  VideoFrameEncodedCallback frame_to_decode_callback = base::Bind( | 
| -      &TestVideoReceiverCallback::FrameToDecode, video_receiver_callback_); | 
| - | 
| -  receiver_->GetEncodedVideoFrame(frame_to_decode_callback); | 
|  | 
| +  // Enqueue a request for a video frame. | 
| +  receiver_->GetEncodedVideoFrame( | 
| +      base::Bind(&FakeVideoClient::DeliverEncodedVideoFrame, | 
| +                 base::Unretained(&fake_video_client_))); | 
| + | 
| +  // The request should not be satisfied since no packets have been received. | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(0, fake_video_client_.number_times_called()); | 
| + | 
| +  // Deliver one video frame to the receiver and expect to get one frame back. | 
| +  fake_video_client_.SetNextExpectedResult(kFirstFrameId, | 
| +                                           testing_clock_->NowTicks()); | 
| +  FeedOneFrameIntoReceiver(); | 
| task_runner_->RunTasks(); | 
| -  EXPECT_EQ(video_receiver_callback_->number_times_called(), 1); | 
| +  EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
|  | 
| std::vector<FrameEvent> frame_events; | 
| event_subscriber.GetFrameEventsAndReset(&frame_events); | 
| @@ -153,23 +150,89 @@ TEST_F(VideoReceiverTest, MultiplePackets) { | 
| EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id); | 
| EXPECT_EQ(rtp_header_.webrtc.header.timestamp, | 
| frame_events.begin()->rtp_timestamp); | 
| + | 
| cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); | 
| } | 
|  | 
| -TEST_F(VideoReceiverTest, GetOnePacketRawframe) { | 
| +TEST_F(VideoReceiverTest, MultiplePendingGetCalls) { | 
| EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 
| .WillRepeatedly(testing::Return(true)); | 
| -  receiver_->OnReceivedPayloadData( | 
| -      payload_.data(), payload_.size(), rtp_header_); | 
| -  // Decode error - requires legal input. | 
| -  VideoFrameDecodedCallback frame_decoded_callback = base::Bind( | 
| -      &TestVideoReceiverCallback::DecodeComplete, video_receiver_callback_); | 
| -  receiver_->GetRawVideoFrame(frame_decoded_callback); | 
| + | 
| +  // Enqueue a request for an video frame. | 
| +  const VideoFrameEncodedCallback frame_encoded_callback = | 
| +      base::Bind(&FakeVideoClient::DeliverEncodedVideoFrame, | 
| +                 base::Unretained(&fake_video_client_)); | 
| +  receiver_->GetEncodedVideoFrame(frame_encoded_callback); | 
| task_runner_->RunTasks(); | 
| -  EXPECT_EQ(video_receiver_callback_->number_times_called(), 0); | 
| -} | 
| +  EXPECT_EQ(0, fake_video_client_.number_times_called()); | 
|  | 
| -// TODO(pwestin): add encoded frames. | 
| +  // Receive one video frame and expect to see the first request satisfied. | 
| +  fake_video_client_.SetNextExpectedResult(kFirstFrameId, | 
| +                                           testing_clock_->NowTicks()); | 
| +  const base::TimeTicks time_at_first_frame_feed = testing_clock_->NowTicks(); | 
| +  FeedOneFrameIntoReceiver(); | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
| + | 
| +  testing_clock_->Advance( | 
| +      base::TimeDelta::FromSeconds(1) / config_.max_frame_rate); | 
| + | 
| +  // Enqueue a second request for an video frame, but it should not be | 
| +  // fulfilled yet. | 
| +  receiver_->GetEncodedVideoFrame(frame_encoded_callback); | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
| + | 
| +  // Receive one video frame out-of-order: Make sure that we are not continuous | 
| +  // and that the RTP timestamp represents a time in the future. | 
| +  rtp_header_.is_key_frame = false; | 
| +  rtp_header_.frame_id = kFirstFrameId + 2; | 
| +  rtp_header_.is_reference = true; | 
| +  rtp_header_.reference_frame_id = 0; | 
| +  rtp_header_.webrtc.header.timestamp += | 
| +      config_.rtp_max_delay_ms * kVideoFrequency / 1000; | 
| +  fake_video_client_.SetNextExpectedResult( | 
| +      kFirstFrameId + 2, | 
| +      time_at_first_frame_feed + | 
| +          base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms)); | 
| +  FeedOneFrameIntoReceiver(); | 
| + | 
| +  // Frame 2 should not come out at this point in time. | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
| + | 
| +  // Enqueue a third request for an video frame. | 
| +  receiver_->GetEncodedVideoFrame(frame_encoded_callback); | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
| + | 
| +  // After |rtp_max_delay_ms| has elapsed, Frame 2 is emitted (to satisfy the | 
| +  // second request) because a decision was made to skip over the no-show Frame | 
| +  // 1. | 
| +  testing_clock_->Advance( | 
| +      base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms)); | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(2, fake_video_client_.number_times_called()); | 
| + | 
| +  // Receive Frame 3 and expect it to fulfill the third request immediately. | 
| +  rtp_header_.frame_id = kFirstFrameId + 3; | 
| +  rtp_header_.is_reference = false; | 
| +  rtp_header_.reference_frame_id = 0; | 
| +  rtp_header_.webrtc.header.timestamp += | 
| +      kVideoFrequency / config_.max_frame_rate; | 
| +  fake_video_client_.SetNextExpectedResult(kFirstFrameId + 3, | 
| +                                           testing_clock_->NowTicks()); | 
| +  FeedOneFrameIntoReceiver(); | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(3, fake_video_client_.number_times_called()); | 
| + | 
| +  // Move forward another |rtp_max_delay_ms| and run any pending tasks (there | 
| +  // should be none).  Expect no additional frames where emitted. | 
| +  testing_clock_->Advance( | 
| +      base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms)); | 
| +  task_runner_->RunTasks(); | 
| +  EXPECT_EQ(3, fake_video_client_.number_times_called()); | 
| +} | 
|  | 
| }  // namespace cast | 
| }  // namespace media | 
|  |