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