1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
12*fb1b10abSAndroid Build Coastguard Worker *
13*fb1b10abSAndroid Build Coastguard Worker * Module Title : scale.c
14*fb1b10abSAndroid Build Coastguard Worker *
15*fb1b10abSAndroid Build Coastguard Worker * Description : Image scaling functions.
16*fb1b10abSAndroid Build Coastguard Worker *
17*fb1b10abSAndroid Build Coastguard Worker ***************************************************************************/
18*fb1b10abSAndroid Build Coastguard Worker
19*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
20*fb1b10abSAndroid Build Coastguard Worker * Header Files
21*fb1b10abSAndroid Build Coastguard Worker ****************************************************************************/
22*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
23*fb1b10abSAndroid Build Coastguard Worker
24*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_scale_rtcd.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "vpx_scale/vpx_scale.h"
27*fb1b10abSAndroid Build Coastguard Worker #include "vpx_scale/yv12config.h"
28*fb1b10abSAndroid Build Coastguard Worker
29*fb1b10abSAndroid Build Coastguard Worker typedef struct {
30*fb1b10abSAndroid Build Coastguard Worker int expanded_frame_width;
31*fb1b10abSAndroid Build Coastguard Worker int expanded_frame_height;
32*fb1b10abSAndroid Build Coastguard Worker
33*fb1b10abSAndroid Build Coastguard Worker int HScale;
34*fb1b10abSAndroid Build Coastguard Worker int HRatio;
35*fb1b10abSAndroid Build Coastguard Worker int VScale;
36*fb1b10abSAndroid Build Coastguard Worker int VRatio;
37*fb1b10abSAndroid Build Coastguard Worker
38*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *src_yuv_config;
39*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *dst_yuv_config;
40*fb1b10abSAndroid Build Coastguard Worker
41*fb1b10abSAndroid Build Coastguard Worker } SCALE_VARS;
42*fb1b10abSAndroid Build Coastguard Worker
43*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
44*fb1b10abSAndroid Build Coastguard Worker *
45*fb1b10abSAndroid Build Coastguard Worker * ROUTINE : scale1d_2t1_i
46*fb1b10abSAndroid Build Coastguard Worker *
47*fb1b10abSAndroid Build Coastguard Worker * INPUTS : const unsigned char *source : Pointer to data to be scaled.
48*fb1b10abSAndroid Build Coastguard Worker * int source_step : Number of pixels to step on in
49*fb1b10abSAndroid Build Coastguard Worker * source.
50*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_scale : Scale for source (UNUSED).
51*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_length : Length of source (UNUSED).
52*fb1b10abSAndroid Build Coastguard Worker * unsigned char *dest : Pointer to output data array.
53*fb1b10abSAndroid Build Coastguard Worker * int dest_step : Number of pixels to step on in
54*fb1b10abSAndroid Build Coastguard Worker * destination.
55*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_scale : Scale for destination
56*fb1b10abSAndroid Build Coastguard Worker * (UNUSED).
57*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_length : Length of destination.
58*fb1b10abSAndroid Build Coastguard Worker *
59*fb1b10abSAndroid Build Coastguard Worker * OUTPUTS : None.
60*fb1b10abSAndroid Build Coastguard Worker *
61*fb1b10abSAndroid Build Coastguard Worker * RETURNS : void
62*fb1b10abSAndroid Build Coastguard Worker *
63*fb1b10abSAndroid Build Coastguard Worker * FUNCTION : Performs 2-to-1 interpolated scaling.
64*fb1b10abSAndroid Build Coastguard Worker *
65*fb1b10abSAndroid Build Coastguard Worker * SPECIAL NOTES : None.
66*fb1b10abSAndroid Build Coastguard Worker *
67*fb1b10abSAndroid Build Coastguard Worker ****************************************************************************/
scale1d_2t1_i(const unsigned char * source,int source_step,unsigned int source_scale,unsigned int source_length,unsigned char * dest,int dest_step,unsigned int dest_scale,unsigned int dest_length)68*fb1b10abSAndroid Build Coastguard Worker static void scale1d_2t1_i(const unsigned char *source, int source_step,
69*fb1b10abSAndroid Build Coastguard Worker unsigned int source_scale, unsigned int source_length,
70*fb1b10abSAndroid Build Coastguard Worker unsigned char *dest, int dest_step,
71*fb1b10abSAndroid Build Coastguard Worker unsigned int dest_scale, unsigned int dest_length) {
72*fb1b10abSAndroid Build Coastguard Worker unsigned int i, j;
73*fb1b10abSAndroid Build Coastguard Worker unsigned int temp;
74*fb1b10abSAndroid Build Coastguard Worker int source_pitch = source_step;
75*fb1b10abSAndroid Build Coastguard Worker (void)source_length;
76*fb1b10abSAndroid Build Coastguard Worker (void)source_scale;
77*fb1b10abSAndroid Build Coastguard Worker (void)dest_scale;
78*fb1b10abSAndroid Build Coastguard Worker
79*fb1b10abSAndroid Build Coastguard Worker source_step *= 2;
80*fb1b10abSAndroid Build Coastguard Worker dest[0] = source[0];
81*fb1b10abSAndroid Build Coastguard Worker
82*fb1b10abSAndroid Build Coastguard Worker for (i = dest_step, j = source_step; i < dest_length * dest_step;
83*fb1b10abSAndroid Build Coastguard Worker i += dest_step, j += source_step) {
84*fb1b10abSAndroid Build Coastguard Worker temp = 8;
85*fb1b10abSAndroid Build Coastguard Worker temp += 3 * source[j - source_pitch];
86*fb1b10abSAndroid Build Coastguard Worker temp += 10 * source[j];
87*fb1b10abSAndroid Build Coastguard Worker temp += 3 * source[j + source_pitch];
88*fb1b10abSAndroid Build Coastguard Worker temp >>= 4;
89*fb1b10abSAndroid Build Coastguard Worker dest[i] = (char)(temp);
90*fb1b10abSAndroid Build Coastguard Worker }
91*fb1b10abSAndroid Build Coastguard Worker }
92*fb1b10abSAndroid Build Coastguard Worker
93*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
94*fb1b10abSAndroid Build Coastguard Worker *
95*fb1b10abSAndroid Build Coastguard Worker * ROUTINE : scale1d_2t1_ps
96*fb1b10abSAndroid Build Coastguard Worker *
97*fb1b10abSAndroid Build Coastguard Worker * INPUTS : const unsigned char *source : Pointer to data to be scaled.
98*fb1b10abSAndroid Build Coastguard Worker * int source_step : Number of pixels to step on in
99*fb1b10abSAndroid Build Coastguard Worker * source.
100*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_scale : Scale for source (UNUSED).
101*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_length : Length of source (UNUSED).
102*fb1b10abSAndroid Build Coastguard Worker * unsigned char *dest : Pointer to output data array.
103*fb1b10abSAndroid Build Coastguard Worker * int dest_step : Number of pixels to step on in
104*fb1b10abSAndroid Build Coastguard Worker * destination.
105*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_scale : Scale for destination
106*fb1b10abSAndroid Build Coastguard Worker * (UNUSED).
107*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_length : Length of destination.
108*fb1b10abSAndroid Build Coastguard Worker *
109*fb1b10abSAndroid Build Coastguard Worker * OUTPUTS : None.
110*fb1b10abSAndroid Build Coastguard Worker *
111*fb1b10abSAndroid Build Coastguard Worker * RETURNS : void
112*fb1b10abSAndroid Build Coastguard Worker *
113*fb1b10abSAndroid Build Coastguard Worker * FUNCTION : Performs 2-to-1 point subsampled scaling.
114*fb1b10abSAndroid Build Coastguard Worker *
115*fb1b10abSAndroid Build Coastguard Worker * SPECIAL NOTES : None.
116*fb1b10abSAndroid Build Coastguard Worker *
117*fb1b10abSAndroid Build Coastguard Worker ****************************************************************************/
scale1d_2t1_ps(const unsigned char * source,int source_step,unsigned int source_scale,unsigned int source_length,unsigned char * dest,int dest_step,unsigned int dest_scale,unsigned int dest_length)118*fb1b10abSAndroid Build Coastguard Worker static void scale1d_2t1_ps(const unsigned char *source, int source_step,
119*fb1b10abSAndroid Build Coastguard Worker unsigned int source_scale,
120*fb1b10abSAndroid Build Coastguard Worker unsigned int source_length, unsigned char *dest,
121*fb1b10abSAndroid Build Coastguard Worker int dest_step, unsigned int dest_scale,
122*fb1b10abSAndroid Build Coastguard Worker unsigned int dest_length) {
123*fb1b10abSAndroid Build Coastguard Worker unsigned int i, j;
124*fb1b10abSAndroid Build Coastguard Worker
125*fb1b10abSAndroid Build Coastguard Worker (void)source_length;
126*fb1b10abSAndroid Build Coastguard Worker (void)source_scale;
127*fb1b10abSAndroid Build Coastguard Worker (void)dest_scale;
128*fb1b10abSAndroid Build Coastguard Worker
129*fb1b10abSAndroid Build Coastguard Worker source_step *= 2;
130*fb1b10abSAndroid Build Coastguard Worker j = 0;
131*fb1b10abSAndroid Build Coastguard Worker
132*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
133*fb1b10abSAndroid Build Coastguard Worker dest[i] = source[j];
134*fb1b10abSAndroid Build Coastguard Worker }
135*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
136*fb1b10abSAndroid Build Coastguard Worker *
137*fb1b10abSAndroid Build Coastguard Worker * ROUTINE : scale1d_c
138*fb1b10abSAndroid Build Coastguard Worker *
139*fb1b10abSAndroid Build Coastguard Worker * INPUTS : const unsigned char *source : Pointer to data to be scaled.
140*fb1b10abSAndroid Build Coastguard Worker * int source_step : Number of pixels to step on in
141*fb1b10abSAndroid Build Coastguard Worker * source.
142*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_scale : Scale for source.
143*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_length : Length of source (UNUSED).
144*fb1b10abSAndroid Build Coastguard Worker * unsigned char *dest : Pointer to output data array.
145*fb1b10abSAndroid Build Coastguard Worker * int dest_step : Number of pixels to step on in
146*fb1b10abSAndroid Build Coastguard Worker * destination.
147*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_scale : Scale for destination.
148*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_length : Length of destination.
149*fb1b10abSAndroid Build Coastguard Worker *
150*fb1b10abSAndroid Build Coastguard Worker * OUTPUTS : None.
151*fb1b10abSAndroid Build Coastguard Worker *
152*fb1b10abSAndroid Build Coastguard Worker * RETURNS : void
153*fb1b10abSAndroid Build Coastguard Worker *
154*fb1b10abSAndroid Build Coastguard Worker * FUNCTION : Performs linear interpolation in one dimension.
155*fb1b10abSAndroid Build Coastguard Worker *
156*fb1b10abSAndroid Build Coastguard Worker * SPECIAL NOTES : None.
157*fb1b10abSAndroid Build Coastguard Worker *
158*fb1b10abSAndroid Build Coastguard Worker ****************************************************************************/
scale1d_c(const unsigned char * source,int source_step,unsigned int source_scale,unsigned int source_length,unsigned char * dest,int dest_step,unsigned int dest_scale,unsigned int dest_length)159*fb1b10abSAndroid Build Coastguard Worker static void scale1d_c(const unsigned char *source, int source_step,
160*fb1b10abSAndroid Build Coastguard Worker unsigned int source_scale, unsigned int source_length,
161*fb1b10abSAndroid Build Coastguard Worker unsigned char *dest, int dest_step,
162*fb1b10abSAndroid Build Coastguard Worker unsigned int dest_scale, unsigned int dest_length) {
163*fb1b10abSAndroid Build Coastguard Worker unsigned int i;
164*fb1b10abSAndroid Build Coastguard Worker unsigned int round_value = dest_scale / 2;
165*fb1b10abSAndroid Build Coastguard Worker unsigned int left_modifier = dest_scale;
166*fb1b10abSAndroid Build Coastguard Worker unsigned int right_modifier = 0;
167*fb1b10abSAndroid Build Coastguard Worker unsigned char left_pixel = *source;
168*fb1b10abSAndroid Build Coastguard Worker unsigned char right_pixel = *(source + source_step);
169*fb1b10abSAndroid Build Coastguard Worker
170*fb1b10abSAndroid Build Coastguard Worker (void)source_length;
171*fb1b10abSAndroid Build Coastguard Worker
172*fb1b10abSAndroid Build Coastguard Worker /* These asserts are needed if there are boundary issues... */
173*fb1b10abSAndroid Build Coastguard Worker /*assert ( dest_scale > source_scale );*/
174*fb1b10abSAndroid Build Coastguard Worker /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale
175*fb1b10abSAndroid Build Coastguard Worker * );*/
176*fb1b10abSAndroid Build Coastguard Worker
177*fb1b10abSAndroid Build Coastguard Worker assert(dest_scale != 0);
178*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < dest_length * dest_step; i += dest_step) {
179*fb1b10abSAndroid Build Coastguard Worker dest[i] = (char)((left_modifier * left_pixel +
180*fb1b10abSAndroid Build Coastguard Worker right_modifier * right_pixel + round_value) /
181*fb1b10abSAndroid Build Coastguard Worker dest_scale);
182*fb1b10abSAndroid Build Coastguard Worker
183*fb1b10abSAndroid Build Coastguard Worker right_modifier += source_scale;
184*fb1b10abSAndroid Build Coastguard Worker
185*fb1b10abSAndroid Build Coastguard Worker while (right_modifier > dest_scale) {
186*fb1b10abSAndroid Build Coastguard Worker right_modifier -= dest_scale;
187*fb1b10abSAndroid Build Coastguard Worker source += source_step;
188*fb1b10abSAndroid Build Coastguard Worker left_pixel = *source;
189*fb1b10abSAndroid Build Coastguard Worker right_pixel = *(source + source_step);
190*fb1b10abSAndroid Build Coastguard Worker }
191*fb1b10abSAndroid Build Coastguard Worker
192*fb1b10abSAndroid Build Coastguard Worker left_modifier = dest_scale - right_modifier;
193*fb1b10abSAndroid Build Coastguard Worker }
194*fb1b10abSAndroid Build Coastguard Worker }
195*fb1b10abSAndroid Build Coastguard Worker
196*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
197*fb1b10abSAndroid Build Coastguard Worker *
198*fb1b10abSAndroid Build Coastguard Worker * ROUTINE : Scale2D
199*fb1b10abSAndroid Build Coastguard Worker *
200*fb1b10abSAndroid Build Coastguard Worker * INPUTS : const unsigned char *source : Pointer to data to be
201*fb1b10abSAndroid Build Coastguard Worker * scaled.
202*fb1b10abSAndroid Build Coastguard Worker * int source_pitch : Stride of source image.
203*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_width : Width of input image.
204*fb1b10abSAndroid Build Coastguard Worker * unsigned int source_height : Height of input image.
205*fb1b10abSAndroid Build Coastguard Worker * unsigned char *dest : Pointer to output data
206*fb1b10abSAndroid Build Coastguard Worker * array.
207*fb1b10abSAndroid Build Coastguard Worker * int dest_pitch : Stride of destination
208*fb1b10abSAndroid Build Coastguard Worker * image.
209*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_width : Width of destination image.
210*fb1b10abSAndroid Build Coastguard Worker * unsigned int dest_height : Height of destination
211*fb1b10abSAndroid Build Coastguard Worker * image.
212*fb1b10abSAndroid Build Coastguard Worker * unsigned char *temp_area : Pointer to temp work area.
213*fb1b10abSAndroid Build Coastguard Worker * unsigned char temp_area_height : Height of temp work area.
214*fb1b10abSAndroid Build Coastguard Worker * unsigned int hscale : Horizontal scale factor
215*fb1b10abSAndroid Build Coastguard Worker * numerator.
216*fb1b10abSAndroid Build Coastguard Worker * unsigned int hratio : Horizontal scale factor
217*fb1b10abSAndroid Build Coastguard Worker * denominator.
218*fb1b10abSAndroid Build Coastguard Worker * unsigned int vscale : Vertical scale factor
219*fb1b10abSAndroid Build Coastguard Worker * numerator.
220*fb1b10abSAndroid Build Coastguard Worker * unsigned int vratio : Vertical scale factor
221*fb1b10abSAndroid Build Coastguard Worker * denominator.
222*fb1b10abSAndroid Build Coastguard Worker * unsigned int interlaced : Interlace flag.
223*fb1b10abSAndroid Build Coastguard Worker *
224*fb1b10abSAndroid Build Coastguard Worker * OUTPUTS : None.
225*fb1b10abSAndroid Build Coastguard Worker *
226*fb1b10abSAndroid Build Coastguard Worker * RETURNS : void
227*fb1b10abSAndroid Build Coastguard Worker *
228*fb1b10abSAndroid Build Coastguard Worker * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
229*fb1b10abSAndroid Build Coastguard Worker *
230*fb1b10abSAndroid Build Coastguard Worker * SPECIAL NOTES : Expansion is performed one band at a time to help with
231*fb1b10abSAndroid Build Coastguard Worker * caching.
232*fb1b10abSAndroid Build Coastguard Worker *
233*fb1b10abSAndroid Build Coastguard Worker ****************************************************************************/
Scale2D(unsigned char * source,int source_pitch,unsigned int source_width,unsigned int source_height,unsigned char * dest,int dest_pitch,unsigned int dest_width,unsigned int dest_height,unsigned char * temp_area,unsigned char temp_area_height,unsigned int hscale,unsigned int hratio,unsigned int vscale,unsigned int vratio,unsigned int interlaced)234*fb1b10abSAndroid Build Coastguard Worker static void Scale2D(
235*fb1b10abSAndroid Build Coastguard Worker /*const*/
236*fb1b10abSAndroid Build Coastguard Worker unsigned char *source, int source_pitch, unsigned int source_width,
237*fb1b10abSAndroid Build Coastguard Worker unsigned int source_height, unsigned char *dest, int dest_pitch,
238*fb1b10abSAndroid Build Coastguard Worker unsigned int dest_width, unsigned int dest_height, unsigned char *temp_area,
239*fb1b10abSAndroid Build Coastguard Worker unsigned char temp_area_height, unsigned int hscale, unsigned int hratio,
240*fb1b10abSAndroid Build Coastguard Worker unsigned int vscale, unsigned int vratio, unsigned int interlaced) {
241*fb1b10abSAndroid Build Coastguard Worker /*unsigned*/
242*fb1b10abSAndroid Build Coastguard Worker int i, j, k;
243*fb1b10abSAndroid Build Coastguard Worker int bands;
244*fb1b10abSAndroid Build Coastguard Worker int dest_band_height;
245*fb1b10abSAndroid Build Coastguard Worker int source_band_height;
246*fb1b10abSAndroid Build Coastguard Worker
247*fb1b10abSAndroid Build Coastguard Worker typedef void (*Scale1D)(const unsigned char *source, int source_step,
248*fb1b10abSAndroid Build Coastguard Worker unsigned int source_scale, unsigned int source_length,
249*fb1b10abSAndroid Build Coastguard Worker unsigned char *dest, int dest_step,
250*fb1b10abSAndroid Build Coastguard Worker unsigned int dest_scale, unsigned int dest_length);
251*fb1b10abSAndroid Build Coastguard Worker
252*fb1b10abSAndroid Build Coastguard Worker Scale1D Scale1Dv = scale1d_c;
253*fb1b10abSAndroid Build Coastguard Worker Scale1D Scale1Dh = scale1d_c;
254*fb1b10abSAndroid Build Coastguard Worker
255*fb1b10abSAndroid Build Coastguard Worker void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *,
256*fb1b10abSAndroid Build Coastguard Worker unsigned int) = NULL;
257*fb1b10abSAndroid Build Coastguard Worker void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *,
258*fb1b10abSAndroid Build Coastguard Worker unsigned int, unsigned int) = NULL;
259*fb1b10abSAndroid Build Coastguard Worker
260*fb1b10abSAndroid Build Coastguard Worker int ratio_scalable = 1;
261*fb1b10abSAndroid Build Coastguard Worker int interpolation = 0;
262*fb1b10abSAndroid Build Coastguard Worker
263*fb1b10abSAndroid Build Coastguard Worker unsigned char *source_base;
264*fb1b10abSAndroid Build Coastguard Worker unsigned char *line_src;
265*fb1b10abSAndroid Build Coastguard Worker
266*fb1b10abSAndroid Build Coastguard Worker source_base = (unsigned char *)source;
267*fb1b10abSAndroid Build Coastguard Worker
268*fb1b10abSAndroid Build Coastguard Worker if (source_pitch < 0) {
269*fb1b10abSAndroid Build Coastguard Worker int offset;
270*fb1b10abSAndroid Build Coastguard Worker
271*fb1b10abSAndroid Build Coastguard Worker offset = (source_height - 1);
272*fb1b10abSAndroid Build Coastguard Worker offset *= source_pitch;
273*fb1b10abSAndroid Build Coastguard Worker
274*fb1b10abSAndroid Build Coastguard Worker source_base += offset;
275*fb1b10abSAndroid Build Coastguard Worker }
276*fb1b10abSAndroid Build Coastguard Worker
277*fb1b10abSAndroid Build Coastguard Worker /* find out the ratio for each direction */
278*fb1b10abSAndroid Build Coastguard Worker switch (hratio * 10 / hscale) {
279*fb1b10abSAndroid Build Coastguard Worker case 8:
280*fb1b10abSAndroid Build Coastguard Worker /* 4-5 Scale in Width direction */
281*fb1b10abSAndroid Build Coastguard Worker horiz_line_scale = vp8_horizontal_line_5_4_scale;
282*fb1b10abSAndroid Build Coastguard Worker break;
283*fb1b10abSAndroid Build Coastguard Worker case 6:
284*fb1b10abSAndroid Build Coastguard Worker /* 3-5 Scale in Width direction */
285*fb1b10abSAndroid Build Coastguard Worker horiz_line_scale = vp8_horizontal_line_5_3_scale;
286*fb1b10abSAndroid Build Coastguard Worker break;
287*fb1b10abSAndroid Build Coastguard Worker case 5:
288*fb1b10abSAndroid Build Coastguard Worker /* 1-2 Scale in Width direction */
289*fb1b10abSAndroid Build Coastguard Worker horiz_line_scale = vp8_horizontal_line_2_1_scale;
290*fb1b10abSAndroid Build Coastguard Worker break;
291*fb1b10abSAndroid Build Coastguard Worker default:
292*fb1b10abSAndroid Build Coastguard Worker /* The ratio is not acceptable now */
293*fb1b10abSAndroid Build Coastguard Worker /* throw("The ratio is not acceptable for now!"); */
294*fb1b10abSAndroid Build Coastguard Worker ratio_scalable = 0;
295*fb1b10abSAndroid Build Coastguard Worker break;
296*fb1b10abSAndroid Build Coastguard Worker }
297*fb1b10abSAndroid Build Coastguard Worker
298*fb1b10abSAndroid Build Coastguard Worker switch (vratio * 10 / vscale) {
299*fb1b10abSAndroid Build Coastguard Worker case 8:
300*fb1b10abSAndroid Build Coastguard Worker /* 4-5 Scale in vertical direction */
301*fb1b10abSAndroid Build Coastguard Worker vert_band_scale = vp8_vertical_band_5_4_scale;
302*fb1b10abSAndroid Build Coastguard Worker source_band_height = 5;
303*fb1b10abSAndroid Build Coastguard Worker dest_band_height = 4;
304*fb1b10abSAndroid Build Coastguard Worker break;
305*fb1b10abSAndroid Build Coastguard Worker case 6:
306*fb1b10abSAndroid Build Coastguard Worker /* 3-5 Scale in vertical direction */
307*fb1b10abSAndroid Build Coastguard Worker vert_band_scale = vp8_vertical_band_5_3_scale;
308*fb1b10abSAndroid Build Coastguard Worker source_band_height = 5;
309*fb1b10abSAndroid Build Coastguard Worker dest_band_height = 3;
310*fb1b10abSAndroid Build Coastguard Worker break;
311*fb1b10abSAndroid Build Coastguard Worker case 5:
312*fb1b10abSAndroid Build Coastguard Worker /* 1-2 Scale in vertical direction */
313*fb1b10abSAndroid Build Coastguard Worker
314*fb1b10abSAndroid Build Coastguard Worker if (interlaced) {
315*fb1b10abSAndroid Build Coastguard Worker /* if the content is interlaced, point sampling is used */
316*fb1b10abSAndroid Build Coastguard Worker vert_band_scale = vp8_vertical_band_2_1_scale;
317*fb1b10abSAndroid Build Coastguard Worker } else {
318*fb1b10abSAndroid Build Coastguard Worker interpolation = 1;
319*fb1b10abSAndroid Build Coastguard Worker /* if the content is progressive, interplo */
320*fb1b10abSAndroid Build Coastguard Worker vert_band_scale = vp8_vertical_band_2_1_scale_i;
321*fb1b10abSAndroid Build Coastguard Worker }
322*fb1b10abSAndroid Build Coastguard Worker
323*fb1b10abSAndroid Build Coastguard Worker source_band_height = 2;
324*fb1b10abSAndroid Build Coastguard Worker dest_band_height = 1;
325*fb1b10abSAndroid Build Coastguard Worker break;
326*fb1b10abSAndroid Build Coastguard Worker default:
327*fb1b10abSAndroid Build Coastguard Worker /* The ratio is not acceptable now */
328*fb1b10abSAndroid Build Coastguard Worker /* throw("The ratio is not acceptable for now!"); */
329*fb1b10abSAndroid Build Coastguard Worker ratio_scalable = 0;
330*fb1b10abSAndroid Build Coastguard Worker break;
331*fb1b10abSAndroid Build Coastguard Worker }
332*fb1b10abSAndroid Build Coastguard Worker
333*fb1b10abSAndroid Build Coastguard Worker if (ratio_scalable) {
334*fb1b10abSAndroid Build Coastguard Worker if (source_height == dest_height) {
335*fb1b10abSAndroid Build Coastguard Worker /* for each band of the image */
336*fb1b10abSAndroid Build Coastguard Worker for (k = 0; k < (int)dest_height; k++) {
337*fb1b10abSAndroid Build Coastguard Worker horiz_line_scale(source, source_width, dest, dest_width);
338*fb1b10abSAndroid Build Coastguard Worker source += source_pitch;
339*fb1b10abSAndroid Build Coastguard Worker dest += dest_pitch;
340*fb1b10abSAndroid Build Coastguard Worker }
341*fb1b10abSAndroid Build Coastguard Worker
342*fb1b10abSAndroid Build Coastguard Worker return;
343*fb1b10abSAndroid Build Coastguard Worker }
344*fb1b10abSAndroid Build Coastguard Worker
345*fb1b10abSAndroid Build Coastguard Worker if (interpolation) {
346*fb1b10abSAndroid Build Coastguard Worker if (source < source_base) source = source_base;
347*fb1b10abSAndroid Build Coastguard Worker
348*fb1b10abSAndroid Build Coastguard Worker horiz_line_scale(source, source_width, temp_area, dest_width);
349*fb1b10abSAndroid Build Coastguard Worker }
350*fb1b10abSAndroid Build Coastguard Worker
351*fb1b10abSAndroid Build Coastguard Worker for (k = 0;
352*fb1b10abSAndroid Build Coastguard Worker k < (int)(dest_height + dest_band_height - 1) / dest_band_height;
353*fb1b10abSAndroid Build Coastguard Worker k++) {
354*fb1b10abSAndroid Build Coastguard Worker /* scale one band horizontally */
355*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < source_band_height; i++) {
356*fb1b10abSAndroid Build Coastguard Worker /* Trap case where we could read off the base of the source buffer */
357*fb1b10abSAndroid Build Coastguard Worker
358*fb1b10abSAndroid Build Coastguard Worker line_src = (unsigned char *)source + i * source_pitch;
359*fb1b10abSAndroid Build Coastguard Worker
360*fb1b10abSAndroid Build Coastguard Worker if (line_src < source_base) line_src = source_base;
361*fb1b10abSAndroid Build Coastguard Worker
362*fb1b10abSAndroid Build Coastguard Worker horiz_line_scale(line_src, source_width,
363*fb1b10abSAndroid Build Coastguard Worker temp_area + (i + 1) * dest_pitch, dest_width);
364*fb1b10abSAndroid Build Coastguard Worker }
365*fb1b10abSAndroid Build Coastguard Worker
366*fb1b10abSAndroid Build Coastguard Worker /* Vertical scaling is in place */
367*fb1b10abSAndroid Build Coastguard Worker vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch,
368*fb1b10abSAndroid Build Coastguard Worker dest_width);
369*fb1b10abSAndroid Build Coastguard Worker
370*fb1b10abSAndroid Build Coastguard Worker if (interpolation)
371*fb1b10abSAndroid Build Coastguard Worker memcpy(temp_area, temp_area + source_band_height * dest_pitch,
372*fb1b10abSAndroid Build Coastguard Worker dest_width);
373*fb1b10abSAndroid Build Coastguard Worker
374*fb1b10abSAndroid Build Coastguard Worker /* Next band... */
375*fb1b10abSAndroid Build Coastguard Worker source += (unsigned long)source_band_height * source_pitch;
376*fb1b10abSAndroid Build Coastguard Worker dest += (unsigned long)dest_band_height * dest_pitch;
377*fb1b10abSAndroid Build Coastguard Worker }
378*fb1b10abSAndroid Build Coastguard Worker
379*fb1b10abSAndroid Build Coastguard Worker return;
380*fb1b10abSAndroid Build Coastguard Worker }
381*fb1b10abSAndroid Build Coastguard Worker
382*fb1b10abSAndroid Build Coastguard Worker if (hscale == 2 && hratio == 1) Scale1Dh = scale1d_2t1_ps;
383*fb1b10abSAndroid Build Coastguard Worker
384*fb1b10abSAndroid Build Coastguard Worker if (vscale == 2 && vratio == 1) {
385*fb1b10abSAndroid Build Coastguard Worker if (interlaced)
386*fb1b10abSAndroid Build Coastguard Worker Scale1Dv = scale1d_2t1_ps;
387*fb1b10abSAndroid Build Coastguard Worker else
388*fb1b10abSAndroid Build Coastguard Worker Scale1Dv = scale1d_2t1_i;
389*fb1b10abSAndroid Build Coastguard Worker }
390*fb1b10abSAndroid Build Coastguard Worker
391*fb1b10abSAndroid Build Coastguard Worker if (source_height == dest_height) {
392*fb1b10abSAndroid Build Coastguard Worker /* for each band of the image */
393*fb1b10abSAndroid Build Coastguard Worker for (k = 0; k < (int)dest_height; k++) {
394*fb1b10abSAndroid Build Coastguard Worker Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio,
395*fb1b10abSAndroid Build Coastguard Worker dest_width);
396*fb1b10abSAndroid Build Coastguard Worker source += source_pitch;
397*fb1b10abSAndroid Build Coastguard Worker dest += dest_pitch;
398*fb1b10abSAndroid Build Coastguard Worker }
399*fb1b10abSAndroid Build Coastguard Worker
400*fb1b10abSAndroid Build Coastguard Worker return;
401*fb1b10abSAndroid Build Coastguard Worker }
402*fb1b10abSAndroid Build Coastguard Worker
403*fb1b10abSAndroid Build Coastguard Worker if (dest_height > source_height) {
404*fb1b10abSAndroid Build Coastguard Worker dest_band_height = temp_area_height - 1;
405*fb1b10abSAndroid Build Coastguard Worker source_band_height = dest_band_height * source_height / dest_height;
406*fb1b10abSAndroid Build Coastguard Worker } else {
407*fb1b10abSAndroid Build Coastguard Worker source_band_height = temp_area_height - 1;
408*fb1b10abSAndroid Build Coastguard Worker dest_band_height = source_band_height * vratio / vscale;
409*fb1b10abSAndroid Build Coastguard Worker }
410*fb1b10abSAndroid Build Coastguard Worker
411*fb1b10abSAndroid Build Coastguard Worker /* first row needs to be done so that we can stay one row ahead for vertical
412*fb1b10abSAndroid Build Coastguard Worker * zoom */
413*fb1b10abSAndroid Build Coastguard Worker Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio,
414*fb1b10abSAndroid Build Coastguard Worker dest_width);
415*fb1b10abSAndroid Build Coastguard Worker
416*fb1b10abSAndroid Build Coastguard Worker /* for each band of the image */
417*fb1b10abSAndroid Build Coastguard Worker bands = (dest_height + dest_band_height - 1) / dest_band_height;
418*fb1b10abSAndroid Build Coastguard Worker
419*fb1b10abSAndroid Build Coastguard Worker for (k = 0; k < bands; k++) {
420*fb1b10abSAndroid Build Coastguard Worker /* scale one band horizontally */
421*fb1b10abSAndroid Build Coastguard Worker for (i = 1; i < source_band_height + 1; i++) {
422*fb1b10abSAndroid Build Coastguard Worker if (k * source_band_height + i < (int)source_height) {
423*fb1b10abSAndroid Build Coastguard Worker Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
424*fb1b10abSAndroid Build Coastguard Worker temp_area + i * dest_pitch, 1, hratio, dest_width);
425*fb1b10abSAndroid Build Coastguard Worker } else { /* Duplicate the last row */
426*fb1b10abSAndroid Build Coastguard Worker /* copy temp_area row 0 over from last row in the past */
427*fb1b10abSAndroid Build Coastguard Worker memcpy(temp_area + i * dest_pitch, temp_area + (i - 1) * dest_pitch,
428*fb1b10abSAndroid Build Coastguard Worker dest_pitch);
429*fb1b10abSAndroid Build Coastguard Worker }
430*fb1b10abSAndroid Build Coastguard Worker }
431*fb1b10abSAndroid Build Coastguard Worker
432*fb1b10abSAndroid Build Coastguard Worker /* scale one band vertically */
433*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < (int)dest_width; j++) {
434*fb1b10abSAndroid Build Coastguard Worker Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
435*fb1b10abSAndroid Build Coastguard Worker &dest[j], dest_pitch, vratio, dest_band_height);
436*fb1b10abSAndroid Build Coastguard Worker }
437*fb1b10abSAndroid Build Coastguard Worker
438*fb1b10abSAndroid Build Coastguard Worker /* copy temp_area row 0 over from last row in the past */
439*fb1b10abSAndroid Build Coastguard Worker memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
440*fb1b10abSAndroid Build Coastguard Worker
441*fb1b10abSAndroid Build Coastguard Worker /* move to the next band */
442*fb1b10abSAndroid Build Coastguard Worker source += source_band_height * source_pitch;
443*fb1b10abSAndroid Build Coastguard Worker dest += dest_band_height * dest_pitch;
444*fb1b10abSAndroid Build Coastguard Worker }
445*fb1b10abSAndroid Build Coastguard Worker }
446*fb1b10abSAndroid Build Coastguard Worker
447*fb1b10abSAndroid Build Coastguard Worker /****************************************************************************
448*fb1b10abSAndroid Build Coastguard Worker *
449*fb1b10abSAndroid Build Coastguard Worker * ROUTINE : vpx_scale_frame
450*fb1b10abSAndroid Build Coastguard Worker *
451*fb1b10abSAndroid Build Coastguard Worker * INPUTS : YV12_BUFFER_CONFIG *src : Pointer to frame to be
452*fb1b10abSAndroid Build Coastguard Worker * scaled.
453*fb1b10abSAndroid Build Coastguard Worker * YV12_BUFFER_CONFIG *dst : Pointer to buffer to hold
454*fb1b10abSAndroid Build Coastguard Worker * scaled frame.
455*fb1b10abSAndroid Build Coastguard Worker * unsigned char *temp_area : Pointer to temp work area.
456*fb1b10abSAndroid Build Coastguard Worker * unsigned char temp_area_height : Height of temp work area.
457*fb1b10abSAndroid Build Coastguard Worker * unsigned int hscale : Horizontal scale factor
458*fb1b10abSAndroid Build Coastguard Worker * numerator.
459*fb1b10abSAndroid Build Coastguard Worker * unsigned int hratio : Horizontal scale factor
460*fb1b10abSAndroid Build Coastguard Worker * denominator.
461*fb1b10abSAndroid Build Coastguard Worker * unsigned int vscale : Vertical scale factor
462*fb1b10abSAndroid Build Coastguard Worker * numerator.
463*fb1b10abSAndroid Build Coastguard Worker * unsigned int vratio : Vertical scale factor
464*fb1b10abSAndroid Build Coastguard Worker * denominator.
465*fb1b10abSAndroid Build Coastguard Worker * unsigned int interlaced : Interlace flag.
466*fb1b10abSAndroid Build Coastguard Worker *
467*fb1b10abSAndroid Build Coastguard Worker * OUTPUTS : None.
468*fb1b10abSAndroid Build Coastguard Worker *
469*fb1b10abSAndroid Build Coastguard Worker * RETURNS : void
470*fb1b10abSAndroid Build Coastguard Worker *
471*fb1b10abSAndroid Build Coastguard Worker * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
472*fb1b10abSAndroid Build Coastguard Worker *
473*fb1b10abSAndroid Build Coastguard Worker * SPECIAL NOTES : Expansion is performed one band at a time to help with
474*fb1b10abSAndroid Build Coastguard Worker * caching.
475*fb1b10abSAndroid Build Coastguard Worker *
476*fb1b10abSAndroid Build Coastguard Worker ****************************************************************************/
vpx_scale_frame(YV12_BUFFER_CONFIG * src,YV12_BUFFER_CONFIG * dst,unsigned char * temp_area,unsigned char temp_height,unsigned int hscale,unsigned int hratio,unsigned int vscale,unsigned int vratio,unsigned int interlaced)477*fb1b10abSAndroid Build Coastguard Worker void vpx_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
478*fb1b10abSAndroid Build Coastguard Worker unsigned char *temp_area, unsigned char temp_height,
479*fb1b10abSAndroid Build Coastguard Worker unsigned int hscale, unsigned int hratio,
480*fb1b10abSAndroid Build Coastguard Worker unsigned int vscale, unsigned int vratio,
481*fb1b10abSAndroid Build Coastguard Worker unsigned int interlaced) {
482*fb1b10abSAndroid Build Coastguard Worker int i;
483*fb1b10abSAndroid Build Coastguard Worker int dw = (hscale - 1 + src->y_width * hratio) / hscale;
484*fb1b10abSAndroid Build Coastguard Worker int dh = (vscale - 1 + src->y_height * vratio) / vscale;
485*fb1b10abSAndroid Build Coastguard Worker
486*fb1b10abSAndroid Build Coastguard Worker /* call our internal scaling routines!! */
487*fb1b10abSAndroid Build Coastguard Worker Scale2D((unsigned char *)src->y_buffer, src->y_stride, src->y_width,
488*fb1b10abSAndroid Build Coastguard Worker src->y_height, (unsigned char *)dst->y_buffer, dst->y_stride, dw, dh,
489*fb1b10abSAndroid Build Coastguard Worker temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
490*fb1b10abSAndroid Build Coastguard Worker
491*fb1b10abSAndroid Build Coastguard Worker if (dw < (int)dst->y_width)
492*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < dh; i++)
493*fb1b10abSAndroid Build Coastguard Worker memset(dst->y_buffer + i * dst->y_stride + dw - 1,
494*fb1b10abSAndroid Build Coastguard Worker dst->y_buffer[i * dst->y_stride + dw - 2], dst->y_width - dw + 1);
495*fb1b10abSAndroid Build Coastguard Worker
496*fb1b10abSAndroid Build Coastguard Worker if (dh < (int)dst->y_height)
497*fb1b10abSAndroid Build Coastguard Worker for (i = dh - 1; i < (int)dst->y_height; i++)
498*fb1b10abSAndroid Build Coastguard Worker memcpy(dst->y_buffer + i * dst->y_stride,
499*fb1b10abSAndroid Build Coastguard Worker dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
500*fb1b10abSAndroid Build Coastguard Worker
501*fb1b10abSAndroid Build Coastguard Worker Scale2D((unsigned char *)src->u_buffer, src->uv_stride, src->uv_width,
502*fb1b10abSAndroid Build Coastguard Worker src->uv_height, (unsigned char *)dst->u_buffer, dst->uv_stride,
503*fb1b10abSAndroid Build Coastguard Worker dw / 2, dh / 2, temp_area, temp_height, hscale, hratio, vscale,
504*fb1b10abSAndroid Build Coastguard Worker vratio, interlaced);
505*fb1b10abSAndroid Build Coastguard Worker
506*fb1b10abSAndroid Build Coastguard Worker if (dw / 2 < (int)dst->uv_width)
507*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < dst->uv_height; i++)
508*fb1b10abSAndroid Build Coastguard Worker memset(dst->u_buffer + i * dst->uv_stride + dw / 2 - 1,
509*fb1b10abSAndroid Build Coastguard Worker dst->u_buffer[i * dst->uv_stride + dw / 2 - 2],
510*fb1b10abSAndroid Build Coastguard Worker dst->uv_width - dw / 2 + 1);
511*fb1b10abSAndroid Build Coastguard Worker
512*fb1b10abSAndroid Build Coastguard Worker if (dh / 2 < (int)dst->uv_height)
513*fb1b10abSAndroid Build Coastguard Worker for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
514*fb1b10abSAndroid Build Coastguard Worker memcpy(dst->u_buffer + i * dst->uv_stride,
515*fb1b10abSAndroid Build Coastguard Worker dst->u_buffer + (dh / 2 - 2) * dst->uv_stride, dst->uv_width);
516*fb1b10abSAndroid Build Coastguard Worker
517*fb1b10abSAndroid Build Coastguard Worker Scale2D((unsigned char *)src->v_buffer, src->uv_stride, src->uv_width,
518*fb1b10abSAndroid Build Coastguard Worker src->uv_height, (unsigned char *)dst->v_buffer, dst->uv_stride,
519*fb1b10abSAndroid Build Coastguard Worker dw / 2, dh / 2, temp_area, temp_height, hscale, hratio, vscale,
520*fb1b10abSAndroid Build Coastguard Worker vratio, interlaced);
521*fb1b10abSAndroid Build Coastguard Worker
522*fb1b10abSAndroid Build Coastguard Worker if (dw / 2 < (int)dst->uv_width)
523*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < dst->uv_height; i++)
524*fb1b10abSAndroid Build Coastguard Worker memset(dst->v_buffer + i * dst->uv_stride + dw / 2 - 1,
525*fb1b10abSAndroid Build Coastguard Worker dst->v_buffer[i * dst->uv_stride + dw / 2 - 2],
526*fb1b10abSAndroid Build Coastguard Worker dst->uv_width - dw / 2 + 1);
527*fb1b10abSAndroid Build Coastguard Worker
528*fb1b10abSAndroid Build Coastguard Worker if (dh / 2 < (int)dst->uv_height)
529*fb1b10abSAndroid Build Coastguard Worker for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
530*fb1b10abSAndroid Build Coastguard Worker memcpy(dst->v_buffer + i * dst->uv_stride,
531*fb1b10abSAndroid Build Coastguard Worker dst->v_buffer + (dh / 2 - 2) * dst->uv_stride, dst->uv_width);
532*fb1b10abSAndroid Build Coastguard Worker }
533