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.
4
5#include <vector>
6
7#include "base/bind.h"
8#include "base/memory/ref_counted.h"
9#include "base/memory/scoped_ptr.h"
10#include "media/base/video_frame.h"
11#include "media/cast/cast_defines.h"
12#include "media/cast/cast_environment.h"
13#include "media/cast/sender/video_encoder_impl.h"
14#include "media/cast/test/fake_single_thread_task_runner.h"
15#include "media/cast/test/utility/default_config.h"
16#include "media/cast/test/utility/video_utility.h"
17#include "testing/gmock/include/gmock/gmock.h"
18
19namespace media {
20namespace cast {
21
22using testing::_;
23
24namespace {
25class TestVideoEncoderCallback
26    : public base::RefCountedThreadSafe<TestVideoEncoderCallback> {
27 public:
28  explicit TestVideoEncoderCallback(bool multiple_buffer_mode)
29      : multiple_buffer_mode_(multiple_buffer_mode),
30        count_frames_delivered_(0) {}
31
32  int count_frames_delivered() const {
33    return count_frames_delivered_;
34  }
35
36  void SetExpectedResult(uint32 expected_frame_id,
37                         uint32 expected_last_referenced_frame_id,
38                         const base::TimeTicks& expected_capture_time) {
39    expected_frame_id_ = expected_frame_id;
40    expected_last_referenced_frame_id_ = expected_last_referenced_frame_id;
41    expected_capture_time_ = expected_capture_time;
42  }
43
44  void DeliverEncodedVideoFrame(
45      scoped_ptr<EncodedFrame> encoded_frame) {
46    if (expected_frame_id_ != expected_last_referenced_frame_id_) {
47      EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
48    } else if (!multiple_buffer_mode_) {
49      EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
50    }
51    EXPECT_EQ(expected_frame_id_, encoded_frame->frame_id);
52    EXPECT_EQ(expected_last_referenced_frame_id_,
53              encoded_frame->referenced_frame_id)
54        << "frame id: " << expected_frame_id_;
55    EXPECT_LT(0u, encoded_frame->rtp_timestamp);
56    EXPECT_EQ(expected_capture_time_, encoded_frame->reference_time);
57    EXPECT_FALSE(encoded_frame->data.empty());
58    ++count_frames_delivered_;
59  }
60
61 private:
62  friend class base::RefCountedThreadSafe<TestVideoEncoderCallback>;
63  virtual ~TestVideoEncoderCallback() {}
64
65  const bool multiple_buffer_mode_;
66  int count_frames_delivered_;
67
68  uint32 expected_frame_id_;
69  uint32 expected_last_referenced_frame_id_;
70  base::TimeTicks expected_capture_time_;
71
72  DISALLOW_COPY_AND_ASSIGN(TestVideoEncoderCallback);
73};
74}  // namespace
75
76class VideoEncoderImplTest : public ::testing::Test {
77 protected:
78  VideoEncoderImplTest() {
79    video_config_ = GetDefaultVideoSenderConfig();
80    video_config_.codec = CODEC_VIDEO_VP8;
81    gfx::Size size(video_config_.width, video_config_.height);
82    video_frame_ = media::VideoFrame::CreateFrame(
83        VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
84    PopulateVideoFrame(video_frame_.get(), 123);
85  }
86
87  virtual ~VideoEncoderImplTest() {}
88
89  virtual void SetUp() OVERRIDE {
90    testing_clock_ = new base::SimpleTestTickClock();
91    testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
92    task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
93    cast_environment_ =
94        new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
95                            task_runner_,
96                            task_runner_,
97                            task_runner_);
98  }
99
100  virtual void TearDown() OVERRIDE {
101    video_encoder_.reset();
102    task_runner_->RunTasks();
103  }
104
105  void CreateEncoder() {
106    test_video_encoder_callback_ = new TestVideoEncoderCallback(
107        video_config_.max_number_of_video_buffers_used != 1);
108    video_encoder_.reset(new VideoEncoderImpl(
109        cast_environment_, video_config_,
110        0 /* useless arg to be removed in later change */));
111  }
112
113  base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
114  scoped_refptr<TestVideoEncoderCallback> test_video_encoder_callback_;
115  VideoSenderConfig video_config_;
116  scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
117  scoped_ptr<VideoEncoder> video_encoder_;
118  scoped_refptr<media::VideoFrame> video_frame_;
119
120  scoped_refptr<CastEnvironment> cast_environment_;
121
122  DISALLOW_COPY_AND_ASSIGN(VideoEncoderImplTest);
123};
124
125TEST_F(VideoEncoderImplTest, GeneratesKeyFrameThenOnlyDeltaFrames) {
126  CreateEncoder();
127
128  VideoEncoder::FrameEncodedCallback frame_encoded_callback =
129      base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame,
130                 test_video_encoder_callback_.get());
131
132  EXPECT_EQ(0, test_video_encoder_callback_->count_frames_delivered());
133
134  test_video_encoder_callback_->SetExpectedResult(
135      0, 0, testing_clock_->NowTicks());
136  EXPECT_TRUE(video_encoder_->EncodeVideoFrame(
137      video_frame_, testing_clock_->NowTicks(), frame_encoded_callback));
138  task_runner_->RunTasks();
139
140  for (uint32 frame_id = 1; frame_id < 10; ++frame_id) {
141    testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33));
142    test_video_encoder_callback_->SetExpectedResult(
143        frame_id, frame_id - 1, testing_clock_->NowTicks());
144    EXPECT_TRUE(video_encoder_->EncodeVideoFrame(
145        video_frame_, testing_clock_->NowTicks(), frame_encoded_callback));
146    task_runner_->RunTasks();
147  }
148
149  EXPECT_EQ(10, test_video_encoder_callback_->count_frames_delivered());
150}
151
152TEST_F(VideoEncoderImplTest,
153       FramesDoNotDependOnUnackedFramesInMultiBufferMode) {
154  video_config_.max_number_of_video_buffers_used = 3;
155  CreateEncoder();
156
157  VideoEncoder::FrameEncodedCallback frame_encoded_callback =
158      base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame,
159                 test_video_encoder_callback_.get());
160
161  EXPECT_EQ(0, test_video_encoder_callback_->count_frames_delivered());
162
163  test_video_encoder_callback_->SetExpectedResult(
164      0, 0, testing_clock_->NowTicks());
165  EXPECT_TRUE(video_encoder_->EncodeVideoFrame(
166      video_frame_, testing_clock_->NowTicks(), frame_encoded_callback));
167  task_runner_->RunTasks();
168
169  testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33));
170  video_encoder_->LatestFrameIdToReference(0);
171  test_video_encoder_callback_->SetExpectedResult(
172      1, 0, testing_clock_->NowTicks());
173  EXPECT_TRUE(video_encoder_->EncodeVideoFrame(
174      video_frame_, testing_clock_->NowTicks(), frame_encoded_callback));
175  task_runner_->RunTasks();
176
177  testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33));
178  video_encoder_->LatestFrameIdToReference(1);
179  test_video_encoder_callback_->SetExpectedResult(
180      2, 1, testing_clock_->NowTicks());
181  EXPECT_TRUE(video_encoder_->EncodeVideoFrame(
182      video_frame_, testing_clock_->NowTicks(), frame_encoded_callback));
183  task_runner_->RunTasks();
184
185  video_encoder_->LatestFrameIdToReference(2);
186
187  for (uint32 frame_id = 3; frame_id < 10; ++frame_id) {
188    testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33));
189    test_video_encoder_callback_->SetExpectedResult(
190        frame_id, 2, testing_clock_->NowTicks());
191    EXPECT_TRUE(video_encoder_->EncodeVideoFrame(
192        video_frame_, testing_clock_->NowTicks(), frame_encoded_callback));
193    task_runner_->RunTasks();
194  }
195
196  EXPECT_EQ(10, test_video_encoder_callback_->count_frames_delivered());
197}
198
199}  // namespace cast
200}  // namespace media
201