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