1 /*****************************************************************************
2 * deinterlace.c : deinterlacer plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2011 the VideoLAN team
7 * Author: Sam Hocevar <sam@zoy.org>
8 * Christophe Massiot <massiot@via.ecp.fr>
9 * Laurent Aimar <fenrir@videolan.org>
10 * Juha Jeronen <juha.jeronen@jyu.fi>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
39 #include <vlc_common.h>
40 #include <vlc_plugin.h>
41 #include <vlc_filter.h>
43 #include <vlc_mouse.h>
45 #include "deinterlace.h"
49 /*****************************************************************************
51 *****************************************************************************/
53 #define MODE_TEXT N_("Deinterlace mode")
54 #define MODE_LONGTEXT N_("Deinterlace method to use for local playback.")
56 #define SOUT_MODE_TEXT N_("Streaming deinterlace mode")
57 #define SOUT_MODE_LONGTEXT N_("Deinterlace method to use for streaming.")
59 #define FILTER_CFG_PREFIX "sout-deinterlace-"
61 /* Tooltips drop linefeeds (at least in the Qt GUI);
62 thus the space before each set of consecutive \n.
64 See phosphor.h for phosphor_chroma_list and phosphor_dimmer_list.
66 #define PHOSPHOR_CHROMA_TEXT N_("Phosphor chroma mode for 4:2:0 input")
67 #define PHOSPHOR_CHROMA_LONGTEXT N_("Choose handling for colours in those "\
68 "output frames that fall across input "\
69 "frame boundaries. \n"\
71 "Latest: take chroma from new (bright) "\
72 "field only. Good for interlaced input, "\
73 "such as videos from a camcorder. \n"\
75 "AltLine: take chroma line 1 from top "\
76 "field, line 2 from bottom field, etc. \n"\
77 "Default, good for NTSC telecined input "\
78 "(anime DVDs, etc.). \n"\
80 "Blend: average input field chromas. "\
81 "May distort the colours of the new "\
82 "(bright) field, too. \n"\
84 "Upconvert: output in 4:2:2 format "\
85 "(independent chroma for each field). "\
86 "Best simulation, but requires more CPU "\
87 "and memory bandwidth.")
89 #define PHOSPHOR_DIMMER_TEXT N_("Phosphor old field dimmer strength")
90 #define PHOSPHOR_DIMMER_LONGTEXT N_("This controls the strength of the "\
91 "darkening filter that simulates CRT TV "\
92 "phosphor light decay for the old field "\
93 "in the Phosphor framerate doubler. "\
97 set_description( N_("Deinterlacing video filter") )
98 set_shortname( N_("Deinterlace" ))
99 set_capability( "video filter2", 0 )
100 set_category( CAT_VIDEO )
101 set_subcategory( SUBCAT_VIDEO_VFILTER )
103 add_string( FILTER_CFG_PREFIX "mode", "blend", SOUT_MODE_TEXT,
104 SOUT_MODE_LONGTEXT, false )
105 change_string_list( mode_list, mode_list_text, 0 )
107 add_integer( FILTER_CFG_PREFIX "phosphor-chroma", 2, PHOSPHOR_CHROMA_TEXT,
108 PHOSPHOR_CHROMA_LONGTEXT, true )
109 change_integer_list( phosphor_chroma_list, phosphor_chroma_list_text )
111 add_integer( FILTER_CFG_PREFIX "phosphor-dimmer", 2, PHOSPHOR_DIMMER_TEXT,
112 PHOSPHOR_DIMMER_LONGTEXT, true )
113 change_integer_list( phosphor_dimmer_list, phosphor_dimmer_list_text )
115 add_shortcut( "deinterlace" )
116 set_callbacks( Open, Close )
119 /*****************************************************************************
121 *****************************************************************************/
124 * Available config options for the deinterlacer module.
126 * Note that also algorithm-specific options must be listed here,
127 * and reading logic for them implemented in Open().
129 static const char *const ppsz_filter_options[] = {
130 "mode", "phosphor-chroma", "phosphor-dimmer",
134 /*****************************************************************************
135 * SetFilterMethod: setup the deinterlace method to use.
136 *****************************************************************************/
138 void SetFilterMethod( filter_t *p_filter, const char *psz_method,
139 vlc_fourcc_t i_chroma )
141 filter_sys_t *p_sys = p_filter->p_sys;
146 if( !strcmp( psz_method, "mean" ) )
148 p_sys->i_mode = DEINTERLACE_MEAN;
149 p_sys->b_double_rate = false;
150 p_sys->b_half_height = true;
151 p_sys->b_use_frame_history = false;
153 else if( !strcmp( psz_method, "bob" )
154 || !strcmp( psz_method, "progressive-scan" ) )
156 p_sys->i_mode = DEINTERLACE_BOB;
157 p_sys->b_double_rate = true;
158 p_sys->b_half_height = false;
159 p_sys->b_use_frame_history = false;
161 else if( !strcmp( psz_method, "linear" ) )
163 p_sys->i_mode = DEINTERLACE_LINEAR;
164 p_sys->b_double_rate = true;
165 p_sys->b_half_height = false;
166 p_sys->b_use_frame_history = false;
168 else if( !strcmp( psz_method, "x" ) )
170 p_sys->i_mode = DEINTERLACE_X;
171 p_sys->b_double_rate = false;
172 p_sys->b_half_height = false;
173 p_sys->b_use_frame_history = false;
175 else if( !strcmp( psz_method, "yadif" ) )
177 p_sys->i_mode = DEINTERLACE_YADIF;
178 p_sys->b_double_rate = false;
179 p_sys->b_half_height = false;
180 p_sys->b_use_frame_history = true;
182 else if( !strcmp( psz_method, "yadif2x" ) )
184 p_sys->i_mode = DEINTERLACE_YADIF2X;
185 p_sys->b_double_rate = true;
186 p_sys->b_half_height = false;
187 p_sys->b_use_frame_history = true;
189 else if( !strcmp( psz_method, "phosphor" ) )
191 p_sys->i_mode = DEINTERLACE_PHOSPHOR;
192 p_sys->b_double_rate = true;
193 p_sys->b_half_height = false;
194 p_sys->b_use_frame_history = true;
196 else if( !strcmp( psz_method, "ivtc" ) )
198 p_sys->i_mode = DEINTERLACE_IVTC;
199 p_sys->b_double_rate = false;
200 p_sys->b_half_height = false;
201 p_sys->b_use_frame_history = true;
203 else if( !strcmp( psz_method, "discard" ) )
205 const bool b_i422 = i_chroma == VLC_CODEC_I422 ||
206 i_chroma == VLC_CODEC_J422;
208 p_sys->i_mode = DEINTERLACE_DISCARD;
209 p_sys->b_double_rate = false;
210 p_sys->b_half_height = !b_i422;
211 p_sys->b_use_frame_history = false;
215 if( strcmp( psz_method, "blend" ) )
217 "no valid deinterlace mode provided, using \"blend\"" );
219 p_sys->i_mode = DEINTERLACE_BLEND;
220 p_sys->b_double_rate = false;
221 p_sys->b_half_height = false;
222 p_sys->b_use_frame_history = false;
225 p_sys->i_frame_offset = 0; /* reset to default when method changes */
227 msg_Dbg( p_filter, "using %s deinterlace method", psz_method );
230 /*****************************************************************************
231 * GetOutputFormat: return which format the chosen algorithm outputs.
232 *****************************************************************************/
234 void GetOutputFormat( filter_t *p_filter,
235 video_format_t *p_dst, const video_format_t *p_src )
237 filter_sys_t *p_sys = p_filter->p_sys;
240 if( p_sys->b_half_height )
242 p_dst->i_height /= 2;
243 p_dst->i_visible_height /= 2;
244 p_dst->i_y_offset /= 2;
245 p_dst->i_sar_den *= 2;
248 if( p_src->i_chroma == VLC_CODEC_I422 ||
249 p_src->i_chroma == VLC_CODEC_J422 )
251 switch( p_sys->i_mode )
253 case DEINTERLACE_MEAN:
254 case DEINTERLACE_LINEAR:
256 case DEINTERLACE_YADIF:
257 case DEINTERLACE_YADIF2X:
258 case DEINTERLACE_PHOSPHOR:
259 case DEINTERLACE_IVTC:
260 p_dst->i_chroma = p_src->i_chroma;
263 p_dst->i_chroma = p_src->i_chroma == VLC_CODEC_I422 ? VLC_CODEC_I420 :
268 else if( p_sys->i_mode == DEINTERLACE_PHOSPHOR &&
269 p_sys->phosphor.i_chroma_for_420 == PC_UPCONVERT )
271 p_dst->i_chroma = p_src->i_chroma == VLC_CODEC_J420 ? VLC_CODEC_J422 :
276 /*****************************************************************************
277 * IsChromaSupported: return whether the specified chroma is implemented.
278 *****************************************************************************/
280 bool IsChromaSupported( vlc_fourcc_t i_chroma )
282 return i_chroma == VLC_CODEC_I420 ||
283 i_chroma == VLC_CODEC_J420 ||
284 i_chroma == VLC_CODEC_YV12 ||
285 i_chroma == VLC_CODEC_I422 ||
286 i_chroma == VLC_CODEC_J422;
289 /*****************************************************************************
290 * video filter2 functions
291 *****************************************************************************/
293 #define DEINTERLACE_DST_SIZE 3
295 /* This is the filter function. See Open(). */
296 picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
298 filter_sys_t *p_sys = p_filter->p_sys;
299 picture_t *p_dst[DEINTERLACE_DST_SIZE];
301 /* Request output picture */
302 p_dst[0] = filter_NewPicture( p_filter );
303 if( p_dst[0] == NULL )
305 picture_Release( p_pic );
308 picture_CopyProperties( p_dst[0], p_pic );
310 /* Any unused p_dst pointers must be NULL, because they are used to
311 check how many output frames we have. */
312 for( int i = 1; i < DEINTERLACE_DST_SIZE; ++i )
315 /* Update the input frame history, if the currently active algorithm
317 if( p_sys->b_use_frame_history )
319 /* Duplicate the picture
320 * TODO when the vout rework is finished, picture_Hold() might be enough
321 * but becarefull, the pitches must match */
322 picture_t *p_dup = picture_NewFromFormat( &p_pic->format );
324 picture_Copy( p_dup, p_pic );
326 /* Slide the history */
327 if( p_sys->pp_history[0] )
328 picture_Release( p_sys->pp_history[0] );
329 for( int i = 1; i < HISTORY_SIZE; i++ )
330 p_sys->pp_history[i-1] = p_sys->pp_history[i];
331 p_sys->pp_history[HISTORY_SIZE-1] = p_dup;
334 /* Slide the metadata history. */
335 for( int i = 1; i < METADATA_SIZE; i++ )
337 p_sys->meta.pi_date[i-1] = p_sys->meta.pi_date[i];
338 p_sys->meta.pi_nb_fields[i-1] = p_sys->meta.pi_nb_fields[i];
339 p_sys->meta.pb_top_field_first[i-1] = p_sys->meta.pb_top_field_first[i];
341 /* The last element corresponds to the current input frame. */
342 p_sys->meta.pi_date[METADATA_SIZE-1] = p_pic->date;
343 p_sys->meta.pi_nb_fields[METADATA_SIZE-1] = p_pic->i_nb_fields;
344 p_sys->meta.pb_top_field_first[METADATA_SIZE-1] = p_pic->b_top_field_first;
346 /* Remember the frame offset that we should use for this frame.
347 The value in p_sys will be updated to reflect the correct value
348 for the *next* frame when we call the renderer. */
349 int i_frame_offset = p_sys->i_frame_offset;
350 int i_meta_idx = (METADATA_SIZE-1) - i_frame_offset;
352 /* These correspond to the current *outgoing* frame. */
353 bool b_top_field_first;
355 if( i_frame_offset != CUSTOM_PTS )
357 /* Pick the correct values from the history. */
358 b_top_field_first = p_sys->meta.pb_top_field_first[i_meta_idx];
359 i_nb_fields = p_sys->meta.pi_nb_fields[i_meta_idx];
363 /* Framerate doublers must not request CUSTOM_PTS, as they need the
364 original field timings, and need Deinterlace() to allocate the
365 correct number of output frames. */
366 assert( !p_sys->b_double_rate );
368 /* NOTE: i_nb_fields is only used for framerate doublers, so it is
369 unused in this case. b_top_field_first is only passed to the
370 algorithm. We assume that algorithms that request CUSTOM_PTS
371 will, if necessary, extract the TFF/BFF information themselves.
373 b_top_field_first = p_pic->b_top_field_first; /* this is not guaranteed
375 i_nb_fields = p_pic->i_nb_fields; /* unused */
378 /* For framerate doublers, determine field duration and allocate
380 mtime_t i_field_dur = 0;
381 int i_double_rate_alloc_end = 0; /* One past last for allocated output
382 frames in p_dst[]. Used only for
383 framerate doublers. Will be inited
384 below. Declared here because the
385 PTS logic needs the result. */
386 if( p_sys->b_double_rate )
388 /* Calculate one field duration. */
390 int iend = METADATA_SIZE-1;
391 /* Find oldest valid logged date.
392 The current input frame doesn't count. */
393 for( ; i < iend; i++ )
394 if( p_sys->meta.pi_date[i] > VLC_TS_INVALID )
398 /* Count how many fields the valid history entries
399 (except the new frame) represent. */
400 int i_fields_total = 0;
401 for( int j = i ; j < iend; j++ )
402 i_fields_total += p_sys->meta.pi_nb_fields[j];
403 /* One field took this long. */
404 i_field_dur = (p_pic->date - p_sys->meta.pi_date[i]) / i_fields_total;
406 /* Note that we default to field duration 0 if it could not be
407 determined. This behaves the same as the old code - leaving the
408 extra output frame dates the same as p_pic->date if the last cached
412 i_double_rate_alloc_end = i_nb_fields;
413 if( i_nb_fields > DEINTERLACE_DST_SIZE )
415 /* Note that the effective buffer size depends also on the constant
416 private_picture in vout_wrapper.c, since that determines the
417 maximum number of output pictures filter_NewPicture() will
418 successfully allocate for one input frame.
420 msg_Err( p_filter, "Framerate doubler: output buffer too small; "\
421 "fields = %d, buffer size = %d. Dropping the "\
423 i_nb_fields, DEINTERLACE_DST_SIZE );
424 i_double_rate_alloc_end = DEINTERLACE_DST_SIZE;
427 /* Allocate output frames. */
428 for( int i = 1; i < i_double_rate_alloc_end ; ++i )
431 p_dst[i] = filter_NewPicture( p_filter );
434 picture_CopyProperties( p_dst[i], p_pic );
438 msg_Err( p_filter, "Framerate doubler: could not allocate "\
439 "output frame %d", i+1 );
440 i_double_rate_alloc_end = i; /* Inform the PTS logic about the
441 correct end position. */
442 break; /* If this happens, the rest of the allocations
443 aren't likely to work, either... */
446 /* Now we have allocated *up to* the correct number of frames;
447 normally, exactly the correct number. Upon alloc failure,
448 we may have succeeded in allocating *some* output frames,
449 but fewer than were desired. In such a case, as many will
450 be rendered as were successfully allocated.
452 Note that now p_dst[i] != NULL
453 for 0 <= i < i_double_rate_alloc_end. */
455 assert( p_sys->b_double_rate || p_dst[1] == NULL );
456 assert( i_nb_fields > 2 || p_dst[2] == NULL );
459 switch( p_sys->i_mode )
461 case DEINTERLACE_DISCARD:
462 RenderDiscard( p_filter, p_dst[0], p_pic, 0 );
465 case DEINTERLACE_BOB:
466 RenderBob( p_filter, p_dst[0], p_pic, !b_top_field_first );
468 RenderBob( p_filter, p_dst[1], p_pic, b_top_field_first );
470 RenderBob( p_filter, p_dst[2], p_pic, !b_top_field_first );
473 case DEINTERLACE_LINEAR:
474 RenderLinear( p_filter, p_dst[0], p_pic, !b_top_field_first );
476 RenderLinear( p_filter, p_dst[1], p_pic, b_top_field_first );
478 RenderLinear( p_filter, p_dst[2], p_pic, !b_top_field_first );
481 case DEINTERLACE_MEAN:
482 RenderMean( p_filter, p_dst[0], p_pic );
485 case DEINTERLACE_BLEND:
486 RenderBlend( p_filter, p_dst[0], p_pic );
490 RenderX( p_dst[0], p_pic );
493 case DEINTERLACE_YADIF:
494 if( RenderYadif( p_filter, p_dst[0], p_pic, 0, 0 ) )
498 case DEINTERLACE_YADIF2X:
499 if( RenderYadif( p_filter, p_dst[0], p_pic, 0, !b_top_field_first ) )
502 RenderYadif( p_filter, p_dst[1], p_pic, 1, b_top_field_first );
504 RenderYadif( p_filter, p_dst[2], p_pic, 2, !b_top_field_first );
507 case DEINTERLACE_PHOSPHOR:
508 if( RenderPhosphor( p_filter, p_dst[0], 0,
509 !b_top_field_first ) )
512 RenderPhosphor( p_filter, p_dst[1], 1,
515 RenderPhosphor( p_filter, p_dst[2], 2,
516 !b_top_field_first );
519 case DEINTERLACE_IVTC:
520 /* Note: RenderIVTC will automatically drop the duplicate frames
521 produced by IVTC. This is part of normal operation. */
522 if( RenderIVTC( p_filter, p_dst[0] ) )
527 /* Set output timestamps, if the algorithm didn't request CUSTOM_PTS
529 assert( i_frame_offset <= METADATA_SIZE || i_frame_offset == CUSTOM_PTS );
530 if( i_frame_offset != CUSTOM_PTS )
532 mtime_t i_base_pts = p_sys->meta.pi_date[i_meta_idx];
534 /* Note: in the usual case (i_frame_offset = 0 and
535 b_double_rate = false), this effectively does nothing.
536 This is needed to correct the timestamp
537 when i_frame_offset > 0. */
538 p_dst[0]->date = i_base_pts;
540 if( p_sys->b_double_rate )
542 /* Processing all actually allocated output frames. */
543 for( int i = 1; i < i_double_rate_alloc_end; ++i )
545 /* XXX it's not really good especially for the first picture, but
546 * I don't think that delaying by one frame is worth it */
547 if( i_base_pts > VLC_TS_INVALID )
548 p_dst[i]->date = i_base_pts + i * i_field_dur;
550 p_dst[i]->date = VLC_TS_INVALID;
555 for( int i = 0; i < DEINTERLACE_DST_SIZE; ++i )
559 p_dst[i]->b_progressive = true;
560 p_dst[i]->i_nb_fields = 2;
564 picture_Release( p_pic );
568 picture_Release( p_dst[0] );
569 for( int i = 1; i < DEINTERLACE_DST_SIZE; ++i )
572 picture_Release( p_dst[i] );
574 picture_Release( p_pic );
578 /*****************************************************************************
580 *****************************************************************************/
582 void Flush( filter_t *p_filter )
584 filter_sys_t *p_sys = p_filter->p_sys;
586 for( int i = 0; i < METADATA_SIZE; i++ )
588 p_sys->meta.pi_date[i] = VLC_TS_INVALID;
589 p_sys->meta.pi_nb_fields[i] = 2;
590 p_sys->meta.pb_top_field_first[i] = true;
592 p_sys->i_frame_offset = 0; /* reset to default value (first frame after
593 flush cannot have offset) */
594 for( int i = 0; i < HISTORY_SIZE; i++ )
596 if( p_sys->pp_history[i] )
597 picture_Release( p_sys->pp_history[i] );
598 p_sys->pp_history[i] = NULL;
600 IVTCClearState( p_filter );
603 /*****************************************************************************
604 * Mouse event callback
605 *****************************************************************************/
607 int Mouse( filter_t *p_filter,
608 vlc_mouse_t *p_mouse,
609 const vlc_mouse_t *p_old, const vlc_mouse_t *p_new )
613 if( p_filter->p_sys->b_half_height )
619 /*****************************************************************************
621 *****************************************************************************/
623 int Open( vlc_object_t *p_this )
625 filter_t *p_filter = (filter_t*)p_this;
628 if( !IsChromaSupported( p_filter->fmt_in.video.i_chroma ) )
632 p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
636 p_sys->i_mode = DEINTERLACE_BLEND;
637 p_sys->b_double_rate = false;
638 p_sys->b_half_height = true;
639 p_sys->b_use_frame_history = false;
640 for( int i = 0; i < METADATA_SIZE; i++ )
642 p_sys->meta.pi_date[i] = VLC_TS_INVALID;
643 p_sys->meta.pi_nb_fields[i] = 2;
644 p_sys->meta.pb_top_field_first[i] = true;
646 p_sys->i_frame_offset = 0; /* start with default value (first-ever frame
647 cannot have offset) */
648 for( int i = 0; i < HISTORY_SIZE; i++ )
649 p_sys->pp_history[i] = NULL;
651 IVTCClearState( p_filter );
653 #if defined(CAN_COMPILE_C_ALTIVEC)
654 if( vlc_CPU() & CPU_CAPABILITY_ALTIVEC )
656 p_sys->pf_merge = MergeAltivec;
657 p_sys->pf_end_merge = NULL;
661 #if defined(CAN_COMPILE_SSE)
662 if( vlc_CPU() & CPU_CAPABILITY_SSE2 )
664 p_sys->pf_merge = MergeSSE2;
665 p_sys->pf_end_merge = EndMMX;
669 #if defined(CAN_COMPILE_MMXEXT)
670 if( vlc_CPU() & CPU_CAPABILITY_MMXEXT )
672 p_sys->pf_merge = MergeMMXEXT;
673 p_sys->pf_end_merge = EndMMX;
677 #if defined(CAN_COMPILE_3DNOW)
678 if( vlc_CPU() & CPU_CAPABILITY_3DNOW )
680 p_sys->pf_merge = Merge3DNow;
681 p_sys->pf_end_merge = End3DNow;
685 #if defined __ARM_NEON__ // FIXME: runtime detect support
686 if( vlc_CPU() & CPU_CAPABILITY_NEON )
688 p_sys->pf_merge = MergeNEON;
689 p_sys->pf_end_merge = NULL;
694 p_sys->pf_merge = MergeGeneric;
695 p_sys->pf_end_merge = NULL;
699 config_ChainParse( p_filter, FILTER_CFG_PREFIX, ppsz_filter_options,
702 char *psz_mode = var_GetNonEmptyString( p_filter, FILTER_CFG_PREFIX "mode" );
703 SetFilterMethod( p_filter, psz_mode, p_filter->fmt_in.video.i_chroma );
706 if( p_sys->i_mode == DEINTERLACE_PHOSPHOR )
708 int i_c420 = var_GetInteger( p_filter,
709 FILTER_CFG_PREFIX "phosphor-chroma" );
710 if( i_c420 != PC_LATEST && i_c420 != PC_ALTLINE &&
711 i_c420 != PC_BLEND && i_c420 != PC_UPCONVERT )
713 msg_Dbg( p_filter, "Phosphor 4:2:0 input chroma mode not set"\
714 "or out of range (valid: 1, 2, 3 or 4), "\
718 msg_Dbg( p_filter, "using Phosphor 4:2:0 input chroma mode %d",
720 /* This maps directly to the phosphor_chroma_t enum. */
721 p_sys->phosphor.i_chroma_for_420 = i_c420;
723 int i_dimmer = var_GetInteger( p_filter,
724 FILTER_CFG_PREFIX "phosphor-dimmer" );
725 if( i_dimmer < 1 || i_dimmer > 4 )
727 msg_Dbg( p_filter, "Phosphor dimmer strength not set "\
728 "or out of range (valid: 1, 2, 3 or 4), "\
730 i_dimmer = 2; /* low */
732 msg_Dbg( p_filter, "using Phosphor dimmer strength %d", i_dimmer );
733 /* The internal value ranges from 0 to 3. */
734 p_sys->phosphor.i_dimmer_strength = i_dimmer - 1;
738 p_sys->phosphor.i_chroma_for_420 = PC_ALTLINE;
739 p_sys->phosphor.i_dimmer_strength = 1;
744 GetOutputFormat( p_filter, &fmt, &p_filter->fmt_in.video );
745 if( !p_filter->b_allow_fmt_out_change &&
746 ( fmt.i_chroma != p_filter->fmt_in.video.i_chroma ||
747 fmt.i_height != p_filter->fmt_in.video.i_height ) )
749 Close( VLC_OBJECT(p_filter) );
752 p_filter->fmt_out.video = fmt;
753 p_filter->fmt_out.i_codec = fmt.i_chroma;
754 p_filter->pf_video_filter = Deinterlace;
755 p_filter->pf_video_flush = Flush;
756 p_filter->pf_video_mouse = Mouse;
758 msg_Dbg( p_filter, "deinterlacing" );
763 /*****************************************************************************
764 * Close: clean up the filter
765 *****************************************************************************/
767 void Close( vlc_object_t *p_this )
769 filter_t *p_filter = (filter_t*)p_this;
772 free( p_filter->p_sys );