Re: [FFmpeg-devel] [PATCH v3 1/5] libavutil: some VAAPI infrastructure
On Mon, 18 Jan 2016 22:49:51 + Mark Thompsonwrote: > --- > configure | 4 + > libavutil/Makefile | 1 + > libavutil/vaapi.c | 497 > + > libavutil/vaapi.h | 123 + > 4 files changed, 625 insertions(+) > create mode 100644 libavutil/vaapi.c > create mode 100644 libavutil/vaapi.h > Trying to do a more thorough review. > diff --git a/configure b/configure > index 7cef6f5..1c77015 100755 > --- a/configure > +++ b/configure > @@ -5739,6 +5739,10 @@ enabled vaapi && enabled xlib && > check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 && > enable vaapi_x11 > > +enabled vaapi && > +check_lib2 "va/va.h va/va_drm.h" vaGetDisplayDRM -lva -lva-drm && > +enable vaapi_drm > + > enabled vdpau && > check_cpp_condition vdpau/vdpau.h "defined > VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || > disable vdpau > diff --git a/libavutil/Makefile b/libavutil/Makefile > index bf8c713..8025f9f 100644 > --- a/libavutil/Makefile > +++ b/libavutil/Makefile > @@ -146,6 +146,7 @@ OBJS-$(!HAVE_ATOMICS_NATIVE)+= atomic.o > \ > > OBJS-$(CONFIG_LZO) += lzo.o > OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o > +OBJS-$(CONFIG_VAAPI)+= vaapi.o > > OBJS += $(COMPAT_OBJS:%=../compat/%) > > diff --git a/libavutil/vaapi.c b/libavutil/vaapi.c > new file mode 100644 > index 000..8a9a524 > --- /dev/null > +++ b/libavutil/vaapi.c > @@ -0,0 +1,497 @@ > +/* > + * VAAPI helper functions. > + * > + * Copyright (C) 2016 Mark Thompson > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include "vaapi.h" > + > +#include "avassert.h" > +#include "imgutils.h" > +#include "pixfmt.h" > + > + > +void av_vaapi_lock_hardware_context(AVVAAPIHardwareContext *ctx) > +{ > +if(ctx->lock) > +ctx->lock(); > +} > + > +void av_vaapi_unlock_hardware_context(AVVAAPIHardwareContext *ctx) > +{ > +if(ctx->unlock) > +ctx->unlock(); > +} The lock callbacks should take some sort of opaque context pointer. > + > +static const AVClass vaapi_pipeline_class = { > +.class_name = "VAAPI/pipeline", > +.item_name = av_default_item_name, > +.version= LIBAVUTIL_VERSION_INT, > +}; > + > +static int vaapi_create_surfaces(AVVAAPIPipelineContext *ctx, > + AVVAAPISurfaceConfig *config, > + AVVAAPISurface *surfaces, > + VASurfaceID *ids) > +{ > +VAStatus vas; > +int i; > + > +vas = vaCreateSurfaces(ctx->hardware_context->display, config->rt_format, > + config->width, config->height, ids, config->count, > + config->attributes, config->attribute_count); > +if(vas != VA_STATUS_SUCCESS) { > +av_log(ctx, AV_LOG_ERROR, "Failed to create " > + "surfaces: %d (%s).\n", vas, vaErrorStr(vas)); > +return AVERROR(EINVAL); > +} > + > +for(i = 0; i < config->count; i++) { > +surfaces[i].id = ids[i]; > +surfaces[i].refcount = 0; > +surfaces[i].hardware_context = ctx->hardware_context; > +surfaces[i].config = config; > +} > + > +return 0; > +} > + > +static void vaapi_destroy_surfaces(AVVAAPIPipelineContext *ctx, > + AVVAAPISurfaceConfig *config, > + AVVAAPISurface *surfaces, > + VASurfaceID *ids) > +{ > +VAStatus vas; > +int i; > + > +for(i = 0; i < config->count; i++) { > +av_assert0(surfaces[i].id == ids[i]); > +if(surfaces[i].refcount > 0) > +av_log(ctx, AV_LOG_WARNING, "Destroying surface %#x which is " > + "still in use.\n", surfaces[i].id); > +av_assert0(surfaces[i].hardware_context == ctx->hardware_context); > +av_assert0(surfaces[i].config == config); > +} > + > +vas = vaDestroySurfaces(ctx->hardware_context->display, > +ids, config->count); > +if(vas != VA_STATUS_SUCCESS) { > +
Re: [FFmpeg-devel] [PATCH v3 1/5] libavutil: some VAAPI infrastructure
On Tue, 19 Jan 2016 13:19:36 + Mark Thompsonwrote: > ... > >> + > >> +static void vaapi_codec_release_surface(void *opaque, uint8_t *data) > >> +{ > >> +AVVAAPISurface *surface = opaque; > >> + > >> +av_assert0(surface->refcount > 0); > >> +--surface->refcount; > >> +} > > > > Maybe that's just me, but I think vaapi surfaces shouldn't break what > > is guaranteed by AVFrame: > > > > - unreffing them is thread-safe > > - unreffing the last AVFrame will also unref whatever manages the > > surfaces (or alternatively, if the vaapi state is not refcounted, kill > > the process if there are still AVFrames referencing the vaapi state, > > as these AVFrames would essentially have dangling pointers) > > > > That's a bit more complex, but IMO worth it. > > Unref being thread safe is a bit annoying because of the locking - if the > lock were recursive then it could work, but that pushes me into pthreadland > to do it. Is that ok? There could be a second lock which is not user-visible, and which protects the surface pool only. > > I'm not sure what you mean by the second point. What do you want to also go > when the last AVFrame gets unreferenced? Imagine someone holding an AVFrame referencing the surface in the pool at a time when the surface pool should be destroyed. In my own vaapi code, I keep the pool alive until all frames are unreferenced, even if the decoder is destroyed before. Helps with making format changes simpler. > > I know the AVFrame setup is all a bit dubious because I still don't really > "get" how AVFrames are meant to be used. I will think about it further. Some explanation: AVFrames are refcounted via AVFrame.buf[]. Each AVBufferRef is a refcounted memory region, and the AVFrame.data[] pointers are supposed to point into one of the buffers. (All planes can point into memory covered by AVFrame.buf[0], but it's also possible to have each plane its own buffer.) If you create a reference to an AVFrame with e.g. av_frame_ref(), new AVBufferRefs are created, which increases the refcount of the internal buffer. Calling av_frame_unref() deletes the AVBufferRefs and decrease the AVBuffer refcount. If the AVBuffer's refcount reaches 0, the user-provided free callback is invoked. (If there's no free callback, av_free() is called on the original buffer data pointer.) With hwaccels, the situation is a bit more confusing. There are no data pointers, only an ID casted to a pointer. So it's harder to reason what exactly AVBufferRef.data should be. But everything else can work in the same way. If the AVFrame is used in a different thread than the decoder, then it can easily happen that the free callback is invoked in a different thread. > >> + > >> +static int vaapi_get_surface(AVVAAPIPipelineContext *ctx, > >> + AVVAAPISurfaceConfig *config, > >> + AVVAAPISurface *surfaces, AVFrame *frame) > >> +{ > >> +AVVAAPISurface *surface; > >> +int i; > >> + > >> +for(i = 0; i < config->count; i++) { > >> +if(surfaces[i].refcount == 0) > >> +break; > >> +} > >> +if(i >= config->count) { > >> +av_log(ctx, AV_LOG_ERROR, "Failed to allocate surface " > >> + "(%d in use).\n", config->count); > >> +return AVERROR(ENOMEM); > >> +} > >> +surface = [i]; > >> + > >> +++surface->refcount; > >> +frame->data[3] = (uint8_t*)(uintptr_t)surface->id; > >> +frame->buf[0] = av_buffer_create((uint8_t*)surface, 0, > >> + _codec_release_surface, > >> + surface, AV_BUFFER_FLAG_READONLY); > >> +if(!frame->buf[0]) { > >> +av_log(ctx, AV_LOG_ERROR, "Failed to allocate dummy buffer " > >> + "for surface %#x.\n", surface->id); > >> +return AVERROR(ENOMEM); > >> +} > >> + > >> +frame->format = AV_PIX_FMT_VAAPI; > >> +frame->width = config->width; > >> +frame->height = config->height; > >> + > >> +return 0; > >> +} > >> + > >> +int ff_vaapi_get_input_surface(AVVAAPIPipelineContext *ctx, AVFrame > >> *frame) > >> +{ > >> +return vaapi_get_surface(ctx, ctx->input, ctx->input_surfaces, frame); > >> +} > >> + > >> +int ff_vaapi_get_output_surface(AVVAAPIPipelineContext *ctx, AVFrame > >> *frame) > >> +{ > >> +return vaapi_get_surface(ctx, ctx->output, ctx->output_surfaces, > >> frame); > >> +} > > > > I wonder if vaapi_get_surface() could instead be some sort of > > independent frame pool? (But maybe the way you did is already elegant > > wrt. how vaapi works?) > > The only trickiness here is that you have to declare all of the surfaces you > are going to use for output when you create the pipeline context. > > So yes, probably, if I understood AVFrames better... Will consider along > with the previous point. Side note: it might also be possible to recreate the decoder and recreate all surfaces if
Re: [FFmpeg-devel] [PATCH v3 1/5] libavutil: some VAAPI infrastructure
On 19/01/16 11:54, wm4 wrote: > On Mon, 18 Jan 2016 22:49:51 + > Mark Thompsonwrote: > >> --- >> configure | 4 + >> libavutil/Makefile | 1 + >> libavutil/vaapi.c | 497 >> + >> libavutil/vaapi.h | 123 + >> 4 files changed, 625 insertions(+) >> create mode 100644 libavutil/vaapi.c >> create mode 100644 libavutil/vaapi.h >> > > Trying to do a more thorough review. Thanks :) >> diff --git a/configure b/configure >> index 7cef6f5..1c77015 100755 >> --- a/configure >> +++ b/configure >> @@ -5739,6 +5739,10 @@ enabled vaapi && enabled xlib && >> check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 && >> enable vaapi_x11 >> >> +enabled vaapi && >> +check_lib2 "va/va.h va/va_drm.h" vaGetDisplayDRM -lva -lva-drm && >> +enable vaapi_drm >> + >> enabled vdpau && >> check_cpp_condition vdpau/vdpau.h "defined >> VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || >> disable vdpau >> diff --git a/libavutil/Makefile b/libavutil/Makefile >> index bf8c713..8025f9f 100644 >> --- a/libavutil/Makefile >> +++ b/libavutil/Makefile >> @@ -146,6 +146,7 @@ OBJS-$(!HAVE_ATOMICS_NATIVE)+= atomic.o >>\ >> >> OBJS-$(CONFIG_LZO) += lzo.o >> OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o >> +OBJS-$(CONFIG_VAAPI)+= vaapi.o >> >> OBJS += $(COMPAT_OBJS:%=../compat/%) >> >> diff --git a/libavutil/vaapi.c b/libavutil/vaapi.c >> new file mode 100644 >> index 000..8a9a524 >> --- /dev/null >> +++ b/libavutil/vaapi.c >> @@ -0,0 +1,497 @@ >> +/* >> + * VAAPI helper functions. >> + * >> + * Copyright (C) 2016 Mark Thompson >> + * >> + * This file is part of FFmpeg. >> + * >> + * FFmpeg is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2.1 of the License, or (at your option) any later version. >> + * >> + * FFmpeg is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with FFmpeg; if not, write to the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 >> USA >> + */ >> + >> +#include "vaapi.h" >> + >> +#include "avassert.h" >> +#include "imgutils.h" >> +#include "pixfmt.h" >> + >> + >> +void av_vaapi_lock_hardware_context(AVVAAPIHardwareContext *ctx) >> +{ >> +if(ctx->lock) >> +ctx->lock(); >> +} >> + >> +void av_vaapi_unlock_hardware_context(AVVAAPIHardwareContext *ctx) >> +{ >> +if(ctx->unlock) >> +ctx->unlock(); >> +} > > The lock callbacks should take some sort of opaque context pointer. Ok; will add. >> + >> +static const AVClass vaapi_pipeline_class = { >> +.class_name = "VAAPI/pipeline", >> +.item_name = av_default_item_name, >> +.version= LIBAVUTIL_VERSION_INT, >> +}; >> + >> +static int vaapi_create_surfaces(AVVAAPIPipelineContext *ctx, >> + AVVAAPISurfaceConfig *config, >> + AVVAAPISurface *surfaces, >> + VASurfaceID *ids) >> +{ >> +VAStatus vas; >> +int i; >> + >> +vas = vaCreateSurfaces(ctx->hardware_context->display, >> config->rt_format, >> + config->width, config->height, ids, >> config->count, >> + config->attributes, config->attribute_count); >> +if(vas != VA_STATUS_SUCCESS) { >> +av_log(ctx, AV_LOG_ERROR, "Failed to create " >> + "surfaces: %d (%s).\n", vas, vaErrorStr(vas)); >> +return AVERROR(EINVAL); >> +} >> + >> +for(i = 0; i < config->count; i++) { >> +surfaces[i].id = ids[i]; >> +surfaces[i].refcount = 0; >> +surfaces[i].hardware_context = ctx->hardware_context; >> +surfaces[i].config = config; >> +} >> + >> +return 0; >> +} >> + >> +static void vaapi_destroy_surfaces(AVVAAPIPipelineContext *ctx, >> + AVVAAPISurfaceConfig *config, >> + AVVAAPISurface *surfaces, >> + VASurfaceID *ids) >> +{ >> +VAStatus vas; >> +int i; >> + >> +for(i = 0; i < config->count; i++) { >> +av_assert0(surfaces[i].id == ids[i]); >> +if(surfaces[i].refcount > 0) >> +av_log(ctx, AV_LOG_WARNING, "Destroying surface %#x which is " >> + "still in use.\n", surfaces[i].id); >> +av_assert0(surfaces[i].hardware_context == ctx->hardware_context); >> +
Re: [FFmpeg-devel] [PATCH v3 1/5] libavutil: some VAAPI infrastructure
On 19/01/16 00:18, Michael Niedermayer wrote: > On Mon, Jan 18, 2016 at 10:49:51PM +, Mark Thompson wrote: >> >> --- >> configure | 4 + >> libavutil/Makefile | 1 + >> libavutil/vaapi.c | 497 >> + >> libavutil/vaapi.h | 123 + >> 4 files changed, 625 insertions(+) >> create mode 100644 libavutil/vaapi.c >> create mode 100644 libavutil/vaapi.h > > breaks build > make distclean ; ./configure && make -j12 > ... > > CC libavutil/time.o > CC libavutil/timecode.o > CC libavutil/tree.o > CC libavutil/twofish.o > CC libavutil/utils.o > CC libavutil/vaapi.o > CC libavutil/x86/cpu.o > In file included from libavutil/vaapi.c:23:0: > libavutil/vaapi.h:63:5: error: unknown type name ‘VASurfaceAttrib’ > libavutil/vaapi.c: In function ‘vaapi_create_surfaces’: > libavutil/vaapi.c:59:28: warning: passing argument 5 of ‘vaCreateSurfaces’ > makes integer from pointer without a cast [enabled by default] > /usr/include/va/va.h:432:10: note: expected ‘int’ but argument is of type > ‘VASurfaceID *’ > libavutil/vaapi.c:59:28: warning: passing argument 6 of ‘vaCreateSurfaces’ > makes pointer from integer without a cast [enabled by default] > /usr/include/va/va.h:432:10: note: expected ‘VASurfaceID *’ but argument is > of type ‘unsigned int’ > libavutil/vaapi.c:59:28: error: too many arguments to function > ‘vaCreateSurfaces’ > /usr/include/va/va.h:432:10: note: declared here > libavutil/vaapi.c: In function ‘ff_vaapi_copy_to_surface’: > libavutil/vaapi.c:447:9: error: ‘VA_FOURCC_BGRX’ undeclared (first use in > this function) > libavutil/vaapi.c:447:9: note: each undeclared identifier is reported only > once for each function it appears in > make: *** [libavutil/vaapi.o] Error 1 > make: *** Waiting for unfinished jobs > Given the old vaCreateSurfaces you must have libva < 1.2. libva >= 1.6 was stated as the requirement for now in the first email, though even done properly your setup would have everything here disabled at configure time. I think the configure test will be looking for libva 1.2.1 / VAAPI 0.34 for most of this and libva 1.6.0 / VAAPI 0.37 for H.265 (with suitable ifdefs), though more testing is needed to know that those do actually always work. (I have been using libva 1.6.2 / VAAPI 0.38.) I'll write something sensible for that test and associated conditionals in the next version, even if it isn't exactly correct. - Mark ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH v3 1/5] libavutil: some VAAPI infrastructure
On Mon, Jan 18, 2016 at 10:49:51PM +, Mark Thompson wrote: > > --- > configure | 4 + > libavutil/Makefile | 1 + > libavutil/vaapi.c | 497 > + > libavutil/vaapi.h | 123 + > 4 files changed, 625 insertions(+) > create mode 100644 libavutil/vaapi.c > create mode 100644 libavutil/vaapi.h breaks build make distclean ; ./configure && make -j12 ... CC libavutil/time.o CC libavutil/timecode.o CC libavutil/tree.o CC libavutil/twofish.o CC libavutil/utils.o CC libavutil/vaapi.o CC libavutil/x86/cpu.o In file included from libavutil/vaapi.c:23:0: libavutil/vaapi.h:63:5: error: unknown type name ‘VASurfaceAttrib’ libavutil/vaapi.c: In function ‘vaapi_create_surfaces’: libavutil/vaapi.c:59:28: warning: passing argument 5 of ‘vaCreateSurfaces’ makes integer from pointer without a cast [enabled by default] /usr/include/va/va.h:432:10: note: expected ‘int’ but argument is of type ‘VASurfaceID *’ libavutil/vaapi.c:59:28: warning: passing argument 6 of ‘vaCreateSurfaces’ makes pointer from integer without a cast [enabled by default] /usr/include/va/va.h:432:10: note: expected ‘VASurfaceID *’ but argument is of type ‘unsigned int’ libavutil/vaapi.c:59:28: error: too many arguments to function ‘vaCreateSurfaces’ /usr/include/va/va.h:432:10: note: declared here libavutil/vaapi.c: In function ‘ff_vaapi_copy_to_surface’: libavutil/vaapi.c:447:9: error: ‘VA_FOURCC_BGRX’ undeclared (first use in this function) libavutil/vaapi.c:447:9: note: each undeclared identifier is reported only once for each function it appears in make: *** [libavutil/vaapi.o] Error 1 make: *** Waiting for unfinished jobs [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB I am the wisest man alive, for I know one thing, and that is that I know nothing. -- Socrates signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v3 1/5] libavutil: some VAAPI infrastructure
--- configure | 4 + libavutil/Makefile | 1 + libavutil/vaapi.c | 497 + libavutil/vaapi.h | 123 + 4 files changed, 625 insertions(+) create mode 100644 libavutil/vaapi.c create mode 100644 libavutil/vaapi.h diff --git a/configure b/configure index 7cef6f5..1c77015 100755 --- a/configure +++ b/configure @@ -5739,6 +5739,10 @@ enabled vaapi && enabled xlib && check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 && enable vaapi_x11 +enabled vaapi && +check_lib2 "va/va.h va/va_drm.h" vaGetDisplayDRM -lva -lva-drm && +enable vaapi_drm + enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau diff --git a/libavutil/Makefile b/libavutil/Makefile index bf8c713..8025f9f 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -146,6 +146,7 @@ OBJS-$(!HAVE_ATOMICS_NATIVE)+= atomic.o \ OBJS-$(CONFIG_LZO) += lzo.o OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o +OBJS-$(CONFIG_VAAPI)+= vaapi.o OBJS += $(COMPAT_OBJS:%=../compat/%) diff --git a/libavutil/vaapi.c b/libavutil/vaapi.c new file mode 100644 index 000..8a9a524 --- /dev/null +++ b/libavutil/vaapi.c @@ -0,0 +1,497 @@ +/* + * VAAPI helper functions. + * + * Copyright (C) 2016 Mark Thompson+ * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vaapi.h" + +#include "avassert.h" +#include "imgutils.h" +#include "pixfmt.h" + + +void av_vaapi_lock_hardware_context(AVVAAPIHardwareContext *ctx) +{ +if(ctx->lock) +ctx->lock(); +} + +void av_vaapi_unlock_hardware_context(AVVAAPIHardwareContext *ctx) +{ +if(ctx->unlock) +ctx->unlock(); +} + + +static const AVClass vaapi_pipeline_class = { +.class_name = "VAAPI/pipeline", +.item_name = av_default_item_name, +.version= LIBAVUTIL_VERSION_INT, +}; + +static int vaapi_create_surfaces(AVVAAPIPipelineContext *ctx, + AVVAAPISurfaceConfig *config, + AVVAAPISurface *surfaces, + VASurfaceID *ids) +{ +VAStatus vas; +int i; + +vas = vaCreateSurfaces(ctx->hardware_context->display, config->rt_format, + config->width, config->height, ids, config->count, + config->attributes, config->attribute_count); +if(vas != VA_STATUS_SUCCESS) { +av_log(ctx, AV_LOG_ERROR, "Failed to create " + "surfaces: %d (%s).\n", vas, vaErrorStr(vas)); +return AVERROR(EINVAL); +} + +for(i = 0; i < config->count; i++) { +surfaces[i].id = ids[i]; +surfaces[i].refcount = 0; +surfaces[i].hardware_context = ctx->hardware_context; +surfaces[i].config = config; +} + +return 0; +} + +static void vaapi_destroy_surfaces(AVVAAPIPipelineContext *ctx, + AVVAAPISurfaceConfig *config, + AVVAAPISurface *surfaces, + VASurfaceID *ids) +{ +VAStatus vas; +int i; + +for(i = 0; i < config->count; i++) { +av_assert0(surfaces[i].id == ids[i]); +if(surfaces[i].refcount > 0) +av_log(ctx, AV_LOG_WARNING, "Destroying surface %#x which is " + "still in use.\n", surfaces[i].id); +av_assert0(surfaces[i].hardware_context == ctx->hardware_context); +av_assert0(surfaces[i].config == config); +} + +vas = vaDestroySurfaces(ctx->hardware_context->display, +ids, config->count); +if(vas != VA_STATUS_SUCCESS) { +av_log(ctx, AV_LOG_ERROR, "Failed to destroy surfaces: " + "%d (%s).\n", vas, vaErrorStr(vas)); +} +} + +int ff_vaapi_pipeline_init(AVVAAPIPipelineContext *ctx, + AVVAAPIHardwareContext *hw_ctx, + AVVAAPIPipelineConfig *config, + AVVAAPISurfaceConfig *input, + AVVAAPISurfaceConfig *output) +{ +VAStatus vas; +int err; + +//