• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include <stdint.h>
6 
7 #include <vector>
8 
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "media/base/video_frame.h"
13 #include "media/cast/cast_environment.h"
14 #include "media/cast/logging/simple_event_subscriber.h"
15 #include "media/cast/test/fake_single_thread_task_runner.h"
16 #include "media/cast/test/fake_video_encode_accelerator.h"
17 #include "media/cast/test/utility/default_config.h"
18 #include "media/cast/test/utility/video_utility.h"
19 #include "media/cast/transport/cast_transport_config.h"
20 #include "media/cast/transport/cast_transport_sender_impl.h"
21 #include "media/cast/transport/pacing/paced_sender.h"
22 #include "media/cast/video_sender/video_sender.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 namespace media {
27 namespace cast {
28 
29 namespace {
30 static const uint8 kPixelValue = 123;
31 static const int kWidth = 320;
32 static const int kHeight = 240;
33 
34 using testing::_;
35 using testing::AtLeast;
36 
CreateVideoEncodeAccelerator(const scoped_refptr<base::SingleThreadTaskRunner> & task_runner,scoped_ptr<VideoEncodeAccelerator> fake_vea,const ReceiveVideoEncodeAcceleratorCallback & callback)37 void CreateVideoEncodeAccelerator(
38     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
39     scoped_ptr<VideoEncodeAccelerator> fake_vea,
40     const ReceiveVideoEncodeAcceleratorCallback& callback) {
41   callback.Run(task_runner, fake_vea.Pass());
42 }
43 
CreateSharedMemory(size_t size,const ReceiveVideoEncodeMemoryCallback & callback)44 void CreateSharedMemory(
45     size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
46   scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
47   if (!shm->CreateAndMapAnonymous(size)) {
48     NOTREACHED();
49     return;
50   }
51   callback.Run(shm.Pass());
52 }
53 
54 class TestPacketSender : public transport::PacketSender {
55  public:
TestPacketSender()56   TestPacketSender()
57       : number_of_rtp_packets_(0),
58         number_of_rtcp_packets_(0),
59         paused_(false) {}
60 
61   // A singular packet implies a RTCP packet.
SendPacket(transport::PacketRef packet,const base::Closure & cb)62   virtual bool SendPacket(transport::PacketRef packet,
63                           const base::Closure& cb) OVERRIDE {
64     if (paused_) {
65       stored_packet_ = packet;
66       callback_ = cb;
67       return false;
68     }
69     if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
70       ++number_of_rtcp_packets_;
71     } else {
72       // Check that at least one RTCP packet was sent before the first RTP
73       // packet.  This confirms that the receiver will have the necessary lip
74       // sync info before it has to calculate the playout time of the first
75       // frame.
76       if (number_of_rtp_packets_ == 0)
77         EXPECT_LE(1, number_of_rtcp_packets_);
78       ++number_of_rtp_packets_;
79     }
80     return true;
81   }
82 
number_of_rtp_packets() const83   int number_of_rtp_packets() const { return number_of_rtp_packets_; }
84 
number_of_rtcp_packets() const85   int number_of_rtcp_packets() const { return number_of_rtcp_packets_; }
86 
SetPause(bool paused)87   void SetPause(bool paused) {
88     paused_ = paused;
89     if (!paused && stored_packet_) {
90       SendPacket(stored_packet_, callback_);
91       callback_.Run();
92     }
93   }
94 
95  private:
96   int number_of_rtp_packets_;
97   int number_of_rtcp_packets_;
98   bool paused_;
99   base::Closure callback_;
100   transport::PacketRef stored_packet_;
101 
102   DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
103 };
104 
105 class PeerVideoSender : public VideoSender {
106  public:
PeerVideoSender(scoped_refptr<CastEnvironment> cast_environment,const VideoSenderConfig & video_config,const CreateVideoEncodeAcceleratorCallback & create_vea_cb,const CreateVideoEncodeMemoryCallback & create_video_encode_mem_cb,transport::CastTransportSender * const transport_sender)107   PeerVideoSender(
108       scoped_refptr<CastEnvironment> cast_environment,
109       const VideoSenderConfig& video_config,
110       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
111       const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
112       transport::CastTransportSender* const transport_sender)
113       : VideoSender(cast_environment,
114                     video_config,
115                     create_vea_cb,
116                     create_video_encode_mem_cb,
117                     transport_sender) {}
118   using VideoSender::OnReceivedCastFeedback;
119 };
120 }  // namespace
121 
122 class VideoSenderTest : public ::testing::Test {
123  protected:
VideoSenderTest()124   VideoSenderTest() {
125     testing_clock_ = new base::SimpleTestTickClock();
126     testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
127     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
128     cast_environment_ =
129         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
130                             task_runner_,
131                             task_runner_,
132                             task_runner_);
133     last_pixel_value_ = kPixelValue;
134     net::IPEndPoint dummy_endpoint;
135     transport_sender_.reset(new transport::CastTransportSenderImpl(
136         NULL,
137         testing_clock_,
138         dummy_endpoint,
139         base::Bind(&UpdateCastTransportStatus),
140         transport::BulkRawEventsCallback(),
141         base::TimeDelta(),
142         task_runner_,
143         &transport_));
144   }
145 
~VideoSenderTest()146   virtual ~VideoSenderTest() {}
147 
TearDown()148   virtual void TearDown() OVERRIDE {
149     video_sender_.reset();
150     task_runner_->RunTasks();
151   }
152 
UpdateCastTransportStatus(transport::CastTransportStatus status)153   static void UpdateCastTransportStatus(transport::CastTransportStatus status) {
154     EXPECT_EQ(transport::TRANSPORT_VIDEO_INITIALIZED, status);
155   }
156 
InitEncoder(bool external)157   void InitEncoder(bool external) {
158     VideoSenderConfig video_config;
159     video_config.rtp_config.ssrc = 1;
160     video_config.incoming_feedback_ssrc = 2;
161     video_config.rtcp_c_name = "video_test@10.1.1.1";
162     video_config.rtp_config.payload_type = 127;
163     video_config.use_external_encoder = external;
164     video_config.width = kWidth;
165     video_config.height = kHeight;
166     video_config.max_bitrate = 5000000;
167     video_config.min_bitrate = 1000000;
168     video_config.start_bitrate = 1000000;
169     video_config.max_qp = 56;
170     video_config.min_qp = 0;
171     video_config.max_frame_rate = 30;
172     video_config.max_number_of_video_buffers_used = 1;
173     video_config.codec = transport::kVp8;
174 
175     if (external) {
176       scoped_ptr<VideoEncodeAccelerator> fake_vea(
177           new test::FakeVideoEncodeAccelerator(task_runner_));
178       video_sender_.reset(
179           new PeerVideoSender(cast_environment_,
180                               video_config,
181                               base::Bind(&CreateVideoEncodeAccelerator,
182                                          task_runner_,
183                                          base::Passed(&fake_vea)),
184                               base::Bind(&CreateSharedMemory),
185                               transport_sender_.get()));
186     } else {
187       video_sender_.reset(
188           new PeerVideoSender(cast_environment_,
189                               video_config,
190                               CreateDefaultVideoEncodeAcceleratorCallback(),
191                               CreateDefaultVideoEncodeMemoryCallback(),
192                               transport_sender_.get()));
193     }
194     ASSERT_EQ(STATUS_VIDEO_INITIALIZED, video_sender_->InitializationResult());
195   }
196 
GetNewVideoFrame()197   scoped_refptr<media::VideoFrame> GetNewVideoFrame() {
198     gfx::Size size(kWidth, kHeight);
199     scoped_refptr<media::VideoFrame> video_frame =
200         media::VideoFrame::CreateFrame(
201             VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
202     PopulateVideoFrame(video_frame, last_pixel_value_++);
203     return video_frame;
204   }
205 
GetLargeNewVideoFrame()206   scoped_refptr<media::VideoFrame> GetLargeNewVideoFrame() {
207     gfx::Size size(kWidth, kHeight);
208     scoped_refptr<media::VideoFrame> video_frame =
209         media::VideoFrame::CreateFrame(
210             VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
211     PopulateVideoFrameWithNoise(video_frame);
212     return video_frame;
213   }
214 
RunTasks(int during_ms)215   void RunTasks(int during_ms) {
216     task_runner_->Sleep(base::TimeDelta::FromMilliseconds(during_ms));
217   }
218 
219   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
220   TestPacketSender transport_;
221   scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
222   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
223   scoped_ptr<PeerVideoSender> video_sender_;
224   scoped_refptr<CastEnvironment> cast_environment_;
225   int last_pixel_value_;
226 
227   DISALLOW_COPY_AND_ASSIGN(VideoSenderTest);
228 };
229 
TEST_F(VideoSenderTest,BuiltInEncoder)230 TEST_F(VideoSenderTest, BuiltInEncoder) {
231   InitEncoder(false);
232   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
233 
234   const base::TimeTicks capture_time = testing_clock_->NowTicks();
235   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
236 
237   task_runner_->RunTasks();
238   EXPECT_LE(1, transport_.number_of_rtp_packets());
239   EXPECT_LE(1, transport_.number_of_rtcp_packets());
240 }
241 
TEST_F(VideoSenderTest,ExternalEncoder)242 TEST_F(VideoSenderTest, ExternalEncoder) {
243   InitEncoder(true);
244   task_runner_->RunTasks();
245 
246   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
247 
248   const base::TimeTicks capture_time = testing_clock_->NowTicks();
249   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
250 
251   task_runner_->RunTasks();
252 
253   // We need to run the task to cleanup the GPU instance.
254   video_sender_.reset(NULL);
255   task_runner_->RunTasks();
256 }
257 
TEST_F(VideoSenderTest,RtcpTimer)258 TEST_F(VideoSenderTest, RtcpTimer) {
259   InitEncoder(false);
260 
261   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
262 
263   const base::TimeTicks capture_time = testing_clock_->NowTicks();
264   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
265 
266   // Make sure that we send at least one RTCP packet.
267   base::TimeDelta max_rtcp_timeout =
268       base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2);
269 
270   RunTasks(max_rtcp_timeout.InMilliseconds());
271   EXPECT_LE(1, transport_.number_of_rtp_packets());
272   EXPECT_LE(1, transport_.number_of_rtcp_packets());
273   // Build Cast msg and expect RTCP packet.
274   RtcpCastMessage cast_feedback(1);
275   cast_feedback.media_ssrc_ = 2;
276   cast_feedback.ack_frame_id_ = 0;
277   video_sender_->OnReceivedCastFeedback(cast_feedback);
278   RunTasks(max_rtcp_timeout.InMilliseconds());
279   EXPECT_LE(1, transport_.number_of_rtcp_packets());
280 }
281 
TEST_F(VideoSenderTest,ResendTimer)282 TEST_F(VideoSenderTest, ResendTimer) {
283   InitEncoder(false);
284 
285   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
286 
287   const base::TimeTicks capture_time = testing_clock_->NowTicks();
288   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
289 
290   // ACK the key frame.
291   RtcpCastMessage cast_feedback(1);
292   cast_feedback.media_ssrc_ = 2;
293   cast_feedback.ack_frame_id_ = 0;
294   video_sender_->OnReceivedCastFeedback(cast_feedback);
295 
296   video_frame = GetNewVideoFrame();
297   video_sender_->InsertRawVideoFrame(video_frame, capture_time);
298 
299   base::TimeDelta max_resend_timeout =
300       base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs);
301 
302   // Make sure that we do a re-send.
303   RunTasks(max_resend_timeout.InMilliseconds());
304   // Should have sent at least 3 packets.
305   EXPECT_LE(
306       3,
307       transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
308 }
309 
TEST_F(VideoSenderTest,LogAckReceivedEvent)310 TEST_F(VideoSenderTest, LogAckReceivedEvent) {
311   InitEncoder(false);
312   SimpleEventSubscriber event_subscriber;
313   cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
314 
315   int num_frames = 10;
316   for (int i = 0; i < num_frames; i++) {
317     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
318 
319     const base::TimeTicks capture_time = testing_clock_->NowTicks();
320     video_sender_->InsertRawVideoFrame(video_frame, capture_time);
321     RunTasks(33);
322   }
323 
324   task_runner_->RunTasks();
325 
326   RtcpCastMessage cast_feedback(1);
327   cast_feedback.ack_frame_id_ = num_frames - 1;
328 
329   video_sender_->OnReceivedCastFeedback(cast_feedback);
330 
331   std::vector<FrameEvent> frame_events;
332   event_subscriber.GetFrameEventsAndReset(&frame_events);
333 
334   ASSERT_TRUE(!frame_events.empty());
335   EXPECT_EQ(FRAME_ACK_RECEIVED, frame_events.rbegin()->type);
336   EXPECT_EQ(VIDEO_EVENT, frame_events.rbegin()->media_type);
337   EXPECT_EQ(num_frames - 1u, frame_events.rbegin()->frame_id);
338 
339   cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
340 }
341 
TEST_F(VideoSenderTest,StopSendingInTheAbsenceOfAck)342 TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
343   InitEncoder(false);
344   // Send a stream of frames and don't ACK; by default we shouldn't have more
345   // than 4 frames in flight.
346   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
347   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
348   RunTasks(33);
349 
350   // Send 3 more frames and record the number of packets sent.
351   for (int i = 0; i < 3; ++i) {
352     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
353     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
354     RunTasks(33);
355   }
356   const int number_of_packets_sent = transport_.number_of_rtp_packets();
357 
358   // Send 3 more frames - they should not be encoded, as we have not received
359   // any acks.
360   for (int i = 0; i < 3; ++i) {
361     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
362     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
363     RunTasks(33);
364   }
365 
366   // We expect a frame to be retransmitted because of duplicated ACKs.
367   // Only one packet of the frame is re-transmitted.
368   EXPECT_EQ(number_of_packets_sent + 1,
369             transport_.number_of_rtp_packets());
370 
371   // Start acking and make sure we're back to steady-state.
372   RtcpCastMessage cast_feedback(1);
373   cast_feedback.media_ssrc_ = 2;
374   cast_feedback.ack_frame_id_ = 0;
375   video_sender_->OnReceivedCastFeedback(cast_feedback);
376   EXPECT_LE(
377       4,
378       transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
379 
380   // Empty the pipeline.
381   RunTasks(100);
382   // Should have sent at least 7 packets.
383   EXPECT_LE(
384       7,
385       transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
386 }
387 
TEST_F(VideoSenderTest,DuplicateAckRetransmit)388 TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
389   InitEncoder(false);
390   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
391   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
392   RunTasks(33);
393   RtcpCastMessage cast_feedback(1);
394   cast_feedback.media_ssrc_ = 2;
395   cast_feedback.ack_frame_id_ = 0;
396 
397   // Send 3 more frames but don't ACK.
398   for (int i = 0; i < 3; ++i) {
399     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
400     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
401     RunTasks(33);
402   }
403   const int number_of_packets_sent = transport_.number_of_rtp_packets();
404 
405   // Send duplicated ACKs and mix some invalid NACKs.
406   for (int i = 0; i < 10; ++i) {
407     RtcpCastMessage ack_feedback(1);
408     ack_feedback.media_ssrc_ = 2;
409     ack_feedback.ack_frame_id_ = 0;
410     RtcpCastMessage nack_feedback(1);
411     nack_feedback.media_ssrc_ = 2;
412     nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
413     video_sender_->OnReceivedCastFeedback(ack_feedback);
414     video_sender_->OnReceivedCastFeedback(nack_feedback);
415   }
416   EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
417 
418   // Re-transmit one packet because of duplicated ACKs.
419   for (int i = 0; i < 3; ++i) {
420     RtcpCastMessage ack_feedback(1);
421     ack_feedback.media_ssrc_ = 2;
422     ack_feedback.ack_frame_id_ = 0;
423     video_sender_->OnReceivedCastFeedback(ack_feedback);
424   }
425   EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
426 }
427 
TEST_F(VideoSenderTest,DuplicateAckRetransmitDoesNotCancelRetransmits)428 TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
429   InitEncoder(false);
430   scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
431   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
432   RunTasks(33);
433   RtcpCastMessage cast_feedback(1);
434   cast_feedback.media_ssrc_ = 2;
435   cast_feedback.ack_frame_id_ = 0;
436 
437   // Send 2 more frames but don't ACK.
438   for (int i = 0; i < 2; ++i) {
439     scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
440     video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
441     RunTasks(33);
442   }
443   // Pause the transport
444   transport_.SetPause(true);
445 
446   // Insert one more video frame.
447   video_frame = GetLargeNewVideoFrame();
448   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
449   RunTasks(33);
450 
451   const int number_of_packets_sent = transport_.number_of_rtp_packets();
452 
453   // Send duplicated ACKs and mix some invalid NACKs.
454   for (int i = 0; i < 10; ++i) {
455     RtcpCastMessage ack_feedback(1);
456     ack_feedback.media_ssrc_ = 2;
457     ack_feedback.ack_frame_id_ = 0;
458     RtcpCastMessage nack_feedback(1);
459     nack_feedback.media_ssrc_ = 2;
460     nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
461     video_sender_->OnReceivedCastFeedback(ack_feedback);
462     video_sender_->OnReceivedCastFeedback(nack_feedback);
463   }
464   EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
465 
466   // Re-transmit one packet because of duplicated ACKs.
467   for (int i = 0; i < 3; ++i) {
468     RtcpCastMessage ack_feedback(1);
469     ack_feedback.media_ssrc_ = 2;
470     ack_feedback.ack_frame_id_ = 0;
471     video_sender_->OnReceivedCastFeedback(ack_feedback);
472   }
473 
474   transport_.SetPause(false);
475   RunTasks(100);
476   EXPECT_LT(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
477 }
478 
TEST_F(VideoSenderTest,AcksCancelRetransmits)479 TEST_F(VideoSenderTest, AcksCancelRetransmits) {
480   InitEncoder(false);
481   transport_.SetPause(true);
482   scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
483   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
484   RunTasks(33);
485 
486   // Frame should be in buffer, waiting. Now let's ack it.
487   RtcpCastMessage cast_feedback(1);
488   cast_feedback.media_ssrc_ = 2;
489   cast_feedback.ack_frame_id_ = 0;
490   video_sender_->OnReceivedCastFeedback(cast_feedback);
491 
492   transport_.SetPause(false);
493   RunTasks(33);
494   EXPECT_EQ(0, transport_.number_of_rtp_packets());
495 }
496 
TEST_F(VideoSenderTest,NAcksCancelRetransmits)497 TEST_F(VideoSenderTest, NAcksCancelRetransmits) {
498   InitEncoder(false);
499   transport_.SetPause(true);
500   // Send two video frames.
501   scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
502   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
503   RunTasks(33);
504   video_frame = GetLargeNewVideoFrame();
505   video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
506   RunTasks(33);
507 
508   // Frames should be in buffer, waiting. Now let's ack the first one and nack
509   // one packet in the second one.
510   RtcpCastMessage cast_feedback(1);
511   cast_feedback.media_ssrc_ = 2;
512   cast_feedback.ack_frame_id_ = 0;
513   PacketIdSet missing_packets;
514   missing_packets.insert(0);
515   cast_feedback.missing_frames_and_packets_[1] = missing_packets;
516   video_sender_->OnReceivedCastFeedback(cast_feedback);
517 
518   transport_.SetPause(false);
519   RunTasks(33);
520   // Only one packet should be retransmitted.
521   EXPECT_EQ(1, transport_.number_of_rtp_packets());
522 }
523 
524 }  // namespace cast
525 }  // namespace media
526