[vlc-devel] [PATCH 10/19] vdpau: implement draining of extra pictures in deinterlacer
Steve Lhomme
robux4 at ycbcr.xyz
Tue Oct 13 15:51:53 CEST 2020
We no longer return pictures chained using vlc_picture_chain_AppendChain().
The original code was returning the source picture, with a few metadata changed
and a secondary picture attached.
The secondary picture, with a different date, is prepared during the drain. We
keep a reference to the primary picture while waiting for the drain. This kept
picture is released during a Flush or on Close.
The last_pts that was used locally when chaining picture is kept as
prev_last_pts to generate the secondary picture(s) during the drain.
---
modules/hw/vdpau/deinterlace.c | 62 ++++++++++++++++++++++++----------
1 file changed, 44 insertions(+), 18 deletions(-)
diff --git a/modules/hw/vdpau/deinterlace.c b/modules/hw/vdpau/deinterlace.c
index 842110c87aa..90a473aabcc 100644
--- a/modules/hw/vdpau/deinterlace.c
+++ b/modules/hw/vdpau/deinterlace.c
@@ -34,12 +34,14 @@
typedef struct
{
vlc_tick_t last_pts;
+ vlc_tick_t prev_last_pts;
+ picture_t *last_pic;
} filter_sys_t;
static picture_t *Deinterlace(filter_t *filter, picture_t *src)
{
filter_sys_t *sys = filter->p_sys;
- vlc_tick_t last_pts = sys->last_pts;
+ sys->prev_last_pts = sys->last_pts;
sys->last_pts = src->date;
@@ -49,66 +51,89 @@ static picture_t *Deinterlace(filter_t *filter, picture_t *src)
if (f1->structure != VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
return src; /* cannot deinterlace twice */
+ sys->last_pic = picture_Hold(src);
+
+ src->i_nb_fields = 1;
+
+ if (src->b_progressive || src->b_top_field_first)
+ f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+ else
+ f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
+
+ dst->b_progressive = true;
+ return src;
+}
+
+static picture_t *Drain(filter_t *filter)
+{
+ filter_sys_t *sys = filter->p_sys;
+ if (sys->last_pic == NULL) // second drain call
+ return NULL;
+
+ const picture_t *src = sys->last_pic;
+ vlc_vdp_video_field_t *f1 = VDPAU_FIELD_FROM_PICCTX(src->context);
#ifdef VOUT_CORE_GETS_A_CLUE
picture_t *dst = filter_NewPicture(filter);
#else
picture_t *dst = picture_NewFromFormat(&src->format);
#endif
if (dst == NULL)
- return src; /* cannot deinterlace without copying fields */
+ goto error; /* cannot deinterlace without copying fields */
vlc_vdp_video_field_t *f2 = vlc_vdp_video_copy(f1); // shallow copy
if (unlikely(f2 == NULL))
{
picture_Release(dst);
- return src;
+ dst = NULL;
+ goto error;
}
picture_CopyProperties(dst, src);
dst->context = &f2->context;
- if (last_pts != VLC_TICK_INVALID)
- dst->date = (3 * src->date - last_pts) / 2;
+ if (sys->prev_last_pts != VLC_TICK_INVALID)
+ dst->date = (3 * src->date - sys->prev_last_pts) / 2;
else
if (filter->fmt_in.video.i_frame_rate != 0)
dst->date = src->date + vlc_tick_from_samples(filter->fmt_in.video.i_frame_rate_base
,filter->fmt_in.video.i_frame_rate);
dst->b_top_field_first = !src->b_top_field_first;
dst->i_nb_fields = 1;
- src->i_nb_fields = 1;
-
- assert(!picture_HasChainedPics(src));
- vlc_picture_chain_AppendChain( src, dst );
if (src->b_progressive || src->b_top_field_first)
- {
- f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
f2->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
- }
else
- {
- f1->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
f2->structure = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
- }
- src->b_progressive = true;
dst->b_progressive = true;
- return src;
+
+error :
+ picture_Release(sys->last_pic);
+ sys->last_pic = NULL;
+ return dst;
}
static void Flush(filter_t *filter)
{
filter_sys_t *sys = filter->p_sys;
+ if (sys->last_pic)
+ {
+ picture_Release(sys->last_pic);
+ sys->last_pic = NULL;
+ }
sys->last_pts = VLC_TICK_INVALID;
+ sys->prev_last_pts = VLC_TICK_INVALID;
}
static void Close(filter_t *filter)
{
+ filter_sys_t *sys = filter->p_sys;
+ Flush(filter);
vlc_video_context_Release(filter->vctx_out);
}
static const struct vlc_filter_operations filter_ops = {
- .filter_video = Deinterlace, .close = Close,
+ .filter_video = Deinterlace, .drain_video = Drain, .close = Close,
.flush = Flush,
};
@@ -132,6 +157,7 @@ static int Open(filter_t *filter)
* The other modes and IVTC should be checked. */
sys->last_pts = VLC_TICK_INVALID;
+ sys->prev_last_pts = VLC_TICK_INVALID;
filter->ops = &filter_ops;
filter->p_sys = sys;
--
2.26.2
More information about the vlc-devel
mailing list