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