1 /*****************************************************************************
2 * i420_rgb16.c : YUV to bitmap RGB conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000 the VideoLAN team
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Damien Fouilleul <damienf@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
34 #include <vlc_filter.h>
38 #if defined (MODULE_NAME_IS_i420_rgb)
39 # include "i420_rgb_c.h"
40 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
41 # include "i420_rgb_mmx.h"
42 #elif defined (MODULE_NAME_IS_i420_rgb_sse2)
43 # include "i420_rgb_mmx.h"
46 static void SetOffset( int, int, int, int, bool *,
47 unsigned int *, int * );
49 #if defined (MODULE_NAME_IS_i420_rgb)
50 /*****************************************************************************
51 * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp with dithering
52 *****************************************************************************
53 * Horizontal alignment needed:
54 * - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
55 * - output: 1 pixel (2 bytes), margins allowed
56 * Vertical alignment needed:
57 * - input: 2 lines (2 Y lines, 1 U/V line)
59 *****************************************************************************/
60 void I420_RGB16_dither( filter_t *p_filter, picture_t *p_src,
63 /* We got this one from the old arguments */
64 uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
65 uint8_t *p_y = p_src->Y_PIXELS;
66 uint8_t *p_u = p_src->U_PIXELS;
67 uint8_t *p_v = p_src->V_PIXELS;
69 bool b_hscale; /* horizontal scaling type */
70 unsigned int i_vscale; /* vertical scaling type */
71 unsigned int i_x, i_y; /* horizontal and vertical indexes */
72 unsigned int i_real_y; /* y % 4 */
76 int i_scale_count; /* scale modulo counter */
77 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
78 uint16_t * p_pic_start; /* beginning of the current line for copy */
79 int i_uval, i_vval; /* U and V samples */
80 int i_red, i_green, i_blue; /* U and V modified samples */
81 uint16_t * p_yuv = p_filter->p_sys->p_rgb16;
82 uint16_t * p_ybase; /* Y dependant conversion table */
84 /* Conversion buffer pointer */
85 uint16_t * p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
88 /* Offset array pointer */
89 int * p_offset_start = p_filter->p_sys->p_offset;
92 const int i_source_margin = p_src->p[0].i_pitch
93 - p_src->p[0].i_visible_pitch;
94 const int i_source_margin_c = p_src->p[1].i_pitch
95 - p_src->p[1].i_visible_pitch;
97 /* The dithering matrices */
98 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
99 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
100 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
101 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
103 for(i_x = 0; i_x < 4; i_x++)
105 dither10[i_x] = dither10[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
106 dither11[i_x] = dither11[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
107 dither12[i_x] = dither12[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
108 dither13[i_x] = dither13[i_x] << (SHIFT - 4 + p_filter->fmt_out.video.i_rrshift);
111 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
113 if( p_filter->fmt_in.video.i_width & 7 )
115 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
122 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
123 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
124 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
125 SetOffset( p_filter->fmt_in.video.i_width,
126 p_filter->fmt_in.video.i_height,
127 p_filter->fmt_out.video.i_width,
128 p_filter->fmt_out.video.i_height,
129 &b_hscale, &i_vscale, p_offset_start );
134 i_scale_count = ( i_vscale == 1 ) ?
135 p_filter->fmt_out.video.i_height :
136 p_filter->fmt_in.video.i_height;
137 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
139 i_real_y = i_y & 0x3;
141 p_buffer = b_hscale ? p_buffer_start : p_pic;
143 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
145 int *p_dither = dither10;
146 CONVERT_YUV_PIXEL_DITHER(2);
148 CONVERT_Y_PIXEL_DITHER(2);
150 CONVERT_YUV_PIXEL_DITHER(2);
152 CONVERT_Y_PIXEL_DITHER(2);
154 CONVERT_YUV_PIXEL_DITHER(2);
156 CONVERT_Y_PIXEL_DITHER(2);
158 CONVERT_YUV_PIXEL_DITHER(2);
160 CONVERT_Y_PIXEL_DITHER(2);
163 /* Here we do some unaligned reads and duplicate conversions, but
164 * at least we have all the pixels */
167 int *p_dither = dither10;
169 p_u -= i_rewind >> 1;
170 p_v -= i_rewind >> 1;
171 p_buffer -= i_rewind;
172 CONVERT_YUV_PIXEL_DITHER(2);
174 CONVERT_Y_PIXEL_DITHER(2);
176 CONVERT_YUV_PIXEL_DITHER(2);
178 CONVERT_Y_PIXEL_DITHER(2);
180 CONVERT_YUV_PIXEL_DITHER(2);
182 CONVERT_Y_PIXEL_DITHER(2);
184 CONVERT_YUV_PIXEL_DITHER(2);
186 CONVERT_Y_PIXEL_DITHER(2);
189 SCALE_HEIGHT( 420, 2 );
191 p_y += i_source_margin;
194 p_u += i_source_margin_c;
195 p_v += i_source_margin_c;
201 /*****************************************************************************
202 * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp
203 *****************************************************************************
204 * Horizontal alignment needed:
205 * - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
206 * - output: 1 pixel (2 bytes), margins allowed
207 * Vertical alignment needed:
208 * - input: 2 lines (2 Y lines, 1 U/V line)
210 *****************************************************************************/
212 #if defined (MODULE_NAME_IS_i420_rgb)
214 void I420_RGB16( filter_t *p_filter, picture_t *p_src,
217 /* We got this one from the old arguments */
218 uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
219 uint8_t *p_y = p_src->Y_PIXELS;
220 uint8_t *p_u = p_src->U_PIXELS;
221 uint8_t *p_v = p_src->V_PIXELS;
223 bool b_hscale; /* horizontal scaling type */
224 unsigned int i_vscale; /* vertical scaling type */
225 unsigned int i_x, i_y; /* horizontal and vertical indexes */
229 int i_scale_count; /* scale modulo counter */
230 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
231 uint16_t * p_pic_start; /* beginning of the current line for copy */
232 int i_uval, i_vval; /* U and V samples */
233 int i_red, i_green, i_blue; /* U and V modified samples */
234 uint16_t * p_yuv = p_filter->p_sys->p_rgb16;
235 uint16_t * p_ybase; /* Y dependant conversion table */
237 /* Conversion buffer pointer */
238 uint16_t * p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
241 /* Offset array pointer */
242 int * p_offset_start = p_filter->p_sys->p_offset;
245 const int i_source_margin = p_src->p[0].i_pitch
246 - p_src->p[0].i_visible_pitch;
247 const int i_source_margin_c = p_src->p[1].i_pitch
248 - p_src->p[1].i_visible_pitch;
250 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
252 if( p_filter->fmt_in.video.i_width & 7 )
254 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
261 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
262 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
263 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
264 SetOffset( p_filter->fmt_in.video.i_width,
265 p_filter->fmt_in.video.i_height,
266 p_filter->fmt_out.video.i_width,
267 p_filter->fmt_out.video.i_height,
268 &b_hscale, &i_vscale, p_offset_start );
273 i_scale_count = ( i_vscale == 1 ) ?
274 p_filter->fmt_out.video.i_height :
275 p_filter->fmt_in.video.i_height;
276 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
279 p_buffer = b_hscale ? p_buffer_start : p_pic;
281 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
283 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
284 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
285 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
286 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
289 /* Here we do some unaligned reads and duplicate conversions, but
290 * at least we have all the pixels */
294 p_u -= i_rewind >> 1;
295 p_v -= i_rewind >> 1;
296 p_buffer -= i_rewind;
298 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
299 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
300 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
301 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
304 SCALE_HEIGHT( 420, 2 );
306 p_y += i_source_margin;
309 p_u += i_source_margin_c;
310 p_v += i_source_margin_c;
315 #else // ! defined (MODULE_NAME_IS_i420_rgb)
317 void I420_R5G5B5( filter_t *p_filter, picture_t *p_src,
320 /* We got this one from the old arguments */
321 uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
322 uint8_t *p_y = p_src->Y_PIXELS;
323 uint8_t *p_u = p_src->U_PIXELS;
324 uint8_t *p_v = p_src->V_PIXELS;
326 bool b_hscale; /* horizontal scaling type */
327 unsigned int i_vscale; /* vertical scaling type */
328 unsigned int i_x, i_y; /* horizontal and vertical indexes */
332 int i_scale_count; /* scale modulo counter */
333 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
334 uint16_t * p_pic_start; /* beginning of the current line for copy */
336 /* Conversion buffer pointer */
337 uint16_t * p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
340 /* Offset array pointer */
341 int * p_offset_start = p_filter->p_sys->p_offset;
344 const int i_source_margin = p_src->p[0].i_pitch
345 - p_src->p[0].i_visible_pitch;
346 const int i_source_margin_c = p_src->p[1].i_pitch
347 - p_src->p[1].i_visible_pitch;
349 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
351 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
352 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
353 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
354 SetOffset( p_filter->fmt_in.video.i_width,
355 p_filter->fmt_in.video.i_height,
356 p_filter->fmt_out.video.i_width,
357 p_filter->fmt_out.video.i_height,
358 &b_hscale, &i_vscale, p_offset_start );
364 i_scale_count = ( i_vscale == 1 ) ?
365 p_filter->fmt_out.video.i_height :
366 p_filter->fmt_in.video.i_height;
368 #if defined (MODULE_NAME_IS_i420_rgb_sse2)
370 if( p_filter->fmt_in.video.i_width & 15 )
372 i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
380 ** SSE2 128 bits fetch/store instructions are faster
381 ** if memory access is 16 bytes aligned
384 p_buffer = b_hscale ? p_buffer_start : p_pic;
385 if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
388 ((intptr_t)p_buffer))) )
390 /* use faster SSE2 aligned fetch and store */
391 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
395 for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
401 SSE2_UNPACK_15_ALIGNED
408 /* Here we do some unaligned reads and duplicate conversions, but
409 * at least we have all the pixels */
413 p_u -= i_rewind >> 1;
414 p_v -= i_rewind >> 1;
415 p_buffer -= i_rewind;
418 SSE2_INIT_16_UNALIGNED
421 SSE2_UNPACK_15_UNALIGNED
428 SCALE_HEIGHT( 420, 2 );
430 p_y += i_source_margin;
433 p_u += i_source_margin_c;
434 p_v += i_source_margin_c;
436 p_buffer = b_hscale ? p_buffer_start : p_pic;
441 /* use slower SSE2 unaligned fetch and store */
442 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
445 p_buffer = b_hscale ? p_buffer_start : p_pic;
447 for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
450 SSE2_INIT_16_UNALIGNED
453 SSE2_UNPACK_15_UNALIGNED
460 /* Here we do some unaligned reads and duplicate conversions, but
461 * at least we have all the pixels */
465 p_u -= i_rewind >> 1;
466 p_v -= i_rewind >> 1;
467 p_buffer -= i_rewind;
470 SSE2_INIT_16_UNALIGNED
473 SSE2_UNPACK_15_UNALIGNED
480 SCALE_HEIGHT( 420, 2 );
482 p_y += i_source_margin;
485 p_u += i_source_margin_c;
486 p_v += i_source_margin_c;
488 p_buffer = b_hscale ? p_buffer_start : p_pic;
492 /* make sure all SSE2 stores are visible thereafter */
495 #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
497 if( p_filter->fmt_in.video.i_width & 7 )
499 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
506 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
509 p_buffer = b_hscale ? p_buffer_start : p_pic;
511 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
525 /* Here we do some unaligned reads and duplicate conversions, but
526 * at least we have all the pixels */
530 p_u -= i_rewind >> 1;
531 p_v -= i_rewind >> 1;
532 p_buffer -= i_rewind;
546 SCALE_HEIGHT( 420, 2 );
548 p_y += i_source_margin;
551 p_u += i_source_margin_c;
552 p_v += i_source_margin_c;
555 /* re-enable FPU registers */
561 void I420_R5G6B5( filter_t *p_filter, picture_t *p_src,
564 /* We got this one from the old arguments */
565 uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
566 uint8_t *p_y = p_src->Y_PIXELS;
567 uint8_t *p_u = p_src->U_PIXELS;
568 uint8_t *p_v = p_src->V_PIXELS;
570 bool b_hscale; /* horizontal scaling type */
571 unsigned int i_vscale; /* vertical scaling type */
572 unsigned int i_x, i_y; /* horizontal and vertical indexes */
576 int i_scale_count; /* scale modulo counter */
577 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
578 uint16_t * p_pic_start; /* beginning of the current line for copy */
580 /* Conversion buffer pointer */
581 uint16_t * p_buffer_start = (uint16_t*)p_filter->p_sys->p_buffer;
584 /* Offset array pointer */
585 int * p_offset_start = p_filter->p_sys->p_offset;
588 const int i_source_margin = p_src->p[0].i_pitch
589 - p_src->p[0].i_visible_pitch;
590 const int i_source_margin_c = p_src->p[1].i_pitch
591 - p_src->p[1].i_visible_pitch;
593 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
595 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
596 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
597 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
598 SetOffset( p_filter->fmt_in.video.i_width,
599 p_filter->fmt_in.video.i_height,
600 p_filter->fmt_out.video.i_width,
601 p_filter->fmt_out.video.i_height,
602 &b_hscale, &i_vscale, p_offset_start );
608 i_scale_count = ( i_vscale == 1 ) ?
609 p_filter->fmt_out.video.i_height :
610 p_filter->fmt_in.video.i_height;
612 #if defined (MODULE_NAME_IS_i420_rgb_sse2)
614 if( p_filter->fmt_in.video.i_width & 15 )
616 i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
624 ** SSE2 128 bits fetch/store instructions are faster
625 ** if memory access is 16 bytes aligned
628 p_buffer = b_hscale ? p_buffer_start : p_pic;
629 if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
632 ((intptr_t)p_buffer))) )
634 /* use faster SSE2 aligned fetch and store */
635 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
639 for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
645 SSE2_UNPACK_16_ALIGNED
652 /* Here we do some unaligned reads and duplicate conversions, but
653 * at least we have all the pixels */
657 p_u -= i_rewind >> 1;
658 p_v -= i_rewind >> 1;
659 p_buffer -= i_rewind;
662 SSE2_INIT_16_UNALIGNED
665 SSE2_UNPACK_16_UNALIGNED
672 SCALE_HEIGHT( 420, 2 );
674 p_y += i_source_margin;
677 p_u += i_source_margin_c;
678 p_v += i_source_margin_c;
680 p_buffer = b_hscale ? p_buffer_start : p_pic;
685 /* use slower SSE2 unaligned fetch and store */
686 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
689 p_buffer = b_hscale ? p_buffer_start : p_pic;
691 for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
694 SSE2_INIT_16_UNALIGNED
697 SSE2_UNPACK_16_UNALIGNED
704 /* Here we do some unaligned reads and duplicate conversions, but
705 * at least we have all the pixels */
709 p_u -= i_rewind >> 1;
710 p_v -= i_rewind >> 1;
711 p_buffer -= i_rewind;
714 SSE2_INIT_16_UNALIGNED
717 SSE2_UNPACK_16_UNALIGNED
724 SCALE_HEIGHT( 420, 2 );
726 p_y += i_source_margin;
729 p_u += i_source_margin_c;
730 p_v += i_source_margin_c;
732 p_buffer = b_hscale ? p_buffer_start : p_pic;
736 /* make sure all SSE2 stores are visible thereafter */
739 #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
741 if( p_filter->fmt_in.video.i_width & 7 )
743 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
750 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
753 p_buffer = b_hscale ? p_buffer_start : p_pic;
755 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
769 /* Here we do some unaligned reads and duplicate conversions, but
770 * at least we have all the pixels */
774 p_u -= i_rewind >> 1;
775 p_v -= i_rewind >> 1;
776 p_buffer -= i_rewind;
790 SCALE_HEIGHT( 420, 2 );
792 p_y += i_source_margin;
795 p_u += i_source_margin_c;
796 p_v += i_source_margin_c;
799 /* re-enable FPU registers */
807 /*****************************************************************************
808 * I420_RGB32: color YUV 4:2:0 to RGB 32 bpp
809 *****************************************************************************
810 * Horizontal alignment needed:
811 * - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
812 * - output: 1 pixel (2 bytes), margins allowed
813 * Vertical alignment needed:
814 * - input: 2 lines (2 Y lines, 1 U/V line)
816 *****************************************************************************/
818 #if defined (MODULE_NAME_IS_i420_rgb)
820 void I420_RGB32( filter_t *p_filter, picture_t *p_src,
823 /* We got this one from the old arguments */
824 uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
825 uint8_t *p_y = p_src->Y_PIXELS;
826 uint8_t *p_u = p_src->U_PIXELS;
827 uint8_t *p_v = p_src->V_PIXELS;
829 bool b_hscale; /* horizontal scaling type */
830 unsigned int i_vscale; /* vertical scaling type */
831 unsigned int i_x, i_y; /* horizontal and vertical indexes */
835 int i_scale_count; /* scale modulo counter */
836 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
837 uint32_t * p_pic_start; /* beginning of the current line for copy */
838 int i_uval, i_vval; /* U and V samples */
839 int i_red, i_green, i_blue; /* U and V modified samples */
840 uint32_t * p_yuv = p_filter->p_sys->p_rgb32;
841 uint32_t * p_ybase; /* Y dependant conversion table */
843 /* Conversion buffer pointer */
844 uint32_t * p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
847 /* Offset array pointer */
848 int * p_offset_start = p_filter->p_sys->p_offset;
851 const int i_source_margin = p_src->p[0].i_pitch
852 - p_src->p[0].i_visible_pitch;
853 const int i_source_margin_c = p_src->p[1].i_pitch
854 - p_src->p[1].i_visible_pitch;
856 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
858 if( p_filter->fmt_in.video.i_width & 7 )
860 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
867 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
868 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
869 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
870 SetOffset( p_filter->fmt_in.video.i_width,
871 p_filter->fmt_in.video.i_height,
872 p_filter->fmt_out.video.i_width,
873 p_filter->fmt_out.video.i_height,
874 &b_hscale, &i_vscale, p_offset_start );
879 i_scale_count = ( i_vscale == 1 ) ?
880 p_filter->fmt_out.video.i_height :
881 p_filter->fmt_in.video.i_height;
882 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
885 p_buffer = b_hscale ? p_buffer_start : p_pic;
887 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
889 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
890 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
891 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
892 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
895 /* Here we do some unaligned reads and duplicate conversions, but
896 * at least we have all the pixels */
900 p_u -= i_rewind >> 1;
901 p_v -= i_rewind >> 1;
902 p_buffer -= i_rewind;
903 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
904 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
905 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
906 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
909 SCALE_HEIGHT( 420, 4 );
911 p_y += i_source_margin;
914 p_u += i_source_margin_c;
915 p_v += i_source_margin_c;
920 #else // defined (MODULE_NAME_IS_i420_rgb_mmx) || defined (MODULE_NAME_IS_i420_rgb_sse2)
922 void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
925 /* We got this one from the old arguments */
926 uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
927 uint8_t *p_y = p_src->Y_PIXELS;
928 uint8_t *p_u = p_src->U_PIXELS;
929 uint8_t *p_v = p_src->V_PIXELS;
931 bool b_hscale; /* horizontal scaling type */
932 unsigned int i_vscale; /* vertical scaling type */
933 unsigned int i_x, i_y; /* horizontal and vertical indexes */
937 int i_scale_count; /* scale modulo counter */
938 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
939 uint32_t * p_pic_start; /* beginning of the current line for copy */
940 /* Conversion buffer pointer */
941 uint32_t * p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
944 /* Offset array pointer */
945 int * p_offset_start = p_filter->p_sys->p_offset;
948 const int i_source_margin = p_src->p[0].i_pitch
949 - p_src->p[0].i_visible_pitch;
950 const int i_source_margin_c = p_src->p[1].i_pitch
951 - p_src->p[1].i_visible_pitch;
953 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
955 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
956 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
957 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
958 SetOffset( p_filter->fmt_in.video.i_width,
959 p_filter->fmt_in.video.i_height,
960 p_filter->fmt_out.video.i_width,
961 p_filter->fmt_out.video.i_height,
962 &b_hscale, &i_vscale, p_offset_start );
967 i_scale_count = ( i_vscale == 1 ) ?
968 p_filter->fmt_out.video.i_height :
969 p_filter->fmt_in.video.i_height;
971 #if defined (MODULE_NAME_IS_i420_rgb_sse2)
973 if( p_filter->fmt_in.video.i_width & 15 )
975 i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
983 ** SSE2 128 bits fetch/store instructions are faster
984 ** if memory access is 16 bytes aligned
987 p_buffer = b_hscale ? p_buffer_start : p_pic;
988 if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
991 ((intptr_t)p_buffer))) )
993 /* use faster SSE2 aligned fetch and store */
994 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
998 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1001 SSE2_INIT_32_ALIGNED
1004 SSE2_UNPACK_32_ARGB_ALIGNED
1012 /* Here we do some unaligned reads and duplicate conversions, but
1013 * at least we have all the pixels */
1017 p_u -= i_rewind >> 1;
1018 p_v -= i_rewind >> 1;
1019 p_buffer -= i_rewind;
1021 SSE2_INIT_32_UNALIGNED
1024 SSE2_UNPACK_32_ARGB_UNALIGNED
1031 SCALE_HEIGHT( 420, 4 );
1033 p_y += i_source_margin;
1036 p_u += i_source_margin_c;
1037 p_v += i_source_margin_c;
1039 p_buffer = b_hscale ? p_buffer_start : p_pic;
1044 /* use slower SSE2 unaligned fetch and store */
1045 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1047 p_pic_start = p_pic;
1048 p_buffer = b_hscale ? p_buffer_start : p_pic;
1050 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1053 SSE2_INIT_32_UNALIGNED
1056 SSE2_UNPACK_32_ARGB_UNALIGNED
1064 /* Here we do some unaligned reads and duplicate conversions, but
1065 * at least we have all the pixels */
1069 p_u -= i_rewind >> 1;
1070 p_v -= i_rewind >> 1;
1071 p_buffer -= i_rewind;
1073 SSE2_INIT_32_UNALIGNED
1076 SSE2_UNPACK_32_ARGB_UNALIGNED
1083 SCALE_HEIGHT( 420, 4 );
1085 p_y += i_source_margin;
1088 p_u += i_source_margin_c;
1089 p_v += i_source_margin_c;
1091 p_buffer = b_hscale ? p_buffer_start : p_pic;
1095 /* make sure all SSE2 stores are visible thereafter */
1098 #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
1100 if( p_filter->fmt_in.video.i_width & 7 )
1102 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
1109 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1111 p_pic_start = p_pic;
1112 p_buffer = b_hscale ? p_buffer_start : p_pic;
1114 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
1128 /* Here we do some unaligned reads and duplicate conversions, but
1129 * at least we have all the pixels */
1133 p_u -= i_rewind >> 1;
1134 p_v -= i_rewind >> 1;
1135 p_buffer -= i_rewind;
1148 SCALE_HEIGHT( 420, 4 );
1150 p_y += i_source_margin;
1153 p_u += i_source_margin_c;
1154 p_v += i_source_margin_c;
1158 /* re-enable FPU registers */
1164 void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src,
1167 /* We got this one from the old arguments */
1168 uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
1169 uint8_t *p_y = p_src->Y_PIXELS;
1170 uint8_t *p_u = p_src->U_PIXELS;
1171 uint8_t *p_v = p_src->V_PIXELS;
1173 bool b_hscale; /* horizontal scaling type */
1174 unsigned int i_vscale; /* vertical scaling type */
1175 unsigned int i_x, i_y; /* horizontal and vertical indexes */
1179 int i_scale_count; /* scale modulo counter */
1180 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
1181 uint32_t * p_pic_start; /* beginning of the current line for copy */
1182 /* Conversion buffer pointer */
1183 uint32_t * p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
1184 uint32_t * p_buffer;
1186 /* Offset array pointer */
1187 int * p_offset_start = p_filter->p_sys->p_offset;
1190 const int i_source_margin = p_src->p[0].i_pitch
1191 - p_src->p[0].i_visible_pitch;
1192 const int i_source_margin_c = p_src->p[1].i_pitch
1193 - p_src->p[1].i_visible_pitch;
1195 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
1197 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
1198 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
1199 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
1200 SetOffset( p_filter->fmt_in.video.i_width,
1201 p_filter->fmt_in.video.i_height,
1202 p_filter->fmt_out.video.i_width,
1203 p_filter->fmt_out.video.i_height,
1204 &b_hscale, &i_vscale, p_offset_start );
1207 * Perform conversion
1209 i_scale_count = ( i_vscale == 1 ) ?
1210 p_filter->fmt_out.video.i_height :
1211 p_filter->fmt_in.video.i_height;
1213 #if defined (MODULE_NAME_IS_i420_rgb_sse2)
1215 if( p_filter->fmt_in.video.i_width & 15 )
1217 i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
1225 ** SSE2 128 bits fetch/store instructions are faster
1226 ** if memory access is 16 bytes aligned
1229 p_buffer = b_hscale ? p_buffer_start : p_pic;
1230 if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
1233 ((intptr_t)p_buffer))) )
1235 /* use faster SSE2 aligned fetch and store */
1236 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1238 p_pic_start = p_pic;
1240 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1243 SSE2_INIT_32_ALIGNED
1246 SSE2_UNPACK_32_RGBA_ALIGNED
1254 /* Here we do some unaligned reads and duplicate conversions, but
1255 * at least we have all the pixels */
1259 p_u -= i_rewind >> 1;
1260 p_v -= i_rewind >> 1;
1261 p_buffer -= i_rewind;
1263 SSE2_INIT_32_UNALIGNED
1266 SSE2_UNPACK_32_RGBA_UNALIGNED
1273 SCALE_HEIGHT( 420, 4 );
1275 p_y += i_source_margin;
1278 p_u += i_source_margin_c;
1279 p_v += i_source_margin_c;
1281 p_buffer = b_hscale ? p_buffer_start : p_pic;
1286 /* use slower SSE2 unaligned fetch and store */
1287 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1289 p_pic_start = p_pic;
1290 p_buffer = b_hscale ? p_buffer_start : p_pic;
1292 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1295 SSE2_INIT_32_UNALIGNED
1298 SSE2_UNPACK_32_RGBA_UNALIGNED
1306 /* Here we do some unaligned reads and duplicate conversions, but
1307 * at least we have all the pixels */
1311 p_u -= i_rewind >> 1;
1312 p_v -= i_rewind >> 1;
1313 p_buffer -= i_rewind;
1315 SSE2_INIT_32_UNALIGNED
1318 SSE2_UNPACK_32_RGBA_UNALIGNED
1325 SCALE_HEIGHT( 420, 4 );
1327 p_y += i_source_margin;
1330 p_u += i_source_margin_c;
1331 p_v += i_source_margin_c;
1333 p_buffer = b_hscale ? p_buffer_start : p_pic;
1337 /* make sure all SSE2 stores are visible thereafter */
1340 #else // defined (MODULE_NAME_IS_i420_rgb_mmx)
1342 if( p_filter->fmt_in.video.i_width & 7 )
1344 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
1351 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1353 p_pic_start = p_pic;
1354 p_buffer = b_hscale ? p_buffer_start : p_pic;
1356 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
1370 /* Here we do some unaligned reads and duplicate conversions, but
1371 * at least we have all the pixels */
1375 p_u -= i_rewind >> 1;
1376 p_v -= i_rewind >> 1;
1377 p_buffer -= i_rewind;
1390 SCALE_HEIGHT( 420, 4 );
1392 p_y += i_source_margin;
1395 p_u += i_source_margin_c;
1396 p_v += i_source_margin_c;
1400 /* re-enable FPU registers */
1406 void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src,
1409 /* We got this one from the old arguments */
1410 uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
1411 uint8_t *p_y = p_src->Y_PIXELS;
1412 uint8_t *p_u = p_src->U_PIXELS;
1413 uint8_t *p_v = p_src->V_PIXELS;
1415 bool b_hscale; /* horizontal scaling type */
1416 unsigned int i_vscale; /* vertical scaling type */
1417 unsigned int i_x, i_y; /* horizontal and vertical indexes */
1421 int i_scale_count; /* scale modulo counter */
1422 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
1423 uint32_t * p_pic_start; /* beginning of the current line for copy */
1424 /* Conversion buffer pointer */
1425 uint32_t * p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
1426 uint32_t * p_buffer;
1428 /* Offset array pointer */
1429 int * p_offset_start = p_filter->p_sys->p_offset;
1432 const int i_source_margin = p_src->p[0].i_pitch
1433 - p_src->p[0].i_visible_pitch;
1434 const int i_source_margin_c = p_src->p[1].i_pitch
1435 - p_src->p[1].i_visible_pitch;
1437 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
1439 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
1440 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
1441 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
1442 SetOffset( p_filter->fmt_in.video.i_width,
1443 p_filter->fmt_in.video.i_height,
1444 p_filter->fmt_out.video.i_width,
1445 p_filter->fmt_out.video.i_height,
1446 &b_hscale, &i_vscale, p_offset_start );
1449 * Perform conversion
1451 i_scale_count = ( i_vscale == 1 ) ?
1452 p_filter->fmt_out.video.i_height :
1453 p_filter->fmt_in.video.i_height;
1455 #if defined (MODULE_NAME_IS_i420_rgb_sse2)
1457 if( p_filter->fmt_in.video.i_width & 15 )
1459 i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
1467 ** SSE2 128 bits fetch/store instructions are faster
1468 ** if memory access is 16 bytes aligned
1471 p_buffer = b_hscale ? p_buffer_start : p_pic;
1472 if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
1475 ((intptr_t)p_buffer))) )
1477 /* use faster SSE2 aligned fetch and store */
1478 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1480 p_pic_start = p_pic;
1482 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1485 SSE2_INIT_32_ALIGNED
1488 SSE2_UNPACK_32_BGRA_ALIGNED
1496 /* Here we do some unaligned reads and duplicate conversions, but
1497 * at least we have all the pixels */
1501 p_u -= i_rewind >> 1;
1502 p_v -= i_rewind >> 1;
1503 p_buffer -= i_rewind;
1505 SSE2_INIT_32_UNALIGNED
1508 SSE2_UNPACK_32_BGRA_UNALIGNED
1515 SCALE_HEIGHT( 420, 4 );
1517 p_y += i_source_margin;
1520 p_u += i_source_margin_c;
1521 p_v += i_source_margin_c;
1523 p_buffer = b_hscale ? p_buffer_start : p_pic;
1528 /* use slower SSE2 unaligned fetch and store */
1529 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1531 p_pic_start = p_pic;
1532 p_buffer = b_hscale ? p_buffer_start : p_pic;
1534 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1537 SSE2_INIT_32_UNALIGNED
1540 SSE2_UNPACK_32_BGRA_UNALIGNED
1548 /* Here we do some unaligned reads and duplicate conversions, but
1549 * at least we have all the pixels */
1553 p_u -= i_rewind >> 1;
1554 p_v -= i_rewind >> 1;
1555 p_buffer -= i_rewind;
1557 SSE2_INIT_32_UNALIGNED
1560 SSE2_UNPACK_32_BGRA_UNALIGNED
1567 SCALE_HEIGHT( 420, 4 );
1569 p_y += i_source_margin;
1572 p_u += i_source_margin_c;
1573 p_v += i_source_margin_c;
1575 p_buffer = b_hscale ? p_buffer_start : p_pic;
1581 if( p_filter->fmt_in.video.i_width & 7 )
1583 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
1590 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1592 p_pic_start = p_pic;
1593 p_buffer = b_hscale ? p_buffer_start : p_pic;
1595 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
1609 /* Here we do some unaligned reads and duplicate conversions, but
1610 * at least we have all the pixels */
1614 p_u -= i_rewind >> 1;
1615 p_v -= i_rewind >> 1;
1616 p_buffer -= i_rewind;
1629 SCALE_HEIGHT( 420, 4 );
1631 p_y += i_source_margin;
1634 p_u += i_source_margin_c;
1635 p_v += i_source_margin_c;
1639 /* re-enable FPU registers */
1645 void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src,
1648 /* We got this one from the old arguments */
1649 uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
1650 uint8_t *p_y = p_src->Y_PIXELS;
1651 uint8_t *p_u = p_src->U_PIXELS;
1652 uint8_t *p_v = p_src->V_PIXELS;
1654 bool b_hscale; /* horizontal scaling type */
1655 unsigned int i_vscale; /* vertical scaling type */
1656 unsigned int i_x, i_y; /* horizontal and vertical indexes */
1660 int i_scale_count; /* scale modulo counter */
1661 int i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
1662 uint32_t * p_pic_start; /* beginning of the current line for copy */
1663 /* Conversion buffer pointer */
1664 uint32_t * p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
1665 uint32_t * p_buffer;
1667 /* Offset array pointer */
1668 int * p_offset_start = p_filter->p_sys->p_offset;
1671 const int i_source_margin = p_src->p[0].i_pitch
1672 - p_src->p[0].i_visible_pitch;
1673 const int i_source_margin_c = p_src->p[1].i_pitch
1674 - p_src->p[1].i_visible_pitch;
1676 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
1678 /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
1679 * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
1680 * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
1681 SetOffset( p_filter->fmt_in.video.i_width,
1682 p_filter->fmt_in.video.i_height,
1683 p_filter->fmt_out.video.i_width,
1684 p_filter->fmt_out.video.i_height,
1685 &b_hscale, &i_vscale, p_offset_start );
1688 * Perform conversion
1690 i_scale_count = ( i_vscale == 1 ) ?
1691 p_filter->fmt_out.video.i_height :
1692 p_filter->fmt_in.video.i_height;
1694 #if defined (MODULE_NAME_IS_i420_rgb_sse2)
1696 if( p_filter->fmt_in.video.i_width & 15 )
1698 i_rewind = 16 - ( p_filter->fmt_in.video.i_width & 15 );
1706 ** SSE2 128 bits fetch/store instructions are faster
1707 ** if memory access is 16 bytes aligned
1710 p_buffer = b_hscale ? p_buffer_start : p_pic;
1711 if( 0 == (15 & (p_src->p[Y_PLANE].i_pitch|
1714 ((intptr_t)p_buffer))) )
1716 /* use faster SSE2 aligned fetch and store */
1717 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1719 p_pic_start = p_pic;
1721 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1724 SSE2_INIT_32_ALIGNED
1727 SSE2_UNPACK_32_ABGR_ALIGNED
1735 /* Here we do some unaligned reads and duplicate conversions, but
1736 * at least we have all the pixels */
1740 p_u -= i_rewind >> 1;
1741 p_v -= i_rewind >> 1;
1742 p_buffer -= i_rewind;
1744 SSE2_INIT_32_UNALIGNED
1747 SSE2_UNPACK_32_ABGR_UNALIGNED
1754 SCALE_HEIGHT( 420, 4 );
1756 p_y += i_source_margin;
1759 p_u += i_source_margin_c;
1760 p_v += i_source_margin_c;
1762 p_buffer = b_hscale ? p_buffer_start : p_pic;
1767 /* use slower SSE2 unaligned fetch and store */
1768 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1770 p_pic_start = p_pic;
1771 p_buffer = b_hscale ? p_buffer_start : p_pic;
1773 for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
1776 SSE2_INIT_32_UNALIGNED
1779 SSE2_UNPACK_32_ABGR_UNALIGNED
1787 /* Here we do some unaligned reads and duplicate conversions, but
1788 * at least we have all the pixels */
1792 p_u -= i_rewind >> 1;
1793 p_v -= i_rewind >> 1;
1794 p_buffer -= i_rewind;
1796 SSE2_INIT_32_UNALIGNED
1799 SSE2_UNPACK_32_ABGR_UNALIGNED
1806 SCALE_HEIGHT( 420, 4 );
1808 p_y += i_source_margin;
1811 p_u += i_source_margin_c;
1812 p_v += i_source_margin_c;
1814 p_buffer = b_hscale ? p_buffer_start : p_pic;
1820 if( p_filter->fmt_in.video.i_width & 7 )
1822 i_rewind = 8 - ( p_filter->fmt_in.video.i_width & 7 );
1829 for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
1831 p_pic_start = p_pic;
1832 p_buffer = b_hscale ? p_buffer_start : p_pic;
1834 for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
1848 /* Here we do some unaligned reads and duplicate conversions, but
1849 * at least we have all the pixels */
1853 p_u -= i_rewind >> 1;
1854 p_v -= i_rewind >> 1;
1855 p_buffer -= i_rewind;
1868 SCALE_HEIGHT( 420, 4 );
1870 p_y += i_source_margin;
1873 p_u += i_source_margin_c;
1874 p_v += i_source_margin_c;
1878 /* re-enable FPU registers */
1886 /* Following functions are local */
1888 /*****************************************************************************
1889 * SetOffset: build offset array for conversion functions
1890 *****************************************************************************
1891 * This function will build an offset array used in later conversion functions.
1892 * It will also set horizontal and vertical scaling indicators.
1893 *****************************************************************************/
1894 static void SetOffset( int i_width, int i_height, int i_pic_width,
1895 int i_pic_height, bool *pb_hscale,
1896 unsigned int *pi_vscale, int *p_offset )
1898 int i_x; /* x position in destination */
1899 int i_scale_count; /* modulo counter */
1902 * Prepare horizontal offset array
1904 if( i_pic_width - i_width == 0 )
1906 /* No horizontal scaling: YUV conversion is done directly to picture */
1909 else if( i_pic_width - i_width > 0 )
1911 /* Prepare scaling array for horizontal extension */
1913 i_scale_count = i_pic_width;
1914 for( i_x = i_width; i_x--; )
1916 while( (i_scale_count -= i_width) > 0 )
1921 i_scale_count += i_pic_width;
1924 else /* if( i_pic_width - i_width < 0 ) */
1926 /* Prepare scaling array for horizontal reduction */
1928 i_scale_count = i_width;
1929 for( i_x = i_pic_width; i_x--; )
1932 while( (i_scale_count -= i_pic_width) > 0 )
1937 i_scale_count += i_width;
1942 * Set vertical scaling indicator
1944 if( i_pic_height - i_height == 0 )
1948 else if( i_pic_height - i_height > 0 )
1952 else /* if( i_pic_height - i_height < 0 ) */