| 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 |