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

Side by Side Diff: webrtc/common_video/libyuv/scaler_unittest.cc

Issue 2020593002: Refactor scaling. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Trivial rebase. Created 4 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
« no previous file with comments | « webrtc/common_video/libyuv/scaler.cc ('k') | webrtc/common_video/libyuv/webrtc_libyuv.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <math.h>
12 #include <string.h>
13
14 #include <memory>
15
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/base/timeutils.h"
18 #include "webrtc/common_video/libyuv/include/scaler.h"
19 #include "webrtc/test/testsupport/fileutils.h"
20
21 namespace webrtc {
22
23 class TestScaler : public ::testing::Test {
24 protected:
25 TestScaler();
26 virtual void SetUp();
27 virtual void TearDown();
28
29 void ScaleSequence(ScaleMethod method,
30 FILE* source_file, std::string out_name,
31 int src_width, int src_height,
32 int dst_width, int dst_height);
33 // Computes the sequence average PSNR between an input sequence in
34 // |input_file| and an output sequence with filename |out_name|. |width| and
35 // |height| are the frame sizes of both sequences.
36 double ComputeAvgSequencePSNR(FILE* input_file, std::string out_name,
37 int width, int height);
38
39 Scaler test_scaler_;
40 FILE* source_file_;
41 VideoFrame test_frame_;
42 const int width_;
43 const int half_width_;
44 const int height_;
45 const int half_height_;
46 const int size_y_;
47 const int size_uv_;
48 const size_t frame_length_;
49 };
50
51 TestScaler::TestScaler()
52 : source_file_(NULL),
53 width_(352),
54 half_width_(width_ / 2),
55 height_(288),
56 half_height_(height_ / 2),
57 size_y_(width_ * height_),
58 size_uv_(half_width_ * half_height_),
59 frame_length_(CalcBufferSize(kI420, width_, height_)) {
60 }
61
62 void TestScaler::SetUp() {
63 const std::string input_file_name =
64 webrtc::test::ResourcePath("foreman_cif", "yuv");
65 source_file_ = fopen(input_file_name.c_str(), "rb");
66 ASSERT_TRUE(source_file_ != NULL) << "Cannot read file: "<<
67 input_file_name << "\n";
68 test_frame_.CreateEmptyFrame(width_, height_,
69 width_, half_width_, half_width_);
70 }
71
72 void TestScaler::TearDown() {
73 if (source_file_ != NULL) {
74 ASSERT_EQ(0, fclose(source_file_));
75 }
76 source_file_ = NULL;
77 }
78
79 TEST_F(TestScaler, ScaleWithoutSettingValues) {
80 EXPECT_EQ(-2, test_scaler_.Scale(test_frame_, &test_frame_));
81 }
82
83 TEST_F(TestScaler, ScaleBadInitialValues) {
84 EXPECT_EQ(-1, test_scaler_.Set(0, 288, 352, 288, kI420, kI420, kScalePoint));
85 EXPECT_EQ(-1, test_scaler_.Set(704, 0, 352, 288, kI420, kI420, kScaleBox));
86 EXPECT_EQ(-1, test_scaler_.Set(704, 576, 352, 0, kI420, kI420,
87 kScaleBilinear));
88 EXPECT_EQ(-1, test_scaler_.Set(704, 576, 0, 288, kI420, kI420, kScalePoint));
89 }
90
91 TEST_F(TestScaler, ScaleSendingNullSourcePointer) {
92 VideoFrame null_src_frame;
93 EXPECT_EQ(-1, test_scaler_.Scale(null_src_frame, &test_frame_));
94 }
95
96 TEST_F(TestScaler, ScaleSendingBufferTooSmall) {
97 // Sending a buffer which is too small (should reallocate and update size)
98 EXPECT_EQ(0, test_scaler_.Set(width_, height_,
99 half_width_, half_height_,
100 kI420, kI420,
101 kScalePoint));
102 VideoFrame test_frame2;
103 std::unique_ptr<uint8_t[]> orig_buffer(new uint8_t[frame_length_]);
104 EXPECT_GT(fread(orig_buffer.get(), 1, frame_length_, source_file_), 0U);
105 test_frame_.CreateFrame(orig_buffer.get(),
106 orig_buffer.get() + size_y_,
107 orig_buffer.get() + size_y_ + size_uv_,
108 width_, height_,
109 width_, half_width_, half_width_,
110 kVideoRotation_0);
111 EXPECT_EQ(0, test_scaler_.Scale(test_frame_, &test_frame2));
112 EXPECT_GT(width_ * height_, test_frame2.allocated_size(kYPlane));
113 EXPECT_GT(size_uv_, test_frame2.allocated_size(kUPlane));
114 EXPECT_GT(size_uv_, test_frame2.allocated_size(kVPlane));
115 EXPECT_EQ(half_width_, test_frame2.width());
116 EXPECT_EQ(half_height_, test_frame2.height());
117 }
118
119 // TODO(mikhal): Converge the test into one function that accepts the method.
120 #if defined(WEBRTC_ANDROID)
121 #define MAYBE_PointScaleTest DISABLED_PointScaleTest
122 #else
123 #define MAYBE_PointScaleTest PointScaleTest
124 #endif
125 TEST_F(TestScaler, MAYBE_PointScaleTest) {
126 double avg_psnr;
127 FILE* source_file2;
128 ScaleMethod method = kScalePoint;
129 std::string out_name = webrtc::test::OutputPath() +
130 "LibYuvTest_PointScale_176_144.yuv";
131 ScaleSequence(method,
132 source_file_, out_name,
133 width_, height_,
134 half_width_, half_height_);
135 // Upsample back up and check PSNR.
136 source_file2 = fopen(out_name.c_str(), "rb");
137 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
138 "upfrom_176_144.yuv";
139 ScaleSequence(method,
140 source_file2, out_name,
141 176, 144,
142 352, 288);
143 avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
144 printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
145 "original size: %f \n", width_, height_, 176, 144, avg_psnr);
146 // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
147 // average PSNR under same conditions.
148 ASSERT_GT(avg_psnr, 27.9);
149 ASSERT_EQ(0, fclose(source_file2));
150 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_320_240.yuv";
151 ScaleSequence(method,
152 source_file_, out_name,
153 width_, height_,
154 320, 240);
155 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_704_576.yuv";
156 ScaleSequence(method,
157 source_file_, out_name,
158 width_, height_,
159 width_ * 2, height_ * 2);
160 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_300_200.yuv";
161 ScaleSequence(method,
162 source_file_, out_name,
163 width_, height_,
164 300, 200);
165 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_400_300.yuv";
166 ScaleSequence(method,
167 source_file_, out_name,
168 width_, height_,
169 400, 300);
170 // Down-sample to odd size frame and scale back up.
171 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_282_231.yuv";
172 ScaleSequence(method,
173 source_file_, out_name,
174 width_, height_,
175 282, 231);
176 source_file2 = fopen(out_name.c_str(), "rb");
177 out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
178 "upfrom_282_231.yuv";
179 ScaleSequence(method,
180 source_file2, out_name,
181 282, 231,
182 352, 288);
183 avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
184 printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
185 "original size: %f \n", width_, height_, 282, 231, avg_psnr);
186 // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
187 // average PSNR under same conditions.
188 ASSERT_GT(avg_psnr, 25.8);
189 ASSERT_EQ(0, fclose(source_file2));
190 }
191
192 #if defined(WEBRTC_ANDROID)
193 #define MAYBE_BilinearScaleTest DISABLED_BiLinearScaleTest
194 #else
195 #define MAYBE_BilinearScaleTest BiLinearScaleTest
196 #endif
197 TEST_F(TestScaler, MAYBE_BiLinearScaleTest) {
198 double avg_psnr;
199 FILE* source_file2;
200 ScaleMethod method = kScaleBilinear;
201 std::string out_name = webrtc::test::OutputPath() +
202 "LibYuvTest_BilinearScale_176_144.yuv";
203 ScaleSequence(method,
204 source_file_, out_name,
205 width_, height_,
206 width_ / 2, height_ / 2);
207 // Up-sample back up and check PSNR.
208 source_file2 = fopen(out_name.c_str(), "rb");
209 out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
210 "upfrom_176_144.yuv";
211 ScaleSequence(method,
212 source_file2, out_name,
213 176, 144,
214 352, 288);
215 avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
216 printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
217 "original size: %f \n", width_, height_, 176, 144, avg_psnr);
218 // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
219 // average PSNR under same conditions.
220 ASSERT_GT(avg_psnr, 27.5);
221 ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
222 ASSERT_EQ(0, fclose(source_file2));
223 out_name = webrtc::test::OutputPath() +
224 "LibYuvTest_BilinearScale_320_240.yuv";
225 ScaleSequence(method,
226 source_file_, out_name,
227 width_, height_,
228 320, 240);
229 out_name = webrtc::test::OutputPath() +
230 "LibYuvTest_BilinearScale_704_576.yuv";
231 ScaleSequence(method,
232 source_file_, out_name,
233 width_, height_,
234 width_ * 2, height_ * 2);
235 out_name = webrtc::test::OutputPath() +
236 "LibYuvTest_BilinearScale_300_200.yuv";
237 ScaleSequence(method,
238 source_file_, out_name,
239 width_, height_,
240 300, 200);
241 out_name = webrtc::test::OutputPath() +
242 "LibYuvTest_BilinearScale_400_300.yuv";
243 ScaleSequence(method,
244 source_file_, out_name,
245 width_, height_,
246 400, 300);
247 }
248
249 #if defined(WEBRTC_ANDROID)
250 #define MAYBE_BoxScaleTest DISABLED_BoxScaleTest
251 #else
252 #define MAYBE_BoxScaleTest BoxScaleTest
253 #endif
254 TEST_F(TestScaler, MAYBE_BoxScaleTest) {
255 double avg_psnr;
256 FILE* source_file2;
257 ScaleMethod method = kScaleBox;
258 std::string out_name = webrtc::test::OutputPath() +
259 "LibYuvTest_BoxScale_176_144.yuv";
260 ScaleSequence(method,
261 source_file_, out_name,
262 width_, height_,
263 width_ / 2, height_ / 2);
264 // Up-sample back up and check PSNR.
265 source_file2 = fopen(out_name.c_str(), "rb");
266 out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
267 "upfrom_176_144.yuv";
268 ScaleSequence(method,
269 source_file2, out_name,
270 176, 144,
271 352, 288);
272 avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
273 printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
274 "original size: %f \n", width_, height_, 176, 144, avg_psnr);
275 // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
276 // average PSNR under same conditions.
277 ASSERT_GT(avg_psnr, 27.5);
278 ASSERT_EQ(0, fclose(source_file2));
279 out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_320_240.yuv";
280 ScaleSequence(method,
281 source_file_, out_name,
282 width_, height_,
283 320, 240);
284 out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_704_576.yuv";
285 ScaleSequence(method,
286 source_file_, out_name,
287 width_, height_,
288 width_ * 2, height_ * 2);
289 out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_300_200.yuv";
290 ScaleSequence(method,
291 source_file_, out_name,
292 width_, height_,
293 300, 200);
294 out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_400_300.yuv";
295 ScaleSequence(method,
296 source_file_, out_name,
297 width_, height_,
298 400, 300);
299 }
300
301 double TestScaler::ComputeAvgSequencePSNR(FILE* input_file,
302 std::string out_name,
303 int width, int height) {
304 FILE* output_file;
305 output_file = fopen(out_name.c_str(), "rb");
306 assert(output_file != NULL);
307 rewind(input_file);
308 rewind(output_file);
309
310 size_t required_size = CalcBufferSize(kI420, width, height);
311 uint8_t* input_buffer = new uint8_t[required_size];
312 uint8_t* output_buffer = new uint8_t[required_size];
313
314 int frame_count = 0;
315 double avg_psnr = 0;
316 VideoFrame in_frame, out_frame;
317 const int half_width = (width + 1) / 2;
318 in_frame.CreateEmptyFrame(width, height, width, half_width, half_width);
319 out_frame.CreateEmptyFrame(width, height, width, half_width, half_width);
320 while (feof(input_file) == 0) {
321 if (fread(input_buffer, 1, required_size, input_file) != required_size) {
322 break;
323 }
324 if (fread(output_buffer, 1, required_size, output_file) != required_size) {
325 break;
326 }
327 frame_count++;
328 EXPECT_EQ(0, ConvertToI420(kI420, input_buffer, 0, 0, width, height,
329 required_size, kVideoRotation_0, &in_frame));
330 EXPECT_EQ(0, ConvertToI420(kI420, output_buffer, 0, 0, width, height,
331 required_size, kVideoRotation_0, &out_frame));
332 double psnr = I420PSNR(&in_frame, &out_frame);
333 avg_psnr += psnr;
334 }
335 avg_psnr = avg_psnr / frame_count;
336 assert(0 == fclose(output_file));
337 delete [] input_buffer;
338 delete [] output_buffer;
339 return avg_psnr;
340 }
341
342 // TODO(mikhal): Move part to a separate scale test.
343 void TestScaler::ScaleSequence(ScaleMethod method,
344 FILE* source_file, std::string out_name,
345 int src_width, int src_height,
346 int dst_width, int dst_height) {
347 FILE* output_file;
348 EXPECT_EQ(0, test_scaler_.Set(src_width, src_height,
349 dst_width, dst_height,
350 kI420, kI420, method));
351
352 output_file = fopen(out_name.c_str(), "wb");
353 ASSERT_TRUE(output_file != NULL);
354
355 rewind(source_file);
356
357 VideoFrame input_frame;
358 VideoFrame output_frame;
359 int64_t start_clock, total_clock;
360 total_clock = 0;
361 int frame_count = 0;
362 size_t src_required_size = CalcBufferSize(kI420, src_width, src_height);
363 std::unique_ptr<uint8_t[]> frame_buffer(new uint8_t[src_required_size]);
364 int size_y = src_width * src_height;
365 int size_uv = ((src_width + 1) / 2) * ((src_height + 1) / 2);
366
367 // Running through entire sequence.
368 while (feof(source_file) == 0) {
369 if (fread(frame_buffer.get(), 1, src_required_size, source_file) !=
370 src_required_size)
371 break;
372
373 input_frame.CreateFrame(frame_buffer.get(),
374 frame_buffer.get() + size_y,
375 frame_buffer.get() + size_y + size_uv,
376 src_width, src_height,
377 src_width, (src_width + 1) / 2,
378 (src_width + 1) / 2,
379 kVideoRotation_0);
380
381 start_clock = rtc::TimeMillis();
382 EXPECT_EQ(0, test_scaler_.Scale(input_frame, &output_frame));
383 total_clock += rtc::TimeMillis() - start_clock;
384 if (PrintVideoFrame(output_frame, output_file) < 0) {
385 return;
386 }
387 frame_count++;
388 }
389
390 if (frame_count) {
391 printf("Scaling[%d %d] => [%d %d]: ",
392 src_width, src_height, dst_width, dst_height);
393 printf("Average time per frame[ms]: %.2lf\n",
394 (static_cast<double>(total_clock) / frame_count));
395 }
396 ASSERT_EQ(0, fclose(output_file));
397 }
398
399 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/common_video/libyuv/scaler.cc ('k') | webrtc/common_video/libyuv/webrtc_libyuv.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698