1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
29 #include <vlc_common.h>
32 #include "interlacing.h"
33 #include "vout_internal.h"
35 /*****************************************************************************
37 *****************************************************************************/
39 * You can use the non vout filter if and only if the video properties stay the
40 * same (width/height/chroma/fps), at least for now.
42 static const char deinterlace_modes
[][9]= {
56 static bool DeinterlaceIsModeValid(const char *mode
)
58 for (unsigned i
= 0; i
< ARRAY_SIZE(deinterlace_modes
); i
++) {
59 if (!strcmp(deinterlace_modes
[i
], mode
))
65 static int DeinterlaceCallback(vlc_object_t
*object
, char const *cmd
,
66 vlc_value_t oldval
, vlc_value_t newval
, void *data
)
68 VLC_UNUSED(cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(newval
); VLC_UNUSED(data
);
69 vout_thread_t
*vout
= (vout_thread_t
*)object
;
72 const int deinterlace_state
= var_GetInteger(vout
, "deinterlace");
73 char *mode
= var_GetString(vout
, "deinterlace-mode");
74 const bool is_needed
= var_GetBool(vout
, "deinterlace-needed");
75 if (!mode
|| !DeinterlaceIsModeValid(mode
))
82 char *old
= var_CreateGetString(vout
, "sout-deinterlace-mode");
83 var_SetString(vout
, "sout-deinterlace-mode", mode
);
85 msg_Dbg(vout
, "deinterlace %d, mode %s, is_needed %d", deinterlace_state
, mode
, is_needed
);
86 if (deinterlace_state
== 0 || (deinterlace_state
< 0 && !is_needed
))
87 vout_control_PushBool(&vout
->p
->control
,
88 VOUT_CONTROL_CHANGE_INTERLACE
, false);
90 vout_control_PushBool(&vout
->p
->control
,
91 VOUT_CONTROL_CHANGE_INTERLACE
, true);
99 void vout_InitInterlacingSupport(vout_thread_t
*vout
, bool is_interlaced
)
101 vlc_value_t val
, text
;
103 msg_Dbg(vout
, "Deinterlacing available");
105 vout
->p
->filter
.has_deint
= false;
107 /* Create the configuration variables */
109 var_Create(vout
, "deinterlace", VLC_VAR_INTEGER
| VLC_VAR_DOINHERIT
);
110 int deinterlace_state
= var_GetInteger(vout
, "deinterlace");
112 text
.psz_string
= _("Deinterlace");
113 var_Change(vout
, "deinterlace", VLC_VAR_SETTEXT
, &text
, NULL
);
115 const module_config_t
*optd
= config_FindConfig("deinterlace");
116 var_Change(vout
, "deinterlace", VLC_VAR_CLEARCHOICES
, NULL
, NULL
);
117 if (likely(optd
!= NULL
))
118 for (unsigned i
= 0; i
< optd
->list_count
; i
++) {
119 val
.i_int
= optd
->list
.i
[i
];
120 text
.psz_string
= vlc_gettext(optd
->list_text
[i
]);
121 var_Change(vout
, "deinterlace", VLC_VAR_ADDCHOICE
, &val
, &text
);
123 var_AddCallback(vout
, "deinterlace", DeinterlaceCallback
, NULL
);
125 var_Create(vout
, "deinterlace-mode", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
126 char *deinterlace_mode
= var_GetNonEmptyString(vout
, "deinterlace-mode");
128 text
.psz_string
= _("Deinterlace mode");
129 var_Change(vout
, "deinterlace-mode", VLC_VAR_SETTEXT
, &text
, NULL
);
131 const module_config_t
*optm
= config_FindConfig("deinterlace-mode");
132 var_Change(vout
, "deinterlace-mode", VLC_VAR_CLEARCHOICES
, NULL
, NULL
);
133 if (likely(optm
!= NULL
))
134 for (unsigned i
= 0; i
< optm
->list_count
; i
++) {
135 if (!DeinterlaceIsModeValid(optm
->list
.psz
[i
]))
138 val
.psz_string
= (char *)optm
->list
.psz
[i
];
139 text
.psz_string
= vlc_gettext(optm
->list_text
[i
]);
140 var_Change(vout
, "deinterlace-mode", VLC_VAR_ADDCHOICE
,
143 var_AddCallback(vout
, "deinterlace-mode", DeinterlaceCallback
, NULL
);
145 var_Create(vout
, "deinterlace-needed", VLC_VAR_BOOL
);
146 var_AddCallback(vout
, "deinterlace-needed", DeinterlaceCallback
, NULL
);
148 /* Override the initial value from filters if present */
149 char *filter_mode
= NULL
;
150 if (vout
->p
->filter
.has_deint
)
151 filter_mode
= var_CreateGetNonEmptyString(vout
, "sout-deinterlace-mode");
153 deinterlace_state
= 1;
154 free(deinterlace_mode
);
155 deinterlace_mode
= filter_mode
;
159 val
.psz_string
= deinterlace_mode
? deinterlace_mode
: optm
->orig
.psz
;
160 var_Change(vout
, "deinterlace-mode", VLC_VAR_SETVALUE
, &val
, NULL
);
161 val
.b_bool
= is_interlaced
;
162 var_Change(vout
, "deinterlace-needed", VLC_VAR_SETVALUE
, &val
, NULL
);
164 var_SetInteger(vout
, "deinterlace", deinterlace_state
);
165 free(deinterlace_mode
);
167 vout
->p
->interlacing
.is_interlaced
= is_interlaced
;
169 vout
->p
->interlacing
.date
= mdate();
172 void vout_ReinitInterlacingSupport(vout_thread_t
*vout
)
174 vout
->p
->interlacing
.is_interlaced
= false;
175 var_SetBool(vout
, "deinterlace-needed", false);
178 void vout_SetInterlacingState(vout_thread_t
*vout
, bool is_interlaced
)
180 /* Wait 30s before quiting interlacing mode */
181 const int interlacing_change
= (!!is_interlaced
)
182 - (!!vout
->p
->interlacing
.is_interlaced
);
183 if (interlacing_change
== 1 ||
184 (interlacing_change
== -1 &&
185 vout
->p
->interlacing
.date
+ 30000000 < mdate()))
187 msg_Dbg(vout
, "Detected %s video",
188 is_interlaced
? "interlaced" : "progressive");
189 var_SetBool(vout
, "deinterlace-needed", is_interlaced
);
190 vout
->p
->interlacing
.is_interlaced
= is_interlaced
;
193 vout
->p
->interlacing
.date
= mdate();