• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2011 The LibYuv 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 "libyuv/scale.h"
12 #include "unit_test.h"
13 #include <stdlib.h>
14 #include <time.h>
15 
16 using namespace libyuv;
17 
18 #define align_buffer_16(var, size) \
19   uint8 *var; \
20   uint8 *var##_mem; \
21   var##_mem = reinterpret_cast<uint8*>(calloc(size+15, sizeof(uint8))); \
22   var = reinterpret_cast<uint8*> \
23         ((reinterpret_cast<intptr_t>(var##_mem) + 15) & (~0x0f));
24 
25 #define free_aligned_buffer_16(var) \
26   free(var##_mem);  \
27   var = 0;
28 
TEST_F(libyuvTest,ScaleDownBy4)29 TEST_F(libyuvTest, ScaleDownBy4) {
30   int b = 128;
31   int src_width = 1280;
32   int src_height = 720;
33   int src_width_uv = (src_width + 1) >> 1;
34   int src_height_uv = (src_height + 1) >> 1;
35 
36   int src_y_plane_size = (src_width + (2 * b)) * (src_height + (2 * b));
37   int src_uv_plane_size = (src_width_uv + (2 * b)) * (src_height_uv + (2 * b));
38 
39   int src_stride_y = 2 * b + src_width;
40   int src_stride_uv = 2 * b + src_width_uv;
41 
42   align_buffer_16(src_y, src_y_plane_size)
43   align_buffer_16(src_u, src_uv_plane_size)
44   align_buffer_16(src_v, src_uv_plane_size)
45 
46   int dst_width = src_width >> 2;
47   int dst_height = src_height >> 2;
48 
49   int dst_width_uv = (dst_width + 1) >> 1;
50   int dst_height_uv = (dst_height + 1) >> 1;
51 
52   int dst_y_plane_size = (dst_width + (2 * b)) * (dst_height + (2 * b));
53   int dst_uv_plane_size = (dst_width_uv + (2 * b)) * (dst_height_uv + (2 * b));
54 
55   int dst_stride_y = 2 * b + dst_width;
56   int dst_stride_uv = 2 * b + dst_width_uv;
57 
58   align_buffer_16(dst_y, dst_y_plane_size)
59   align_buffer_16(dst_u, dst_uv_plane_size)
60   align_buffer_16(dst_v, dst_uv_plane_size)
61 
62   // create an image with random data reoccurring in 4x4 grid.  When the image
63   // is filtered all the values should be the same.
64   srandom(time(NULL));
65 
66   uint8 block_data[16];
67 
68   int i, j;
69 
70   // Pulling 16 random numbers there is an infinitesimally small
71   //  chance that they are all 0.  Then the output will be all 0.
72   //  Output buffer is filled with 0, want to make sure that after the
73   //  filtering something went into the output buffer.
74   //  Avoid this by setting one of the values to 128.  Also set the
75   //  random data to at least 1 for when point sampling to prevent
76   //  output all being 0.
77   block_data[0] = 128;
78 
79   for (i = 1; i < 16; i++)
80     block_data[i] = (random() & 0xfe) + 1;
81 
82   for (i = b; i < (src_height + b); i += 4) {
83     for (j = b; j < (src_width + b); j += 4) {
84       uint8 *ptr = src_y + (i * src_stride_y) + j;
85       int k, l;
86       for (k = 0; k < 4; ++k)
87         for (l = 0; l < 4; ++l)
88           ptr[k + src_stride_y * l] = block_data[k + 4 * l];
89     }
90   }
91 
92   for (i = 1; i < 16; i++)
93     block_data[i] = (random() & 0xfe) + 1;
94 
95   for (i = b; i < (src_height_uv + b); i += 4) {
96     for (j = b; j < (src_width_uv + b); j += 4) {
97       uint8 *ptru = src_u + (i * src_stride_uv) + j;
98       uint8 *ptrv = src_v + (i * src_stride_uv) + j;
99       int k, l;
100       for (k = 0; k < 4; ++k)
101         for (l = 0; l < 4; ++l) {
102           ptru[k + src_stride_uv * l] = block_data[k + 4 * l];
103           ptrv[k + src_stride_uv * l] = block_data[k + 4 * l];
104         }
105     }
106   }
107 
108   int f;
109   int err = 0;
110 
111   // currently three filter modes, defined as FilterMode in scale.h
112   for (f = 0; f < 3; ++f) {
113     I420Scale(src_y + (src_stride_y * b) + b, src_stride_y,
114               src_u + (src_stride_uv * b) + b, src_stride_uv,
115               src_v + (src_stride_uv * b) + b, src_stride_uv,
116               src_width, src_height,
117               dst_y + (dst_stride_y * b) + b, dst_stride_y,
118               dst_u + (dst_stride_uv * b) + b, dst_stride_uv,
119               dst_v + (dst_stride_uv * b) + b, dst_stride_uv,
120               dst_width, dst_height,
121               static_cast<FilterMode>(f));
122 
123     int value = dst_y[(dst_stride_y * b) + b];
124 
125     // catch the case that the output buffer is all 0
126     if (value == 0)
127       ++err;
128 
129     for (i = b; i < (dst_height + b); ++i) {
130       for (j = b; j < (dst_width + b); ++j) {
131         if (value != dst_y[(i * dst_stride_y) + j])
132           ++err;
133       }
134     }
135 
136     value = dst_u[(dst_stride_uv * b) + b];
137 
138     if (value == 0)
139       ++err;
140 
141     for (i = b; i < (dst_height_uv + b); ++i) {
142       for (j = b; j < (dst_width_uv + b); ++j) {
143         if (value != dst_u[(i * dst_stride_uv) + j])
144           ++err;
145         if (value != dst_v[(i * dst_stride_uv) + j])
146           ++err;
147       }
148     }
149   }
150 
151   free_aligned_buffer_16(src_y)
152   free_aligned_buffer_16(src_u)
153   free_aligned_buffer_16(src_v)
154   free_aligned_buffer_16(dst_y)
155   free_aligned_buffer_16(dst_u)
156   free_aligned_buffer_16(dst_v)
157 
158   EXPECT_EQ(0, err);
159 }
160