]> git.sesse.net Git - vlc/blob - modules/video_filter/deinterlace/algo_yadif.c
Qt: change tools accessor
[vlc] / modules / video_filter / deinterlace / algo_yadif.c
1 /*****************************************************************************
2  * algo_yadif.c : Wrapper for FFmpeg's Yadif algorithm
3  *****************************************************************************
4  * Copyright (C) 2000-2011 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Author: Laurent Aimar <fenrir@videolan.org>
8  *         Juha Jeronen  <juha.jeronen@jyu.fi> (soft field repeat hack)
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_cpu.h>
34 #include <vlc_picture.h>
35 #include <vlc_filter.h>
36
37 #include "deinterlace.h" /* filter_sys_t  */
38 #include "common.h"      /* FFMIN3 et al. */
39
40 #include "algo_yadif.h"
41
42 /*****************************************************************************
43  * Yadif (Yet Another DeInterlacing Filter).
44  *****************************************************************************/
45
46 /* yadif.h comes from yadif.c of FFmpeg project.
47    Necessary preprocessor macros are defined in common.h. */
48 #include "yadif.h"
49
50 int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
51                  int i_order, int i_field )
52 {
53     VLC_UNUSED(p_src);
54
55     filter_sys_t *p_sys = p_filter->p_sys;
56
57     /* */
58     assert( i_order >= 0 && i_order <= 2 ); /* 2 = soft field repeat */
59     assert( i_field == 0 || i_field == 1 );
60
61     /* As the pitches must match, use ONLY pictures coming from picture_New()! */
62     picture_t *p_prev = p_sys->pp_history[0];
63     picture_t *p_cur  = p_sys->pp_history[1];
64     picture_t *p_next = p_sys->pp_history[2];
65
66     /* Account for soft field repeat.
67
68        The "parity" parameter affects the algorithm like this (from yadif.h):
69        uint8_t *prev2= parity ? prev : cur ;
70        uint8_t *next2= parity ? cur  : next;
71
72        The original parity expression that was used here is:
73        (i_field ^ (i_order == i_field)) & 1
74
75        Truth table:
76        i_field = 0, i_order = 0  => 1
77        i_field = 1, i_order = 1  => 0
78        i_field = 1, i_order = 0  => 1
79        i_field = 0, i_order = 1  => 0
80
81        => equivalent with e.g.  (1 - i_order)  or  (i_order + 1) % 2
82
83        Thus, in a normal two-field frame,
84              parity 1 = first field  (i_order == 0)
85              parity 0 = second field (i_order == 1)
86
87        Now, with three fields, where the third is a copy of the first,
88              i_order = 0  =>  parity 1 (as usual)
89              i_order = 1  =>  due to the repeat, prev = cur, but also next = cur.
90                               Because in such a case there is no motion
91                               (otherwise field repeat makes no sense),
92                               we don't actually need to invoke Yadif's filter().
93                               Thus, set "parity" to 2, and use this to bypass
94                               the filter.
95              i_order = 2  =>  parity 0 (as usual)
96     */
97     int yadif_parity;
98     if( p_cur  &&  p_cur->i_nb_fields > 2 )
99         yadif_parity = (i_order + 1) % 3; /* 1, *2*, 0; where 2 is a special
100                                              value meaning "bypass filter". */
101     else
102         yadif_parity = (i_order + 1) % 2; /* 1, 0 */
103
104     /* Filter if we have all the pictures we need */
105     if( p_prev && p_cur && p_next )
106     {
107         /* */
108         void (*filter)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next,
109                        int w, int prefs, int mrefs, int parity, int mode);
110
111 #if defined(HAVE_YADIF_SSSE3)
112         if( vlc_CPU_SSSE3() )
113             filter = yadif_filter_line_ssse3;
114         else
115 #endif
116 #if defined(HAVE_YADIF_SSE2)
117         if( vlc_CPU_SSE2() )
118             filter = yadif_filter_line_sse2;
119         else
120 #endif
121 #if defined(HAVE_YADIF_MMX)
122         if( vlc_CPU_MMX() )
123             filter = yadif_filter_line_mmx;
124         else
125 #endif
126             filter = yadif_filter_line_c;
127
128         if( p_sys->chroma->pixel_size == 2 )
129             filter = yadif_filter_line_c_16bit;
130
131         for( int n = 0; n < p_dst->i_planes; n++ )
132         {
133             const plane_t *prevp = &p_prev->p[n];
134             const plane_t *curp  = &p_cur->p[n];
135             const plane_t *nextp = &p_next->p[n];
136             plane_t *dstp        = &p_dst->p[n];
137
138             for( int y = 1; y < dstp->i_visible_lines - 1; y++ )
139             {
140                 if( (y % 2) == i_field  ||  yadif_parity == 2 )
141                 {
142                     memcpy( &dstp->p_pixels[y * dstp->i_pitch],
143                                 &curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch );
144                 }
145                 else
146                 {
147                     int mode;
148                     /* Spatial checks only when enough data */
149                     mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2;
150
151                     assert( prevp->i_pitch == curp->i_pitch && curp->i_pitch == nextp->i_pitch );
152                     filter( &dstp->p_pixels[y * dstp->i_pitch],
153                             &prevp->p_pixels[y * prevp->i_pitch],
154                             &curp->p_pixels[y * curp->i_pitch],
155                             &nextp->p_pixels[y * nextp->i_pitch],
156                             dstp->i_visible_pitch,
157                             y < dstp->i_visible_lines - 2  ? curp->i_pitch : -curp->i_pitch,
158                             y  - 1  ?  -curp->i_pitch : curp->i_pitch,
159                             yadif_parity,
160                             mode );
161                 }
162
163                 /* We duplicate the first and last lines */
164                 if( y == 1 )
165                     memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch],
166                                &dstp->p_pixels[ y    * dstp->i_pitch],
167                                dstp->i_pitch);
168                 else if( y == dstp->i_visible_lines - 2 )
169                     memcpy(&dstp->p_pixels[(y+1) * dstp->i_pitch],
170                                &dstp->p_pixels[ y    * dstp->i_pitch],
171                                dstp->i_pitch);
172             }
173         }
174
175         p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame, too */
176
177         return VLC_SUCCESS;
178     }
179     else if( !p_prev && !p_cur && p_next )
180     {
181         /* NOTE: For the first frame, we use the default frame offset
182                  as set by Open() or SetFilterMethod(). It is always 0. */
183
184         /* FIXME not good as it does not use i_order/i_field */
185         RenderX( p_dst, p_next );
186         return VLC_SUCCESS;
187     }
188     else
189     {
190         p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame */
191
192         return VLC_EGENERIC;
193     }
194 }