• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavfilter/libmpcodecs/vf_ilpack.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of MPlayer.
00003  *
00004  * MPlayer is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * MPlayer is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License along
00015  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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 /* HAVE_EBX_AVAILABLE */
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     // hope we'll get DR buffer:
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     /* FIXME - also support UYVY output? */
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     /* FIXME - really any YUV 4:2:0 input format should work */
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 };
Generated on Fri Feb 1 2013 14:34:49 for FFmpeg by doxygen 1.7.1