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
16static const int kPacketSize = 1500;
17static const int64 kStartMillisecond = GG_INT64_C(12345678900000);
18
19namespace media {
20namespace cast {
21
22using testing::_;
23
24namespace {
25// Was thread counted thread safe.
26class TestVideoReceiverCallback :
27    public base::RefCountedThreadSafe<TestVideoReceiverCallback> {
28 public:
29  TestVideoReceiverCallback()
30      : num_called_(0) {}
31
32  // TODO(mikhal): Set and check expectations.
33  void DecodeComplete(const scoped_refptr<media::VideoFrame>& video_frame,
34                      const base::TimeTicks& render_time) {
35    ++num_called_;
36  }
37
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
45  int number_times_called() const { return num_called_;}
46
47 protected:
48  virtual ~TestVideoReceiverCallback() {}
49
50 private:
51  friend class base::RefCountedThreadSafe<TestVideoReceiverCallback>;
52
53  int num_called_;
54};
55}  // namespace
56
57class PeerVideoReceiver : public VideoReceiver {
58 public:
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
68class VideoReceiverTest : public ::testing::Test {
69 protected:
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
85  virtual ~VideoReceiverTest() {}
86
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
111TEST_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
126TEST_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
150TEST_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