Cleanup: Pass std::string as const reference from chromeos/
[chromium-blink-merge.git] / media / cast / receiver / frame_receiver_unittest.cc
bloba92b93a73cd802c030151b27212a0a7b17e98dc0
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <deque>
6 #include <utility>
8 #include "base/bind.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "media/cast/cast_defines.h"
13 #include "media/cast/cast_environment.h"
14 #include "media/cast/logging/simple_event_subscriber.h"
15 #include "media/cast/net/cast_transport_sender_impl.h"
16 #include "media/cast/net/mock_cast_transport_sender.h"
17 #include "media/cast/net/rtcp/test_rtcp_packet_builder.h"
18 #include "media/cast/receiver/frame_receiver.h"
19 #include "media/cast/test/fake_single_thread_task_runner.h"
20 #include "media/cast/test/utility/default_config.h"
21 #include "testing/gmock/include/gmock/gmock.h"
23 using ::testing::_;
25 namespace media {
26 namespace cast {
28 namespace {
30 const int kPacketSize = 1500;
31 const uint32 kFirstFrameId = 1234;
32 const int kPlayoutDelayMillis = 100;
34 class FakeFrameClient {
35 public:
36 FakeFrameClient() : num_called_(0) {}
37 virtual ~FakeFrameClient() {}
39 void AddExpectedResult(uint32 expected_frame_id,
40 const base::TimeTicks& expected_playout_time) {
41 expected_results_.push_back(
42 std::make_pair(expected_frame_id, expected_playout_time));
45 void DeliverEncodedFrame(scoped_ptr<EncodedFrame> frame) {
46 SCOPED_TRACE(::testing::Message() << "num_called_ is " << num_called_);
47 ASSERT_TRUE(frame)
48 << "If at shutdown: There were unsatisfied requests enqueued.";
49 ASSERT_FALSE(expected_results_.empty());
50 EXPECT_EQ(expected_results_.front().first, frame->frame_id);
51 EXPECT_EQ(expected_results_.front().second, frame->reference_time);
52 expected_results_.pop_front();
53 ++num_called_;
56 int number_times_called() const { return num_called_; }
58 private:
59 std::deque<std::pair<uint32, base::TimeTicks> > expected_results_;
60 int num_called_;
62 DISALLOW_COPY_AND_ASSIGN(FakeFrameClient);
64 } // namespace
66 class FrameReceiverTest : public ::testing::Test {
67 protected:
68 FrameReceiverTest() {
69 testing_clock_ = new base::SimpleTestTickClock();
70 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
71 start_time_ = testing_clock_->NowTicks();
72 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
74 cast_environment_ =
75 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
76 task_runner_,
77 task_runner_,
78 task_runner_);
81 ~FrameReceiverTest() override {}
83 void SetUp() final {
84 payload_.assign(kPacketSize, 0);
86 // Always start with a key frame.
87 rtp_header_.is_key_frame = true;
88 rtp_header_.frame_id = kFirstFrameId;
89 rtp_header_.packet_id = 0;
90 rtp_header_.max_packet_id = 0;
91 rtp_header_.reference_frame_id = rtp_header_.frame_id;
92 rtp_header_.rtp_timestamp = 0;
95 void CreateFrameReceiverOfAudio() {
96 config_ = GetDefaultAudioReceiverConfig();
97 config_.rtp_max_delay_ms = kPlayoutDelayMillis;
99 receiver_.reset(new FrameReceiver(
100 cast_environment_, config_, AUDIO_EVENT, &mock_transport_));
103 void CreateFrameReceiverOfVideo() {
104 config_ = GetDefaultVideoReceiverConfig();
105 config_.rtp_max_delay_ms = kPlayoutDelayMillis;
106 // Note: Frame rate must divide 1000 without remainder so the test code
107 // doesn't have to account for rounding errors.
108 config_.target_frame_rate = 25;
110 receiver_.reset(new FrameReceiver(
111 cast_environment_, config_, VIDEO_EVENT, &mock_transport_));
114 void FeedOneFrameIntoReceiver() {
115 // Note: For testing purposes, a frame consists of only a single packet.
116 receiver_->ProcessParsedPacket(
117 rtp_header_, &payload_[0], payload_.size());
120 void FeedLipSyncInfoIntoReceiver() {
121 const base::TimeTicks now = testing_clock_->NowTicks();
122 const int64 rtp_timestamp = (now - start_time_) *
123 config_.rtp_timebase / base::TimeDelta::FromSeconds(1);
124 CHECK_LE(0, rtp_timestamp);
125 uint32 ntp_seconds;
126 uint32 ntp_fraction;
127 ConvertTimeTicksToNtp(now, &ntp_seconds, &ntp_fraction);
128 TestRtcpPacketBuilder rtcp_packet;
129 rtcp_packet.AddSrWithNtp(config_.sender_ssrc,
130 ntp_seconds, ntp_fraction,
131 static_cast<uint32>(rtp_timestamp));
132 ASSERT_TRUE(receiver_->ProcessPacket(rtcp_packet.GetPacket().Pass()));
135 FrameReceiverConfig config_;
136 std::vector<uint8> payload_;
137 RtpCastHeader rtp_header_;
138 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
139 base::TimeTicks start_time_;
140 MockCastTransportSender mock_transport_;
141 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
142 scoped_refptr<CastEnvironment> cast_environment_;
143 FakeFrameClient frame_client_;
145 // Important for the FrameReceiver to be declared last, since its dependencies
146 // must remain alive until after its destruction.
147 scoped_ptr<FrameReceiver> receiver_;
149 private:
150 DISALLOW_COPY_AND_ASSIGN(FrameReceiverTest);
153 TEST_F(FrameReceiverTest, RejectsUnparsablePackets) {
154 CreateFrameReceiverOfVideo();
156 SimpleEventSubscriber event_subscriber;
157 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
159 const bool success = receiver_->ProcessPacket(
160 scoped_ptr<Packet>(new Packet(kPacketSize, 0xff)).Pass());
161 EXPECT_FALSE(success);
163 // Confirm no log events.
164 std::vector<FrameEvent> frame_events;
165 event_subscriber.GetFrameEventsAndReset(&frame_events);
166 EXPECT_TRUE(frame_events.empty());
167 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
170 TEST_F(FrameReceiverTest, ReceivesOneFrame) {
171 CreateFrameReceiverOfAudio();
173 SimpleEventSubscriber event_subscriber;
174 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
176 EXPECT_CALL(mock_transport_, SendRtcpFromRtpReceiver(_, _, _, _, _, _, _))
177 .WillRepeatedly(testing::Return());
179 FeedLipSyncInfoIntoReceiver();
180 task_runner_->RunTasks();
182 // Enqueue a request for a frame.
183 receiver_->RequestEncodedFrame(
184 base::Bind(&FakeFrameClient::DeliverEncodedFrame,
185 base::Unretained(&frame_client_)));
187 // The request should not be satisfied since no packets have been received.
188 task_runner_->RunTasks();
189 EXPECT_EQ(0, frame_client_.number_times_called());
191 // Deliver one frame to the receiver and expect to get one frame back.
192 const base::TimeDelta target_playout_delay =
193 base::TimeDelta::FromMilliseconds(kPlayoutDelayMillis);
194 frame_client_.AddExpectedResult(
195 kFirstFrameId, testing_clock_->NowTicks() + target_playout_delay);
196 FeedOneFrameIntoReceiver();
197 task_runner_->RunTasks();
198 EXPECT_EQ(1, frame_client_.number_times_called());
200 // Was the frame logged?
201 std::vector<FrameEvent> frame_events;
202 event_subscriber.GetFrameEventsAndReset(&frame_events);
203 ASSERT_TRUE(!frame_events.empty());
204 EXPECT_EQ(FRAME_ACK_SENT, frame_events.begin()->type);
205 EXPECT_EQ(AUDIO_EVENT, frame_events.begin()->media_type);
206 EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id);
207 EXPECT_EQ(rtp_header_.rtp_timestamp, frame_events.begin()->rtp_timestamp);
208 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
211 TEST_F(FrameReceiverTest, ReceivesFramesSkippingWhenAppropriate) {
212 CreateFrameReceiverOfAudio();
214 SimpleEventSubscriber event_subscriber;
215 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
217 EXPECT_CALL(mock_transport_, SendRtcpFromRtpReceiver(_, _, _, _, _, _, _))
218 .WillRepeatedly(testing::Return());
220 const uint32 rtp_advance_per_frame =
221 config_.rtp_timebase / config_.target_frame_rate;
222 const base::TimeDelta time_advance_per_frame =
223 base::TimeDelta::FromSeconds(1) / config_.target_frame_rate;
225 // Feed and process lip sync in receiver.
226 FeedLipSyncInfoIntoReceiver();
227 task_runner_->RunTasks();
228 const base::TimeTicks first_frame_capture_time = testing_clock_->NowTicks();
230 // Enqueue a request for a frame.
231 const ReceiveEncodedFrameCallback frame_encoded_callback =
232 base::Bind(&FakeFrameClient::DeliverEncodedFrame,
233 base::Unretained(&frame_client_));
234 receiver_->RequestEncodedFrame(frame_encoded_callback);
235 task_runner_->RunTasks();
236 EXPECT_EQ(0, frame_client_.number_times_called());
238 // Receive one frame and expect to see the first request satisfied.
239 const base::TimeDelta target_playout_delay =
240 base::TimeDelta::FromMilliseconds(kPlayoutDelayMillis);
241 frame_client_.AddExpectedResult(
242 kFirstFrameId, first_frame_capture_time + target_playout_delay);
243 rtp_header_.rtp_timestamp = 0;
244 FeedOneFrameIntoReceiver(); // Frame 1
245 task_runner_->RunTasks();
246 EXPECT_EQ(1, frame_client_.number_times_called());
248 // Enqueue a second request for a frame, but it should not be fulfilled yet.
249 receiver_->RequestEncodedFrame(frame_encoded_callback);
250 task_runner_->RunTasks();
251 EXPECT_EQ(1, frame_client_.number_times_called());
253 // Receive one frame out-of-order: Make sure that we are not continuous and
254 // that the RTP timestamp represents a time in the future.
255 rtp_header_.frame_id = kFirstFrameId + 2; // "Frame 3"
256 rtp_header_.reference_frame_id = rtp_header_.frame_id;
257 rtp_header_.rtp_timestamp += 2 * rtp_advance_per_frame;
258 frame_client_.AddExpectedResult(
259 kFirstFrameId + 2,
260 first_frame_capture_time + 2 * time_advance_per_frame +
261 target_playout_delay);
262 FeedOneFrameIntoReceiver(); // Frame 3
264 // Frame 2 should not come out at this point in time.
265 task_runner_->RunTasks();
266 EXPECT_EQ(1, frame_client_.number_times_called());
268 // Enqueue a third request for a frame.
269 receiver_->RequestEncodedFrame(frame_encoded_callback);
270 task_runner_->RunTasks();
271 EXPECT_EQ(1, frame_client_.number_times_called());
273 // Now, advance time forward such that the receiver is convinced it should
274 // skip Frame 2. Frame 3 is emitted (to satisfy the second request) because a
275 // decision was made to skip over the no-show Frame 2.
276 testing_clock_->Advance(2 * time_advance_per_frame + target_playout_delay);
277 task_runner_->RunTasks();
278 EXPECT_EQ(2, frame_client_.number_times_called());
280 // Receive Frame 4 and expect it to fulfill the third request immediately.
281 rtp_header_.frame_id = kFirstFrameId + 3; // "Frame 4"
282 rtp_header_.reference_frame_id = rtp_header_.frame_id;
283 rtp_header_.rtp_timestamp += rtp_advance_per_frame;
284 frame_client_.AddExpectedResult(
285 kFirstFrameId + 3, first_frame_capture_time + 3 * time_advance_per_frame +
286 target_playout_delay);
287 FeedOneFrameIntoReceiver(); // Frame 4
288 task_runner_->RunTasks();
289 EXPECT_EQ(3, frame_client_.number_times_called());
291 // Move forward to the playout time of an unreceived Frame 5. Expect no
292 // additional frames were emitted.
293 testing_clock_->Advance(3 * time_advance_per_frame);
294 task_runner_->RunTasks();
295 EXPECT_EQ(3, frame_client_.number_times_called());
297 // Were only non-skipped frames logged?
298 std::vector<FrameEvent> frame_events;
299 event_subscriber.GetFrameEventsAndReset(&frame_events);
300 ASSERT_TRUE(!frame_events.empty());
301 for (size_t i = 0; i < frame_events.size(); ++i) {
302 EXPECT_EQ(FRAME_ACK_SENT, frame_events[i].type);
303 EXPECT_EQ(AUDIO_EVENT, frame_events[i].media_type);
304 EXPECT_LE(kFirstFrameId, frame_events[i].frame_id);
305 EXPECT_GE(kFirstFrameId + 4, frame_events[i].frame_id);
306 const int frame_offset = frame_events[i].frame_id - kFirstFrameId;
307 EXPECT_NE(frame_offset, 1); // Frame 2 never received.
308 EXPECT_EQ(frame_offset * rtp_advance_per_frame,
309 frame_events[i].rtp_timestamp);
311 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
314 TEST_F(FrameReceiverTest, ReceivesFramesRefusingToSkipAny) {
315 CreateFrameReceiverOfVideo();
317 SimpleEventSubscriber event_subscriber;
318 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
320 EXPECT_CALL(mock_transport_, SendRtcpFromRtpReceiver(_, _, _, _, _, _, _))
321 .WillRepeatedly(testing::Return());
323 const uint32 rtp_advance_per_frame =
324 config_.rtp_timebase / config_.target_frame_rate;
325 const base::TimeDelta time_advance_per_frame =
326 base::TimeDelta::FromSeconds(1) / config_.target_frame_rate;
328 // Feed and process lip sync in receiver.
329 FeedLipSyncInfoIntoReceiver();
330 task_runner_->RunTasks();
331 const base::TimeTicks first_frame_capture_time = testing_clock_->NowTicks();
333 // Enqueue a request for a frame.
334 const ReceiveEncodedFrameCallback frame_encoded_callback =
335 base::Bind(&FakeFrameClient::DeliverEncodedFrame,
336 base::Unretained(&frame_client_));
337 receiver_->RequestEncodedFrame(frame_encoded_callback);
338 task_runner_->RunTasks();
339 EXPECT_EQ(0, frame_client_.number_times_called());
341 // Receive one frame and expect to see the first request satisfied.
342 const base::TimeDelta target_playout_delay =
343 base::TimeDelta::FromMilliseconds(kPlayoutDelayMillis);
344 frame_client_.AddExpectedResult(
345 kFirstFrameId, first_frame_capture_time + target_playout_delay);
346 rtp_header_.rtp_timestamp = 0;
347 FeedOneFrameIntoReceiver(); // Frame 1
348 task_runner_->RunTasks();
349 EXPECT_EQ(1, frame_client_.number_times_called());
351 // Enqueue a second request for a frame, but it should not be fulfilled yet.
352 receiver_->RequestEncodedFrame(frame_encoded_callback);
353 task_runner_->RunTasks();
354 EXPECT_EQ(1, frame_client_.number_times_called());
356 // Receive one frame out-of-order: Make sure that we are not continuous and
357 // that the RTP timestamp represents a time in the future.
358 rtp_header_.is_key_frame = false;
359 rtp_header_.frame_id = kFirstFrameId + 2; // "Frame 3"
360 rtp_header_.reference_frame_id = kFirstFrameId + 1; // "Frame 2"
361 rtp_header_.rtp_timestamp += 2 * rtp_advance_per_frame;
362 FeedOneFrameIntoReceiver(); // Frame 3
364 // Frame 2 should not come out at this point in time.
365 task_runner_->RunTasks();
366 EXPECT_EQ(1, frame_client_.number_times_called());
368 // Enqueue a third request for a frame.
369 receiver_->RequestEncodedFrame(frame_encoded_callback);
370 task_runner_->RunTasks();
371 EXPECT_EQ(1, frame_client_.number_times_called());
373 // Now, advance time forward such that Frame 2 is now too late for playback.
374 // Regardless, the receiver must NOT emit Frame 3 yet because it is not
375 // allowed to skip frames when dependencies are not satisfied. In other
376 // words, Frame 3 is not decodable without Frame 2.
377 testing_clock_->Advance(2 * time_advance_per_frame + target_playout_delay);
378 task_runner_->RunTasks();
379 EXPECT_EQ(1, frame_client_.number_times_called());
381 // Now receive Frame 2 and expect both the second and third requests to be
382 // fulfilled immediately.
383 frame_client_.AddExpectedResult(
384 kFirstFrameId + 1, // "Frame 2"
385 first_frame_capture_time + 1 * time_advance_per_frame +
386 target_playout_delay);
387 frame_client_.AddExpectedResult(
388 kFirstFrameId + 2, // "Frame 3"
389 first_frame_capture_time + 2 * time_advance_per_frame +
390 target_playout_delay);
391 --rtp_header_.frame_id; // "Frame 2"
392 --rtp_header_.reference_frame_id; // "Frame 1"
393 rtp_header_.rtp_timestamp -= rtp_advance_per_frame;
394 FeedOneFrameIntoReceiver(); // Frame 2
395 task_runner_->RunTasks();
396 EXPECT_EQ(3, frame_client_.number_times_called());
398 // Move forward to the playout time of an unreceived Frame 5. Expect no
399 // additional frames were emitted.
400 testing_clock_->Advance(3 * time_advance_per_frame);
401 task_runner_->RunTasks();
402 EXPECT_EQ(3, frame_client_.number_times_called());
404 // Sanity-check logging results.
405 std::vector<FrameEvent> frame_events;
406 event_subscriber.GetFrameEventsAndReset(&frame_events);
407 ASSERT_TRUE(!frame_events.empty());
408 for (size_t i = 0; i < frame_events.size(); ++i) {
409 EXPECT_EQ(FRAME_ACK_SENT, frame_events[i].type);
410 EXPECT_EQ(VIDEO_EVENT, frame_events[i].media_type);
411 EXPECT_LE(kFirstFrameId, frame_events[i].frame_id);
412 EXPECT_GE(kFirstFrameId + 3, frame_events[i].frame_id);
413 const int frame_offset = frame_events[i].frame_id - kFirstFrameId;
414 EXPECT_EQ(frame_offset * rtp_advance_per_frame,
415 frame_events[i].rtp_timestamp);
417 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
420 } // namespace cast
421 } // namespace media