| OLD | NEW | 
|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <stdint.h> |  | 
| 6 |  | 
| 7 #include "base/bind.h" | 5 #include "base/bind.h" | 
| 8 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" | 
| 9 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" | 
| 10 #include "base/test/simple_test_tick_clock.h" | 8 #include "base/test/simple_test_tick_clock.h" | 
| 11 #include "media/cast/cast_defines.h" | 9 #include "media/cast/cast_defines.h" | 
| 12 #include "media/cast/cast_environment.h" | 10 #include "media/cast/cast_environment.h" | 
| 13 #include "media/cast/logging/simple_event_subscriber.h" | 11 #include "media/cast/logging/simple_event_subscriber.h" | 
| 14 #include "media/cast/test/fake_single_thread_task_runner.h" | 12 #include "media/cast/test/fake_single_thread_task_runner.h" | 
| 15 #include "media/cast/transport/pacing/mock_paced_packet_sender.h" | 13 #include "media/cast/transport/pacing/mock_paced_packet_sender.h" | 
| 16 #include "media/cast/video_receiver/video_receiver.h" | 14 #include "media/cast/video_receiver/video_receiver.h" | 
| 17 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" | 
| 18 | 16 | 
| 19 static const int kPacketSize = 1500; |  | 
| 20 static const int64 kStartMillisecond = INT64_C(12345678900000); |  | 
| 21 |  | 
| 22 namespace media { | 17 namespace media { | 
| 23 namespace cast { | 18 namespace cast { | 
| 24 | 19 | 
| 25 using testing::_; | 20 using ::testing::_; | 
| 26 | 21 | 
| 27 namespace { | 22 namespace { | 
| 28 // Was thread counted thread safe. | 23 | 
| 29 class TestVideoReceiverCallback | 24 const int kPacketSize = 1500; | 
| 30     : public base::RefCountedThreadSafe<TestVideoReceiverCallback> { | 25 const int64 kStartMillisecond = INT64_C(12345678900000); | 
|  | 26 const uint32 kFirstFrameId = 1234; | 
|  | 27 | 
|  | 28 class FakeVideoClient { | 
| 31  public: | 29  public: | 
| 32   TestVideoReceiverCallback() : num_called_(0) {} | 30   FakeVideoClient() : num_called_(0) {} | 
|  | 31   virtual ~FakeVideoClient() {} | 
| 33 | 32 | 
| 34   // TODO(mikhal): Set and check expectations. | 33   void SetNextExpectedResult(uint32 expected_frame_id, | 
| 35   void DecodeComplete(const scoped_refptr<media::VideoFrame>& video_frame, | 34                              const base::TimeTicks& expected_playout_time) { | 
| 36                       const base::TimeTicks& render_time) { | 35     expected_frame_id_ = expected_frame_id; | 
| 37     ++num_called_; | 36     expected_playout_time_ = expected_playout_time; | 
| 38   } | 37   } | 
| 39 | 38 | 
| 40   void FrameToDecode(scoped_ptr<transport::EncodedVideoFrame> video_frame, | 39   void DeliverEncodedVideoFrame( | 
| 41                      const base::TimeTicks& render_time) { | 40       scoped_ptr<transport::EncodedVideoFrame> video_frame, | 
| 42     EXPECT_TRUE(video_frame->key_frame); | 41       const base::TimeTicks& playout_time) { | 
|  | 42     ASSERT_FALSE(!video_frame) | 
|  | 43         << "If at shutdown: There were unsatisfied requests enqueued."; | 
|  | 44     EXPECT_EQ(expected_frame_id_, video_frame->frame_id); | 
| 43     EXPECT_EQ(transport::kVp8, video_frame->codec); | 45     EXPECT_EQ(transport::kVp8, video_frame->codec); | 
|  | 46     EXPECT_EQ(expected_playout_time_, playout_time); | 
| 44     ++num_called_; | 47     ++num_called_; | 
| 45   } | 48   } | 
| 46 | 49 | 
| 47   int number_times_called() const { return num_called_; } | 50   int number_times_called() const { return num_called_; } | 
| 48 | 51 | 
| 49  protected: | 52  private: | 
| 50   virtual ~TestVideoReceiverCallback() {} | 53   int num_called_; | 
|  | 54   uint32 expected_frame_id_; | 
|  | 55   base::TimeTicks expected_playout_time_; | 
| 51 | 56 | 
| 52  private: | 57   DISALLOW_COPY_AND_ASSIGN(FakeVideoClient); | 
| 53   friend class base::RefCountedThreadSafe<TestVideoReceiverCallback>; |  | 
| 54 |  | 
| 55   int num_called_; |  | 
| 56 |  | 
| 57   DISALLOW_COPY_AND_ASSIGN(TestVideoReceiverCallback); |  | 
| 58 }; | 58 }; | 
| 59 }  // namespace | 59 }  // namespace | 
| 60 | 60 | 
| 61 class VideoReceiverTest : public ::testing::Test { | 61 class VideoReceiverTest : public ::testing::Test { | 
| 62  protected: | 62  protected: | 
| 63   VideoReceiverTest() { | 63   VideoReceiverTest() { | 
| 64     // Configure to use vp8 software implementation. | 64     // Configure to use vp8 software implementation. | 
|  | 65     config_.rtp_max_delay_ms = 100; | 
|  | 66     config_.use_external_decoder = false; | 
|  | 67     // Note: Frame rate must divide 1000 without remainder so the test code | 
|  | 68     // doesn't have to account for rounding errors. | 
|  | 69     config_.max_frame_rate = 25; | 
| 65     config_.codec = transport::kVp8; | 70     config_.codec = transport::kVp8; | 
| 66     config_.use_external_decoder = false; |  | 
| 67     testing_clock_ = new base::SimpleTestTickClock(); | 71     testing_clock_ = new base::SimpleTestTickClock(); | 
|  | 72     testing_clock_->Advance( | 
|  | 73         base::TimeDelta::FromMilliseconds(kStartMillisecond)); | 
| 68     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); | 74     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); | 
|  | 75 | 
| 69     cast_environment_ = | 76     cast_environment_ = | 
| 70         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(), | 77         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(), | 
| 71                             task_runner_, | 78                             task_runner_, | 
| 72                             task_runner_, | 79                             task_runner_, | 
| 73                             task_runner_); | 80                             task_runner_); | 
|  | 81 | 
| 74     receiver_.reset(new VideoReceiver( | 82     receiver_.reset(new VideoReceiver( | 
| 75         cast_environment_, config_, &mock_transport_, target_delay_cb_)); | 83         cast_environment_, config_, &mock_transport_)); | 
| 76     testing_clock_->Advance( | 84   } | 
| 77         base::TimeDelta::FromMilliseconds(kStartMillisecond)); |  | 
| 78     video_receiver_callback_ = new TestVideoReceiverCallback(); |  | 
| 79 | 85 | 
|  | 86   virtual ~VideoReceiverTest() {} | 
|  | 87 | 
|  | 88   virtual void SetUp() { | 
| 80     payload_.assign(kPacketSize, 0); | 89     payload_.assign(kPacketSize, 0); | 
| 81 | 90 | 
| 82     // Always start with a key frame. | 91     // Always start with a key frame. | 
| 83     rtp_header_.is_key_frame = true; | 92     rtp_header_.is_key_frame = true; | 
| 84     rtp_header_.frame_id = 1234; | 93     rtp_header_.frame_id = kFirstFrameId; | 
| 85     rtp_header_.packet_id = 0; | 94     rtp_header_.packet_id = 0; | 
| 86     rtp_header_.max_packet_id = 0; | 95     rtp_header_.max_packet_id = 0; | 
| 87     rtp_header_.is_reference = false; | 96     rtp_header_.is_reference = false; | 
| 88     rtp_header_.reference_frame_id = 0; | 97     rtp_header_.reference_frame_id = 0; | 
| 89     rtp_header_.webrtc.header.timestamp = 9000; | 98     rtp_header_.webrtc.header.timestamp = 0; | 
| 90   } | 99   } | 
| 91 | 100 | 
| 92   virtual ~VideoReceiverTest() {} | 101   void FeedOneFrameIntoReceiver() { | 
|  | 102     receiver_->OnReceivedPayloadData( | 
|  | 103         payload_.data(), payload_.size(), rtp_header_); | 
|  | 104   } | 
| 93 | 105 | 
| 94   transport::MockPacedPacketSender mock_transport_; |  | 
| 95   VideoReceiverConfig config_; | 106   VideoReceiverConfig config_; | 
| 96   scoped_ptr<VideoReceiver> receiver_; |  | 
| 97   std::vector<uint8> payload_; | 107   std::vector<uint8> payload_; | 
| 98   RtpCastHeader rtp_header_; | 108   RtpCastHeader rtp_header_; | 
| 99   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment. | 109   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment. | 
| 100 | 110   transport::MockPacedPacketSender mock_transport_; | 
| 101   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 111   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 
| 102   scoped_refptr<CastEnvironment> cast_environment_; | 112   scoped_refptr<CastEnvironment> cast_environment_; | 
| 103   scoped_refptr<TestVideoReceiverCallback> video_receiver_callback_; | 113   FakeVideoClient fake_video_client_; | 
| 104   SetTargetDelayCallback target_delay_cb_; | 114 | 
|  | 115   // Important for the VideoReceiver to be declared last, since its dependencies | 
|  | 116   // must remain alive until after its destruction. | 
|  | 117   scoped_ptr<VideoReceiver> receiver_; | 
| 105 | 118 | 
| 106   DISALLOW_COPY_AND_ASSIGN(VideoReceiverTest); | 119   DISALLOW_COPY_AND_ASSIGN(VideoReceiverTest); | 
| 107 }; | 120 }; | 
| 108 | 121 | 
| 109 TEST_F(VideoReceiverTest, GetOnePacketEncodedframe) { | 122 TEST_F(VideoReceiverTest, GetOnePacketEncodedFrame) { | 
| 110   EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) |  | 
| 111       .WillRepeatedly(testing::Return(true)); |  | 
| 112   receiver_->OnReceivedPayloadData( |  | 
| 113       payload_.data(), payload_.size(), rtp_header_); |  | 
| 114 |  | 
| 115   VideoFrameEncodedCallback frame_to_decode_callback = base::Bind( |  | 
| 116       &TestVideoReceiverCallback::FrameToDecode, video_receiver_callback_); |  | 
| 117 |  | 
| 118   receiver_->GetEncodedVideoFrame(frame_to_decode_callback); |  | 
| 119   task_runner_->RunTasks(); |  | 
| 120   EXPECT_EQ(video_receiver_callback_->number_times_called(), 1); |  | 
| 121 } |  | 
| 122 |  | 
| 123 TEST_F(VideoReceiverTest, MultiplePackets) { |  | 
| 124   SimpleEventSubscriber event_subscriber; | 123   SimpleEventSubscriber event_subscriber; | 
| 125   cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); | 124   cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); | 
| 126 | 125 | 
| 127   EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 126   EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 
| 128       .WillRepeatedly(testing::Return(true)); | 127       .WillRepeatedly(testing::Return(true)); | 
| 129   rtp_header_.max_packet_id = 2; |  | 
| 130   receiver_->OnReceivedPayloadData( |  | 
| 131       payload_.data(), payload_.size(), rtp_header_); |  | 
| 132   ++rtp_header_.packet_id; |  | 
| 133   ++rtp_header_.webrtc.header.sequenceNumber; |  | 
| 134   receiver_->OnReceivedPayloadData( |  | 
| 135       payload_.data(), payload_.size(), rtp_header_); |  | 
| 136   ++rtp_header_.packet_id; |  | 
| 137   receiver_->OnReceivedPayloadData( |  | 
| 138       payload_.data(), payload_.size(), rtp_header_); |  | 
| 139 | 128 | 
| 140   VideoFrameEncodedCallback frame_to_decode_callback = base::Bind( | 129   // Enqueue a request for a video frame. | 
| 141       &TestVideoReceiverCallback::FrameToDecode, video_receiver_callback_); | 130   receiver_->GetEncodedVideoFrame( | 
|  | 131       base::Bind(&FakeVideoClient::DeliverEncodedVideoFrame, | 
|  | 132                  base::Unretained(&fake_video_client_))); | 
| 142 | 133 | 
| 143   receiver_->GetEncodedVideoFrame(frame_to_decode_callback); | 134   // The request should not be satisfied since no packets have been received. | 
|  | 135   task_runner_->RunTasks(); | 
|  | 136   EXPECT_EQ(0, fake_video_client_.number_times_called()); | 
| 144 | 137 | 
|  | 138   // Deliver one video frame to the receiver and expect to get one frame back. | 
|  | 139   fake_video_client_.SetNextExpectedResult(kFirstFrameId, | 
|  | 140                                            testing_clock_->NowTicks()); | 
|  | 141   FeedOneFrameIntoReceiver(); | 
| 145   task_runner_->RunTasks(); | 142   task_runner_->RunTasks(); | 
| 146   EXPECT_EQ(video_receiver_callback_->number_times_called(), 1); | 143   EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
| 147 | 144 | 
| 148   std::vector<FrameEvent> frame_events; | 145   std::vector<FrameEvent> frame_events; | 
| 149   event_subscriber.GetFrameEventsAndReset(&frame_events); | 146   event_subscriber.GetFrameEventsAndReset(&frame_events); | 
| 150 | 147 | 
| 151   ASSERT_TRUE(!frame_events.empty()); | 148   ASSERT_TRUE(!frame_events.empty()); | 
| 152   EXPECT_EQ(kVideoAckSent, frame_events.begin()->type); | 149   EXPECT_EQ(kVideoAckSent, frame_events.begin()->type); | 
| 153   EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id); | 150   EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id); | 
| 154   EXPECT_EQ(rtp_header_.webrtc.header.timestamp, | 151   EXPECT_EQ(rtp_header_.webrtc.header.timestamp, | 
| 155             frame_events.begin()->rtp_timestamp); | 152             frame_events.begin()->rtp_timestamp); | 
|  | 153 | 
| 156   cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); | 154   cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); | 
| 157 } | 155 } | 
| 158 | 156 | 
| 159 TEST_F(VideoReceiverTest, GetOnePacketRawframe) { | 157 TEST_F(VideoReceiverTest, MultiplePendingGetCalls) { | 
| 160   EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 158   EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) | 
| 161       .WillRepeatedly(testing::Return(true)); | 159       .WillRepeatedly(testing::Return(true)); | 
| 162   receiver_->OnReceivedPayloadData( | 160 | 
| 163       payload_.data(), payload_.size(), rtp_header_); | 161   // Enqueue a request for an video frame. | 
| 164   // Decode error - requires legal input. | 162   const VideoFrameEncodedCallback frame_encoded_callback = | 
| 165   VideoFrameDecodedCallback frame_decoded_callback = base::Bind( | 163       base::Bind(&FakeVideoClient::DeliverEncodedVideoFrame, | 
| 166       &TestVideoReceiverCallback::DecodeComplete, video_receiver_callback_); | 164                  base::Unretained(&fake_video_client_)); | 
| 167   receiver_->GetRawVideoFrame(frame_decoded_callback); | 165   receiver_->GetEncodedVideoFrame(frame_encoded_callback); | 
| 168   task_runner_->RunTasks(); | 166   task_runner_->RunTasks(); | 
| 169   EXPECT_EQ(video_receiver_callback_->number_times_called(), 0); | 167   EXPECT_EQ(0, fake_video_client_.number_times_called()); | 
|  | 168 | 
|  | 169   // Receive one video frame and expect to see the first request satisfied. | 
|  | 170   fake_video_client_.SetNextExpectedResult(kFirstFrameId, | 
|  | 171                                            testing_clock_->NowTicks()); | 
|  | 172   const base::TimeTicks time_at_first_frame_feed = testing_clock_->NowTicks(); | 
|  | 173   FeedOneFrameIntoReceiver(); | 
|  | 174   task_runner_->RunTasks(); | 
|  | 175   EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
|  | 176 | 
|  | 177   testing_clock_->Advance( | 
|  | 178       base::TimeDelta::FromSeconds(1) / config_.max_frame_rate); | 
|  | 179 | 
|  | 180   // Enqueue a second request for an video frame, but it should not be | 
|  | 181   // fulfilled yet. | 
|  | 182   receiver_->GetEncodedVideoFrame(frame_encoded_callback); | 
|  | 183   task_runner_->RunTasks(); | 
|  | 184   EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
|  | 185 | 
|  | 186   // Receive one video frame out-of-order: Make sure that we are not continuous | 
|  | 187   // and that the RTP timestamp represents a time in the future. | 
|  | 188   rtp_header_.is_key_frame = false; | 
|  | 189   rtp_header_.frame_id = kFirstFrameId + 2; | 
|  | 190   rtp_header_.is_reference = true; | 
|  | 191   rtp_header_.reference_frame_id = 0; | 
|  | 192   rtp_header_.webrtc.header.timestamp += | 
|  | 193       config_.rtp_max_delay_ms * kVideoFrequency / 1000; | 
|  | 194   fake_video_client_.SetNextExpectedResult( | 
|  | 195       kFirstFrameId + 2, | 
|  | 196       time_at_first_frame_feed + | 
|  | 197           base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms)); | 
|  | 198   FeedOneFrameIntoReceiver(); | 
|  | 199 | 
|  | 200   // Frame 2 should not come out at this point in time. | 
|  | 201   task_runner_->RunTasks(); | 
|  | 202   EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
|  | 203 | 
|  | 204   // Enqueue a third request for an video frame. | 
|  | 205   receiver_->GetEncodedVideoFrame(frame_encoded_callback); | 
|  | 206   task_runner_->RunTasks(); | 
|  | 207   EXPECT_EQ(1, fake_video_client_.number_times_called()); | 
|  | 208 | 
|  | 209   // After |rtp_max_delay_ms| has elapsed, Frame 2 is emitted (to satisfy the | 
|  | 210   // second request) because a decision was made to skip over the no-show Frame | 
|  | 211   // 1. | 
|  | 212   testing_clock_->Advance( | 
|  | 213       base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms)); | 
|  | 214   task_runner_->RunTasks(); | 
|  | 215   EXPECT_EQ(2, fake_video_client_.number_times_called()); | 
|  | 216 | 
|  | 217   // Receive Frame 3 and expect it to fulfill the third request immediately. | 
|  | 218   rtp_header_.frame_id = kFirstFrameId + 3; | 
|  | 219   rtp_header_.is_reference = false; | 
|  | 220   rtp_header_.reference_frame_id = 0; | 
|  | 221   rtp_header_.webrtc.header.timestamp += | 
|  | 222       kVideoFrequency / config_.max_frame_rate; | 
|  | 223   fake_video_client_.SetNextExpectedResult(kFirstFrameId + 3, | 
|  | 224                                            testing_clock_->NowTicks()); | 
|  | 225   FeedOneFrameIntoReceiver(); | 
|  | 226   task_runner_->RunTasks(); | 
|  | 227   EXPECT_EQ(3, fake_video_client_.number_times_called()); | 
|  | 228 | 
|  | 229   // Move forward another |rtp_max_delay_ms| and run any pending tasks (there | 
|  | 230   // should be none).  Expect no additional frames where emitted. | 
|  | 231   testing_clock_->Advance( | 
|  | 232       base::TimeDelta::FromMilliseconds(config_.rtp_max_delay_ms)); | 
|  | 233   task_runner_->RunTasks(); | 
|  | 234   EXPECT_EQ(3, fake_video_client_.number_times_called()); | 
| 170 } | 235 } | 
| 171 | 236 | 
| 172 // TODO(pwestin): add encoded frames. |  | 
| 173 |  | 
| 174 }  // namespace cast | 237 }  // namespace cast | 
| 175 }  // namespace media | 238 }  // namespace media | 
| OLD | NEW | 
|---|