00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <inttypes.h>
00023
00024 #include "config.h"
00025 #include "mp_msg.h"
00026 #include "cpudetect.h"
00027
00028 #include "img_format.h"
00029 #include "mp_image.h"
00030 #include "vf.h"
00031
00032 typedef void (pack_func_t)(unsigned char *dst, unsigned char *y,
00033 unsigned char *u, unsigned char *v, int w, int us, int vs);
00034
00035 struct vf_priv_s {
00036 int mode;
00037 pack_func_t *pack[2];
00038 };
00039
00040 static void pack_nn_C(unsigned char *dst, unsigned char *y,
00041 unsigned char *u, unsigned char *v, int w)
00042 {
00043 int j;
00044 for (j = w/2; j; j--) {
00045 *dst++ = *y++;
00046 *dst++ = *u++;
00047 *dst++ = *y++;
00048 *dst++ = *v++;
00049 }
00050 }
00051
00052 static void pack_li_0_C(unsigned char *dst, unsigned char *y,
00053 unsigned char *u, unsigned char *v, int w, int us, int vs)
00054 {
00055 int j;
00056 for (j = w/2; j; j--) {
00057 *dst++ = *y++;
00058 *dst++ = (u[us+us] + 7*u[0])>>3;
00059 *dst++ = *y++;
00060 *dst++ = (v[vs+vs] + 7*v[0])>>3;
00061 u++; v++;
00062 }
00063 }
00064
00065 static void pack_li_1_C(unsigned char *dst, unsigned char *y,
00066 unsigned char *u, unsigned char *v, int w, int us, int vs)
00067 {
00068 int j;
00069 for (j = w/2; j; j--) {
00070 *dst++ = *y++;
00071 *dst++ = (3*u[us+us] + 5*u[0])>>3;
00072 *dst++ = *y++;
00073 *dst++ = (3*v[vs+vs] + 5*v[0])>>3;
00074 u++; v++;
00075 }
00076 }
00077
00078 #if HAVE_MMX
00079 static void pack_nn_MMX(unsigned char *dst, unsigned char *y,
00080 unsigned char *u, unsigned char *v, int w)
00081 {
00082 __asm__ volatile (""
00083 ASMALIGN(4)
00084 "1: \n\t"
00085 "movq (%0), %%mm1 \n\t"
00086 "movq (%0), %%mm2 \n\t"
00087 "movq (%1), %%mm4 \n\t"
00088 "movq (%2), %%mm6 \n\t"
00089 "punpcklbw %%mm6, %%mm4 \n\t"
00090 "punpcklbw %%mm4, %%mm1 \n\t"
00091 "punpckhbw %%mm4, %%mm2 \n\t"
00092
00093 "add $8, %0 \n\t"
00094 "add $4, %1 \n\t"
00095 "add $4, %2 \n\t"
00096 "movq %%mm1, (%3) \n\t"
00097 "movq %%mm2, 8(%3) \n\t"
00098 "add $16, %3 \n\t"
00099 "decl %4 \n\t"
00100 "jnz 1b \n\t"
00101 "emms \n\t"
00102 :
00103 : "r" (y), "r" (u), "r" (v), "r" (dst), "r" (w/8)
00104 : "memory"
00105 );
00106 pack_nn_C(dst, y, u, v, (w&7));
00107 }
00108
00109 #if HAVE_EBX_AVAILABLE
00110 static void pack_li_0_MMX(unsigned char *dst, unsigned char *y,
00111 unsigned char *u, unsigned char *v, int w, int us, int vs)
00112 {
00113 __asm__ volatile (""
00114 "push %%"REG_BP" \n\t"
00115 #if ARCH_X86_64
00116 "mov %6, %%"REG_BP" \n\t"
00117 #else
00118 "movl 4(%%"REG_d"), %%"REG_BP" \n\t"
00119 "movl (%%"REG_d"), %%"REG_d" \n\t"
00120 #endif
00121 "pxor %%mm0, %%mm0 \n\t"
00122
00123 ASMALIGN(4)
00124 ".Lli0: \n\t"
00125 "movq (%%"REG_S"), %%mm1 \n\t"
00126 "movq (%%"REG_S"), %%mm2 \n\t"
00127
00128 "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
00129 "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
00130 "punpcklbw %%mm0, %%mm4 \n\t"
00131 "punpcklbw %%mm0, %%mm6 \n\t"
00132 "movq (%%"REG_a"), %%mm3 \n\t"
00133 "movq (%%"REG_b"), %%mm5 \n\t"
00134 "punpcklbw %%mm0, %%mm3 \n\t"
00135 "punpcklbw %%mm0, %%mm5 \n\t"
00136 "paddw %%mm3, %%mm4 \n\t"
00137 "paddw %%mm5, %%mm6 \n\t"
00138 "paddw %%mm3, %%mm4 \n\t"
00139 "paddw %%mm5, %%mm6 \n\t"
00140 "paddw %%mm3, %%mm4 \n\t"
00141 "paddw %%mm5, %%mm6 \n\t"
00142 "paddw %%mm3, %%mm4 \n\t"
00143 "paddw %%mm5, %%mm6 \n\t"
00144 "paddw %%mm3, %%mm4 \n\t"
00145 "paddw %%mm5, %%mm6 \n\t"
00146 "paddw %%mm3, %%mm4 \n\t"
00147 "paddw %%mm5, %%mm6 \n\t"
00148 "paddw %%mm3, %%mm4 \n\t"
00149 "paddw %%mm5, %%mm6 \n\t"
00150 "psrlw $3, %%mm4 \n\t"
00151 "psrlw $3, %%mm6 \n\t"
00152 "packuswb %%mm4, %%mm4 \n\t"
00153 "packuswb %%mm6, %%mm6 \n\t"
00154 "punpcklbw %%mm6, %%mm4 \n\t"
00155 "punpcklbw %%mm4, %%mm1 \n\t"
00156 "punpckhbw %%mm4, %%mm2 \n\t"
00157
00158 "movq %%mm1, (%%"REG_D") \n\t"
00159 "movq %%mm2, 8(%%"REG_D") \n\t"
00160
00161 "movq 8(%%"REG_S"), %%mm1 \n\t"
00162 "movq 8(%%"REG_S"), %%mm2 \n\t"
00163
00164 "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
00165 "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
00166 "punpckhbw %%mm0, %%mm4 \n\t"
00167 "punpckhbw %%mm0, %%mm6 \n\t"
00168 "movq (%%"REG_a"), %%mm3 \n\t"
00169 "movq (%%"REG_b"), %%mm5 \n\t"
00170 "punpckhbw %%mm0, %%mm3 \n\t"
00171 "punpckhbw %%mm0, %%mm5 \n\t"
00172 "paddw %%mm3, %%mm4 \n\t"
00173 "paddw %%mm5, %%mm6 \n\t"
00174 "paddw %%mm3, %%mm4 \n\t"
00175 "paddw %%mm5, %%mm6 \n\t"
00176 "paddw %%mm3, %%mm4 \n\t"
00177 "paddw %%mm5, %%mm6 \n\t"
00178 "paddw %%mm3, %%mm4 \n\t"
00179 "paddw %%mm5, %%mm6 \n\t"
00180 "paddw %%mm3, %%mm4 \n\t"
00181 "paddw %%mm5, %%mm6 \n\t"
00182 "paddw %%mm3, %%mm4 \n\t"
00183 "paddw %%mm5, %%mm6 \n\t"
00184 "paddw %%mm3, %%mm4 \n\t"
00185 "paddw %%mm5, %%mm6 \n\t"
00186 "psrlw $3, %%mm4 \n\t"
00187 "psrlw $3, %%mm6 \n\t"
00188 "packuswb %%mm4, %%mm4 \n\t"
00189 "packuswb %%mm6, %%mm6 \n\t"
00190 "punpcklbw %%mm6, %%mm4 \n\t"
00191 "punpcklbw %%mm4, %%mm1 \n\t"
00192 "punpckhbw %%mm4, %%mm2 \n\t"
00193
00194 "add $16, %%"REG_S" \n\t"
00195 "add $8, %%"REG_a" \n\t"
00196 "add $8, %%"REG_b" \n\t"
00197
00198 "movq %%mm1, 16(%%"REG_D") \n\t"
00199 "movq %%mm2, 24(%%"REG_D") \n\t"
00200 "add $32, %%"REG_D" \n\t"
00201
00202 "decl %%ecx \n\t"
00203 "jnz .Lli0 \n\t"
00204 "emms \n\t"
00205 "pop %%"REG_BP" \n\t"
00206 :
00207 : "S" (y), "D" (dst), "a" (u), "b" (v), "c" (w/16),
00208 #if ARCH_X86_64
00209 "d" ((x86_reg)us), "r" ((x86_reg)vs)
00210 #else
00211 "d" (&us)
00212 #endif
00213 : "memory"
00214 );
00215 pack_li_0_C(dst, y, u, v, (w&15), us, vs);
00216 }
00217
00218 static void pack_li_1_MMX(unsigned char *dst, unsigned char *y,
00219 unsigned char *u, unsigned char *v, int w, int us, int vs)
00220 {
00221 __asm__ volatile (""
00222 "push %%"REG_BP" \n\t"
00223 #if ARCH_X86_64
00224 "mov %6, %%"REG_BP" \n\t"
00225 #else
00226 "movl 4(%%"REG_d"), %%"REG_BP" \n\t"
00227 "movl (%%"REG_d"), %%"REG_d" \n\t"
00228 #endif
00229 "pxor %%mm0, %%mm0 \n\t"
00230
00231 ASMALIGN(4)
00232 ".Lli1: \n\t"
00233 "movq (%%"REG_S"), %%mm1 \n\t"
00234 "movq (%%"REG_S"), %%mm2 \n\t"
00235
00236 "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
00237 "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
00238 "punpcklbw %%mm0, %%mm4 \n\t"
00239 "punpcklbw %%mm0, %%mm6 \n\t"
00240 "movq (%%"REG_a"), %%mm3 \n\t"
00241 "movq (%%"REG_b"), %%mm5 \n\t"
00242 "punpcklbw %%mm0, %%mm3 \n\t"
00243 "punpcklbw %%mm0, %%mm5 \n\t"
00244 "movq %%mm4, %%mm7 \n\t"
00245 "paddw %%mm4, %%mm4 \n\t"
00246 "paddw %%mm7, %%mm4 \n\t"
00247 "movq %%mm6, %%mm7 \n\t"
00248 "paddw %%mm6, %%mm6 \n\t"
00249 "paddw %%mm7, %%mm6 \n\t"
00250 "paddw %%mm3, %%mm4 \n\t"
00251 "paddw %%mm5, %%mm6 \n\t"
00252 "paddw %%mm3, %%mm4 \n\t"
00253 "paddw %%mm5, %%mm6 \n\t"
00254 "paddw %%mm3, %%mm4 \n\t"
00255 "paddw %%mm5, %%mm6 \n\t"
00256 "paddw %%mm3, %%mm4 \n\t"
00257 "paddw %%mm5, %%mm6 \n\t"
00258 "paddw %%mm3, %%mm4 \n\t"
00259 "paddw %%mm5, %%mm6 \n\t"
00260 "psrlw $3, %%mm4 \n\t"
00261 "psrlw $3, %%mm6 \n\t"
00262 "packuswb %%mm4, %%mm4 \n\t"
00263 "packuswb %%mm6, %%mm6 \n\t"
00264 "punpcklbw %%mm6, %%mm4 \n\t"
00265 "punpcklbw %%mm4, %%mm1 \n\t"
00266 "punpckhbw %%mm4, %%mm2 \n\t"
00267
00268 "movq %%mm1, (%%"REG_D") \n\t"
00269 "movq %%mm2, 8(%%"REG_D") \n\t"
00270
00271 "movq 8(%%"REG_S"), %%mm1 \n\t"
00272 "movq 8(%%"REG_S"), %%mm2 \n\t"
00273
00274 "movq (%%"REG_a",%%"REG_d",2), %%mm4 \n\t"
00275 "movq (%%"REG_b",%%"REG_BP",2), %%mm6 \n\t"
00276 "punpckhbw %%mm0, %%mm4 \n\t"
00277 "punpckhbw %%mm0, %%mm6 \n\t"
00278 "movq (%%"REG_a"), %%mm3 \n\t"
00279 "movq (%%"REG_b"), %%mm5 \n\t"
00280 "punpckhbw %%mm0, %%mm3 \n\t"
00281 "punpckhbw %%mm0, %%mm5 \n\t"
00282 "movq %%mm4, %%mm7 \n\t"
00283 "paddw %%mm4, %%mm4 \n\t"
00284 "paddw %%mm7, %%mm4 \n\t"
00285 "movq %%mm6, %%mm7 \n\t"
00286 "paddw %%mm6, %%mm6 \n\t"
00287 "paddw %%mm7, %%mm6 \n\t"
00288 "paddw %%mm3, %%mm4 \n\t"
00289 "paddw %%mm5, %%mm6 \n\t"
00290 "paddw %%mm3, %%mm4 \n\t"
00291 "paddw %%mm5, %%mm6 \n\t"
00292 "paddw %%mm3, %%mm4 \n\t"
00293 "paddw %%mm5, %%mm6 \n\t"
00294 "paddw %%mm3, %%mm4 \n\t"
00295 "paddw %%mm5, %%mm6 \n\t"
00296 "paddw %%mm3, %%mm4 \n\t"
00297 "paddw %%mm5, %%mm6 \n\t"
00298 "psrlw $3, %%mm4 \n\t"
00299 "psrlw $3, %%mm6 \n\t"
00300 "packuswb %%mm4, %%mm4 \n\t"
00301 "packuswb %%mm6, %%mm6 \n\t"
00302 "punpcklbw %%mm6, %%mm4 \n\t"
00303 "punpcklbw %%mm4, %%mm1 \n\t"
00304 "punpckhbw %%mm4, %%mm2 \n\t"
00305
00306 "add $16, %%"REG_S" \n\t"
00307 "add $8, %%"REG_a" \n\t"
00308 "add $8, %%"REG_b" \n\t"
00309
00310 "movq %%mm1, 16(%%"REG_D") \n\t"
00311 "movq %%mm2, 24(%%"REG_D") \n\t"
00312 "add $32, %%"REG_D" \n\t"
00313
00314 "decl %%ecx \n\t"
00315 "jnz .Lli1 \n\t"
00316 "emms \n\t"
00317 "pop %%"REG_BP" \n\t"
00318 :
00319 : "S" (y), "D" (dst), "a" (u), "b" (v), "c" (w/16),
00320 #if ARCH_X86_64
00321 "d" ((x86_reg)us), "r" ((x86_reg)vs)
00322 #else
00323 "d" (&us)
00324 #endif
00325 : "memory"
00326 );
00327 pack_li_1_C(dst, y, u, v, (w&15), us, vs);
00328 }
00329 #endif
00330 #endif
00331
00332 static pack_func_t *pack_nn;
00333 static pack_func_t *pack_li_0;
00334 static pack_func_t *pack_li_1;
00335
00336 static void ilpack(unsigned char *dst, unsigned char *src[3],
00337 int dststride, int srcstride[3], int w, int h, pack_func_t *pack[2])
00338 {
00339 int i;
00340 unsigned char *y, *u, *v;
00341 int ys = srcstride[0], us = srcstride[1], vs = srcstride[2];
00342 int a, b;
00343
00344 y = src[0];
00345 u = src[1];
00346 v = src[2];
00347
00348 pack_nn(dst, y, u, v, w, 0, 0);
00349 y += ys; dst += dststride;
00350 pack_nn(dst, y, u+us, v+vs, w, 0, 0);
00351 y += ys; dst += dststride;
00352 for (i=2; i<h-2; i++) {
00353 a = (i&2) ? 1 : -1;
00354 b = (i&1) ^ ((i&2)>>1);
00355 pack[b](dst, y, u, v, w, us*a, vs*a);
00356 y += ys;
00357 if ((i&3) == 1) {
00358 u -= us;
00359 v -= vs;
00360 } else {
00361 u += us;
00362 v += vs;
00363 }
00364 dst += dststride;
00365 }
00366 pack_nn(dst, y, u, v, w, 0, 0);
00367 y += ys; dst += dststride; u += us; v += vs;
00368 pack_nn(dst, y, u, v, w, 0, 0);
00369 }
00370
00371
00372 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
00373 {
00374 mp_image_t *dmpi;
00375
00376
00377 dmpi=vf_get_image(vf->next, IMGFMT_YUY2,
00378 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
00379 mpi->w, mpi->h);
00380
00381 ilpack(dmpi->planes[0], mpi->planes, dmpi->stride[0], mpi->stride, mpi->w, mpi->h, vf->priv->pack);
00382
00383 return vf_next_put_image(vf,dmpi, pts);
00384 }
00385
00386 static int config(struct vf_instance *vf,
00387 int width, int height, int d_width, int d_height,
00388 unsigned int flags, unsigned int outfmt)
00389 {
00390
00391 return vf_next_config(vf, width, height, d_width, d_height, flags, IMGFMT_YUY2);
00392 }
00393
00394
00395 static int query_format(struct vf_instance *vf, unsigned int fmt)
00396 {
00397
00398 switch (fmt) {
00399 case IMGFMT_YV12:
00400 case IMGFMT_IYUV:
00401 case IMGFMT_I420:
00402 return vf_next_query_format(vf,IMGFMT_YUY2);
00403 }
00404 return 0;
00405 }
00406
00407 static int vf_open(vf_instance_t *vf, char *args)
00408 {
00409 vf->config=config;
00410 vf->query_format=query_format;
00411 vf->put_image=put_image;
00412 vf->priv = calloc(1, sizeof(struct vf_priv_s));
00413 vf->priv->mode = 1;
00414 if (args) sscanf(args, "%d", &vf->priv->mode);
00415
00416 pack_nn = (pack_func_t *)pack_nn_C;
00417 pack_li_0 = pack_li_0_C;
00418 pack_li_1 = pack_li_1_C;
00419 #if HAVE_MMX
00420 if(gCpuCaps.hasMMX) {
00421 pack_nn = (pack_func_t *)pack_nn_MMX;
00422 #if HAVE_EBX_AVAILABLE
00423 pack_li_0 = pack_li_0_MMX;
00424 pack_li_1 = pack_li_1_MMX;
00425 #endif
00426 }
00427 #endif
00428
00429 switch(vf->priv->mode) {
00430 case 0:
00431 vf->priv->pack[0] = vf->priv->pack[1] = pack_nn;
00432 break;
00433 default:
00434 mp_msg(MSGT_VFILTER, MSGL_WARN,
00435 "ilpack: unknown mode %d (fallback to linear)\n",
00436 vf->priv->mode);
00437 case 1:
00438 vf->priv->pack[0] = pack_li_0;
00439 vf->priv->pack[1] = pack_li_1;
00440 break;
00441 }
00442
00443 return 1;
00444 }
00445
00446 const vf_info_t vf_info_ilpack = {
00447 "4:2:0 planar -> 4:2:2 packed reinterlacer",
00448 "ilpack",
00449 "Richard Felker",
00450 "",
00451 vf_open,
00452 NULL
00453 };