Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: remoting/host/video_frame_recorder_unittest.cc

Issue 339073002: Add VideoFrameRecorder for use recording test frame sequences. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add missing OVERRIDEs Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "remoting/base/auto_thread.h"
10 #include "remoting/base/auto_thread_task_runner.h"
11 #include "remoting/codec/video_encoder_verbatim.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 {
Sergey Ulanov 2014/06/20 22:32:13 ah, so == operator must be defined in the same nam
Wez 2014/06/24 01:02:15 Yeah, apparently so. :(
18
19 static bool operator==(const DesktopRegion& a,
Sergey Ulanov 2014/06/20 22:32:13 comment why you need to define these.
Wez 2014/06/24 01:02:15 Done.
20 const DesktopRegion& b) {
21 return a.Equals(b);
22 }
23
24 static bool operator==(const DesktopSize& a,
25 const DesktopSize& b) {
26 return a.equals(b);
27 }
28
29 static bool operator==(const DesktopVector& a,
30 const DesktopVector& b) {
31 return a.equals(b);
32 }
33
34 static bool operator==(const DesktopFrame& a,
35 const DesktopFrame& b) {
36 if ((a.size() == b.size()) &&
37 (a.updated_region() == b.updated_region()) &&
38 (a.dpi() == b.dpi())) {
39 for (int i = 0; i < a.size().height(); ++i) {
40 if (memcmp(a.data() + a.stride() * i,
41 b.data() + b.stride() * i,
42 a.size().width() * DesktopFrame::kBytesPerPixel) != 0) {
43 return false;
44 }
45 }
46 return true;
47 }
48 return false;
49 }
50
51 } // namespace
52
53 namespace remoting {
54
55 const int kWidth = 640;
56 const int kHeight = 480;
57 const int kTestFrameCount = 6;
58
59 class VideoFrameRecorderTest : public testing::Test {
60 public:
61 VideoFrameRecorderTest();
62
63 virtual void SetUp() OVERRIDE;
64 virtual void TearDown() OVERRIDE;
65
66 void CreateAndWrapEncoder();
67 scoped_ptr<webrtc::DesktopFrame> CreateNextFrame();
68 void CreateTestFrames();
69 void EncodeTestFrames();
70 void EncodeDummyFrame();
71 void StartRecording();
72 void VerifyTestFrames();
73
74 protected:
75 base::MessageLoop message_loop_;
76
77 scoped_ptr<VideoFrameRecorder> recorder_;
78 scoped_ptr<VideoEncoder> encoder_;
79
80 std::list<webrtc::DesktopFrame*> test_frames_;
81 int frame_count_;
82 };
83
84 VideoFrameRecorderTest::VideoFrameRecorderTest() : frame_count_(0) {}
85
86 void VideoFrameRecorderTest::SetUp() {
87 recorder_.reset(new VideoFrameRecorder());
88 }
89
90 void VideoFrameRecorderTest::TearDown() {
91 // Allow events posted to the recorder_, if still valid, to be processed.
92 base::RunLoop().RunUntilIdle();
93
94 // Tear down the recorder, if necessary.
95 recorder_.reset();
96
97 // Process any events resulting from recorder teardown.
98 base::RunLoop().RunUntilIdle();
99 }
100
101 void VideoFrameRecorderTest::CreateAndWrapEncoder() {
102 scoped_ptr<VideoEncoder> encoder(new VideoEncoderVerbatim());
103 encoder_ = recorder_->WrapVideoEncoder(encoder.Pass());
104
105 // Encode a dummy frame to bind the wrapper to the TaskRunner.
106 EncodeDummyFrame();
107 }
108
109 scoped_ptr<webrtc::DesktopFrame> VideoFrameRecorderTest::CreateNextFrame() {
110 scoped_ptr<webrtc::DesktopFrame> frame(
111 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)));
112
113 // Fill content, DPI and updated-region based on |frame_count_| so that each
114 // generated frame is different.
115 memset(frame->data(), frame_count_, frame->stride() * kHeight);
116 frame->set_dpi(webrtc::DesktopVector(frame_count_, frame_count_));
117 frame->mutable_updated_region()->SetRect(
118 webrtc::DesktopRect::MakeWH(frame_count_, frame_count_));
119 ++frame_count_;
120
121 return frame.Pass();
122 }
123
124 void VideoFrameRecorderTest::CreateTestFrames() {
125 for (int i=0; i < kTestFrameCount; ++i) {
126 test_frames_.push_back(CreateNextFrame().release());
127 }
128 }
129
130 void VideoFrameRecorderTest::EncodeTestFrames() {
131 std::list<webrtc::DesktopFrame*>::iterator i;
132 for (i = test_frames_.begin(); i != test_frames_.end(); ++i) {
133 scoped_ptr<VideoPacket> packet = encoder_->Encode(*(*i));
134
135 // Process tasks to let the recorder pick up the frame.
136 base::RunLoop().RunUntilIdle();
137 }
138 }
139
140 void VideoFrameRecorderTest::EncodeDummyFrame() {
141 webrtc::BasicDesktopFrame dummy_frame(webrtc::DesktopSize(kWidth, kHeight));
142 scoped_ptr<VideoPacket> packet = encoder_->Encode(dummy_frame);
143 base::RunLoop().RunUntilIdle();
144 }
145
146 void VideoFrameRecorderTest::StartRecording() {
147 // Start the recorder and pump events to let things initialize.
148 recorder_->SetEnableRecording(true);
149 base::RunLoop().RunUntilIdle();
150 }
151
152 void VideoFrameRecorderTest::VerifyTestFrames() {
153 // Verify that the recorded frames match the ones passed to the encoder.
154 while (!test_frames_.empty()) {
155 scoped_ptr<webrtc::DesktopFrame> recorded_frame(recorder_->NextFrame());
156 ASSERT_TRUE(recorded_frame);
157
158 scoped_ptr<webrtc::DesktopFrame> expected_frame(test_frames_.front());
159 test_frames_.pop_front();
160
161 EXPECT_EQ(*recorded_frame, *expected_frame);
162 }
163
164 EXPECT_FALSE(recorder_->NextFrame());
165 }
166
167 // Basic test that creating & tearing down VideoFrameRecorder doesn't crash.
168 TEST_F(VideoFrameRecorderTest, CreateDestroy) {
169 }
170
171 // Basic test that creating, starting, stopping and destroying a
172 // VideoFrameRecorder don't end the world.
173 TEST_F(VideoFrameRecorderTest, StartStop) {
174 StartRecording();
175 recorder_->SetEnableRecording(false);
176 }
177
178 // Test that tearing down the VideoFrameRecorder while the VideoEncoder
179 // wrapper exists doesn't crash.
180 TEST_F(VideoFrameRecorderTest, DestroyVideoFrameRecorderFirst) {
181 CreateAndWrapEncoder();
182
183 // Start the recorder, so that the wrapper will push frames to it.
184 StartRecording();
185
186 // Tear down the recorder.
187 recorder_.reset();
188
189 // Encode a dummy frame via the wrapper to ensure we don't crash.
190 EncodeDummyFrame();
191 }
192
193 // Test that creating & tearing down the wrapper while the
194 // VideoFrameRecorder still exists doesn't crash.
195 TEST_F(VideoFrameRecorderTest, DestroyVideoEncoderWrapperFirst) {
196 CreateAndWrapEncoder();
197
198 // Start the recorder, so that the wrapper will push frames to it.
199 StartRecording();
200
201 // Encode a dummy frame via the wrapper to ensure we don't crash.
202 EncodeDummyFrame();
203
204 // Tear down the encoder wrapper.
205 encoder_.reset();
206
207 // Test teardown will stop the recorder and process pending events.
208 }
209
210 // Test that when asked to encode a short sequence of frames, those frames are
211 // all recorded, in sequence.
212 TEST_F(VideoFrameRecorderTest, RecordFrames) {
213 CreateAndWrapEncoder();
214
215 // Start the recorder, so that the wrapper will push frames to it.
216 StartRecording();
217
218 // Create frames, store them and pass them to the encoder.
219 CreateTestFrames();
220 EncodeTestFrames();
221
222 // Verify that the recorded frames match the ones passed to the encoder.
223 VerifyTestFrames();
224 }
225
226 // Test that when asked to record more frames than the maximum content bytes
227 // limit allows, the first encoded frames are dropped.
228 TEST_F(VideoFrameRecorderTest, MaxContentBytesEnforced) {
229 CreateAndWrapEncoder();
230
231 // Configure a maximum content size sufficient for five and a half frames.
232 int64 frame_bytes = kWidth * kHeight * webrtc::DesktopFrame::kBytesPerPixel;
233 recorder_->SetMaxContentBytes((frame_bytes * 11) / 2);
234
235 // Start the recorder, so that the wrapper will push frames to it.
236 StartRecording();
237
238 // Create frames, store them and pass them to the encoder.
239 CreateTestFrames();
240 EncodeTestFrames();
241
242 // Only five of the supplied frames should have been recorded.
243 while (test_frames_.size() > 5) {
244 scoped_ptr<webrtc::DesktopFrame> frame(test_frames_.front());
245 test_frames_.pop_front();
246 }
247
248 // Verify that the recorded frames match the ones passed to the encoder.
249 VerifyTestFrames();
250 }
251
252 // Test that when asked to encode a short sequence of frames, none are recorded
253 // if recording was not enabled.
254 TEST_F(VideoFrameRecorderTest, EncodeButDontRecord) {
255 CreateAndWrapEncoder();
256
257 // Create frames, store them and pass them to the encoder.
258 CreateTestFrames();
259 EncodeTestFrames();
260
261 // Clear the list of expected test frames, since none should be recorded.
262 test_frames_.clear();
263
264 // Verify that the recorded frames match the ones passed to the encoder.
265 VerifyTestFrames();
266 }
267
268 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698