Mercurial > mplayer.hg
comparison libmpcodecs/vf_halfpack.c @ 7155:66019eb62edc
"halfpack" (yuv planar 4:2:0 -> packed 4:2:2, half height) video filter
(useful for downsampling luma for low-res output devices without
losing chroma samples, when hardware downscaling is poor quality or
unavailable)
author | rfelker |
---|---|
date | Fri, 30 Aug 2002 06:16:40 +0000 |
parents | |
children | 6cd20773b17e |
comparison
equal
deleted
inserted
replaced
7154:308d36832b7f | 7155:66019eb62edc |
---|---|
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <inttypes.h> | |
5 | |
6 #include "../config.h" | |
7 #include "../mp_msg.h" | |
8 #include "../cpudetect.h" | |
9 | |
10 #include "img_format.h" | |
11 #include "mp_image.h" | |
12 #include "vf.h" | |
13 | |
14 #include "../libvo/fastmemcpy.h" | |
15 #include "../postproc/rgb2rgb.h" | |
16 | |
17 | |
18 #ifdef HAVE_MMX | |
19 static void halfpack_MMX(unsigned char *dst, unsigned char *src[3], | |
20 unsigned int dststride, unsigned int srcstride[3], | |
21 int w, int h) | |
22 { | |
23 int j; | |
24 unsigned char *y1, *y2, *u, *v; | |
25 unsigned int dstinc, yinc, uinc, vinc; | |
26 | |
27 y1 = src[0]; | |
28 y2 = src[0] + srcstride[0]; | |
29 u = src[1]; | |
30 v = src[2]; | |
31 | |
32 dstinc = dststride - 2*w; | |
33 yinc = 2*srcstride[0] - w; | |
34 uinc = srcstride[1] - w/2; | |
35 vinc = srcstride[2] - w/2; | |
36 | |
37 for (h/=2; h; h--) { | |
38 asm ( | |
39 "pxor %%mm0, %%mm0 \n\t" | |
40 ".align 16 \n\t" | |
41 "1: \n\t" | |
42 "movq (%0), %%mm1 \n\t" | |
43 "movq (%0), %%mm2 \n\t" | |
44 "movq (%1), %%mm3 \n\t" | |
45 "movq (%1), %%mm4 \n\t" | |
46 "punpcklbw %%mm0, %%mm1 \n\t" | |
47 "punpckhbw %%mm0, %%mm2 \n\t" | |
48 "punpcklbw %%mm0, %%mm3 \n\t" | |
49 "punpckhbw %%mm0, %%mm4 \n\t" | |
50 "paddw %%mm3, %%mm1 \n\t" | |
51 "paddw %%mm4, %%mm2 \n\t" | |
52 "psrlw $1, %%mm1 \n\t" | |
53 "psrlw $1, %%mm2 \n\t" | |
54 | |
55 "movq (%2), %%mm3 \n\t" | |
56 "movq (%3), %%mm5 \n\t" | |
57 "punpcklbw %%mm0, %%mm3 \n\t" | |
58 "punpcklbw %%mm0, %%mm5 \n\t" | |
59 "movq %%mm3, %%mm4 \n\t" | |
60 "movq %%mm5, %%mm6 \n\t" | |
61 "punpcklwd %%mm0, %%mm3 \n\t" | |
62 "punpckhwd %%mm0, %%mm4 \n\t" | |
63 "punpcklwd %%mm0, %%mm5 \n\t" | |
64 "punpckhwd %%mm0, %%mm6 \n\t" | |
65 "pslld $8, %%mm3 \n\t" | |
66 "pslld $8, %%mm4 \n\t" | |
67 "pslld $24, %%mm5 \n\t" | |
68 "pslld $24, %%mm6 \n\t" | |
69 | |
70 "por %%mm3, %%mm1 \n\t" | |
71 "por %%mm4, %%mm2 \n\t" | |
72 "por %%mm5, %%mm1 \n\t" | |
73 "por %%mm6, %%mm2 \n\t" | |
74 | |
75 "addl $8, %0 \n\t" | |
76 "addl $8, %1 \n\t" | |
77 "addl $4, %2 \n\t" | |
78 "addl $4, %3 \n\t" | |
79 "movq %%mm1, (%8) \n\t" | |
80 "movq %%mm2, 8(%8) \n\t" | |
81 "addl $16, %8 \n\t" | |
82 "decl %9 \n\t" | |
83 "jnz 1b \n\t" | |
84 : "=r" (y1), "=r" (y2), "=r" (u), "=r" (v) | |
85 : "0" (y1), "1" (y2), "2" (u), "3" (v), "r" (dst), "r" (w/8) | |
86 : "memory" | |
87 ); | |
88 for (j = (w&7)/2; j; j--) { | |
89 *dst++ = (*y1++ + *y2++)/2; | |
90 *dst++ = *u++; | |
91 *dst++ = (*y1++ + *y2++)/2; | |
92 *dst++ = *v++; | |
93 } | |
94 y1 += yinc; | |
95 y2 += yinc; | |
96 u += uinc; | |
97 v += vinc; | |
98 dst += dstinc; | |
99 } | |
100 asm volatile ( "emms \n\t" ::: "memory" ); | |
101 } | |
102 #endif | |
103 | |
104 | |
105 | |
106 static void halfpack_C(unsigned char *dst, unsigned char *src[3], | |
107 unsigned int dststride, unsigned int srcstride[3], | |
108 int w, int h) | |
109 { | |
110 int i, j; | |
111 unsigned char *y1, *y2, *u, *v; | |
112 unsigned int dstinc, yinc, uinc, vinc; | |
113 | |
114 y1 = src[0]; | |
115 y2 = src[0] + srcstride[0]; | |
116 u = src[1]; | |
117 v = src[2]; | |
118 | |
119 dstinc = dststride - 2*w; | |
120 yinc = 2*srcstride[0] - w; | |
121 uinc = srcstride[1] - w/2; | |
122 vinc = srcstride[2] - w/2; | |
123 | |
124 for (i = h/2; i; i--) { | |
125 for (j = w/2; j; j--) { | |
126 *dst++ = (*y1++ + *y2++)>>1; | |
127 *dst++ = *u++; | |
128 *dst++ = (*y1++ + *y2++)>>1; | |
129 *dst++ = *v++; | |
130 } | |
131 y1 += yinc; | |
132 y2 += yinc; | |
133 u += uinc; | |
134 v += vinc; | |
135 dst += dstinc; | |
136 } | |
137 } | |
138 | |
139 static void (*halfpack)(unsigned char *dst, unsigned char *src[3], | |
140 unsigned int dststride, unsigned int srcstride[3], int w, int h); | |
141 | |
142 | |
143 static void put_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
144 { | |
145 mp_image_t *dmpi; | |
146 | |
147 // hope we'll get DR buffer: | |
148 dmpi=vf_get_image(vf->next, IMGFMT_YUY2, | |
149 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, | |
150 mpi->w, mpi->h/2); | |
151 | |
152 halfpack(dmpi->planes[0], mpi->planes, | |
153 dmpi->stride[0], mpi->stride, | |
154 mpi->w, mpi->h); | |
155 | |
156 vf_next_put_image(vf,dmpi); | |
157 } | |
158 | |
159 static int config(struct vf_instance_s* vf, | |
160 int width, int height, int d_width, int d_height, | |
161 unsigned int flags, unsigned int outfmt) | |
162 { | |
163 /* FIXME - also support UYVY output? */ | |
164 return vf_next_config(vf, width, height/2, d_width, d_height, flags, IMGFMT_YUY2); | |
165 } | |
166 | |
167 | |
168 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
169 { | |
170 /* FIXME - really any YUV 4:2:0 input format should work */ | |
171 switch (fmt) { | |
172 case IMGFMT_YV12: | |
173 case IMGFMT_IYUV: | |
174 case IMGFMT_I420: | |
175 return vf_next_query_format(vf,IMGFMT_YUY2); | |
176 } | |
177 return 0; | |
178 } | |
179 | |
180 | |
181 static int open(vf_instance_t *vf, char* args) | |
182 { | |
183 vf->config=config; | |
184 vf->query_format=query_format; | |
185 vf->put_image=put_image; | |
186 halfpack = halfpack_C; | |
187 #ifdef HAVE_MMX | |
188 if(gCpuCaps.hasMMX) halfpack = halfpack_MMX; | |
189 #endif | |
190 return 1; | |
191 } | |
192 | |
193 vf_info_t vf_info_halfpack = { | |
194 "yuv planar 4:2:0 -> packed 4:2:2, half height", | |
195 "halfpack", | |
196 "Richard Felker", | |
197 "", | |
198 open | |
199 }; | |
200 |