Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / remoting / host / video_frame_recorder_unittest.cc
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 "remoting/host/video_frame_recorder.h"
6
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"
16
17 namespace webrtc {
18
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;
26   }
27
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;
33     }
34   }
35
36   return true;
37 }
38
39 } // namespace
40
41 namespace remoting {
42
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
50
51 class VideoFrameRecorderTest : public testing::Test {
52  public:
53   VideoFrameRecorderTest();
54
55   void SetUp() override;
56   void TearDown() override;
57
58   // Creates a new VideoEncoder, wraps it using |recorder_|, and stores the
59   // newly wrapped encoder in |encoder_|.
60   void CreateAndWrapEncoder();
61
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();
66
67   // Calls CreateNextFrame() to create kTextFrameCount test frames, and stores
68   // them to |test_frames_|.
69   void CreateTestFrames();
70
71   // Passes the frames in |test_frames_| to |encoder_|, in order, to encode.
72   void EncodeTestFrames();
73
74   // Creates a frame and passes it to |encoder_| without adding it to
75   // |test_frames_|.
76   void EncodeDummyFrame();
77
78   // Configures |recorder_| to start recording, and pumps events to ensure that
79   // |encoder_| is ready to record frames.
80   void StartRecording();
81
82   // Reads frames from |recorder_| and compares them to the |test_frames_|.
83   void VerifyTestFrames();
84
85  protected:
86   typedef std::list<webrtc::DesktopFrame*> DesktopFrames;
87
88   base::MessageLoop message_loop_;
89
90   scoped_ptr<VideoFrameRecorder> recorder_;
91   scoped_ptr<VideoEncoder> encoder_;
92
93   DesktopFrames test_frames_;
94   int frame_count_;
95
96   DISALLOW_COPY_AND_ASSIGN(VideoFrameRecorderTest);
97 };
98
99 VideoFrameRecorderTest::VideoFrameRecorderTest() : frame_count_(0) {}
100
101 void VideoFrameRecorderTest::SetUp() {
102   const int64_t kMaxContentBytes = 10 * 1024 * 1024;
103   recorder_.reset(new VideoFrameRecorder());
104   recorder_->SetMaxContentBytes(kMaxContentBytes);
105 }
106
107 void VideoFrameRecorderTest::TearDown() {
108   ASSERT_TRUE(test_frames_.empty());
109
110   // Allow events posted to the recorder_, if still valid, to be processed.
111   base::RunLoop().RunUntilIdle();
112
113   // Tear down the recorder, if necessary.
114   recorder_.reset();
115
116   // Process any events resulting from recorder teardown.
117   base::RunLoop().RunUntilIdle();
118 }
119
120 void VideoFrameRecorderTest::CreateAndWrapEncoder() {
121   scoped_ptr<VideoEncoder> encoder(new VideoEncoderVerbatim());
122   encoder_ = recorder_->WrapVideoEncoder(encoder.Pass());
123
124   // Encode a dummy frame to bind the wrapper to the TaskRunner.
125   EncodeDummyFrame();
126 }
127
128 scoped_ptr<webrtc::DesktopFrame> VideoFrameRecorderTest::CreateNextFrame() {
129   scoped_ptr<webrtc::DesktopFrame> frame(
130       new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kFrameWidth,
131                                                         kFrameHeight)));
132
133   // Fill content, DPI and updated-region based on |frame_count_| so that each
134   // generated frame is different.
135   memset(frame->data(), frame_count_, frame->stride() * kFrameHeight);
136   frame->set_dpi(webrtc::DesktopVector(frame_count_, frame_count_));
137   frame->mutable_updated_region()->SetRect(
138       webrtc::DesktopRect::MakeWH(frame_count_, frame_count_));
139   ++frame_count_;
140
141   return frame.Pass();
142 }
143
144 void VideoFrameRecorderTest::CreateTestFrames() {
145   for (size_t i = 0; i < kTestFrameCount; ++i) {
146     test_frames_.push_back(CreateNextFrame().release());
147   }
148 }
149
150 void VideoFrameRecorderTest::EncodeTestFrames() {
151   for (DesktopFrames::iterator i = test_frames_.begin();
152        i != test_frames_.end(); ++i) {
153     ASSERT_TRUE(encoder_->Encode(**i));
154
155     // Process tasks to let the recorder pick up the frame.
156     base::RunLoop().RunUntilIdle();
157   }
158 }
159
160 void VideoFrameRecorderTest::EncodeDummyFrame() {
161   webrtc::BasicDesktopFrame dummy_frame(
162       webrtc::DesktopSize(kFrameWidth, kFrameHeight));
163   ASSERT_TRUE(encoder_->Encode(dummy_frame));
164   base::RunLoop().RunUntilIdle();
165 }
166
167 void VideoFrameRecorderTest::StartRecording() {
168   // Start the recorder and pump events to let things initialize.
169   recorder_->SetEnableRecording(true);
170   base::RunLoop().RunUntilIdle();
171 }
172
173 void VideoFrameRecorderTest::VerifyTestFrames() {
174   // Verify that the recorded frames match the ones passed to the encoder.
175   while (!test_frames_.empty()) {
176     scoped_ptr<webrtc::DesktopFrame> recorded_frame(recorder_->NextFrame());
177     ASSERT_TRUE(recorded_frame);
178
179     scoped_ptr<webrtc::DesktopFrame> expected_frame(test_frames_.front());
180     test_frames_.pop_front();
181
182     EXPECT_EQ(*recorded_frame, *expected_frame);
183   }
184
185   EXPECT_FALSE(recorder_->NextFrame());
186 }
187
188 // Basic test that creating & tearing down VideoFrameRecorder doesn't crash.
189 TEST_F(VideoFrameRecorderTest, CreateDestroy) {
190 }
191
192 // Basic test that creating, starting, stopping and destroying a
193 // VideoFrameRecorder succeeds (e.g. does not crash or DCHECK).
194 TEST_F(VideoFrameRecorderTest, StartStop) {
195   StartRecording();
196   recorder_->SetEnableRecording(false);
197 }
198
199 // Test that tearing down the VideoFrameRecorder while the VideoEncoder
200 // wrapper exists doesn't crash.
201 TEST_F(VideoFrameRecorderTest, DestroyVideoFrameRecorderFirst) {
202   CreateAndWrapEncoder();
203
204   // Start the recorder, so that the wrapper will push frames to it.
205   StartRecording();
206
207   // Tear down the recorder.
208   recorder_.reset();
209
210   // Encode a dummy frame via the wrapper to ensure we don't crash.
211   EncodeDummyFrame();
212 }
213
214 // Test that creating & tearing down the wrapper while the
215 // VideoFrameRecorder still exists doesn't crash.
216 TEST_F(VideoFrameRecorderTest, DestroyVideoEncoderWrapperFirst) {
217   CreateAndWrapEncoder();
218
219   // Start the recorder, so that the wrapper will push frames to it.
220   StartRecording();
221
222   // Encode a dummy frame via the wrapper to ensure we don't crash.
223   EncodeDummyFrame();
224
225   // Tear down the encoder wrapper.
226   encoder_.reset();
227
228   // Test teardown will stop the recorder and process pending events.
229 }
230
231 // Test that when asked to encode a short sequence of frames, those frames are
232 // all recorded, in sequence.
233 TEST_F(VideoFrameRecorderTest, RecordFrames) {
234   CreateAndWrapEncoder();
235
236   // Start the recorder, so that the wrapper will push frames to it.
237   StartRecording();
238
239   // Create frames, store them and pass them to the encoder.
240   CreateTestFrames();
241   EncodeTestFrames();
242
243   // Verify that the recorded frames match the ones passed to the encoder.
244   VerifyTestFrames();
245 }
246
247 // Test that when asked to record more frames than the maximum content bytes
248 // limit allows, the first encoded frames are dropped.
249 TEST_F(VideoFrameRecorderTest, MaxContentBytesEnforced) {
250   CreateAndWrapEncoder();
251
252   // Configure a maximum content size sufficient for five and a half frames.
253   recorder_->SetMaxContentBytes((kTestFrameBytes * 11) / 2);
254
255   // Start the recorder, so that the wrapper will push frames to it.
256   StartRecording();
257
258   // Create frames, store them and pass them to the encoder.
259   CreateTestFrames();
260   EncodeTestFrames();
261
262   // Only five of the supplied frames should have been recorded.
263   while (test_frames_.size() > 5) {
264     scoped_ptr<webrtc::DesktopFrame> frame(test_frames_.front());
265     test_frames_.pop_front();
266   }
267
268   // Verify that the recorded frames match the ones passed to the encoder.
269   VerifyTestFrames();
270 }
271
272 // Test that when frames are consumed the corresponding space is freed up in
273 // the content buffer, allowing subsequent frames to be recorded.
274 TEST_F(VideoFrameRecorderTest, ContentBytesUpdatedByNextFrame) {
275   CreateAndWrapEncoder();
276
277   // Configure a maximum content size sufficient for kTestFrameCount frames.
278   recorder_->SetMaxContentBytes(kTestFrameBytes * kTestFrameCount);
279
280   // Start the recorder, so that the wrapper will push frames to it.
281   StartRecording();
282
283   // Encode a frame, to record it, and consume it from the recorder.
284   EncodeDummyFrame();
285   scoped_ptr<webrtc::DesktopFrame> frame = recorder_->NextFrame();
286   EXPECT_TRUE(frame);
287
288   // Create frames, store them and pass them to the encoder.
289   CreateTestFrames();
290   EncodeTestFrames();
291
292   // Verify that the recorded frames match the ones passed to the encoder.
293   VerifyTestFrames();
294 }
295
296 // Test that when asked to encode a short sequence of frames, none are recorded
297 // if recording was not enabled.
298 TEST_F(VideoFrameRecorderTest, EncodeButDontRecord) {
299   CreateAndWrapEncoder();
300
301   // Create frames, store them and pass them to the encoder.
302   CreateTestFrames();
303   EncodeTestFrames();
304
305   // Clear the list of expected test frames, since none should be recorded.
306   STLDeleteElements(&test_frames_);
307
308   // Verify that the recorded frames match the ones passed to the encoder.
309   VerifyTestFrames();
310 }
311
312 }  // namespace remoting