[Mesa-dev] [PATCH v4] st/vdpau: use bicubic filter for scaling

Nayan Deshmukh nayan26deshmukh at gmail.com
Wed Jun 22 11:17:29 UTC 2016


Thanks for the review.

On Wed, Jun 22, 2016 at 1:17 PM, Christian König <deathsimple at vodafone.de>
wrote:

> Am 21.06.2016 um 21:21 schrieb Nayan Deshmukh:
>
>> use bicubic filtering as high quality scaling L1.
>>
>> v2: fix a typo and add a newline to code
>>
>> v3: -render the unscaled image on a temporary surface (Christian)
>>      -apply noise reduction and sharpness filter on
>>       unscaled surface
>>      -render the final scaled surface using bicubic
>>       interpolation
>>
>> v4: support high quality scaling
>>
>> Signed-off-by: Nayan Deshmukh <nayan26deshmukh at gmail.com>
>> ---
>>   src/gallium/state_trackers/vdpau/mixer.c         | 109
>> ++++++++++++++++++++---
>>   src/gallium/state_trackers/vdpau/query.c         |   1 +
>>   src/gallium/state_trackers/vdpau/vdpau_private.h |   6 ++
>>   3 files changed, 102 insertions(+), 14 deletions(-)
>>
>> diff --git a/src/gallium/state_trackers/vdpau/mixer.c
>> b/src/gallium/state_trackers/vdpau/mixer.c
>> index 65c3ce2..2a67ac2 100644
>> --- a/src/gallium/state_trackers/vdpau/mixer.c
>> +++ b/src/gallium/state_trackers/vdpau/mixer.c
>> @@ -82,7 +82,6 @@ vlVdpVideoMixerCreate(VdpDevice device,
>>         switch (features[i]) {
>>         /* they are valid, but we doesn't support them */
>>         case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
>> -      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
>> @@ -110,6 +109,9 @@ vlVdpVideoMixerCreate(VdpDevice device,
>>            vmixer->luma_key.supported = true;
>>            break;
>>   +      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>> +         vmixer->bicubic.supported = true;
>> +         break;
>>         default: goto no_params;
>>         }
>>      }
>> @@ -202,6 +204,11 @@ vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
>>         vl_matrix_filter_cleanup(vmixer->sharpness.filter);
>>         FREE(vmixer->sharpness.filter);
>>      }
>> +
>> +   if (vmixer->bicubic.filter) {
>> +      vl_bicubic_filter_cleanup(vmixer->bicubic.filter);
>> +      FREE(vmixer->bicubic.filter);
>> +   }
>>      pipe_mutex_unlock(vmixer->device->mutex);
>>      DeviceReference(&vmixer->device, NULL);
>>   @@ -230,9 +237,11 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer
>> mixer,
>>                                   VdpLayer const *layers)
>>   {
>>      enum vl_compositor_deinterlace deinterlace;
>> -   struct u_rect rect, clip, *prect;
>> +   struct u_rect rect, clip, *prect, *rect_temp, dirty_area, temp;
>>      unsigned i, layer = 0;
>>      struct pipe_video_buffer *video_buffer;
>> +   struct pipe_sampler_view *sampler_view;
>> +   struct pipe_surface *surface;
>>        vlVdpVideoMixer *vmixer;
>>      vlVdpSurface *surf;
>> @@ -324,8 +333,48 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
>>         rect.y1 = surf->templat.height;
>>         prect = ▭
>>      }
>> +
>> +   if(vmixer->bicubic.filter){
>> +      struct pipe_context *pipe;
>> +      struct pipe_resource res_tmpl, *res;
>> +      struct pipe_sampler_view sv_templ;
>> +      struct pipe_surface surf_templ;
>> +
>> +      pipe = vmixer->device->context;
>> +      memset(&res_tmpl, 0, sizeof(res_tmpl));
>> +
>> +      res_tmpl.target = PIPE_TEXTURE_2D;
>> +      res_tmpl.format = surf->templat.chroma_format;
>>
>
> That is incorrect. The resource format isn't related in any way to the
> chroma format. Please use the format of the destination surface here.
>
> I should probably use res_tmpl = dst->sampler_view->texture->format; Right?


> +      res_tmpl.width0 = surf->templat.width;
>> +      res_tmpl.height0 = surf->templat.height;
>> +      res_tmpl.depth0 = 1;
>> +      res_tmpl.array_size = 1;
>> +      res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET |
>> +                     PIPE_BIND_LINEAR | PIPE_BIND_SHARED;
>>
>
> No need for PIPE_BIND_LINEAR or PIPE_BIND_SHARED here, we are not going to
> share the temporary texture with anybody.
>
> +      res_tmpl.usage = PIPE_USAGE_DEFAULT;
>> +
>> +      res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
>> +
>> +      vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
>> +      sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
>> +
>> +      memset(&surf_templ, 0, sizeof(surf_templ));
>> +      surf_templ.format = res->format;
>> +      surface = pipe->create_surface(pipe, res, &surf_templ);
>> +
>> +      vl_compositor_reset_dirty_area(&dirty_area);
>> +      rect_temp = prect;
>>
>
> You need to free the resource with pipe_resource_reference(&res, NULL);
> here, otherwise you will create quite a memory leak.
>
> Same thing is true for the surface and the sampler view, but you need
> those and can only free them later on. Easiest way to do this is probably
> to grab an extra reference in the else case as well.
>
> I can also check in the end if (surface != dst->surface) and then free the
surface and sampler_view if it's true.


> +   }
>> +
>> +   else{
>>
>
> Coding style here should be "} else {" if I remember correctly.
>
> +       surface = dst->surface;
>> +       sampler_view = dst->sampler_view;
>> +       rect_temp = RectToPipe(destination_video_rect, &temp);
>> +       dirty_area = dst->dirty_area;
>> +   }
>> +
>>      vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer,
>> video_buffer, prect, NULL, deinterlace);
>> -   vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++,
>> RectToPipe(destination_video_rect, &rect));
>> +   vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, rect_temp);
>>        for (i = 0; i < layer_count; ++i) {
>>         vlVdpOutputSurface *src = vlGetDataHTAB(layers->source_surface);
>> @@ -343,22 +392,22 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
>>         ++layers;
>>      }
>>   -   vl_compositor_set_dst_clip(&vmixer->cstate,
>> RectToPipe(destination_rect, &clip));
>>
>
> That probably needs to be moved into the true case of the if and the clip
> handled by the bicubic filter as well.
>
> Same is true for the destination video rectangle as well.
>
>
if the bicubic scaling is off then we need to set dst_area and dst_clip in
vl_compositor, but if bicubic scaling is on then
dst_area and dst_clip should be set in bicubic_filter.

Regards,
Nayan.

> Regards,
> Christian.
>
>
> -   if (!vmixer->noise_reduction.filter && !vmixer->sharpness.filter)
>> +   if (!vmixer->noise_reduction.filter && !vmixer->sharpness.filter &&
>> !vmixer->bicubic.filter)
>>         vlVdpSave4DelayedRendering(vmixer->device, destination_surface,
>> &vmixer->cstate);
>>      else {
>> -      vl_compositor_render(&vmixer->cstate, compositor, dst->surface,
>> &dst->dirty_area, true);
>> +      vl_compositor_render(&vmixer->cstate, compositor, surface,
>> &dirty_area, true);
>>   -      /* applying the noise reduction after scaling is actually not
>> very
>> -         clever, but currently we should avoid to copy around the image
>> -         data once more. */
>>         if (vmixer->noise_reduction.filter)
>>            vl_median_filter_render(vmixer->noise_reduction.filter,
>> -                                 dst->sampler_view, dst->surface);
>> +                                 sampler_view, surface);
>>           if (vmixer->sharpness.filter)
>>            vl_matrix_filter_render(vmixer->sharpness.filter,
>> -                                 dst->sampler_view, dst->surface);
>> +                                 sampler_view, surface);
>> +
>> +      if (vmixer->bicubic.filter)
>> +         vl_bicubic_filter_render(vmixer->bicubic.filter,
>> +                                 sampler_view, dst->surface);
>>      }
>>      pipe_mutex_unlock(vmixer->device->mutex);
>>   @@ -461,6 +510,28 @@
>> vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer)
>>   }
>>     /**
>> + * Update the bicubic filter
>> + */
>> +static void
>> +vlVdpVideoMixerUpdateBicubicFilter(vlVdpVideoMixer *vmixer)
>> +{
>> +   assert(vmixer);
>> +
>> +   /* if present remove the old filter first */
>> +   if (vmixer->bicubic.filter) {
>> +      vl_bicubic_filter_cleanup(vmixer->bicubic.filter);
>> +      FREE(vmixer->bicubic.filter);
>> +      vmixer->bicubic.filter = NULL;
>> +   }
>> +   /* and create a new filter as needed */
>> +   if (vmixer->bicubic.enabled) {
>> +      vmixer->bicubic.filter = MALLOC(sizeof(struct vl_bicubic_filter));
>> +      vl_bicubic_filter_init(vmixer->bicubic.filter,
>> vmixer->device->context,
>> +                            vmixer->video_width, vmixer->video_height);
>> +   }
>> +}
>> +
>> +/**
>>    * Retrieve whether features were requested at creation time.
>>    */
>>   VdpStatus
>> @@ -483,7 +554,6 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
>>         switch (features[i]) {
>>         /* they are valid, but we doesn't support them */
>>         case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
>> -      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
>> @@ -512,6 +582,10 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
>>            feature_supports[i] = vmixer->luma_key.supported;
>>            break;
>>   +      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>> +         feature_supports[i] = vmixer->bicubic.supported;
>> +         break;
>> +
>>         default:
>>            return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
>>         }
>> @@ -544,7 +618,6 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
>>         switch (features[i]) {
>>         /* they are valid, but we doesn't support them */
>>         case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
>> -      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
>> @@ -578,6 +651,11 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
>>                                            vmixer->luma_key.luma_min,
>> vmixer->luma_key.luma_max);
>>            break;
>>   +      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>> +         vmixer->bicubic.enabled = feature_enables[i];
>> +         vlVdpVideoMixerUpdateBicubicFilter(vmixer);
>> +         break;
>> +
>>         default:
>>            pipe_mutex_unlock(vmixer->device->mutex);
>>            return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
>> @@ -612,7 +690,6 @@ vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,
>>         /* they are valid, but we doesn't support them */
>>         case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
>>         case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
>> -      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
>>         case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
>> @@ -636,6 +713,10 @@ vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,
>>            feature_enables[i] = vmixer->luma_key.enabled;
>>            break;
>>   +      case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>> +         feature_enables[i] = vmixer->bicubic.enabled;
>> +         break;
>> +
>>         default:
>>            return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
>>         }
>> diff --git a/src/gallium/state_trackers/vdpau/query.c
>> b/src/gallium/state_trackers/vdpau/query.c
>> index c3decc0..e69c9b1 100644
>> --- a/src/gallium/state_trackers/vdpau/query.c
>> +++ b/src/gallium/state_trackers/vdpau/query.c
>> @@ -471,6 +471,7 @@ vlVdpVideoMixerQueryFeatureSupport(VdpDevice device,
>> VdpVideoMixerFeature featur
>>      case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
>>      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
>>      case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
>> +   case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
>>         *is_supported = VDP_TRUE;
>>         break;
>>      default:
>> diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h
>> b/src/gallium/state_trackers/vdpau/vdpau_private.h
>> index 8673c6a..bcd4bb1 100644
>> --- a/src/gallium/state_trackers/vdpau/vdpau_private.h
>> +++ b/src/gallium/state_trackers/vdpau/vdpau_private.h
>> @@ -45,6 +45,7 @@
>>   #include "os/os_thread.h"
>>     #include "vl/vl_video_buffer.h"
>> +#include "vl/vl_bicubic_filter.h"
>>   #include "vl/vl_compositor.h"
>>   #include "vl/vl_csc.h"
>>   #include "vl/vl_deint_filter.h"
>> @@ -373,6 +374,11 @@ typedef struct
>>      } deint;
>>        struct {
>> +         bool supported, enabled;
>> +         struct vl_bicubic_filter *filter;
>> +   } bicubic;
>> +
>> +   struct {
>>         bool supported, enabled;
>>         unsigned level;
>>         struct vl_median_filter *filter;
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160622/76537003/attachment-0001.html>


More information about the mesa-dev mailing list