• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 
12 /****************************************************************************
13  *
14  *   Module Title :     scale.c
15  *
16  *   Description  :     Image scaling functions.
17  *
18  ***************************************************************************/
19 
20 /****************************************************************************
21 *  Header Files
22 ****************************************************************************/
23 #include "vpx_mem/vpx_mem.h"
24 #include "vpx_scale/yv12config.h"
25 #include "vpx_scale/scale_mode.h"
26 
27 /****************************************************************************
28 *  Exports
29 ****************************************************************************/
30 #ifndef VPX_NO_GLOBALS
31 void (*vp8_vertical_band_4_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
32 void (*vp8_last_vertical_band_4_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
33 void (*vp8_vertical_band_2_3_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
34 void (*vp8_last_vertical_band_2_3_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
35 void (*vp8_vertical_band_3_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
36 void (*vp8_last_vertical_band_3_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
37 void (*vp8_vertical_band_3_4_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
38 void (*vp8_last_vertical_band_3_4_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
39 void (*vp8_horizontal_line_1_2_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
40 void (*vp8_horizontal_line_3_5_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
41 void (*vp8_horizontal_line_3_4_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
42 void (*vp8_horizontal_line_2_3_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
43 void (*vp8_horizontal_line_4_5_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
44 void (*vp8_vertical_band_1_2_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
45 void (*vp8_last_vertical_band_1_2_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
46 
47 void (*vp8_vertical_band_5_4_scale)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
48 void (*vp8_vertical_band_5_3_scale)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
49 void (*vp8_vertical_band_2_1_scale)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
50 void (*vp8_vertical_band_2_1_scale_i)(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width) = 0;
51 void (*vp8_horizontal_line_2_1_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
52 void (*vp8_horizontal_line_5_3_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
53 void (*vp8_horizontal_line_5_4_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width) = 0;
54 #else
55 # include "vpxscale_nofp.h"
56 #endif
57 
58 typedef struct
59 {
60     int     expanded_frame_width;
61     int     expanded_frame_height;
62 
63     int HScale;
64     int HRatio;
65     int VScale;
66     int VRatio;
67 
68     YV12_BUFFER_CONFIG *src_yuv_config;
69     YV12_BUFFER_CONFIG *dst_yuv_config;
70 
71 } SCALE_VARS;
72 
73 /****************************************************************************
74  *
75  *  ROUTINE       :     horizontal_line_copy
76  *
77  *  INPUTS        :     None
78  *
79  *
80  *  OUTPUTS       :     None.
81  *
82  *  RETURNS       :     None
83  *
84  *  FUNCTION      :     1 to 1 scaling up for a horizontal line of pixles
85  *
86  *  SPECIAL NOTES :     None.
87  *
88  *  ERRORS        :     None.
89  *
90  ****************************************************************************/
91 static
horizontal_line_copy(const unsigned char * source,unsigned int source_width,unsigned char * dest,unsigned int dest_width)92 void horizontal_line_copy(
93     const unsigned char *source,
94     unsigned int source_width,
95     unsigned char *dest,
96     unsigned int dest_width
97 )
98 {
99     (void) dest_width;
100 
101     duck_memcpy(dest, source, source_width);
102 }
103 /****************************************************************************
104  *
105  *  ROUTINE       :     null_scale
106  *
107  *  INPUTS        :     None
108  *
109  *
110  *  OUTPUTS       :     None.
111  *
112  *  RETURNS       :     None
113  *
114  *  FUNCTION      :     1 to 1 scaling up for a vertical band
115  *
116  *  SPECIAL NOTES :     None.
117  *
118  *  ERRORS        :     None.
119  *
120  ****************************************************************************/
121 static
null_scale(unsigned char * dest,unsigned int dest_pitch,unsigned int dest_width)122 void null_scale(
123     unsigned char *dest,
124     unsigned int dest_pitch,
125     unsigned int dest_width
126 )
127 {
128     (void) dest;
129     (void) dest_pitch;
130     (void) dest_width;
131 
132     return;
133 }
134 
135 /****************************************************************************
136  *
137  *  ROUTINE       : scale1d_2t1_i
138  *
139  *  INPUTS        : const unsigned char *source : Pointer to data to be scaled.
140  *                  int source_step              : Number of pixels to step on in source.
141  *                  unsigned int source_scale    : Scale for source (UNUSED).
142  *                  unsigned int source_length   : Length of source (UNUSED).
143  *                  unsigned char *dest         : Pointer to output data array.
144  *                  int dest_step                : Number of pixels to step on in destination.
145  *                  unsigned int dest_scale      : Scale for destination (UNUSED).
146  *                  unsigned int dest_length     : Length of destination.
147  *
148  *  OUTPUTS       : None.
149  *
150  *  RETURNS       : void
151  *
152  *  FUNCTION      : Performs 2-to-1 interpolated scaling.
153  *
154  *  SPECIAL NOTES : None.
155  *
156  ****************************************************************************/
157 static
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)158 void scale1d_2t1_i
159 (
160     const unsigned char *source,
161     int source_step,
162     unsigned int source_scale,
163     unsigned int source_length,
164     unsigned char *dest,
165     int dest_step,
166     unsigned int dest_scale,
167     unsigned int dest_length
168 )
169 {
170     unsigned int i, j;
171     unsigned int temp;
172     int source_pitch = source_step;
173     (void) source_length;
174     (void) source_scale;
175     (void) dest_scale;
176 
177     source_step *= 2;
178     dest[0] = source[0];
179 
180     for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step)
181     {
182         temp = 8;
183         temp += 3 * source[j-source_pitch];
184         temp += 10 * source[j];
185         temp += 3 * source[j+source_pitch];
186         temp >>= 4;
187         dest[i] = (char)(temp);
188     }
189 }
190 
191 /****************************************************************************
192  *
193  *  ROUTINE       : scale1d_2t1_ps
194  *
195  *  INPUTS        : const unsigned char *source : Pointer to data to be scaled.
196  *                  int source_step              : Number of pixels to step on in source.
197  *                  unsigned int source_scale    : Scale for source (UNUSED).
198  *                  unsigned int source_length   : Length of source (UNUSED).
199  *                  unsigned char *dest         : Pointer to output data array.
200  *                  int dest_step                : Number of pixels to step on in destination.
201  *                  unsigned int dest_scale      : Scale for destination (UNUSED).
202  *                  unsigned int dest_length     : Length of destination.
203  *
204  *  OUTPUTS       : None.
205  *
206  *  RETURNS       : void
207  *
208  *  FUNCTION      : Performs 2-to-1 point subsampled scaling.
209  *
210  *  SPECIAL NOTES : None.
211  *
212  ****************************************************************************/
213 static
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)214 void scale1d_2t1_ps
215 (
216     const unsigned char *source,
217     int source_step,
218     unsigned int source_scale,
219     unsigned int source_length,
220     unsigned char *dest,
221     int dest_step,
222     unsigned int dest_scale,
223     unsigned int dest_length
224 )
225 {
226     unsigned int i, j;
227 
228     (void) source_length;
229     (void) source_scale;
230     (void) dest_scale;
231 
232     source_step *= 2;
233     j = 0;
234 
235     for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
236         dest[i] = source[j];
237 }
238 /****************************************************************************
239  *
240  *  ROUTINE       : scale1d_c
241  *
242  *  INPUTS        : const unsigned char *source : Pointer to data to be scaled.
243  *                  int source_step              : Number of pixels to step on in source.
244  *                  unsigned int source_scale    : Scale for source.
245  *                  unsigned int source_length   : Length of source (UNUSED).
246  *                  unsigned char *dest         : Pointer to output data array.
247  *                  int dest_step                : Number of pixels to step on in destination.
248  *                  unsigned int dest_scale      : Scale for destination.
249  *                  unsigned int dest_length     : Length of destination.
250  *
251  *  OUTPUTS       : None.
252  *
253  *  RETURNS       : void
254  *
255  *  FUNCTION      : Performs linear interpolation in one dimension.
256  *
257  *  SPECIAL NOTES : None.
258  *
259  ****************************************************************************/
260 static
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)261 void scale1d_c
262 (
263     const unsigned char *source,
264     int source_step,
265     unsigned int source_scale,
266     unsigned int source_length,
267     unsigned char *dest,
268     int dest_step,
269     unsigned int dest_scale,
270     unsigned int dest_length
271 )
272 {
273     unsigned int i;
274     unsigned int round_value = dest_scale / 2;
275     unsigned int left_modifier = dest_scale;
276     unsigned int right_modifier = 0;
277     unsigned char left_pixel = *source;
278     unsigned char right_pixel = *(source + source_step);
279 
280     (void) source_length;
281 
282     /* These asserts are needed if there are boundary issues... */
283     /*assert ( dest_scale > source_scale );*/
284     /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale );*/
285 
286     for (i = 0; i < dest_length * dest_step; i += dest_step)
287     {
288         dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale);
289 
290         right_modifier += source_scale;
291 
292         while (right_modifier > dest_scale)
293         {
294             right_modifier -= dest_scale;
295             source += source_step;
296             left_pixel = *source;
297             right_pixel = *(source + source_step);
298         }
299 
300         left_modifier = dest_scale - right_modifier;
301     }
302 }
303 
304 /****************************************************************************
305  *
306  *  ROUTINE       : Scale2D
307  *
308  *  INPUTS        : const unsigned char *source  : Pointer to data to be scaled.
309  *                  int source_pitch              : Stride of source image.
310  *                  unsigned int source_width     : Width of input image.
311  *                  unsigned int source_height    : Height of input image.
312  *                  unsigned char *dest          : Pointer to output data array.
313  *                  int dest_pitch                : Stride of destination image.
314  *                  unsigned int dest_width       : Width of destination image.
315  *                  unsigned int dest_height      : Height of destination image.
316  *                  unsigned char *temp_area      : Pointer to temp work area.
317  *                  unsigned char temp_area_height : Height of temp work area.
318  *                  unsigned int hscale          : Horizontal scale factor numerator.
319  *                  unsigned int hratio          : Horizontal scale factor denominator.
320  *                  unsigned int vscale          : Vertical scale factor numerator.
321  *                  unsigned int vratio          : Vertical scale factor denominator.
322  *                  unsigned int interlaced      : Interlace flag.
323  *
324  *  OUTPUTS       : None.
325  *
326  *  RETURNS       : void
327  *
328  *  FUNCTION      : Performs 2-tap linear interpolation in two dimensions.
329  *
330  *  SPECIAL NOTES : Expansion is performed one band at a time to help with
331  *                  caching.
332  *
333  ****************************************************************************/
334 static
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)335 void Scale2D
336 (
337     /*const*/
338     unsigned char *source,
339     int source_pitch,
340     unsigned int source_width,
341     unsigned int source_height,
342     unsigned char *dest,
343     int dest_pitch,
344     unsigned int dest_width,
345     unsigned int dest_height,
346     unsigned char *temp_area,
347     unsigned char temp_area_height,
348     unsigned int hscale,
349     unsigned int hratio,
350     unsigned int vscale,
351     unsigned int vratio,
352     unsigned int interlaced
353 )
354 {
355     /*unsigned*/
356     int i, j, k;
357     int bands;
358     int dest_band_height;
359     int source_band_height;
360 
361     typedef void (*Scale1D)(const unsigned char * source, int source_step, unsigned int source_scale, unsigned int source_length,
362                             unsigned char * dest, int dest_step, unsigned int dest_scale, unsigned int dest_length);
363 
364     Scale1D Scale1Dv = scale1d_c;
365     Scale1D Scale1Dh = scale1d_c;
366 
367     void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
368     void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL;
369 
370     int ratio_scalable = 1;
371     int interpolation = 0;
372 
373     unsigned char *source_base; /* = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch))); */
374     unsigned char *line_src;
375 
376 
377     source_base = (unsigned char *)source;
378 
379     if (source_pitch < 0)
380     {
381         int offset;
382 
383         offset = (source_height - 1);
384         offset *= source_pitch;
385 
386         source_base += offset;
387     }
388 
389     /* find out the ratio for each direction */
390     switch (hratio * 10 / hscale)
391     {
392     case 8:
393         /* 4-5 Scale in Width direction */
394         horiz_line_scale = vp8_horizontal_line_5_4_scale;
395         break;
396     case 6:
397         /* 3-5 Scale in Width direction */
398         horiz_line_scale = vp8_horizontal_line_5_3_scale;
399         break;
400     case 5:
401         /* 1-2 Scale in Width direction */
402         horiz_line_scale = vp8_horizontal_line_2_1_scale;
403         break;
404     default:
405         /* The ratio is not acceptable now */
406         /* throw("The ratio is not acceptable for now!"); */
407         ratio_scalable = 0;
408         break;
409     }
410 
411     switch (vratio * 10 / vscale)
412     {
413     case 8:
414         /* 4-5 Scale in vertical direction */
415         vert_band_scale     = vp8_vertical_band_5_4_scale;
416         source_band_height  = 5;
417         dest_band_height    = 4;
418         break;
419     case 6:
420         /* 3-5 Scale in vertical direction */
421         vert_band_scale     = vp8_vertical_band_5_3_scale;
422         source_band_height  = 5;
423         dest_band_height    = 3;
424         break;
425     case 5:
426         /* 1-2 Scale in vertical direction */
427 
428         if (interlaced)
429         {
430             /* if the content is interlaced, point sampling is used */
431             vert_band_scale     = vp8_vertical_band_2_1_scale;
432         }
433         else
434         {
435 
436             interpolation = 1;
437             /* if the content is progressive, interplo */
438             vert_band_scale     = vp8_vertical_band_2_1_scale_i;
439 
440         }
441 
442         source_band_height  = 2;
443         dest_band_height    = 1;
444         break;
445     default:
446         /* The ratio is not acceptable now */
447         /* throw("The ratio is not acceptable for now!"); */
448         ratio_scalable = 0;
449         break;
450     }
451 
452     if (ratio_scalable)
453     {
454         if (source_height == dest_height)
455         {
456             /* for each band of the image */
457             for (k = 0; k < (int)dest_height; k++)
458             {
459                 horiz_line_scale(source, source_width, dest, dest_width);
460                 source += source_pitch;
461                 dest   += dest_pitch;
462             }
463 
464             return;
465         }
466 
467         if (interpolation)
468         {
469             if (source < source_base)
470                 source = source_base;
471 
472             horiz_line_scale(source, source_width, temp_area, dest_width);
473         }
474 
475         for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++)
476         {
477             /* scale one band horizontally */
478             for (i = 0; i < source_band_height; i++)
479             {
480                 /* Trap case where we could read off the base of the source buffer */
481 
482                 line_src = (unsigned char *)source + i * source_pitch;
483 
484                 if (line_src < source_base)
485                     line_src = source_base;
486 
487                 horiz_line_scale(line_src, source_width,
488                                  temp_area + (i + 1)*dest_pitch, dest_width);
489             }
490 
491             /* Vertical scaling is in place */
492             vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width);
493 
494             if (interpolation)
495                 vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width);
496 
497             /* Next band... */
498             source += (unsigned long) source_band_height  * source_pitch;
499             dest   += (unsigned long) dest_band_height * dest_pitch;
500         }
501 
502         return;
503     }
504 
505     if (hscale == 2 && hratio == 1)
506         Scale1Dh = scale1d_2t1_ps;
507 
508     if (vscale == 2 && vratio == 1)
509     {
510         if (interlaced)
511             Scale1Dv = scale1d_2t1_ps;
512         else
513             Scale1Dv = scale1d_2t1_i;
514     }
515 
516     if (source_height == dest_height)
517     {
518         /* for each band of the image */
519         for (k = 0; k < (int)dest_height; k++)
520         {
521             Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width);
522             source += source_pitch;
523             dest   += dest_pitch;
524         }
525 
526         return;
527     }
528 
529     if (dest_height > source_height)
530     {
531         dest_band_height   = temp_area_height - 1;
532         source_band_height = dest_band_height * source_height / dest_height;
533     }
534     else
535     {
536         source_band_height = temp_area_height - 1;
537         dest_band_height   = source_band_height * vratio / vscale;
538     }
539 
540     /* first row needs to be done so that we can stay one row ahead for vertical zoom */
541     Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width);
542 
543     /* for each band of the image */
544     bands = (dest_height + dest_band_height - 1) / dest_band_height;
545 
546     for (k = 0; k < bands; k++)
547     {
548         /* scale one band horizontally */
549         for (i = 1; i < source_band_height + 1; i++)
550         {
551             if (k * source_band_height + i < (int) source_height)
552             {
553                 Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
554                          temp_area + i * dest_pitch, 1, hratio, dest_width);
555             }
556             else  /*  Duplicate the last row */
557             {
558                 /* copy temp_area row 0 over from last row in the past */
559                 duck_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch);
560             }
561         }
562 
563         /* scale one band vertically */
564         for (j = 0; j < (int)dest_width; j++)
565         {
566             Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
567                      &dest[j], dest_pitch, vratio, dest_band_height);
568         }
569 
570         /* copy temp_area row 0 over from last row in the past */
571         duck_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
572 
573         /* move to the next band */
574         source += source_band_height * source_pitch;
575         dest   += dest_band_height * dest_pitch;
576     }
577 }
578 
579 /****************************************************************************
580  *
581  *  ROUTINE       :
582  *
583  *  INPUTS        : YV12_BUFFER_CONFIG *src       : Pointer to frame to be scaled.
584  *                  YV12_BUFFER_CONFIG *dst       : Pointer to buffer to hold scaled frame.
585  *                  unsigned char *temp_area      : Pointer to temp work area.
586  *                  unsigned char temp_area_height : Height of temp work area.
587  *                  unsigned int hscale          : Horizontal scale factor numerator.
588  *                  unsigned int hratio          : Horizontal scale factor denominator.
589  *                  unsigned int vscale          : Vertical scale factor numerator.
590  *                  unsigned int vratio          : Vertical scale factor denominator.
591  *                  unsigned int interlaced      : Interlace flag.
592  *
593  *  OUTPUTS       : None.
594  *
595  *  RETURNS       : void
596  *
597  *  FUNCTION      : Performs 2-tap linear interpolation in two dimensions.
598  *
599  *  SPECIAL NOTES : Expansion is performed one band at a time to help with
600  *                  caching.
601  *
602  ****************************************************************************/
vp8_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)603 void vp8_scale_frame
604 (
605     YV12_BUFFER_CONFIG *src,
606     YV12_BUFFER_CONFIG *dst,
607     unsigned char *temp_area,
608     unsigned char temp_height,
609     unsigned int hscale,
610     unsigned int hratio,
611     unsigned int vscale,
612     unsigned int vratio,
613     unsigned int interlaced
614 )
615 {
616     int i;
617     int dw = (hscale - 1 + src->y_width * hratio) / hscale;
618     int dh = (vscale - 1 + src->y_height * vratio) / vscale;
619 
620     /* call our internal scaling routines!! */
621     Scale2D((unsigned char *) src->y_buffer, src->y_stride, src->y_width, src->y_height,
622             (unsigned char *) dst->y_buffer, dst->y_stride, dw, dh,
623             temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
624 
625     if (dw < (int)dst->y_width)
626         for (i = 0; i < dh; i++)
627             duck_memset(dst->y_buffer + i * dst->y_stride + dw - 1, dst->y_buffer[i*dst->y_stride+dw-2], dst->y_width - dw + 1);
628 
629     if (dh < (int)dst->y_height)
630         for (i = dh - 1; i < (int)dst->y_height; i++)
631             duck_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
632 
633     Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height,
634             (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2,
635             temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
636 
637     if (dw / 2 < (int)dst->uv_width)
638         for (i = 0; i < dst->uv_height; i++)
639             duck_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);
640 
641     if (dh / 2 < (int)dst->uv_height)
642         for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
643             duck_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
644 
645     Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height,
646             (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2,
647             temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
648 
649     if (dw / 2 < (int)dst->uv_width)
650         for (i = 0; i < dst->uv_height; i++)
651             duck_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);
652 
653     if (dh / 2 < (int) dst->uv_height)
654         for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
655             duck_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
656 }
657 /****************************************************************************
658  *
659  *  ROUTINE       : any_ratio_2d_scale
660  *
661  *  INPUTS        : SCALE_INSTANCE *si      : Pointer to post-processor instance (NOT USED).
662  *                  const unsigned char *source : Pointer to source image.
663  *                  unsigned int source_pitch    : Stride of source image.
664  *                  unsigned int source_width    : Width of source image.
665  *                  unsigned int source_height   : Height of source image (NOT USED).
666  *                  unsigned char *dest         : Pointer to destination image.
667  *                  unsigned int dest_pitch      : Stride of destination image.
668  *                  unsigned int dest_width      : Width of destination image.
669  *                  unsigned int dest_height     : Height of destination image.
670  *
671  *  OUTPUTS       : None.
672  *
673  *  RETURNS       : int: 1 if image scaled, 0 if image could not be scaled.
674  *
675  *  FUNCTION      : Scale the image with changing apect ratio.
676  *
677  *  SPECIAL NOTES : This scaling is a bi-linear scaling. Need to re-work the
678  *                  whole function for new scaling algorithm.
679  *
680  ****************************************************************************/
681 static
any_ratio_2d_scale(SCALE_VARS * si,const unsigned char * source,int source_pitch,unsigned int source_width,unsigned int source_height,unsigned char * dest,unsigned int dest_pitch,unsigned int dest_width,unsigned int dest_height)682 int any_ratio_2d_scale
683 (
684     SCALE_VARS *si,
685     const unsigned char *source,
686     int source_pitch,
687     unsigned int source_width,
688     unsigned int source_height,
689     unsigned char *dest,
690     unsigned int dest_pitch,
691     unsigned int dest_width,
692     unsigned int dest_height
693 )
694 {
695     unsigned int i, k;
696     unsigned int src_band_height  = 0;
697     unsigned int dest_band_height = 0;
698 
699     /* suggested scale factors */
700     int hs = si->HScale;
701     int hr = si->HRatio;
702     int vs = si->VScale;
703     int vr = si->VRatio;
704 
705     /* assume the ratios are scalable instead of should be centered */
706     int ratio_scalable = 1;
707 
708     const unsigned char *source_base = ((source_pitch >= 0) ? source : (source + ((source_height - 1) * source_pitch)));
709     const unsigned char *line_src;
710 
711     void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
712     void (*vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
713     void (*last_vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
714 
715     (void) si;
716 
717     /* find out the ratio for each direction */
718     switch (hr * 30 / hs)
719     {
720     case 24:
721         /* 4-5 Scale in Width direction */
722         horiz_line_scale = vp8_horizontal_line_4_5_scale;
723         break;
724     case 22:
725         /* 3-4 Scale in Width direction */
726         horiz_line_scale = vp8_horizontal_line_3_4_scale;
727         break;
728 
729     case 20:
730         /* 4-5 Scale in Width direction */
731         horiz_line_scale = vp8_horizontal_line_2_3_scale;
732         break;
733     case 18:
734         /* 3-5 Scale in Width direction */
735         horiz_line_scale = vp8_horizontal_line_3_5_scale;
736         break;
737     case 15:
738         /* 1-2 Scale in Width direction */
739         horiz_line_scale = vp8_horizontal_line_1_2_scale;
740         break;
741     case 30:
742         /* no scale in Width direction */
743         horiz_line_scale = horizontal_line_copy;
744         break;
745     default:
746         /* The ratio is not acceptable now */
747         /* throw("The ratio is not acceptable for now!"); */
748         ratio_scalable = 0;
749         break;
750     }
751 
752     switch (vr * 30 / vs)
753     {
754     case 24:
755         /* 4-5 Scale in vertical direction */
756         vert_band_scale     = vp8_vertical_band_4_5_scale;
757         last_vert_band_scale = vp8_last_vertical_band_4_5_scale;
758         src_band_height     = 4;
759         dest_band_height    = 5;
760         break;
761     case 22:
762         /* 3-4 Scale in vertical direction */
763         vert_band_scale     = vp8_vertical_band_3_4_scale;
764         last_vert_band_scale = vp8_last_vertical_band_3_4_scale;
765         src_band_height     = 3;
766         dest_band_height    = 4;
767         break;
768     case 20:
769         /* 2-3 Scale in vertical direction */
770         vert_band_scale     = vp8_vertical_band_2_3_scale;
771         last_vert_band_scale = vp8_last_vertical_band_2_3_scale;
772         src_band_height     = 2;
773         dest_band_height    = 3;
774         break;
775     case 18:
776         /* 3-5 Scale in vertical direction */
777         vert_band_scale     = vp8_vertical_band_3_5_scale;
778         last_vert_band_scale = vp8_last_vertical_band_3_5_scale;
779         src_band_height     = 3;
780         dest_band_height    = 5;
781         break;
782     case 15:
783         /* 1-2 Scale in vertical direction */
784         vert_band_scale     = vp8_vertical_band_1_2_scale;
785         last_vert_band_scale = vp8_last_vertical_band_1_2_scale;
786         src_band_height     = 1;
787         dest_band_height    = 2;
788         break;
789     case 30:
790         /* no scale in Width direction */
791         vert_band_scale     = null_scale;
792         last_vert_band_scale = null_scale;
793         src_band_height     = 4;
794         dest_band_height    = 4;
795         break;
796     default:
797         /* The ratio is not acceptable now */
798         /* throw("The ratio is not acceptable for now!"); */
799         ratio_scalable = 0;
800         break;
801     }
802 
803     if (ratio_scalable == 0)
804         return ratio_scalable;
805 
806     horiz_line_scale(source, source_width, dest, dest_width);
807 
808     /* except last band */
809     for (k = 0; k < (dest_height + dest_band_height - 1) / dest_band_height - 1; k++)
810     {
811         /* scale one band horizontally */
812         for (i = 1; i < src_band_height; i++)
813         {
814             /* Trap case where we could read off the base of the source buffer */
815             line_src = source + i * source_pitch;
816 
817             if (line_src < source_base)
818                 line_src = source_base;
819 
820             horiz_line_scale(line_src, source_width,
821                              dest + i * dest_pitch, dest_width);
822         }
823 
824         /* first line of next band */
825         /* Trap case where we could read off the base of the source buffer */
826         line_src = source + src_band_height * source_pitch;
827 
828         if (line_src < source_base)
829             line_src = source_base;
830 
831         horiz_line_scale(line_src, source_width,
832                          dest + dest_band_height * dest_pitch,
833                          dest_width);
834 
835         /* Vertical scaling is in place */
836         vert_band_scale(dest, dest_pitch, dest_width);
837 
838         /* Next band... */
839         source += src_band_height  * source_pitch;
840         dest   += dest_band_height * dest_pitch;
841     }
842 
843     /* scale one band horizontally */
844     for (i = 1; i < src_band_height; i++)
845     {
846         /* Trap case where we could read off the base of the source buffer */
847         line_src = source + i * source_pitch;
848 
849         if (line_src < source_base)
850             line_src = source_base;
851 
852         horiz_line_scale(line_src, source_width,
853                          dest + i * dest_pitch,
854                          dest_width);
855     }
856 
857     /* Vertical scaling is in place */
858     last_vert_band_scale(dest, dest_pitch, dest_width);
859 
860     return ratio_scalable;
861 }
862 
863 /****************************************************************************
864  *
865  *  ROUTINE       : any_ratio_frame_scale
866  *
867  *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance (NOT USED).
868  *                  unsigned char *frame_buffer           : Pointer to source image.
869  *                  int YOffset                : Offset from start of buffer to Y samples.
870  *                  int UVOffset               : Offset from start of buffer to UV samples.
871  *
872  *  OUTPUTS       : None.
873  *
874  *  RETURNS       : int: 1 if image scaled, 0 if image could not be scaled.
875  *
876  *  FUNCTION      : Scale the image with changing apect ratio.
877  *
878  *  SPECIAL NOTES : None.
879  *
880  ****************************************************************************/
881 static
any_ratio_frame_scale(SCALE_VARS * scale_vars,int YOffset,int UVOffset)882 int any_ratio_frame_scale(SCALE_VARS *scale_vars, int YOffset, int UVOffset)
883 {
884     int i;
885     int ew;
886     int eh;
887 
888     /* suggested scale factors */
889     int hs = scale_vars->HScale;
890     int hr = scale_vars->HRatio;
891     int vs = scale_vars->VScale;
892     int vr = scale_vars->VRatio;
893 
894     int ratio_scalable = 1;
895 
896     int sw = (scale_vars->expanded_frame_width * hr + hs - 1) / hs;
897     int sh = (scale_vars->expanded_frame_height * vr + vs - 1) / vs;
898     int dw = scale_vars->expanded_frame_width;
899     int dh = scale_vars->expanded_frame_height;
900     YV12_BUFFER_CONFIG *src_yuv_config = scale_vars->src_yuv_config;
901     YV12_BUFFER_CONFIG *dst_yuv_config = scale_vars->dst_yuv_config;
902 
903     if (hr == 3)
904         ew = (sw + 2) / 3 * 3 * hs / hr;
905     else
906         ew = (sw + 7) / 8 * 8 * hs / hr;
907 
908     if (vr == 3)
909         eh = (sh + 2) / 3 * 3 * vs / vr;
910     else
911         eh = (sh + 7) / 8 * 8 * vs / vr;
912 
913     ratio_scalable = any_ratio_2d_scale(scale_vars,
914                                         (const unsigned char *)src_yuv_config->y_buffer,
915                                         src_yuv_config->y_stride, sw, sh,
916                                         (unsigned char *) dst_yuv_config->y_buffer + YOffset,
917                                         dst_yuv_config->y_stride, dw, dh);
918 
919     for (i = 0; i < eh; i++)
920         duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride + dw, 0, ew - dw);
921 
922     for (i = dh; i < eh; i++)
923         duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride, 0, ew);
924 
925     if (ratio_scalable == 0)
926         return ratio_scalable;
927 
928     sw = (sw + 1) >> 1;
929     sh = (sh + 1) >> 1;
930     dw = (dw + 1) >> 1;
931     dh = (dh + 1) >> 1;
932 
933     any_ratio_2d_scale(scale_vars,
934                        (const unsigned char *)src_yuv_config->u_buffer,
935                        src_yuv_config->y_stride / 2, sw, sh,
936                        (unsigned char *)dst_yuv_config->u_buffer + UVOffset,
937                        dst_yuv_config->uv_stride, dw, dh);
938 
939     any_ratio_2d_scale(scale_vars,
940                        (const unsigned char *)src_yuv_config->v_buffer,
941                        src_yuv_config->y_stride / 2, sw, sh,
942                        (unsigned char *)dst_yuv_config->v_buffer + UVOffset,
943                        dst_yuv_config->uv_stride, dw, dh);
944 
945     return ratio_scalable;
946 }
947 
948 /****************************************************************************
949  *
950  *  ROUTINE       : center_image
951  *
952  *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance.
953  *
954  *  OUTPUTS       : None.
955  *
956  *  RETURNS       : void
957  *
958  *  FUNCTION      : Centers the image without scaling in the output buffer.
959  *
960  *  SPECIAL NOTES : None.
961  *
962  ****************************************************************************/
963 static void
center_image(YV12_BUFFER_CONFIG * src_yuv_config,YV12_BUFFER_CONFIG * dst_yuv_config)964 center_image(YV12_BUFFER_CONFIG *src_yuv_config, YV12_BUFFER_CONFIG *dst_yuv_config)
965 {
966     int i;
967     int row_offset, col_offset;
968     unsigned char *src_data_pointer;
969     unsigned char *dst_data_pointer;
970 
971     /* center values */
972     row_offset = (dst_yuv_config->y_height - src_yuv_config->y_height) / 2;
973     col_offset = (dst_yuv_config->y_width - src_yuv_config->y_width) / 2;
974 
975     /* Y's */
976     src_data_pointer = src_yuv_config->y_buffer;
977     dst_data_pointer = (unsigned char *)dst_yuv_config->y_buffer + (row_offset * dst_yuv_config->y_stride) + col_offset;
978 
979     for (i = 0; i < src_yuv_config->y_height; i++)
980     {
981         duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->y_width);
982         dst_data_pointer += dst_yuv_config->y_stride;
983         src_data_pointer += src_yuv_config->y_stride;
984     }
985 
986     row_offset /= 2;
987     col_offset /= 2;
988 
989     /* U's */
990     src_data_pointer = src_yuv_config->u_buffer;
991     dst_data_pointer = (unsigned char *)dst_yuv_config->u_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
992 
993     for (i = 0; i < src_yuv_config->uv_height; i++)
994     {
995         duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
996         dst_data_pointer += dst_yuv_config->uv_stride;
997         src_data_pointer += src_yuv_config->uv_stride;
998     }
999 
1000     /* V's */
1001     src_data_pointer = src_yuv_config->v_buffer;
1002     dst_data_pointer = (unsigned char *)dst_yuv_config->v_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
1003 
1004     for (i = 0; i < src_yuv_config->uv_height; i++)
1005     {
1006         duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
1007         dst_data_pointer += dst_yuv_config->uv_stride;
1008         src_data_pointer += src_yuv_config->uv_stride;
1009     }
1010 }
1011 
1012 /****************************************************************************
1013  *
1014  *  ROUTINE       : scale_or_center
1015  *
1016  *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance.
1017  *
1018  *
1019  *
1020  *  OUTPUTS       : None.
1021  *
1022  *  RETURNS       : void
1023  *
1024  *  FUNCTION      : Decides to scale or center image in scale buffer for blit
1025  *
1026  *  SPECIAL NOTES : None.
1027  *
1028  ****************************************************************************/
1029 void
vp8_yv12_scale_or_center(YV12_BUFFER_CONFIG * src_yuv_config,YV12_BUFFER_CONFIG * dst_yuv_config,int expanded_frame_width,int expanded_frame_height,int scaling_mode,int HScale,int HRatio,int VScale,int VRatio)1030 vp8_yv12_scale_or_center
1031 (
1032     YV12_BUFFER_CONFIG *src_yuv_config,
1033     YV12_BUFFER_CONFIG *dst_yuv_config,
1034     int expanded_frame_width,
1035     int expanded_frame_height,
1036     int scaling_mode,
1037     int HScale,
1038     int HRatio,
1039     int VScale,
1040     int VRatio
1041 )
1042 {
1043     /*if ( ppi->post_processing_level )
1044           update_umvborder ( ppi, frame_buffer );*/
1045 
1046 
1047     switch (scaling_mode)
1048     {
1049     case SCALE_TO_FIT:
1050     case MAINTAIN_ASPECT_RATIO:
1051     {
1052         SCALE_VARS scale_vars;
1053         /* center values */
1054 #if 1
1055         int row = (dst_yuv_config->y_height - expanded_frame_height) / 2;
1056         int col = (dst_yuv_config->y_width  - expanded_frame_width) / 2;
1057         /*int YOffset  = row * dst_yuv_config->y_width + col;
1058         int UVOffset = (row>>1) * dst_yuv_config->uv_width + (col>>1);*/
1059         int YOffset  = row * dst_yuv_config->y_stride + col;
1060         int UVOffset = (row >> 1) * dst_yuv_config->uv_stride + (col >> 1);
1061 #else
1062         int row = (src_yuv_config->y_height - expanded_frame_height) / 2;
1063         int col = (src_yuv_config->y_width  - expanded_frame_width) / 2;
1064         int YOffset  = row * src_yuv_config->y_width + col;
1065         int UVOffset = (row >> 1) * src_yuv_config->uv_width + (col >> 1);
1066 #endif
1067 
1068         scale_vars.dst_yuv_config = dst_yuv_config;
1069         scale_vars.src_yuv_config = src_yuv_config;
1070         scale_vars.HScale = HScale;
1071         scale_vars.HRatio = HRatio;
1072         scale_vars.VScale = VScale;
1073         scale_vars.VRatio = VRatio;
1074         scale_vars.expanded_frame_width = expanded_frame_width;
1075         scale_vars.expanded_frame_height = expanded_frame_height;
1076 
1077         /* perform center and scale */
1078         any_ratio_frame_scale(&scale_vars, YOffset, UVOffset);
1079 
1080         break;
1081     }
1082     case CENTER:
1083         center_image(src_yuv_config, dst_yuv_config);
1084         break;
1085 
1086     default:
1087         break;
1088     }
1089 }
1090