Commit 8a97b7a8 authored by Steve Lhomme's avatar Steve Lhomme
Browse files

vaapi: implement draining of extra pictures in x2 deinterlacer

The picture used to create secondary pictures (cur) is kept as long as pictures
are produced by the drain. It comes from the picture history so it will be
released from there.

cur_frame was either 0 (primary output) or 1 (secondary output). The value is
used the same way in the filter and drain functions.

The i_field_dur duration shift is only done for the drained picture.

We no longer return pictures chained using vlc_picture_chain_AppendChain().
parent 6267b320
......@@ -51,6 +51,10 @@ typedef struct
struct va_filter_desc va;
picture_pool_t * dest_pics;
bool b_pipeline_fast;
picture_t * cur; // X2 Deinterlacer
vlc_tick_t src_date;
void * p_data;
} filter_sys_t;
......@@ -308,6 +312,7 @@ Open(filter_t * filter,
return VLC_ENOMEM;
filter->p_sys = filter_sys;
filter_sys->cur = NULL;
filter_sys->p_data = p_data;
filter_sys->va.conf = VA_INVALID_ID;
......@@ -764,7 +769,7 @@ Deinterlace_UpdateHistory(struct deint_data * p_deint_data, picture_t * src)
}
p_deint_data->history.pp_pics[p_deint_data->history.num_pics++] = src;
return *p_deint_data->history.pp_cur_pic;
return p_deint_data->history.pp_cur_pic[0];
}
static void
......@@ -844,7 +849,6 @@ DeinterlaceX2(filter_t * filter, picture_t * src)
{
filter_sys_t *const filter_sys = filter->p_sys;
struct deint_data *const p_deint_data = filter_sys->p_data;
const video_format_t * fmt = &filter->fmt_out.video;
/* TODO: could use the meta array and calculation from deinterlace/common
but then it would also be appropriate to use the picture history array
......@@ -854,53 +858,75 @@ DeinterlaceX2(filter_t * filter, picture_t * src)
p_deint_data->meta[METADATA_SIZE-1].date = src->date;
p_deint_data->meta[METADATA_SIZE-1].i_nb_fields = src->i_nb_fields;
picture_t * cur = Deinterlace_UpdateHistory(p_deint_data, src);
filter_sys->cur = Deinterlace_UpdateHistory(p_deint_data, src);
if (p_deint_data->history.num_pics < p_deint_data->history.sz)
return NULL;
vlc_tick_t i_field_dur = 0;
unsigned int i = 0;
for ( ; i < METADATA_SIZE-1; i ++)
if (p_deint_data->meta[i].date != VLC_TICK_INVALID)
break;
if (i < METADATA_SIZE-1) {
unsigned int i_fields_total = 0;
for (unsigned int j = i; j < METADATA_SIZE-1; ++j)
i_fields_total += p_deint_data->meta[j].i_nb_fields;
i_field_dur = (src->date - p_deint_data->meta[i].date) / i_fields_total;
}
else if (fmt->i_frame_rate_base)
i_field_dur = vlc_tick_from_samples(fmt->i_frame_rate_base, fmt->i_frame_rate);
picture_t *dest[2] = {NULL, NULL};
for (i = 0; i < 2; ++i)
{
p_deint_data->cur_frame = i;
dest[i] = Filter(filter, cur,
p_deint_data->cur_frame = 0;
picture_t *dest = Filter(filter, filter_sys->cur,
Deinterlace_UpdateFilterParams,
Deinterlace_UpdateReferenceFrames,
Deinterlace_UpdatePipelineParams);
if (!dest[i])
goto error;
if (!dest)
goto error;
dest[i]->b_progressive = true;
dest[i]->i_nb_fields = 1;
}
dest->b_progressive = true;
dest->i_nb_fields = 1;
vlc_picture_chain_AppendChain( dest[0], dest[1] );
dest[0]->date = cur->date;
if (dest[0]->date != VLC_TICK_INVALID)
dest[1]->date = dest[0]->date + i_field_dur;
else
dest[1]->date = VLC_TICK_INVALID;
dest->date = filter_sys->cur->date;
filter_sys->src_date = src->date;
return dest[0];
return dest;
error:
for (i = 0; i < 2; ++i)
if (dest[i])
picture_Release(dest[i]);
filter_sys->cur = NULL;
return NULL;
}
static picture_t *DrainX2(filter_t *filter)
{
filter_sys_t *const filter_sys = filter->p_sys;
struct deint_data *const p_deint_data = filter_sys->p_data;
const video_format_t * fmt = &filter->fmt_out.video;
if (filter_sys->cur == NULL)
return NULL;
p_deint_data->cur_frame = 1;
picture_t *dest = Filter(filter, filter_sys->cur,
Deinterlace_UpdateFilterParams,
Deinterlace_UpdateReferenceFrames,
Deinterlace_UpdatePipelineParams);
if (unlikely(!dest))
goto error;
dest->b_progressive = true;
dest->i_nb_fields = 1;
if (filter_sys->cur->date != VLC_TICK_INVALID)
{
vlc_tick_t i_field_dur = 0;
unsigned int i = 0;
for ( ; i < METADATA_SIZE-1; i ++)
if (p_deint_data->meta[i].date != VLC_TICK_INVALID)
break;
if (i < METADATA_SIZE-1) {
unsigned int i_fields_total = 0;
for (unsigned int j = i; j < METADATA_SIZE-1; ++j)
i_fields_total += p_deint_data->meta[j].i_nb_fields;
i_field_dur = (filter_sys->src_date - p_deint_data->meta[i].date) / i_fields_total;
}
else if (fmt->i_frame_rate_base)
i_field_dur = vlc_tick_from_samples(fmt->i_frame_rate_base, fmt->i_frame_rate);
dest->date = filter_sys->cur->date + i_field_dur;
}
else
dest->date = VLC_TICK_INVALID;
return dest;
error:
filter_sys->cur = NULL;
return NULL;
}
......@@ -916,6 +942,11 @@ Deinterlace_Flush(filter_t *filter)
p_deint_data->history.pp_pics[--p_deint_data->history.num_pics];
picture_Release(pic);
}
if (p_sys->cur != NULL)
{
picture_Release( p_sys->cur );
p_sys->cur = NULL;
}
for (unsigned int i = 0; i < METADATA_SIZE; ++i)
{
......@@ -1083,6 +1114,7 @@ static void CloseDeinterlace(filter_t *filter)
static const struct vlc_filter_operations DeinterlaceX2_ops = {
.filter_video = DeinterlaceX2, .flush = Deinterlace_Flush, .close = CloseDeinterlace,
.drain_video = DrainX2,
};
static const struct vlc_filter_operations Deinterlace_ops = {
.filter_video = Deinterlace, .flush = Deinterlace_Flush, .close = CloseDeinterlace,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment