1 /*****************************************************************************
2 * algo_basic.c : Basic algorithms for the VLC deinterlacer
3 *****************************************************************************
4 * Copyright (C) 2000-2011 VLC authors and VideoLAN
6 * Author: Sam Hocevar <sam@zoy.org>
7 * Damien Lucas <nitrox@videolan.org> (Bob, Blend)
8 * Laurent Aimar <fenrir@videolan.org> (Bob, Blend)
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.
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.
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 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_picture.h>
34 #include <vlc_filter.h>
37 #include "deinterlace.h" /* definition of p_sys, needed for Merge() */
39 #include "algo_basic.h"
41 /*****************************************************************************
42 * RenderDiscard: only keep TOP or BOTTOM field, discard the other.
43 *****************************************************************************/
45 int RenderDiscard( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
50 /* Copy image and skip lines */
51 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
53 uint8_t *p_in, *p_out_end, *p_out;
55 p_in = p_pic->p[i_plane].p_pixels;
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;
61 for( ; p_out < p_out_end ; )
63 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
65 p_out += p_outpic->p[i_plane].i_pitch;
66 p_in += 2 * p_pic->p[i_plane].i_pitch;
72 /*****************************************************************************
73 * RenderBob: renders a BOB picture - simple copy
74 *****************************************************************************/
76 int RenderBob( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic,
77 int order, int i_field )
83 /* Copy image and skip lines */
84 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
86 uint8_t *p_in, *p_out_end, *p_out;
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;
93 /* For BOTTOM field we need to add the first line */
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;
101 p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
103 for( ; p_out < p_out_end ; )
105 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
107 p_out += p_outpic->p[i_plane].i_pitch;
109 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
111 p_in += 2 * p_pic->p[i_plane].i_pitch;
112 p_out += p_outpic->p[i_plane].i_pitch;
115 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
117 /* For TOP field we need to add the last line */
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 );
128 /*****************************************************************************
129 * RenderLinear: BOB with linear interpolation
130 *****************************************************************************/
132 int RenderLinear( filter_t *p_filter,
133 picture_t *p_outpic, picture_t *p_pic, int order, int i_field )
138 filter_sys_t *p_sys = p_filter->p_sys;
140 /* Copy image and skip lines */
141 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
143 uint8_t *p_in, *p_out_end, *p_out;
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;
150 /* For BOTTOM field we need to add the first line */
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;
158 p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
160 for( ; p_out < p_out_end ; )
162 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
164 p_out += p_outpic->p[i_plane].i_pitch;
166 Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch,
167 p_pic->p[i_plane].i_pitch );
169 p_in += 2 * p_pic->p[i_plane].i_pitch;
170 p_out += p_outpic->p[i_plane].i_pitch;
173 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
175 /* For TOP field we need to add the last line */
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 );
187 /*****************************************************************************
188 * RenderMean: Half-resolution blender
189 *****************************************************************************/
191 int RenderMean( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
195 filter_sys_t *p_sys = p_filter->p_sys;
197 /* Copy image and skip lines */
198 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
200 uint8_t *p_in, *p_out_end, *p_out;
202 p_in = p_pic->p[i_plane].p_pixels;
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;
208 /* All lines: mean value */
209 for( ; p_out < p_out_end ; )
211 Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
212 p_pic->p[i_plane].i_pitch );
214 p_out += p_outpic->p[i_plane].i_pitch;
215 p_in += 2 * p_pic->p[i_plane].i_pitch;
222 /*****************************************************************************
223 * RenderBlend: Full-resolution blender
224 *****************************************************************************/
226 int RenderBlend( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
230 filter_sys_t *p_sys = p_filter->p_sys;
232 /* Copy image and skip lines */
233 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
235 uint8_t *p_in, *p_out_end, *p_out;
237 p_in = p_pic->p[i_plane].p_pixels;
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;
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;
247 /* Remaining lines: mean value */
248 for( ; p_out < p_out_end ; )
250 Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
251 p_pic->p[i_plane].i_pitch );
253 p_out += p_outpic->p[i_plane].i_pitch;
254 p_in += p_pic->p[i_plane].i_pitch;