1 /*****************************************************************************
2 * algo_yadif.c : Wrapper for FFmpeg's Yadif algorithm
3 *****************************************************************************
4 * Copyright (C) 2000-2011 VLC authors and VideoLAN
7 * Author: Laurent Aimar <fenrir@videolan.org>
8 * Juha Jeronen <juha.jeronen@jyu.fi> (soft field repeat hack)
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>
34 #include <vlc_picture.h>
35 #include <vlc_filter.h>
37 #include "deinterlace.h" /* filter_sys_t */
38 #include "common.h" /* FFMIN3 et al. */
40 #include "algo_yadif.h"
42 /*****************************************************************************
43 * Yadif (Yet Another DeInterlacing Filter).
44 *****************************************************************************/
46 /* yadif.h comes from yadif.c of FFmpeg project.
47 Necessary preprocessor macros are defined in common.h. */
50 int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
51 int i_order, int i_field )
55 filter_sys_t *p_sys = p_filter->p_sys;
58 assert( i_order >= 0 && i_order <= 2 ); /* 2 = soft field repeat */
59 assert( i_field == 0 || i_field == 1 );
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];
66 /* Account for soft field repeat.
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;
72 The original parity expression that was used here is:
73 (i_field ^ (i_order == i_field)) & 1
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
81 => equivalent with e.g. (1 - i_order) or (i_order + 1) % 2
83 Thus, in a normal two-field frame,
84 parity 1 = first field (i_order == 0)
85 parity 0 = second field (i_order == 1)
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
95 i_order = 2 => parity 0 (as usual)
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". */
102 yadif_parity = (i_order + 1) % 2; /* 1, 0 */
104 /* Filter if we have all the pictures we need */
105 if( p_prev && p_cur && p_next )
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);
111 #if defined(HAVE_YADIF_SSSE3)
112 if( vlc_CPU_SSSE3() )
113 filter = yadif_filter_line_ssse3;
116 #if defined(HAVE_YADIF_SSE2)
118 filter = yadif_filter_line_sse2;
121 #if defined(HAVE_YADIF_MMX)
123 filter = yadif_filter_line_mmx;
126 filter = yadif_filter_line_c;
128 if( p_sys->chroma->pixel_size == 2 )
129 filter = yadif_filter_line_c_16bit;
131 for( int n = 0; n < p_dst->i_planes; n++ )
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];
138 for( int y = 1; y < dstp->i_visible_lines - 1; y++ )
140 if( (y % 2) == i_field || yadif_parity == 2 )
142 memcpy( &dstp->p_pixels[y * dstp->i_pitch],
143 &curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch );
148 /* Spatial checks only when enough data */
149 mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2;
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,
163 /* We duplicate the first and last lines */
165 memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch],
166 &dstp->p_pixels[ y * 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],
175 p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame, too */
179 else if( !p_prev && !p_cur && p_next )
181 /* NOTE: For the first frame, we use the default frame offset
182 as set by Open() or SetFilterMethod(). It is always 0. */
184 /* FIXME not good as it does not use i_order/i_field */
185 RenderX( p_dst, p_next );
190 p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame */