1 /*****************************************************************************
2 * algo_yadif.c : Wrapper for MPlayer's Yadif algorithm
3 *****************************************************************************
4 * Copyright (C) 2000-2011 the VideoLAN team
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
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
29 #ifdef CAN_COMPILE_MMXEXT
36 #include <vlc_common.h>
38 #include <vlc_picture.h>
39 #include <vlc_filter.h>
41 #include "deinterlace.h" /* filter_sys_t */
42 #include "common.h" /* FFMIN3 et al. */
44 #include "algo_yadif.h"
46 /*****************************************************************************
47 * Yadif (Yet Another DeInterlacing Filter).
48 *****************************************************************************/
50 /* Yadif's private data struct */
53 * 0: Output 1 frame for each frame.
54 * 1: Output 1 frame for each field.
55 * 2: Like 0 but skips spatial interlacing check.
56 * 3: Like 1 but skips spatial interlacing check.
58 * In vlc, only & 0x02 has meaning, as we do the & 0x01 ourself.
63 /* I am unsure it is the right one */
64 typedef intptr_t x86_reg;
66 /* yadif.h comes from vf_yadif.c of mplayer project.
67 Necessary preprocessor macros are defined in common.h. */
70 int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
71 int i_order, int i_field )
75 filter_sys_t *p_sys = p_filter->p_sys;
78 assert( i_order >= 0 && i_order <= 2 ); /* 2 = soft field repeat */
79 assert( i_field == 0 || i_field == 1 );
81 /* As the pitches must match, use ONLY pictures coming from picture_New()! */
82 picture_t *p_prev = p_sys->pp_history[0];
83 picture_t *p_cur = p_sys->pp_history[1];
84 picture_t *p_next = p_sys->pp_history[2];
86 /* Account for soft field repeat.
88 The "parity" parameter affects the algorithm like this (from yadif.h):
89 uint8_t *prev2= parity ? prev : cur ;
90 uint8_t *next2= parity ? cur : next;
92 The original parity expression that was used here is:
93 (i_field ^ (i_order == i_field)) & 1
96 i_field = 0, i_order = 0 => 1
97 i_field = 1, i_order = 1 => 0
98 i_field = 1, i_order = 0 => 1
99 i_field = 0, i_order = 1 => 0
101 => equivalent with e.g. (1 - i_order) or (i_order + 1) % 2
103 Thus, in a normal two-field frame,
104 parity 1 = first field (i_order == 0)
105 parity 0 = second field (i_order == 1)
107 Now, with three fields, where the third is a copy of the first,
108 i_order = 0 => parity 1 (as usual)
109 i_order = 1 => due to the repeat, prev = cur, but also next = cur.
110 Because in such a case there is no motion
111 (otherwise field repeat makes no sense),
112 we don't actually need to invoke Yadif's filter().
113 Thus, set "parity" to 2, and use this to bypass
115 i_order = 2 => parity 0 (as usual)
118 if( p_cur && p_cur->i_nb_fields > 2 )
119 yadif_parity = (i_order + 1) % 3; /* 1, *2*, 0; where 2 is a special
120 value meaning "bypass filter". */
122 yadif_parity = (i_order + 1) % 2; /* 1, 0 */
124 /* Filter if we have all the pictures we need */
125 if( p_prev && p_cur && p_next )
128 void (*filter)(struct vf_priv_s *p, uint8_t *dst,
129 uint8_t *prev, uint8_t *cur, uint8_t *next,
130 int w, int refs, int parity);
131 #if defined(HAVE_YADIF_SSE2)
132 if( vlc_CPU() & CPU_CAPABILITY_SSE2 )
133 filter = yadif_filter_line_mmx2;
136 filter = yadif_filter_line_c;
138 for( int n = 0; n < p_dst->i_planes; n++ )
140 const plane_t *prevp = &p_prev->p[n];
141 const plane_t *curp = &p_cur->p[n];
142 const plane_t *nextp = &p_next->p[n];
143 plane_t *dstp = &p_dst->p[n];
145 for( int y = 1; y < dstp->i_visible_lines - 1; y++ )
147 if( (y % 2) == i_field || yadif_parity == 2 )
149 vlc_memcpy( &dstp->p_pixels[y * dstp->i_pitch],
150 &curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch );
154 struct vf_priv_s cfg;
155 /* Spatial checks only when enough data */
156 cfg.mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2;
158 assert( prevp->i_pitch == curp->i_pitch && curp->i_pitch == nextp->i_pitch );
160 &dstp->p_pixels[y * dstp->i_pitch],
161 &prevp->p_pixels[y * prevp->i_pitch],
162 &curp->p_pixels[y * curp->i_pitch],
163 &nextp->p_pixels[y * nextp->i_pitch],
164 dstp->i_visible_pitch,
169 /* We duplicate the first and last lines */
171 vlc_memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch],
172 &dstp->p_pixels[ y * dstp->i_pitch],
174 else if( y == dstp->i_visible_lines - 2 )
175 vlc_memcpy(&dstp->p_pixels[(y+1) * dstp->i_pitch],
176 &dstp->p_pixels[ y * dstp->i_pitch],
181 p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame, too */
185 else if( !p_prev && !p_cur && p_next )
187 /* NOTE: For the first frame, we use the default frame offset
188 as set by Open() or SetFilterMethod(). It is always 0. */
190 /* FIXME not good as it does not use i_order/i_field */
191 RenderX( p_dst, p_next );
196 p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame */