MythTV  master
color.c
Go to the documentation of this file.
1 /*
2  * Taken from Xine Project (color.c) for mythtv-greedyHighMotion Deinterlacer
3  * Copyright (C) 2000-2003 the xine project
4  *
5  * This file is part of xine, a free video player.
6  *
7  * xine is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * xine is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  *
22  */
23 
24 #include "config.h"
25 
26 #include <string.h>
27 #include <stdlib.h>
28 #if HAVE_STDINT_H
29 #include <stdint.h>
30 #endif
31 #include <math.h>
32 
33 #include "libavutil/mem.h"
34 #include "libavutil/cpu.h"
35 
36 #include "color.h"
37 
38 #if HAVE_MMX
39 #include "ffmpeg-mmx.h"
40 #endif
41 
42 void (*yv12_to_yuy2)
43  (const unsigned char *y_src, int y_src_pitch,
44  const unsigned char *u_src, int u_src_pitch,
45  const unsigned char *v_src, int v_src_pitch,
46  unsigned char *yuy2_map, int yuy2_pitch,
47  int width, int height, int progressive);
48 
49 void (*yuy2_to_yv12)
50  (const unsigned char *yuy2_map, int yuy2_pitch,
51  unsigned char *y_dst, int y_dst_pitch,
52  unsigned char *u_dst, int u_dst_pitch,
53  unsigned char *v_dst, int v_dst_pitch,
54  int width, int height);
55 
56 void (*vfilter_chroma_332_packed422_scanline)( uint8_t *output, int width, uint8_t *m, uint8_t *t, uint8_t *b );
57 
58 
59 #define C_YUV420_YUYV( ) \
60  *p_line1++ = *p_y1++; *p_line2++ = *p_y2++; \
61 *p_line1++ = *p_u; *p_line2++ = (*p_u++ + *p_u2++)>>1; \
62 *p_line1++ = *p_y1++; *p_line2++ = *p_y2++; \
63 *p_line1++ = *p_v; *p_line2++ = (*p_v++ + *p_v2++)>>1;
64 
65 /*****************************************************************************
66  * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
67  * original conversion routine from Videolan project
68  * changed to support interlaced frames and use simple mean interpolation [MF]
69  *****************************************************************************/
70 static void yv12_to_yuy2_c
71 (const unsigned char *y_src, int y_src_pitch,
72  const unsigned char *u_src, int u_src_pitch,
73  const unsigned char *v_src, int v_src_pitch,
74  unsigned char *yuy2_map, int yuy2_pitch,
75  int width, int height, int progressive)
76 {
77 
78  uint8_t *p_line1, *p_line2 = yuy2_map;
79  const uint8_t *p_y1, *p_y2 = y_src;
80  const uint8_t *p_u = u_src;
81  const uint8_t *p_v = v_src;
82  const uint8_t *p_u2 = u_src + u_src_pitch;
83  const uint8_t *p_v2 = v_src + v_src_pitch;
84 
85  int i_x, i_y;
86 
87  const int i_source_margin = y_src_pitch - width;
88  const int i_source_u_margin = u_src_pitch - width/2;
89  const int i_source_v_margin = v_src_pitch - width/2;
90  const int i_dest_margin = yuy2_pitch - width*2;
91 
92 
93  if ( progressive )
94  {
95  for ( i_y = height / 2 ; i_y-- ; )
96  {
97  p_line1 = p_line2;
98  p_line2 += yuy2_pitch;
99 
100  p_y1 = p_y2;
101  p_y2 += y_src_pitch;
102 
103  for ( i_x = width / 2 ; i_x-- ; )
104  {
105  C_YUV420_YUYV( );
106  }
107 
108  p_y2 += i_source_margin;
109  p_u += i_source_u_margin;
110  p_v += i_source_v_margin;
111  if ( i_y > 1 )
112  {
113  p_u2 += i_source_u_margin;
114  p_v2 += i_source_v_margin;
115  }
116  else
117  {
118  p_u2 = p_u;
119  p_v2 = p_v;
120  }
121  p_line2 += i_dest_margin;
122  }
123  }
124  else
125  {
126  p_u2 = u_src + 2*u_src_pitch;
127  p_v2 = v_src + 2*v_src_pitch;
128  for ( i_y = height / 4 ; i_y-- ; )
129  {
130  p_line1 = p_line2;
131  p_line2 += 2 * yuy2_pitch;
132 
133  p_y1 = p_y2;
134  p_y2 += 2 * y_src_pitch;
135 
136  for ( i_x = width / 2 ; i_x-- ; )
137  {
138  C_YUV420_YUYV( );
139  }
140 
141  p_y2 += i_source_margin + y_src_pitch;
142  p_u += i_source_u_margin + u_src_pitch;
143  p_v += i_source_v_margin + v_src_pitch;
144  if ( i_y > 1 )
145  {
146  p_u2 += i_source_u_margin + u_src_pitch;
147  p_v2 += i_source_v_margin + v_src_pitch;
148  }
149  else
150  {
151  p_u2 = p_u;
152  p_v2 = p_v;
153  }
154  p_line2 += i_dest_margin + yuy2_pitch;
155  }
156 
157  p_line2 = yuy2_map + yuy2_pitch;
158  p_y2 = y_src + y_src_pitch;
159  p_u = u_src + u_src_pitch;
160  p_v = v_src + v_src_pitch;
161  p_u2 = u_src + 3*u_src_pitch;
162  p_v2 = v_src + 3*v_src_pitch;
163 
164  for ( i_y = height / 4 ; i_y-- ; )
165  {
166  p_line1 = p_line2;
167  p_line2 += 2 * yuy2_pitch;
168 
169  p_y1 = p_y2;
170  p_y2 += 2 * y_src_pitch;
171 
172  for ( i_x = width / 2 ; i_x-- ; )
173  {
174  C_YUV420_YUYV( );
175  }
176 
177  p_y2 += i_source_margin + y_src_pitch;
178  p_u += i_source_u_margin + u_src_pitch;
179  p_v += i_source_v_margin + v_src_pitch;
180  if ( i_y > 1 )
181  {
182  p_u2 += i_source_u_margin + u_src_pitch;
183  p_v2 += i_source_v_margin + v_src_pitch;
184  }
185  else
186  {
187  p_u2 = p_u;
188  p_v2 = p_v;
189  }
190  p_line2 += i_dest_margin + yuy2_pitch;
191  }
192  }
193 }
194 
195 
196 #if HAVE_MMX
197 
198 #define MMXEXT_YUV420_YUYV( ) \
199  do { \
200  __asm__ __volatile__(".align 8 \n\t" \
201  "movq (%0), %%mm0 \n\t" /* Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 */ \
202  "movd (%1), %%mm1 \n\t" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */ \
203  "movd (%2), %%mm2 \n\t" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */ \
204  "punpcklbw %%mm2, %%mm1 \n\t" /* v3 u3 v2 u2 v1 u1 v0 u0 */ \
205  "movq %%mm0, %%mm2 \n\t" /* y7 y6 y5 y4 y3 y2 y1 y0 */ \
206  "punpcklbw %%mm1, %%mm2 \n\t" /* v1 y3 u1 y2 v0 y1 u0 y0 */ \
207  : \
208  : "r" (p_y1), "r" (p_u), "r" (p_v) ); \
209  __asm__ __volatile__( \
210  "movd (%0), %%mm3 \n\t" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */ \
211  "movd (%1), %%mm4 \n\t" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */ \
212  "punpcklbw %%mm4, %%mm3 \n\t" /* v3 u3 v2 u2 v1 u1 v0 u0 */ \
213  "pavgb %%mm1, %%mm3 \n\t" /* (mean) v3 u3 v2 u2 v1 u1 v0 u0 */ \
214  : \
215  : "r" (p_u2), "r" (p_v2) ); \
216  __asm__ __volatile__( \
217  "movntq %%mm2, (%0) \n\t" /* Store low YUYV */ \
218  "punpckhbw %%mm1, %%mm0 \n\t" /* v3 y7 u3 y6 v2 y5 u2 y4 */ \
219  "movntq %%mm0, 8(%0) \n\t" /* Store high YUYV */ \
220  "movq (%2), %%mm0 \n\t" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */ \
221  "movq %%mm0, %%mm2 \n\t" /* Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */ \
222  "punpcklbw %%mm3, %%mm2 \n\t" /* v1 Y3 u1 Y2 v0 Y1 u0 Y0 */ \
223  "movntq %%mm2, (%1) \n\t" /* Store low YUYV */ \
224  "punpckhbw %%mm3, %%mm0 \n\t" /* v3 Y7 u3 Y6 v2 Y5 u2 Y4 */ \
225  "movntq %%mm0, 8(%1) \n\t" /* Store high YUYV */ \
226  : \
227  : "r" (p_line1), "r" (p_line2), "r" (p_y2) ); \
228  p_line1 += 16; p_line2 += 16; p_y1 += 8; p_y2 += 8; p_u += 4; p_v += 4; \
229  p_u2 += 4; p_v2 += 4; \
230  } while(0)
231 
232 #endif
233 
234 #if HAVE_MMX
235 static void yv12_to_yuy2_mmxext
236 (const unsigned char *y_src, int y_src_pitch,
237  const unsigned char *u_src, int u_src_pitch,
238  const unsigned char *v_src, int v_src_pitch,
239  unsigned char *yuy2_map, int yuy2_pitch,
240  int width, int height, int progressive )
241 {
242  uint8_t *p_line1, *p_line2 = yuy2_map;
243  const uint8_t *p_y1, *p_y2 = y_src;
244  const uint8_t *p_u = u_src;
245  const uint8_t *p_v = v_src;
246  const uint8_t *p_u2 = u_src + u_src_pitch;
247  const uint8_t *p_v2 = v_src + v_src_pitch;
248 
249  int i_x, i_y;
250 
251  const int i_source_margin = y_src_pitch - width;
252  const int i_source_u_margin = u_src_pitch - width/2;
253  const int i_source_v_margin = v_src_pitch - width/2;
254  const int i_dest_margin = yuy2_pitch - width*2;
255 
256  if ( progressive )
257  {
258  for ( i_y = height / 2; i_y-- ; )
259  {
260  p_line1 = p_line2;
261  p_line2 += yuy2_pitch;
262 
263  p_y1 = p_y2;
264  p_y2 += y_src_pitch;
265 
266  for ( i_x = width / 8 ; i_x-- ; )
267  {
268  MMXEXT_YUV420_YUYV( );
269  }
270  for ( i_x = (width % 8) / 2 ; i_x-- ; )
271  {
272  C_YUV420_YUYV( );
273  }
274 
275  p_y2 += i_source_margin;
276  p_u += i_source_u_margin;
277  p_v += i_source_v_margin;
278  if ( i_y > 1 )
279  {
280  p_u2 += i_source_u_margin;
281  p_v2 += i_source_v_margin;
282  }
283  else
284  {
285  p_u2 = p_u;
286  p_v2 = p_v;
287  }
288  p_line2 += i_dest_margin;
289  }
290  }
291  else
292  {
293  p_u2 = u_src + 2*u_src_pitch;
294  p_v2 = v_src + 2*v_src_pitch;
295  for ( i_y = height / 4 ; i_y-- ; )
296  {
297  p_line1 = p_line2;
298  p_line2 += 2 * yuy2_pitch;
299 
300  p_y1 = p_y2;
301  p_y2 += 2 * y_src_pitch;
302 
303  for ( i_x = width / 8 ; i_x-- ; )
304  {
305  MMXEXT_YUV420_YUYV( );
306  }
307  for ( i_x = (width % 8) / 2 ; i_x-- ; )
308  {
309  C_YUV420_YUYV( );
310  }
311 
312  p_y2 += i_source_margin + y_src_pitch;
313  p_u += i_source_u_margin + u_src_pitch;
314  p_v += i_source_v_margin + v_src_pitch;
315  if ( i_y > 1 )
316  {
317  p_u2 += i_source_u_margin + u_src_pitch;
318  p_v2 += i_source_v_margin + v_src_pitch;
319  }
320  else
321  {
322  p_u2 = p_u;
323  p_v2 = p_v;
324  }
325  p_line2 += i_dest_margin + yuy2_pitch;
326  }
327 
328  p_line2 = yuy2_map + yuy2_pitch;
329  p_y2 = y_src + y_src_pitch;
330  p_u = u_src + u_src_pitch;
331  p_v = v_src + v_src_pitch;
332  p_u2 = u_src + 3*u_src_pitch;
333  p_v2 = v_src + 3*v_src_pitch;
334 
335  for ( i_y = height / 4 ; i_y-- ; )
336  {
337  p_line1 = p_line2;
338  p_line2 += 2 * yuy2_pitch;
339 
340  p_y1 = p_y2;
341  p_y2 += 2 * y_src_pitch;
342 
343  for ( i_x = width / 8 ; i_x-- ; )
344  {
345  MMXEXT_YUV420_YUYV( );
346  }
347  for ( i_x = (width % 8) / 2 ; i_x-- ; )
348  {
349  C_YUV420_YUYV( );
350  }
351 
352  p_y2 += i_source_margin + y_src_pitch;
353  p_u += i_source_u_margin + u_src_pitch;
354  p_v += i_source_v_margin + v_src_pitch;
355  if ( i_y > 1 )
356  {
357  p_u2 += i_source_u_margin + u_src_pitch;
358  p_v2 += i_source_v_margin + v_src_pitch;
359  }
360  else
361  {
362  p_u2 = p_u;
363  p_v2 = p_v;
364  }
365  p_line2 += i_dest_margin + yuy2_pitch;
366  }
367  }
368 
369  sfence();
370  emms();
371 }
372 #endif
373 
374 #define C_YUYV_YUV420( ) \
375  *p_y1++ = *p_line1++; *p_y2++ = *p_line2++; \
376 *p_u++ = (*p_line1++ + *p_line2++)>>1; \
377 *p_y1++ = *p_line1++; *p_y2++ = *p_line2++; \
378 *p_v++ = (*p_line1++ + *p_line2++)>>1;
379 
380 static void yuy2_to_yv12_c
381 (const unsigned char *yuy2_map, int yuy2_pitch,
382  unsigned char *y_dst, int y_dst_pitch,
383  unsigned char *u_dst, int u_dst_pitch,
384  unsigned char *v_dst, int v_dst_pitch,
385  int width, int height)
386 {
387 
388  const uint8_t *p_line2 = yuy2_map;
389  uint8_t *p_y2 = y_dst;
390  uint8_t *p_u = u_dst;
391  uint8_t *p_v = v_dst;
392 
393  int i_x, i_y;
394 
395  const int i_dest_margin = y_dst_pitch - width;
396  const int i_dest_u_margin = u_dst_pitch - width/2;
397  const int i_dest_v_margin = v_dst_pitch - width/2;
398  const int i_source_margin = yuy2_pitch - width*2;
399 
400 
401  for ( i_y = height / 2 ; i_y-- ; )
402  {
403  const uint8_t *p_line1 = p_line2;
404  p_line2 += yuy2_pitch;
405 
406  uint8_t *p_y1 = p_y2;
407  p_y2 += y_dst_pitch;
408 
409  for ( i_x = width / 8 ; i_x-- ; )
410  {
411  C_YUYV_YUV420( );
412  C_YUYV_YUV420( );
413  C_YUYV_YUV420( );
414  C_YUYV_YUV420( );
415  }
416 
417  p_y2 += i_dest_margin;
418  p_u += i_dest_u_margin;
419  p_v += i_dest_v_margin;
420  p_line2 += i_source_margin;
421  }
422 }
423 
424 
425 #if HAVE_MMX
426 
427 /* yuy2->yv12 with subsampling (some ideas from mplayer's yuy2toyv12) */
428 #define MMXEXT_YUYV_YUV420( ) \
429  do { \
430  __asm__ __volatile__(".align 8 \n\t" \
431  "movq (%0), %%mm0 \n\t" /* Load v1 y3 u1 y2 v0 y1 u0 y0 */ \
432  "movq 8(%0), %%mm1 \n\t" /* Load v3 y7 u3 y6 v2 y5 u2 y4 */ \
433  "movq %%mm0, %%mm2 \n\t" /* v1 y3 u1 y2 v0 y1 u0 y0 */ \
434  "movq %%mm1, %%mm3 \n\t" /* v3 y7 u3 y6 v2 y5 u2 y4 */ \
435  "psrlw $8, %%mm0 \n\t" /* 00 v1 00 u1 00 v0 00 u0 */ \
436  "psrlw $8, %%mm1 \n\t" /* 00 v3 00 u3 00 v2 00 u2 */ \
437  "pand %%mm7, %%mm2 \n\t" /* 00 y3 00 y2 00 y1 00 y0 */ \
438  "pand %%mm7, %%mm3 \n\t" /* 00 y7 00 y6 00 y5 00 y4 */ \
439  "packuswb %%mm1, %%mm0 \n\t" /* v3 u3 v2 u2 v1 u1 v0 u0 */ \
440  "packuswb %%mm3, %%mm2 \n\t" /* y7 y6 y5 y4 y3 y2 y1 y0 */ \
441  "movntq %%mm2, (%1) \n\t" /* Store YYYYYYYY line1 */ \
442  : \
443  : "r" (p_line1), "r" (p_y1) ); \
444  __asm__ __volatile__(".align 8 \n\t" \
445  "movq (%0), %%mm1 \n\t" /* Load v1 y3 u1 y2 v0 y1 u0 y0 */ \
446  "movq 8(%0), %%mm2 \n\t" /* Load v3 y7 u3 y6 v2 y5 u2 y4 */ \
447  "movq %%mm1, %%mm3 \n\t" /* v1 y3 u1 y2 v0 y1 u0 y0 */ \
448  "movq %%mm2, %%mm4 \n\t" /* v3 y7 u3 y6 v2 y5 u2 y4 */ \
449  "psrlw $8, %%mm1 \n\t" /* 00 v1 00 u1 00 v0 00 u0 */ \
450  "psrlw $8, %%mm2 \n\t" /* 00 v3 00 u3 00 v2 00 u2 */ \
451  "pand %%mm7, %%mm3 \n\t" /* 00 y3 00 y2 00 y1 00 y0 */ \
452  "pand %%mm7, %%mm4 \n\t" /* 00 y7 00 y6 00 y5 00 y4 */ \
453  "packuswb %%mm2, %%mm1 \n\t" /* v3 u3 v2 u2 v1 u1 v0 u0 */ \
454  "packuswb %%mm4, %%mm3 \n\t" /* y7 y6 y5 y4 y3 y2 y1 y0 */ \
455  "movntq %%mm3, (%1) \n\t" /* Store YYYYYYYY line2 */ \
456  : \
457  : "r" (p_line2), "r" (p_y2) ); \
458  __asm__ __volatile__( \
459  "pavgb %%mm1, %%mm0 \n\t" /* (mean) v3 u3 v2 u2 v1 u1 v0 u0 */ \
460  "movq %%mm0, %%mm1 \n\t" /* v3 u3 v2 u2 v1 u1 v0 u0 */ \
461  "psrlw $8, %%mm0 \n\t" /* 00 v3 00 v2 00 v1 00 v0 */ \
462  "packuswb %%mm0, %%mm0 \n\t" /* v3 v2 v1 v0 */ \
463  "movd %%mm0, (%0) \n\t" /* Store VVVV */ \
464  "pand %%mm7, %%mm1 \n\t" /* 00 u3 00 u2 00 u1 00 u0 */ \
465  "packuswb %%mm1, %%mm1 \n\t" /* u3 u2 u1 u0 */ \
466  "movd %%mm1, (%1) \n\t" /* Store UUUU */ \
467  : \
468  : "r" (p_v), "r" (p_u) ); \
469  p_line1 += 16; p_line2 += 16; p_y1 += 8; p_y2 += 8; p_u += 4; p_v += 4; \
470  } while(0)
471 
472 #endif
473 
474 #if HAVE_MMX
475 static void yuy2_to_yv12_mmxext
476 (const unsigned char *yuy2_map, int yuy2_pitch,
477  unsigned char *y_dst, int y_dst_pitch,
478  unsigned char *u_dst, int u_dst_pitch,
479  unsigned char *v_dst, int v_dst_pitch,
480  int width, int height)
481 {
482  const uint8_t *p_line2 = yuy2_map;
483  uint8_t *p_y2 = y_dst;
484  uint8_t *p_u = u_dst;
485  uint8_t *p_v = v_dst;
486 
487  int i_x, i_y;
488 
489  const int i_dest_margin = y_dst_pitch - width;
490  const int i_dest_u_margin = u_dst_pitch - width/2;
491  const int i_dest_v_margin = v_dst_pitch - width/2;
492  const int i_source_margin = yuy2_pitch - width*2;
493 
494  __asm__ __volatile__(
495  "pcmpeqw %mm7, %mm7 \n\t"
496  "psrlw $8, %mm7 \n\t" /* 00 ff 00 ff 00 ff 00 ff */
497  );
498 
499  for ( i_y = height / 2 ; i_y-- ; )
500  {
501  const uint8_t *p_line1 = p_line2;
502  p_line2 += yuy2_pitch;
503 
504  uint8_t *p_y1 = p_y2;
505  p_y2 += y_dst_pitch;
506 
507  for ( i_x = width / 8 ; i_x-- ; )
508  {
509  MMXEXT_YUYV_YUV420( );
510  }
511 
512  p_y2 += i_dest_margin;
513  p_u += i_dest_u_margin;
514  p_v += i_dest_v_margin;
515  p_line2 += i_source_margin;
516  }
517 
518  sfence();
519  emms();
520 }
521 #endif
522 
523 #if HAVE_MMX
524 static void vfilter_chroma_332_packed422_scanline_mmx( uint8_t *output, int width,
525  uint8_t *m, uint8_t *t, uint8_t *b )
526 {
527  int i;
528  const mmx_t ymask = { 0x00ff00ff00ff00ffULL };
529  const mmx_t cmask = { 0xff00ff00ff00ff00ULL };
530 
531  // Get width in bytes.
532  width *= 2;
533  i = width / 8;
534  width -= i * 8;
535 
536  movq_m2r( ymask, mm7 );
537  movq_m2r( cmask, mm6 );
538 
539  while ( i-- )
540  {
541  movq_m2r( *t, mm0 );
542  movq_m2r( *b, mm1 );
543  movq_m2r( *m, mm2 );
544 
545  movq_r2r ( mm2, mm3 );
546  pand_r2r ( mm7, mm3 );
547 
548  pand_r2r ( mm6, mm0 );
549  pand_r2r ( mm6, mm1 );
550  pand_r2r ( mm6, mm2 );
551 
552  psrlq_i2r( 8, mm0 );
553  psrlq_i2r( 7, mm1 );
554  psrlq_i2r( 8, mm2 );
555 
556  movq_r2r ( mm0, mm4 );
557  psllw_i2r( 1, mm4 );
558  paddw_r2r( mm4, mm0 );
559 
560  movq_r2r ( mm2, mm4 );
561  psllw_i2r( 1, mm4 );
562  paddw_r2r( mm4, mm2 );
563 
564  paddw_r2r( mm0, mm2 );
565  paddw_r2r( mm1, mm2 );
566 
567  psllw_i2r( 5, mm2 );
568  pand_r2r( mm6, mm2 );
569 
570  por_r2r ( mm3, mm2 );
571 
572  movq_r2m( mm2, *output );
573  output += 8;
574  t += 8;
575  b += 8;
576  m += 8;
577  }
578  output++; t++; b++; m++;
579  while ( width-- )
580  {
581  *output = (3 * *t + 3 * *m + 2 * *b) >> 3;
582  output +=2; t+=2; b+=2; m+=2;
583  }
584 
585  emms();
586 }
587 #endif
588 
589 static void vfilter_chroma_332_packed422_scanline_c( uint8_t *output, int width,
590  uint8_t *m, uint8_t *t, uint8_t *b )
591 {
592  output++; t++; b++; m++;
593  while ( width-- )
594  {
595  *output = (3 * *t + 3 * *m + 2 * *b) >> 3;
596  output +=2; t+=2; b+=2; m+=2;
597  }
598 }
599 /*
600  * init_yuv_conversion
601  *
602  * This function precalculates all of the tables used for converting RGB
603  * values to YUV values. This function also decides which conversion
604  * functions to use.
605  */
607 {
608  /* determine best YUV444 -> YUY2 converter to use */
609  /* determine best YV12 -> YUY2 converter to use */
610  /* determine best YV12 -> YUY2 converter to use */
611 
612 #ifdef MMX
613  if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2)
614  {
615  yv12_to_yuy2 = yv12_to_yuy2_mmxext;
616  yuy2_to_yv12 = yuy2_to_yv12_mmxext;
617  vfilter_chroma_332_packed422_scanline = vfilter_chroma_332_packed422_scanline_mmx;
618  }
619  else
620 #endif
621  {
625  }
626 }
627 
628 void apply_chroma_filter( uint8_t *data, int stride, int width, int height )
629 {
630  int i;
631 
632  /* ok, using linearblend inplace is a bit weird: the result of a scanline
633  * interpolation will affect the next scanline. this might not be a problem
634  * at all, we just want a kind of filter here.
635  */
636  for ( i = 0; i < height; i++, data += stride )
637  {
639  data,
640  (i) ? (data - stride) : data,
641  (i < height-1) ? (data + stride) : data );
642  }
643 }
644 
645 /* vim: set expandtab tabstop=4 shiftwidth=4: */
void apply_chroma_filter(uint8_t *data, int stride, int width, int height)
Definition: color.c:628
unsigned char b
Definition: ParseText.cpp:329
void(* yuy2_to_yv12)(const unsigned char *yuy2_map, int yuy2_pitch, unsigned char *y_dst, int y_dst_pitch, unsigned char *u_dst, int u_dst_pitch, unsigned char *v_dst, int v_dst_pitch, int width, int height)
Definition: color.c:50
static void vfilter_chroma_332_packed422_scanline_c(uint8_t *output, int width, uint8_t *m, uint8_t *t, uint8_t *b)
Definition: color.c:589
unsigned char t
Definition: ParseText.cpp:329
static void yv12_to_yuy2_c(const unsigned char *y_src, int y_src_pitch, const unsigned char *u_src, int u_src_pitch, const unsigned char *v_src, int v_src_pitch, unsigned char *yuy2_map, int yuy2_pitch, int width, int height, int progressive)
Definition: color.c:71
#define C_YUV420_YUYV()
Definition: color.c:59
static void yuy2_to_yv12_c(const unsigned char *yuy2_map, int yuy2_pitch, unsigned char *y_dst, int y_dst_pitch, unsigned char *u_dst, int u_dst_pitch, unsigned char *v_dst, int v_dst_pitch, int width, int height)
Definition: color.c:381
void(* vfilter_chroma_332_packed422_scanline)(uint8_t *output, int width, uint8_t *m, uint8_t *t, uint8_t *b)
Definition: color.c:56
#define mmx_t
#define emms()
Definition: mm_arch.h:15
void init_yuv_conversion(void)
Definition: color.c:606
void(* yv12_to_yuy2)(const unsigned char *y_src, int y_src_pitch, const unsigned char *u_src, int u_src_pitch, const unsigned char *v_src, int v_src_pitch, unsigned char *yuy2_map, int yuy2_pitch, int width, int height, int progressive)
Definition: color.c:43
#define C_YUYV_YUV420()
Definition: color.c:374
#define output