On Fri, 01 Jan 2016 20:02:07 +0200
Rémi Denis-Courmont <r...@remlab.net> wrote:

> Le 2016-01-01 18:09, Anton Khirnov a écrit :
> > Quoting wm4 (2015-12-27 14:41:16)  
> >> On Sun, 20 Dec 2015 20:59:30 +0100
> >> Anton Khirnov <an...@khirnov.net> wrote:
> >>  
> >> > ---
> >> >  libavcodec/vdpau.c          | 101   
> >> ++++++++++++++++++++++++++++++++++++++++++--  
> >> >  libavcodec/vdpau_h264.c     |   1 +
> >> >  libavcodec/vdpau_internal.h |  11 +++++
> >> >  libavcodec/vdpau_mpeg12.c   |   1 +
> >> >  libavcodec/vdpau_mpeg4.c    |   1 +
> >> >  libavcodec/vdpau_vc1.c      |   2 +
> >> >  6 files changed, 113 insertions(+), 4 deletions(-)
> >> >
> >> > diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c
> >> > index dd48c04..5c41ee8 100644
> >> > --- a/libavcodec/vdpau.c
> >> > +++ b/libavcodec/vdpau.c
> >> > @@ -23,6 +23,10 @@
> >> >
> >> >  #include <limits.h>
> >> >  #include "libavutil/avassert.h"
> >> > +#include "libavutil/buffer.h"
> >> > +#include "libavutil/hwframe.h"
> >> > +#include "libavutil/hwframe_vdpau.h"
> >> > +
> >> >  #include "avcodec.h"
> >> >  #include "internal.h"
> >> >  #include "h264.h"
> >> > @@ -201,14 +205,52 @@ int ff_vdpau_common_init(AVCodecContext   
> >> *avctx, VdpDecoderProfile profile,  
> >> >      else
> >> >          vdctx->render = func;
> >> >
> >> > +    status = vdctx->get_proc_address(vdctx->device,   
> >> VDP_FUNC_ID_VIDEO_SURFACE_CREATE,  
> >> > +                                     &func);
> >> > +    if (status != VDP_STATUS_OK)
> >> > +        return vdpau_error(status);
> >> > +    vdctx->surf_create = func;
> >> > +
> >> > +    status = vdctx->get_proc_address(vdctx->device,   
> >> VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,  
> >> > +                                     &func);
> >> > +    if (status != VDP_STATUS_OK)
> >> > +        return vdpau_error(status);
> >> > +    vdctx->surf_destroy = func;
> >> > +
> >> >      status = create(vdctx->device, profile, width, height,   
> >> avctx->refs,  
> >> >                      &vdctx->decoder);
> >> > -    if (status == VDP_STATUS_OK) {
> >> > -        vdctx->width  = avctx->coded_width;
> >> > -        vdctx->height = avctx->coded_height;
> >> > +    if (status != VDP_STATUS_OK)
> >> > +        return vdpau_error(status);
> >> > +
> >> > +    vdctx->width       = avctx->coded_width;
> >> > +    vdctx->height      = avctx->coded_height;
> >> > +    vdctx->chroma_type = type;
> >> > +
> >> > +    if (avctx->hwframe_ctx_free) {
> >> > +        AVHWFramesContext *hwframe_ctx;
> >> > +        AVVDPAUFramesContext *vdpau_frame_ctx;
> >> > +        int ret;
> >> > +
> >> > +        vdctx->hwframe_ctx =   
> >> av_hwframe_ctx_alloc(AV_PIX_FMT_VDPAU);  
> >> > +        if (!vdctx->hwframe_ctx)
> >> > +            return AVERROR(ENOMEM);
> >> > +
> >> > +        hwframe_ctx              =   
> >> (AVHWFramesContext*)vdctx->hwframe_ctx->data;  
> >> > +        hwframe_ctx->free        = avctx->hwframe_ctx_free;
> >> > +        hwframe_ctx->user_opaque = avctx->hwframe_ctx_opaque;
> >> > +
> >> > +        vdpau_frame_ctx                   = hwframe_ctx->hwctx;
> >> > +        vdpau_frame_ctx->device           = vdctx->device;
> >> > +        vdpau_frame_ctx->get_proc_address =   
> >> vdctx->get_proc_address;  
> >> > +
> >> > +        ret = av_hwframe_ctx_init(vdctx->hwframe_ctx);
> >> > +        if (ret < 0) {
> >> > +            av_buffer_unref(&vdctx->hwframe_ctx);
> >> > +            return ret;
> >> > +        }
> >> >      }
> >> >
> >> > -    return vdpau_error(status);
> >> > +    return 0;
> >> >  }
> >> >
> >> >  int ff_vdpau_common_uninit(AVCodecContext *avctx)
> >> > @@ -218,6 +260,8 @@ int ff_vdpau_common_uninit(AVCodecContext   
> >> *avctx)  
> >> >      void *func;
> >> >      VdpStatus status;
> >> >
> >> > +    av_buffer_unref(&vdctx->hwframe_ctx);
> >> > +
> >> >      if (vdctx->device == VDP_INVALID_HANDLE)
> >> >          return 0; /* Decoder created and destroyed by user */
> >> >      if (vdctx->width == UINT32_MAX && vdctx->height ==   
> >> UINT32_MAX)  
> >> > @@ -317,6 +361,55 @@ int ff_vdpau_add_buffer(struct   
> >> vdpau_picture_context *pic_ctx,  
> >> >      return 0;
> >> >  }
> >> >
> >> > +static void vdpau_release_buffer(void *opaque, uint8_t *data)
> >> > +{
> >> > +    VdpVideoSurfaceDestroy *destroy = opaque;
> >> > +    VdpVideoSurface            surf =   
> >> (VdpVideoSurface)(uintptr_t)data;  
> >> > +
> >> > +    destroy(surf);
> >> > +}
> >> > +
> >> > +int ff_vdpau_get_buffer(AVCodecContext *avctx, AVFrame *frame)
> >> > +{
> >> > +    VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
> >> > +
> >> > +    VdpVideoSurface surf;
> >> > +    VdpStatus        err;
> >> > +
> >> > +    if (!vdctx->hwframe_ctx) {
> >> > +        av_log(avctx, AV_LOG_ERROR,
> >> > +               "You must set AVCodecContext.hwframe_ctx_free to   
> >> use"  
> >> > +               "the internal VDPAU get_buffer().\n");
> >> > +        return AVERROR(EINVAL);
> >> > +    }
> >> > +
> >> > +    err = vdctx->surf_create(vdctx->device, vdctx->chroma_type,
> >> > +                             frame->width, frame->height, &surf);
> >> > +    if (err != VDP_STATUS_OK) {
> >> > +        av_log(avctx, AV_LOG_ERROR, "Error creating a   
> >> surface\n");  
> >> > +        return vdpau_error(err);
> >> > +    }
> >> > +
> >> > +    frame->buf[0] = av_buffer_create((uint8_t*)(uintptr_t)surf,   
> >> sizeof(surf),  
> >> > +                                     vdpau_release_buffer,   
> >> vdctx->surf_destroy,  
> >> > +                                     AV_BUFFER_FLAG_READONLY);  
> >>
> >> Shouldn't this return/alloc the frame from a surface pool? (Though 
> >> I'm
> >> going to be happy if you tell me that vdpau surface allocation is
> >> always maximally efficient and doesn't need a pool.)
> >>  
> >
> > Rémi tells me the pools are not need for performance reasons. But 
> > some
> > old hardware requires preallocating surfaces for some other weird
> > reasons. And of course many other APIs can only work with the full 
> > pool
> > preallocated beforehand, so some support for that will be needed.  
> 
> Uh? No. VDPAU has no requirements to preallocate surfaces. The problem 
> is, preallocating is the only way to ensure that the GPU will have 
> enough memory to meet the run-time buffers requirements.
> 
> Otherwise, you might end up, e.g. with 4 video surfaces on a bitstream 
> that requires 16 reference frames. And fail.
> 

Is that the only reason? So preallocation (and reusing surfaces) is not
needed for performance?
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to