Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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, | |
46 | MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | | |
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)) { | |
55 | ff_mp_msg(MSGT_VFILTER, MSGL_WARN, | |
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; | |
150 | vf->default_reqs = VFCAP_ACCEPT_STRIDE; | |
151 | vf->priv = calloc(1, sizeof(struct vf_priv_s)); | |
152 | vf->priv->state = 0; | |
153 | return 1; | |
154 | } | |
155 | ||
156 | const vf_info_t ff_vf_info_softpulldown = { | |
157 | "mpeg2 soft 3:2 pulldown", | |
158 | "softpulldown", | |
159 | "Tobias Diedrich <ranma+mplayer@tdiedrich.de>", | |
160 | "", | |
161 | vf_open, | |
162 | NULL | |
163 | }; |