118
122
#define FILTER_CFG_PREFIX "sout-deinterlace-"
120
124
static const char *const mode_list[] = {
121
"discard", "blend", "mean", "bob", "linear", "x" };
125
"discard", "blend", "mean", "bob", "linear", "x", "yadif", "yadif2x" };
122
126
static const char *const mode_list_text[] = {
123
N_("Discard"), N_("Blend"), N_("Mean"), N_("Bob"), N_("Linear"), "X" };
127
N_("Discard"), N_("Blend"), N_("Mean"), N_("Bob"), N_("Linear"), "X", "Yadif", "Yadif (2x)" };
125
129
vlc_module_begin ()
126
130
set_description( N_("Deinterlacing video filter") )
583
614
RenderX( pp_outpic[0], p_pic );
584
615
vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
618
case DEINTERLACE_YADIF:
619
RenderYadif( p_vout, pp_outpic[0], p_pic, 0, 0 );
620
vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
623
case DEINTERLACE_YADIF2X:
624
RenderYadif( p_vout, pp_outpic[0], p_pic, 0, p_pic->b_top_field_first ? 0 : 1 );
625
vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
626
RenderYadif( p_vout, pp_outpic[1], p_pic, 1, p_pic->b_top_field_first ? 1 : 0 );
627
vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[1] );
587
630
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
1679
1722
/*****************************************************************************
1723
* Yadif (Yet Another DeInterlacing Filter).
1724
*****************************************************************************/
1728
* 0: Output 1 frame for each frame.
1729
* 1: Output 1 frame for each field.
1730
* 2: Like 0 but skips spatial interlacing check.
1731
* 3: Like 1 but skips spatial interlacing check.
1733
* In vlc, only & 0x02 has meaning, as we do the & 0x01 ourself.
1738
/* I am unsure it is the right one */
1739
typedef intptr_t x86_reg;
1741
#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
1742
#define FFMAX(a,b) __MAX(a,b)
1743
#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
1744
#define FFMIN(a,b) __MIN(a,b)
1745
#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
1747
/* yadif.h comes from vf_yadif.c of mplayer project */
1750
static void RenderYadif( vout_thread_t *p_vout, picture_t *p_dst, picture_t *p_src, int i_order, int i_field )
1752
vout_sys_t *p_sys = p_vout->p_sys;
1755
assert( i_order == 0 || i_order == 1 );
1756
assert( i_field == 0 || i_field == 1 );
1760
/* Duplicate the picture
1761
* TODO when the vout rework is finished, picture_Hold() might be enough
1762
* but becarefull, the pitches must match */
1763
picture_t *p_dup = picture_New( p_src->format.i_chroma,
1764
p_src->format.i_width,
1765
p_src->format.i_height,
1766
p_src->format.i_aspect );
1768
picture_Copy( p_dup, p_src );
1770
/* Slide the history */
1771
if( p_sys->pp_history[0] )
1772
picture_Release( p_sys->pp_history[0] );
1773
for( int i = 1; i < HISTORY_SIZE; i++ )
1774
p_sys->pp_history[i-1] = p_sys->pp_history[i];
1775
p_sys->pp_history[HISTORY_SIZE-1] = p_dup;
1778
/* As the pitches must match, use ONLY pictures coming from picture_New()! */
1779
picture_t *p_prev = p_sys->pp_history[0];
1780
picture_t *p_cur = p_sys->pp_history[1];
1781
picture_t *p_next = p_sys->pp_history[2];
1783
/* Filter if we have all the pictures we need */
1784
if( p_prev && p_cur && p_next )
1787
void (*filter)(struct vf_priv_s *p, uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int refs, int parity);
1788
#if defined(HAVE_YADIF_SSE2)
1789
if( vlc_CPU() & CPU_CAPABILITY_SSE2 )
1790
filter = yadif_filter_line_mmx2;
1793
filter = yadif_filter_line_c;
1795
for( int n = 0; n < p_dst->i_planes; n++ )
1797
const plane_t *prevp = &p_prev->p[n];
1798
const plane_t *curp = &p_cur->p[n];
1799
const plane_t *nextp = &p_next->p[n];
1800
plane_t *dstp = &p_dst->p[n];
1802
for( int y = 1; y < dstp->i_visible_lines - 1; y++ )
1804
if( (y % 2) == i_field )
1806
vlc_memcpy( &dstp->p_pixels[y * dstp->i_pitch],
1807
&curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch );
1811
struct vf_priv_s cfg;
1812
/* Spatial checks only when enough data */
1813
cfg.mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2;
1815
assert( prevp->i_pitch == curp->i_pitch && curp->i_pitch == nextp->i_pitch );
1817
&dstp->p_pixels[y * dstp->i_pitch],
1818
&prevp->p_pixels[y * prevp->i_pitch],
1819
&curp->p_pixels[y * curp->i_pitch],
1820
&nextp->p_pixels[y * nextp->i_pitch],
1821
dstp->i_visible_pitch,
1823
(i_field ^ (i_order == i_field)) & 1 );
1826
/* We duplicate the first and last lines */
1828
vlc_memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch], &dstp->p_pixels[y * dstp->i_pitch], dstp->i_pitch);
1829
else if( y == dstp->i_visible_lines - 2 )
1830
vlc_memcpy(&dstp->p_pixels[(y+1) * dstp->i_pitch], &dstp->p_pixels[y * dstp->i_pitch], dstp->i_pitch);
1835
p_dst->date = (p_next->date - p_cur->date) * i_order / 2 + p_cur->date;
1839
/* Fallback to something simple
1840
* XXX it is wrong when we have 2 pictures, we should not output a picture */
1841
RenderX( p_dst, p_src );
1845
/*****************************************************************************
1680
1846
* FilterCallback: called when changing the deinterlace method on the fly.
1681
1847
*****************************************************************************/
1682
1848
static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,