---
 Changelog       |    2 +-
 Makefile        |    4 +-
 avconv.h        |    2 +
 avconv_opt.c    |    3 +
 avconv_vaapi.c  |  596 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 configure       |   13 ++
 doc/avconv.texi |   13 ++
 7 files changed, 631 insertions(+), 2 deletions(-)
 create mode 100644 avconv_vaapi.c

diff --git a/Changelog b/Changelog
index 15e5ac9..af67ce5 100644
--- a/Changelog
+++ b/Changelog
@@ -48,7 +48,7 @@ version 10:
 - setsar/setdar filters now support variables in ratio expressions
 - dar variable in the scale filter now returns the actual DAR (i.e. a * sar)
 - VP9 decoder
-- support for decoding through VDPAU in avconv (the -hwaccel option)
+- support for decoding through VDPAU and VAAPI in avconv (the -hwaccel option)
 
 
 version 9:
diff --git a/Makefile b/Makefile
index 184aa37..b249cda 100644
--- a/Makefile
+++ b/Makefile
@@ -64,6 +64,8 @@ PROGS-$(CONFIG_AVSERVER) += avserver
 PROGS      := $(PROGS-yes:%=%$(EXESUF))
 
 OBJS-avconv = avconv_opt.o avconv_filter.o
+OBJS-avconv-$(HAVE_VAAPI_DRM) += avconv_vaapi.o
+OBJS-avconv-$(HAVE_VAAPI_X11) += avconv_vaapi.o
 OBJS-avconv-$(HAVE_VDPAU_X11) += avconv_vdpau.o
 
 TESTTOOLS   = audiogen videogen rotozoom tiny_psnr base64
@@ -129,7 +131,7 @@ endef
 $(foreach D,$(FFLIBS),$(eval $(call DOSUBDIR,lib$(D))))
 
 define DOPROG
-OBJS-$(1) += $(1).o cmdutils.o $(EXEOBJS) $(OBJS-$(1)-yes)
+OBJS-$(1) += $(1).o cmdutils.o $(EXEOBJS) $$(sort $$(OBJS-$(1)-yes))
 $(1)$(EXESUF): $$(OBJS-$(1))
 $$(OBJS-$(1)): CFLAGS  += $(CFLAGS-$(1))
 $(1)$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
diff --git a/avconv.h b/avconv.h
index c270401..1fd9f73 100644
--- a/avconv.h
+++ b/avconv.h
@@ -52,6 +52,7 @@ enum HWAccelID {
     HWACCEL_NONE = 0,
     HWACCEL_AUTO,
     HWACCEL_VDPAU,
+    HWACCEL_VAAPI,
 };
 
 typedef struct HWAccel {
@@ -404,5 +405,6 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, 
OutputStream *ost);
 int avconv_parse_options(int argc, char **argv);
 
 int vdpau_init(AVCodecContext *s);
+int vaapi_init(AVCodecContext *s);
 
 #endif /* AVCONV_H */
diff --git a/avconv_opt.c b/avconv_opt.c
index da8c6e7..c4cee74 100644
--- a/avconv_opt.c
+++ b/avconv_opt.c
@@ -57,6 +57,9 @@ const HWAccel hwaccels[] = {
 #if HAVE_VDPAU_X11
     { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU },
 #endif
+#if HAVE_VAAPI_DRM || HAVE_VAAPI_X11
+    { "vaapi", vaapi_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI_VLD },
+#endif
     { 0 },
 };
 
diff --git a/avconv_vaapi.c b/avconv_vaapi.c
new file mode 100644
index 0000000..c6574e2
--- /dev/null
+++ b/avconv_vaapi.c
@@ -0,0 +1,596 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include <va/va.h>
+
+#if HAVE_VAAPI_DRM
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <sys/stat.h>
+#include <va/va_drm.h>
+#endif
+
+#if HAVE_VAAPI_X11
+#include <X11/Xlib.h>
+#include <va/va_x11.h>
+#endif
+
+#include "libavcodec/avcodec.h"
+#include "libavcodec/vaapi.h"
+
+#include "libavutil/avassert.h"
+#include "libavutil/buffer.h"
+#include "libavutil/frame.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/mem.h"
+
+#include "avconv.h"
+
+/* Stuff associated with one VAAPI config/decoder. It is refcounted, one ref is
+ * held by each used frame + one by the VAAPIContext as long as this config is
+ * being used for decoding */
+typedef struct VAAPIConfig {
+    AVBufferRef *ctx_buf;
+    struct VAAPIContext *ctx;
+
+    VAConfigID  config_id;
+    VAContextID context_id;
+
+    VASurfaceID *surfaces;
+    uint8_t *surface_used;
+    int nb_surfaces;
+} VAAPIConfig;
+
+/* Global stuff associated with a VAAPI display device + some temp variables. 
It
+ * is refcounted, one reference is held by each config, one by each VAAPIImage 
+
+ * one by itself (released on uninit). */
+typedef struct VAAPIContext {
+    AVBufferRef *self;
+#if HAVE_VAAPI_DRM
+    int drm_fd;
+#endif
+#if HAVE_VAAPI_X11
+    Display *dpy;
+#endif
+
+    VADisplay display;
+
+    VAAPIConfig *cur_config;
+    AVBufferRef *cur_config_buf;
+
+    VAImageFormat      img_fmt;
+    enum AVPixelFormat pix_fmt;
+    AVFrame *tmp_frame;
+} VAAPIContext;
+
+/* A wrapper around a VAAPI surface */
+typedef struct VAAPIFrame {
+    VADisplay display;
+    AVBufferRef *config;
+    uint8_t *used;
+} VAAPIFrame;
+
+/* A wrapper around a VAImage for retrieving the data */
+typedef struct VAAPIImage {
+    VAAPIContext *ctx;
+    AVBufferRef  *ctx_buf;
+
+    VAImage image;
+} VAAPIImage;
+
+static const int vaapi_formats[][2] = {
+    { VA_FOURCC_YV12, AV_PIX_FMT_YUV420P },
+    { VA_FOURCC_NV12, AV_PIX_FMT_NV12    },
+};
+
+static void vaapi_free_image(void *opaque, uint8_t *data)
+{
+    VAAPIImage *img = opaque;
+
+    if (img->image.buf != VA_INVALID_ID)
+        vaUnmapBuffer(img->ctx->display, img->image.buf);
+    if (img->image.image_id != VA_INVALID_ID)
+        vaDestroyImage(img->ctx->display, img->image.image_id);
+    av_buffer_unref(&img->ctx_buf);
+    av_freep(&img);
+}
+
+static int vaapi_retrieve_data(AVCodecContext *s, AVFrame *frame)
+{
+    VASurfaceID surface = (VASurfaceID)(uintptr_t)frame->data[3];
+    InputStream    *ist = s->opaque;
+    VAAPIContext   *ctx = ist->hwaccel_ctx;
+    VAAPIImage *img;
+    VAStatus err;
+    uint8_t *data;
+    int i, ret;
+
+    img = av_mallocz(sizeof(*img));
+    if (!img)
+        return AVERROR(ENOMEM);
+
+    img->image.buf      = VA_INVALID_ID;
+    img->image.image_id = VA_INVALID_ID;
+
+    img->ctx_buf = av_buffer_ref(ctx->self);
+    if (!img->ctx_buf) {
+        av_freep(&img);
+        return AVERROR(ENOMEM);
+    }
+    img->ctx = ctx;
+
+    err = vaCreateImage(ctx->display, &ctx->img_fmt,
+                        frame->width, frame->height, &img->image);
+    if (err != VA_STATUS_SUCCESS) {
+        vaapi_free_image(img, NULL);
+        av_log(NULL, AV_LOG_ERROR, "Error creating an image: %s\n",
+               vaErrorStr(err));
+        return AVERROR_UNKNOWN;
+    }
+
+    /* We do not use vaDeriveImage, because even when it is implemented, the
+     * access to the image data is usually very slow */
+    err = vaGetImage(ctx->display, surface, 0, 0, frame->width, frame->height,
+                     img->image.image_id);
+    if (err != VA_STATUS_SUCCESS) {
+        vaapi_free_image(img, NULL);
+        av_log(NULL, AV_LOG_ERROR, "Error getting an image: %s\n",
+               vaErrorStr(err));
+        return AVERROR_UNKNOWN;
+    }
+
+    err = vaMapBuffer(ctx->display, img->image.buf, (void**)&data);
+    if (err != VA_STATUS_SUCCESS) {
+        vaapi_free_image(img, NULL);
+        av_log(NULL, AV_LOG_ERROR, "Error mapping the image buffer: %s\n",
+               vaErrorStr(err));
+        return AVERROR_UNKNOWN;
+    }
+
+    ctx->tmp_frame->buf[0] = av_buffer_create(data, img->image.data_size,
+                                              vaapi_free_image, img, 0);
+    if (!ctx->tmp_frame->buf[0]) {
+        vaapi_free_image(img, NULL);
+        return AVERROR(ENOMEM);
+    }
+
+    for (i = 0; i < img->image.num_planes; i++) {
+        ctx->tmp_frame->data[i]     = data + img->image.offsets[i];
+        ctx->tmp_frame->linesize[i] = img->image.pitches[i];
+    }
+    ctx->tmp_frame->format = ctx->pix_fmt;
+    ctx->tmp_frame->width  = frame->width;
+    ctx->tmp_frame->height = frame->height;
+
+    ret = av_frame_copy_props(ctx->tmp_frame, frame);
+    if (ret < 0) {
+        av_frame_unref(ctx->tmp_frame);
+        return ret;
+    }
+
+    av_frame_unref(frame);
+    av_frame_move_ref(frame, ctx->tmp_frame);
+
+    return 0;
+
+    if (frame->format == AV_PIX_FMT_YUV420P)
+        FFSWAP(uint8_t*, frame->data[1], frame->data[2]);
+
+    return ret;
+}
+
+static void vaapi_release_buffer(void *opaque, uint8_t *data)
+{
+    VAAPIFrame *priv = opaque;
+
+    *priv->used = 0;
+    av_buffer_unref(&priv->config);
+    av_freep(&priv);
+}
+
+static int vaapi_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
+{
+    InputStream     *ist = s->opaque;
+    VAAPIContext    *ctx = ist->hwaccel_ctx;
+    VAAPIConfig  *config = ctx->cur_config;
+    VAAPIFrame     *priv = NULL;
+    int i;
+
+    av_assert0(frame->format == AV_PIX_FMT_VAAPI_VLD);
+
+    for (i = 0; i < config->nb_surfaces; i++)
+        if (!config->surface_used[i])
+            break;
+    if (i == config->nb_surfaces) {
+        av_log(NULL, AV_LOG_ERROR, "No free surfaces left.\n");
+        return AVERROR(ENOMEM);
+    }
+
+    priv = av_mallocz(sizeof(*priv));
+    if (!priv)
+        return AVERROR(ENOMEM);
+
+    priv->used           = &config->surface_used[i];
+    priv->display        = ctx->display;
+    priv->config         = av_buffer_ref(ctx->cur_config_buf);
+    if (!priv->config)
+        goto fail;
+
+    frame->buf[0] = av_buffer_create((uint8_t*)&config->surfaces[i],
+                                     sizeof(*config->surfaces),
+                                     vaapi_release_buffer, priv,
+                                     AV_BUFFER_FLAG_READONLY);
+    if (!frame->buf[0])
+        return AVERROR(ENOMEM);
+
+    frame->opaque  = priv;
+    frame->data[3] = (uint8_t*)(uintptr_t)config->surfaces[i];
+    config->surface_used[i] = 1;
+
+    return 0;
+fail:
+    if (priv)
+        av_buffer_unref(&priv->config);
+    av_freep(&priv);
+    return AVERROR(ENOMEM);
+}
+
+static void vaapi_free_config(void *opaque, uint8_t *data)
+{
+    VAAPIConfig *config = opaque;
+
+    vaDestroySurfaces(config->ctx->display, config->surfaces, 
config->nb_surfaces);
+    av_freep(&config->surfaces);
+    av_freep(&config->surface_used);
+
+    if (config->context_id != VA_INVALID_ID)
+        vaDestroyContext(config->ctx->display, config->context_id);
+
+    if (config->config_id != VA_INVALID_ID)
+        vaDestroyConfig(config->ctx->display, config->config_id);
+
+    av_buffer_unref(&config->ctx_buf);
+    av_freep(&config);
+}
+
+static int vaapi_create_config(AVCodecContext *s)
+{
+    InputStream  *ist = s->opaque;
+    VAAPIContext *ctx = ist->hwaccel_ctx;
+    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : 
AV_LOG_ERROR;
+    VAAPIConfig *config;
+    VAProfile profile;
+    VAStatus err;
+    int ret;
+
+    ret = av_vaapi_get_profile(s, &profile);
+    if (ret < 0) {
+        av_log(NULL, loglevel, "No known VAAPI decoder profile for input "
+               "stream #%d:%d.\n", ist->file_index, ist->st->index);
+        return AVERROR(EINVAL);
+    }
+
+    /* setup a refcounted buffer for the current config */
+    config = av_mallocz(sizeof(*config));
+    if (!config)
+        return AVERROR(ENOMEM);
+    ctx->cur_config_buf = av_buffer_create((uint8_t*)config,
+                                           sizeof(*config),
+                                           vaapi_free_config, config,
+                                           AV_BUFFER_FLAG_READONLY);
+    if (!ctx->cur_config_buf) {
+        av_freep(&config);
+        return AVERROR(ENOMEM);
+    }
+
+    config->ctx_buf    = av_buffer_ref(ctx->self);
+    if (!config->ctx_buf)
+        goto fail;
+    config->ctx        = ctx;
+    config->config_id  = VA_INVALID_ID;
+    config->context_id = VA_INVALID_ID;
+
+    /* create the surfaces */
+    config->nb_surfaces = 16;
+    if (s->active_thread_type == FF_THREAD_FRAME)
+        config->nb_surfaces += s->thread_count;
+    config->surfaces     = av_malloc_array (config->nb_surfaces, 
sizeof(*config->surfaces));
+    config->surface_used = av_mallocz_array(config->nb_surfaces, 
sizeof(*config->surface_used));
+    if (!config->surfaces || !config->surface_used) {
+        av_freep(&config->surfaces);
+        av_freep(&config->surface_used);
+        goto fail;
+    }
+
+    err = vaCreateSurfaces(ctx->display, VA_RT_FORMAT_YUV420,
+                           s->coded_width, s->coded_height,
+                           config->surfaces, config->nb_surfaces, NULL, 0);
+    if (err != VA_STATUS_SUCCESS) {
+        config->surfaces[0] = VA_INVALID_ID;
+        av_log(NULL, loglevel, "Error creating surfaces: %s\n",
+               vaErrorStr(err));
+        goto fail;
+    }
+
+    /* create the decoder configuration */
+    err = vaCreateConfig(ctx->display, profile, VAEntrypointVLD,
+                         NULL, 0, &config->config_id);
+    if (err != VA_STATUS_SUCCESS) {
+        av_log(NULL, loglevel, "Error creating configuration: %s\n",
+               vaErrorStr(err));
+        goto fail;
+    }
+
+    /* create the decoder context */
+    err = vaCreateContext(ctx->display, config->config_id,
+                          s->coded_width, s->coded_height, 0,
+                          config->surfaces, config->nb_surfaces,
+                          &config->context_id);
+    if (err != VA_STATUS_SUCCESS) {
+        av_log(NULL, loglevel, "Error creating the decoding context: %s\n",
+               vaErrorStr(err));
+        goto fail;
+    }
+
+    ctx->cur_config = config;
+
+    return 0;
+fail:
+    av_buffer_unref(&ctx->cur_config_buf);
+    return AVERROR_UNKNOWN;
+}
+
+static void vaapi_uninit(AVCodecContext *s)
+{
+    InputStream  *ist = s->opaque;
+    VAAPIContext *ctx = ist->hwaccel_ctx;
+
+    av_buffer_unref(&ctx->cur_config_buf);
+    ctx->cur_config = NULL;
+
+    av_freep(&s->hwaccel_context);
+    ist->hwaccel_ctx = NULL;
+
+    av_buffer_unref(&ctx->self);
+}
+
+static int pick_format(InputStream *ist, VAAPIContext *ctx)
+{
+    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : 
AV_LOG_ERROR;
+    VAImageFormat *formats = NULL;
+    VAStatus err;
+    int nb_formats, i, j;
+
+    nb_formats = vaMaxNumImageFormats(ctx->display);
+    if (!nb_formats) {
+        av_log(NULL, loglevel, "No image formats supported.\n");
+        return AVERROR(EINVAL);
+    }
+
+    formats = av_mallocz_array(nb_formats, sizeof(*formats));
+    if (!formats)
+        return AVERROR(ENOMEM);
+
+    err = vaQueryImageFormats(ctx->display, formats, &nb_formats);
+    if (err != VA_STATUS_SUCCESS) {
+        av_log(NULL, loglevel, "Error querying image formats: %s\n",
+               vaErrorStr(err));
+        goto fail;
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(vaapi_formats); i++)
+        for (j = 0; j < nb_formats; j++)
+            if (vaapi_formats[i][0] == formats[j].fourcc) {
+                ctx->img_fmt = formats[j];
+                ctx->pix_fmt = vaapi_formats[i][1];
+                av_freep(&formats);
+                return 0;
+            }
+
+fail:
+    av_freep(&formats);
+    return AVERROR(EINVAL);
+}
+
+#if HAVE_VAAPI_DRM
+static void vaapi_open_drm(InputStream *ist, VAAPIContext *ctx)
+{
+    if (!ist->hwaccel_device)
+        return;
+
+    ctx->drm_fd = drmOpen(ist->hwaccel_device, NULL);
+    if (ctx->drm_fd == -1)
+        ctx->drm_fd = open(ist->hwaccel_device, O_RDONLY);
+
+    if (ctx->drm_fd == -1) {
+        av_log(NULL, AV_LOG_VERBOSE, "Cannot open DRM device %s: %s.\n",
+               ist->hwaccel_device, strerror(errno));
+        return;
+    }
+
+    ctx->display = vaGetDisplayDRM(ctx->drm_fd);
+    if (!ctx->display) {
+        av_log(NULL, AV_LOG_VERBOSE, "Error getting a DRM VAAPI display.\n");
+        drmClose(ctx->drm_fd);
+        return;
+    }
+
+    av_log(NULL, AV_LOG_VERBOSE, "Successfully opened a VAAPI display on DRM "
+           "device %s.\n", ist->hwaccel_device);
+}
+#endif
+
+#if HAVE_VAAPI_X11
+static void vaapi_open_x11(InputStream *ist, VAAPIContext *ctx)
+{
+    const char *display;
+
+    ctx->dpy = XOpenDisplay(ist->hwaccel_device);
+    if (!ctx->dpy) {
+        av_log(NULL, AV_LOG_VERBOSE, "Cannot open the X11 display %s.\n",
+               XDisplayName(ist->hwaccel_device));
+        return;
+    }
+    display = XDisplayString(ctx->dpy);
+
+    ctx->display = vaGetDisplay(ctx->dpy);
+    if (!ctx->display) {
+        av_log(NULL, AV_LOG_VERBOSE, "Error getting an X11 VAAPI display.\n");
+        XCloseDisplay(ctx->dpy);
+        return;
+    }
+
+    av_log(NULL, AV_LOG_VERBOSE, "Successfully opened a VAAPI display on X11 "
+           "display %s.\n", display);
+}
+#endif
+
+static void vaapi_free_context(void *opaque, uint8_t *data)
+{
+    VAAPIContext *ctx = opaque;
+
+#if HAVE_VAAPI_DRM
+    close(ctx->drm_fd);
+#endif
+
+#if HAVE_VAAPI_X11
+    if (ctx->dpy)
+        XCloseDisplay(ctx->dpy);
+#endif
+
+    if (ctx->display)
+        vaTerminate(ctx->display);
+
+
+    av_frame_free(&ctx->tmp_frame);
+    av_freep(&ctx);
+}
+
+static int vaapi_create_context(AVCodecContext *s)
+{
+    InputStream  *ist = s->opaque;
+    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : 
AV_LOG_ERROR;
+    AVVAAPIContext *vaapi_ctx;
+    VAAPIContext *ctx;
+    VAStatus err;
+    int ret, ver_minor, ver_major;
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return AVERROR(ENOMEM);
+
+    ctx->self = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
+                                 vaapi_free_context, ctx,
+                                 AV_BUFFER_FLAG_READONLY);
+    if (!ctx->self) {
+        av_freep(&ctx);
+        return AVERROR(ENOMEM);
+    }
+
+    ctx->tmp_frame = av_frame_alloc();
+    if (!ctx->tmp_frame)
+        goto fail;
+
+#if HAVE_VAAPI_DRM
+    vaapi_open_drm(ist, ctx);
+#endif
+#if HAVE_VAAPI_X11
+    if (!ctx->display)
+        vaapi_open_x11(ist, ctx);
+#endif
+
+    if (!ctx->display) {
+        av_log(NULL, loglevel, "Could not open a VAAPI display.\n");
+        goto fail;
+    }
+
+    err = vaInitialize(ctx->display, &ver_major, &ver_minor);
+    if (err != VA_STATUS_SUCCESS) {
+        av_log(NULL, loglevel, "Error initializing VAAPI: %s\n",
+               vaErrorStr(err));
+        goto fail;
+    }
+
+    ret = pick_format(ist, ctx);
+    if (ret < 0) {
+        av_log(NULL, loglevel, "No supported image format found.\n");
+        goto fail;
+    }
+
+    vaapi_ctx = av_vaapi_alloc_context();
+    if (!vaapi_ctx)
+        goto fail;
+    vaapi_ctx->display = ctx->display;
+
+    s->hwaccel_context = vaapi_ctx;
+
+    ist->hwaccel_ctx           = ctx;
+    ist->hwaccel_uninit        = vaapi_uninit;
+
+    av_log(NULL, AV_LOG_VERBOSE, "Using VAAPI version %d.%d -- %s -- "
+           "to decode input stream #%d:%d.\n", ver_major, ver_minor,
+           vaQueryVendorString(ctx->display), ist->file_index, ist->st->index);
+
+    return 0;
+
+fail:
+    av_log(NULL, loglevel, "VAAPI init failed for stream #%d:%d.\n",
+           ist->file_index, ist->st->index);
+    vaapi_uninit(s);
+    return AVERROR(EINVAL);
+}
+
+int vaapi_init(AVCodecContext *s)
+{
+    InputStream *ist = s->opaque;
+    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : 
AV_LOG_ERROR;
+    AVVAAPIContext *vaapi_ctx;
+    VAAPIContext *ctx;
+    int ret;
+
+    if (!ist->hwaccel_ctx) {
+        ret = vaapi_create_context(s);
+        if (ret < 0)
+            return ret;
+    }
+    ctx       = ist->hwaccel_ctx;
+    vaapi_ctx = s->hwaccel_context;
+
+    av_buffer_unref(&ctx->cur_config_buf);
+    ctx->cur_config = NULL;
+
+    ret = vaapi_create_config(s);
+    if (ret < 0) {
+        av_log(NULL, loglevel, "Error initializing a VAAPI configuration.\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    vaapi_ctx->config_id  = ctx->cur_config->config_id;
+    vaapi_ctx->context_id = ctx->cur_config->context_id;
+
+    ist->hwaccel_get_buffer    = vaapi_get_buffer;
+    ist->hwaccel_retrieve_data = vaapi_retrieve_data;
+
+    return 0;
+}
diff --git a/configure b/configure
index b23d5e7..c5b6761 100755
--- a/configure
+++ b/configure
@@ -1367,6 +1367,8 @@ HAVE_LIST="
     threads
     unistd_h
     usleep
+    vaapi_drm
+    vaapi_x11
     vdpau_x11
     vfp_args
     VirtualAlloc
@@ -3915,6 +3917,15 @@ require Xext X11/extensions/XShm.h XShmCreateImage 
-lXext &&
 require Xfixes X11/extensions/Xfixes.h XFixesGetCursorImage -lXfixes &&
 { enabled xlib || die "ERROR: Xlib not found"; }
 
+enabled vaapi && enabled unistd_h &&
+    check_pkg_config libdrm xf86drm.h drmOpen &&
+    check_lib2 "va/va.h va/va_drm.h" vaGetDisplayDRM -lva -lva-drm &&
+    enable vaapi_drm
+
+enabled vaapi && enabled xlib &&
+    check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 &&
+    enable vaapi_x11
+
 enabled vdpau &&
     check_cpp_condition vdpau/vdpau.h "defined 
VDP_DECODER_PROFILE_MPEG4_PART2_ASP" ||
     disable vdpau
@@ -4266,6 +4277,8 @@ TARGET_PATH=$target_path
 TARGET_SAMPLES=${target_samples:-\$(SAMPLES)}
 LIBS-avplay=$sdl_libs
 CFLAGS-avplay=$sdl_cflags
+LIBS-avconv=$libdrm_libs
+CFLAGS-avconv=$libdrm_cflags
 ZLIB=$($ldflags_filter -lz)
 LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD
 EXTRALIBS=$extralibs
diff --git a/doc/avconv.texi b/doc/avconv.texi
index 972d13f..38ed2ce 100644
--- a/doc/avconv.texi
+++ b/doc/avconv.texi
@@ -565,6 +565,10 @@ Automatically select the hardware acceleration method.
 
 @item vdpau
 Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration.
+
+@item vaapi
+Use VA API (Video Acceleration API) hardware acceleration. X11 and raw DRM
+access are supported.
 @end table
 
 This option has no effect if the selected hwaccel is not available or not
@@ -587,6 +591,15 @@ method chosen.
 @item vdpau
 For VDPAU, this option specifies the X11 display/screen to use. If this option
 is not specified, the value of the @var{DISPLAY} environment variable is used
+
+@item vaapi
+For VAAPI, this option specifies either the X11 display/screen to use (for X11
+access), the DRM driver name or the DRM device node (for DRM access). If this
+option is not specified, the @var{DISPLAY} environment variable is used to
+determine an X11 display to use.
+
+Note that raw DRM access allows using VAAPI acceleration without an X server,
+but this requires root privileges.
 @end table
 @end table
 
-- 
1.7.10.4

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

Reply via email to