Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / common_video / libyuv / scaler_unittest.cc
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 "testing/gtest/include/gtest/gtest.h"
15 #include "webrtc/common_video/libyuv/include/scaler.h"
16 #include "webrtc/system_wrappers/interface/tick_util.h"
17 #include "webrtc/test/testsupport/fileutils.h"
18 #include "webrtc/test/testsupport/gtest_disable.h"
19
20 namespace webrtc {
21
22 class TestScaler : public ::testing::Test {
23  protected:
24   TestScaler();
25   virtual void SetUp();
26   virtual void TearDown();
27
28   void ScaleSequence(ScaleMethod method,
29                      FILE* source_file, std::string out_name,
30                      int src_width, int src_height,
31                      int dst_width, int dst_height);
32   // Computes the sequence average PSNR between an input sequence in
33   // |input_file| and an output sequence with filename |out_name|. |width| and
34   // |height| are the frame sizes of both sequences.
35   double ComputeAvgSequencePSNR(FILE* input_file, std::string out_name,
36                                 int width, int height);
37
38   Scaler test_scaler_;
39   FILE* source_file_;
40   I420VideoFrame test_frame_;
41   const int width_;
42   const int half_width_;
43   const int height_;
44   const int half_height_;
45   const int size_y_;
46   const int size_uv_;
47   const int frame_length_;
48 };
49
50 TestScaler::TestScaler()
51     : source_file_(NULL),
52       width_(352),
53       half_width_(width_ / 2),
54       height_(288),
55       half_height_(height_ / 2),
56       size_y_(width_ * height_),
57       size_uv_(half_width_ * half_height_),
58       frame_length_(CalcBufferSize(kI420, width_, height_)) {
59 }
60
61 void TestScaler::SetUp() {
62   const std::string input_file_name =
63       webrtc::test::ResourcePath("foreman_cif", "yuv");
64   source_file_  = fopen(input_file_name.c_str(), "rb");
65   ASSERT_TRUE(source_file_ != NULL) << "Cannot read file: "<<
66                                        input_file_name << "\n";
67   test_frame_.CreateEmptyFrame(width_, height_,
68                                width_, half_width_, half_width_);
69 }
70
71 void TestScaler::TearDown() {
72   if (source_file_ != NULL) {
73     ASSERT_EQ(0, fclose(source_file_));
74   }
75   source_file_ = NULL;
76 }
77
78 TEST_F(TestScaler, ScaleWithoutSettingValues) {
79   EXPECT_EQ(-2, test_scaler_.Scale(test_frame_, &test_frame_));
80 }
81
82 TEST_F(TestScaler, ScaleBadInitialValues) {
83   EXPECT_EQ(-1, test_scaler_.Set(0, 288, 352, 288, kI420, kI420, kScalePoint));
84   EXPECT_EQ(-1, test_scaler_.Set(704, 0, 352, 288, kI420, kI420, kScaleBox));
85   EXPECT_EQ(-1, test_scaler_.Set(704, 576, 352, 0, kI420, kI420,
86                                  kScaleBilinear));
87   EXPECT_EQ(-1, test_scaler_.Set(704, 576, 0, 288, kI420, kI420, kScalePoint));
88 }
89
90 TEST_F(TestScaler, ScaleSendingNullSourcePointer) {
91   I420VideoFrame null_src_frame;
92   EXPECT_EQ(-1, test_scaler_.Scale(null_src_frame, &test_frame_));
93 }
94
95 TEST_F(TestScaler, ScaleSendingBufferTooSmall) {
96   // Sending a buffer which is too small (should reallocate and update size)
97   EXPECT_EQ(0, test_scaler_.Set(width_, height_,
98                                 half_width_, half_height_,
99                                 kI420, kI420,
100                                 kScalePoint));
101   I420VideoFrame test_frame2;
102   scoped_ptr<uint8_t[]> orig_buffer(new uint8_t[frame_length_]);
103   EXPECT_GT(fread(orig_buffer.get(), 1, frame_length_, source_file_), 0U);
104   test_frame_.CreateFrame(size_y_, orig_buffer.get(),
105                           size_uv_, orig_buffer.get() + size_y_,
106                           size_uv_, orig_buffer.get() + size_y_ + size_uv_,
107                           width_, height_,
108                           width_, half_width_, half_width_);
109   EXPECT_EQ(0, test_scaler_.Scale(test_frame_, &test_frame2));
110   EXPECT_GT(width_ * height_, test_frame2.allocated_size(kYPlane));
111   EXPECT_GT(size_uv_, test_frame2.allocated_size(kUPlane));
112   EXPECT_GT(size_uv_, test_frame2.allocated_size(kVPlane));
113   EXPECT_EQ(half_width_, test_frame2.width());
114   EXPECT_EQ(half_height_, test_frame2.height());
115 }
116
117 //TODO (mikhal): Converge the test into one function that accepts the method.
118 TEST_F(TestScaler, DISABLED_ON_ANDROID(PointScaleTest)) {
119   double avg_psnr;
120   FILE* source_file2;
121   ScaleMethod method = kScalePoint;
122   std::string out_name = webrtc::test::OutputPath() +
123                          "LibYuvTest_PointScale_176_144.yuv";
124   ScaleSequence(method,
125                 source_file_, out_name,
126                 width_, height_,
127                 half_width_, half_height_);
128   // Upsample back up and check PSNR.
129   source_file2 = fopen(out_name.c_str(), "rb");
130   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
131       "upfrom_176_144.yuv";
132   ScaleSequence(method,
133                 source_file2, out_name,
134                 176, 144,
135                 352, 288);
136   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
137   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
138       "original size: %f \n", width_, height_, 176, 144, avg_psnr);
139   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
140   // average PSNR under same conditions.
141   ASSERT_GT(avg_psnr, 27.9);
142   ASSERT_EQ(0, fclose(source_file2));
143   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_320_240.yuv";
144   ScaleSequence(method,
145                 source_file_, out_name,
146                 width_, height_,
147                 320, 240);
148   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_704_576.yuv";
149   ScaleSequence(method,
150                 source_file_, out_name,
151                 width_, height_,
152                 width_ * 2, height_ * 2);
153   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_300_200.yuv";
154   ScaleSequence(method,
155                 source_file_, out_name,
156                 width_, height_,
157                 300, 200);
158   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_400_300.yuv";
159   ScaleSequence(method,
160                 source_file_, out_name,
161                 width_, height_,
162                 400, 300);
163   // Down-sample to odd size frame and scale back up.
164   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_282_231.yuv";
165   ScaleSequence(method,
166                 source_file_, out_name,
167                 width_, height_,
168                 282, 231);
169   source_file2 = fopen(out_name.c_str(), "rb");
170   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
171       "upfrom_282_231.yuv";
172   ScaleSequence(method,
173                 source_file2, out_name,
174                 282, 231,
175                 352, 288);
176   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
177   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
178       "original size: %f \n", width_, height_, 282, 231, avg_psnr);
179   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
180   // average PSNR under same conditions.
181   ASSERT_GT(avg_psnr, 25.8);
182   ASSERT_EQ(0, fclose(source_file2));
183   // Up-sample to odd size frame and scale back down.
184   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_699_531.yuv";
185   ScaleSequence(method,
186                 source_file_, out_name,
187                 width_, height_,
188                 699, 531);
189   source_file2 = fopen(out_name.c_str(), "rb");
190   out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
191       "downfrom_699_531.yuv";
192   ScaleSequence(method,
193                 source_file2, out_name,
194                 699, 531,
195                 352, 288);
196   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
197   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
198       "original size: %f \n", width_, height_, 699, 531, avg_psnr);
199   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
200   // average PSNR under same conditions.
201   ASSERT_GT(avg_psnr, 37.8);
202   ASSERT_EQ(0, fclose(source_file2));
203 }
204
205 TEST_F(TestScaler, DISABLED_ON_ANDROID(BiLinearScaleTest)) {
206   double avg_psnr;
207   FILE* source_file2;
208   ScaleMethod method = kScaleBilinear;
209   std::string out_name = webrtc::test::OutputPath() +
210                          "LibYuvTest_BilinearScale_176_144.yuv";
211   ScaleSequence(method,
212                 source_file_, out_name,
213                 width_, height_,
214                 width_ / 2, height_ / 2);
215   // Up-sample back up and check PSNR.
216   source_file2 = fopen(out_name.c_str(), "rb");
217   out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
218       "upfrom_176_144.yuv";
219   ScaleSequence(method,
220                 source_file2, out_name,
221                 176, 144,
222                 352, 288);
223   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
224   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
225       "original size: %f \n", width_, height_, 176, 144, avg_psnr);
226   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
227   // average PSNR under same conditions.
228   ASSERT_GT(avg_psnr, 27.5);
229   ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
230   ASSERT_EQ(0, fclose(source_file2));
231   out_name = webrtc::test::OutputPath() +
232              "LibYuvTest_BilinearScale_320_240.yuv";
233   ScaleSequence(method,
234                 source_file_, out_name,
235                 width_, height_,
236                 320, 240);
237   out_name = webrtc::test::OutputPath() +
238              "LibYuvTest_BilinearScale_704_576.yuv";
239   ScaleSequence(method,
240                 source_file_, out_name,
241                 width_, height_,
242                 width_ * 2, height_ * 2);
243   out_name = webrtc::test::OutputPath() +
244              "LibYuvTest_BilinearScale_300_200.yuv";
245   ScaleSequence(method,
246                 source_file_, out_name,
247                 width_, height_,
248                 300, 200);
249   out_name = webrtc::test::OutputPath() +
250              "LibYuvTest_BilinearScale_400_300.yuv";
251   ScaleSequence(method,
252                 source_file_, out_name,
253                 width_, height_,
254                 400, 300);
255   // Down-sample to odd size frame and scale back up.
256   out_name = webrtc::test::OutputPath() +
257       "LibYuvTest_BilinearScale_282_231.yuv";
258   ScaleSequence(method,
259                 source_file_, out_name,
260                 width_, height_,
261                 282, 231);
262   source_file2 = fopen(out_name.c_str(), "rb");
263   out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
264       "upfrom_282_231.yuv";
265   ScaleSequence(method,
266                 source_file2, out_name,
267                 282, 231,
268                 width_, height_);
269   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
270   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
271       "original size: %f \n", width_, height_, 282, 231, avg_psnr);
272   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
273   // average PSNR under same conditions.
274   ASSERT_GT(avg_psnr, 29.7);
275   ASSERT_EQ(0, fclose(source_file2));
276   // Upsample to odd size frame and scale back down.
277   out_name = webrtc::test::OutputPath() +
278       "LibYuvTest_BilinearScale_699_531.yuv";
279   ScaleSequence(method,
280                 source_file_, out_name,
281                 width_, height_,
282                 699, 531);
283   source_file2 = fopen(out_name.c_str(), "rb");
284   out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
285       "downfrom_699_531.yuv";
286   ScaleSequence(method,
287                 source_file2, out_name,
288                 699, 531,
289                 width_, height_);
290   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
291   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
292       "original size: %f \n", width_, height_, 699, 531, avg_psnr);
293   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
294   // average PSNR under same conditions.
295   ASSERT_GT(avg_psnr, 31.4);
296   ASSERT_EQ(0, fclose(source_file2));
297 }
298
299 TEST_F(TestScaler, DISABLED_ON_ANDROID(BoxScaleTest)) {
300   double avg_psnr;
301   FILE* source_file2;
302   ScaleMethod method = kScaleBox;
303   std::string out_name = webrtc::test::OutputPath() +
304                          "LibYuvTest_BoxScale_176_144.yuv";
305   ScaleSequence(method,
306                 source_file_, out_name,
307                 width_, height_,
308                 width_ / 2, height_ / 2);
309   // Up-sample back up and check PSNR.
310   source_file2 = fopen(out_name.c_str(), "rb");
311   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
312       "upfrom_176_144.yuv";
313   ScaleSequence(method,
314                 source_file2, out_name,
315                 176, 144,
316                 352, 288);
317   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
318   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
319       "original size: %f \n", width_, height_, 176, 144, avg_psnr);
320   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
321   // average PSNR under same conditions.
322   ASSERT_GT(avg_psnr, 27.5);
323   ASSERT_EQ(0, fclose(source_file2));
324   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_320_240.yuv";
325   ScaleSequence(method,
326                 source_file_, out_name,
327                 width_, height_,
328                 320, 240);
329   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_704_576.yuv";
330   ScaleSequence(method,
331                 source_file_, out_name,
332                 width_, height_,
333                 width_ * 2, height_ * 2);
334   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_300_200.yuv";
335   ScaleSequence(method,
336                 source_file_, out_name,
337                 width_, height_,
338                 300, 200);
339   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_400_300.yuv";
340   ScaleSequence(method,
341                 source_file_, out_name,
342                 width_, height_,
343                 400, 300);
344   // Down-sample to odd size frame and scale back up.
345   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_282_231.yuv";
346   ScaleSequence(method,
347                 source_file_, out_name,
348                 width_, height_,
349                 282, 231);
350   source_file2 = fopen(out_name.c_str(), "rb");
351   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
352        "upfrom_282_231.yuv";
353   ScaleSequence(method,
354                 source_file2, out_name,
355                 282, 231,
356                 width_, height_);
357   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
358   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
359       "original size: %f \n", width_, height_, 282, 231, avg_psnr);
360   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
361   // average PSNR under same conditions.
362   ASSERT_GT(avg_psnr, 29.7);
363   ASSERT_EQ(0, fclose(source_file2));
364   // Up-sample to odd size frame and scale back down.
365   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_699_531.yuv";
366   ScaleSequence(method,
367                 source_file_, out_name,
368                 width_, height_,
369                 699, 531);
370   source_file2 = fopen(out_name.c_str(), "rb");
371   out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
372        "downfrom_699_531.yuv";
373   ScaleSequence(method,
374                 source_file2, out_name,
375                 699, 531,
376                 width_, height_);
377   avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
378   printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
379        "original size: %f \n", width_, height_, 699, 531, avg_psnr);
380   // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
381   // average PSNR under same conditions.
382   ASSERT_GT(avg_psnr, 31.4);
383   ASSERT_EQ(0, fclose(source_file2));
384 }
385
386 double TestScaler::ComputeAvgSequencePSNR(FILE* input_file,
387                                           std::string out_name,
388                                           int width, int height) {
389   FILE* output_file;
390   output_file = fopen(out_name.c_str(), "rb");
391   assert(output_file != NULL);
392   rewind(input_file);
393   rewind(output_file);
394
395   int required_size = CalcBufferSize(kI420, width, height);
396   uint8_t* input_buffer = new uint8_t[required_size];
397   uint8_t* output_buffer = new uint8_t[required_size];
398
399   int frame_count = 0;
400   double avg_psnr = 0;
401   I420VideoFrame in_frame, out_frame;
402   while (feof(input_file) == 0) {
403     if ((size_t)required_size !=
404         fread(input_buffer, 1, required_size, input_file)) {
405       break;
406     }
407     if ((size_t)required_size !=
408         fread(output_buffer, 1, required_size, output_file)) {
409       break;
410     }
411     frame_count++;
412     ConvertFromI420(in_frame, kI420, 0, input_buffer);
413     ConvertFromI420(out_frame, kI420, 0, output_buffer);
414     double psnr = I420PSNR(&in_frame, &out_frame);
415     avg_psnr += psnr;
416   }
417   avg_psnr = avg_psnr / frame_count;
418   assert(0 == fclose(output_file));
419   delete [] input_buffer;
420   delete [] output_buffer;
421   return avg_psnr;
422 }
423
424 // TODO (mikhal): Move part to a separate scale test.
425 void TestScaler::ScaleSequence(ScaleMethod method,
426                    FILE* source_file, std::string out_name,
427                    int src_width, int src_height,
428                    int dst_width, int dst_height) {
429   FILE* output_file;
430   EXPECT_EQ(0, test_scaler_.Set(src_width, src_height,
431                                dst_width, dst_height,
432                                kI420, kI420, method));
433
434   output_file = fopen(out_name.c_str(), "wb");
435   ASSERT_TRUE(output_file != NULL);
436
437   rewind(source_file);
438
439   I420VideoFrame input_frame;
440   I420VideoFrame output_frame;
441   int64_t start_clock, total_clock;
442   total_clock = 0;
443   int frame_count = 0;
444   int src_required_size = CalcBufferSize(kI420, src_width, src_height);
445   scoped_ptr<uint8_t[]> frame_buffer(new uint8_t[src_required_size]);
446   int size_y = src_width * src_height;
447   int size_uv = ((src_width + 1) / 2) * ((src_height + 1) / 2);
448
449   // Running through entire sequence.
450   while (feof(source_file) == 0) {
451     if ((size_t)src_required_size !=
452       fread(frame_buffer.get(), 1, src_required_size, source_file))
453       break;
454
455     input_frame.CreateFrame(size_y, frame_buffer.get(),
456                             size_uv, frame_buffer.get() + size_y,
457                             size_uv, frame_buffer.get() + size_y + size_uv,
458                             src_width, src_height,
459                             src_width, (src_width + 1) / 2,
460                             (src_width + 1) / 2);
461
462     start_clock = TickTime::MillisecondTimestamp();
463     EXPECT_EQ(0, test_scaler_.Scale(input_frame, &output_frame));
464     total_clock += TickTime::MillisecondTimestamp() - start_clock;
465     if (PrintI420VideoFrame(output_frame, output_file) < 0) {
466         return;
467     }
468     frame_count++;
469   }
470
471   if (frame_count) {
472     printf("Scaling[%d %d] => [%d %d]: ",
473            src_width, src_height, dst_width, dst_height);
474     printf("Average time per frame[ms]: %.2lf\n",
475              (static_cast<double>(total_clock) / frame_count));
476   }
477   ASSERT_EQ(0, fclose(output_file));
478 }
479
480 }  // namespace webrtc