1 /*****************************************************************************
2 * algo_basic.c : Basic algorithms for the VLC deinterlacer
3 *****************************************************************************
4 * Copyright (C) 2000-2011 VLC authors and VideoLAN
7 * Author: Sam Hocevar <sam@zoy.org>
8 * Damien Lucas <nitrox@videolan.org> (Bob, Blend)
9 * Laurent Aimar <fenrir@videolan.org> (Bob, Blend)
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
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 void RenderDiscard( picture_t *p_outpic, picture_t *p_pic, int i_field )
49 /* Copy image and skip lines */
50 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
52 uint8_t *p_in, *p_out_end, *p_out;
54 p_in = p_pic->p[i_plane].p_pixels
55 + i_field * p_pic->p[i_plane].i_pitch;
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;
71 /*****************************************************************************
72 * RenderBob: renders a BOB picture - simple copy
73 *****************************************************************************/
75 void RenderBob( picture_t *p_outpic, picture_t *p_pic, int i_field )
79 /* Copy image and skip lines */
80 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
82 uint8_t *p_in, *p_out_end, *p_out;
84 p_in = p_pic->p[i_plane].p_pixels;
85 p_out = p_outpic->p[i_plane].p_pixels;
86 p_out_end = p_out + p_outpic->p[i_plane].i_pitch
87 * p_outpic->p[i_plane].i_visible_lines;
89 /* For BOTTOM field we need to add the first line */
92 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
93 p_in += p_pic->p[i_plane].i_pitch;
94 p_out += p_outpic->p[i_plane].i_pitch;
97 p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
99 for( ; p_out < p_out_end ; )
101 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
103 p_out += p_outpic->p[i_plane].i_pitch;
105 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
107 p_in += 2 * p_pic->p[i_plane].i_pitch;
108 p_out += p_outpic->p[i_plane].i_pitch;
111 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
113 /* For TOP field we need to add the last line */
116 p_in += p_pic->p[i_plane].i_pitch;
117 p_out += p_outpic->p[i_plane].i_pitch;
118 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
123 /*****************************************************************************
124 * RenderLinear: BOB with linear interpolation
125 *****************************************************************************/
127 void RenderLinear( filter_t *p_filter,
128 picture_t *p_outpic, picture_t *p_pic, int i_field )
132 /* Copy image and skip lines */
133 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
135 uint8_t *p_in, *p_out_end, *p_out;
137 p_in = p_pic->p[i_plane].p_pixels;
138 p_out = p_outpic->p[i_plane].p_pixels;
139 p_out_end = p_out + p_outpic->p[i_plane].i_pitch
140 * p_outpic->p[i_plane].i_visible_lines;
142 /* For BOTTOM field we need to add the first line */
145 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
146 p_in += p_pic->p[i_plane].i_pitch;
147 p_out += p_outpic->p[i_plane].i_pitch;
150 p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
152 for( ; p_out < p_out_end ; )
154 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
156 p_out += p_outpic->p[i_plane].i_pitch;
158 Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch,
159 p_pic->p[i_plane].i_pitch );
161 p_in += 2 * p_pic->p[i_plane].i_pitch;
162 p_out += p_outpic->p[i_plane].i_pitch;
165 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
167 /* For TOP field we need to add the last line */
170 p_in += p_pic->p[i_plane].i_pitch;
171 p_out += p_outpic->p[i_plane].i_pitch;
172 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
178 /*****************************************************************************
179 * RenderMean: Half-resolution blender
180 *****************************************************************************/
182 void RenderMean( filter_t *p_filter,
183 picture_t *p_outpic, picture_t *p_pic )
187 /* Copy image and skip lines */
188 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
190 uint8_t *p_in, *p_out_end, *p_out;
192 p_in = p_pic->p[i_plane].p_pixels;
194 p_out = p_outpic->p[i_plane].p_pixels;
195 p_out_end = p_out + p_outpic->p[i_plane].i_pitch
196 * p_outpic->p[i_plane].i_visible_lines;
198 /* All lines: mean value */
199 for( ; p_out < p_out_end ; )
201 Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
202 p_pic->p[i_plane].i_pitch );
204 p_out += p_outpic->p[i_plane].i_pitch;
205 p_in += 2 * p_pic->p[i_plane].i_pitch;
211 /*****************************************************************************
212 * RenderBlend: Full-resolution blender
213 *****************************************************************************/
215 void RenderBlend( filter_t *p_filter,
216 picture_t *p_outpic, picture_t *p_pic )
220 /* Copy image and skip lines */
221 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
223 uint8_t *p_in, *p_out_end, *p_out;
225 p_in = p_pic->p[i_plane].p_pixels;
227 p_out = p_outpic->p[i_plane].p_pixels;
228 p_out_end = p_out + p_outpic->p[i_plane].i_pitch
229 * p_outpic->p[i_plane].i_visible_lines;
231 /* First line: simple copy */
232 memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
233 p_out += p_outpic->p[i_plane].i_pitch;
235 /* Remaining lines: mean value */
236 for( ; p_out < p_out_end ; )
238 Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
239 p_pic->p[i_plane].i_pitch );
241 p_out += p_outpic->p[i_plane].i_pitch;
242 p_in += p_pic->p[i_plane].i_pitch;