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
92 0 : 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 0 : duck_memcpy(dest, source, source_width);
102 0 : }
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
122 0 : 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
158 0 : 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 0 : int source_pitch = source_step;
173 : (void) source_length;
174 : (void) source_scale;
175 : (void) dest_scale;
176 :
177 0 : source_step *= 2;
178 0 : dest[0] = source[0];
179 :
180 0 : for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step)
181 : {
182 0 : temp = 8;
183 0 : temp += 3 * source[j-source_pitch];
184 0 : temp += 10 * source[j];
185 0 : temp += 3 * source[j+source_pitch];
186 0 : temp >>= 4;
187 0 : dest[i] = (char)(temp);
188 : }
189 0 : }
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
214 0 : 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 0 : source_step *= 2;
233 0 : j = 0;
234 :
235 0 : for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
236 0 : dest[i] = source[j];
237 0 : }
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
261 0 : 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 0 : unsigned int round_value = dest_scale / 2;
275 0 : unsigned int left_modifier = dest_scale;
276 0 : unsigned int right_modifier = 0;
277 0 : unsigned char left_pixel = *source;
278 0 : 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 0 : for (i = 0; i < dest_length * dest_step; i += dest_step)
287 : {
288 0 : dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale);
289 :
290 0 : right_modifier += source_scale;
291 :
292 0 : while (right_modifier > dest_scale)
293 : {
294 0 : right_modifier -= dest_scale;
295 0 : source += source_step;
296 0 : left_pixel = *source;
297 0 : right_pixel = *(source + source_step);
298 : }
299 :
300 0 : left_modifier = dest_scale - right_modifier;
301 : }
302 0 : }
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
335 0 : 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 0 : Scale1D Scale1Dv = scale1d_c;
365 0 : Scale1D Scale1Dh = scale1d_c;
366 :
367 0 : void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
368 0 : void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL;
369 :
370 0 : int ratio_scalable = 1;
371 0 : 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 0 : source_base = (unsigned char *)source;
378 :
379 0 : if (source_pitch < 0)
380 : {
381 : int offset;
382 :
383 0 : offset = (source_height - 1);
384 0 : offset *= source_pitch;
385 :
386 0 : source_base += offset;
387 : }
388 :
389 : /* find out the ratio for each direction */
390 0 : switch (hratio * 10 / hscale)
391 : {
392 : case 8:
393 : /* 4-5 Scale in Width direction */
394 0 : horiz_line_scale = vp8_horizontal_line_5_4_scale;
395 0 : break;
396 : case 6:
397 : /* 3-5 Scale in Width direction */
398 0 : horiz_line_scale = vp8_horizontal_line_5_3_scale;
399 0 : break;
400 : case 5:
401 : /* 1-2 Scale in Width direction */
402 0 : horiz_line_scale = vp8_horizontal_line_2_1_scale;
403 0 : break;
404 : default:
405 : /* The ratio is not acceptable now */
406 : /* throw("The ratio is not acceptable for now!"); */
407 0 : ratio_scalable = 0;
408 0 : break;
409 : }
410 :
411 0 : switch (vratio * 10 / vscale)
412 : {
413 : case 8:
414 : /* 4-5 Scale in vertical direction */
415 0 : vert_band_scale = vp8_vertical_band_5_4_scale;
416 0 : source_band_height = 5;
417 0 : dest_band_height = 4;
418 0 : break;
419 : case 6:
420 : /* 3-5 Scale in vertical direction */
421 0 : vert_band_scale = vp8_vertical_band_5_3_scale;
422 0 : source_band_height = 5;
423 0 : dest_band_height = 3;
424 0 : break;
425 : case 5:
426 : /* 1-2 Scale in vertical direction */
427 :
428 0 : if (interlaced)
429 : {
430 : /* if the content is interlaced, point sampling is used */
431 0 : vert_band_scale = vp8_vertical_band_2_1_scale;
432 : }
433 : else
434 : {
435 :
436 0 : interpolation = 1;
437 : /* if the content is progressive, interplo */
438 0 : vert_band_scale = vp8_vertical_band_2_1_scale_i;
439 :
440 : }
441 :
442 0 : source_band_height = 2;
443 0 : dest_band_height = 1;
444 0 : break;
445 : default:
446 : /* The ratio is not acceptable now */
447 : /* throw("The ratio is not acceptable for now!"); */
448 0 : ratio_scalable = 0;
449 0 : break;
450 : }
451 :
452 0 : if (ratio_scalable)
453 : {
454 0 : if (source_height == dest_height)
455 : {
456 : /* for each band of the image */
457 0 : for (k = 0; k < (int)dest_height; k++)
458 : {
459 0 : horiz_line_scale(source, source_width, dest, dest_width);
460 0 : source += source_pitch;
461 0 : dest += dest_pitch;
462 : }
463 :
464 0 : return;
465 : }
466 :
467 0 : if (interpolation)
468 : {
469 0 : if (source < source_base)
470 0 : source = source_base;
471 :
472 0 : horiz_line_scale(source, source_width, temp_area, dest_width);
473 : }
474 :
475 0 : for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++)
476 : {
477 : /* scale one band horizontally */
478 0 : 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 0 : line_src = (unsigned char *)source + i * source_pitch;
483 :
484 0 : if (line_src < source_base)
485 0 : line_src = source_base;
486 :
487 0 : horiz_line_scale(line_src, source_width,
488 0 : temp_area + (i + 1)*dest_pitch, dest_width);
489 : }
490 :
491 : /* Vertical scaling is in place */
492 0 : vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width);
493 :
494 0 : if (interpolation)
495 0 : vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width);
496 :
497 : /* Next band... */
498 0 : source += (unsigned long) source_band_height * source_pitch;
499 0 : dest += (unsigned long) dest_band_height * dest_pitch;
500 : }
501 :
502 0 : return;
503 : }
504 :
505 0 : if (hscale == 2 && hratio == 1)
506 0 : Scale1Dh = scale1d_2t1_ps;
507 :
508 0 : if (vscale == 2 && vratio == 1)
509 : {
510 0 : if (interlaced)
511 0 : Scale1Dv = scale1d_2t1_ps;
512 : else
513 0 : Scale1Dv = scale1d_2t1_i;
514 : }
515 :
516 0 : if (source_height == dest_height)
517 : {
518 : /* for each band of the image */
519 0 : for (k = 0; k < (int)dest_height; k++)
520 : {
521 0 : Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width);
522 0 : source += source_pitch;
523 0 : dest += dest_pitch;
524 : }
525 :
526 0 : return;
527 : }
528 :
529 0 : if (dest_height > source_height)
530 : {
531 0 : dest_band_height = temp_area_height - 1;
532 0 : source_band_height = dest_band_height * source_height / dest_height;
533 : }
534 : else
535 : {
536 0 : source_band_height = temp_area_height - 1;
537 0 : 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 0 : Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width);
542 :
543 : /* for each band of the image */
544 0 : bands = (dest_height + dest_band_height - 1) / dest_band_height;
545 :
546 0 : for (k = 0; k < bands; k++)
547 : {
548 : /* scale one band horizontally */
549 0 : for (i = 1; i < source_band_height + 1; i++)
550 : {
551 0 : if (k * source_band_height + i < (int) source_height)
552 : {
553 0 : Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
554 0 : 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 0 : duck_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch);
560 : }
561 : }
562 :
563 : /* scale one band vertically */
564 0 : for (j = 0; j < (int)dest_width; j++)
565 : {
566 0 : 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 0 : duck_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
572 :
573 : /* move to the next band */
574 0 : source += source_band_height * source_pitch;
575 0 : 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 : ****************************************************************************/
603 0 : 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 0 : int dw = (hscale - 1 + src->y_width * hratio) / hscale;
618 0 : int dh = (vscale - 1 + src->y_height * vratio) / vscale;
619 :
620 : /* call our internal scaling routines!! */
621 0 : 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 0 : if (dw < (int)dst->y_width)
626 0 : for (i = 0; i < dh; i++)
627 0 : 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 0 : if (dh < (int)dst->y_height)
630 0 : for (i = dh - 1; i < (int)dst->y_height; i++)
631 0 : duck_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
632 :
633 0 : Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height,
634 0 : (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2,
635 : temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
636 :
637 0 : if (dw / 2 < (int)dst->uv_width)
638 0 : for (i = 0; i < dst->uv_height; i++)
639 0 : 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 0 : if (dh / 2 < (int)dst->uv_height)
642 0 : for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
643 0 : duck_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
644 :
645 0 : Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height,
646 0 : (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2,
647 : temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
648 :
649 0 : if (dw / 2 < (int)dst->uv_width)
650 0 : for (i = 0; i < dst->uv_height; i++)
651 0 : 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 0 : if (dh / 2 < (int) dst->uv_height)
654 0 : for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
655 0 : duck_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
656 0 : }
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
682 0 : 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 0 : unsigned int src_band_height = 0;
697 0 : unsigned int dest_band_height = 0;
698 :
699 : /* suggested scale factors */
700 0 : int hs = si->HScale;
701 0 : int hr = si->HRatio;
702 0 : int vs = si->VScale;
703 0 : int vr = si->VRatio;
704 :
705 : /* assume the ratios are scalable instead of should be centered */
706 0 : int ratio_scalable = 1;
707 :
708 0 : const unsigned char *source_base = ((source_pitch >= 0) ? source : (source + ((source_height - 1) * source_pitch)));
709 : const unsigned char *line_src;
710 :
711 0 : void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
712 0 : void (*vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
713 0 : 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 0 : switch (hr * 30 / hs)
719 : {
720 : case 24:
721 : /* 4-5 Scale in Width direction */
722 0 : horiz_line_scale = vp8_horizontal_line_4_5_scale;
723 0 : break;
724 : case 22:
725 : /* 3-4 Scale in Width direction */
726 0 : horiz_line_scale = vp8_horizontal_line_3_4_scale;
727 0 : break;
728 :
729 : case 20:
730 : /* 4-5 Scale in Width direction */
731 0 : horiz_line_scale = vp8_horizontal_line_2_3_scale;
732 0 : break;
733 : case 18:
734 : /* 3-5 Scale in Width direction */
735 0 : horiz_line_scale = vp8_horizontal_line_3_5_scale;
736 0 : break;
737 : case 15:
738 : /* 1-2 Scale in Width direction */
739 0 : horiz_line_scale = vp8_horizontal_line_1_2_scale;
740 0 : break;
741 : case 30:
742 : /* no scale in Width direction */
743 0 : horiz_line_scale = horizontal_line_copy;
744 0 : break;
745 : default:
746 : /* The ratio is not acceptable now */
747 : /* throw("The ratio is not acceptable for now!"); */
748 0 : ratio_scalable = 0;
749 0 : break;
750 : }
751 :
752 0 : switch (vr * 30 / vs)
753 : {
754 : case 24:
755 : /* 4-5 Scale in vertical direction */
756 0 : vert_band_scale = vp8_vertical_band_4_5_scale;
757 0 : last_vert_band_scale = vp8_last_vertical_band_4_5_scale;
758 0 : src_band_height = 4;
759 0 : dest_band_height = 5;
760 0 : break;
761 : case 22:
762 : /* 3-4 Scale in vertical direction */
763 0 : vert_band_scale = vp8_vertical_band_3_4_scale;
764 0 : last_vert_band_scale = vp8_last_vertical_band_3_4_scale;
765 0 : src_band_height = 3;
766 0 : dest_band_height = 4;
767 0 : break;
768 : case 20:
769 : /* 2-3 Scale in vertical direction */
770 0 : vert_band_scale = vp8_vertical_band_2_3_scale;
771 0 : last_vert_band_scale = vp8_last_vertical_band_2_3_scale;
772 0 : src_band_height = 2;
773 0 : dest_band_height = 3;
774 0 : break;
775 : case 18:
776 : /* 3-5 Scale in vertical direction */
777 0 : vert_band_scale = vp8_vertical_band_3_5_scale;
778 0 : last_vert_band_scale = vp8_last_vertical_band_3_5_scale;
779 0 : src_band_height = 3;
780 0 : dest_band_height = 5;
781 0 : break;
782 : case 15:
783 : /* 1-2 Scale in vertical direction */
784 0 : vert_band_scale = vp8_vertical_band_1_2_scale;
785 0 : last_vert_band_scale = vp8_last_vertical_band_1_2_scale;
786 0 : src_band_height = 1;
787 0 : dest_band_height = 2;
788 0 : break;
789 : case 30:
790 : /* no scale in Width direction */
791 0 : vert_band_scale = null_scale;
792 0 : last_vert_band_scale = null_scale;
793 0 : src_band_height = 4;
794 0 : dest_band_height = 4;
795 0 : break;
796 : default:
797 : /* The ratio is not acceptable now */
798 : /* throw("The ratio is not acceptable for now!"); */
799 0 : ratio_scalable = 0;
800 0 : break;
801 : }
802 :
803 0 : if (ratio_scalable == 0)
804 0 : return ratio_scalable;
805 :
806 0 : horiz_line_scale(source, source_width, dest, dest_width);
807 :
808 : /* except last band */
809 0 : for (k = 0; k < (dest_height + dest_band_height - 1) / dest_band_height - 1; k++)
810 : {
811 : /* scale one band horizontally */
812 0 : for (i = 1; i < src_band_height; i++)
813 : {
814 : /* Trap case where we could read off the base of the source buffer */
815 0 : line_src = source + i * source_pitch;
816 :
817 0 : if (line_src < source_base)
818 0 : line_src = source_base;
819 :
820 0 : horiz_line_scale(line_src, source_width,
821 0 : 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 0 : line_src = source + src_band_height * source_pitch;
827 :
828 0 : if (line_src < source_base)
829 0 : line_src = source_base;
830 :
831 0 : horiz_line_scale(line_src, source_width,
832 0 : dest + dest_band_height * dest_pitch,
833 : dest_width);
834 :
835 : /* Vertical scaling is in place */
836 0 : vert_band_scale(dest, dest_pitch, dest_width);
837 :
838 : /* Next band... */
839 0 : source += src_band_height * source_pitch;
840 0 : dest += dest_band_height * dest_pitch;
841 : }
842 :
843 : /* scale one band horizontally */
844 0 : for (i = 1; i < src_band_height; i++)
845 : {
846 : /* Trap case where we could read off the base of the source buffer */
847 0 : line_src = source + i * source_pitch;
848 :
849 0 : if (line_src < source_base)
850 0 : line_src = source_base;
851 :
852 0 : horiz_line_scale(line_src, source_width,
853 0 : dest + i * dest_pitch,
854 : dest_width);
855 : }
856 :
857 : /* Vertical scaling is in place */
858 0 : last_vert_band_scale(dest, dest_pitch, dest_width);
859 :
860 0 : 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
882 0 : 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 0 : int hs = scale_vars->HScale;
890 0 : int hr = scale_vars->HRatio;
891 0 : int vs = scale_vars->VScale;
892 0 : int vr = scale_vars->VRatio;
893 :
894 0 : int ratio_scalable = 1;
895 :
896 0 : int sw = (scale_vars->expanded_frame_width * hr + hs - 1) / hs;
897 0 : int sh = (scale_vars->expanded_frame_height * vr + vs - 1) / vs;
898 0 : int dw = scale_vars->expanded_frame_width;
899 0 : int dh = scale_vars->expanded_frame_height;
900 0 : YV12_BUFFER_CONFIG *src_yuv_config = scale_vars->src_yuv_config;
901 0 : YV12_BUFFER_CONFIG *dst_yuv_config = scale_vars->dst_yuv_config;
902 :
903 0 : if (hr == 3)
904 0 : ew = (sw + 2) / 3 * 3 * hs / hr;
905 : else
906 0 : ew = (sw + 7) / 8 * 8 * hs / hr;
907 :
908 0 : if (vr == 3)
909 0 : eh = (sh + 2) / 3 * 3 * vs / vr;
910 : else
911 0 : eh = (sh + 7) / 8 * 8 * vs / vr;
912 :
913 0 : ratio_scalable = any_ratio_2d_scale(scale_vars,
914 0 : (const unsigned char *)src_yuv_config->y_buffer,
915 : src_yuv_config->y_stride, sw, sh,
916 0 : (unsigned char *) dst_yuv_config->y_buffer + YOffset,
917 0 : dst_yuv_config->y_stride, dw, dh);
918 :
919 0 : for (i = 0; i < eh; i++)
920 0 : duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride + dw, 0, ew - dw);
921 :
922 0 : for (i = dh; i < eh; i++)
923 0 : duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride, 0, ew);
924 :
925 0 : if (ratio_scalable == 0)
926 0 : return ratio_scalable;
927 :
928 0 : sw = (sw + 1) >> 1;
929 0 : sh = (sh + 1) >> 1;
930 0 : dw = (dw + 1) >> 1;
931 0 : dh = (dh + 1) >> 1;
932 :
933 0 : any_ratio_2d_scale(scale_vars,
934 0 : (const unsigned char *)src_yuv_config->u_buffer,
935 0 : src_yuv_config->y_stride / 2, sw, sh,
936 0 : (unsigned char *)dst_yuv_config->u_buffer + UVOffset,
937 0 : dst_yuv_config->uv_stride, dw, dh);
938 :
939 0 : any_ratio_2d_scale(scale_vars,
940 0 : (const unsigned char *)src_yuv_config->v_buffer,
941 0 : src_yuv_config->y_stride / 2, sw, sh,
942 0 : (unsigned char *)dst_yuv_config->v_buffer + UVOffset,
943 0 : dst_yuv_config->uv_stride, dw, dh);
944 :
945 0 : 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
964 0 : 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 0 : row_offset = (dst_yuv_config->y_height - src_yuv_config->y_height) / 2;
973 0 : col_offset = (dst_yuv_config->y_width - src_yuv_config->y_width) / 2;
974 :
975 : /* Y's */
976 0 : src_data_pointer = src_yuv_config->y_buffer;
977 0 : dst_data_pointer = (unsigned char *)dst_yuv_config->y_buffer + (row_offset * dst_yuv_config->y_stride) + col_offset;
978 :
979 0 : for (i = 0; i < src_yuv_config->y_height; i++)
980 : {
981 0 : duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->y_width);
982 0 : dst_data_pointer += dst_yuv_config->y_stride;
983 0 : src_data_pointer += src_yuv_config->y_stride;
984 : }
985 :
986 0 : row_offset /= 2;
987 0 : col_offset /= 2;
988 :
989 : /* U's */
990 0 : src_data_pointer = src_yuv_config->u_buffer;
991 0 : dst_data_pointer = (unsigned char *)dst_yuv_config->u_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
992 :
993 0 : for (i = 0; i < src_yuv_config->uv_height; i++)
994 : {
995 0 : duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
996 0 : dst_data_pointer += dst_yuv_config->uv_stride;
997 0 : src_data_pointer += src_yuv_config->uv_stride;
998 : }
999 :
1000 : /* V's */
1001 0 : src_data_pointer = src_yuv_config->v_buffer;
1002 0 : dst_data_pointer = (unsigned char *)dst_yuv_config->v_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
1003 :
1004 0 : for (i = 0; i < src_yuv_config->uv_height; i++)
1005 : {
1006 0 : duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
1007 0 : dst_data_pointer += dst_yuv_config->uv_stride;
1008 0 : src_data_pointer += src_yuv_config->uv_stride;
1009 : }
1010 0 : }
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
1030 0 : 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 0 : 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 0 : int row = (dst_yuv_config->y_height - expanded_frame_height) / 2;
1056 0 : 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 0 : int YOffset = row * dst_yuv_config->y_stride + col;
1060 0 : 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 0 : scale_vars.dst_yuv_config = dst_yuv_config;
1069 0 : scale_vars.src_yuv_config = src_yuv_config;
1070 0 : scale_vars.HScale = HScale;
1071 0 : scale_vars.HRatio = HRatio;
1072 0 : scale_vars.VScale = VScale;
1073 0 : scale_vars.VRatio = VRatio;
1074 0 : scale_vars.expanded_frame_width = expanded_frame_width;
1075 0 : scale_vars.expanded_frame_height = expanded_frame_height;
1076 :
1077 : /* perform center and scale */
1078 0 : any_ratio_frame_scale(&scale_vars, YOffset, UVOffset);
1079 :
1080 0 : break;
1081 : }
1082 : case CENTER:
1083 0 : center_image(src_yuv_config, dst_yuv_config);
1084 0 : break;
1085 :
1086 : default:
1087 0 : break;
1088 : }
1089 0 : }
|