[vlc-devel] [PATCH 7/9] deinterlace: merge separate fields into a picture to match other sources
Steve Lhomme
robux4 at ycbcr.xyz
Mon Nov 16 13:44:18 CET 2020
Set the default to blend in that case as other modes produce various artifacts
from a correct looking source. yadif and yadif2 also give good results.
Filters not setting b_merge_fields won't have MergeFields called.
Direct3D11 implementation is possible via shaders.
---
modules/hw/d3d11/d3d11_deinterlace.c | 5 ++
modules/hw/d3d9/dxva2_deinterlace.c | 6 +++
modules/video_filter/deinterlace/common.c | 47 +++++++++++++++++++
modules/video_filter/deinterlace/common.h | 5 ++
.../video_filter/deinterlace/deinterlace.c | 29 +++++++++++-
5 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/modules/hw/d3d11/d3d11_deinterlace.c b/modules/hw/d3d11/d3d11_deinterlace.c
index fafb4fd84b6..0d7bc095b8a 100644
--- a/modules/hw/d3d11/d3d11_deinterlace.c
+++ b/modules/hw/d3d11/d3d11_deinterlace.c
@@ -219,6 +219,11 @@ picture_t *AllocPicture( filter_t *p_filter )
return pic;
}
+void MergeFields( filter_t *p_filter, picture_t *merged, picture_t *fields[2])
+{
+ vlc_assert_unreachable(); // TODO add b_merge_fields support
+}
+
static void D3D11CloseDeinterlace(filter_t *filter)
{
filter_sys_t *sys = filter->p_sys;
diff --git a/modules/hw/d3d9/dxva2_deinterlace.c b/modules/hw/d3d9/dxva2_deinterlace.c
index 65cacdad59b..ea5be24e008 100644
--- a/modules/hw/d3d9/dxva2_deinterlace.c
+++ b/modules/hw/d3d9/dxva2_deinterlace.c
@@ -321,6 +321,12 @@ picture_t *AllocPicture( filter_t *p_filter )
return pic;
}
+void MergeFields( filter_t *p_filter, picture_t *merged, picture_t *fields[2])
+{
+ VLC_UNUSED(p_filter); VLC_UNUSED(merged); VLC_UNUSED(fields);
+ vlc_assert_unreachable(); // b_merge_fields not supported
+}
+
static void D3D9CloseDeinterlace(filter_t *filter)
{
diff --git a/modules/video_filter/deinterlace/common.c b/modules/video_filter/deinterlace/common.c
index 94a6280e37e..13b33feb0d1 100644
--- a/modules/video_filter/deinterlace/common.c
+++ b/modules/video_filter/deinterlace/common.c
@@ -49,10 +49,19 @@ void InitDeinterlacingContext( struct deinterlace_ctx *p_context )
cannot have offset) */
for( int i = 0; i < HISTORY_SIZE; i++ )
p_context->pp_history[i] = NULL;
+
+ p_context->b_merge_fields = false;
+ p_context->prev = NULL;
}
void FlushDeinterlacing(struct deinterlace_ctx *p_context)
{
+ if ( p_context->prev )
+ {
+ picture_Release( p_context->prev );
+ p_context->prev = NULL;
+ }
+
p_context->meta[0].pi_date = VLC_TICK_INVALID;
p_context->meta[0].pi_nb_fields = 2;
p_context->meta[0].pb_top_field_first = true;
@@ -108,6 +117,15 @@ void GetDeinterlacingOutput( const struct deinterlace_ctx *p_context,
{
*p_dst = *p_src;
+ if( p_context->b_merge_fields )
+ {
+ p_dst->i_num_fields = 2;
+ p_dst->i_height *= 2;
+ p_dst->i_visible_height *= 2;
+ p_dst->i_y_offset *= 2;
+ p_dst->i_frame_rate /= 2; // we turn 2 picture_t into 1
+ }
+
if( p_context->settings.b_half_height )
{
p_dst->i_height /= 2;
@@ -127,6 +145,35 @@ void GetDeinterlacingOutput( const struct deinterlace_ctx *p_context,
picture_t *DoDeinterlacing( filter_t *p_filter,
struct deinterlace_ctx *p_context, picture_t *p_pic )
{
+ if ( p_context->b_merge_fields && p_pic != NULL )
+ {
+ if ( p_context->prev == NULL )
+ {
+ p_context->prev = p_pic;
+ return NULL;
+ }
+
+ picture_t *out = AllocPicture( p_filter );
+ if (likely(out != NULL))
+ {
+ picture_t *src_pics[2] = { p_context->prev, p_pic };
+
+ MergeFields( p_filter, out, src_pics );
+
+ out->date = p_pic->date;
+ out->b_force = p_pic->b_force;
+ out->b_still = p_pic->b_still;
+
+ out->b_top_field_first = p_pic->b_top_field_first;
+ }
+ picture_Release( p_context->prev );
+ p_context->prev = NULL;
+ picture_Release( p_pic );
+ if (out == NULL)
+ return NULL;
+ p_pic = out;
+ }
+
picture_t *p_dst[DEINTERLACE_DST_SIZE];
int i_double_rate_alloc_end;
/* Remember the frame offset that we should use for this frame.
diff --git a/modules/video_filter/deinterlace/common.h b/modules/video_filter/deinterlace/common.h
index 144523647c2..160ec2c567a 100644
--- a/modules/video_filter/deinterlace/common.h
+++ b/modules/video_filter/deinterlace/common.h
@@ -66,6 +66,10 @@ struct deinterlace_ctx
/* Algorithm behaviour flags */
deinterlace_algo settings;
+ /* Incoming pictures only contain one field */
+ bool b_merge_fields;
+ picture_t *prev;
+
/**
* Metadata history (PTS, nb_fields, TFF). Used for framerate doublers.
* @see metadata_history_t
@@ -123,5 +127,6 @@ picture_t *DoDeinterlacing( filter_t *, struct deinterlace_ctx *, picture_t * );
void FlushDeinterlacing( struct deinterlace_ctx * );
picture_t *AllocPicture( filter_t * );
+void MergeFields( filter_t *, picture_t *merged, picture_t *fields[2]);
#endif
diff --git a/modules/video_filter/deinterlace/deinterlace.c b/modules/video_filter/deinterlace/deinterlace.c
index 62bd077c0a2..cf4b4deb367 100644
--- a/modules/video_filter/deinterlace/deinterlace.c
+++ b/modules/video_filter/deinterlace/deinterlace.c
@@ -378,7 +378,12 @@ static void SetFilterMethod( filter_t *p_filter, const char *mode, bool pack )
filter_sys_t *p_sys = p_filter->p_sys;
if ( mode == NULL || !strcmp( mode, "auto" ) )
- mode = "x";
+ {
+ if ( p_sys->context.b_merge_fields )
+ mode = "blend";
+ else
+ mode = "x";
+ }
for ( size_t i = 0; i < ARRAY_SIZE(filter_mode); i++ )
{
@@ -434,9 +439,27 @@ static void GetOutputFormat( filter_t *p_filter,
picture_t *AllocPicture( filter_t *filter )
{
- return filter_NewPicture( filter );
+ // TODO update the private pool after format update return filter_NewPicture( filter );
+ return picture_NewFromFormat( &filter->fmt_out.video );
}
+void MergeFields( filter_t *p_filter, picture_t *merged, picture_t *fields[2])
+{
+ VLC_UNUSED(p_filter);
+ for (int plane=0; plane<merged->i_planes; plane++)
+ {
+ plane_t dst = merged->p[plane];
+ const plane_t *src1 = &fields[0]->p[plane];
+ const plane_t *src2 = &fields[1]->p[plane];
+
+ dst.i_pitch *= 2; // every other line
+ plane_CopyPixels(&dst, src1);
+ dst.p_pixels += dst.i_pitch / 2; // other field
+ plane_CopyPixels(&dst, src2);
+ }
+}
+
+
/* This is the filter function. See Open(). */
picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
{
@@ -540,6 +563,8 @@ notsupp:
config_ChainParse( p_filter, FILTER_CFG_PREFIX, ppsz_filter_options,
p_filter->p_cfg );
+ p_sys->context.b_merge_fields = p_filter->fmt_in.video.i_num_fields == 1;
+
char *psz_mode = var_InheritString( p_filter, FILTER_CFG_PREFIX "mode" );
SetFilterMethod( p_filter, psz_mode, packed );
--
2.26.2
More information about the vlc-devel
mailing list