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