8d675e01c61d7ddc885a741b06966f2d1b19d64c
[vlc.git] / modules / video_filter / deinterlace / algo_basic.c
1 /*****************************************************************************
2  * algo_basic.c : Basic algorithms for the VLC deinterlacer
3  *****************************************************************************
4  * Copyright (C) 2000-2011 VLC authors and VideoLAN
5  *
6  * Author: Sam Hocevar <sam@zoy.org>
7  *         Damien Lucas <nitrox@videolan.org>  (Bob, Blend)
8  *         Laurent Aimar <fenrir@videolan.org> (Bob, Blend)
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 #   include "config.h"
27 #endif
28
29 #include <stdint.h>
30 #include <assert.h>
31
32 #include <vlc_common.h>
33 #include <vlc_picture.h>
34 #include <vlc_filter.h>
35
36 #include "merge.h"
37 #include "deinterlace.h" /* definition of p_sys, needed for Merge() */
38
39 #include "algo_basic.h"
40
41 /*****************************************************************************
42  * RenderDiscard: only keep TOP or BOTTOM field, discard the other.
43  *****************************************************************************/
44
45 int RenderDiscard( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
46 {
47     VLC_UNUSED(p_filter);
48     int i_plane;
49
50     /* Copy image and skip lines */
51     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
52     {
53         uint8_t *p_in, *p_out_end, *p_out;
54
55         p_in = p_pic->p[i_plane].p_pixels;
56
57         p_out = p_outpic->p[i_plane].p_pixels;
58         p_out_end = p_out + p_outpic->p[i_plane].i_pitch
59                              * p_outpic->p[i_plane].i_visible_lines;
60
61         for( ; p_out < p_out_end ; )
62         {
63             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
64
65             p_out += p_outpic->p[i_plane].i_pitch;
66             p_in += 2 * p_pic->p[i_plane].i_pitch;
67         }
68     }
69     return VLC_SUCCESS;
70 }
71
72 /*****************************************************************************
73  * RenderBob: renders a BOB picture - simple copy
74  *****************************************************************************/
75
76 int RenderBob( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic,
77                int order, int i_field )
78 {
79     VLC_UNUSED(p_filter);
80     VLC_UNUSED(order);
81     int i_plane;
82
83     /* Copy image and skip lines */
84     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
85     {
86         uint8_t *p_in, *p_out_end, *p_out;
87
88         p_in = p_pic->p[i_plane].p_pixels;
89         p_out = p_outpic->p[i_plane].p_pixels;
90         p_out_end = p_out + p_outpic->p[i_plane].i_pitch
91                              * p_outpic->p[i_plane].i_visible_lines;
92
93         /* For BOTTOM field we need to add the first line */
94         if( i_field == 1 )
95         {
96             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
97             p_in += p_pic->p[i_plane].i_pitch;
98             p_out += p_outpic->p[i_plane].i_pitch;
99         }
100
101         p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
102
103         for( ; p_out < p_out_end ; )
104         {
105             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
106
107             p_out += p_outpic->p[i_plane].i_pitch;
108
109             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
110
111             p_in += 2 * p_pic->p[i_plane].i_pitch;
112             p_out += p_outpic->p[i_plane].i_pitch;
113         }
114
115         memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
116
117         /* For TOP field we need to add the last line */
118         if( i_field == 0 )
119         {
120             p_in += p_pic->p[i_plane].i_pitch;
121             p_out += p_outpic->p[i_plane].i_pitch;
122             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
123         }
124     }
125     return VLC_SUCCESS;
126 }
127
128 /*****************************************************************************
129  * RenderLinear: BOB with linear interpolation
130  *****************************************************************************/
131
132 int RenderLinear( filter_t *p_filter,
133                   picture_t *p_outpic, picture_t *p_pic, int order, int i_field )
134 {
135     VLC_UNUSED(order);
136     int i_plane;
137
138     filter_sys_t *p_sys = p_filter->p_sys;
139
140     /* Copy image and skip lines */
141     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
142     {
143         uint8_t *p_in, *p_out_end, *p_out;
144
145         p_in = p_pic->p[i_plane].p_pixels;
146         p_out = p_outpic->p[i_plane].p_pixels;
147         p_out_end = p_out + p_outpic->p[i_plane].i_pitch
148                              * p_outpic->p[i_plane].i_visible_lines;
149
150         /* For BOTTOM field we need to add the first line */
151         if( i_field == 1 )
152         {
153             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
154             p_in += p_pic->p[i_plane].i_pitch;
155             p_out += p_outpic->p[i_plane].i_pitch;
156         }
157
158         p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
159
160         for( ; p_out < p_out_end ; )
161         {
162             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
163
164             p_out += p_outpic->p[i_plane].i_pitch;
165
166             Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch,
167                    p_pic->p[i_plane].i_pitch );
168
169             p_in += 2 * p_pic->p[i_plane].i_pitch;
170             p_out += p_outpic->p[i_plane].i_pitch;
171         }
172
173         memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
174
175         /* For TOP field we need to add the last line */
176         if( i_field == 0 )
177         {
178             p_in += p_pic->p[i_plane].i_pitch;
179             p_out += p_outpic->p[i_plane].i_pitch;
180             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
181         }
182     }
183     EndMerge();
184     return VLC_SUCCESS;
185 }
186
187 /*****************************************************************************
188  * RenderMean: Half-resolution blender
189  *****************************************************************************/
190
191 int RenderMean( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
192 {
193     int i_plane;
194
195     filter_sys_t *p_sys = p_filter->p_sys;
196
197     /* Copy image and skip lines */
198     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
199     {
200         uint8_t *p_in, *p_out_end, *p_out;
201
202         p_in = p_pic->p[i_plane].p_pixels;
203
204         p_out = p_outpic->p[i_plane].p_pixels;
205         p_out_end = p_out + p_outpic->p[i_plane].i_pitch
206                              * p_outpic->p[i_plane].i_visible_lines;
207
208         /* All lines: mean value */
209         for( ; p_out < p_out_end ; )
210         {
211             Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
212                    p_pic->p[i_plane].i_pitch );
213
214             p_out += p_outpic->p[i_plane].i_pitch;
215             p_in += 2 * p_pic->p[i_plane].i_pitch;
216         }
217     }
218     EndMerge();
219     return VLC_SUCCESS;
220 }
221
222 /*****************************************************************************
223  * RenderBlend: Full-resolution blender
224  *****************************************************************************/
225
226 int RenderBlend( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
227 {
228     int i_plane;
229
230     filter_sys_t *p_sys = p_filter->p_sys;
231
232     /* Copy image and skip lines */
233     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
234     {
235         uint8_t *p_in, *p_out_end, *p_out;
236
237         p_in = p_pic->p[i_plane].p_pixels;
238
239         p_out = p_outpic->p[i_plane].p_pixels;
240         p_out_end = p_out + p_outpic->p[i_plane].i_pitch
241                              * p_outpic->p[i_plane].i_visible_lines;
242
243         /* First line: simple copy */
244         memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
245         p_out += p_outpic->p[i_plane].i_pitch;
246
247         /* Remaining lines: mean value */
248         for( ; p_out < p_out_end ; )
249         {
250             Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
251                    p_pic->p[i_plane].i_pitch );
252
253             p_out += p_outpic->p[i_plane].i_pitch;
254             p_in  += p_pic->p[i_plane].i_pitch;
255         }
256     }
257     EndMerge();
258     return VLC_SUCCESS;
259 }