docs: document --quvi-format
[mplayer.git] / libmpcodecs / vf_telecine.c
blob4ae96f2434668b0ba75f159d5117ddbac72a63d2
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include "config.h"
24 #include "mp_msg.h"
26 #include "img_format.h"
27 #include "mp_image.h"
28 #include "vf.h"
30 #include "libvo/fastmemcpy.h"
32 struct vf_priv_s {
33 int frame;
34 double pts;
35 double lastpts;
36 mp_image_t *buffered_mpi;
39 static int continue_buffered_image_fullframe(struct vf_instance *vf)
41 mp_image_t *mpi = vf->priv->buffered_mpi;
42 mp_image_t *dmpi = vf_get_image(vf->next, mpi->imgfmt,
43 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
44 MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
46 memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
47 dmpi->stride[0], mpi->stride[0]);
48 if (mpi->flags & MP_IMGFLAG_PLANAR) {
49 memcpy_pic(dmpi->planes[1], mpi->planes[1],
50 mpi->chroma_width, mpi->chroma_height,
51 dmpi->stride[1], mpi->stride[1]);
52 memcpy_pic(dmpi->planes[2], mpi->planes[2],
53 mpi->chroma_width, mpi->chroma_height,
54 dmpi->stride[2], mpi->stride[2]);
56 return vf_next_put_image(vf, dmpi, vf->priv->pts);
59 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
61 mp_image_t *dmpi;
62 int ret;
64 vf->priv->frame = (vf->priv->frame+1)%4;
66 if (pts != MP_NOPTS_VALUE) {
67 if (vf->priv->lastpts == MP_NOPTS_VALUE) {
68 vf->priv->pts = pts;
69 vf->priv->lastpts = pts;
70 } else {
71 // we only increase by 80% of input pts at each frame; in the case
72 // in which we render two frames, we jump back
73 // this turns 23.98fps perfectly into 29.97fps
74 vf->priv->pts += 0.8 * (pts - vf->priv->lastpts);
75 vf->priv->lastpts = pts;
79 ret = 0;
80 // 0/0 1/1 2/2 2/3 3/0
81 switch (vf->priv->frame) {
82 case 0:
83 dmpi = vf_get_image(vf->next, mpi->imgfmt,
84 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
85 MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
86 my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
87 mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
88 dmpi->stride[0]*2, mpi->stride[0]*2);
89 if (mpi->flags & MP_IMGFLAG_PLANAR) {
90 my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
91 mpi->planes[1]+mpi->stride[1],
92 mpi->chroma_width, mpi->chroma_height/2,
93 dmpi->stride[1]*2, mpi->stride[1]*2);
94 my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
95 mpi->planes[2]+mpi->stride[2],
96 mpi->chroma_width, mpi->chroma_height/2,
97 dmpi->stride[2]*2, mpi->stride[2]*2);
99 ret = vf_next_put_image(vf, dmpi, vf->priv->pts);
100 vf->priv->pts = pts;
101 vf->priv->buffered_mpi = mpi;
102 vf_queue_frame(vf, continue_buffered_image_fullframe);
103 return ret;
104 case 1:
105 case 2:
106 vf->priv->buffered_mpi = mpi;
107 return continue_buffered_image_fullframe(vf);
108 case 3:
109 dmpi = vf_get_image(vf->next, mpi->imgfmt,
110 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
111 MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
112 my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
113 mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
114 dmpi->stride[0]*2, mpi->stride[0]*2);
115 if (mpi->flags & MP_IMGFLAG_PLANAR) {
116 my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
117 mpi->planes[1]+mpi->stride[1],
118 mpi->chroma_width, mpi->chroma_height/2,
119 dmpi->stride[1]*2, mpi->stride[1]*2);
120 my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
121 mpi->planes[2]+mpi->stride[2],
122 mpi->chroma_width, mpi->chroma_height/2,
123 dmpi->stride[2]*2, mpi->stride[2]*2);
125 ret = vf_next_put_image(vf, dmpi, vf->priv->pts);
126 my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
127 dmpi->stride[0]*2, mpi->stride[0]*2);
128 if (mpi->flags & MP_IMGFLAG_PLANAR) {
129 my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
130 mpi->chroma_width, mpi->chroma_height/2,
131 dmpi->stride[1]*2, mpi->stride[1]*2);
132 my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
133 mpi->chroma_width, mpi->chroma_height/2,
134 dmpi->stride[2]*2, mpi->stride[2]*2);
136 return ret;
138 return 0;
141 #if 0
142 static int query_format(struct vf_instance *vf, unsigned int fmt)
144 /* FIXME - figure out which other formats work */
145 switch (fmt) {
146 case IMGFMT_YV12:
147 case IMGFMT_IYUV:
148 case IMGFMT_I420:
149 return vf_next_query_format(vf, fmt);
151 return 0;
154 static int config(struct vf_instance *vf,
155 int width, int height, int d_width, int d_height,
156 unsigned int flags, unsigned int outfmt)
158 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
160 #endif
162 static void uninit(struct vf_instance *vf)
164 free(vf->priv);
167 static int vf_open(vf_instance_t *vf, char *args)
169 //vf->config = config;
170 vf->put_image = put_image;
171 //vf->query_format = query_format;
172 vf->uninit = uninit;
173 vf->default_reqs = VFCAP_ACCEPT_STRIDE;
174 vf->priv = calloc(1, sizeof(struct vf_priv_s));
175 vf->priv->frame = 1;
176 if (args) sscanf(args, "%d", &vf->priv->frame);
177 vf->priv->frame--;
178 vf->priv->pts = MP_NOPTS_VALUE;
179 vf->priv->lastpts = MP_NOPTS_VALUE;
180 return 1;
183 const vf_info_t vf_info_telecine = {
184 "telecine filter",
185 "telecine",
186 "Rich Felker",
188 vf_open,
189 NULL