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