blob: f4d1053e47a5a5fb181f26cefb34ef9702e08b3b [file] [log] [blame]
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001/*
fbarchard@google.comb0c97972012-08-08 19:04:24 +00002 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00003 *
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
fbarchard@google.comcde58702013-01-28 00:02:35 +00007 * in the file PATENTS. All contributing project authors may
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00008 * be found in the AUTHORS file in the root of the source tree.
9 */
10
fbarchard@google.coma1280732011-10-14 17:50:12 +000011#include "libyuv/scale.h"
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +000012
mikhal@webrtc.org283eb132011-10-11 18:22:34 +000013#include <assert.h>
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +000014#include <string.h>
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +000015
fbarchard@google.coma1280732011-10-14 17:50:12 +000016#include "libyuv/cpu_id.h"
fbarchard@google.com45b9ef02011-12-16 03:34:09 +000017#include "libyuv/planar_functions.h" // For CopyPlane
fbarchard@google.com142f6c42012-09-18 20:56:51 +000018#include "libyuv/row.h"
fbarchard@google.comdcd87ff2013-09-03 20:00:10 +000019#include "libyuv/scale_row.h"
Frank Barcharde6479022020-09-29 15:49:57 -070020#include "libyuv/scale_uv.h" // For UVScale
fbarchard@google.coma1280732011-10-14 17:50:12 +000021
fbarchard@google.comfe5ff7e2011-12-10 07:45:58 +000022#ifdef __cplusplus
23namespace libyuv {
24extern "C" {
25#endif
26
fbarchard@google.com306e9842013-05-13 17:57:27 +000027static __inline int Abs(int v) {
28 return v >= 0 ? v : -v;
29}
30
fbarchard@google.com99a12982013-12-04 23:36:06 +000031#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
Frank Barchard30f9b282022-06-09 00:14:11 -070032#define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s)
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +000033
fbarchard@google.com3c7bb052013-02-20 22:18:36 +000034// Scale plane, 1/2
35// This is an optimized version for scaling down a plane to 1/2 of
36// its original size.
37
Frank Barcharde62309f2016-11-07 17:37:23 -080038static void ScalePlaneDown2(int src_width,
39 int src_height,
40 int dst_width,
41 int dst_height,
42 int src_stride,
43 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -080044 const uint8_t* src_ptr,
45 uint8_t* dst_ptr,
fbarchard@google.comdb735182014-01-07 03:59:31 +000046 enum FilterMode filtering) {
fbarchard@google.comfa831882014-01-18 01:30:58 +000047 int y;
Frank Barchard7e389882018-01-22 18:35:52 -080048 void (*ScaleRowDown2)(const uint8_t* src_ptr, ptrdiff_t src_stride,
49 uint8_t* dst_ptr, int dst_width) =
Frank Barchard73a603e2017-03-08 09:49:02 -080050 filtering == kFilterNone
51 ? ScaleRowDown2_C
52 : (filtering == kFilterLinear ? ScaleRowDown2Linear_C
53 : ScaleRowDown2Box_C);
Frank Barchardf0cfc1f2021-10-18 10:36:27 -070054 int row_stride = src_stride * 2;
Frank Barchardbbe8c232017-02-15 12:08:43 -080055 (void)src_width;
56 (void)src_height;
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +000057 if (!filtering) {
58 src_ptr += src_stride; // Point to odd rows.
59 src_stride = 0;
60 }
61
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +000062#if defined(HAS_SCALEROWDOWN2_NEON)
fbarchard@google.comd41fbf42015-03-24 23:25:30 +000063 if (TestCpuFlag(kCpuHasNEON)) {
Frank Barcharde62309f2016-11-07 17:37:23 -080064 ScaleRowDown2 =
65 filtering == kFilterNone
66 ? ScaleRowDown2_Any_NEON
67 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_NEON
68 : ScaleRowDown2Box_Any_NEON);
fbarchard@google.comd41fbf42015-03-24 23:25:30 +000069 if (IS_ALIGNED(dst_width, 16)) {
Frank Barcharde62309f2016-11-07 17:37:23 -080070 ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_NEON
71 : (filtering == kFilterLinear
72 ? ScaleRowDown2Linear_NEON
73 : ScaleRowDown2Box_NEON);
fbarchard@google.comd41fbf42015-03-24 23:25:30 +000074 }
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +000075 }
fbarchard@google.comf7136912014-10-16 20:47:22 +000076#endif
Frank Barchardae55e412015-12-14 17:25:36 -080077#if defined(HAS_SCALEROWDOWN2_SSSE3)
78 if (TestCpuFlag(kCpuHasSSSE3)) {
Frank Barcharde62309f2016-11-07 17:37:23 -080079 ScaleRowDown2 =
80 filtering == kFilterNone
81 ? ScaleRowDown2_Any_SSSE3
82 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_SSSE3
83 : ScaleRowDown2Box_Any_SSSE3);
fbarchard@google.comd41fbf42015-03-24 23:25:30 +000084 if (IS_ALIGNED(dst_width, 16)) {
Frank Barcharde62309f2016-11-07 17:37:23 -080085 ScaleRowDown2 =
86 filtering == kFilterNone
87 ? ScaleRowDown2_SSSE3
88 : (filtering == kFilterLinear ? ScaleRowDown2Linear_SSSE3
89 : ScaleRowDown2Box_SSSE3);
fbarchard@google.comd41fbf42015-03-24 23:25:30 +000090 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +000091 }
fbarchard@google.comf7136912014-10-16 20:47:22 +000092#endif
fbarchard@google.come6ca9cc2015-03-26 23:21:08 +000093#if defined(HAS_SCALEROWDOWN2_AVX2)
fbarchard@google.com72673ac2015-03-30 21:46:08 +000094 if (TestCpuFlag(kCpuHasAVX2)) {
Frank Barcharde62309f2016-11-07 17:37:23 -080095 ScaleRowDown2 =
96 filtering == kFilterNone
97 ? ScaleRowDown2_Any_AVX2
98 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_AVX2
99 : ScaleRowDown2Box_Any_AVX2);
fbarchard@google.come6ca9cc2015-03-26 23:21:08 +0000100 if (IS_ALIGNED(dst_width, 32)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800101 ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_AVX2
102 : (filtering == kFilterLinear
103 ? ScaleRowDown2Linear_AVX2
104 : ScaleRowDown2Box_AVX2);
fbarchard@google.come6ca9cc2015-03-26 23:21:08 +0000105 }
106 }
107#endif
Shiyou Yinbed92922020-04-08 15:58:52 +0800108#if defined(HAS_SCALEROWDOWN2_MSA)
109 if (TestCpuFlag(kCpuHasMSA)) {
110 ScaleRowDown2 =
111 filtering == kFilterNone
112 ? ScaleRowDown2_Any_MSA
113 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_MSA
114 : ScaleRowDown2Box_Any_MSA);
115 if (IS_ALIGNED(dst_width, 32)) {
116 ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_MSA
117 : (filtering == kFilterLinear
118 ? ScaleRowDown2Linear_MSA
119 : ScaleRowDown2Box_MSA);
120 }
121 }
122#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +0800123#if defined(HAS_SCALEROWDOWN2_LSX)
124 if (TestCpuFlag(kCpuHasLSX)) {
125 ScaleRowDown2 =
126 filtering == kFilterNone
127 ? ScaleRowDown2_Any_LSX
128 : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_LSX
129 : ScaleRowDown2Box_Any_LSX);
130 if (IS_ALIGNED(dst_width, 32)) {
131 ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_LSX
132 : (filtering == kFilterLinear
133 ? ScaleRowDown2Linear_LSX
134 : ScaleRowDown2Box_LSX);
135 }
136 }
137#endif
Darren Hsieh873eaa32023-05-16 23:47:58 -0700138#if defined(HAS_SCALEROWDOWN2_RVV)
139 if (TestCpuFlag(kCpuHasRVV)) {
140 ScaleRowDown2 = filtering == kFilterNone
141 ? ScaleRowDown2_RVV
142 : (filtering == kFilterLinear ? ScaleRowDown2Linear_RVV
143 : ScaleRowDown2Box_RVV);
144 }
145#endif
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000146
fbarchard@google.com788f7572013-11-11 18:53:19 +0000147 if (filtering == kFilterLinear) {
148 src_stride = 0;
149 }
fbarchard@google.com8ae294e2012-02-02 22:33:21 +0000150 // TODO(fbarchard): Loop through source height to allow odd height.
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000151 for (y = 0; y < dst_height; ++y) {
fbarchard@google.com3faa0f12011-10-20 06:04:16 +0000152 ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000153 src_ptr += row_stride;
fbarchard@google.com3faa0f12011-10-20 06:04:16 +0000154 dst_ptr += dst_stride;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000155 }
156}
157
Frank Barcharde62309f2016-11-07 17:37:23 -0800158static void ScalePlaneDown2_16(int src_width,
159 int src_height,
160 int dst_width,
161 int dst_height,
162 int src_stride,
163 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800164 const uint16_t* src_ptr,
165 uint16_t* dst_ptr,
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000166 enum FilterMode filtering) {
167 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800168 void (*ScaleRowDown2)(const uint16_t* src_ptr, ptrdiff_t src_stride,
169 uint16_t* dst_ptr, int dst_width) =
Frank Barcharde62309f2016-11-07 17:37:23 -0800170 filtering == kFilterNone
171 ? ScaleRowDown2_16_C
172 : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_C
173 : ScaleRowDown2Box_16_C);
Frank Barchardf0cfc1f2021-10-18 10:36:27 -0700174 int row_stride = src_stride * 2;
Frank Barchardbbe8c232017-02-15 12:08:43 -0800175 (void)src_width;
176 (void)src_height;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000177 if (!filtering) {
178 src_ptr += src_stride; // Point to odd rows.
179 src_stride = 0;
180 }
181
182#if defined(HAS_SCALEROWDOWN2_16_NEON)
183 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800184 ScaleRowDown2 =
185 filtering ? ScaleRowDown2Box_16_NEON : ScaleRowDown2_16_NEON;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000186 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000187#endif
188#if defined(HAS_SCALEROWDOWN2_16_SSE2)
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000189 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800190 ScaleRowDown2 =
191 filtering == kFilterNone
192 ? ScaleRowDown2_16_SSE2
193 : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2
194 : ScaleRowDown2Box_16_SSE2);
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000195 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000196#endif
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000197
198 if (filtering == kFilterLinear) {
199 src_stride = 0;
200 }
201 // TODO(fbarchard): Loop through source height to allow odd height.
202 for (y = 0; y < dst_height; ++y) {
203 ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
204 src_ptr += row_stride;
205 dst_ptr += dst_stride;
206 }
207}
208
Sergio Garcia Murillo22a579c2023-01-03 22:09:09 +0100209void ScalePlaneDown2_16To8(int src_width,
210 int src_height,
211 int dst_width,
212 int dst_height,
213 int src_stride,
214 int dst_stride,
215 const uint16_t* src_ptr,
216 uint8_t* dst_ptr,
217 int scale,
218 enum FilterMode filtering) {
219 int y;
220 void (*ScaleRowDown2)(const uint16_t* src_ptr, ptrdiff_t src_stride,
221 uint8_t* dst_ptr, int dst_width, int scale) =
Sergio Garcia Murillob2528b02023-01-23 11:13:48 +0100222 (src_width & 1)
223 ? (filtering == kFilterNone
224 ? ScaleRowDown2_16To8_Odd_C
225 : (filtering == kFilterLinear ? ScaleRowDown2Linear_16To8_Odd_C
226 : ScaleRowDown2Box_16To8_Odd_C))
227 : (filtering == kFilterNone
228 ? ScaleRowDown2_16To8_C
229 : (filtering == kFilterLinear ? ScaleRowDown2Linear_16To8_C
230 : ScaleRowDown2Box_16To8_C));
Sergio Garcia Murillo22a579c2023-01-03 22:09:09 +0100231 int row_stride = src_stride * 2;
Sergio Garcia Murillob2528b02023-01-23 11:13:48 +0100232 (void)dst_height;
Sergio Garcia Murillo22a579c2023-01-03 22:09:09 +0100233 if (!filtering) {
234 src_ptr += src_stride; // Point to odd rows.
235 src_stride = 0;
236 }
237
238 if (filtering == kFilterLinear) {
239 src_stride = 0;
240 }
Sergio Garcia Murillob2528b02023-01-23 11:13:48 +0100241 for (y = 0; y < src_height / 2; ++y) {
Sergio Garcia Murillo22a579c2023-01-03 22:09:09 +0100242 ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width, scale);
243 src_ptr += row_stride;
244 dst_ptr += dst_stride;
245 }
Sergio Garcia Murillob2528b02023-01-23 11:13:48 +0100246 if (src_height & 1) {
247 if (!filtering) {
248 src_ptr -= src_stride; // Point to last row.
249 }
250 ScaleRowDown2(src_ptr, 0, dst_ptr, dst_width, scale);
251 }
Sergio Garcia Murillo22a579c2023-01-03 22:09:09 +0100252}
253
fbarchard@google.com3c7bb052013-02-20 22:18:36 +0000254// Scale plane, 1/4
255// This is an optimized version for scaling down a plane to 1/4 of
256// its original size.
257
Frank Barcharde62309f2016-11-07 17:37:23 -0800258static void ScalePlaneDown4(int src_width,
259 int src_height,
260 int dst_width,
261 int dst_height,
262 int src_stride,
263 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800264 const uint8_t* src_ptr,
265 uint8_t* dst_ptr,
fbarchard@google.comdb735182014-01-07 03:59:31 +0000266 enum FilterMode filtering) {
fbarchard@google.comfa831882014-01-18 01:30:58 +0000267 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800268 void (*ScaleRowDown4)(const uint8_t* src_ptr, ptrdiff_t src_stride,
269 uint8_t* dst_ptr, int dst_width) =
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000270 filtering ? ScaleRowDown4Box_C : ScaleRowDown4_C;
Frank Barchardf0cfc1f2021-10-18 10:36:27 -0700271 int row_stride = src_stride * 4;
Frank Barchardbbe8c232017-02-15 12:08:43 -0800272 (void)src_width;
273 (void)src_height;
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000274 if (!filtering) {
275 src_ptr += src_stride * 2; // Point to row 2.
276 src_stride = 0;
277 }
frkoenig@google.com36ab38a2011-10-21 21:17:16 +0000278#if defined(HAS_SCALEROWDOWN4_NEON)
fbarchard@google.com44b6ba92015-04-03 22:12:53 +0000279 if (TestCpuFlag(kCpuHasNEON)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800280 ScaleRowDown4 =
281 filtering ? ScaleRowDown4Box_Any_NEON : ScaleRowDown4_Any_NEON;
George Steed2d62d8d2024-05-15 21:50:12 +0100282 if (IS_ALIGNED(dst_width, 16)) {
fbarchard@google.com44b6ba92015-04-03 22:12:53 +0000283 ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON;
284 }
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000285 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000286#endif
Frank Barchard80ca4512015-12-15 21:25:18 -0800287#if defined(HAS_SCALEROWDOWN4_SSSE3)
288 if (TestCpuFlag(kCpuHasSSSE3)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800289 ScaleRowDown4 =
290 filtering ? ScaleRowDown4Box_Any_SSSE3 : ScaleRowDown4_Any_SSSE3;
fbarchard@google.com44b6ba92015-04-03 22:12:53 +0000291 if (IS_ALIGNED(dst_width, 8)) {
Frank Barchard80ca4512015-12-15 21:25:18 -0800292 ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSSE3 : ScaleRowDown4_SSSE3;
fbarchard@google.com44b6ba92015-04-03 22:12:53 +0000293 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000294 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000295#endif
fbarchard@google.com9f4636e2015-04-30 01:58:32 +0000296#if defined(HAS_SCALEROWDOWN4_AVX2)
297 if (TestCpuFlag(kCpuHasAVX2)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800298 ScaleRowDown4 =
299 filtering ? ScaleRowDown4Box_Any_AVX2 : ScaleRowDown4_Any_AVX2;
fbarchard@google.com9f4636e2015-04-30 01:58:32 +0000300 if (IS_ALIGNED(dst_width, 16)) {
301 ScaleRowDown4 = filtering ? ScaleRowDown4Box_AVX2 : ScaleRowDown4_AVX2;
302 }
303 }
304#endif
Shiyou Yinbed92922020-04-08 15:58:52 +0800305#if defined(HAS_SCALEROWDOWN4_MSA)
306 if (TestCpuFlag(kCpuHasMSA)) {
307 ScaleRowDown4 =
308 filtering ? ScaleRowDown4Box_Any_MSA : ScaleRowDown4_Any_MSA;
309 if (IS_ALIGNED(dst_width, 16)) {
310 ScaleRowDown4 = filtering ? ScaleRowDown4Box_MSA : ScaleRowDown4_MSA;
311 }
312 }
313#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +0800314#if defined(HAS_SCALEROWDOWN4_LSX)
315 if (TestCpuFlag(kCpuHasLSX)) {
316 ScaleRowDown4 =
317 filtering ? ScaleRowDown4Box_Any_LSX : ScaleRowDown4_Any_LSX;
318 if (IS_ALIGNED(dst_width, 16)) {
319 ScaleRowDown4 = filtering ? ScaleRowDown4Box_LSX : ScaleRowDown4_LSX;
320 }
321 }
322#endif
Darren Hsieh873eaa32023-05-16 23:47:58 -0700323#if defined(HAS_SCALEROWDOWN4_RVV)
324 if (TestCpuFlag(kCpuHasRVV)) {
325 ScaleRowDown4 = filtering ? ScaleRowDown4Box_RVV : ScaleRowDown4_RVV;
326 }
327#endif
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000328
fbarchard@google.com788f7572013-11-11 18:53:19 +0000329 if (filtering == kFilterLinear) {
330 src_stride = 0;
331 }
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000332 for (y = 0; y < dst_height; ++y) {
fbarchard@google.com3faa0f12011-10-20 06:04:16 +0000333 ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000334 src_ptr += row_stride;
fbarchard@google.com3faa0f12011-10-20 06:04:16 +0000335 dst_ptr += dst_stride;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000336 }
337}
338
Frank Barcharde62309f2016-11-07 17:37:23 -0800339static void ScalePlaneDown4_16(int src_width,
340 int src_height,
341 int dst_width,
342 int dst_height,
343 int src_stride,
344 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800345 const uint16_t* src_ptr,
346 uint16_t* dst_ptr,
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000347 enum FilterMode filtering) {
348 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800349 void (*ScaleRowDown4)(const uint16_t* src_ptr, ptrdiff_t src_stride,
350 uint16_t* dst_ptr, int dst_width) =
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000351 filtering ? ScaleRowDown4Box_16_C : ScaleRowDown4_16_C;
Frank Barchardf0cfc1f2021-10-18 10:36:27 -0700352 int row_stride = src_stride * 4;
Frank Barchardbbe8c232017-02-15 12:08:43 -0800353 (void)src_width;
354 (void)src_height;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000355 if (!filtering) {
356 src_ptr += src_stride * 2; // Point to row 2.
357 src_stride = 0;
358 }
359#if defined(HAS_SCALEROWDOWN4_16_NEON)
360 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800361 ScaleRowDown4 =
362 filtering ? ScaleRowDown4Box_16_NEON : ScaleRowDown4_16_NEON;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000363 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000364#endif
365#if defined(HAS_SCALEROWDOWN4_16_SSE2)
fbarchard@google.comca308322014-10-07 00:59:31 +0000366 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
Frank Barcharde62309f2016-11-07 17:37:23 -0800367 ScaleRowDown4 =
368 filtering ? ScaleRowDown4Box_16_SSE2 : ScaleRowDown4_16_SSE2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000369 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000370#endif
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000371
372 if (filtering == kFilterLinear) {
373 src_stride = 0;
374 }
375 for (y = 0; y < dst_height; ++y) {
376 ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
377 src_ptr += row_stride;
378 dst_ptr += dst_stride;
379 }
380}
381
fbarchard@google.com3c7bb052013-02-20 22:18:36 +0000382// Scale plane down, 3/4
Frank Barcharde62309f2016-11-07 17:37:23 -0800383static void ScalePlaneDown34(int src_width,
384 int src_height,
385 int dst_width,
386 int dst_height,
387 int src_stride,
388 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800389 const uint8_t* src_ptr,
390 uint8_t* dst_ptr,
fbarchard@google.comdb735182014-01-07 03:59:31 +0000391 enum FilterMode filtering) {
fbarchard@google.comfa831882014-01-18 01:30:58 +0000392 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800393 void (*ScaleRowDown34_0)(const uint8_t* src_ptr, ptrdiff_t src_stride,
394 uint8_t* dst_ptr, int dst_width);
395 void (*ScaleRowDown34_1)(const uint8_t* src_ptr, ptrdiff_t src_stride,
396 uint8_t* dst_ptr, int dst_width);
fbarchard@google.comfa831882014-01-18 01:30:58 +0000397 const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
Frank Barchardbbe8c232017-02-15 12:08:43 -0800398 (void)src_width;
399 (void)src_height;
fbarchard@google.comfa831882014-01-18 01:30:58 +0000400 assert(dst_width % 3 == 0);
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000401 if (!filtering) {
402 ScaleRowDown34_0 = ScaleRowDown34_C;
403 ScaleRowDown34_1 = ScaleRowDown34_C;
404 } else {
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000405 ScaleRowDown34_0 = ScaleRowDown34_0_Box_C;
406 ScaleRowDown34_1 = ScaleRowDown34_1_Box_C;
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000407 }
frkoenig@google.comf626bea2011-10-28 17:32:35 +0000408#if defined(HAS_SCALEROWDOWN34_NEON)
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000409 if (TestCpuFlag(kCpuHasNEON)) {
Wan-Teh Chang77f3aca2024-09-27 15:59:29 -0700410#if defined(__aarch64__)
Frank Barchard4620f172024-09-12 15:48:33 -0700411 if (dst_width % 48 == 0) {
Wan-Teh Chang77f3aca2024-09-27 15:59:29 -0700412#else
413 if (dst_width % 24 == 0) {
414#endif
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000415 if (!filtering) {
416 ScaleRowDown34_0 = ScaleRowDown34_NEON;
417 ScaleRowDown34_1 = ScaleRowDown34_NEON;
418 } else {
419 ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON;
420 ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON;
421 }
Frank Barchard4620f172024-09-12 15:48:33 -0700422 } else {
423 if (!filtering) {
424 ScaleRowDown34_0 = ScaleRowDown34_Any_NEON;
425 ScaleRowDown34_1 = ScaleRowDown34_Any_NEON;
426 } else {
427 ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_NEON;
428 ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_NEON;
429 }
frkoenig@google.comf626bea2011-10-28 17:32:35 +0000430 }
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000431 }
432#endif
Frank Barchard8cd3e4f2017-08-18 10:22:19 -0700433#if defined(HAS_SCALEROWDOWN34_MSA)
434 if (TestCpuFlag(kCpuHasMSA)) {
Frank Barchard8cd3e4f2017-08-18 10:22:19 -0700435 if (dst_width % 48 == 0) {
436 if (!filtering) {
437 ScaleRowDown34_0 = ScaleRowDown34_MSA;
438 ScaleRowDown34_1 = ScaleRowDown34_MSA;
439 } else {
440 ScaleRowDown34_0 = ScaleRowDown34_0_Box_MSA;
441 ScaleRowDown34_1 = ScaleRowDown34_1_Box_MSA;
442 }
Frank Barchard4620f172024-09-12 15:48:33 -0700443 } else {
444 if (!filtering) {
445 ScaleRowDown34_0 = ScaleRowDown34_Any_MSA;
446 ScaleRowDown34_1 = ScaleRowDown34_Any_MSA;
447 } else {
448 ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_MSA;
449 ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_MSA;
450 }
Frank Barchard8cd3e4f2017-08-18 10:22:19 -0700451 }
452 }
453#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +0800454#if defined(HAS_SCALEROWDOWN34_LSX)
455 if (TestCpuFlag(kCpuHasLSX)) {
Hao Chen2f87e9a2021-12-20 20:23:28 +0800456 if (dst_width % 48 == 0) {
457 if (!filtering) {
458 ScaleRowDown34_0 = ScaleRowDown34_LSX;
459 ScaleRowDown34_1 = ScaleRowDown34_LSX;
460 } else {
461 ScaleRowDown34_0 = ScaleRowDown34_0_Box_LSX;
462 ScaleRowDown34_1 = ScaleRowDown34_1_Box_LSX;
463 }
Frank Barchard4620f172024-09-12 15:48:33 -0700464 } else {
465 if (!filtering) {
466 ScaleRowDown34_0 = ScaleRowDown34_Any_LSX;
467 ScaleRowDown34_1 = ScaleRowDown34_Any_LSX;
468 } else {
469 ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_LSX;
470 ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_LSX;
471 }
Hao Chen2f87e9a2021-12-20 20:23:28 +0800472 }
473 }
474#endif
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000475#if defined(HAS_SCALEROWDOWN34_SSSE3)
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000476 if (TestCpuFlag(kCpuHasSSSE3)) {
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000477 if (dst_width % 24 == 0) {
478 if (!filtering) {
479 ScaleRowDown34_0 = ScaleRowDown34_SSSE3;
480 ScaleRowDown34_1 = ScaleRowDown34_SSSE3;
481 } else {
482 ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3;
483 ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3;
484 }
Frank Barchard4620f172024-09-12 15:48:33 -0700485 } else {
486 if (!filtering) {
487 ScaleRowDown34_0 = ScaleRowDown34_Any_SSSE3;
488 ScaleRowDown34_1 = ScaleRowDown34_Any_SSSE3;
489 } else {
490 ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_SSSE3;
491 ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_SSSE3;
492 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000493 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000494 }
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000495#endif
Darren Hsieh552571e2023-06-07 01:17:43 -0700496#if defined(HAS_SCALEROWDOWN34_RVV)
497 if (TestCpuFlag(kCpuHasRVV)) {
498 if (!filtering) {
499 ScaleRowDown34_0 = ScaleRowDown34_RVV;
500 ScaleRowDown34_1 = ScaleRowDown34_RVV;
501 } else {
502 ScaleRowDown34_0 = ScaleRowDown34_0_Box_RVV;
503 ScaleRowDown34_1 = ScaleRowDown34_1_Box_RVV;
504 }
505 }
506#endif
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000507
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000508 for (y = 0; y < dst_height - 2; y += 3) {
fbarchard@google.com788f7572013-11-11 18:53:19 +0000509 ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.coma1280732011-10-14 17:50:12 +0000510 src_ptr += src_stride;
fbarchard@google.com3faa0f12011-10-20 06:04:16 +0000511 dst_ptr += dst_stride;
fbarchard@google.com788f7572013-11-11 18:53:19 +0000512 ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000513 src_ptr += src_stride;
514 dst_ptr += dst_stride;
Frank Barcharde62309f2016-11-07 17:37:23 -0800515 ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000516 src_ptr += src_stride * 2;
517 dst_ptr += dst_stride;
518 }
519
fbarchard@google.com8ae294e2012-02-02 22:33:21 +0000520 // Remainder 1 or 2 rows with last row vertically unfiltered
521 if ((dst_height % 3) == 2) {
fbarchard@google.com788f7572013-11-11 18:53:19 +0000522 ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000523 src_ptr += src_stride;
524 dst_ptr += dst_stride;
fbarchard@google.com8ae294e2012-02-02 22:33:21 +0000525 ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width);
526 } else if ((dst_height % 3) == 1) {
527 ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width);
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000528 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000529}
530
Frank Barcharde62309f2016-11-07 17:37:23 -0800531static void ScalePlaneDown34_16(int src_width,
532 int src_height,
533 int dst_width,
534 int dst_height,
535 int src_stride,
536 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800537 const uint16_t* src_ptr,
538 uint16_t* dst_ptr,
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000539 enum FilterMode filtering) {
540 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800541 void (*ScaleRowDown34_0)(const uint16_t* src_ptr, ptrdiff_t src_stride,
542 uint16_t* dst_ptr, int dst_width);
543 void (*ScaleRowDown34_1)(const uint16_t* src_ptr, ptrdiff_t src_stride,
544 uint16_t* dst_ptr, int dst_width);
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000545 const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
Frank Barchardbbe8c232017-02-15 12:08:43 -0800546 (void)src_width;
547 (void)src_height;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000548 assert(dst_width % 3 == 0);
549 if (!filtering) {
550 ScaleRowDown34_0 = ScaleRowDown34_16_C;
551 ScaleRowDown34_1 = ScaleRowDown34_16_C;
552 } else {
553 ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_C;
554 ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_C;
555 }
556#if defined(HAS_SCALEROWDOWN34_16_NEON)
557 if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) {
558 if (!filtering) {
559 ScaleRowDown34_0 = ScaleRowDown34_16_NEON;
560 ScaleRowDown34_1 = ScaleRowDown34_16_NEON;
561 } else {
562 ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_NEON;
563 ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_NEON;
564 }
565 }
566#endif
567#if defined(HAS_SCALEROWDOWN34_16_SSSE3)
fbarchard@google.comca308322014-10-07 00:59:31 +0000568 if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000569 if (!filtering) {
570 ScaleRowDown34_0 = ScaleRowDown34_16_SSSE3;
571 ScaleRowDown34_1 = ScaleRowDown34_16_SSSE3;
572 } else {
573 ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_SSSE3;
574 ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_SSSE3;
575 }
576 }
577#endif
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000578
579 for (y = 0; y < dst_height - 2; y += 3) {
580 ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
581 src_ptr += src_stride;
582 dst_ptr += dst_stride;
583 ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width);
584 src_ptr += src_stride;
585 dst_ptr += dst_stride;
Frank Barcharde62309f2016-11-07 17:37:23 -0800586 ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width);
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000587 src_ptr += src_stride * 2;
588 dst_ptr += dst_stride;
589 }
590
591 // Remainder 1 or 2 rows with last row vertically unfiltered
592 if ((dst_height % 3) == 2) {
593 ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
594 src_ptr += src_stride;
595 dst_ptr += dst_stride;
596 ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width);
597 } else if ((dst_height % 3) == 1) {
598 ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width);
599 }
600}
601
fbarchard@google.com3c7bb052013-02-20 22:18:36 +0000602// Scale plane, 3/8
603// This is an optimized version for scaling down a plane to 3/8
604// of its original size.
605//
606// Uses box filter arranges like this
607// aaabbbcc -> abc
608// aaabbbcc def
609// aaabbbcc ghi
610// dddeeeff
611// dddeeeff
612// dddeeeff
613// ggghhhii
614// ggghhhii
615// Boxes are 3x3, 2x3, 3x2 and 2x2
616
Frank Barcharde62309f2016-11-07 17:37:23 -0800617static void ScalePlaneDown38(int src_width,
618 int src_height,
619 int dst_width,
620 int dst_height,
621 int src_stride,
622 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800623 const uint8_t* src_ptr,
624 uint8_t* dst_ptr,
fbarchard@google.comdb735182014-01-07 03:59:31 +0000625 enum FilterMode filtering) {
fbarchard@google.comfa831882014-01-18 01:30:58 +0000626 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800627 void (*ScaleRowDown38_3)(const uint8_t* src_ptr, ptrdiff_t src_stride,
628 uint8_t* dst_ptr, int dst_width);
629 void (*ScaleRowDown38_2)(const uint8_t* src_ptr, ptrdiff_t src_stride,
630 uint8_t* dst_ptr, int dst_width);
fbarchard@google.comfa831882014-01-18 01:30:58 +0000631 const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
632 assert(dst_width % 3 == 0);
Frank Barchardbbe8c232017-02-15 12:08:43 -0800633 (void)src_width;
634 (void)src_height;
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000635 if (!filtering) {
636 ScaleRowDown38_3 = ScaleRowDown38_C;
637 ScaleRowDown38_2 = ScaleRowDown38_C;
638 } else {
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000639 ScaleRowDown38_3 = ScaleRowDown38_3_Box_C;
640 ScaleRowDown38_2 = ScaleRowDown38_2_Box_C;
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000641 }
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000642
frkoenig@google.com0e9b5152011-10-29 00:26:17 +0000643#if defined(HAS_SCALEROWDOWN38_NEON)
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000644 if (TestCpuFlag(kCpuHasNEON)) {
frkoenig@google.com0e9b5152011-10-29 00:26:17 +0000645 if (!filtering) {
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000646 ScaleRowDown38_3 = ScaleRowDown38_Any_NEON;
647 ScaleRowDown38_2 = ScaleRowDown38_Any_NEON;
frkoenig@google.com0e9b5152011-10-29 00:26:17 +0000648 } else {
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000649 ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_NEON;
650 ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_NEON;
651 }
652 if (dst_width % 12 == 0) {
653 if (!filtering) {
654 ScaleRowDown38_3 = ScaleRowDown38_NEON;
655 ScaleRowDown38_2 = ScaleRowDown38_NEON;
656 } else {
657 ScaleRowDown38_3 = ScaleRowDown38_3_Box_NEON;
658 ScaleRowDown38_2 = ScaleRowDown38_2_Box_NEON;
659 }
frkoenig@google.com0e9b5152011-10-29 00:26:17 +0000660 }
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000661 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000662#endif
663#if defined(HAS_SCALEROWDOWN38_SSSE3)
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000664 if (TestCpuFlag(kCpuHasSSSE3)) {
fbarchard@google.coma1280732011-10-14 17:50:12 +0000665 if (!filtering) {
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000666 ScaleRowDown38_3 = ScaleRowDown38_Any_SSSE3;
667 ScaleRowDown38_2 = ScaleRowDown38_Any_SSSE3;
668 } else {
669 ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_SSSE3;
670 ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_SSSE3;
671 }
672 if (dst_width % 12 == 0 && !filtering) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000673 ScaleRowDown38_3 = ScaleRowDown38_SSSE3;
674 ScaleRowDown38_2 = ScaleRowDown38_SSSE3;
fbarchard@google.com4e78b8d2015-04-27 21:56:08 +0000675 }
676 if (dst_width % 6 == 0 && filtering) {
fbarchard@google.com8ffe78a2013-05-30 07:14:14 +0000677 ScaleRowDown38_3 = ScaleRowDown38_3_Box_SSSE3;
678 ScaleRowDown38_2 = ScaleRowDown38_2_Box_SSSE3;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000679 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000680 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000681#endif
Manojkumar Bhosale288bfbe2016-12-21 13:39:44 +0530682#if defined(HAS_SCALEROWDOWN38_MSA)
683 if (TestCpuFlag(kCpuHasMSA)) {
684 if (!filtering) {
685 ScaleRowDown38_3 = ScaleRowDown38_Any_MSA;
686 ScaleRowDown38_2 = ScaleRowDown38_Any_MSA;
687 } else {
688 ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_MSA;
689 ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_MSA;
690 }
691 if (dst_width % 12 == 0) {
692 if (!filtering) {
693 ScaleRowDown38_3 = ScaleRowDown38_MSA;
694 ScaleRowDown38_2 = ScaleRowDown38_MSA;
695 } else {
696 ScaleRowDown38_3 = ScaleRowDown38_3_Box_MSA;
697 ScaleRowDown38_2 = ScaleRowDown38_2_Box_MSA;
698 }
699 }
700 }
701#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +0800702#if defined(HAS_SCALEROWDOWN38_LSX)
703 if (TestCpuFlag(kCpuHasLSX)) {
704 if (!filtering) {
705 ScaleRowDown38_3 = ScaleRowDown38_Any_LSX;
706 ScaleRowDown38_2 = ScaleRowDown38_Any_LSX;
707 } else {
708 ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_LSX;
709 ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_LSX;
710 }
711 if (dst_width % 12 == 0) {
712 if (!filtering) {
713 ScaleRowDown38_3 = ScaleRowDown38_LSX;
714 ScaleRowDown38_2 = ScaleRowDown38_LSX;
715 } else {
716 ScaleRowDown38_3 = ScaleRowDown38_3_Box_LSX;
717 ScaleRowDown38_2 = ScaleRowDown38_2_Box_LSX;
718 }
719 }
720 }
721#endif
Bruce Laic60ac402023-07-04 22:05:46 -0700722#if defined(HAS_SCALEROWDOWN38_RVV)
723 if (TestCpuFlag(kCpuHasRVV)) {
724 if (!filtering) {
725 ScaleRowDown38_3 = ScaleRowDown38_RVV;
726 ScaleRowDown38_2 = ScaleRowDown38_RVV;
727 } else {
728 ScaleRowDown38_3 = ScaleRowDown38_3_Box_RVV;
729 ScaleRowDown38_2 = ScaleRowDown38_2_Box_RVV;
730 }
731 }
732#endif
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000733
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000734 for (y = 0; y < dst_height - 2; y += 3) {
fbarchard@google.com788f7572013-11-11 18:53:19 +0000735 ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000736 src_ptr += src_stride * 3;
fbarchard@google.com3faa0f12011-10-20 06:04:16 +0000737 dst_ptr += dst_stride;
fbarchard@google.com788f7572013-11-11 18:53:19 +0000738 ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000739 src_ptr += src_stride * 3;
740 dst_ptr += dst_stride;
fbarchard@google.com788f7572013-11-11 18:53:19 +0000741 ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000742 src_ptr += src_stride * 2;
743 dst_ptr += dst_stride;
744 }
fbarchard@google.com8ae294e2012-02-02 22:33:21 +0000745
746 // Remainder 1 or 2 rows with last row vertically unfiltered
747 if ((dst_height % 3) == 2) {
fbarchard@google.com788f7572013-11-11 18:53:19 +0000748 ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
fbarchard@google.com94602792012-01-21 06:46:34 +0000749 src_ptr += src_stride * 3;
750 dst_ptr += dst_stride;
fbarchard@google.com8ae294e2012-02-02 22:33:21 +0000751 ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
752 } else if ((dst_height % 3) == 1) {
753 ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000754 }
755}
756
Frank Barcharde62309f2016-11-07 17:37:23 -0800757static void ScalePlaneDown38_16(int src_width,
758 int src_height,
759 int dst_width,
760 int dst_height,
761 int src_stride,
762 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -0800763 const uint16_t* src_ptr,
764 uint16_t* dst_ptr,
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000765 enum FilterMode filtering) {
766 int y;
Frank Barchard7e389882018-01-22 18:35:52 -0800767 void (*ScaleRowDown38_3)(const uint16_t* src_ptr, ptrdiff_t src_stride,
768 uint16_t* dst_ptr, int dst_width);
769 void (*ScaleRowDown38_2)(const uint16_t* src_ptr, ptrdiff_t src_stride,
770 uint16_t* dst_ptr, int dst_width);
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000771 const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
Frank Barchardbbe8c232017-02-15 12:08:43 -0800772 (void)src_width;
773 (void)src_height;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000774 assert(dst_width % 3 == 0);
775 if (!filtering) {
776 ScaleRowDown38_3 = ScaleRowDown38_16_C;
777 ScaleRowDown38_2 = ScaleRowDown38_16_C;
778 } else {
779 ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_C;
780 ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_C;
781 }
782#if defined(HAS_SCALEROWDOWN38_16_NEON)
783 if (TestCpuFlag(kCpuHasNEON) && (dst_width % 12 == 0)) {
784 if (!filtering) {
785 ScaleRowDown38_3 = ScaleRowDown38_16_NEON;
786 ScaleRowDown38_2 = ScaleRowDown38_16_NEON;
787 } else {
788 ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_NEON;
789 ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_NEON;
790 }
791 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000792#endif
793#if defined(HAS_SCALEROWDOWN38_16_SSSE3)
fbarchard@google.comca308322014-10-07 00:59:31 +0000794 if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000795 if (!filtering) {
796 ScaleRowDown38_3 = ScaleRowDown38_16_SSSE3;
797 ScaleRowDown38_2 = ScaleRowDown38_16_SSSE3;
798 } else {
799 ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_SSSE3;
800 ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_SSSE3;
801 }
802 }
fbarchard@google.comf7136912014-10-16 20:47:22 +0000803#endif
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000804
805 for (y = 0; y < dst_height - 2; y += 3) {
806 ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
807 src_ptr += src_stride * 3;
808 dst_ptr += dst_stride;
809 ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
810 src_ptr += src_stride * 3;
811 dst_ptr += dst_stride;
812 ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width);
813 src_ptr += src_stride * 2;
814 dst_ptr += dst_stride;
815 }
816
817 // Remainder 1 or 2 rows with last row vertically unfiltered
818 if ((dst_height % 3) == 2) {
819 ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
820 src_ptr += src_stride * 3;
821 dst_ptr += dst_stride;
822 ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
823 } else if ((dst_height % 3) == 1) {
824 ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
825 }
826}
827
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000828#define MIN1(x) ((x) < 1 ? 1 : (x))
829
Frank Barchard7e389882018-01-22 18:35:52 -0800830static __inline uint32_t SumPixels(int iboxwidth, const uint16_t* src_ptr) {
831 uint32_t sum = 0u;
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000832 int x;
fbarchard@google.comfa831882014-01-18 01:30:58 +0000833 assert(iboxwidth > 0);
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000834 for (x = 0; x < iboxwidth; ++x) {
fbarchard@google.coma1280732011-10-14 17:50:12 +0000835 sum += src_ptr[x];
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000836 }
837 return sum;
838}
839
Frank Barchard7e389882018-01-22 18:35:52 -0800840static __inline uint32_t SumPixels_16(int iboxwidth, const uint32_t* src_ptr) {
841 uint32_t sum = 0u;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000842 int x;
843 assert(iboxwidth > 0);
844 for (x = 0; x < iboxwidth; ++x) {
845 sum += src_ptr[x];
846 }
847 return sum;
848}
849
Frank Barcharde62309f2016-11-07 17:37:23 -0800850static void ScaleAddCols2_C(int dst_width,
851 int boxheight,
852 int x,
853 int dx,
Frank Barchard7e389882018-01-22 18:35:52 -0800854 const uint16_t* src_ptr,
855 uint8_t* dst_ptr) {
fbarchard@google.comfa831882014-01-18 01:30:58 +0000856 int i;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000857 int scaletbl[2];
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000858 int minboxwidth = dx >> 16;
fbarchard@google.comfa831882014-01-18 01:30:58 +0000859 int boxwidth;
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000860 scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight);
861 scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight);
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000862 for (i = 0; i < dst_width; ++i) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000863 int ix = x >> 16;
864 x += dx;
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000865 boxwidth = MIN1((x >> 16) - ix);
Wan-Teh Changdcbe0822023-05-20 16:18:10 -0700866 int scaletbl_index = boxwidth - minboxwidth;
867 assert((scaletbl_index == 0) || (scaletbl_index == 1));
Frank Barchard3abd6f32022-12-15 14:11:52 -0800868 *dst_ptr++ = (uint8_t)(SumPixels(boxwidth, src_ptr + ix) *
Wan-Teh Changdcbe0822023-05-20 16:18:10 -0700869 scaletbl[scaletbl_index] >>
Frank Barchard3abd6f32022-12-15 14:11:52 -0800870 16);
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000871 }
872}
873
Frank Barcharde62309f2016-11-07 17:37:23 -0800874static void ScaleAddCols2_16_C(int dst_width,
875 int boxheight,
876 int x,
877 int dx,
Frank Barchard7e389882018-01-22 18:35:52 -0800878 const uint32_t* src_ptr,
879 uint16_t* dst_ptr) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000880 int i;
881 int scaletbl[2];
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000882 int minboxwidth = dx >> 16;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000883 int boxwidth;
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000884 scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight);
885 scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight);
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000886 for (i = 0; i < dst_width; ++i) {
887 int ix = x >> 16;
888 x += dx;
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000889 boxwidth = MIN1((x >> 16) - ix);
Wan-Teh Changdcbe0822023-05-20 16:18:10 -0700890 int scaletbl_index = boxwidth - minboxwidth;
891 assert((scaletbl_index == 0) || (scaletbl_index == 1));
892 *dst_ptr++ =
893 SumPixels_16(boxwidth, src_ptr + ix) * scaletbl[scaletbl_index] >> 16;
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000894 }
895}
896
Frank Barcharde62309f2016-11-07 17:37:23 -0800897static void ScaleAddCols0_C(int dst_width,
898 int boxheight,
899 int x,
Frank Barcharde26b0a72017-11-08 17:57:04 -0800900 int dx,
Frank Barchard7e389882018-01-22 18:35:52 -0800901 const uint16_t* src_ptr,
902 uint8_t* dst_ptr) {
fbarchard@google.com013e8122015-04-14 00:21:15 +0000903 int scaleval = 65536 / boxheight;
904 int i;
Frank Barcharde26b0a72017-11-08 17:57:04 -0800905 (void)dx;
fbarchard@google.com013e8122015-04-14 00:21:15 +0000906 src_ptr += (x >> 16);
907 for (i = 0; i < dst_width; ++i) {
Frank Barchard3abd6f32022-12-15 14:11:52 -0800908 *dst_ptr++ = (uint8_t)(src_ptr[i] * scaleval >> 16);
fbarchard@google.com013e8122015-04-14 00:21:15 +0000909 }
910}
911
Frank Barcharde62309f2016-11-07 17:37:23 -0800912static void ScaleAddCols1_C(int dst_width,
913 int boxheight,
914 int x,
915 int dx,
Frank Barchard7e389882018-01-22 18:35:52 -0800916 const uint16_t* src_ptr,
917 uint8_t* dst_ptr) {
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000918 int boxwidth = MIN1(dx >> 16);
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000919 int scaleval = 65536 / (boxwidth * boxheight);
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000920 int i;
fbarchard@google.com013e8122015-04-14 00:21:15 +0000921 x >>= 16;
fbarchard@google.com5aa39952014-01-11 04:59:01 +0000922 for (i = 0; i < dst_width; ++i) {
Frank Barchard3abd6f32022-12-15 14:11:52 -0800923 *dst_ptr++ = (uint8_t)(SumPixels(boxwidth, src_ptr + x) * scaleval >> 16);
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +0000924 x += boxwidth;
925 }
926}
927
Frank Barcharde62309f2016-11-07 17:37:23 -0800928static void ScaleAddCols1_16_C(int dst_width,
929 int boxheight,
930 int x,
931 int dx,
Frank Barchard7e389882018-01-22 18:35:52 -0800932 const uint32_t* src_ptr,
933 uint16_t* dst_ptr) {
fbarchard@google.come52b9c32015-04-16 21:02:16 +0000934 int boxwidth = MIN1(dx >> 16);
fbarchard@google.comb18413e2014-05-20 19:22:30 +0000935 int scaleval = 65536 / (boxwidth * boxheight);
936 int i;
937 for (i = 0; i < dst_width; ++i) {
938 *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + x) * scaleval >> 16;
939 x += boxwidth;
940 }
941}
942
fbarchard@google.com3c7bb052013-02-20 22:18:36 +0000943// Scale plane down to any dimensions, with interpolation.
944// (boxfilter).
945//
946// Same method as SimpleScale, which is fixed point, outputting
947// one pixel of destination using fixed point (16.16) to step
948// through source, sampling a box of pixel with simple
949// averaging.
Wan-Teh Changfb6341d2023-11-03 14:23:15 -0700950static int ScalePlaneBox(int src_width,
951 int src_height,
952 int dst_width,
953 int dst_height,
954 int src_stride,
955 int dst_stride,
956 const uint8_t* src_ptr,
957 uint8_t* dst_ptr) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000958 int j, k;
fbarchard@google.comaae7deb2013-12-07 00:55:23 +0000959 // Initial source x/y coordinate and step values as 16.16 fixed point.
fbarchard@google.com5f885862013-02-12 19:05:40 +0000960 int x = 0;
961 int y = 0;
fbarchard@google.comaae7deb2013-12-07 00:55:23 +0000962 int dx = 0;
963 int dy = 0;
fbarchard@google.comfa831882014-01-18 01:30:58 +0000964 const int max_y = (src_height << 16);
Frank Barcharde62309f2016-11-07 17:37:23 -0800965 ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y,
966 &dx, &dy);
fbarchard@google.com6700a272014-01-09 20:21:24 +0000967 src_width = Abs(src_width);
fbarchard@google.comfa831882014-01-18 01:30:58 +0000968 {
Frank Barchard7e389882018-01-22 18:35:52 -0800969 // Allocate a row buffer of uint16_t.
fbarchard@google.comfa831882014-01-18 01:30:58 +0000970 align_buffer_64(row16, src_width * 2);
Frank Barcharddef473f2023-12-04 01:16:59 -0800971 if (!row16)
972 return 1;
fbarchard@google.comfa831882014-01-18 01:30:58 +0000973 void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx,
Frank Barchard7e389882018-01-22 18:35:52 -0800974 const uint16_t* src_ptr, uint8_t* dst_ptr) =
Frank Barcharde62309f2016-11-07 17:37:23 -0800975 (dx & 0xffff) ? ScaleAddCols2_C
976 : ((dx != 0x10000) ? ScaleAddCols1_C : ScaleAddCols0_C);
Frank Barchard92e22cf2018-01-24 10:52:17 -0800977 void (*ScaleAddRow)(const uint8_t* src_ptr, uint16_t* dst_ptr,
978 int src_width) = ScaleAddRow_C;
fbarchard@google.com05416e22015-06-09 01:05:18 +0000979#if defined(HAS_SCALEADDROW_SSE2)
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000980 if (TestCpuFlag(kCpuHasSSE2)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000981 ScaleAddRow = ScaleAddRow_Any_SSE2;
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000982 if (IS_ALIGNED(src_width, 16)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000983 ScaleAddRow = ScaleAddRow_SSE2;
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000984 }
fbarchard@google.comfa831882014-01-18 01:30:58 +0000985 }
fbarchard@google.comf3fb7b62012-03-29 23:19:34 +0000986#endif
fbarchard@google.com05416e22015-06-09 01:05:18 +0000987#if defined(HAS_SCALEADDROW_AVX2)
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000988 if (TestCpuFlag(kCpuHasAVX2)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000989 ScaleAddRow = ScaleAddRow_Any_AVX2;
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000990 if (IS_ALIGNED(src_width, 32)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000991 ScaleAddRow = ScaleAddRow_AVX2;
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000992 }
fbarchard@google.com013e8122015-04-14 00:21:15 +0000993 }
994#endif
fbarchard@google.com05416e22015-06-09 01:05:18 +0000995#if defined(HAS_SCALEADDROW_NEON)
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000996 if (TestCpuFlag(kCpuHasNEON)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000997 ScaleAddRow = ScaleAddRow_Any_NEON;
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +0000998 if (IS_ALIGNED(src_width, 16)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +0000999 ScaleAddRow = ScaleAddRow_NEON;
fbarchard@google.com2b7f6b72015-04-22 00:51:56 +00001000 }
yang.zhang@arm.comca5b1bd2015-03-16 02:57:46 +00001001 }
1002#endif
Shiyou Yinbed92922020-04-08 15:58:52 +08001003#if defined(HAS_SCALEADDROW_MSA)
1004 if (TestCpuFlag(kCpuHasMSA)) {
1005 ScaleAddRow = ScaleAddRow_Any_MSA;
1006 if (IS_ALIGNED(src_width, 16)) {
1007 ScaleAddRow = ScaleAddRow_MSA;
1008 }
1009 }
1010#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +08001011#if defined(HAS_SCALEADDROW_LSX)
1012 if (TestCpuFlag(kCpuHasLSX)) {
1013 ScaleAddRow = ScaleAddRow_Any_LSX;
1014 if (IS_ALIGNED(src_width, 16)) {
1015 ScaleAddRow = ScaleAddRow_LSX;
1016 }
1017 }
1018#endif
Darren Hsieh873eaa32023-05-16 23:47:58 -07001019#if defined(HAS_SCALEADDROW_RVV)
1020 if (TestCpuFlag(kCpuHasRVV)) {
1021 ScaleAddRow = ScaleAddRow_RVV;
1022 }
1023#endif
yang.zhang@arm.comca5b1bd2015-03-16 02:57:46 +00001024
fbarchard@google.comfa831882014-01-18 01:30:58 +00001025 for (j = 0; j < dst_height; ++j) {
1026 int boxheight;
1027 int iy = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001028 const uint8_t* src = src_ptr + iy * (int64_t)src_stride;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001029 y += dy;
fbarchard@google.com35aa92a2015-04-28 18:41:04 +00001030 if (y > max_y) {
1031 y = max_y;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001032 }
fbarchard@google.come52b9c32015-04-16 21:02:16 +00001033 boxheight = MIN1((y >> 16) - iy);
fbarchard@google.com05416e22015-06-09 01:05:18 +00001034 memset(row16, 0, src_width * 2);
1035 for (k = 0; k < boxheight; ++k) {
Frank Barchard7e389882018-01-22 18:35:52 -08001036 ScaleAddRow(src, (uint16_t*)(row16), src_width);
fbarchard@google.com05416e22015-06-09 01:05:18 +00001037 src += src_stride;
1038 }
Frank Barchard7e389882018-01-22 18:35:52 -08001039 ScaleAddCols(dst_width, boxheight, x, dx, (uint16_t*)(row16), dst_ptr);
fbarchard@google.comfa831882014-01-18 01:30:58 +00001040 dst_ptr += dst_stride;
1041 }
1042 free_aligned_buffer_64(row16);
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001043 }
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001044 return 0;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001045}
1046
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001047static int ScalePlaneBox_16(int src_width,
1048 int src_height,
1049 int dst_width,
1050 int dst_height,
1051 int src_stride,
1052 int dst_stride,
1053 const uint16_t* src_ptr,
1054 uint16_t* dst_ptr) {
fbarchard@google.com05416e22015-06-09 01:05:18 +00001055 int j, k;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001056 // Initial source x/y coordinate and step values as 16.16 fixed point.
1057 int x = 0;
1058 int y = 0;
1059 int dx = 0;
1060 int dy = 0;
1061 const int max_y = (src_height << 16);
Frank Barcharde62309f2016-11-07 17:37:23 -08001062 ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y,
1063 &dx, &dy);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001064 src_width = Abs(src_width);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001065 {
Frank Barchard7e389882018-01-22 18:35:52 -08001066 // Allocate a row buffer of uint32_t.
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001067 align_buffer_64(row32, src_width * 4);
Frank Barcharddef473f2023-12-04 01:16:59 -08001068 if (!row32)
1069 return 1;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001070 void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx,
Frank Barchard7e389882018-01-22 18:35:52 -08001071 const uint32_t* src_ptr, uint16_t* dst_ptr) =
Frank Barcharde62309f2016-11-07 17:37:23 -08001072 (dx & 0xffff) ? ScaleAddCols2_16_C : ScaleAddCols1_16_C;
Frank Barchard92e22cf2018-01-24 10:52:17 -08001073 void (*ScaleAddRow)(const uint16_t* src_ptr, uint32_t* dst_ptr,
1074 int src_width) = ScaleAddRow_16_C;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001075
fbarchard@google.com05416e22015-06-09 01:05:18 +00001076#if defined(HAS_SCALEADDROW_16_SSE2)
fbarchard@google.com62a9fe32015-04-02 21:23:52 +00001077 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(src_width, 16)) {
fbarchard@google.com05416e22015-06-09 01:05:18 +00001078 ScaleAddRow = ScaleAddRow_16_SSE2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001079 }
1080#endif
1081
1082 for (j = 0; j < dst_height; ++j) {
1083 int boxheight;
1084 int iy = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001085 const uint16_t* src = src_ptr + iy * (int64_t)src_stride;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001086 y += dy;
fbarchard@google.com35aa92a2015-04-28 18:41:04 +00001087 if (y > max_y) {
1088 y = max_y;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001089 }
fbarchard@google.come52b9c32015-04-16 21:02:16 +00001090 boxheight = MIN1((y >> 16) - iy);
fbarchard@google.com05416e22015-06-09 01:05:18 +00001091 memset(row32, 0, src_width * 4);
1092 for (k = 0; k < boxheight; ++k) {
Frank Barchard7e389882018-01-22 18:35:52 -08001093 ScaleAddRow(src, (uint32_t*)(row32), src_width);
fbarchard@google.com05416e22015-06-09 01:05:18 +00001094 src += src_stride;
1095 }
Frank Barchard7e389882018-01-22 18:35:52 -08001096 ScaleAddCols(dst_width, boxheight, x, dx, (uint32_t*)(row32), dst_ptr);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001097 dst_ptr += dst_stride;
1098 }
1099 free_aligned_buffer_64(row32);
1100 }
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001101 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001102}
1103
fbarchard@google.coma2311692013-11-13 21:16:17 +00001104// Scale plane down with bilinear interpolation.
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001105static int ScalePlaneBilinearDown(int src_width,
1106 int src_height,
1107 int dst_width,
1108 int dst_height,
1109 int src_stride,
1110 int dst_stride,
1111 const uint8_t* src_ptr,
1112 uint8_t* dst_ptr,
1113 enum FilterMode filtering) {
fbarchard@google.comaae7deb2013-12-07 00:55:23 +00001114 // Initial source x/y coordinate and step values as 16.16 fixed point.
1115 int x = 0;
1116 int y = 0;
1117 int dx = 0;
1118 int dy = 0;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001119 // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
1120 // Allocate a row buffer.
1121 align_buffer_64(row, src_width);
Frank Barcharddef473f2023-12-04 01:16:59 -08001122 if (!row)
1123 return 1;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001124
1125 const int max_y = (src_height - 1) << 16;
1126 int j;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001127 void (*ScaleFilterCols)(uint8_t* dst_ptr, const uint8_t* src_ptr,
Frank Barchard92e22cf2018-01-24 10:52:17 -08001128 int dst_width, int x, int dx) =
fbarchard@google.comfa831882014-01-18 01:30:58 +00001129 (src_width >= 32768) ? ScaleFilterCols64_C : ScaleFilterCols_C;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001130 void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr,
Frank Barcharde62309f2016-11-07 17:37:23 -08001131 ptrdiff_t src_stride, int dst_width,
1132 int source_y_fraction) = InterpolateRow_C;
1133 ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
1134 &dx, &dy);
fbarchard@google.com6700a272014-01-09 20:21:24 +00001135 src_width = Abs(src_width);
fbarchard@google.comaae7deb2013-12-07 00:55:23 +00001136
fbarchard@google.comb9114282013-05-30 23:42:27 +00001137#if defined(HAS_INTERPOLATEROW_SSSE3)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001138 if (TestCpuFlag(kCpuHasSSSE3)) {
fbarchard@google.comb9114282013-05-30 23:42:27 +00001139 InterpolateRow = InterpolateRow_Any_SSSE3;
1140 if (IS_ALIGNED(src_width, 16)) {
fbarchard@google.com044f9142014-10-01 01:16:04 +00001141 InterpolateRow = InterpolateRow_SSSE3;
fbarchard@google.comb9114282013-05-30 23:42:27 +00001142 }
1143 }
1144#endif
fbarchard@google.com2154de42013-09-03 07:18:21 +00001145#if defined(HAS_INTERPOLATEROW_AVX2)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001146 if (TestCpuFlag(kCpuHasAVX2)) {
fbarchard@google.com2154de42013-09-03 07:18:21 +00001147 InterpolateRow = InterpolateRow_Any_AVX2;
1148 if (IS_ALIGNED(src_width, 32)) {
1149 InterpolateRow = InterpolateRow_AVX2;
1150 }
1151 }
1152#endif
fbarchard@google.comb9114282013-05-30 23:42:27 +00001153#if defined(HAS_INTERPOLATEROW_NEON)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001154 if (TestCpuFlag(kCpuHasNEON)) {
fbarchard@google.comb9114282013-05-30 23:42:27 +00001155 InterpolateRow = InterpolateRow_Any_NEON;
1156 if (IS_ALIGNED(src_width, 16)) {
1157 InterpolateRow = InterpolateRow_NEON;
1158 }
1159 }
1160#endif
Shiyou Yinbed92922020-04-08 15:58:52 +08001161#if defined(HAS_INTERPOLATEROW_MSA)
1162 if (TestCpuFlag(kCpuHasMSA)) {
1163 InterpolateRow = InterpolateRow_Any_MSA;
1164 if (IS_ALIGNED(src_width, 32)) {
1165 InterpolateRow = InterpolateRow_MSA;
1166 }
1167 }
1168#endif
Hao Chendfe046d2021-12-20 20:14:11 +08001169#if defined(HAS_INTERPOLATEROW_LSX)
1170 if (TestCpuFlag(kCpuHasLSX)) {
1171 InterpolateRow = InterpolateRow_Any_LSX;
1172 if (IS_ALIGNED(src_width, 32)) {
1173 InterpolateRow = InterpolateRow_LSX;
1174 }
1175 }
1176#endif
Darren Hsiehd14bd702023-05-23 02:03:37 -07001177#if defined(HAS_INTERPOLATEROW_RVV)
1178 if (TestCpuFlag(kCpuHasRVV)) {
1179 InterpolateRow = InterpolateRow_RVV;
1180 }
1181#endif
fbarchard@google.comf7eb04b2013-11-11 23:13:57 +00001182
fbarchard@google.comf7eb04b2013-11-11 23:13:57 +00001183#if defined(HAS_SCALEFILTERCOLS_SSSE3)
fbarchard@google.com90a36b22014-01-03 00:34:55 +00001184 if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
fbarchard@google.comf7eb04b2013-11-11 23:13:57 +00001185 ScaleFilterCols = ScaleFilterCols_SSSE3;
1186 }
1187#endif
yang.zhang@arm.comd6d7de52015-03-19 03:55:05 +00001188#if defined(HAS_SCALEFILTERCOLS_NEON)
1189 if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
1190 ScaleFilterCols = ScaleFilterCols_Any_NEON;
1191 if (IS_ALIGNED(dst_width, 8)) {
1192 ScaleFilterCols = ScaleFilterCols_NEON;
1193 }
1194 }
1195#endif
Frank Barchard8cd3e4f2017-08-18 10:22:19 -07001196#if defined(HAS_SCALEFILTERCOLS_MSA)
1197 if (TestCpuFlag(kCpuHasMSA) && src_width < 32768) {
1198 ScaleFilterCols = ScaleFilterCols_Any_MSA;
1199 if (IS_ALIGNED(dst_width, 16)) {
1200 ScaleFilterCols = ScaleFilterCols_MSA;
1201 }
1202 }
1203#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +08001204#if defined(HAS_SCALEFILTERCOLS_LSX)
1205 if (TestCpuFlag(kCpuHasLSX) && src_width < 32768) {
1206 ScaleFilterCols = ScaleFilterCols_Any_LSX;
1207 if (IS_ALIGNED(dst_width, 16)) {
1208 ScaleFilterCols = ScaleFilterCols_LSX;
1209 }
1210 }
1211#endif
fbarchard@google.comfa831882014-01-18 01:30:58 +00001212 if (y > max_y) {
1213 y = max_y;
1214 }
fbarchard@google.comf7eb04b2013-11-11 23:13:57 +00001215
fbarchard@google.com5aa39952014-01-11 04:59:01 +00001216 for (j = 0; j < dst_height; ++j) {
fbarchard@google.comb9114282013-05-30 23:42:27 +00001217 int yi = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001218 const uint8_t* src = src_ptr + yi * (int64_t)src_stride;
fbarchard@google.com788f7572013-11-11 18:53:19 +00001219 if (filtering == kFilterLinear) {
fbarchard@google.comf7eb04b2013-11-11 23:13:57 +00001220 ScaleFilterCols(dst_ptr, src, dst_width, x, dx);
fbarchard@google.com788f7572013-11-11 18:53:19 +00001221 } else {
1222 int yf = (y >> 8) & 255;
1223 InterpolateRow(row, src, src_stride, src_width, yf);
fbarchard@google.comf7eb04b2013-11-11 23:13:57 +00001224 ScaleFilterCols(dst_ptr, row, dst_width, x, dx);
fbarchard@google.com788f7572013-11-11 18:53:19 +00001225 }
fbarchard@google.com4339f092012-02-23 10:52:55 +00001226 dst_ptr += dst_stride;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001227 y += dy;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001228 if (y > max_y) {
1229 y = max_y;
1230 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001231 }
fbarchard@google.come86abbd2013-12-27 01:11:26 +00001232 free_aligned_buffer_64(row);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001233 return 0;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001234}
1235
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001236static int ScalePlaneBilinearDown_16(int src_width,
1237 int src_height,
1238 int dst_width,
1239 int dst_height,
1240 int src_stride,
1241 int dst_stride,
1242 const uint16_t* src_ptr,
1243 uint16_t* dst_ptr,
1244 enum FilterMode filtering) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001245 // Initial source x/y coordinate and step values as 16.16 fixed point.
1246 int x = 0;
1247 int y = 0;
1248 int dx = 0;
1249 int dy = 0;
1250 // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
1251 // Allocate a row buffer.
1252 align_buffer_64(row, src_width * 2);
Frank Barcharddef473f2023-12-04 01:16:59 -08001253 if (!row)
1254 return 1;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001255
1256 const int max_y = (src_height - 1) << 16;
1257 int j;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001258 void (*ScaleFilterCols)(uint16_t* dst_ptr, const uint16_t* src_ptr,
Frank Barchard73a603e2017-03-08 09:49:02 -08001259 int dst_width, int x, int dx) =
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001260 (src_width >= 32768) ? ScaleFilterCols64_16_C : ScaleFilterCols_16_C;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001261 void (*InterpolateRow)(uint16_t* dst_ptr, const uint16_t* src_ptr,
Frank Barcharde62309f2016-11-07 17:37:23 -08001262 ptrdiff_t src_stride, int dst_width,
1263 int source_y_fraction) = InterpolateRow_16_C;
1264 ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
1265 &dx, &dy);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001266 src_width = Abs(src_width);
1267
1268#if defined(HAS_INTERPOLATEROW_16_SSE2)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001269 if (TestCpuFlag(kCpuHasSSE2)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001270 InterpolateRow = InterpolateRow_16_Any_SSE2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001271 if (IS_ALIGNED(src_width, 16)) {
fbarchard@google.com044f9142014-10-01 01:16:04 +00001272 InterpolateRow = InterpolateRow_16_SSE2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001273 }
1274 }
1275#endif
1276#if defined(HAS_INTERPOLATEROW_16_SSSE3)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001277 if (TestCpuFlag(kCpuHasSSSE3)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001278 InterpolateRow = InterpolateRow_16_Any_SSSE3;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001279 if (IS_ALIGNED(src_width, 16)) {
fbarchard@google.com044f9142014-10-01 01:16:04 +00001280 InterpolateRow = InterpolateRow_16_SSSE3;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001281 }
1282 }
1283#endif
1284#if defined(HAS_INTERPOLATEROW_16_AVX2)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001285 if (TestCpuFlag(kCpuHasAVX2)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001286 InterpolateRow = InterpolateRow_16_Any_AVX2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001287 if (IS_ALIGNED(src_width, 32)) {
1288 InterpolateRow = InterpolateRow_16_AVX2;
1289 }
1290 }
1291#endif
1292#if defined(HAS_INTERPOLATEROW_16_NEON)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001293 if (TestCpuFlag(kCpuHasNEON)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001294 InterpolateRow = InterpolateRow_16_Any_NEON;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001295 if (IS_ALIGNED(src_width, 16)) {
1296 InterpolateRow = InterpolateRow_16_NEON;
1297 }
1298 }
1299#endif
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001300
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001301#if defined(HAS_SCALEFILTERCOLS_16_SSSE3)
1302 if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
1303 ScaleFilterCols = ScaleFilterCols_16_SSSE3;
1304 }
1305#endif
1306 if (y > max_y) {
1307 y = max_y;
1308 }
1309
1310 for (j = 0; j < dst_height; ++j) {
1311 int yi = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001312 const uint16_t* src = src_ptr + yi * (int64_t)src_stride;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001313 if (filtering == kFilterLinear) {
1314 ScaleFilterCols(dst_ptr, src, dst_width, x, dx);
1315 } else {
1316 int yf = (y >> 8) & 255;
Frank Barchard7e389882018-01-22 18:35:52 -08001317 InterpolateRow((uint16_t*)row, src, src_stride, src_width, yf);
1318 ScaleFilterCols(dst_ptr, (uint16_t*)row, dst_width, x, dx);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001319 }
1320 dst_ptr += dst_stride;
1321 y += dy;
1322 if (y > max_y) {
1323 y = max_y;
1324 }
1325 }
1326 free_aligned_buffer_64(row);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001327 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001328}
1329
fbarchard@google.coma2311692013-11-13 21:16:17 +00001330// Scale up down with bilinear interpolation.
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001331static int ScalePlaneBilinearUp(int src_width,
1332 int src_height,
1333 int dst_width,
1334 int dst_height,
1335 int src_stride,
1336 int dst_stride,
1337 const uint8_t* src_ptr,
1338 uint8_t* dst_ptr,
1339 enum FilterMode filtering) {
fbarchard@google.comfa831882014-01-18 01:30:58 +00001340 int j;
fbarchard@google.comaae7deb2013-12-07 00:55:23 +00001341 // Initial source x/y coordinate and step values as 16.16 fixed point.
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001342 int x = 0;
1343 int y = 0;
fbarchard@google.comaae7deb2013-12-07 00:55:23 +00001344 int dx = 0;
1345 int dy = 0;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001346 const int max_y = (src_height - 1) << 16;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001347 void (*InterpolateRow)(uint8_t* dst_ptr, const uint8_t* src_ptr,
Frank Barcharde62309f2016-11-07 17:37:23 -08001348 ptrdiff_t src_stride, int dst_width,
1349 int source_y_fraction) = InterpolateRow_C;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001350 void (*ScaleFilterCols)(uint8_t* dst_ptr, const uint8_t* src_ptr,
Frank Barchard92e22cf2018-01-24 10:52:17 -08001351 int dst_width, int x, int dx) =
fbarchard@google.com62a9fe32015-04-02 21:23:52 +00001352 filtering ? ScaleFilterCols_C : ScaleCols_C;
Frank Barcharde62309f2016-11-07 17:37:23 -08001353 ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
1354 &dx, &dy);
fbarchard@google.com6700a272014-01-09 20:21:24 +00001355 src_width = Abs(src_width);
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001356
fbarchard@google.coma2311692013-11-13 21:16:17 +00001357#if defined(HAS_INTERPOLATEROW_SSSE3)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001358 if (TestCpuFlag(kCpuHasSSSE3)) {
fbarchard@google.coma2311692013-11-13 21:16:17 +00001359 InterpolateRow = InterpolateRow_Any_SSSE3;
1360 if (IS_ALIGNED(dst_width, 16)) {
fbarchard@google.com044f9142014-10-01 01:16:04 +00001361 InterpolateRow = InterpolateRow_SSSE3;
fbarchard@google.coma2311692013-11-13 21:16:17 +00001362 }
1363 }
1364#endif
1365#if defined(HAS_INTERPOLATEROW_AVX2)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001366 if (TestCpuFlag(kCpuHasAVX2)) {
fbarchard@google.coma2311692013-11-13 21:16:17 +00001367 InterpolateRow = InterpolateRow_Any_AVX2;
1368 if (IS_ALIGNED(dst_width, 32)) {
1369 InterpolateRow = InterpolateRow_AVX2;
1370 }
1371 }
1372#endif
1373#if defined(HAS_INTERPOLATEROW_NEON)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001374 if (TestCpuFlag(kCpuHasNEON)) {
fbarchard@google.coma2311692013-11-13 21:16:17 +00001375 InterpolateRow = InterpolateRow_Any_NEON;
1376 if (IS_ALIGNED(dst_width, 16)) {
1377 InterpolateRow = InterpolateRow_NEON;
1378 }
1379 }
1380#endif
Darren Hsiehd14bd702023-05-23 02:03:37 -07001381#if defined(HAS_INTERPOLATEROW_RVV)
1382 if (TestCpuFlag(kCpuHasRVV)) {
1383 InterpolateRow = InterpolateRow_RVV;
1384 }
1385#endif
fbarchard@google.coma2311692013-11-13 21:16:17 +00001386
fbarchard@google.com90a36b22014-01-03 00:34:55 +00001387 if (filtering && src_width >= 32768) {
1388 ScaleFilterCols = ScaleFilterCols64_C;
1389 }
fbarchard@google.coma2311692013-11-13 21:16:17 +00001390#if defined(HAS_SCALEFILTERCOLS_SSSE3)
fbarchard@google.com90a36b22014-01-03 00:34:55 +00001391 if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
fbarchard@google.coma2311692013-11-13 21:16:17 +00001392 ScaleFilterCols = ScaleFilterCols_SSSE3;
1393 }
1394#endif
yang.zhang@arm.comd6d7de52015-03-19 03:55:05 +00001395#if defined(HAS_SCALEFILTERCOLS_NEON)
1396 if (filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
1397 ScaleFilterCols = ScaleFilterCols_Any_NEON;
1398 if (IS_ALIGNED(dst_width, 8)) {
1399 ScaleFilterCols = ScaleFilterCols_NEON;
1400 }
1401 }
1402#endif
Frank Barchard8cd3e4f2017-08-18 10:22:19 -07001403#if defined(HAS_SCALEFILTERCOLS_MSA)
1404 if (filtering && TestCpuFlag(kCpuHasMSA) && src_width < 32768) {
1405 ScaleFilterCols = ScaleFilterCols_Any_MSA;
1406 if (IS_ALIGNED(dst_width, 16)) {
1407 ScaleFilterCols = ScaleFilterCols_MSA;
1408 }
1409 }
1410#endif
Hao Chen2f87e9a2021-12-20 20:23:28 +08001411#if defined(HAS_SCALEFILTERCOLS_LSX)
1412 if (filtering && TestCpuFlag(kCpuHasLSX) && src_width < 32768) {
1413 ScaleFilterCols = ScaleFilterCols_Any_LSX;
1414 if (IS_ALIGNED(dst_width, 16)) {
1415 ScaleFilterCols = ScaleFilterCols_LSX;
1416 }
1417 }
1418#endif
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001419 if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
1420 ScaleFilterCols = ScaleColsUp2_C;
1421#if defined(HAS_SCALECOLS_SSE2)
fbarchard@google.comca308322014-10-07 00:59:31 +00001422 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001423 ScaleFilterCols = ScaleColsUp2_SSE2;
1424 }
1425#endif
fbarchard@google.coma2311692013-11-13 21:16:17 +00001426 }
1427
fbarchard@google.coma2311692013-11-13 21:16:17 +00001428 if (y > max_y) {
1429 y = max_y;
1430 }
fbarchard@google.comfa831882014-01-18 01:30:58 +00001431 {
1432 int yi = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001433 const uint8_t* src = src_ptr + yi * (int64_t)src_stride;
fbarchard@google.come86abbd2013-12-27 01:11:26 +00001434
fbarchard@google.comfa831882014-01-18 01:30:58 +00001435 // Allocate 2 row buffers.
Frank Barchardf71c8352022-09-16 11:12:39 -07001436 const int row_size = (dst_width + 31) & ~31;
1437 align_buffer_64(row, row_size * 2);
Frank Barcharddef473f2023-12-04 01:16:59 -08001438 if (!row)
1439 return 1;
fbarchard@google.come86abbd2013-12-27 01:11:26 +00001440
Frank Barchard7e389882018-01-22 18:35:52 -08001441 uint8_t* rowptr = row;
Frank Barchardf71c8352022-09-16 11:12:39 -07001442 int rowstride = row_size;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001443 int lasty = yi;
fbarchard@google.coma2311692013-11-13 21:16:17 +00001444
fbarchard@google.comfa831882014-01-18 01:30:58 +00001445 ScaleFilterCols(rowptr, src, dst_width, x, dx);
1446 if (src_height > 1) {
1447 src += src_stride;
1448 }
1449 ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx);
Frank Barchardfe4a50d2022-06-21 16:07:01 -07001450 if (src_height > 2) {
1451 src += src_stride;
1452 }
fbarchard@google.coma2311692013-11-13 21:16:17 +00001453
fbarchard@google.comfa831882014-01-18 01:30:58 +00001454 for (j = 0; j < dst_height; ++j) {
1455 yi = y >> 16;
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001456 if (yi != lasty) {
fbarchard@google.comfa831882014-01-18 01:30:58 +00001457 if (y > max_y) {
1458 y = max_y;
1459 yi = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001460 src = src_ptr + yi * (int64_t)src_stride;
fbarchard@google.comfa831882014-01-18 01:30:58 +00001461 }
1462 if (yi != lasty) {
1463 ScaleFilterCols(rowptr, src, dst_width, x, dx);
1464 rowptr += rowstride;
1465 rowstride = -rowstride;
1466 lasty = yi;
Frank Barchardfe4a50d2022-06-21 16:07:01 -07001467 if ((y + 65536) < max_y) {
1468 src += src_stride;
1469 }
fbarchard@google.comfa831882014-01-18 01:30:58 +00001470 }
fbarchard@google.coma2311692013-11-13 21:16:17 +00001471 }
fbarchard@google.comfa831882014-01-18 01:30:58 +00001472 if (filtering == kFilterLinear) {
1473 InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0);
1474 } else {
1475 int yf = (y >> 8) & 255;
1476 InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf);
1477 }
1478 dst_ptr += dst_stride;
1479 y += dy;
fbarchard@google.coma2311692013-11-13 21:16:17 +00001480 }
fbarchard@google.comfa831882014-01-18 01:30:58 +00001481 free_aligned_buffer_64(row);
fbarchard@google.coma2311692013-11-13 21:16:17 +00001482 }
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001483 return 0;
fbarchard@google.coma2311692013-11-13 21:16:17 +00001484}
1485
Frank Barchard942c5082021-02-05 16:14:25 -08001486// Scale plane, horizontally up by 2 times.
Yuan Tongfc61dde2021-02-03 14:21:07 +08001487// Uses linear filter horizontally, nearest vertically.
1488// This is an optimized version for scaling up a plane to 2 times of
1489// its original width, using linear interpolation.
1490// This is used to scale U and V planes of I422 to I444.
Frank Barchard650be742023-06-29 22:53:42 -07001491static void ScalePlaneUp2_Linear(int src_width,
1492 int src_height,
1493 int dst_width,
1494 int dst_height,
1495 int src_stride,
1496 int dst_stride,
1497 const uint8_t* src_ptr,
1498 uint8_t* dst_ptr) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08001499 void (*ScaleRowUp)(const uint8_t* src_ptr, uint8_t* dst_ptr, int dst_width) =
1500 ScaleRowUp2_Linear_Any_C;
1501 int i;
1502 int y;
1503 int dy;
1504
Yannis Guyona3b9c362023-10-02 15:03:27 +02001505 (void)src_width;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001506 // This function can only scale up by 2 times horizontally.
Frank Barchard942c5082021-02-05 16:14:25 -08001507 assert(src_width == ((dst_width + 1) / 2));
Yuan Tongfc61dde2021-02-03 14:21:07 +08001508
Frank Barchardb0284532022-08-01 12:49:02 -07001509#ifdef HAS_SCALEROWUP2_LINEAR_SSE2
Yuan Tongfc61dde2021-02-03 14:21:07 +08001510 if (TestCpuFlag(kCpuHasSSE2)) {
1511 ScaleRowUp = ScaleRowUp2_Linear_Any_SSE2;
1512 }
1513#endif
1514
Frank Barchardb0284532022-08-01 12:49:02 -07001515#ifdef HAS_SCALEROWUP2_LINEAR_SSSE3
Yuan Tongfc61dde2021-02-03 14:21:07 +08001516 if (TestCpuFlag(kCpuHasSSSE3)) {
1517 ScaleRowUp = ScaleRowUp2_Linear_Any_SSSE3;
1518 }
1519#endif
1520
Frank Barchardb0284532022-08-01 12:49:02 -07001521#ifdef HAS_SCALEROWUP2_LINEAR_AVX2
Yuan Tongfc61dde2021-02-03 14:21:07 +08001522 if (TestCpuFlag(kCpuHasAVX2)) {
1523 ScaleRowUp = ScaleRowUp2_Linear_Any_AVX2;
1524 }
1525#endif
1526
Frank Barchardb0284532022-08-01 12:49:02 -07001527#ifdef HAS_SCALEROWUP2_LINEAR_NEON
Yuan Tongfc61dde2021-02-03 14:21:07 +08001528 if (TestCpuFlag(kCpuHasNEON)) {
1529 ScaleRowUp = ScaleRowUp2_Linear_Any_NEON;
1530 }
1531#endif
Darren Hsieh10de9432023-06-09 05:51:48 -07001532#ifdef HAS_SCALEROWUP2_LINEAR_RVV
1533 if (TestCpuFlag(kCpuHasRVV)) {
1534 ScaleRowUp = ScaleRowUp2_Linear_RVV;
1535 }
1536#endif
Yuan Tongfc61dde2021-02-03 14:21:07 +08001537
1538 if (dst_height == 1) {
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001539 ScaleRowUp(src_ptr + ((src_height - 1) / 2) * (int64_t)src_stride, dst_ptr,
Yuan Tongfc61dde2021-02-03 14:21:07 +08001540 dst_width);
1541 } else {
1542 dy = FixedDiv(src_height - 1, dst_height - 1);
1543 y = (1 << 15) - 1;
1544 for (i = 0; i < dst_height; ++i) {
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001545 ScaleRowUp(src_ptr + (y >> 16) * (int64_t)src_stride, dst_ptr, dst_width);
Yuan Tongfc61dde2021-02-03 14:21:07 +08001546 dst_ptr += dst_stride;
1547 y += dy;
1548 }
1549 }
1550}
1551
Frank Barchard942c5082021-02-05 16:14:25 -08001552// Scale plane, up by 2 times.
Yuan Tongfc61dde2021-02-03 14:21:07 +08001553// This is an optimized version for scaling up a plane to 2 times of
1554// its original size, using bilinear interpolation.
1555// This is used to scale U and V planes of I420 to I444.
Frank Barchard650be742023-06-29 22:53:42 -07001556static void ScalePlaneUp2_Bilinear(int src_width,
1557 int src_height,
1558 int dst_width,
1559 int dst_height,
1560 int src_stride,
1561 int dst_stride,
1562 const uint8_t* src_ptr,
1563 uint8_t* dst_ptr) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08001564 void (*Scale2RowUp)(const uint8_t* src_ptr, ptrdiff_t src_stride,
1565 uint8_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
1566 ScaleRowUp2_Bilinear_Any_C;
1567 int x;
1568
Yannis Guyona3b9c362023-10-02 15:03:27 +02001569 (void)src_width;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001570 // This function can only scale up by 2 times.
Frank Barchard942c5082021-02-05 16:14:25 -08001571 assert(src_width == ((dst_width + 1) / 2));
Yuan Tongf7fc83f2021-02-09 13:09:59 +08001572 assert(src_height == ((dst_height + 1) / 2));
Yuan Tongfc61dde2021-02-03 14:21:07 +08001573
Frank Barchardb0284532022-08-01 12:49:02 -07001574#ifdef HAS_SCALEROWUP2_BILINEAR_SSE2
Yuan Tongfc61dde2021-02-03 14:21:07 +08001575 if (TestCpuFlag(kCpuHasSSE2)) {
1576 Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSE2;
1577 }
1578#endif
1579
Frank Barchardb0284532022-08-01 12:49:02 -07001580#ifdef HAS_SCALEROWUP2_BILINEAR_SSSE3
Yuan Tongfc61dde2021-02-03 14:21:07 +08001581 if (TestCpuFlag(kCpuHasSSSE3)) {
1582 Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSSE3;
1583 }
1584#endif
1585
Frank Barchardb0284532022-08-01 12:49:02 -07001586#ifdef HAS_SCALEROWUP2_BILINEAR_AVX2
Yuan Tongfc61dde2021-02-03 14:21:07 +08001587 if (TestCpuFlag(kCpuHasAVX2)) {
1588 Scale2RowUp = ScaleRowUp2_Bilinear_Any_AVX2;
1589 }
1590#endif
1591
Frank Barchardb0284532022-08-01 12:49:02 -07001592#ifdef HAS_SCALEROWUP2_BILINEAR_NEON
Yuan Tongfc61dde2021-02-03 14:21:07 +08001593 if (TestCpuFlag(kCpuHasNEON)) {
1594 Scale2RowUp = ScaleRowUp2_Bilinear_Any_NEON;
1595 }
1596#endif
Darren Hsieh10de9432023-06-09 05:51:48 -07001597#ifdef HAS_SCALEROWUP2_BILINEAR_RVV
1598 if (TestCpuFlag(kCpuHasRVV)) {
1599 Scale2RowUp = ScaleRowUp2_Bilinear_RVV;
1600 }
1601#endif
Yuan Tongfc61dde2021-02-03 14:21:07 +08001602
Yuan Tongd4ecb702021-02-12 10:49:25 +08001603 Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width);
1604 dst_ptr += dst_stride;
1605 for (x = 0; x < src_height - 1; ++x) {
1606 Scale2RowUp(src_ptr, src_stride, dst_ptr, dst_stride, dst_width);
1607 src_ptr += src_stride;
Frank Barchard60db98b2021-04-01 14:20:35 -07001608 // TODO(fbarchard): Test performance of writing one row of destination at a
1609 // time.
Yuan Tongd4ecb702021-02-12 10:49:25 +08001610 dst_ptr += 2 * dst_stride;
1611 }
1612 if (!(dst_height & 1)) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08001613 Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width);
Yuan Tongfc61dde2021-02-03 14:21:07 +08001614 }
1615}
1616
Frank Barchard942c5082021-02-05 16:14:25 -08001617// Scale at most 14 bit plane, horizontally up by 2 times.
Yuan Tongfc61dde2021-02-03 14:21:07 +08001618// This is an optimized version for scaling up a plane to 2 times of
1619// its original width, using linear interpolation.
1620// stride is in count of uint16_t.
1621// This is used to scale U and V planes of I210 to I410 and I212 to I412.
Frank Barchard650be742023-06-29 22:53:42 -07001622static void ScalePlaneUp2_12_Linear(int src_width,
1623 int src_height,
1624 int dst_width,
1625 int dst_height,
1626 int src_stride,
1627 int dst_stride,
1628 const uint16_t* src_ptr,
1629 uint16_t* dst_ptr) {
Yuan Tongc41eabe2021-03-02 23:41:07 +08001630 void (*ScaleRowUp)(const uint16_t* src_ptr, uint16_t* dst_ptr,
1631 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
1632 int i;
1633 int y;
1634 int dy;
1635
Yannis Guyona3b9c362023-10-02 15:03:27 +02001636 (void)src_width;
Yuan Tongc41eabe2021-03-02 23:41:07 +08001637 // This function can only scale up by 2 times horizontally.
1638 assert(src_width == ((dst_width + 1) / 2));
1639
Frank Barchardb0284532022-08-01 12:49:02 -07001640#ifdef HAS_SCALEROWUP2_LINEAR_12_SSSE3
Yuan Tongc41eabe2021-03-02 23:41:07 +08001641 if (TestCpuFlag(kCpuHasSSSE3)) {
1642 ScaleRowUp = ScaleRowUp2_Linear_12_Any_SSSE3;
1643 }
1644#endif
1645
Frank Barchardb0284532022-08-01 12:49:02 -07001646#ifdef HAS_SCALEROWUP2_LINEAR_12_AVX2
Yuan Tongc41eabe2021-03-02 23:41:07 +08001647 if (TestCpuFlag(kCpuHasAVX2)) {
1648 ScaleRowUp = ScaleRowUp2_Linear_12_Any_AVX2;
1649 }
1650#endif
1651
Frank Barchardb0284532022-08-01 12:49:02 -07001652#ifdef HAS_SCALEROWUP2_LINEAR_12_NEON
Yuan Tongc41eabe2021-03-02 23:41:07 +08001653 if (TestCpuFlag(kCpuHasNEON)) {
1654 ScaleRowUp = ScaleRowUp2_Linear_12_Any_NEON;
1655 }
1656#endif
1657
1658 if (dst_height == 1) {
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001659 ScaleRowUp(src_ptr + ((src_height - 1) / 2) * (int64_t)src_stride, dst_ptr,
Yuan Tongc41eabe2021-03-02 23:41:07 +08001660 dst_width);
1661 } else {
1662 dy = FixedDiv(src_height - 1, dst_height - 1);
1663 y = (1 << 15) - 1;
1664 for (i = 0; i < dst_height; ++i) {
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001665 ScaleRowUp(src_ptr + (y >> 16) * (int64_t)src_stride, dst_ptr, dst_width);
Yuan Tongc41eabe2021-03-02 23:41:07 +08001666 dst_ptr += dst_stride;
1667 y += dy;
1668 }
1669 }
1670}
1671
1672// Scale at most 12 bit plane, up by 2 times.
1673// This is an optimized version for scaling up a plane to 2 times of
1674// its original size, using bilinear interpolation.
1675// stride is in count of uint16_t.
1676// This is used to scale U and V planes of I010 to I410 and I012 to I412.
Frank Barchard650be742023-06-29 22:53:42 -07001677static void ScalePlaneUp2_12_Bilinear(int src_width,
1678 int src_height,
1679 int dst_width,
1680 int dst_height,
1681 int src_stride,
1682 int dst_stride,
1683 const uint16_t* src_ptr,
1684 uint16_t* dst_ptr) {
Yuan Tongc41eabe2021-03-02 23:41:07 +08001685 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
1686 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
1687 ScaleRowUp2_Bilinear_16_Any_C;
1688 int x;
1689
Yannis Guyona3b9c362023-10-02 15:03:27 +02001690 (void)src_width;
Yuan Tongc41eabe2021-03-02 23:41:07 +08001691 // This function can only scale up by 2 times.
1692 assert(src_width == ((dst_width + 1) / 2));
1693 assert(src_height == ((dst_height + 1) / 2));
1694
Frank Barchardb0284532022-08-01 12:49:02 -07001695#ifdef HAS_SCALEROWUP2_BILINEAR_12_SSSE3
Yuan Tongc41eabe2021-03-02 23:41:07 +08001696 if (TestCpuFlag(kCpuHasSSSE3)) {
1697 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_SSSE3;
1698 }
1699#endif
1700
Frank Barchardb0284532022-08-01 12:49:02 -07001701#ifdef HAS_SCALEROWUP2_BILINEAR_12_AVX2
Yuan Tongc41eabe2021-03-02 23:41:07 +08001702 if (TestCpuFlag(kCpuHasAVX2)) {
1703 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_AVX2;
1704 }
1705#endif
1706
Frank Barchardb0284532022-08-01 12:49:02 -07001707#ifdef HAS_SCALEROWUP2_BILINEAR_12_NEON
Yuan Tongc41eabe2021-03-02 23:41:07 +08001708 if (TestCpuFlag(kCpuHasNEON)) {
1709 Scale2RowUp = ScaleRowUp2_Bilinear_12_Any_NEON;
1710 }
1711#endif
1712
1713 Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width);
1714 dst_ptr += dst_stride;
1715 for (x = 0; x < src_height - 1; ++x) {
1716 Scale2RowUp(src_ptr, src_stride, dst_ptr, dst_stride, dst_width);
1717 src_ptr += src_stride;
1718 dst_ptr += 2 * dst_stride;
1719 }
1720 if (!(dst_height & 1)) {
1721 Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width);
1722 }
1723}
1724
Frank Barchard650be742023-06-29 22:53:42 -07001725static void ScalePlaneUp2_16_Linear(int src_width,
1726 int src_height,
1727 int dst_width,
1728 int dst_height,
1729 int src_stride,
1730 int dst_stride,
1731 const uint16_t* src_ptr,
1732 uint16_t* dst_ptr) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08001733 void (*ScaleRowUp)(const uint16_t* src_ptr, uint16_t* dst_ptr,
1734 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
1735 int i;
1736 int y;
1737 int dy;
1738
Yannis Guyona3b9c362023-10-02 15:03:27 +02001739 (void)src_width;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001740 // This function can only scale up by 2 times horizontally.
Frank Barchard942c5082021-02-05 16:14:25 -08001741 assert(src_width == ((dst_width + 1) / 2));
Yuan Tongfc61dde2021-02-03 14:21:07 +08001742
Frank Barchardb0284532022-08-01 12:49:02 -07001743#ifdef HAS_SCALEROWUP2_LINEAR_16_SSE2
Yuan Tongc41eabe2021-03-02 23:41:07 +08001744 if (TestCpuFlag(kCpuHasSSE2)) {
1745 ScaleRowUp = ScaleRowUp2_Linear_16_Any_SSE2;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001746 }
1747#endif
1748
Frank Barchardb0284532022-08-01 12:49:02 -07001749#ifdef HAS_SCALEROWUP2_LINEAR_16_AVX2
Yuan Tongfc61dde2021-02-03 14:21:07 +08001750 if (TestCpuFlag(kCpuHasAVX2)) {
1751 ScaleRowUp = ScaleRowUp2_Linear_16_Any_AVX2;
1752 }
1753#endif
1754
Frank Barchardb0284532022-08-01 12:49:02 -07001755#ifdef HAS_SCALEROWUP2_LINEAR_16_NEON
Yuan Tongfc61dde2021-02-03 14:21:07 +08001756 if (TestCpuFlag(kCpuHasNEON)) {
1757 ScaleRowUp = ScaleRowUp2_Linear_16_Any_NEON;
1758 }
1759#endif
1760
1761 if (dst_height == 1) {
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001762 ScaleRowUp(src_ptr + ((src_height - 1) / 2) * (int64_t)src_stride, dst_ptr,
Yuan Tongfc61dde2021-02-03 14:21:07 +08001763 dst_width);
1764 } else {
1765 dy = FixedDiv(src_height - 1, dst_height - 1);
1766 y = (1 << 15) - 1;
1767 for (i = 0; i < dst_height; ++i) {
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001768 ScaleRowUp(src_ptr + (y >> 16) * (int64_t)src_stride, dst_ptr, dst_width);
Yuan Tongfc61dde2021-02-03 14:21:07 +08001769 dst_ptr += dst_stride;
1770 y += dy;
1771 }
1772 }
1773}
1774
Frank Barchard650be742023-06-29 22:53:42 -07001775static void ScalePlaneUp2_16_Bilinear(int src_width,
1776 int src_height,
1777 int dst_width,
1778 int dst_height,
1779 int src_stride,
1780 int dst_stride,
1781 const uint16_t* src_ptr,
1782 uint16_t* dst_ptr) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08001783 void (*Scale2RowUp)(const uint16_t* src_ptr, ptrdiff_t src_stride,
1784 uint16_t* dst_ptr, ptrdiff_t dst_stride, int dst_width) =
Frank Barchardba033a12021-03-04 12:33:02 -08001785 ScaleRowUp2_Bilinear_16_Any_C;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001786 int x;
1787
Yannis Guyona3b9c362023-10-02 15:03:27 +02001788 (void)src_width;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001789 // This function can only scale up by 2 times.
Frank Barchard942c5082021-02-05 16:14:25 -08001790 assert(src_width == ((dst_width + 1) / 2));
Yuan Tongf7fc83f2021-02-09 13:09:59 +08001791 assert(src_height == ((dst_height + 1) / 2));
Yuan Tongfc61dde2021-02-03 14:21:07 +08001792
Frank Barchardb0284532022-08-01 12:49:02 -07001793#ifdef HAS_SCALEROWUP2_BILINEAR_16_SSE2
Yuan Tong98ec7c22022-08-02 17:43:54 +08001794 if (TestCpuFlag(kCpuHasSSE2)) {
1795 Scale2RowUp = ScaleRowUp2_Bilinear_16_Any_SSE2;
Yuan Tongfc61dde2021-02-03 14:21:07 +08001796 }
1797#endif
1798
Frank Barchardb0284532022-08-01 12:49:02 -07001799#ifdef HAS_SCALEROWUP2_BILINEAR_16_AVX2
Yuan Tongfc61dde2021-02-03 14:21:07 +08001800 if (TestCpuFlag(kCpuHasAVX2)) {
1801 Scale2RowUp = ScaleRowUp2_Bilinear_16_Any_AVX2;
1802 }
1803#endif
1804
Frank Barchardb0284532022-08-01 12:49:02 -07001805#ifdef HAS_SCALEROWUP2_BILINEAR_16_NEON
Yuan Tongfc61dde2021-02-03 14:21:07 +08001806 if (TestCpuFlag(kCpuHasNEON)) {
1807 Scale2RowUp = ScaleRowUp2_Bilinear_16_Any_NEON;
1808 }
1809#endif
1810
Yuan Tongd4ecb702021-02-12 10:49:25 +08001811 Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width);
1812 dst_ptr += dst_stride;
1813 for (x = 0; x < src_height - 1; ++x) {
1814 Scale2RowUp(src_ptr, src_stride, dst_ptr, dst_stride, dst_width);
1815 src_ptr += src_stride;
1816 dst_ptr += 2 * dst_stride;
1817 }
1818 if (!(dst_height & 1)) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08001819 Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width);
Yuan Tongfc61dde2021-02-03 14:21:07 +08001820 }
1821}
1822
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001823static int ScalePlaneBilinearUp_16(int src_width,
1824 int src_height,
1825 int dst_width,
1826 int dst_height,
1827 int src_stride,
1828 int dst_stride,
1829 const uint16_t* src_ptr,
1830 uint16_t* dst_ptr,
1831 enum FilterMode filtering) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001832 int j;
1833 // Initial source x/y coordinate and step values as 16.16 fixed point.
1834 int x = 0;
1835 int y = 0;
1836 int dx = 0;
1837 int dy = 0;
1838 const int max_y = (src_height - 1) << 16;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001839 void (*InterpolateRow)(uint16_t* dst_ptr, const uint16_t* src_ptr,
Frank Barcharde62309f2016-11-07 17:37:23 -08001840 ptrdiff_t src_stride, int dst_width,
1841 int source_y_fraction) = InterpolateRow_16_C;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001842 void (*ScaleFilterCols)(uint16_t* dst_ptr, const uint16_t* src_ptr,
Frank Barchard73a603e2017-03-08 09:49:02 -08001843 int dst_width, int x, int dx) =
fbarchard@google.com62a9fe32015-04-02 21:23:52 +00001844 filtering ? ScaleFilterCols_16_C : ScaleCols_16_C;
Frank Barcharde62309f2016-11-07 17:37:23 -08001845 ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
1846 &dx, &dy);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001847 src_width = Abs(src_width);
1848
1849#if defined(HAS_INTERPOLATEROW_16_SSE2)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001850 if (TestCpuFlag(kCpuHasSSE2)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001851 InterpolateRow = InterpolateRow_16_Any_SSE2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001852 if (IS_ALIGNED(dst_width, 16)) {
fbarchard@google.com044f9142014-10-01 01:16:04 +00001853 InterpolateRow = InterpolateRow_16_SSE2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001854 }
1855 }
1856#endif
1857#if defined(HAS_INTERPOLATEROW_16_SSSE3)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001858 if (TestCpuFlag(kCpuHasSSSE3)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001859 InterpolateRow = InterpolateRow_16_Any_SSSE3;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001860 if (IS_ALIGNED(dst_width, 16)) {
fbarchard@google.com044f9142014-10-01 01:16:04 +00001861 InterpolateRow = InterpolateRow_16_SSSE3;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001862 }
1863 }
1864#endif
1865#if defined(HAS_INTERPOLATEROW_16_AVX2)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001866 if (TestCpuFlag(kCpuHasAVX2)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001867 InterpolateRow = InterpolateRow_16_Any_AVX2;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001868 if (IS_ALIGNED(dst_width, 32)) {
1869 InterpolateRow = InterpolateRow_16_AVX2;
1870 }
1871 }
1872#endif
1873#if defined(HAS_INTERPOLATEROW_16_NEON)
fbarchard@google.com9ed836b2014-10-24 23:29:31 +00001874 if (TestCpuFlag(kCpuHasNEON)) {
Frank Barchard30f9b282022-06-09 00:14:11 -07001875 InterpolateRow = InterpolateRow_16_Any_NEON;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001876 if (IS_ALIGNED(dst_width, 16)) {
1877 InterpolateRow = InterpolateRow_16_NEON;
1878 }
1879 }
1880#endif
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001881
1882 if (filtering && src_width >= 32768) {
1883 ScaleFilterCols = ScaleFilterCols64_16_C;
1884 }
1885#if defined(HAS_SCALEFILTERCOLS_16_SSSE3)
1886 if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
1887 ScaleFilterCols = ScaleFilterCols_16_SSSE3;
1888 }
1889#endif
1890 if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
1891 ScaleFilterCols = ScaleColsUp2_16_C;
1892#if defined(HAS_SCALECOLS_16_SSE2)
fbarchard@google.comca308322014-10-07 00:59:31 +00001893 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001894 ScaleFilterCols = ScaleColsUp2_16_SSE2;
1895 }
1896#endif
1897 }
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001898 if (y > max_y) {
1899 y = max_y;
1900 }
1901 {
1902 int yi = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001903 const uint16_t* src = src_ptr + yi * (int64_t)src_stride;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001904
1905 // Allocate 2 row buffers.
Frank Barchardf71c8352022-09-16 11:12:39 -07001906 const int row_size = (dst_width + 31) & ~31;
1907 align_buffer_64(row, row_size * 4);
Frank Barchardf71c8352022-09-16 11:12:39 -07001908 int rowstride = row_size;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001909 int lasty = yi;
Frank Barcharddef473f2023-12-04 01:16:59 -08001910 uint16_t* rowptr = (uint16_t*)row;
1911 if (!row)
1912 return 1;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001913
1914 ScaleFilterCols(rowptr, src, dst_width, x, dx);
1915 if (src_height > 1) {
1916 src += src_stride;
1917 }
1918 ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx);
Frank Barchardfe4a50d2022-06-21 16:07:01 -07001919 if (src_height > 2) {
1920 src += src_stride;
1921 }
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001922
1923 for (j = 0; j < dst_height; ++j) {
1924 yi = y >> 16;
1925 if (yi != lasty) {
1926 if (y > max_y) {
1927 y = max_y;
1928 yi = y >> 16;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07001929 src = src_ptr + yi * (int64_t)src_stride;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001930 }
1931 if (yi != lasty) {
1932 ScaleFilterCols(rowptr, src, dst_width, x, dx);
1933 rowptr += rowstride;
1934 rowstride = -rowstride;
1935 lasty = yi;
Frank Barchardfe4a50d2022-06-21 16:07:01 -07001936 if ((y + 65536) < max_y) {
1937 src += src_stride;
1938 }
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001939 }
1940 }
1941 if (filtering == kFilterLinear) {
1942 InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0);
1943 } else {
1944 int yf = (y >> 8) & 255;
1945 InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf);
1946 }
1947 dst_ptr += dst_stride;
1948 y += dy;
1949 }
1950 free_aligned_buffer_64(row);
1951 }
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07001952 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00001953}
1954
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001955// Scale Plane to/from any dimensions, without interpolation.
fbarchard@google.com3c7bb052013-02-20 22:18:36 +00001956// Fixed point math is used for performance: The upper 16 bits
1957// of x and dx is the integer part of the source position and
1958// the lower 16 bits are the fixed decimal part.
1959
Frank Barcharde62309f2016-11-07 17:37:23 -08001960static void ScalePlaneSimple(int src_width,
1961 int src_height,
1962 int dst_width,
1963 int dst_height,
1964 int src_stride,
1965 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -08001966 const uint8_t* src_ptr,
1967 uint8_t* dst_ptr) {
fbarchard@google.comfa831882014-01-18 01:30:58 +00001968 int i;
Frank Barchard2bdc2102023-02-13 10:52:58 -08001969 void (*ScaleCols)(uint8_t* dst_ptr, const uint8_t* src_ptr, int dst_width,
Frank Barchard92e22cf2018-01-24 10:52:17 -08001970 int x, int dx) = ScaleCols_C;
fbarchard@google.comaae7deb2013-12-07 00:55:23 +00001971 // Initial source x/y coordinate and step values as 16.16 fixed point.
fbarchard@google.coma8e4dcb2013-12-04 20:31:53 +00001972 int x = 0;
1973 int y = 0;
fbarchard@google.comaae7deb2013-12-07 00:55:23 +00001974 int dx = 0;
1975 int dy = 0;
Frank Barcharde62309f2016-11-07 17:37:23 -08001976 ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone, &x, &y,
1977 &dx, &dy);
fbarchard@google.com6700a272014-01-09 20:21:24 +00001978 src_width = Abs(src_width);
fbarchard@google.coma8e4dcb2013-12-04 20:31:53 +00001979
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001980 if (src_width * 2 == dst_width && x < 0x8000) {
1981 ScaleCols = ScaleColsUp2_C;
1982#if defined(HAS_SCALECOLS_SSE2)
fbarchard@google.comca308322014-10-07 00:59:31 +00001983 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001984 ScaleCols = ScaleColsUp2_SSE2;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001985 }
fbarchard@google.come8c74b62013-11-14 02:03:32 +00001986#endif
1987 }
1988
fbarchard@google.com5aa39952014-01-11 04:59:01 +00001989 for (i = 0; i < dst_height; ++i) {
Frank Barchard55b97cb2021-10-15 12:12:02 -07001990 ScaleCols(dst_ptr, src_ptr + (y >> 16) * (int64_t)src_stride, dst_width, x,
1991 dx);
fbarchard@google.com4339f092012-02-23 10:52:55 +00001992 dst_ptr += dst_stride;
1993 y += dy;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00001994 }
1995}
1996
Frank Barcharde62309f2016-11-07 17:37:23 -08001997static void ScalePlaneSimple_16(int src_width,
1998 int src_height,
1999 int dst_width,
2000 int dst_height,
2001 int src_stride,
2002 int dst_stride,
Frank Barchard7e389882018-01-22 18:35:52 -08002003 const uint16_t* src_ptr,
2004 uint16_t* dst_ptr) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002005 int i;
Frank Barchard2bdc2102023-02-13 10:52:58 -08002006 void (*ScaleCols)(uint16_t* dst_ptr, const uint16_t* src_ptr, int dst_width,
Frank Barcharde62309f2016-11-07 17:37:23 -08002007 int x, int dx) = ScaleCols_16_C;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002008 // Initial source x/y coordinate and step values as 16.16 fixed point.
2009 int x = 0;
2010 int y = 0;
2011 int dx = 0;
2012 int dy = 0;
Frank Barcharde62309f2016-11-07 17:37:23 -08002013 ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone, &x, &y,
2014 &dx, &dy);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002015 src_width = Abs(src_width);
2016
2017 if (src_width * 2 == dst_width && x < 0x8000) {
2018 ScaleCols = ScaleColsUp2_16_C;
2019#if defined(HAS_SCALECOLS_16_SSE2)
fbarchard@google.comca308322014-10-07 00:59:31 +00002020 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002021 ScaleCols = ScaleColsUp2_16_SSE2;
2022 }
2023#endif
2024 }
2025
2026 for (i = 0; i < dst_height; ++i) {
Frank Barchard55b97cb2021-10-15 12:12:02 -07002027 ScaleCols(dst_ptr, src_ptr + (y >> 16) * (int64_t)src_stride, dst_width, x,
2028 dx);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002029 dst_ptr += dst_stride;
2030 y += dy;
2031 }
2032}
2033
fbarchard@google.com74b50f12012-03-27 02:09:03 +00002034// Scale a plane.
fbarchard@google.com99a12982013-12-04 23:36:06 +00002035// This function dispatches to a specialized scaler based on scale factor.
fbarchard@google.comfc7314e2012-09-27 02:17:51 +00002036LIBYUV_API
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002037int ScalePlane(const uint8_t* src,
2038 int src_stride,
2039 int src_width,
2040 int src_height,
2041 uint8_t* dst,
2042 int dst_stride,
2043 int dst_width,
2044 int dst_height,
2045 enum FilterMode filtering) {
fbarchard@google.comec0cc5b2013-12-05 00:28:12 +00002046 // Simplify filtering when possible.
Frank Barcharde62309f2016-11-07 17:37:23 -08002047 filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
2048 filtering);
fbarchard@google.comec0cc5b2013-12-05 00:28:12 +00002049
fbarchard@google.com99a12982013-12-04 23:36:06 +00002050 // Negative height means invert the image.
2051 if (src_height < 0) {
2052 src_height = -src_height;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07002053 src = src + (src_height - 1) * (int64_t)src_stride;
fbarchard@google.com99a12982013-12-04 23:36:06 +00002054 src_stride = -src_stride;
2055 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002056 // Use specialized scales to improve performance for common resolutions.
2057 // For example, all the 1/2 scalings will use ScalePlaneDown2()
fbarchard@google.coma1280732011-10-14 17:50:12 +00002058 if (dst_width == src_width && dst_height == src_height) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002059 // Straight copy.
fbarchard@google.com45b9ef02011-12-16 03:34:09 +00002060 CopyPlane(src, src_stride, dst, dst_stride, dst_width, dst_height);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002061 return 0;
fbarchard@google.coma2311692013-11-13 21:16:17 +00002062 }
fbarchard@google.com013e8122015-04-14 00:21:15 +00002063 if (dst_width == src_width && filtering != kFilterBox) {
Frank Barchard30f9b282022-06-09 00:14:11 -07002064 int dy = 0;
2065 int y = 0;
2066 // When scaling down, use the center 2 rows to filter.
2067 // When scaling up, last row of destination uses the last 2 source rows.
2068 if (dst_height <= src_height) {
2069 dy = FixedDiv(src_height, dst_height);
2070 y = CENTERSTART(dy, -32768); // Subtract 0.5 (32768) to center filter.
2071 } else if (src_height > 1 && dst_height > 1) {
2072 dy = FixedDiv1(src_height, dst_height);
2073 }
fbarchard@google.com812f59e2015-04-17 18:04:09 +00002074 // Arbitrary scale vertically, but unscaled horizontally.
Frank Barcharde62309f2016-11-07 17:37:23 -08002075 ScalePlaneVertical(src_height, dst_width, dst_height, src_stride,
Frank Barchard30f9b282022-06-09 00:14:11 -07002076 dst_stride, src, dst, 0, y, dy, /*bpp=*/1, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002077 return 0;
fbarchard@google.coma2311692013-11-13 21:16:17 +00002078 }
2079 if (dst_width <= Abs(src_width) && dst_height <= src_height) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002080 // Scale down.
Frank Barchard8279df92016-09-16 14:57:47 -07002081 if (4 * dst_width == 3 * src_width && 4 * dst_height == 3 * src_height) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002082 // optimized, 3/4
Frank Barcharde62309f2016-11-07 17:37:23 -08002083 ScalePlaneDown34(src_width, src_height, dst_width, dst_height, src_stride,
2084 dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002085 return 0;
fbarchard@google.coma2311692013-11-13 21:16:17 +00002086 }
2087 if (2 * dst_width == src_width && 2 * dst_height == src_height) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002088 // optimized, 1/2
Frank Barcharde62309f2016-11-07 17:37:23 -08002089 ScalePlaneDown2(src_width, src_height, dst_width, dst_height, src_stride,
2090 dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002091 return 0;
fbarchard@google.coma2311692013-11-13 21:16:17 +00002092 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002093 // 3/8 rounded up for odd sized chroma height.
Frank Barchard8279df92016-09-16 14:57:47 -07002094 if (8 * dst_width == 3 * src_width && 8 * dst_height == 3 * src_height) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002095 // optimized, 3/8
Frank Barcharde62309f2016-11-07 17:37:23 -08002096 ScalePlaneDown38(src_width, src_height, dst_width, dst_height, src_stride,
2097 dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002098 return 0;
fbarchard@google.coma2311692013-11-13 21:16:17 +00002099 }
2100 if (4 * dst_width == src_width && 4 * dst_height == src_height &&
fbarchard@google.com812f59e2015-04-17 18:04:09 +00002101 (filtering == kFilterBox || filtering == kFilterNone)) {
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002102 // optimized, 1/4
Frank Barcharde62309f2016-11-07 17:37:23 -08002103 ScalePlaneDown4(src_width, src_height, dst_width, dst_height, src_stride,
2104 dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002105 return 0;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002106 }
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002107 }
fbarchard@google.com6b6eb8c2013-12-27 02:09:58 +00002108 if (filtering == kFilterBox && dst_height * 2 < src_height) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002109 return ScalePlaneBox(src_width, src_height, dst_width, dst_height,
2110 src_stride, dst_stride, src, dst);
fbarchard@google.come8c74b62013-11-14 02:03:32 +00002111 }
Yuan Tongfc61dde2021-02-03 14:21:07 +08002112 if ((dst_width + 1) / 2 == src_width && filtering == kFilterLinear) {
2113 ScalePlaneUp2_Linear(src_width, src_height, dst_width, dst_height,
2114 src_stride, dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002115 return 0;
Yuan Tongfc61dde2021-02-03 14:21:07 +08002116 }
2117 if ((dst_height + 1) / 2 == src_height && (dst_width + 1) / 2 == src_width &&
2118 (filtering == kFilterBilinear || filtering == kFilterBox)) {
2119 ScalePlaneUp2_Bilinear(src_width, src_height, dst_width, dst_height,
2120 src_stride, dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002121 return 0;
Yuan Tongfc61dde2021-02-03 14:21:07 +08002122 }
fbarchard@google.come86abbd2013-12-27 01:11:26 +00002123 if (filtering && dst_height > src_height) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002124 return ScalePlaneBilinearUp(src_width, src_height, dst_width, dst_height,
2125 src_stride, dst_stride, src, dst, filtering);
fbarchard@google.come8c74b62013-11-14 02:03:32 +00002126 }
fbarchard@google.come86abbd2013-12-27 01:11:26 +00002127 if (filtering) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002128 return ScalePlaneBilinearDown(src_width, src_height, dst_width, dst_height,
2129 src_stride, dst_stride, src, dst, filtering);
fbarchard@google.come8c74b62013-11-14 02:03:32 +00002130 }
Frank Barcharde62309f2016-11-07 17:37:23 -08002131 ScalePlaneSimple(src_width, src_height, dst_width, dst_height, src_stride,
2132 dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002133 return 0;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002134}
2135
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002136LIBYUV_API
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002137int ScalePlane_16(const uint16_t* src,
2138 int src_stride,
2139 int src_width,
2140 int src_height,
2141 uint16_t* dst,
2142 int dst_stride,
2143 int dst_width,
2144 int dst_height,
2145 enum FilterMode filtering) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002146 // Simplify filtering when possible.
Frank Barcharde62309f2016-11-07 17:37:23 -08002147 filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
2148 filtering);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002149
2150 // Negative height means invert the image.
2151 if (src_height < 0) {
2152 src_height = -src_height;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07002153 src = src + (src_height - 1) * (int64_t)src_stride;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002154 src_stride = -src_stride;
2155 }
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002156 // Use specialized scales to improve performance for common resolutions.
2157 // For example, all the 1/2 scalings will use ScalePlaneDown2()
2158 if (dst_width == src_width && dst_height == src_height) {
2159 // Straight copy.
2160 CopyPlane_16(src, src_stride, dst, dst_stride, dst_width, dst_height);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002161 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002162 }
Frank Barchard630c8ed2017-11-15 10:48:42 -08002163 if (dst_width == src_width && filtering != kFilterBox) {
Frank Barchard30f9b282022-06-09 00:14:11 -07002164 int dy = 0;
2165 int y = 0;
2166 // When scaling down, use the center 2 rows to filter.
2167 // When scaling up, last row of destination uses the last 2 source rows.
2168 if (dst_height <= src_height) {
2169 dy = FixedDiv(src_height, dst_height);
2170 y = CENTERSTART(dy, -32768); // Subtract 0.5 (32768) to center filter.
2171 // When scaling up, ensure the last row of destination uses the last
2172 // source. Avoid divide by zero for dst_height but will do no scaling
2173 // later.
2174 } else if (src_height > 1 && dst_height > 1) {
2175 dy = FixedDiv1(src_height, dst_height);
2176 }
Frank Barchard7a52fde2020-09-28 12:41:52 -07002177 // Arbitrary scale vertically, but unscaled horizontally.
Frank Barcharde62309f2016-11-07 17:37:23 -08002178 ScalePlaneVertical_16(src_height, dst_width, dst_height, src_stride,
Frank Barchard3e38ce52022-08-17 11:20:36 -07002179 dst_stride, src, dst, 0, y, dy, /*bpp=*/1, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002180 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002181 }
2182 if (dst_width <= Abs(src_width) && dst_height <= src_height) {
2183 // Scale down.
Frank Barcharde62309f2016-11-07 17:37:23 -08002184 if (4 * dst_width == 3 * src_width && 4 * dst_height == 3 * src_height) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002185 // optimized, 3/4
2186 ScalePlaneDown34_16(src_width, src_height, dst_width, dst_height,
2187 src_stride, dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002188 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002189 }
2190 if (2 * dst_width == src_width && 2 * dst_height == src_height) {
2191 // optimized, 1/2
2192 ScalePlaneDown2_16(src_width, src_height, dst_width, dst_height,
2193 src_stride, dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002194 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002195 }
2196 // 3/8 rounded up for odd sized chroma height.
Frank Barchard8279df92016-09-16 14:57:47 -07002197 if (8 * dst_width == 3 * src_width && 8 * dst_height == 3 * src_height) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002198 // optimized, 3/8
2199 ScalePlaneDown38_16(src_width, src_height, dst_width, dst_height,
2200 src_stride, dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002201 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002202 }
2203 if (4 * dst_width == src_width && 4 * dst_height == src_height &&
Frank Barchard630c8ed2017-11-15 10:48:42 -08002204 (filtering == kFilterBox || filtering == kFilterNone)) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002205 // optimized, 1/4
2206 ScalePlaneDown4_16(src_width, src_height, dst_width, dst_height,
2207 src_stride, dst_stride, src, dst, filtering);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002208 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002209 }
2210 }
2211 if (filtering == kFilterBox && dst_height * 2 < src_height) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002212 return ScalePlaneBox_16(src_width, src_height, dst_width, dst_height,
2213 src_stride, dst_stride, src, dst);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002214 }
Yuan Tongc41eabe2021-03-02 23:41:07 +08002215 if ((dst_width + 1) / 2 == src_width && filtering == kFilterLinear) {
2216 ScalePlaneUp2_16_Linear(src_width, src_height, dst_width, dst_height,
2217 src_stride, dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002218 return 0;
Yuan Tongc41eabe2021-03-02 23:41:07 +08002219 }
2220 if ((dst_height + 1) / 2 == src_height && (dst_width + 1) / 2 == src_width &&
2221 (filtering == kFilterBilinear || filtering == kFilterBox)) {
2222 ScalePlaneUp2_16_Bilinear(src_width, src_height, dst_width, dst_height,
2223 src_stride, dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002224 return 0;
Yuan Tongc41eabe2021-03-02 23:41:07 +08002225 }
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002226 if (filtering && dst_height > src_height) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002227 return ScalePlaneBilinearUp_16(src_width, src_height, dst_width, dst_height,
2228 src_stride, dst_stride, src, dst, filtering);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002229 }
2230 if (filtering) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002231 return ScalePlaneBilinearDown_16(src_width, src_height, dst_width,
2232 dst_height, src_stride, dst_stride, src,
2233 dst, filtering);
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002234 }
Frank Barcharde62309f2016-11-07 17:37:23 -08002235 ScalePlaneSimple_16(src_width, src_height, dst_width, dst_height, src_stride,
2236 dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002237 return 0;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002238}
2239
Yuan Tongfc61dde2021-02-03 14:21:07 +08002240LIBYUV_API
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002241int ScalePlane_12(const uint16_t* src,
2242 int src_stride,
2243 int src_width,
2244 int src_height,
2245 uint16_t* dst,
2246 int dst_stride,
2247 int dst_width,
2248 int dst_height,
2249 enum FilterMode filtering) {
Yuan Tongfc61dde2021-02-03 14:21:07 +08002250 // Simplify filtering when possible.
2251 filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
2252 filtering);
2253
2254 // Negative height means invert the image.
2255 if (src_height < 0) {
2256 src_height = -src_height;
Frank Barchard11cbf8f2021-10-14 13:06:54 -07002257 src = src + (src_height - 1) * (int64_t)src_stride;
Yuan Tongfc61dde2021-02-03 14:21:07 +08002258 src_stride = -src_stride;
2259 }
2260
2261 if ((dst_width + 1) / 2 == src_width && filtering == kFilterLinear) {
Yuan Tongc41eabe2021-03-02 23:41:07 +08002262 ScalePlaneUp2_12_Linear(src_width, src_height, dst_width, dst_height,
Yuan Tongfc61dde2021-02-03 14:21:07 +08002263 src_stride, dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002264 return 0;
Yuan Tongfc61dde2021-02-03 14:21:07 +08002265 }
2266 if ((dst_height + 1) / 2 == src_height && (dst_width + 1) / 2 == src_width &&
2267 (filtering == kFilterBilinear || filtering == kFilterBox)) {
Yuan Tongc41eabe2021-03-02 23:41:07 +08002268 ScalePlaneUp2_12_Bilinear(src_width, src_height, dst_width, dst_height,
Yuan Tongfc61dde2021-02-03 14:21:07 +08002269 src_stride, dst_stride, src, dst);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002270 return 0;
Yuan Tongfc61dde2021-02-03 14:21:07 +08002271 }
2272
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002273 return ScalePlane_16(src, src_stride, src_width, src_height, dst, dst_stride,
2274 dst_width, dst_height, filtering);
Yuan Tongfc61dde2021-02-03 14:21:07 +08002275}
2276
fbarchard@google.com74b50f12012-03-27 02:09:03 +00002277// Scale an I420 image.
fbarchard@google.com74b50f12012-03-27 02:09:03 +00002278// This function in turn calls a scaling function for each plane.
fbarchard@google.comd9eb63f2012-06-21 01:13:44 +00002279
fbarchard@google.comfc7314e2012-09-27 02:17:51 +00002280LIBYUV_API
Frank Barchard7e389882018-01-22 18:35:52 -08002281int I420Scale(const uint8_t* src_y,
Frank Barcharde62309f2016-11-07 17:37:23 -08002282 int src_stride_y,
Frank Barchard7e389882018-01-22 18:35:52 -08002283 const uint8_t* src_u,
Frank Barcharde62309f2016-11-07 17:37:23 -08002284 int src_stride_u,
Frank Barchard7e389882018-01-22 18:35:52 -08002285 const uint8_t* src_v,
Frank Barcharde62309f2016-11-07 17:37:23 -08002286 int src_stride_v,
2287 int src_width,
2288 int src_height,
Frank Barchard7e389882018-01-22 18:35:52 -08002289 uint8_t* dst_y,
Frank Barcharde62309f2016-11-07 17:37:23 -08002290 int dst_stride_y,
Frank Barchard7e389882018-01-22 18:35:52 -08002291 uint8_t* dst_u,
Frank Barcharde62309f2016-11-07 17:37:23 -08002292 int dst_stride_u,
Frank Barchard7e389882018-01-22 18:35:52 -08002293 uint8_t* dst_v,
Frank Barcharde62309f2016-11-07 17:37:23 -08002294 int dst_stride_v,
2295 int dst_width,
2296 int dst_height,
fbarchard@google.comdb735182014-01-07 03:59:31 +00002297 enum FilterMode filtering) {
fbarchard@google.com99a12982013-12-04 23:36:06 +00002298 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2299 int src_halfheight = SUBSAMPLE(src_height, 1, 1);
2300 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
2301 int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002302 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002303
Frank Barchardd7687742021-02-12 09:59:00 -08002304 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
Frank Barcharde62309f2016-11-07 17:37:23 -08002305 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2306 dst_width <= 0 || dst_height <= 0) {
fbarchard@google.comfa831882014-01-18 01:30:58 +00002307 return -1;
2308 }
fbarchard@google.comd9eb63f2012-06-21 01:13:44 +00002309
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002310 r = ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y,
2311 dst_stride_y, dst_width, dst_height, filtering);
2312 if (r != 0) {
2313 return r;
2314 }
2315 r = ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u,
2316 dst_stride_u, dst_halfwidth, dst_halfheight, filtering);
2317 if (r != 0) {
2318 return r;
2319 }
2320 r = ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v,
2321 dst_stride_v, dst_halfwidth, dst_halfheight, filtering);
2322 return r;
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002323}
2324
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002325LIBYUV_API
Frank Barchard7e389882018-01-22 18:35:52 -08002326int I420Scale_16(const uint16_t* src_y,
Frank Barcharde62309f2016-11-07 17:37:23 -08002327 int src_stride_y,
Frank Barchard7e389882018-01-22 18:35:52 -08002328 const uint16_t* src_u,
Frank Barcharde62309f2016-11-07 17:37:23 -08002329 int src_stride_u,
Frank Barchard7e389882018-01-22 18:35:52 -08002330 const uint16_t* src_v,
Frank Barcharde62309f2016-11-07 17:37:23 -08002331 int src_stride_v,
2332 int src_width,
2333 int src_height,
Frank Barchard7e389882018-01-22 18:35:52 -08002334 uint16_t* dst_y,
Frank Barcharde62309f2016-11-07 17:37:23 -08002335 int dst_stride_y,
Frank Barchard7e389882018-01-22 18:35:52 -08002336 uint16_t* dst_u,
Frank Barcharde62309f2016-11-07 17:37:23 -08002337 int dst_stride_u,
Frank Barchard7e389882018-01-22 18:35:52 -08002338 uint16_t* dst_v,
Frank Barcharde62309f2016-11-07 17:37:23 -08002339 int dst_stride_v,
2340 int dst_width,
2341 int dst_height,
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002342 enum FilterMode filtering) {
2343 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2344 int src_halfheight = SUBSAMPLE(src_height, 1, 1);
2345 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
2346 int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002347 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002348
Frank Barchardd7687742021-02-12 09:59:00 -08002349 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
Frank Barcharde62309f2016-11-07 17:37:23 -08002350 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2351 dst_width <= 0 || dst_height <= 0) {
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002352 return -1;
2353 }
2354
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002355 r = ScalePlane_16(src_y, src_stride_y, src_width, src_height, dst_y,
2356 dst_stride_y, dst_width, dst_height, filtering);
2357 if (r != 0) {
2358 return r;
2359 }
2360 r = ScalePlane_16(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u,
2361 dst_stride_u, dst_halfwidth, dst_halfheight, filtering);
2362 if (r != 0) {
2363 return r;
2364 }
2365 r = ScalePlane_16(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v,
2366 dst_stride_v, dst_halfwidth, dst_halfheight, filtering);
2367 return r;
fbarchard@google.comb18413e2014-05-20 19:22:30 +00002368}
2369
Frank Barchard08815a22021-02-19 08:58:07 -08002370LIBYUV_API
2371int I420Scale_12(const uint16_t* src_y,
2372 int src_stride_y,
2373 const uint16_t* src_u,
2374 int src_stride_u,
2375 const uint16_t* src_v,
2376 int src_stride_v,
2377 int src_width,
2378 int src_height,
2379 uint16_t* dst_y,
2380 int dst_stride_y,
2381 uint16_t* dst_u,
2382 int dst_stride_u,
2383 uint16_t* dst_v,
2384 int dst_stride_v,
2385 int dst_width,
2386 int dst_height,
2387 enum FilterMode filtering) {
2388 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2389 int src_halfheight = SUBSAMPLE(src_height, 1, 1);
2390 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
2391 int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002392 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002393
Frank Barchard08815a22021-02-19 08:58:07 -08002394 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
2395 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2396 dst_width <= 0 || dst_height <= 0) {
2397 return -1;
2398 }
2399
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002400 r = ScalePlane_12(src_y, src_stride_y, src_width, src_height, dst_y,
2401 dst_stride_y, dst_width, dst_height, filtering);
2402 if (r != 0) {
2403 return r;
2404 }
2405 r = ScalePlane_12(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u,
2406 dst_stride_u, dst_halfwidth, dst_halfheight, filtering);
2407 if (r != 0) {
2408 return r;
2409 }
2410 r = ScalePlane_12(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v,
2411 dst_stride_v, dst_halfwidth, dst_halfheight, filtering);
2412 return r;
Frank Barchard08815a22021-02-19 08:58:07 -08002413}
2414
Emmanuel Weber05f72b82019-05-06 15:40:22 -07002415// Scale an I444 image.
2416// This function in turn calls a scaling function for each plane.
2417
2418LIBYUV_API
2419int I444Scale(const uint8_t* src_y,
2420 int src_stride_y,
2421 const uint8_t* src_u,
2422 int src_stride_u,
2423 const uint8_t* src_v,
2424 int src_stride_v,
2425 int src_width,
2426 int src_height,
2427 uint8_t* dst_y,
2428 int dst_stride_y,
2429 uint8_t* dst_u,
2430 int dst_stride_u,
2431 uint8_t* dst_v,
2432 int dst_stride_v,
2433 int dst_width,
2434 int dst_height,
2435 enum FilterMode filtering) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002436 int r;
2437
Frank Barchardd7687742021-02-12 09:59:00 -08002438 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
Emmanuel Weber05f72b82019-05-06 15:40:22 -07002439 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2440 dst_width <= 0 || dst_height <= 0) {
2441 return -1;
2442 }
2443
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002444 r = ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y,
2445 dst_stride_y, dst_width, dst_height, filtering);
2446 if (r != 0) {
2447 return r;
2448 }
2449 r = ScalePlane(src_u, src_stride_u, src_width, src_height, dst_u,
2450 dst_stride_u, dst_width, dst_height, filtering);
2451 if (r != 0) {
2452 return r;
2453 }
2454 r = ScalePlane(src_v, src_stride_v, src_width, src_height, dst_v,
2455 dst_stride_v, dst_width, dst_height, filtering);
2456 return r;
Emmanuel Weber05f72b82019-05-06 15:40:22 -07002457}
2458
Frank Barchard681c6c62019-05-13 17:34:53 -07002459LIBYUV_API
2460int I444Scale_16(const uint16_t* src_y,
2461 int src_stride_y,
2462 const uint16_t* src_u,
2463 int src_stride_u,
2464 const uint16_t* src_v,
2465 int src_stride_v,
2466 int src_width,
2467 int src_height,
2468 uint16_t* dst_y,
2469 int dst_stride_y,
2470 uint16_t* dst_u,
2471 int dst_stride_u,
2472 uint16_t* dst_v,
2473 int dst_stride_v,
2474 int dst_width,
2475 int dst_height,
2476 enum FilterMode filtering) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002477 int r;
2478
Frank Barchardd7687742021-02-12 09:59:00 -08002479 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
Frank Barchard681c6c62019-05-13 17:34:53 -07002480 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2481 dst_width <= 0 || dst_height <= 0) {
2482 return -1;
2483 }
2484
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002485 r = ScalePlane_16(src_y, src_stride_y, src_width, src_height, dst_y,
2486 dst_stride_y, dst_width, dst_height, filtering);
2487 if (r != 0) {
2488 return r;
2489 }
2490 r = ScalePlane_16(src_u, src_stride_u, src_width, src_height, dst_u,
2491 dst_stride_u, dst_width, dst_height, filtering);
2492 if (r != 0) {
2493 return r;
2494 }
2495 r = ScalePlane_16(src_v, src_stride_v, src_width, src_height, dst_v,
2496 dst_stride_v, dst_width, dst_height, filtering);
2497 return r;
Frank Barchard681c6c62019-05-13 17:34:53 -07002498}
2499
Frank Barchard08815a22021-02-19 08:58:07 -08002500LIBYUV_API
2501int I444Scale_12(const uint16_t* src_y,
2502 int src_stride_y,
2503 const uint16_t* src_u,
2504 int src_stride_u,
2505 const uint16_t* src_v,
2506 int src_stride_v,
2507 int src_width,
2508 int src_height,
2509 uint16_t* dst_y,
2510 int dst_stride_y,
2511 uint16_t* dst_u,
2512 int dst_stride_u,
2513 uint16_t* dst_v,
2514 int dst_stride_v,
2515 int dst_width,
2516 int dst_height,
2517 enum FilterMode filtering) {
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002518 int r;
2519
Frank Barchard08815a22021-02-19 08:58:07 -08002520 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
2521 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2522 dst_width <= 0 || dst_height <= 0) {
2523 return -1;
2524 }
2525
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002526 r = ScalePlane_12(src_y, src_stride_y, src_width, src_height, dst_y,
2527 dst_stride_y, dst_width, dst_height, filtering);
2528 if (r != 0) {
2529 return r;
2530 }
2531 r = ScalePlane_12(src_u, src_stride_u, src_width, src_height, dst_u,
2532 dst_stride_u, dst_width, dst_height, filtering);
2533 if (r != 0) {
2534 return r;
2535 }
2536 r = ScalePlane_12(src_v, src_stride_v, src_width, src_height, dst_v,
2537 dst_stride_v, dst_width, dst_height, filtering);
2538 return r;
Frank Barchard08815a22021-02-19 08:58:07 -08002539}
2540
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002541// Scale an I422 image.
2542// This function in turn calls a scaling function for each plane.
2543
2544LIBYUV_API
2545int I422Scale(const uint8_t* src_y,
2546 int src_stride_y,
2547 const uint8_t* src_u,
2548 int src_stride_u,
2549 const uint8_t* src_v,
2550 int src_stride_v,
2551 int src_width,
2552 int src_height,
2553 uint8_t* dst_y,
2554 int dst_stride_y,
2555 uint8_t* dst_u,
2556 int dst_stride_u,
2557 uint8_t* dst_v,
2558 int dst_stride_v,
2559 int dst_width,
2560 int dst_height,
Frank Barchard2ad73732022-04-07 11:53:03 -07002561 enum FilterMode filtering) {
2562 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2563 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002564 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002565
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002566 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
2567 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2568 dst_width <= 0 || dst_height <= 0) {
2569 return -1;
2570 }
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002571
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002572 r = ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y,
2573 dst_stride_y, dst_width, dst_height, filtering);
2574 if (r != 0) {
2575 return r;
2576 }
2577 r = ScalePlane(src_u, src_stride_u, src_halfwidth, src_height, dst_u,
2578 dst_stride_u, dst_halfwidth, dst_height, filtering);
2579 if (r != 0) {
2580 return r;
2581 }
2582 r = ScalePlane(src_v, src_stride_v, src_halfwidth, src_height, dst_v,
2583 dst_stride_v, dst_halfwidth, dst_height, filtering);
2584 return r;
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002585}
2586
2587LIBYUV_API
2588int I422Scale_16(const uint16_t* src_y,
2589 int src_stride_y,
2590 const uint16_t* src_u,
2591 int src_stride_u,
2592 const uint16_t* src_v,
2593 int src_stride_v,
2594 int src_width,
2595 int src_height,
2596 uint16_t* dst_y,
2597 int dst_stride_y,
2598 uint16_t* dst_u,
2599 int dst_stride_u,
2600 uint16_t* dst_v,
2601 int dst_stride_v,
2602 int dst_width,
2603 int dst_height,
Frank Barchard2ad73732022-04-07 11:53:03 -07002604 enum FilterMode filtering) {
2605 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2606 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002607 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002608
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002609 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
2610 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2611 dst_width <= 0 || dst_height <= 0) {
2612 return -1;
2613 }
2614
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002615 r = ScalePlane_16(src_y, src_stride_y, src_width, src_height, dst_y,
2616 dst_stride_y, dst_width, dst_height, filtering);
2617 if (r != 0) {
2618 return r;
2619 }
2620 r = ScalePlane_16(src_u, src_stride_u, src_halfwidth, src_height, dst_u,
2621 dst_stride_u, dst_halfwidth, dst_height, filtering);
2622 if (r != 0) {
2623 return r;
2624 }
2625 r = ScalePlane_16(src_v, src_stride_v, src_halfwidth, src_height, dst_v,
2626 dst_stride_v, dst_halfwidth, dst_height, filtering);
2627 return r;
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002628}
2629
2630LIBYUV_API
2631int I422Scale_12(const uint16_t* src_y,
2632 int src_stride_y,
2633 const uint16_t* src_u,
2634 int src_stride_u,
2635 const uint16_t* src_v,
2636 int src_stride_v,
2637 int src_width,
2638 int src_height,
2639 uint16_t* dst_y,
2640 int dst_stride_y,
2641 uint16_t* dst_u,
2642 int dst_stride_u,
2643 uint16_t* dst_v,
2644 int dst_stride_v,
2645 int dst_width,
2646 int dst_height,
Frank Barchard2ad73732022-04-07 11:53:03 -07002647 enum FilterMode filtering) {
2648 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2649 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002650 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002651
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002652 if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
2653 src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
2654 dst_width <= 0 || dst_height <= 0) {
2655 return -1;
2656 }
2657
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002658 r = ScalePlane_12(src_y, src_stride_y, src_width, src_height, dst_y,
2659 dst_stride_y, dst_width, dst_height, filtering);
2660 if (r != 0) {
2661 return r;
2662 }
2663 r = ScalePlane_12(src_u, src_stride_u, src_halfwidth, src_height, dst_u,
2664 dst_stride_u, dst_halfwidth, dst_height, filtering);
2665 if (r != 0) {
2666 return r;
2667 }
2668 r = ScalePlane_12(src_v, src_stride_v, src_halfwidth, src_height, dst_v,
2669 dst_stride_v, dst_halfwidth, dst_height, filtering);
2670 return r;
Sergio Garcia Murillo45890812022-03-30 11:20:30 +02002671}
2672
Frank Barchard7a52fde2020-09-28 12:41:52 -07002673// Scale an NV12 image.
2674// This function in turn calls a scaling function for each plane.
2675
Frank Barcharde6479022020-09-29 15:49:57 -07002676LIBYUV_API
Frank Barchard7a52fde2020-09-28 12:41:52 -07002677int NV12Scale(const uint8_t* src_y,
Frank Barcharde6479022020-09-29 15:49:57 -07002678 int src_stride_y,
2679 const uint8_t* src_uv,
2680 int src_stride_uv,
2681 int src_width,
2682 int src_height,
2683 uint8_t* dst_y,
2684 int dst_stride_y,
2685 uint8_t* dst_uv,
2686 int dst_stride_uv,
2687 int dst_width,
2688 int dst_height,
2689 enum FilterMode filtering) {
2690 int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
2691 int src_halfheight = SUBSAMPLE(src_height, 1, 1);
2692 int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
2693 int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002694 int r;
Frank Barchard2ad73732022-04-07 11:53:03 -07002695
Frank Barchardd7687742021-02-12 09:59:00 -08002696 if (!src_y || !src_uv || src_width <= 0 || src_height == 0 ||
Frank Barcharde6479022020-09-29 15:49:57 -07002697 src_width > 32768 || src_height > 32768 || !dst_y || !dst_uv ||
2698 dst_width <= 0 || dst_height <= 0) {
2699 return -1;
Frank Barchard7a52fde2020-09-28 12:41:52 -07002700 }
2701
Wan-Teh Changfb6341d2023-11-03 14:23:15 -07002702 r = ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y,
2703 dst_stride_y, dst_width, dst_height, filtering);
2704 if (r != 0) {
2705 return r;
2706 }
2707 r = UVScale(src_uv, src_stride_uv, src_halfwidth, src_halfheight, dst_uv,
2708 dst_stride_uv, dst_halfwidth, dst_halfheight, filtering);
2709 return r;
Frank Barchard7a52fde2020-09-28 12:41:52 -07002710}
2711
fbarchard@google.comfe5ff7e2011-12-10 07:45:58 +00002712// Deprecated api
fbarchard@google.comfc7314e2012-09-27 02:17:51 +00002713LIBYUV_API
Frank Barchard7e389882018-01-22 18:35:52 -08002714int Scale(const uint8_t* src_y,
2715 const uint8_t* src_u,
2716 const uint8_t* src_v,
Frank Barcharde62309f2016-11-07 17:37:23 -08002717 int src_stride_y,
2718 int src_stride_u,
2719 int src_stride_v,
2720 int src_width,
2721 int src_height,
Frank Barchard7e389882018-01-22 18:35:52 -08002722 uint8_t* dst_y,
2723 uint8_t* dst_u,
2724 uint8_t* dst_v,
Frank Barcharde62309f2016-11-07 17:37:23 -08002725 int dst_stride_y,
2726 int dst_stride_u,
2727 int dst_stride_v,
2728 int dst_width,
2729 int dst_height,
fbarchard@google.comdb735182014-01-07 03:59:31 +00002730 LIBYUV_BOOL interpolate) {
Frank Barcharde62309f2016-11-07 17:37:23 -08002731 return I420Scale(src_y, src_stride_y, src_u, src_stride_u, src_v,
2732 src_stride_v, src_width, src_height, dst_y, dst_stride_y,
2733 dst_u, dst_stride_u, dst_v, dst_stride_v, dst_width,
2734 dst_height, interpolate ? kFilterBox : kFilterNone);
fbarchard@google.coma1280732011-10-14 17:50:12 +00002735}
2736
fbarchard@google.comfe5ff7e2011-12-10 07:45:58 +00002737#ifdef __cplusplus
2738} // extern "C"
mikhal@webrtc.orgaed1cc92011-09-28 00:06:25 +00002739} // namespace libyuv
fbarchard@google.comfe5ff7e2011-12-10 07:45:58 +00002740#endif