dx50 = DX50
[mplayer/glamo.git] / libmpcodecs / vf_halfpack.c
blobb4fc0e648f8ab7b45312ed1103d50de2c01e850c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <inttypes.h>
6 #include "../config.h"
7 #include "../mp_msg.h"
8 #include "../cpudetect.h"
10 #include "img_format.h"
11 #include "mp_image.h"
12 #include "vf.h"
14 #include "../libvo/fastmemcpy.h"
15 #include "../postproc/rgb2rgb.h"
17 struct vf_priv_s {
18 int field;
21 #ifdef HAVE_MMX
22 static void halfpack_MMX(unsigned char *dst, unsigned char *src[3],
23 unsigned int dststride, unsigned int srcstride[3],
24 int w, int h)
26 int j;
27 unsigned char *y1, *y2, *u, *v;
28 unsigned int dstinc, yinc, uinc, vinc;
30 y1 = src[0];
31 y2 = src[0] + srcstride[0];
32 u = src[1];
33 v = src[2];
35 dstinc = dststride - 2*w;
36 yinc = 2*srcstride[0] - w;
37 uinc = srcstride[1] - w/2;
38 vinc = srcstride[2] - w/2;
40 for (h/=2; h; h--) {
41 asm (
42 "pxor %%mm0, %%mm0 \n\t"
43 ".balign 16 \n\t"
44 "1: \n\t"
45 "movq (%0), %%mm1 \n\t"
46 "movq (%0), %%mm2 \n\t"
47 "movq (%1), %%mm3 \n\t"
48 "movq (%1), %%mm4 \n\t"
49 "punpcklbw %%mm0, %%mm1 \n\t"
50 "punpckhbw %%mm0, %%mm2 \n\t"
51 "punpcklbw %%mm0, %%mm3 \n\t"
52 "punpckhbw %%mm0, %%mm4 \n\t"
53 "paddw %%mm3, %%mm1 \n\t"
54 "paddw %%mm4, %%mm2 \n\t"
55 "psrlw $1, %%mm1 \n\t"
56 "psrlw $1, %%mm2 \n\t"
58 "movq (%2), %%mm3 \n\t"
59 "movq (%3), %%mm5 \n\t"
60 "punpcklbw %%mm0, %%mm3 \n\t"
61 "punpcklbw %%mm0, %%mm5 \n\t"
62 "movq %%mm3, %%mm4 \n\t"
63 "movq %%mm5, %%mm6 \n\t"
64 "punpcklwd %%mm0, %%mm3 \n\t"
65 "punpckhwd %%mm0, %%mm4 \n\t"
66 "punpcklwd %%mm0, %%mm5 \n\t"
67 "punpckhwd %%mm0, %%mm6 \n\t"
68 "pslld $8, %%mm3 \n\t"
69 "pslld $8, %%mm4 \n\t"
70 "pslld $24, %%mm5 \n\t"
71 "pslld $24, %%mm6 \n\t"
73 "por %%mm3, %%mm1 \n\t"
74 "por %%mm4, %%mm2 \n\t"
75 "por %%mm5, %%mm1 \n\t"
76 "por %%mm6, %%mm2 \n\t"
78 "addl $8, %0 \n\t"
79 "addl $8, %1 \n\t"
80 "addl $4, %2 \n\t"
81 "addl $4, %3 \n\t"
82 "movq %%mm1, (%8) \n\t"
83 "movq %%mm2, 8(%8) \n\t"
84 "addl $16, %8 \n\t"
85 "decl %9 \n\t"
86 "jnz 1b \n\t"
87 : "=r" (y1), "=r" (y2), "=r" (u), "=r" (v)
88 : "0" (y1), "1" (y2), "2" (u), "3" (v), "r" (dst), "r" (w/8)
89 : "memory"
91 for (j = (w&7)/2; j; j--) {
92 *dst++ = (*y1++ + *y2++)/2;
93 *dst++ = *u++;
94 *dst++ = (*y1++ + *y2++)/2;
95 *dst++ = *v++;
97 y1 += yinc;
98 y2 += yinc;
99 u += uinc;
100 v += vinc;
101 dst += dstinc;
103 asm volatile ( "emms \n\t" ::: "memory" );
105 #endif
109 static void halfpack_C(unsigned char *dst, unsigned char *src[3],
110 unsigned int dststride, unsigned int srcstride[3],
111 int w, int h)
113 int i, j;
114 unsigned char *y1, *y2, *u, *v;
115 unsigned int dstinc, yinc, uinc, vinc;
117 y1 = src[0];
118 y2 = src[0] + srcstride[0];
119 u = src[1];
120 v = src[2];
122 dstinc = dststride - 2*w;
123 yinc = 2*srcstride[0] - w;
124 uinc = srcstride[1] - w/2;
125 vinc = srcstride[2] - w/2;
127 for (i = h/2; i; i--) {
128 for (j = w/2; j; j--) {
129 *dst++ = (*y1++ + *y2++)>>1;
130 *dst++ = *u++;
131 *dst++ = (*y1++ + *y2++)>>1;
132 *dst++ = *v++;
134 y1 += yinc;
135 y2 += yinc;
136 u += uinc;
137 v += vinc;
138 dst += dstinc;
142 static void (*halfpack)(unsigned char *dst, unsigned char *src[3],
143 unsigned int dststride, unsigned int srcstride[3], int w, int h);
146 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
148 mp_image_t *dmpi;
150 // hope we'll get DR buffer:
151 dmpi=vf_get_image(vf->next, IMGFMT_YUY2,
152 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
153 mpi->w, mpi->h/2);
155 switch(vf->priv->field) {
156 case 0:
157 case 1:
158 yuv422ptoyuy2(mpi->planes[0] + mpi->stride[0]*vf->priv->field,
159 mpi->planes[1], mpi->planes[2], dmpi->planes[0],
160 mpi->w, mpi->h/2, mpi->stride[0]*2, mpi->stride[1], dmpi->stride[0]);
161 break;
162 default:
163 halfpack(dmpi->planes[0], mpi->planes, dmpi->stride[0],
164 mpi->stride, mpi->w, mpi->h);
167 return vf_next_put_image(vf,dmpi);
170 static int config(struct vf_instance_s* vf,
171 int width, int height, int d_width, int d_height,
172 unsigned int flags, unsigned int outfmt)
174 /* FIXME - also support UYVY output? */
175 return vf_next_config(vf, width, height/2, d_width, d_height, flags, IMGFMT_YUY2);
179 static int query_format(struct vf_instance_s* vf, unsigned int fmt)
181 /* FIXME - really any YUV 4:2:0 input format should work */
182 switch (fmt) {
183 case IMGFMT_YV12:
184 case IMGFMT_IYUV:
185 case IMGFMT_I420:
186 return vf_next_query_format(vf,IMGFMT_YUY2);
188 return 0;
191 static void uninit(struct vf_instance_s* vf)
193 free(vf->priv);
196 static int open(vf_instance_t *vf, char* args)
198 vf->config=config;
199 vf->query_format=query_format;
200 vf->put_image=put_image;
201 vf->uninit=uninit;
203 vf->priv = calloc(1, sizeof (struct vf_priv_s));
204 vf->priv->field = 2;
205 if (args) sscanf(args, "%d", &vf->priv->field);
207 halfpack = halfpack_C;
208 #ifdef HAVE_MMX
209 if(gCpuCaps.hasMMX) halfpack = halfpack_MMX;
210 #endif
211 return 1;
214 vf_info_t vf_info_halfpack = {
215 "yuv planar 4:2:0 -> packed 4:2:2, half height",
216 "halfpack",
217 "Richard Felker",
219 open,
220 NULL