MD Downloads: prevent search text from overlapping with the cancel search (X)
[chromium-blink-merge.git] / remoting / host / video_frame_recorder_unittest.cc
blob319201254a53edbb69c1d1ff0d83132f8bb9265e
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 "remoting/host/video_frame_recorder.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/stl_util.h"
10 #include "remoting/codec/video_encoder_verbatim.h"
11 #include "remoting/proto/video.pb.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
14 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
15 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
17 namespace webrtc {
19 // Define equality operator for DesktopFrame to allow use of EXPECT_EQ().
20 static bool operator==(const DesktopFrame& a,
21 const DesktopFrame& b) {
22 if ((!a.size().equals(b.size())) ||
23 (!a.updated_region().Equals(b.updated_region())) ||
24 (!a.dpi().equals(b.dpi()))) {
25 return false;
28 for (int i = 0; i < a.size().height(); ++i) {
29 if (memcmp(a.data() + a.stride() * i,
30 b.data() + b.stride() * i,
31 a.size().width() * DesktopFrame::kBytesPerPixel) != 0) {
32 return false;
36 return true;
39 } // namespace
41 namespace remoting {
43 namespace {
44 const int kFrameWidth = 640;
45 const int kFrameHeight = 480;
46 const size_t kTestFrameCount = 6;
47 const int64 kTestFrameBytes =
48 kFrameWidth * kFrameHeight * webrtc::DesktopFrame::kBytesPerPixel;
49 } // namespace
51 class VideoFrameRecorderTest : public testing::Test {
52 public:
53 VideoFrameRecorderTest();
55 void SetUp() override;
56 void TearDown() override;
58 // Creates a new VideoEncoder, wraps it using |recorder_|, and stores the
59 // newly wrapped encoder in |encoder_|.
60 void CreateAndWrapEncoder();
62 // Creates the next test frame to pass to |encoder_|. Each test frame's pixel
63 // values are set uniquely, so that tests can verify that the correct set of
64 // frames were recorded.
65 scoped_ptr<webrtc::DesktopFrame> CreateNextFrame();
67 // Calls CreateNextFrame() to create kTextFrameCount test frames, and stores
68 // them to |test_frames_|.
69 void CreateTestFrames();
71 // Passes the frames in |test_frames_| to |encoder_|, in order, to encode.
72 void EncodeTestFrames();
74 // Creates a frame and passes it to |encoder_| without adding it to
75 // |test_frames_|.
76 void EncodeDummyFrame();
78 // Configures |recorder_| to start recording, and pumps events to ensure that
79 // |encoder_| is ready to record frames.
80 void StartRecording();
82 // Reads frames from |recorder_| and compares them to the |test_frames_|.
83 void VerifyTestFrames();
85 protected:
86 typedef std::list<webrtc::DesktopFrame*> DesktopFrames;
88 base::MessageLoop message_loop_;
90 scoped_ptr<VideoFrameRecorder> recorder_;
91 scoped_ptr<VideoEncoder> encoder_;
93 DesktopFrames test_frames_;
94 int frame_count_;
96 DISALLOW_COPY_AND_ASSIGN(VideoFrameRecorderTest);
99 VideoFrameRecorderTest::VideoFrameRecorderTest() : frame_count_(0) {}
101 void VideoFrameRecorderTest::SetUp() {
102 const int64_t kMaxContentBytes = 10 * 1024 * 1024;
103 recorder_.reset(new VideoFrameRecorder());
104 recorder_->SetMaxContentBytes(kMaxContentBytes);
107 void VideoFrameRecorderTest::TearDown() {
108 ASSERT_TRUE(test_frames_.empty());
110 // Allow events posted to the recorder_, if still valid, to be processed.
111 base::RunLoop().RunUntilIdle();
113 // Tear down the recorder, if necessary.
114 recorder_.reset();
116 // Process any events resulting from recorder teardown.
117 base::RunLoop().RunUntilIdle();
120 void VideoFrameRecorderTest::CreateAndWrapEncoder() {
121 scoped_ptr<VideoEncoder> encoder(new VideoEncoderVerbatim());
122 encoder_ = recorder_->WrapVideoEncoder(encoder.Pass());
124 // Encode a dummy frame to bind the wrapper to the TaskRunner.
125 EncodeDummyFrame();
128 scoped_ptr<webrtc::DesktopFrame> VideoFrameRecorderTest::CreateNextFrame() {
129 scoped_ptr<webrtc::DesktopFrame> frame(
130 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kFrameWidth,
131 kFrameHeight)));
133 // Fill content, DPI and updated-region based on |frame_count_| so that each
134 // generated frame is different.
135 ++frame_count_;
136 memset(frame->data(), frame_count_, frame->stride() * kFrameHeight);
137 frame->set_dpi(webrtc::DesktopVector(frame_count_, frame_count_));
138 frame->mutable_updated_region()->SetRect(
139 webrtc::DesktopRect::MakeWH(frame_count_, frame_count_));
141 return frame.Pass();
144 void VideoFrameRecorderTest::CreateTestFrames() {
145 for (size_t i = 0; i < kTestFrameCount; ++i) {
146 test_frames_.push_back(CreateNextFrame().release());
150 void VideoFrameRecorderTest::EncodeTestFrames() {
151 for (DesktopFrames::iterator i = test_frames_.begin();
152 i != test_frames_.end(); ++i) {
153 ASSERT_TRUE(encoder_->Encode(**i));
155 // Process tasks to let the recorder pick up the frame.
156 base::RunLoop().RunUntilIdle();
160 void VideoFrameRecorderTest::EncodeDummyFrame() {
161 webrtc::BasicDesktopFrame dummy_frame(
162 webrtc::DesktopSize(kFrameWidth, kFrameHeight));
163 dummy_frame.mutable_updated_region()->SetRect(
164 webrtc::DesktopRect::MakeWH(kFrameWidth, kFrameHeight));
165 ASSERT_TRUE(encoder_->Encode(dummy_frame));
166 base::RunLoop().RunUntilIdle();
169 void VideoFrameRecorderTest::StartRecording() {
170 // Start the recorder and pump events to let things initialize.
171 recorder_->SetEnableRecording(true);
172 base::RunLoop().RunUntilIdle();
175 void VideoFrameRecorderTest::VerifyTestFrames() {
176 // Verify that the recorded frames match the ones passed to the encoder.
177 while (!test_frames_.empty()) {
178 scoped_ptr<webrtc::DesktopFrame> recorded_frame(recorder_->NextFrame());
179 ASSERT_TRUE(recorded_frame);
181 scoped_ptr<webrtc::DesktopFrame> expected_frame(test_frames_.front());
182 test_frames_.pop_front();
184 EXPECT_EQ(*recorded_frame, *expected_frame);
187 EXPECT_FALSE(recorder_->NextFrame());
190 // Basic test that creating & tearing down VideoFrameRecorder doesn't crash.
191 TEST_F(VideoFrameRecorderTest, CreateDestroy) {
194 // Basic test that creating, starting, stopping and destroying a
195 // VideoFrameRecorder succeeds (e.g. does not crash or DCHECK).
196 TEST_F(VideoFrameRecorderTest, StartStop) {
197 StartRecording();
198 recorder_->SetEnableRecording(false);
201 // Test that tearing down the VideoFrameRecorder while the VideoEncoder
202 // wrapper exists doesn't crash.
203 TEST_F(VideoFrameRecorderTest, DestroyVideoFrameRecorderFirst) {
204 CreateAndWrapEncoder();
206 // Start the recorder, so that the wrapper will push frames to it.
207 StartRecording();
209 // Tear down the recorder.
210 recorder_.reset();
212 // Encode a dummy frame via the wrapper to ensure we don't crash.
213 EncodeDummyFrame();
216 // Test that creating & tearing down the wrapper while the
217 // VideoFrameRecorder still exists doesn't crash.
218 TEST_F(VideoFrameRecorderTest, DestroyVideoEncoderWrapperFirst) {
219 CreateAndWrapEncoder();
221 // Start the recorder, so that the wrapper will push frames to it.
222 StartRecording();
224 // Encode a dummy frame via the wrapper to ensure we don't crash.
225 EncodeDummyFrame();
227 // Tear down the encoder wrapper.
228 encoder_.reset();
230 // Test teardown will stop the recorder and process pending events.
233 // Test that when asked to encode a short sequence of frames, those frames are
234 // all recorded, in sequence.
235 TEST_F(VideoFrameRecorderTest, RecordFrames) {
236 CreateAndWrapEncoder();
238 // Start the recorder, so that the wrapper will push frames to it.
239 StartRecording();
241 // Create frames, store them and pass them to the encoder.
242 CreateTestFrames();
243 EncodeTestFrames();
245 // Verify that the recorded frames match the ones passed to the encoder.
246 VerifyTestFrames();
249 // Test that when asked to record more frames than the maximum content bytes
250 // limit allows, the first encoded frames are dropped.
251 TEST_F(VideoFrameRecorderTest, MaxContentBytesEnforced) {
252 CreateAndWrapEncoder();
254 // Configure a maximum content size sufficient for five and a half frames.
255 recorder_->SetMaxContentBytes((kTestFrameBytes * 11) / 2);
257 // Start the recorder, so that the wrapper will push frames to it.
258 StartRecording();
260 // Create frames, store them and pass them to the encoder.
261 CreateTestFrames();
262 EncodeTestFrames();
264 // Only five of the supplied frames should have been recorded.
265 while (test_frames_.size() > 5) {
266 scoped_ptr<webrtc::DesktopFrame> frame(test_frames_.front());
267 test_frames_.pop_front();
270 // Verify that the recorded frames match the ones passed to the encoder.
271 VerifyTestFrames();
274 // Test that when frames are consumed the corresponding space is freed up in
275 // the content buffer, allowing subsequent frames to be recorded.
276 TEST_F(VideoFrameRecorderTest, ContentBytesUpdatedByNextFrame) {
277 CreateAndWrapEncoder();
279 // Configure a maximum content size sufficient for kTestFrameCount frames.
280 recorder_->SetMaxContentBytes(kTestFrameBytes * kTestFrameCount);
282 // Start the recorder, so that the wrapper will push frames to it.
283 StartRecording();
285 // Encode a frame, to record it, and consume it from the recorder.
286 EncodeDummyFrame();
287 scoped_ptr<webrtc::DesktopFrame> frame = recorder_->NextFrame();
288 EXPECT_TRUE(frame);
290 // Create frames, store them and pass them to the encoder.
291 CreateTestFrames();
292 EncodeTestFrames();
294 // Verify that the recorded frames match the ones passed to the encoder.
295 VerifyTestFrames();
298 // Test that when asked to encode a short sequence of frames, none are recorded
299 // if recording was not enabled.
300 TEST_F(VideoFrameRecorderTest, EncodeButDontRecord) {
301 CreateAndWrapEncoder();
303 // Create frames, store them and pass them to the encoder.
304 CreateTestFrames();
305 EncodeTestFrames();
307 // Clear the list of expected test frames, since none should be recorded.
308 STLDeleteElements(&test_frames_);
310 // Verify that the recorded frames match the ones passed to the encoder.
311 VerifyTestFrames();
314 } // namespace remoting