/*****************************************************************************
* interlacing.c
*****************************************************************************
* Copyright (C) 2010 Laurent Aimar
*
* Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_configuration.h>
#include <vlc_threads.h>
#include <vlc_vout.h>
#include "vout_private.h"
#include "vout_internal.h"
/*****************************************************************************
* Deinterlacing
*****************************************************************************/
/* XXX
* You can use the non vout filter if and only if the video properties stay the
* same (width/height/chroma/fps), at least for now.
*/
static const char deinterlace_modes[][9]= {
"auto",
"discard",
"blend",
"mean",
"bob",
"linear",
"x",
"yadif",
"yadif2x",
"phosphor",
"ivtc",
};
static bool DeinterlaceIsModeValid(const char *mode)
{
for (unsigned i = 0; i < ARRAY_SIZE(deinterlace_modes); i++) {
if (!strcmp(deinterlace_modes[i], mode))
return true;
}
return false;
}
static int DeinterlaceCallback(vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *data)
{
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(newval); VLC_UNUSED(data);
vout_thread_t *vout = (vout_thread_t *)object;
/* */
const int deinterlace_state = var_GetInteger(vout, "deinterlace");
char *mode = var_GetString(vout, "deinterlace-mode");
const bool is_needed = var_GetBool(vout, "deinterlace-needed");
if (!mode || !DeinterlaceIsModeValid(mode))
{
msg_Err(vout, "unknown deinterlace mode %s", mode);
free(mode);
return VLC_EGENERIC;
}
/* */
var_SetString(vout, "sout-deinterlace-mode", mode);
msg_Dbg(vout, "deinterlace %d, mode %s, is_needed %d", deinterlace_state, mode, is_needed);
vout_ControlChangeInterlacing(vout, deinterlace_state != 0 && (is_needed || deinterlace_state >= 0));
/* */
free(mode);
return VLC_SUCCESS;
}
void vout_InitInterlacingSupport(vout_thread_t *vout, vout_interlacing_state_t *sys)
{
vlc_value_t val;
msg_Dbg(vout, "Deinterlacing available");
sys->has_deint = false;
/* Create the configuration variables */
/* */
var_Create(vout, "deinterlace", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
int deinterlace_state = var_GetInteger(vout, "deinterlace");
var_Change(vout, "deinterlace", VLC_VAR_SETTEXT, _("Deinterlace"));
const module_config_t *optd = config_FindConfig("deinterlace");
var_Change(vout, "deinterlace", VLC_VAR_CLEARCHOICES);
if (likely(optd != NULL))
for (unsigned i = 0; i < optd->list_count; i++) {
val.i_int = optd->list.i[i];
var_Change(vout, "deinterlace", VLC_VAR_ADDCHOICE, val,
vlc_gettext(optd->list_text[i]));
}
var_AddCallback(vout, "deinterlace", DeinterlaceCallback, NULL);
/* */
var_Create(vout, "deinterlace-mode", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
char *deinterlace_mode = var_GetNonEmptyString(vout, "deinterlace-mode");
var_Change(vout, "deinterlace-mode", VLC_VAR_SETTEXT,
_("Deinterlace mode"));
const module_config_t *optm = config_FindConfig("deinterlace-mode");
var_Change(vout, "deinterlace-mode", VLC_VAR_CLEARCHOICES);
if (likely(optm != NULL))
for (unsigned i = 0; i < optm->list_count; i++) {
if (!DeinterlaceIsModeValid(optm->list.psz[i]))
continue;
val.psz_string = (char *)optm->list.psz[i];
var_Change(vout, "deinterlace-mode", VLC_VAR_ADDCHOICE,
val, vlc_gettext(optm->list_text[i]));
}
var_AddCallback(vout, "deinterlace-mode", DeinterlaceCallback, NULL);
/* */
var_Create(vout, "deinterlace-needed", VLC_VAR_BOOL);
var_AddCallback(vout, "deinterlace-needed", DeinterlaceCallback, NULL);
/* */
val.psz_string = deinterlace_mode ? deinterlace_mode : optm->orig.psz;
var_Change(vout, "deinterlace-mode", VLC_VAR_SETVALUE, val);
var_SetInteger(vout, "deinterlace", deinterlace_state);
free(deinterlace_mode);
var_Create(vout, "sout-deinterlace-mode", VLC_VAR_STRING);
sys->is_interlaced = false;
}
void vout_ReinitInterlacingSupport(vout_thread_t *vout, vout_interlacing_state_t *sys)
{
sys->is_interlaced = false;
var_SetBool(vout, "deinterlace-needed", false);
}
void vout_SetInterlacingState(vout_thread_t *vout, vout_interlacing_state_t *sys, bool is_interlaced)
{
const bool interlacing_change =
is_interlaced != sys->is_interlaced;
/* Wait 30s before quitting interlacing mode */
const bool is_after_deadline =
sys->date + VLC_TICK_FROM_SEC(30) < vlc_tick_now();
if (interlacing_change && (is_interlaced || is_after_deadline))
{
msg_Dbg(vout, "Detected %s video",
is_interlaced ? "interlaced" : "progressive");
var_SetBool(vout, "deinterlace-needed", is_interlaced);
sys->is_interlaced = is_interlaced;
}
if (is_interlaced)
sys->date = vlc_tick_now();
}
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|