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