1 /*****************************************************************************
2 * algo_yadif.c : Wrapper for MPlayer's Yadif algorithm
3 *****************************************************************************
4 * Copyright (C) 2000-2011 the VideoLAN team
7 * Author: Sam Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #ifdef CAN_COMPILE_MMXEXT
35 #include <vlc_common.h>
37 #include <vlc_picture.h>
38 #include <vlc_filter.h>
40 #include "deinterlace.h" /* filter_sys_t */
41 #include "common.h" /* FFMIN3 et al. */
43 #include "algo_yadif.h"
45 /*****************************************************************************
46 * Yadif (Yet Another DeInterlacing Filter).
47 *****************************************************************************/
49 /* Yadif's private data struct */
52 * 0: Output 1 frame for each frame.
53 * 1: Output 1 frame for each field.
54 * 2: Like 0 but skips spatial interlacing check.
55 * 3: Like 1 but skips spatial interlacing check.
57 * In vlc, only & 0x02 has meaning, as we do the & 0x01 ourself.
62 /* I am unsure it is the right one */
63 typedef intptr_t x86_reg;
65 /* yadif.h comes from vf_yadif.c of mplayer project.
66 Necessary preprocessor macros are defined in common.h. */
69 int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
70 int i_order, int i_field )
74 filter_sys_t *p_sys = p_filter->p_sys;
77 assert( i_order >= 0 && i_order <= 2 ); /* 2 = soft field repeat */
78 assert( i_field == 0 || i_field == 1 );
80 /* As the pitches must match, use ONLY pictures coming from picture_New()! */
81 picture_t *p_prev = p_sys->pp_history[0];
82 picture_t *p_cur = p_sys->pp_history[1];
83 picture_t *p_next = p_sys->pp_history[2];
85 /* Account for soft field repeat.
87 The "parity" parameter affects the algorithm like this (from yadif.h):
88 uint8_t *prev2= parity ? prev : cur ;
89 uint8_t *next2= parity ? cur : next;
91 The original parity expression that was used here is:
92 (i_field ^ (i_order == i_field)) & 1
95 i_field = 0, i_order = 0 => 1
96 i_field = 1, i_order = 1 => 0
97 i_field = 1, i_order = 0 => 1
98 i_field = 0, i_order = 1 => 0
100 => equivalent with e.g. (1 - i_order) or (i_order + 1) % 2
102 Thus, in a normal two-field frame,
103 parity 1 = first field (i_order == 0)
104 parity 0 = second field (i_order == 1)
106 Now, with three fields, where the third is a copy of the first,
107 i_order = 0 => parity 1 (as usual)
108 i_order = 1 => due to the repeat, prev = cur, but also next = cur.
109 Because in such a case there is no motion
110 (otherwise field repeat makes no sense),
111 we don't actually need to invoke Yadif's filter().
112 Thus, set "parity" to 2, and use this to bypass
114 i_order = 2 => parity 0 (as usual)
117 if( p_cur && p_cur->i_nb_fields > 2 )
118 yadif_parity = (i_order + 1) % 3; /* 1, *2*, 0; where 2 is a special
119 value meaning "bypass filter". */
121 yadif_parity = (i_order + 1) % 2; /* 1, 0 */
123 /* Filter if we have all the pictures we need */
124 if( p_prev && p_cur && p_next )
127 void (*filter)(struct vf_priv_s *p, uint8_t *dst,
128 uint8_t *prev, uint8_t *cur, uint8_t *next,
129 int w, int refs, int parity);
130 #if defined(HAVE_YADIF_SSE2)
131 if( vlc_CPU() & CPU_CAPABILITY_SSE2 )
132 filter = yadif_filter_line_mmx2;
135 filter = yadif_filter_line_c;
137 for( int n = 0; n < p_dst->i_planes; n++ )
139 const plane_t *prevp = &p_prev->p[n];
140 const plane_t *curp = &p_cur->p[n];
141 const plane_t *nextp = &p_next->p[n];
142 plane_t *dstp = &p_dst->p[n];
144 for( int y = 1; y < dstp->i_visible_lines - 1; y++ )
146 if( (y % 2) == i_field || yadif_parity == 2 )
148 vlc_memcpy( &dstp->p_pixels[y * dstp->i_pitch],
149 &curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch );
153 struct vf_priv_s cfg;
154 /* Spatial checks only when enough data */
155 cfg.mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2;
157 assert( prevp->i_pitch == curp->i_pitch && curp->i_pitch == nextp->i_pitch );
159 &dstp->p_pixels[y * dstp->i_pitch],
160 &prevp->p_pixels[y * prevp->i_pitch],
161 &curp->p_pixels[y * curp->i_pitch],
162 &nextp->p_pixels[y * nextp->i_pitch],
163 dstp->i_visible_pitch,
168 /* We duplicate the first and last lines */
170 vlc_memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch],
171 &dstp->p_pixels[ y * dstp->i_pitch],
173 else if( y == dstp->i_visible_lines - 2 )
174 vlc_memcpy(&dstp->p_pixels[(y+1) * dstp->i_pitch],
175 &dstp->p_pixels[ y * dstp->i_pitch],
180 p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame, too */
184 else if( !p_prev && !p_cur && p_next )
186 /* NOTE: For the first frame, we use the default frame offset
187 as set by Open() or SetFilterMethod(). It is always 0. */
189 /* FIXME not good as it does not use i_order/i_field */
190 RenderX( p_dst, p_next );
195 p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame */