[Mesa-dev] [PATCH 1/2] st/vdpau: Don't reallocate video surfaces on putBitsYCbCr format mismatch

Christian K├Ânig deathsimple at vodafone.de
Wed Feb 22 14:00:56 UTC 2017


Am 22.02.2017 um 14:42 schrieb Thomas Hellstrom:
> mplayer likes putting YV12 data, and if there is a buffer format mismatch,
> the vdpau state tracker would try to reallocate the video surface as an
> YV12 surface. A virtual driver doesn't like reallocating and doesn't like YV12
> surfaces, so before trying the reallocation, check whether we can instead do
> an YV12 to NV12 format conversion.
>
> Also advertize that we actually can do the getBits and putBits conversion.
>
> Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>
> Reviewed-by: Sinclair Yeh <syeh at vmware.com>

NAK, the internal format of the surfaces should follow what the 
application has put into it as much as possible. That has quite some 
performance advantages.

You should only do the conversation if the backend driver can't handle 
the desired format.

Regards,
Christian.

> ---
>   src/gallium/auxiliary/util/u_video.h       | 42 +++++++++++++++++++++++++
>   src/gallium/state_trackers/vdpau/query.c   | 13 ++++++++
>   src/gallium/state_trackers/vdpau/surface.c | 50 +++++++++++++++++++++++++-----
>   3 files changed, 98 insertions(+), 7 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_video.h b/src/gallium/auxiliary/util/u_video.h
> index 99a8fd6..7cd6268 100644
> --- a/src/gallium/auxiliary/util/u_video.h
> +++ b/src/gallium/auxiliary/util/u_video.h
> @@ -107,6 +107,48 @@ u_copy_nv12_to_yv12(void *const *destination_data,
>      }
>   }
>   
> +/**
> + * \brief  Copy YV12 chroma data while converting it NV12
> + *
> + * Given a set of YV12 source pointers and -pitches, copy the data to a
> + * layout typical for NV12 video buffers.
> + *
> + * \param source data[in]  The plane data pointers. Array of 3.
> + * \param source_pitches[in]  The plane pitches. Array of 3.
> + * \param dst_plane[in]  The destination plane to copy to. For NV12 always 1.
> + * \param dst_field[in]  The destination field if interlaced.
> + * \param dst_stride[in]  The destination stride for this plane.
> + * \param num_fields[in]  The number of fields in the video buffer.
> + * \param dst[in]  The destination plane pointer.
> + * \param width[in]  The source plane width.
> + * \param height[in]  The source plane height.
> + */
> +static inline void
> +u_copy_nv12_from_yv12(const void *const *source_data,
> +                      uint32_t const *source_pitches,
> +                      int dst_plane, int dst_field,
> +                      int dst_stride, int num_fields,
> +                      uint8_t *dst,
> +                      int width, int height)
> +{
> +   int x, y;
> +   unsigned u_stride = source_pitches[2] * num_fields;
> +   unsigned v_stride = source_pitches[1] * num_fields;
> +   uint8_t *u_src = (uint8_t *)source_data[2] + source_pitches[2] * dst_field;
> +   uint8_t *v_src = (uint8_t *)source_data[1] + source_pitches[1] * dst_field;
> +
> +   /* TODO: SIMD */
> +   for (y = 0; y < height; y++) {
> +      for (x = 0; x < width; x++) {
> +         dst[2*x] = u_src[x];
> +         dst[2*x+1] = v_src[x];
> +      }
> +      u_src += u_stride;
> +      v_src += v_stride;
> +      dst += dst_stride;
> +   }
> +}
> +
>   static inline void
>   u_copy_yv12_to_nv12(void *const *destination_data,
>                       uint32_t const *destination_pitches,
> diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c
> index e69c9b1..435cafd 100644
> --- a/src/gallium/state_trackers/vdpau/query.c
> +++ b/src/gallium/state_trackers/vdpau/query.c
> @@ -123,8 +123,21 @@ vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaTyp
>   
>      switch(bits_ycbcr_format) {
>      case VDP_YCBCR_FORMAT_NV12:
> +      *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420;
> +      break;
> +
>      case VDP_YCBCR_FORMAT_YV12:
>         *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420;
> +
> +      /* We can convert YV12 to NV12 on the fly! */
> +      if (*is_supported &&
> +          pscreen->is_video_format_supported(pscreen,
> +                                             PIPE_FORMAT_NV12,
> +                                             PIPE_VIDEO_PROFILE_UNKNOWN,
> +                                             PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) {
> +         pipe_mutex_unlock(dev->mutex);
> +         return VDP_STATUS_OK;
> +      }
>         break;
>   
>      case VDP_YCBCR_FORMAT_UYVY:
> diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c
> index 9a80605..927fbcb 100644
> --- a/src/gallium/state_trackers/vdpau/surface.c
> +++ b/src/gallium/state_trackers/vdpau/surface.c
> @@ -304,9 +304,11 @@ vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface,
>                                 uint32_t const *source_pitches)
>   {
>      enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format);
> +   enum getbits_conversion conversion = CONVERSION_NONE;
>      struct pipe_context *pipe;
>      struct pipe_sampler_view **sampler_views;
>      unsigned i, j;
> +   unsigned usage = PIPE_TRANSFER_WRITE;
>   
>      vlVdpSurface *p_surf = vlGetDataHTAB(surface);
>      if (!p_surf)
> @@ -320,7 +322,16 @@ vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface,
>          return VDP_STATUS_INVALID_POINTER;
>   
>      pipe_mutex_lock(p_surf->device->mutex);
> -   if (p_surf->video_buffer == NULL || pformat != p_surf->video_buffer->buffer_format) {
> +
> +   if (pformat != p_surf->video_buffer->buffer_format) {
> +      if (pformat == PIPE_FORMAT_YV12 &&
> +          p_surf->video_buffer->buffer_format == PIPE_FORMAT_NV12)
> +         conversion = CONVERSION_YV12_TO_NV12;
> +   }
> +
> +   if (p_surf->video_buffer == NULL ||
> +       ((pformat != p_surf->video_buffer->buffer_format) &&
> +        conversion == CONVERSION_NONE)) {
>   
>         /* destroy the old one */
>         if (p_surf->video_buffer)
> @@ -349,21 +360,46 @@ vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface,
>      for (i = 0; i < 3; ++i) {
>         unsigned width, height;
>         struct pipe_sampler_view *sv = sampler_views[i];
> +      struct pipe_resource *tex;
>         if (!sv || !source_pitches[i]) continue;
>   
> +      tex = sv->texture;
>         vlVdpVideoSurfaceSize(p_surf, i, &width, &height);
>   
> -      for (j = 0; j < sv->texture->array_size; ++j) {
> +      for (j = 0; j < tex->array_size; ++j) {
>            struct pipe_box dst_box = {
>               0, 0, j,
>               width, height, 1
>            };
>   
> -         pipe->texture_subdata(pipe, sv->texture, 0,
> -                               PIPE_TRANSFER_WRITE, &dst_box,
> -                               source_data[i] + source_pitches[i] * j,
> -                               source_pitches[i] * sv->texture->array_size,
> -                               0);
> +         if (conversion == CONVERSION_YV12_TO_NV12 && i == 1) {
> +            struct pipe_transfer *transfer;
> +            uint8_t *map;
> +
> +            map = pipe->transfer_map(pipe, tex, 0, usage,
> +                                     &dst_box, &transfer);
> +            if (!map) {
> +               pipe_mutex_unlock(p_surf->device->mutex);
> +               return VDP_STATUS_RESOURCES;
> +            }
> +
> +            u_copy_nv12_from_yv12(source_data, source_pitches,
> +                                  i, j, transfer->stride, tex->array_size,
> +                                  map, dst_box.width, dst_box.height);
> +
> +            pipe_transfer_unmap(pipe, transfer);
> +         } else {
> +            pipe->texture_subdata(pipe, tex, 0,
> +                                  PIPE_TRANSFER_WRITE, &dst_box,
> +                                  source_data[i] + source_pitches[i] * j,
> +                                  source_pitches[i] * tex->array_size,
> +                                  0);
> +         }
> +         /*
> +          * This surface has already been synced
> +          * by the first map.
> +          */
> +         usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
>         }
>      }
>      pipe_mutex_unlock(p_surf->device->mutex);




More information about the mesa-dev mailing list