blob: 51b52f03ee2358b8073051ba330e61d5bffafde2 [file] [log] [blame]
[email protected]a9c88d12012-01-29 03:45:171// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]fb13c762010-07-24 02:22:072// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]542bdfe2010-11-30 03:55:475#include <deque>
[email protected]fb13c762010-07-24 02:22:076#include <stdlib.h>
7
[email protected]1e1cb3b2011-11-10 02:07:418#include "base/bind.h"
9#include "base/logging.h"
[email protected]dc454a7c2011-08-12 22:01:1310#include "base/memory/scoped_ptr.h"
[email protected]fb13c762010-07-24 02:22:0711#include "media/base/video_frame.h"
[email protected]38609832012-08-23 01:36:1012#include "remoting/codec/codec_test.h"
13#include "remoting/codec/video_decoder.h"
14#include "remoting/codec/video_encoder.h"
[email protected]c3af26f332010-10-06 22:46:0015#include "remoting/base/util.h"
[email protected]fb13c762010-07-24 02:22:0716#include "testing/gtest/include/gtest/gtest.h"
[email protected]b9ed58f2013-05-16 10:45:2417#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
18
[email protected]c5a0f6012014-07-01 06:44:3419using webrtc::BasicDesktopFrame;
20using webrtc::DesktopFrame;
[email protected]b9ed58f2013-05-16 10:45:2421using webrtc::DesktopRect;
[email protected]f301d7362013-06-05 00:02:0222using webrtc::DesktopRegion;
[email protected]b9ed58f2013-05-16 10:45:2423using webrtc::DesktopSize;
[email protected]fb13c762010-07-24 02:22:0724
[email protected]1d65f482012-07-28 06:40:4625namespace {
26
27const int kBytesPerPixel = 4;
[email protected]fb13c762010-07-24 02:22:0728
29// Some sample rects for testing.
[email protected]b9ed58f2013-05-16 10:45:2430std::vector<std::vector<DesktopRect> > MakeTestRectLists(DesktopSize size) {
31 std::vector<std::vector<DesktopRect> > rect_lists;
32 std::vector<DesktopRect> rects;
33 rects.push_back(DesktopRect::MakeXYWH(0, 0, size.width(), size.height()));
[email protected]1d65f482012-07-28 06:40:4634 rect_lists.push_back(rects);
35 rects.clear();
[email protected]b9ed58f2013-05-16 10:45:2436 rects.push_back(DesktopRect::MakeXYWH(
37 0, 0, size.width() / 2, size.height() / 2));
[email protected]1d65f482012-07-28 06:40:4638 rect_lists.push_back(rects);
39 rects.clear();
[email protected]b9ed58f2013-05-16 10:45:2440 rects.push_back(DesktopRect::MakeXYWH(
41 size.width() / 2, size.height() / 2,
42 size.width() / 2, size.height() / 2));
[email protected]1d65f482012-07-28 06:40:4643 rect_lists.push_back(rects);
44 rects.clear();
[email protected]b9ed58f2013-05-16 10:45:2445 rects.push_back(DesktopRect::MakeXYWH(16, 16, 16, 16));
46 rects.push_back(DesktopRect::MakeXYWH(128, 64, 32, 32));
[email protected]1d65f482012-07-28 06:40:4647 rect_lists.push_back(rects);
48 return rect_lists;
49}
50
51} // namespace
[email protected]fb13c762010-07-24 02:22:0752
53namespace remoting {
54
[email protected]d9004e42012-08-24 01:47:3755class VideoDecoderTester {
[email protected]fb13c762010-07-24 02:22:0756 public:
[email protected]b9ed58f2013-05-16 10:45:2457 VideoDecoderTester(VideoDecoder* decoder,
58 const DesktopSize& screen_size,
59 const DesktopSize& view_size)
[email protected]1d65f482012-07-28 06:40:4660 : screen_size_(screen_size),
61 view_size_(view_size),
62 strict_(false),
[email protected]a3c1d452013-08-21 18:51:4063 decoder_(decoder),
64 frame_(NULL) {
[email protected]1d65f482012-07-28 06:40:4665 image_data_.reset(new uint8[
66 view_size_.width() * view_size_.height() * kBytesPerPixel]);
[email protected]55d3688e2012-02-24 23:05:5667 EXPECT_TRUE(image_data_.get());
[email protected]b9ed58f2013-05-16 10:45:2468 decoder_->Initialize(
[email protected]c5a0f6012014-07-01 06:44:3469 DesktopSize(screen_size_.width(), screen_size_.height()));
[email protected]fb13c762010-07-24 02:22:0770 }
71
[email protected]137e58f12010-12-07 19:35:4372 void Reset() {
[email protected]b9ed58f2013-05-16 10:45:2473 expected_region_.Clear();
[email protected]e59d6592013-09-25 22:16:2174 update_region_.Clear();
[email protected]137e58f12010-12-07 19:35:4375 }
[email protected]cee5dba2010-12-07 03:19:4876
[email protected]1d65f482012-07-28 06:40:4677 void ResetRenderedData() {
78 memset(image_data_.get(), 0,
79 view_size_.width() * view_size_.height() * kBytesPerPixel);
80 }
81
[email protected]137e58f12010-12-07 19:35:4382 void ReceivedPacket(VideoPacket* packet) {
[email protected]41b93ad32013-09-23 18:53:5283 ASSERT_TRUE(decoder_->DecodePacket(*packet));
[email protected]cee5dba2010-12-07 03:19:4884
[email protected]41b93ad32013-09-23 18:53:5285 RenderFrame();
[email protected]fb13c762010-07-24 02:22:0786 }
87
[email protected]1d65f482012-07-28 06:40:4688 void RenderFrame() {
[email protected]b9ed58f2013-05-16 10:45:2489 decoder_->RenderFrame(
[email protected]c5a0f6012014-07-01 06:44:3490 DesktopSize(view_size_.width(), view_size_.height()),
91 DesktopRect::MakeWH(view_size_.width(), view_size_.height()),
[email protected]e59d6592013-09-25 22:16:2192 image_data_.get(), view_size_.width() * kBytesPerPixel,
[email protected]b9ed58f2013-05-16 10:45:2493 &update_region_);
[email protected]1d65f482012-07-28 06:40:4694 }
95
[email protected]36b967f2012-07-27 18:35:3296 void ReceivedScopedPacket(scoped_ptr<VideoPacket> packet) {
97 ReceivedPacket(packet.get());
98 }
99
[email protected]fb13c762010-07-24 02:22:07100 void set_strict(bool strict) {
101 strict_ = strict;
102 }
103
[email protected]c5a0f6012014-07-01 06:44:34104 void set_frame(DesktopFrame* frame) {
[email protected]b9ed58f2013-05-16 10:45:24105 frame_ = frame;
[email protected]fb13c762010-07-24 02:22:07106 }
107
[email protected]b9ed58f2013-05-16 10:45:24108 void AddRects(const DesktopRect* rects, int count) {
109 for (int i = 0; i < count; ++i) {
110 expected_region_.AddRect(rects[i]);
111 }
[email protected]36b967f2012-07-27 18:35:32112 }
113
[email protected]c5a0f6012014-07-01 06:44:34114 void AddRegion(const DesktopRegion& region) {
[email protected]b9ed58f2013-05-16 10:45:24115 expected_region_.AddRegion(region);
[email protected]fb13c762010-07-24 02:22:07116 }
117
[email protected]137e58f12010-12-07 19:35:43118 void VerifyResults() {
[email protected]fb13c762010-07-24 02:22:07119 if (!strict_)
120 return;
[email protected]66db1af92010-07-27 01:42:46121
[email protected]b9ed58f2013-05-16 10:45:24122 ASSERT_TRUE(frame_);
[email protected]137e58f12010-12-07 19:35:43123
[email protected]a9c88d12012-01-29 03:45:17124 // Test the content of the update region.
[email protected]e59d6592013-09-25 22:16:21125 EXPECT_TRUE(expected_region_.Equals(update_region_));
[email protected]b9ed58f2013-05-16 10:45:24126
[email protected]c5a0f6012014-07-01 06:44:34127 for (DesktopRegion::Iterator i(update_region_); !i.IsAtEnd();
[email protected]e59d6592013-09-25 22:16:21128 i.Advance()) {
[email protected]1d65f482012-07-28 06:40:46129 const int stride = view_size_.width() * kBytesPerPixel;
[email protected]b9ed58f2013-05-16 10:45:24130 EXPECT_EQ(stride, frame_->stride());
[email protected]a9c88d12012-01-29 03:45:17131 const int offset = stride * i.rect().top() +
132 kBytesPerPixel * i.rect().left();
[email protected]b9ed58f2013-05-16 10:45:24133 const uint8* original = frame_->data() + offset;
[email protected]55d3688e2012-02-24 23:05:56134 const uint8* decoded = image_data_.get() + offset;
[email protected]a9c88d12012-01-29 03:45:17135 const int row_size = kBytesPerPixel * i.rect().width();
136 for (int y = 0; y < i.rect().height(); ++y) {
[email protected]66db1af92010-07-27 01:42:46137 EXPECT_EQ(0, memcmp(original, decoded, row_size))
138 << "Row " << y << " is different";
139 original += stride;
140 decoded += stride;
141 }
[email protected]fb13c762010-07-24 02:22:07142 }
143 }
144
[email protected]36b967f2012-07-27 18:35:32145 // The error at each pixel is the root mean square of the errors in
146 // the R, G, and B components, each normalized to [0, 1]. This routine
147 // checks that the maximum and mean pixel errors do not exceed given limits.
[email protected]8c6d71d2012-10-23 21:20:04148 void VerifyResultsApprox(const uint8* expected_view_data,
149 double max_error_limit, double mean_error_limit) {
[email protected]36b967f2012-07-27 18:35:32150 double max_error = 0.0;
151 double sum_error = 0.0;
152 int error_num = 0;
[email protected]c5a0f6012014-07-01 06:44:34153 for (DesktopRegion::Iterator i(update_region_); !i.IsAtEnd();
[email protected]e59d6592013-09-25 22:16:21154 i.Advance()) {
[email protected]1d65f482012-07-28 06:40:46155 const int stride = view_size_.width() * kBytesPerPixel;
[email protected]36b967f2012-07-27 18:35:32156 const int offset = stride * i.rect().top() +
157 kBytesPerPixel * i.rect().left();
[email protected]1d65f482012-07-28 06:40:46158 const uint8* expected = expected_view_data + offset;
159 const uint8* actual = image_data_.get() + offset;
[email protected]36b967f2012-07-27 18:35:32160 for (int y = 0; y < i.rect().height(); ++y) {
161 for (int x = 0; x < i.rect().width(); ++x) {
[email protected]1d65f482012-07-28 06:40:46162 double error = CalculateError(expected, actual);
[email protected]36b967f2012-07-27 18:35:32163 max_error = std::max(max_error, error);
164 sum_error += error;
165 ++error_num;
[email protected]1d65f482012-07-28 06:40:46166 expected += 4;
167 actual += 4;
[email protected]36b967f2012-07-27 18:35:32168 }
169 }
170 }
171 EXPECT_LE(max_error, max_error_limit);
172 double mean_error = sum_error / error_num;
173 EXPECT_LE(mean_error, mean_error_limit);
[email protected]5cbe3cf2013-11-25 17:05:04174 VLOG(0) << "Max error: " << max_error;
175 VLOG(0) << "Mean error: " << mean_error;
[email protected]36b967f2012-07-27 18:35:32176 }
177
178 double CalculateError(const uint8* original, const uint8* decoded) {
179 double error_sum_squares = 0.0;
180 for (int i = 0; i < 3; i++) {
181 double error = static_cast<double>(*original++) -
182 static_cast<double>(*decoded++);
183 error /= 255.0;
184 error_sum_squares += error * error;
185 }
186 original++;
187 decoded++;
188 return sqrt(error_sum_squares / 3.0);
189 }
190
[email protected]137e58f12010-12-07 19:35:43191 private:
[email protected]b9ed58f2013-05-16 10:45:24192 DesktopSize screen_size_;
193 DesktopSize view_size_;
[email protected]fb13c762010-07-24 02:22:07194 bool strict_;
[email protected]c5a0f6012014-07-01 06:44:34195 DesktopRegion expected_region_;
196 DesktopRegion update_region_;
[email protected]d9004e42012-08-24 01:47:37197 VideoDecoder* decoder_;
[email protected]c84c53d2013-04-08 20:13:23198 scoped_ptr<uint8[]> image_data_;
[email protected]c5a0f6012014-07-01 06:44:34199 DesktopFrame* frame_;
[email protected]fb13c762010-07-24 02:22:07200
[email protected]d9004e42012-08-24 01:47:37201 DISALLOW_COPY_AND_ASSIGN(VideoDecoderTester);
[email protected]fb13c762010-07-24 02:22:07202};
203
[email protected]92b45b8e2012-08-24 19:46:47204// The VideoEncoderTester provides a hook for retrieving the data, and passing
205// the message to other subprograms for validaton.
206class VideoEncoderTester {
[email protected]fb13c762010-07-24 02:22:07207 public:
[email protected]8b6d3d02013-09-13 22:43:41208 VideoEncoderTester()
209 : decoder_tester_(NULL),
[email protected]fb13c762010-07-24 02:22:07210 data_available_(0) {
211 }
212
[email protected]92b45b8e2012-08-24 19:46:47213 ~VideoEncoderTester() {
[email protected]fb13c762010-07-24 02:22:07214 EXPECT_GT(data_available_, 0);
215 }
216
[email protected]3361e1f2012-03-20 20:31:44217 void DataAvailable(scoped_ptr<VideoPacket> packet) {
[email protected]fb13c762010-07-24 02:22:07218 ++data_available_;
[email protected]d9004e42012-08-24 01:47:37219 // Send the message to the VideoDecoderTester.
[email protected]fb13c762010-07-24 02:22:07220 if (decoder_tester_) {
[email protected]3361e1f2012-03-20 20:31:44221 decoder_tester_->ReceivedPacket(packet.get());
[email protected]cee5dba2010-12-07 03:19:48222 }
[email protected]fb13c762010-07-24 02:22:07223 }
224
[email protected]d9004e42012-08-24 01:47:37225 void set_decoder_tester(VideoDecoderTester* decoder_tester) {
[email protected]fb13c762010-07-24 02:22:07226 decoder_tester_ = decoder_tester;
227 }
228
229 private:
[email protected]d9004e42012-08-24 01:47:37230 VideoDecoderTester* decoder_tester_;
[email protected]fb13c762010-07-24 02:22:07231 int data_available_;
232
[email protected]92b45b8e2012-08-24 19:46:47233 DISALLOW_COPY_AND_ASSIGN(VideoEncoderTester);
[email protected]fb13c762010-07-24 02:22:07234};
235
[email protected]c5a0f6012014-07-01 06:44:34236scoped_ptr<DesktopFrame> PrepareFrame(const DesktopSize& size) {
237 scoped_ptr<DesktopFrame> frame(new BasicDesktopFrame(size));
[email protected]04499fb2012-08-25 00:33:50238
[email protected]fb13c762010-07-24 02:22:07239 srand(0);
[email protected]b9ed58f2013-05-16 10:45:24240 int memory_size = size.width() * size.height() * kBytesPerPixel;
[email protected]1d65f482012-07-28 06:40:46241 for (int i = 0; i < memory_size; ++i) {
[email protected]b9ed58f2013-05-16 10:45:24242 frame->data()[i] = rand() % 256;
[email protected]fb13c762010-07-24 02:22:07243 }
244
[email protected]b9ed58f2013-05-16 10:45:24245 return frame.Pass();
[email protected]fb13c762010-07-24 02:22:07246}
247
[email protected]92b45b8e2012-08-24 19:46:47248static void TestEncodingRects(VideoEncoder* encoder,
249 VideoEncoderTester* tester,
wez43ac2662015-06-10 18:22:29250 DesktopFrame* frame,
[email protected]b9ed58f2013-05-16 10:45:24251 const DesktopRect* rects,
252 int count) {
253 frame->mutable_updated_region()->Clear();
[email protected]88552a92010-08-06 22:50:00254 for (int i = 0; i < count; ++i) {
[email protected]b9ed58f2013-05-16 10:45:24255 frame->mutable_updated_region()->AddRect(rects[i]);
[email protected]88552a92010-08-06 22:50:00256 }
[email protected]fb13c762010-07-24 02:22:07257
[email protected]8b6d3d02013-09-13 22:43:41258 scoped_ptr<VideoPacket> packet = encoder->Encode(*frame);
259 tester->DataAvailable(packet.Pass());
[email protected]fb13c762010-07-24 02:22:07260}
261
[email protected]92b45b8e2012-08-24 19:46:47262void TestVideoEncoder(VideoEncoder* encoder, bool strict) {
[email protected]8c6d71d2012-10-23 21:20:04263 const int kSizes[] = {320, 319, 317, 150};
[email protected]1d65f482012-07-28 06:40:46264
[email protected]8b6d3d02013-09-13 22:43:41265 VideoEncoderTester tester;
[email protected]fb13c762010-07-24 02:22:07266
[email protected]8c6d71d2012-10-23 21:20:04267 for (size_t xi = 0; xi < arraysize(kSizes); ++xi) {
268 for (size_t yi = 0; yi < arraysize(kSizes); ++yi) {
[email protected]b9ed58f2013-05-16 10:45:24269 DesktopSize size = DesktopSize(kSizes[xi], kSizes[yi]);
wez43ac2662015-06-10 18:22:29270 scoped_ptr<DesktopFrame> frame = PrepareFrame(size);
[email protected]b9ed58f2013-05-16 10:45:24271 std::vector<std::vector<DesktopRect> > test_rect_lists =
[email protected]8c6d71d2012-10-23 21:20:04272 MakeTestRectLists(size);
273 for (size_t i = 0; i < test_rect_lists.size(); ++i) {
[email protected]b9ed58f2013-05-16 10:45:24274 const std::vector<DesktopRect>& test_rects = test_rect_lists[i];
275 TestEncodingRects(encoder, &tester, frame.get(),
[email protected]8c6d71d2012-10-23 21:20:04276 &test_rects[0], test_rects.size());
277 }
wez43ac2662015-06-10 18:22:29278
279 // Pass some empty frames through the encoder.
280 for (int i = 0; i < 10; ++i) {
281 TestEncodingRects(encoder, &tester, frame.get(), nullptr, 0);
282 }
[email protected]8c6d71d2012-10-23 21:20:04283 }
[email protected]1d65f482012-07-28 06:40:46284 }
[email protected]fb13c762010-07-24 02:22:07285}
286
wez43ac2662015-06-10 18:22:29287void TestVideoEncoderEmptyFrames(VideoEncoder* encoder, int topoff_frames) {
288 const DesktopSize kSize(640, 480);
289 scoped_ptr<DesktopFrame> frame(PrepareFrame(kSize));
290
291 frame->mutable_updated_region()->SetRect(
292 webrtc::DesktopRect::MakeSize(kSize));
293 EXPECT_TRUE(encoder->Encode(*frame));
294
295 frame->mutable_updated_region()->Clear();
296 for (int i=0; i < topoff_frames; ++i) {
297 EXPECT_TRUE(encoder->Encode(*frame));
298 }
299
300 EXPECT_FALSE(encoder->Encode(*frame));
301}
302
[email protected]92b45b8e2012-08-24 19:46:47303static void TestEncodeDecodeRects(VideoEncoder* encoder,
304 VideoEncoderTester* encoder_tester,
[email protected]d9004e42012-08-24 01:47:37305 VideoDecoderTester* decoder_tester,
[email protected]c5a0f6012014-07-01 06:44:34306 DesktopFrame* frame,
[email protected]b9ed58f2013-05-16 10:45:24307 const DesktopRect* rects, int count) {
308 frame->mutable_updated_region()->Clear();
309 for (int i = 0; i < count; ++i) {
310 frame->mutable_updated_region()->AddRect(rects[i]);
311 }
[email protected]fb13c762010-07-24 02:22:07312 decoder_tester->AddRects(rects, count);
[email protected]fb13c762010-07-24 02:22:07313
[email protected]a9c88d12012-01-29 03:45:17314 // Generate random data for the updated region.
[email protected]66db1af92010-07-27 01:42:46315 srand(0);
316 for (int i = 0; i < count; ++i) {
[email protected]b9ed58f2013-05-16 10:45:24317 const int row_size =
[email protected]c5a0f6012014-07-01 06:44:34318 DesktopFrame::kBytesPerPixel * rects[i].width();
[email protected]b9ed58f2013-05-16 10:45:24319 uint8* memory = frame->data() +
320 frame->stride() * rects[i].top() +
[email protected]c5a0f6012014-07-01 06:44:34321 DesktopFrame::kBytesPerPixel * rects[i].left();
[email protected]a9c88d12012-01-29 03:45:17322 for (int y = 0; y < rects[i].height(); ++y) {
[email protected]66db1af92010-07-27 01:42:46323 for (int x = 0; x < row_size; ++x)
324 memory[x] = rand() % 256;
[email protected]b9ed58f2013-05-16 10:45:24325 memory += frame->stride();
[email protected]66db1af92010-07-27 01:42:46326 }
327 }
328
[email protected]8b6d3d02013-09-13 22:43:41329 scoped_ptr<VideoPacket> packet = encoder->Encode(*frame);
330 encoder_tester->DataAvailable(packet.Pass());
[email protected]137e58f12010-12-07 19:35:43331 decoder_tester->VerifyResults();
332 decoder_tester->Reset();
[email protected]fb13c762010-07-24 02:22:07333}
334
[email protected]92b45b8e2012-08-24 19:46:47335void TestVideoEncoderDecoder(
336 VideoEncoder* encoder, VideoDecoder* decoder, bool strict) {
[email protected]b9ed58f2013-05-16 10:45:24337 DesktopSize kSize = DesktopSize(320, 240);
[email protected]1d65f482012-07-28 06:40:46338
[email protected]8b6d3d02013-09-13 22:43:41339 VideoEncoderTester encoder_tester;
[email protected]fb13c762010-07-24 02:22:07340
[email protected]c5a0f6012014-07-01 06:44:34341 scoped_ptr<DesktopFrame> frame = PrepareFrame(kSize);
[email protected]dc454a7c2011-08-12 22:01:13342
[email protected]d9004e42012-08-24 01:47:37343 VideoDecoderTester decoder_tester(decoder, kSize, kSize);
[email protected]fb13c762010-07-24 02:22:07344 decoder_tester.set_strict(strict);
[email protected]b9ed58f2013-05-16 10:45:24345 decoder_tester.set_frame(frame.get());
[email protected]fb13c762010-07-24 02:22:07346 encoder_tester.set_decoder_tester(&decoder_tester);
347
[email protected]b9ed58f2013-05-16 10:45:24348 std::vector<std::vector<DesktopRect> > test_rect_lists =
349 MakeTestRectLists(kSize);
[email protected]1d65f482012-07-28 06:40:46350 for (size_t i = 0; i < test_rect_lists.size(); ++i) {
[email protected]b9ed58f2013-05-16 10:45:24351 const std::vector<DesktopRect> test_rects = test_rect_lists[i];
352 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester,
353 frame.get(), &test_rects[0], test_rects.size());
[email protected]1d65f482012-07-28 06:40:46354 }
[email protected]fb13c762010-07-24 02:22:07355}
356
[email protected]c5a0f6012014-07-01 06:44:34357static void FillWithGradient(DesktopFrame* frame) {
[email protected]b9ed58f2013-05-16 10:45:24358 for (int j = 0; j < frame->size().height(); ++j) {
359 uint8* p = frame->data() + j * frame->stride();
360 for (int i = 0; i < frame->size().width(); ++i) {
361 *p++ = (255.0 * i) / frame->size().width();
362 *p++ = (164.0 * j) / frame->size().height();
363 *p++ = (82.0 * (i + j)) /
364 (frame->size().width() + frame->size().height());
[email protected]36b967f2012-07-27 18:35:32365 *p++ = 0;
366 }
367 }
368}
369
[email protected]92b45b8e2012-08-24 19:46:47370void TestVideoEncoderDecoderGradient(VideoEncoder* encoder,
371 VideoDecoder* decoder,
[email protected]b9ed58f2013-05-16 10:45:24372 const DesktopSize& screen_size,
373 const DesktopSize& view_size,
[email protected]92b45b8e2012-08-24 19:46:47374 double max_error_limit,
375 double mean_error_limit) {
[email protected]c5a0f6012014-07-01 06:44:34376 scoped_ptr<BasicDesktopFrame> frame(
377 new BasicDesktopFrame(screen_size));
[email protected]b9ed58f2013-05-16 10:45:24378 FillWithGradient(frame.get());
379 frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(screen_size));
[email protected]1d65f482012-07-28 06:40:46380
[email protected]c5a0f6012014-07-01 06:44:34381 scoped_ptr<BasicDesktopFrame> expected_result(
382 new BasicDesktopFrame(view_size));
[email protected]b9ed58f2013-05-16 10:45:24383 FillWithGradient(expected_result.get());
[email protected]36b967f2012-07-27 18:35:32384
[email protected]d9004e42012-08-24 01:47:37385 VideoDecoderTester decoder_tester(decoder, screen_size, view_size);
[email protected]b9ed58f2013-05-16 10:45:24386 decoder_tester.set_frame(frame.get());
387 decoder_tester.AddRegion(frame->updated_region());
[email protected]36b967f2012-07-27 18:35:32388
[email protected]8b6d3d02013-09-13 22:43:41389 scoped_ptr<VideoPacket> packet = encoder->Encode(*frame);
390 decoder_tester.ReceivedScopedPacket(packet.Pass());
[email protected]36b967f2012-07-27 18:35:32391
[email protected]b9ed58f2013-05-16 10:45:24392 decoder_tester.VerifyResultsApprox(expected_result->data(),
[email protected]1d65f482012-07-28 06:40:46393 max_error_limit, mean_error_limit);
394
395 // Check that the decoder correctly re-renders the frame if its client
396 // invalidates the frame.
397 decoder_tester.ResetRenderedData();
[email protected]b9ed58f2013-05-16 10:45:24398 decoder->Invalidate(
[email protected]c5a0f6012014-07-01 06:44:34399 DesktopSize(view_size.width(), view_size.height()),
400 DesktopRegion(
401 DesktopRect::MakeWH(view_size.width(), view_size.height())));
[email protected]1d65f482012-07-28 06:40:46402 decoder_tester.RenderFrame();
[email protected]b9ed58f2013-05-16 10:45:24403 decoder_tester.VerifyResultsApprox(expected_result->data(),
[email protected]1d65f482012-07-28 06:40:46404 max_error_limit, mean_error_limit);
[email protected]36b967f2012-07-27 18:35:32405}
406
[email protected]c5a0f6012014-07-01 06:44:34407float MeasureVideoEncoderFpsWithSize(VideoEncoder* encoder,
408 const DesktopSize& size) {
409 scoped_ptr<DesktopFrame> frame(PrepareFrame(size));
410 frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(size));
411 std::list<DesktopFrame*> frames;
412 frames.push_back(frame.get());
413 return MeasureVideoEncoderFpsWithFrames(encoder, frames);
414}
415
416float MeasureVideoEncoderFpsWithFrames(VideoEncoder* encoder,
417 const std::list<DesktopFrame*>& frames) {
418 const base::TimeDelta kTestTime = base::TimeDelta::FromSeconds(1);
419
420 // Encode some frames to "warm up" the encoder (i.e. to let it set up initial
421 // structures, establish a stable working set, etc), then encode at least
422 // kMinimumFrameCount frames to measure the encoder's performance.
423 const int kWarmUpFrameCount = 10;
424 const int kMinimumFrameCount = 10;
425 base::TimeTicks start_time;
426 base::TimeDelta elapsed;
427 std::list<DesktopFrame*> test_frames;
428 int frame_count;
429 for (frame_count = 0;
430 (frame_count < kMinimumFrameCount + kWarmUpFrameCount ||
431 elapsed < kTestTime);
432 ++frame_count) {
433 if (frame_count == kWarmUpFrameCount) {
434 start_time = base::TimeTicks::Now();
435 }
436
437 if (test_frames.empty()) {
438 test_frames = frames;
439 }
440 scoped_ptr<VideoPacket> packet = encoder->Encode(*test_frames.front());
441 test_frames.pop_front();
442
443 if (frame_count >= kWarmUpFrameCount) {
444 elapsed = base::TimeTicks::Now() - start_time;
445 }
446 }
447
448 return (frame_count * base::TimeDelta::FromSeconds(1)) / elapsed;
449}
450
[email protected]fb13c762010-07-24 02:22:07451} // namespace remoting