]> git.sesse.net Git - vlc/blob - modules/video_filter/deinterlace/algo_basic.c
postproc: reduce lock contention in callback
[vlc] / 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  * $Id$
6  *
7  * Author: Sam Hocevar <sam@zoy.org>
8  *         Damien Lucas <nitrox@videolan.org>  (Bob, Blend)
9  *         Laurent Aimar <fenrir@videolan.org> (Bob, Blend)
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 #   include "config.h"
28 #endif
29
30 #include <stdint.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 void RenderDiscard( picture_t *p_outpic, picture_t *p_pic, int i_field )
46 {
47     int i_plane;
48
49     /* Copy image and skip lines */
50     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
51     {
52         uint8_t *p_in, *p_out_end, *p_out;
53
54         p_in = p_pic->p[i_plane].p_pixels
55                    + i_field * p_pic->p[i_plane].i_pitch;
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 }
70
71 /*****************************************************************************
72  * RenderBob: renders a BOB picture - simple copy
73  *****************************************************************************/
74
75 void RenderBob( picture_t *p_outpic, picture_t *p_pic, int i_field )
76 {
77     int i_plane;
78
79     /* Copy image and skip lines */
80     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
81     {
82         uint8_t *p_in, *p_out_end, *p_out;
83
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;
88
89         /* For BOTTOM field we need to add the first line */
90         if( i_field == 1 )
91         {
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;
95         }
96
97         p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
98
99         for( ; p_out < p_out_end ; )
100         {
101             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
102
103             p_out += p_outpic->p[i_plane].i_pitch;
104
105             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
106
107             p_in += 2 * p_pic->p[i_plane].i_pitch;
108             p_out += p_outpic->p[i_plane].i_pitch;
109         }
110
111         memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
112
113         /* For TOP field we need to add the last line */
114         if( i_field == 0 )
115         {
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 );
119         }
120     }
121 }
122
123 /*****************************************************************************
124  * RenderLinear: BOB with linear interpolation
125  *****************************************************************************/
126
127 void RenderLinear( filter_t *p_filter,
128                    picture_t *p_outpic, picture_t *p_pic, int i_field )
129 {
130     int i_plane;
131
132     /* Copy image and skip lines */
133     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
134     {
135         uint8_t *p_in, *p_out_end, *p_out;
136
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;
141
142         /* For BOTTOM field we need to add the first line */
143         if( i_field == 1 )
144         {
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;
148         }
149
150         p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
151
152         for( ; p_out < p_out_end ; )
153         {
154             memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
155
156             p_out += p_outpic->p[i_plane].i_pitch;
157
158             Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch,
159                    p_pic->p[i_plane].i_pitch );
160
161             p_in += 2 * p_pic->p[i_plane].i_pitch;
162             p_out += p_outpic->p[i_plane].i_pitch;
163         }
164
165         memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
166
167         /* For TOP field we need to add the last line */
168         if( i_field == 0 )
169         {
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 );
173         }
174     }
175     EndMerge();
176 }
177
178 /*****************************************************************************
179  * RenderMean: Half-resolution blender
180  *****************************************************************************/
181
182 void RenderMean( filter_t *p_filter,
183                  picture_t *p_outpic, picture_t *p_pic )
184 {
185     int i_plane;
186
187     /* Copy image and skip lines */
188     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
189     {
190         uint8_t *p_in, *p_out_end, *p_out;
191
192         p_in = p_pic->p[i_plane].p_pixels;
193
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;
197
198         /* All lines: mean value */
199         for( ; p_out < p_out_end ; )
200         {
201             Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
202                    p_pic->p[i_plane].i_pitch );
203
204             p_out += p_outpic->p[i_plane].i_pitch;
205             p_in += 2 * p_pic->p[i_plane].i_pitch;
206         }
207     }
208     EndMerge();
209 }
210
211 /*****************************************************************************
212  * RenderBlend: Full-resolution blender
213  *****************************************************************************/
214
215 void RenderBlend( filter_t *p_filter,
216                   picture_t *p_outpic, picture_t *p_pic )
217 {
218     int i_plane;
219
220     /* Copy image and skip lines */
221     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
222     {
223         uint8_t *p_in, *p_out_end, *p_out;
224
225         p_in = p_pic->p[i_plane].p_pixels;
226
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;
230
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;
234
235         /* Remaining lines: mean value */
236         for( ; p_out < p_out_end ; )
237         {
238             Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
239                    p_pic->p[i_plane].i_pitch );
240
241             p_out += p_outpic->p[i_plane].i_pitch;
242             p_in  += p_pic->p[i_plane].i_pitch;
243         }
244     }
245     EndMerge();
246 }