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

libavfilter/libmpcodecs/vf_pullup.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 
00023 #include "config.h"
00024 #include "mp_msg.h"
00025 #include "cpudetect.h"
00026 
00027 #include "img_format.h"
00028 #include "mp_image.h"
00029 #include "vf.h"
00030 
00031 #include "libvo/fastmemcpy.h"
00032 
00033 #include "pullup.h"
00034 
00035 #undef MAX
00036 #define MAX(a,b) ((a)>(b)?(a):(b))
00037 
00038 struct vf_priv_s {
00039     struct pullup_context *ctx;
00040     int init;
00041     int fakecount;
00042     char *qbuf;
00043 };
00044 
00045 static void init_pullup(struct vf_instance *vf, mp_image_t *mpi)
00046 {
00047     struct pullup_context *c = vf->priv->ctx;
00048 
00049     if (mpi->flags & MP_IMGFLAG_PLANAR) {
00050         c->format = PULLUP_FMT_Y;
00051         c->nplanes = 4;
00052         pullup_preinit_context(c);
00053         c->bpp[0] = c->bpp[1] = c->bpp[2] = 8;
00054         c->w[0] = mpi->w;
00055         c->h[0] = mpi->h;
00056         c->w[1] = c->w[2] = mpi->chroma_width;
00057         c->h[1] = c->h[2] = mpi->chroma_height;
00058         c->w[3] = ((mpi->w+15)/16) * ((mpi->h+15)/16);
00059         c->h[3] = 2;
00060         c->stride[0] = mpi->width;
00061         c->stride[1] = c->stride[2] = mpi->chroma_width;
00062         c->stride[3] = c->w[3];
00063         c->background[1] = c->background[2] = 128;
00064     }
00065 
00066     if (gCpuCaps.hasMMX) c->cpu |= PULLUP_CPU_MMX;
00067     if (gCpuCaps.hasMMX2) c->cpu |= PULLUP_CPU_MMX2;
00068     if (gCpuCaps.has3DNow) c->cpu |= PULLUP_CPU_3DNOW;
00069     if (gCpuCaps.has3DNowExt) c->cpu |= PULLUP_CPU_3DNOWEXT;
00070     if (gCpuCaps.hasSSE) c->cpu |= PULLUP_CPU_SSE;
00071     if (gCpuCaps.hasSSE2) c->cpu |= PULLUP_CPU_SSE2;
00072 
00073     pullup_init_context(c);
00074 
00075     vf->priv->init = 1;
00076     vf->priv->qbuf = malloc(c->w[3]);
00077 }
00078 
00079 
00080 #if 0
00081 static void get_image(struct vf_instance *vf, mp_image_t *mpi)
00082 {
00083     struct pullup_context *c = vf->priv->ctx;
00084     struct pullup_buffer *b;
00085 
00086     if (mpi->type == MP_IMGTYPE_STATIC) return;
00087 
00088     if (!vf->priv->init) init_pullup(vf, mpi);
00089 
00090     b = pullup_get_buffer(c, 2);
00091     if (!b) return; /* shouldn't happen... */
00092 
00093     mpi->priv = b;
00094 
00095     mpi->planes[0] = b->planes[0];
00096     mpi->planes[1] = b->planes[1];
00097     mpi->planes[2] = b->planes[2];
00098     mpi->stride[0] = c->stride[0];
00099     mpi->stride[1] = c->stride[1];
00100     mpi->stride[2] = c->stride[2];
00101 
00102     mpi->flags |= MP_IMGFLAG_DIRECT;
00103     mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
00104 }
00105 #endif
00106 
00107 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
00108 {
00109     struct pullup_context *c = vf->priv->ctx;
00110     struct pullup_buffer *b;
00111     struct pullup_frame *f;
00112     mp_image_t *dmpi;
00113     int ret;
00114     int p;
00115     int i;
00116 
00117     if (!vf->priv->init) init_pullup(vf, mpi);
00118 
00119     if (mpi->flags & MP_IMGFLAG_DIRECT) {
00120         b = mpi->priv;
00121         mpi->priv = 0;
00122     } else {
00123         b = pullup_get_buffer(c, 2);
00124         if (!b) {
00125             mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n");
00126             f = pullup_get_frame(c);
00127             pullup_release_frame(f);
00128             return 0;
00129         }
00130         memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
00131             c->stride[0], mpi->stride[0]);
00132         if (mpi->flags & MP_IMGFLAG_PLANAR) {
00133             memcpy_pic(b->planes[1], mpi->planes[1],
00134                 mpi->chroma_width, mpi->chroma_height,
00135                 c->stride[1], mpi->stride[1]);
00136             memcpy_pic(b->planes[2], mpi->planes[2],
00137                 mpi->chroma_width, mpi->chroma_height,
00138                 c->stride[2], mpi->stride[2]);
00139         }
00140     }
00141     if (mpi->qscale) {
00142         fast_memcpy(b->planes[3], mpi->qscale, c->w[3]);
00143         fast_memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]);
00144     }
00145 
00146     p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 :
00147         (mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0);
00148     pullup_submit_field(c, b, p);
00149     pullup_submit_field(c, b, p^1);
00150     if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST)
00151         pullup_submit_field(c, b, p);
00152 
00153     pullup_release_buffer(b, 2);
00154 
00155     f = pullup_get_frame(c);
00156 
00157     /* Fake yes for first few frames (buffer depth) to keep from
00158      * breaking A/V sync with G1's bad architecture... */
00159     if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
00160 
00161     if (f->length < 2) {
00162         pullup_release_frame(f);
00163         f = pullup_get_frame(c);
00164         if (!f) return 0;
00165         if (f->length < 2) {
00166             pullup_release_frame(f);
00167             if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
00168                 return 0;
00169             f = pullup_get_frame(c);
00170             if (!f) return 0;
00171             if (f->length < 2) {
00172                 pullup_release_frame(f);
00173                 return 0;
00174             }
00175         }
00176     }
00177 
00178 #if 0
00179     /* Average qscale tables from both frames. */
00180     if (mpi->qscale) {
00181         for (i=0; i<c->w[3]; i++) {
00182             vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i]
00183                 + f->ofields[1]->planes[3][i+c->w[3]])>>1;
00184         }
00185     }
00186 #else
00187     /* Take worst of qscale tables from both frames. */
00188     if (mpi->qscale) {
00189         for (i=0; i<c->w[3]; i++) {
00190             vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]);
00191         }
00192     }
00193 #endif
00194 
00195     /* If the frame isn't already exportable... */
00196     while (!f->buffer) {
00197         dmpi = vf_get_image(vf->next, mpi->imgfmt,
00198             MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
00199             mpi->width, mpi->height);
00200         /* FIXME: Is it ok to discard dmpi if it's not direct? */
00201         if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) {
00202             pullup_pack_frame(c, f);
00203             break;
00204         }
00205         /* Direct render fields into output buffer */
00206         my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0],
00207             mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
00208         my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0],
00209             f->ofields[1]->planes[0] + c->stride[0],
00210             mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
00211         if (mpi->flags & MP_IMGFLAG_PLANAR) {
00212             my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1],
00213                 mpi->chroma_width, mpi->chroma_height/2,
00214                 dmpi->stride[1]*2, c->stride[1]*2);
00215             my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1],
00216                 f->ofields[1]->planes[1] + c->stride[1],
00217                 mpi->chroma_width, mpi->chroma_height/2,
00218                 dmpi->stride[1]*2, c->stride[1]*2);
00219             my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2],
00220                 mpi->chroma_width, mpi->chroma_height/2,
00221                 dmpi->stride[2]*2, c->stride[2]*2);
00222             my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2],
00223                 f->ofields[1]->planes[2] + c->stride[2],
00224                 mpi->chroma_width, mpi->chroma_height/2,
00225                 dmpi->stride[2]*2, c->stride[2]*2);
00226         }
00227         pullup_release_frame(f);
00228         if (mpi->qscale) {
00229             dmpi->qscale = vf->priv->qbuf;
00230             dmpi->qstride = mpi->qstride;
00231             dmpi->qscale_type = mpi->qscale_type;
00232         }
00233         return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
00234     }
00235     dmpi = vf_get_image(vf->next, mpi->imgfmt,
00236         MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
00237         mpi->width, mpi->height);
00238 
00239     dmpi->planes[0] = f->buffer->planes[0];
00240     dmpi->planes[1] = f->buffer->planes[1];
00241     dmpi->planes[2] = f->buffer->planes[2];
00242 
00243     dmpi->stride[0] = c->stride[0];
00244     dmpi->stride[1] = c->stride[1];
00245     dmpi->stride[2] = c->stride[2];
00246 
00247     if (mpi->qscale) {
00248         dmpi->qscale = vf->priv->qbuf;
00249         dmpi->qstride = mpi->qstride;
00250         dmpi->qscale_type = mpi->qscale_type;
00251     }
00252     ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
00253     pullup_release_frame(f);
00254     return ret;
00255 }
00256 
00257 static int query_format(struct vf_instance *vf, unsigned int fmt)
00258 {
00259     /* FIXME - support more formats */
00260     switch (fmt) {
00261     case IMGFMT_YV12:
00262     case IMGFMT_IYUV:
00263     case IMGFMT_I420:
00264         return vf_next_query_format(vf, fmt);
00265     }
00266     return 0;
00267 }
00268 
00269 static int config(struct vf_instance *vf,
00270     int width, int height, int d_width, int d_height,
00271     unsigned int flags, unsigned int outfmt)
00272 {
00273     if (height&3) return 0;
00274     return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
00275 }
00276 
00277 static void uninit(struct vf_instance *vf)
00278 {
00279     pullup_free_context(vf->priv->ctx);
00280     free(vf->priv);
00281 }
00282 
00283 static int vf_open(vf_instance_t *vf, char *args)
00284 {
00285     struct vf_priv_s *p;
00286     struct pullup_context *c;
00287     //vf->get_image = get_image;
00288     vf->put_image = put_image;
00289     vf->config = config;
00290     vf->query_format = query_format;
00291     vf->uninit = uninit;
00292     vf->default_reqs = VFCAP_ACCEPT_STRIDE;
00293     vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
00294     p->ctx = c = pullup_alloc_context();
00295     p->fakecount = 1;
00296     c->verbose = 1;
00297     c->junk_left = c->junk_right = 1;
00298     c->junk_top = c->junk_bottom = 4;
00299     c->strict_breaks = 0;
00300     c->metric_plane = 0;
00301     if (args) {
00302         sscanf(args, "%d:%d:%d:%d:%d:%d", &c->junk_left, &c->junk_right, &c->junk_top, &c->junk_bottom, &c->strict_breaks, &c->metric_plane);
00303     }
00304     return 1;
00305 }
00306 
00307 const vf_info_t vf_info_pullup = {
00308     "pullup (from field sequence to frames)",
00309     "pullup",
00310     "Rich Felker",
00311     "",
00312     vf_open,
00313     NULL
00314 };
Generated on Fri Feb 1 2013 14:34:49 for FFmpeg by doxygen 1.7.1