Quoting wm4 (2015-12-27 14:41:16)
> On Sun, 20 Dec 2015 20:59:30 +0100
> Anton Khirnov <[email protected]> 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.

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to