[vlc-devel] [vlc-commits] hw: vaapi: double framerate for Bob and X deint modes
Oliver Collyer
ovcollyer at mac.com
Mon Jul 10 12:55:33 CEST 2017
> On 10 Jul 2017, at 10:02, Steve Lhomme <robux4 at gmail.com> wrote:
>
> A little late...
>
> On Fri, Jul 7, 2017 at 9:09 AM, Oliver Collyer <git at videolan.org> wrote:
>> vlc | branch: master | Oliver Collyer <ovcollyer at mac.com> | Thu Jul 6 20:43:38 2017 +0300| [c932d06d31de5cd6161345db4ab4a284589be1a4] | committer: Thomas Guillem
>>
>> hw: vaapi: double framerate for Bob and X deint modes
>>
>> Signed-off-by: Victorien Le Couviour--Tuffet <victorien.lecouviour.tuffet at gmail.com>
>> Signed-off-by: Thomas Guillem <thomas at gllm.fr>
>>
>>> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c932d06d31de5cd6161345db4ab4a284589be1a4
>> ---
>>
>> modules/hw/vaapi/filters.c | 142 +++++++++++++++++++++++++++++++++++++++------
>> 1 file changed, 124 insertions(+), 18 deletions(-)
>>
>> diff --git a/modules/hw/vaapi/filters.c b/modules/hw/vaapi/filters.c
>> old mode 100644
>> new mode 100755
>> index 6d124b5ab9..091a949f24
>> --- a/modules/hw/vaapi/filters.c
>> +++ b/modules/hw/vaapi/filters.c
>> @@ -222,16 +222,19 @@ struct deint_mode
>> {
>> char const name[5];
>> VAProcDeinterlacingType type;
>> + bool b_double_rate;
>> };
>>
>> static struct deint_mode const deint_modes[] =
>> {
>> - { "x", VAProcDeinterlacingMotionAdaptive },
>> - { "x", VAProcDeinterlacingMotionCompensated },
>> - { "bob", VAProcDeinterlacingBob },
>> - { "mean", VAProcDeinterlacingWeave }
>> + { "x", VAProcDeinterlacingMotionAdaptive, true },
>> + { "x", VAProcDeinterlacingMotionCompensated, true },
>> + { "bob", VAProcDeinterlacingBob, true },
>> + { "mean", VAProcDeinterlacingWeave, false }
>> };
>>
>> +#define METADATA_SIZE 3
>> +
>> struct deint_data
>> {
>> struct
>> @@ -247,6 +250,15 @@ struct deint_data
>> VASurfaceID * surfaces;
>> unsigned int sz;
>> } backward_refs, forward_refs;
>> +
>> + struct
>> + {
>> + mtime_t date;
>> + int i_nb_fields;
>> + } meta[METADATA_SIZE];
>> +
>> + bool b_double_rate;
>> + unsigned int cur_frame;
>> };
>>
>> /********************
>> @@ -813,6 +825,20 @@ Deinterlace_UpdateHistory(struct deint_data * p_deint_data, picture_t * src)
>> }
>>
>> static void
>> +Deinterlace_UpdateFilterParams(void * p_data, void * va_params)
>> +{
>> + struct deint_data *const p_deint_data = p_data;
>> + VAProcFilterParameterBufferDeinterlacing *const p_va_params = va_params;
>> +
>> + p_va_params->flags =
>> + p_deint_data->history.pp_cur_pic[0]->b_top_field_first ?
>> + 0 : VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
>> + if (p_deint_data->cur_frame ==
>> + (p_deint_data->history.pp_cur_pic[0]->b_top_field_first ? 1 : 0))
>> + p_va_params->flags |= VA_DEINTERLACING_BOTTOM_FIELD;
>> +}
>> +
>> +static void
>> Deinterlace_UpdateReferenceFrames(void * p_data)
>> {
>> struct deint_data *const p_deint_data = p_data;
>> @@ -842,10 +868,6 @@ Deinterlace_UpdatePipelineParams
>> {
>> struct deint_data *const p_deint_data = p_data;
>>
>> - pipeline_param->filter_flags =
>> - p_deint_data->history.pp_cur_pic[0]->b_top_field_first ?
>> - 0 : VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
>> -
>> pipeline_param->backward_references = p_deint_data->backward_refs.surfaces;
>> pipeline_param->forward_references = p_deint_data->forward_refs.surfaces;
>> pipeline_param->num_backward_references = p_deint_data->backward_refs.sz;
>> @@ -863,7 +885,8 @@ Deinterlace(filter_t * filter, picture_t * src)
>> return NULL;
>>
>> picture_t *const dest =
>> - Filter(filter, src, NULL,
>> + Filter(filter, src,
>> + Deinterlace_UpdateFilterParams,
>> Deinterlace_UpdateReferenceFrames,
>> Deinterlace_UpdatePipelineParams);
>>
>> @@ -873,6 +896,71 @@ Deinterlace(filter_t * filter, picture_t * src)
>> return dest;
>> }
>>
>> +static picture_t *
>> +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
>> + too and the callback system...so a rewrite of this module basically.*/
>> + for (unsigned int i = 1; i < METADATA_SIZE; ++i)
>> + p_deint_data->meta[i-1] = p_deint_data->meta[i];
>> + 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);
>> + if (p_deint_data->history.num_pics < p_deint_data->history.sz)
>> + return NULL;
>> +
>> + mtime_t i_field_dur = 0;
>> + unsigned int i = 0;
>> + for ( ; i < METADATA_SIZE-1; i ++)
>> + if (p_deint_data->meta[i].date > VLC_TS_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 = CLOCK_FREQ * 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,
>> + Deinterlace_UpdateFilterParams,
>> + Deinterlace_UpdateReferenceFrames,
>> + Deinterlace_UpdatePipelineParams);
>> + if (!dest[i])
>> + goto error;
>> +
>> + dest[i]->b_progressive = true;
>> + dest[i]->i_nb_fields = 1;
>> + }
>> +
>> + dest[0]->p_next = dest[1];
>> + dest[0]->date = cur->date;
>> + if (dest[0]->date > VLC_TS_INVALID)
>> + dest[1]->date = dest[0]->date + i_field_dur;
>> + else
>> + dest[1]->date = VLC_TS_INVALID;
>> +
>> + return dest[0];
>> +
>> +error:
>> + for (i = 0; i < 2; ++i)
>> + if (dest[i])
>> + picture_Release(dest[i]);
>> +
>> + return NULL;
>> +}
>> +
>> static void
>> Deinterlace_Flush(filter_t *filter)
>> {
>> @@ -884,6 +972,12 @@ Deinterlace_Flush(filter_t *filter)
>> p_deint_data->history.pp_pics[--p_deint_data->history.num_pics];
>> picture_Release(pic);
>> }
>> +
>> + for (unsigned int i = 0; i < METADATA_SIZE; ++i)
>> + {
>> + p_deint_data->meta[i].date = VLC_TS_INVALID;
>> + p_deint_data->meta[i].i_nb_fields = 2;
>> + }
>> }
>>
>> static inline bool
>> @@ -901,7 +995,7 @@ OpenDeinterlace_IsValidType(filter_t * filter,
>>
>> static inline int
>> OpenDeinterlace_GetMode(filter_t * filter, char const * deint_mode,
>> - VAProcDeinterlacingType * p_deint_mode,
>> + struct deint_mode * p_deint_mode,
>> VAProcDeinterlacingType const caps[],
>> unsigned int num_caps)
>> {
>> @@ -915,7 +1009,7 @@ OpenDeinterlace_GetMode(filter_t * filter, char const * deint_mode,
>> if (OpenDeinterlace_IsValidType(filter, caps, num_caps,
>> deint_modes + i))
>> {
>> - *p_deint_mode = deint_modes[i].type;
>> + memcpy(p_deint_mode, &deint_modes[i], sizeof(*p_deint_mode));
>
> *p_deint_mode = deint_modes[i] was fine. That's one good thing about structure.
Yeah...that's how I had it actually, but it gave a compile error (sorry I can't remember which one now, but I'm using a self-built gcc 5.4.0 on a deliberately old version of Ubuntu - 12.04 ), so I figured something about the compiler flags was disallowing this.
>
>> msg_Dbg(filter, "using %s deinterlace method",
>> deint_modes[i].name);
>> return VLC_SUCCESS;
>> @@ -929,7 +1023,7 @@ OpenDeinterlace_GetMode(filter_t * filter, char const * deint_mode,
>> if (OpenDeinterlace_IsValidType(filter, caps, num_caps,
>> deint_modes + i))
>> {
>> - *p_deint_mode = deint_modes[i].type;
>> + memcpy(p_deint_mode, &deint_modes[i], sizeof(*p_deint_mode));
>
> idem
>
>> if (fallback)
>> msg_Info(filter, "%s algorithm not available, falling back to "
>> "%s algorithm", deint_mode, deint_modes[i].name);
>> @@ -952,7 +1046,8 @@ OpenDeinterlace_InitFilterParams(filter_t * filter, void * p_data,
>> void ** pp_va_params,
>> uint32_t * p_va_param_sz,
>> uint32_t * p_num_va_params)
>> -{ VLC_UNUSED(p_data);
>> +{
>> + struct deint_data *const p_deint_data = p_data;
>> filter_sys_t *const filter_sys = filter->p_sys;
>> VAProcDeinterlacingType caps[VAProcDeinterlacingCount];
>> unsigned int num_caps = VAProcDeinterlacingCount;
>> @@ -964,12 +1059,12 @@ OpenDeinterlace_InitFilterParams(filter_t * filter, void * p_data,
>> &caps, &num_caps))
>> return VLC_EGENERIC;
>>
>> - VAProcDeinterlacingType va_mode;
>> - char *const psz_deint_mode =
>> + struct deint_mode deint_mode;
>> + char *const psz_deint_mode =
>> var_InheritString(filter, "deinterlace-mode");
>>
>> int ret = OpenDeinterlace_GetMode(filter, psz_deint_mode,
>> - &va_mode, caps, num_caps);
>> + &deint_mode, caps, num_caps);
>> free(psz_deint_mode);
>> if (ret)
>> return VLC_EGENERIC;
>> @@ -984,9 +1079,11 @@ OpenDeinterlace_InitFilterParams(filter_t * filter, void * p_data,
>> return VLC_ENOMEM;
>>
>> p_va_param->type = VAProcFilterDeinterlacing;
>> - p_va_param->algorithm = va_mode;
>> + p_va_param->algorithm = deint_mode.type;
>> *pp_va_params = p_va_param;
>>
>> + p_deint_data->b_double_rate = deint_mode.b_double_rate;
>> +
>> return VLC_SUCCESS;
>> }
>>
>> @@ -1040,9 +1137,18 @@ OpenDeinterlace(vlc_object_t * obj)
>> OpenDeinterlace_InitFilterParams, OpenDeinterlace_InitHistory))
>> goto error;
>>
>> - filter->pf_video_filter = Deinterlace;
>> + if (p_data->b_double_rate)
>> + filter->pf_video_filter = DeinterlaceX2;
>> + else
>> + filter->pf_video_filter = Deinterlace;
>> filter->pf_flush = Deinterlace_Flush;
>>
>> + for (unsigned int i = 0; i < METADATA_SIZE; ++i)
>> + {
>> + p_data->meta[i].date = VLC_TS_INVALID;
>> + p_data->meta[i].i_nb_fields = 2;
>> + }
>> +
>> return VLC_SUCCESS;
>>
>> error:
>>
>> _______________________________________________
>> vlc-commits mailing list
>> vlc-commits at videolan.org
>> https://mailman.videolan.org/listinfo/vlc-commits
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list