FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vf_softpulldown.c
Go to the documentation of this file.
1 /*
2  * This file is part of MPlayer.
3  *
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.
8  *
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.
13  *
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.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "config.h"
24 #include "mp_msg.h"
25 
26 #include "img_format.h"
27 #include "mp_image.h"
28 #include "vf.h"
29 
30 #include "libvo/fastmemcpy.h"
31 
32 struct vf_priv_s {
33  int state;
34  long long in;
35  long long out;
36 };
37 
38 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
39 {
40  mp_image_t *dmpi;
41  int ret = 0;
42  int flags = mpi->fields;
43  int state = vf->priv->state;
44 
45  dmpi = ff_vf_get_image(vf->next, mpi->imgfmt,
47  MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
48 
49  vf->priv->in++;
50 
51  if ((state == 0 &&
52  !(flags & MP_IMGFIELD_TOP_FIRST)) ||
53  (state == 1 &&
54  flags & MP_IMGFIELD_TOP_FIRST)) {
56  "softpulldown: Unexpected field flags: state=%d top_field_first=%d repeat_first_field=%d\n",
57  state,
58  (flags & MP_IMGFIELD_TOP_FIRST) != 0,
59  (flags & MP_IMGFIELD_REPEAT_FIRST) != 0);
60  state ^= 1;
61  }
62 
63  if (state == 0) {
64  ret = ff_vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
65  vf->priv->out++;
66  if (flags & MP_IMGFIELD_REPEAT_FIRST) {
67  my_memcpy_pic(dmpi->planes[0],
68  mpi->planes[0], mpi->w, mpi->h/2,
69  dmpi->stride[0]*2, mpi->stride[0]*2);
70  if (mpi->flags & MP_IMGFLAG_PLANAR) {
71  my_memcpy_pic(dmpi->planes[1],
72  mpi->planes[1],
73  mpi->chroma_width,
74  mpi->chroma_height/2,
75  dmpi->stride[1]*2,
76  mpi->stride[1]*2);
77  my_memcpy_pic(dmpi->planes[2],
78  mpi->planes[2],
79  mpi->chroma_width,
80  mpi->chroma_height/2,
81  dmpi->stride[2]*2,
82  mpi->stride[2]*2);
83  }
84  state=1;
85  }
86  } else {
87  my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
88  mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
89  dmpi->stride[0]*2, mpi->stride[0]*2);
90  if (mpi->flags & MP_IMGFLAG_PLANAR) {
91  my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
92  mpi->planes[1]+mpi->stride[1],
93  mpi->chroma_width, mpi->chroma_height/2,
94  dmpi->stride[1]*2, mpi->stride[1]*2);
95  my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
96  mpi->planes[2]+mpi->stride[2],
97  mpi->chroma_width, mpi->chroma_height/2,
98  dmpi->stride[2]*2, mpi->stride[2]*2);
99  }
100  ret = ff_vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
101  vf->priv->out++;
102  if (flags & MP_IMGFIELD_REPEAT_FIRST) {
103  ret |= ff_vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
104  vf->priv->out++;
105  state=0;
106  } else {
107  my_memcpy_pic(dmpi->planes[0],
108  mpi->planes[0], mpi->w, mpi->h/2,
109  dmpi->stride[0]*2, mpi->stride[0]*2);
110  if (mpi->flags & MP_IMGFLAG_PLANAR) {
111  my_memcpy_pic(dmpi->planes[1],
112  mpi->planes[1],
113  mpi->chroma_width,
114  mpi->chroma_height/2,
115  dmpi->stride[1]*2,
116  mpi->stride[1]*2);
117  my_memcpy_pic(dmpi->planes[2],
118  mpi->planes[2],
119  mpi->chroma_width,
120  mpi->chroma_height/2,
121  dmpi->stride[2]*2,
122  mpi->stride[2]*2);
123  }
124  }
125  }
126 
127  vf->priv->state = state;
128 
129  return ret;
130 }
131 
132 static int config(struct vf_instance *vf,
133  int width, int height, int d_width, int d_height,
134  unsigned int flags, unsigned int outfmt)
135 {
136  return ff_vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
137 }
138 
139 static void uninit(struct vf_instance *vf)
140 {
141  ff_mp_msg(MSGT_VFILTER, MSGL_INFO, "softpulldown: %lld frames in, %lld frames out\n", vf->priv->in, vf->priv->out);
142  free(vf->priv);
143 }
144 
145 static int vf_open(vf_instance_t *vf, char *args)
146 {
147  vf->config = config;
148  vf->put_image = put_image;
149  vf->uninit = uninit;
151  vf->priv = calloc(1, sizeof(struct vf_priv_s));
152  vf->priv->state = 0;
153  return 1;
154 }
155 
157  "mpeg2 soft 3:2 pulldown",
158  "softpulldown",
159  "Tobias Diedrich <ranma+mplayer@tdiedrich.de>",
160  "",
161  vf_open,
162  NULL
163 };