[FFmpeg-devel] [PATCH v4 1/5] libavutil: VAAPI infrastructure
Mark Thompson
sw at jkqxz.net
Sat Jan 23 20:13:38 CET 2016
---
configure | 5 +
libavutil/Makefile | 1 +
libavutil/vaapi.c | 546 +++++++++++++++++++++++++++++++++++++++++++++++++++++
libavutil/vaapi.h | 115 +++++++++++
4 files changed, 667 insertions(+)
create mode 100644 libavutil/vaapi.c
create mode 100644 libavutil/vaapi.h
diff --git a/configure b/configure
index 8f4642b..cd386b4 100755
--- a/configure
+++ b/configure
@@ -2042,6 +2042,7 @@ CONFIG_EXTRA="
texturedsp
texturedspenc
tpeldsp
+ vaapi_recent
videodsp
vp3dsp
vp56dsp
@@ -5740,6 +5741,10 @@ enabled vaapi &&
check_lib va/va.h vaInitialize -lva ||
disable vaapi
+enabled vaapi &&
+ check_code cc va/va.h "vaCreateSurfaces(0, 0, 0, 0, 0, 0, 0, 0)" &&
+ enable vaapi_recent
+
enabled vaapi && enabled xlib &&
check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 &&
enable vaapi_x11
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 65b2d25..9d6a313 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -148,6 +148,7 @@ OBJS-$(!HAVE_ATOMICS_NATIVE) += atomic.o \
OBJS-$(CONFIG_LZO) += lzo.o
OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o
+OBJS-$(CONFIG_VAAPI_RECENT) += vaapi.o
OBJS += $(COMPAT_OBJS:%=../compat/%)
diff --git a/libavutil/vaapi.c b/libavutil/vaapi.c
new file mode 100644
index 0000000..d5e67c4
--- /dev/null
+++ b/libavutil/vaapi.c
@@ -0,0 +1,546 @@
+/*
+ * VAAPI helper functions.
+ *
+ * Copyright (C) 2016 Mark Thompson <mrt at jkqxz.net>
+ *
+ * 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"
+
+
+AVVAAPIHardwareContext *av_vaapi_alloc_hardware_context(void)
+{
+ return av_mallocz(sizeof(AVVAAPIHardwareContext));
+}
+
+void av_vaapi_lock_hardware_context(AVVAAPIHardwareContext *ctx)
+{
+ if(ctx->lock)
+ ctx->lock(ctx->lock_user_context);
+}
+
+void av_vaapi_unlock_hardware_context(AVVAAPIHardwareContext *ctx)
+{
+ if(ctx->unlock)
+ ctx->unlock(ctx->lock_user_context);
+}
+
+
+typedef struct AVVAAPISurface {
+ VASurfaceID id;
+ AVVAAPIHardwareContext *hardware_context;
+
+ VAImage image;
+ void *mapped_address;
+} AVVAAPISurface;
+
+static AVVAAPISurface *vaapi_get_surface(const AVFrame *frame)
+{
+ av_assert0(frame);
+ av_assert0(frame->buf[0]);
+ av_assert0(frame->buf[0]->data);
+ return (AVVAAPISurface*)frame->buf[0]->data;
+}
+
+static AVVAAPISurfaceConfig *vaapi_get_surface_config(const AVFrame *frame)
+{
+ av_assert0(frame);
+ av_assert0(frame->buf[1]);
+ av_assert0(frame->buf[1]->data);
+ return (AVVAAPISurfaceConfig*)frame->buf[1]->data;
+}
+
+static void vaapi_surface_free(void *opaque, uint8_t *data)
+{
+ AVVAAPISurface *surface = (AVVAAPISurface*)data;
+ AVVAAPIHardwareContext *hw_ctx = surface->hardware_context;
+ VAStatus vas;
+
+ av_vaapi_lock_hardware_context(hw_ctx);
+
+ vas = vaDestroySurfaces(surface->hardware_context->display,
+ &surface->id, 1);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to destroy surface: "
+ "%d (%s).\n", vas, vaErrorStr(vas));
+ }
+
+ av_free(surface);
+
+ av_vaapi_unlock_hardware_context(hw_ctx);
+}
+
+int av_vaapi_surface_pool_init(AVVAAPISurfacePool *pool,
+ AVVAAPIHardwareContext *hw_ctx,
+ AVVAAPISurfaceConfig *config,
+ int frame_count)
+{
+ AVBufferRef *config_buffer;
+ AVVAAPISurface *surface;
+ AVFrame *frame;
+ VAStatus vas;
+ int i, err;
+
+ memset(pool, 0, sizeof(*pool));
+
+ pool->hardware_context = hw_ctx;
+ pool->frame_count = frame_count;
+
+ config_buffer = av_buffer_alloc(sizeof(*config));
+ if(!config_buffer)
+ return AVERROR(ENOMEM);
+ memcpy(config_buffer->data, config, sizeof(*config));
+ config = (AVVAAPISurfaceConfig*)config_buffer->data;
+
+ av_vaapi_lock_hardware_context(hw_ctx);
+
+ for(i = 0; i < frame_count; i++) {
+ frame = av_frame_alloc();
+ if(!frame) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+ surface = av_mallocz(sizeof(*surface));
+ if(!surface) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ surface->hardware_context = hw_ctx;
+
+ vas = vaCreateSurfaces(hw_ctx->display, config->rt_format,
+ config->width, config->height,
+ &surface->id, 1,
+ config->attributes, config->attribute_count);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to create surface: "
+ "%d (%s).\n", vas, vaErrorStr(vas));
+ err = AVERROR_EXTERNAL;
+ goto fail;
+ }
+
+ frame->buf[0] = av_buffer_create((uint8_t*)surface, sizeof(*surface),
+ &vaapi_surface_free,
+ 0, AV_BUFFER_FLAG_READONLY);
+ if(!frame->buf[0]) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ frame->buf[1] = av_buffer_ref(config_buffer);
+ if(!frame->buf[1]) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ frame->data[3] = (uint8_t*)(uintptr_t)surface->id;
+
+ frame->format = AV_PIX_FMT_VAAPI;
+ frame->width = config->width;
+ frame->height = config->height;
+
+ pool->frames[i] = frame;
+ }
+
+ for(; i < FF_ARRAY_ELEMS(pool->frames); i++)
+ pool->frames[i] = 0;
+
+ av_buffer_unref(&config_buffer);
+
+ av_log(0, AV_LOG_DEBUG, "Surface pool initialised: %u surfaces of %ux%u.\n",
+ pool->frame_count, config->width, config->height);
+
+ err = 0;
+ fail:
+ av_vaapi_unlock_hardware_context(hw_ctx);
+ return err;
+}
+
+int av_vaapi_surface_pool_uninit(AVVAAPISurfacePool *pool)
+
+{
+ int i;
+
+ av_vaapi_lock_hardware_context(pool->hardware_context);
+
+ for(i = 0; i < FF_ARRAY_ELEMS(pool->frames); i++) {
+ if(pool->frames[i])
+ av_frame_free(&pool->frames[i]);
+ }
+
+ av_vaapi_unlock_hardware_context(pool->hardware_context);
+
+ return 0;
+}
+
+int av_vaapi_surface_pool_get(AVVAAPISurfacePool *pool, AVFrame *target)
+{
+ AVFrame *frame = 0;
+ int i, err;
+
+ av_vaapi_lock_hardware_context(pool->hardware_context);
+
+ for(i = 0; i < FF_ARRAY_ELEMS(pool->frames); i++) {
+ if(!pool->frames[i])
+ break;
+
+ if(av_buffer_get_ref_count(pool->frames[i]->buf[0]) == 1) {
+ frame = pool->frames[i];
+ break;
+ }
+ }
+
+ if(frame) {
+ err = av_frame_ref(target, frame);
+ } else {
+ err = AVERROR(ENOMEM);
+ }
+
+ av_vaapi_unlock_hardware_context(pool->hardware_context);
+
+ return err;
+}
+
+int av_vaapi_map_frame(AVFrame *frame, int get)
+{
+ AVVAAPISurface *surface = vaapi_get_surface(frame);
+ AVVAAPISurfaceConfig *config = vaapi_get_surface_config(frame);
+ AVVAAPIHardwareContext *hw_ctx = surface->hardware_context;
+ VAImage *image = &surface->image;
+ VAStatus vas;
+ int i, err;
+ void *address;
+ // On current Intel drivers, derive gives you memory which is very slow
+ // to read (uncached?). It can be better for write-only cases, but for
+ // now play it safe and never use derive.
+ int derive = 0;
+
+ if(surface->mapped_address) {
+ av_log(0, AV_LOG_ERROR, "Surface %#x already mapped.\n",
+ surface->id);
+ // This could refcount somehow to allow multiple mappings?
+ return AVERROR(EINVAL);
+ }
+
+ av_vaapi_lock_hardware_context(hw_ctx);
+
+ vas = vaSyncSurface(hw_ctx->display, surface->id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to sync surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ err = AVERROR_EXTERNAL;
+ goto fail;
+ }
+
+ if(derive) {
+ vas = vaDeriveImage(hw_ctx->display,
+ surface->id, image);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to derive image from surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ derive = 0;
+ }
+ }
+ if(!derive) {
+ vas = vaCreateImage(hw_ctx->display, &config->image_format,
+ config->width, config->height, image);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to create image for surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ err = AVERROR_EXTERNAL;
+ goto fail;
+ }
+
+ if(get) {
+ vas = vaGetImage(hw_ctx->display, surface->id, 0, 0,
+ config->width, config->height, image->image_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to get image for surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ err = AVERROR_EXTERNAL;
+ goto fail_image;
+ }
+ }
+ }
+
+ av_assert0(image->format.fourcc == config->image_format.fourcc);
+
+ vas = vaMapBuffer(hw_ctx->display, image->buf, &address);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to map image from surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ err = AVERROR_EXTERNAL;
+ goto fail_image;
+ }
+
+ surface->mapped_address = address;
+
+ for(i = 0; i < image->num_planes; i++) {
+ frame->data[i] = (uint8_t*)address + image->offsets[i];
+ frame->linesize[i] = image->pitches[i];
+ }
+
+ av_vaapi_unlock_hardware_context(hw_ctx);
+ return 0;
+
+ fail_image:
+ vas = vaDestroyImage(hw_ctx->display, surface->image.image_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to destroy image for surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ }
+ fail:
+ av_vaapi_unlock_hardware_context(hw_ctx);
+ return err;
+}
+
+int av_vaapi_unmap_frame(AVFrame *frame, int put)
+{
+ AVVAAPISurface *surface = vaapi_get_surface(frame);
+ AVVAAPISurfaceConfig *config = vaapi_get_surface_config(frame);
+ AVVAAPIHardwareContext *hw_ctx = surface->hardware_context;
+ VAImage *image = &surface->image;
+ VAStatus vas;
+ int i;
+ int derive = 0;
+
+ surface->mapped_address = 0;
+
+ for(i = 0; i < image->num_planes; i++) {
+ frame->data[i] = 0;
+ frame->linesize[i] = 0;
+ }
+
+ vas = vaUnmapBuffer(hw_ctx->display, image->buf);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to unmap image from surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ }
+
+ if(!derive && put) {
+ vas = vaPutImage(hw_ctx->display, surface->id, image->image_id,
+ 0, 0, config->width, config->height,
+ 0, 0, config->width, config->height);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to put image for surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ }
+ }
+
+ vas = vaDestroyImage(hw_ctx->display,
+ surface->image.image_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(0, AV_LOG_ERROR, "Failed to destroy image for surface "
+ "%#x: %d (%s).\n", surface->id, vas, vaErrorStr(vas));
+ }
+
+ return 0;
+}
+
+static enum AVPixelFormat vaapi_pix_fmt(unsigned int fourcc)
+{
+ switch(fourcc) {
+ case VA_FOURCC_NV12: return AV_PIX_FMT_NV12;
+ case VA_FOURCC_IYUV: return AV_PIX_FMT_YUV420P;
+ case VA_FOURCC_YV12: return AV_PIX_FMT_YUV420P; // U/V planes swapped.
+ case VA_FOURCC_BGRA: return AV_PIX_FMT_BGRA;
+ case VA_FOURCC_BGRX: return AV_PIX_FMT_BGR0;
+ case VA_FOURCC_RGBA: return AV_PIX_FMT_RGBA;
+ case VA_FOURCC_RGBX: return AV_PIX_FMT_RGB0;
+ default:
+ return AV_PIX_FMT_NONE;
+ }
+}
+
+static AVFrame *vaapi_make_proxy_frame(const AVFrame *src)
+{
+ AVVAAPISurface *surface = vaapi_get_surface(src);
+ VAImage *image = &surface->image;
+ AVFrame *dst;
+ int i;
+
+ if(!surface->mapped_address) {
+ av_log(0, AV_LOG_ERROR, "Surface %#x is not mapped.",
+ surface->id);
+ return 0;
+ }
+
+ dst = av_frame_alloc();
+ if(!dst)
+ return 0;
+
+ for(i = 0; i < image->num_planes; i++) {
+ dst->data[i] = src->data[i];
+ dst->linesize[i] = src->linesize[i];
+ }
+
+ dst->width = src->width;
+ dst->height = src->height;
+
+ dst->format = vaapi_pix_fmt(image->format.fourcc);
+ if(image->format.fourcc == VA_FOURCC_YV12) {
+ uint8_t *tmp;
+ tmp = dst->data[1];
+ dst->data[1] = dst->data[2];
+ dst->data[2] = tmp;
+ }
+
+ av_frame_copy_props(dst, src);
+
+ return dst;
+}
+
+int av_vaapi_copy_to_surface(AVFrame *dst, const AVFrame *src)
+{
+ AVFrame *proxy;
+ int err;
+
+ if(dst->format != AV_PIX_FMT_VAAPI)
+ return AVERROR(EINVAL);
+
+ err = av_vaapi_map_frame(dst, 0);
+ if(err)
+ return err;
+
+ proxy = vaapi_make_proxy_frame(dst);
+ if(proxy)
+ err = av_frame_copy(proxy, src);
+ else
+ err = AVERROR(ENOMEM);
+
+ av_vaapi_unmap_frame(dst, 1);
+
+ return 0;
+}
+
+int av_vaapi_copy_from_surface(AVFrame *dst, AVFrame *src)
+{
+ AVFrame *proxy;
+ int err;
+
+ if(src->format != AV_PIX_FMT_VAAPI)
+ return AVERROR(EINVAL);
+
+ err = av_vaapi_map_frame(src, 1);
+ if(err)
+ return err;
+
+ proxy = vaapi_make_proxy_frame(src);
+ if(proxy)
+ err = av_frame_copy(dst, proxy);
+ else
+ err = AVERROR(ENOMEM);
+
+ av_vaapi_unmap_frame(src, 0);
+
+ return err;
+}
+
+static const AVClass vaapi_pipeline_class = {
+ .class_name = "VAAPI/pipeline",
+ .item_name = av_default_item_name,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+int av_vaapi_pipeline_init(AVVAAPIPipelineContext *ctx,
+ AVVAAPIHardwareContext *hw_ctx,
+ AVVAAPIPipelineConfig *config,
+ AVVAAPISurfacePool *pool)
+{
+ VASurfaceID output_surface_ids[AV_VAAPI_MAX_SURFACES];
+ int output_surface_count;
+ VAStatus vas;
+ int i, err;
+
+ av_vaapi_lock_hardware_context(hw_ctx);
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->class = &vaapi_pipeline_class;
+
+ ctx->hardware_context = hw_ctx;
+
+ if(pool) {
+ output_surface_count = pool->frame_count;
+ for(i = 0; i < output_surface_count; i++)
+ output_surface_ids[i] = vaapi_get_surface(pool->frames[i])->id;
+ } else {
+ // An output surface pool need not be supplied if the pipeline
+ // produces no image output (an intra-only codec like JPEG, say).
+
+ output_surface_count = 0;
+ }
+
+ vas = vaCreateConfig(hw_ctx->display, config->profile,
+ config->entrypoint, config->attributes,
+ config->attribute_count, &ctx->config_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to create pipeline configuration: "
+ "%d (%s).\n", vas, vaErrorStr(vas));
+ err = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ vas = vaCreateContext(hw_ctx->display, ctx->config_id,
+ config->width, config->height,
+ VA_PROGRESSIVE,
+ output_surface_ids, output_surface_count,
+ &ctx->context_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to create pipeline context: "
+ "%d (%s).\n", vas, vaErrorStr(vas));
+ err = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ av_log(ctx, AV_LOG_DEBUG, "VAAPI pipeline initialised: config %#x "
+ "context %#x.\n", ctx->config_id, ctx->context_id);
+
+ err = 0;
+ fail:
+ av_vaapi_unlock_hardware_context(hw_ctx);
+ return err;
+}
+
+int av_vaapi_pipeline_uninit(AVVAAPIPipelineContext *ctx)
+{
+ VAStatus vas;
+
+ av_vaapi_lock_hardware_context(ctx->hardware_context);
+
+ av_assert0(ctx->hardware_context);
+
+ vas = vaDestroyContext(ctx->hardware_context->display, ctx->context_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to destroy pipeline context: "
+ "%d (%s).\n", vas, vaErrorStr(vas));
+ }
+
+ vaDestroyConfig(ctx->hardware_context->display, ctx->config_id);
+ if(vas != VA_STATUS_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to destroy pipeline configuration: "
+ "%d (%s).\n", vas, vaErrorStr(vas));
+ }
+
+ av_vaapi_unlock_hardware_context(ctx->hardware_context);
+
+ return 0;
+}
diff --git a/libavutil/vaapi.h b/libavutil/vaapi.h
new file mode 100644
index 0000000..53c4c7c
--- /dev/null
+++ b/libavutil/vaapi.h
@@ -0,0 +1,115 @@
+/*
+ * VAAPI helper functions.
+ *
+ * Copyright (C) 2016 Mark Thompson <mrt at jkqxz.net>
+ *
+ * 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
+ */
+
+#ifndef LIBAVUTIL_VAAPI_H_
+#define LIBAVUTIL_VAAPI_H_
+
+#include <va/va.h>
+
+#include "pixfmt.h"
+#include "frame.h"
+
+
+typedef struct AVVAAPIHardwareContext {
+ VADisplay display;
+
+ VAConfigID decoder_pipeline_config_id;
+ VAContextID decoder_pipeline_context_id;
+
+ void (*lock)(void *user_context);
+ void (*unlock)(void *user_context);
+ void *lock_user_context;
+} AVVAAPIHardwareContext;
+
+AVVAAPIHardwareContext *av_vaapi_alloc_hardware_context(void);
+
+void av_vaapi_lock_hardware_context(AVVAAPIHardwareContext *ctx);
+void av_vaapi_unlock_hardware_context(AVVAAPIHardwareContext *ctx);
+
+
+#define AV_VAAPI_MAX_SURFACES 64
+
+typedef struct AVVAAPISurfaceConfig {
+ enum AVPixelFormat av_format;
+ unsigned int rt_format;
+ VAImageFormat image_format;
+
+ unsigned int width;
+ unsigned int height;
+
+ unsigned int attribute_count;
+ VASurfaceAttrib *attributes;
+} AVVAAPISurfaceConfig;
+
+typedef struct AVVAAPISurfacePool {
+ AVVAAPIHardwareContext *hardware_context;
+
+ int frame_count;
+ AVFrame *frames[AV_VAAPI_MAX_SURFACES];
+} AVVAAPISurfacePool;
+
+int av_vaapi_surface_pool_init(AVVAAPISurfacePool *pool,
+ AVVAAPIHardwareContext *hw_ctx,
+ AVVAAPISurfaceConfig *config,
+ int frame_count);
+
+int av_vaapi_surface_pool_uninit(AVVAAPISurfacePool *pool);
+
+int av_vaapi_surface_pool_get(AVVAAPISurfacePool *pool, AVFrame *target);
+
+
+typedef struct AVVAAPIPipelineConfig {
+ VAProfile profile;
+ VAEntrypoint entrypoint;
+
+ unsigned int width;
+ unsigned int height;
+
+ unsigned int attribute_count;
+ VAConfigAttrib *attributes;
+} AVVAAPIPipelineConfig;
+
+typedef struct AVVAAPIPipelineContext {
+ const AVClass *class;
+
+ AVVAAPIHardwareContext *hardware_context;
+
+ VAConfigID config_id;
+ VAContextID context_id;
+} AVVAAPIPipelineContext;
+
+int av_vaapi_pipeline_init(AVVAAPIPipelineContext *ctx,
+ AVVAAPIHardwareContext *hw_ctx,
+ AVVAAPIPipelineConfig *config,
+ AVVAAPISurfacePool *pool);
+
+int av_vaapi_pipeline_uninit(AVVAAPIPipelineContext *ctx);
+
+
+int av_vaapi_map_frame(AVFrame *frame, int get);
+int av_vaapi_unmap_frame(AVFrame *frame, int put);
+
+int av_vaapi_copy_to_surface(AVFrame *dst, const AVFrame *src);
+int av_vaapi_copy_from_surface(AVFrame *dst, AVFrame *src);
+
+
+#endif /* LIBAVUTIL_VAAPI_H_ */
--
2.6.4
More information about the ffmpeg-devel
mailing list