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