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 "base/bind.h"
6 #include "base/memory/ref_counted.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "media/cast/cast_defines.h"
10 #include "media/cast/cast_environment.h"
11 #include "media/cast/net/pacing/mock_paced_packet_sender.h"
12 #include "media/cast/test/fake_task_runner.h"
13 #include "media/cast/video_receiver/video_receiver.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15
16 static const int kPacketSize = 1500;
17 static const int64 kStartMillisecond = GG_INT64_C(12345678900000);
18
19 namespace media {
20 namespace cast {
21
22 using testing::_;
23
24 namespace {
25 // Was thread counted thread safe.
26 class TestVideoReceiverCallback :
27 public base::RefCountedThreadSafe<TestVideoReceiverCallback> {
28 public:
TestVideoReceiverCallback()29 TestVideoReceiverCallback()
30 : num_called_(0) {}
31
32 // TODO(mikhal): Set and check expectations.
DecodeComplete(const scoped_refptr<media::VideoFrame> & video_frame,const base::TimeTicks & render_time)33 void DecodeComplete(const scoped_refptr<media::VideoFrame>& video_frame,
34 const base::TimeTicks& render_time) {
35 ++num_called_;
36 }
37
FrameToDecode(scoped_ptr<EncodedVideoFrame> video_frame,const base::TimeTicks & render_time)38 void FrameToDecode(scoped_ptr<EncodedVideoFrame> video_frame,
39 const base::TimeTicks& render_time) {
40 EXPECT_TRUE(video_frame->key_frame);
41 EXPECT_EQ(kVp8, video_frame->codec);
42 ++num_called_;
43 }
44
number_times_called() const45 int number_times_called() const { return num_called_;}
46
47 protected:
~TestVideoReceiverCallback()48 virtual ~TestVideoReceiverCallback() {}
49
50 private:
51 friend class base::RefCountedThreadSafe<TestVideoReceiverCallback>;
52
53 int num_called_;
54 };
55 } // namespace
56
57 class PeerVideoReceiver : public VideoReceiver {
58 public:
PeerVideoReceiver(scoped_refptr<CastEnvironment> cast_environment,const VideoReceiverConfig & video_config,PacedPacketSender * const packet_sender)59 PeerVideoReceiver(scoped_refptr<CastEnvironment> cast_environment,
60 const VideoReceiverConfig& video_config,
61 PacedPacketSender* const packet_sender)
62 : VideoReceiver(cast_environment, video_config, packet_sender) {
63 }
64 using VideoReceiver::IncomingParsedRtpPacket;
65 };
66
67
68 class VideoReceiverTest : public ::testing::Test {
69 protected:
VideoReceiverTest()70 VideoReceiverTest() {
71 // Configure to use vp8 software implementation.
72 config_.codec = kVp8;
73 config_.use_external_decoder = false;
74 task_runner_ = new test::FakeTaskRunner(&testing_clock_);
75 cast_environment_ = new CastEnvironment(&testing_clock_, task_runner_,
76 task_runner_, task_runner_, task_runner_, task_runner_,
77 GetDefaultCastLoggingConfig());
78 receiver_.reset(new
79 PeerVideoReceiver(cast_environment_, config_, &mock_transport_));
80 testing_clock_.Advance(
81 base::TimeDelta::FromMilliseconds(kStartMillisecond));
82 video_receiver_callback_ = new TestVideoReceiverCallback();
83 }
84
~VideoReceiverTest()85 virtual ~VideoReceiverTest() {}
86
SetUp()87 virtual void SetUp() {
88 payload_.assign(kPacketSize, 0);
89
90 // Always start with a key frame.
91 rtp_header_.is_key_frame = true;
92 rtp_header_.frame_id = 0;
93 rtp_header_.packet_id = 0;
94 rtp_header_.max_packet_id = 0;
95 rtp_header_.is_reference = false;
96 rtp_header_.reference_frame_id = 0;
97 }
98
99 MockPacedPacketSender mock_transport_;
100 VideoReceiverConfig config_;
101 scoped_ptr<PeerVideoReceiver> receiver_;
102 std::vector<uint8> payload_;
103 RtpCastHeader rtp_header_;
104 base::SimpleTestTickClock testing_clock_;
105
106 scoped_refptr<test::FakeTaskRunner> task_runner_;
107 scoped_refptr<CastEnvironment> cast_environment_;
108 scoped_refptr<TestVideoReceiverCallback> video_receiver_callback_;
109 };
110
TEST_F(VideoReceiverTest,GetOnePacketEncodedframe)111 TEST_F(VideoReceiverTest, GetOnePacketEncodedframe) {
112 EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).WillRepeatedly(
113 testing::Return(true));
114 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
115 rtp_header_);
116
117 VideoFrameEncodedCallback frame_to_decode_callback =
118 base::Bind(&TestVideoReceiverCallback::FrameToDecode,
119 video_receiver_callback_);
120
121 receiver_->GetEncodedVideoFrame(frame_to_decode_callback);
122 task_runner_->RunTasks();
123 EXPECT_EQ(video_receiver_callback_->number_times_called(), 1);
124 }
125
TEST_F(VideoReceiverTest,MultiplePackets)126 TEST_F(VideoReceiverTest, MultiplePackets) {
127 EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).WillRepeatedly(
128 testing::Return(true));
129 rtp_header_.max_packet_id = 2;
130 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
131 rtp_header_);
132 ++rtp_header_.packet_id;
133 ++rtp_header_.webrtc.header.sequenceNumber;
134 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
135 rtp_header_);
136 ++rtp_header_.packet_id;
137 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
138 rtp_header_);
139
140 VideoFrameEncodedCallback frame_to_decode_callback =
141 base::Bind(&TestVideoReceiverCallback::FrameToDecode,
142 video_receiver_callback_);
143
144 receiver_->GetEncodedVideoFrame(frame_to_decode_callback);
145
146 task_runner_->RunTasks();
147 EXPECT_EQ(video_receiver_callback_->number_times_called(), 1);
148 }
149
TEST_F(VideoReceiverTest,GetOnePacketRawframe)150 TEST_F(VideoReceiverTest, GetOnePacketRawframe) {
151 EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).WillRepeatedly(
152 testing::Return(true));
153 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
154 rtp_header_);
155 // Decode error - requires legal input.
156 VideoFrameDecodedCallback frame_decoded_callback =
157 base::Bind(&TestVideoReceiverCallback::DecodeComplete,
158 video_receiver_callback_);
159 receiver_->GetRawVideoFrame(frame_decoded_callback);
160 task_runner_->RunTasks();
161 EXPECT_EQ(video_receiver_callback_->number_times_called(), 0);
162 }
163
164 // TODO(pwestin): add encoded frames.
165
166 } // namespace cast
167 } // namespace media
168
169
170