[FFmpeg-devel] [PATCH] lavc add XVBA decoder and hardware accelerator
Feng
digamma2function at gmail.com
Fri Jun 28 11:38:23 CEST 2013
---
Changelog | 1 +
configure | 13 ++
doc/decoders.texi | 8 +
libavcodec/Makefile | 8 +
libavcodec/allcodecs.c | 4 +
libavcodec/xvba.c | 66 ++++++
libavcodec/xvba.h | 69 +++++++
libavcodec/xvba_dec.c | 261 +++++++++++++++++++++++
libavcodec/xvba_h264.c | 229 +++++++++++++++++++++
libavcodec/xvba_internal.h | 25 +++
libavcodec/xvba_vc1.c | 183 +++++++++++++++++
libavcodec/xvba_wrapper.c | 489 ++++++++++++++++++++++++++++++++++++++++++++
libavcodec/xvba_wrapper.h | 115 +++++++++++
libavutil/pixdesc.c | 6 +
libavutil/pixfmt.h | 1 +
15 files changed, 1478 insertions(+)
create mode 100644 libavcodec/xvba.c
create mode 100644 libavcodec/xvba.h
create mode 100644 libavcodec/xvba_dec.c
create mode 100644 libavcodec/xvba_h264.c
create mode 100644 libavcodec/xvba_internal.h
create mode 100644 libavcodec/xvba_vc1.c
create mode 100644 libavcodec/xvba_wrapper.c
create mode 100644 libavcodec/xvba_wrapper.h
diff --git a/Changelog b/Changelog
index be3cf4c..44e2550 100644
--- a/Changelog
+++ b/Changelog
@@ -68,6 +68,7 @@ version <next>:
- WavPack encoding through libwavpack
- rotate filter
- spp filter ported from libmpcodecs
+- XVBA decoder and hardware acceleration
version 1.2:
diff --git a/configure b/configure
index a179036..0d495c8 100755
--- a/configure
+++ b/configure
@@ -145,6 +145,7 @@ Hardware accelerators:
--disable-vaapi disable VAAPI code [autodetect]
--enable-vda enable VDA code
--disable-vdpau disable VDPAU code [autodetect]
+ --enable-xvba enable xvba code
Individual component options:
--disable-everything disable all components listed below
@@ -1220,6 +1221,7 @@ HWACCEL_LIST="
vaapi
vda
vdpau
+ xvba
"
LIBRARY_LIST="
@@ -1408,6 +1410,7 @@ HAVE_LIST="
aligned_stack
alsa_asoundlib_h
altivec_h
+ amd_amdxvba_h
arpa_inet_h
asm_mod_q
asm_mod_y
@@ -1907,6 +1910,7 @@ vaapi_deps="va_va_h"
vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads"
vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore"
vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
+xvba_deps="amd_amdxvba_h"
h263_vaapi_hwaccel_deps="vaapi"
h263_vaapi_hwaccel_select="h263_decoder"
@@ -1925,6 +1929,9 @@ h264_vdpau_decoder_deps="vdpau"
h264_vdpau_decoder_select="h264_decoder"
h264_vdpau_hwaccel_deps="vdpau"
h264_vdpau_hwaccel_select="h264_decoder"
+h264_xvba_decoder_select="h264_decoder"
+h264_xvba_hwaccel_deps="xvba"
+h264_xvba_hwaccel_select="h264_decoder"
mpeg_vdpau_decoder_deps="vdpau"
mpeg_vdpau_decoder_select="mpeg2video_decoder"
mpeg1_vdpau_decoder_deps="vdpau"
@@ -1955,6 +1962,9 @@ vc1_vdpau_decoder_deps="vdpau"
vc1_vdpau_decoder_select="vc1_decoder"
vc1_vdpau_hwaccel_deps="vdpau"
vc1_vdpau_hwaccel_select="vc1_decoder"
+vc1_xvba_decoder_select="vc1_decoder"
+vc1_xvba_hwaccel_deps="xvba"
+vc1_xvba_hwaccel_select="vc1_decoder"
wmv3_crystalhd_decoder_select="crystalhd"
wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
@@ -4033,6 +4043,7 @@ check_func_headers windows.h VirtualAlloc
check_func_headers glob.h glob
check_func_headers "X11/Xlib.h X11/extensions/Xvlib.h" XvGetPortAttribute -lXv -lX11 -lXext
+check_header amd/amdxvba.h
check_header cl/cl.h
check_header direct.h
check_header dlfcn.h
@@ -4055,6 +4066,7 @@ check_header VideoDecodeAcceleration/VDADecoder.h
check_header windows.h
check_header X11/extensions/XvMClib.h
check_header asm/types.h
+check_header xvba.h
disabled zlib || check_lib zlib.h zlibVersion -lz || disable zlib
disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib
@@ -4194,6 +4206,7 @@ enabled openssl && { check_lib openssl/ssl.h SSL_library_init -lssl -l
check_lib openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
die "ERROR: openssl not found"; }
+enabled xvba && require libXvBAW amd/amdxvba.h XVBACreateContext -lXvBAW && require X11 X11/Xlib.h XOpenDisplay -lX11
if enabled gnutls; then
{ check_lib nettle/bignum.h nettle_mpz_get_str_256 -lnettle -lhogweed -lgmp && enable nettle; } ||
diff --git a/doc/decoders.texi b/doc/decoders.texi
index e907a61..57b49c3 100644
--- a/doc/decoders.texi
+++ b/doc/decoders.texi
@@ -47,6 +47,14 @@ top-field-first is assumed
@end table
+ at section xvba
+
+xvba decoder wrapper.
+
+xvba allows libavcodec to decode MPEG-4 AVC (H.264) and VC-1 encoded video.
+Requires the presence of the AMD xvba headers and library during configuration.
+You need to explicitly configure the build with @code{--enable-xvba}
+
@c man end VIDEO DECODERS
@chapter Audio Decoders
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index c6cd41b..438eb9b 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -12,6 +12,8 @@ HEADERS = avcodec.h \
vdpau.h \
version.h \
xvmc.h \
+ xvba.h \
+ xvba_wrapper.h \
OBJS = allcodecs.o \
audioconvert.o \
@@ -74,6 +76,7 @@ OBJS-$(CONFIG_VAAPI) += vaapi.o
OBJS-$(CONFIG_VDPAU) += vdpau.o
OBJS-$(CONFIG_VIDEODSP) += videodsp.o
OBJS-$(CONFIG_VP3DSP) += vp3dsp.o
+OBJS-$(CONFIG_XVBA) += xvba.o
# decoders/encoders
OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
@@ -229,6 +232,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \
cabac.o h264_sei.o h264_ps.o \
h264_refs.o h264_cavlc.o h264_cabac.o
OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.o
+OBJS-$(CONFIG_H264_XVBA_DECODER) += xvba_wrapper.o xvba_dec.o
OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o
OBJS-$(CONFIG_IAC_DECODER) += imc.o
@@ -451,6 +455,7 @@ OBJS-$(CONFIG_VBLE_DECODER) += vble.o
OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \
msmpeg4dec.o msmpeg4.o msmpeg4data.o \
intrax8.o intrax8dsp.o wmv2dsp.o
+OBJS-$(CONFIG_VC1_XVBA_DECODER) += xvba_wrapper.o xvba_dec.o
OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o
@@ -620,6 +625,7 @@ OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
+OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o
OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
@@ -629,6 +635,7 @@ OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
+OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o
# libavformat dependencies
OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o
@@ -806,6 +813,7 @@ SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h
SKIPHEADERS-$(CONFIG_VDA) += vda.h
SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h
+SKIPHEADERS-$(CONFIG_XVBA) += xvba.h xvba_internal.h
TESTPROGS = cabac \
dct \
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 5cdf778..f1ac23e 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -79,6 +79,7 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(H264_VAAPI, h264_vaapi);
REGISTER_HWACCEL(H264_VDA, h264_vda);
REGISTER_HWACCEL(H264_VDPAU, h264_vdpau);
+ REGISTER_HWACCEL(H264_XVBA, h264_xvba);
REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2);
REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi);
@@ -88,6 +89,7 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau);
+ REGISTER_HWACCEL(VC1_XVBA, vc1_xvba);
REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2);
REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi);
REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau);
@@ -164,6 +166,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(H264_CRYSTALHD, h264_crystalhd);
REGISTER_DECODER(H264_VDA, h264_vda);
REGISTER_DECODER(H264_VDPAU, h264_vdpau);
+ REGISTER_DECODER(H264_XVBA, h264_xvba);
REGISTER_ENCDEC (HUFFYUV, huffyuv);
REGISTER_DECODER(IDCIN, idcin);
REGISTER_DECODER(IFF_BYTERUN1, iff_byterun1);
@@ -275,6 +278,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(VC1, vc1);
REGISTER_DECODER(VC1_CRYSTALHD, vc1_crystalhd);
REGISTER_DECODER(VC1_VDPAU, vc1_vdpau);
+ REGISTER_DECODER(VC1_XVBA, vc1_xvba);
REGISTER_DECODER(VC1IMAGE, vc1image);
REGISTER_DECODER(VCR1, vcr1);
REGISTER_DECODER(VMDVIDEO, vmdvideo);
diff --git a/libavcodec/xvba.c b/libavcodec/xvba.c
new file mode 100644
index 0000000..0cba5dd
--- /dev/null
+++ b/libavcodec/xvba.c
@@ -0,0 +1,66 @@
+/*
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
+ *
+ * Copyright (C) 2005-2011 Team XBMC
+ *
+ * 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
+ */
+
+
+/**
+ * \addtogroup XVBA_Decoding
+ *
+ * @{
+ */
+
+#include <stdint.h>
+#include "xvba.h"
+#include "xvba_internal.h"
+#include "avcodec.h"
+
+int ff_xvba_translate_profile(int profile)
+{
+ if (profile == 66)
+ return 1;
+ else if (profile == 77)
+ return 2;
+ else if (profile == 100)
+ return 3;
+ else if (profile == 0)
+ return 4;
+ else if (profile == 1)
+ return 5;
+ else if (profile == 3)
+ return 6;
+ else
+ return -1;
+}
+
+void ff_xvba_add_slice_data(struct xvba_render_state *render,
+ const uint8_t * buffer, uint32_t size)
+{
+ render->buffers = av_fast_realloc(render->buffers,
+ &render->buffers_alllocated,
+ sizeof(struct xvba_bitstream_buffers)
+ * (render->num_slices + 1)
+ );
+
+ render->buffers[render->num_slices].buffer = buffer;
+ render->buffers[render->num_slices].size = size;
+
+ render->num_slices++;
+}
diff --git a/libavcodec/xvba.h b/libavcodec/xvba.h
new file mode 100644
index 0000000..94ad35e
--- /dev/null
+++ b/libavcodec/xvba.h
@@ -0,0 +1,69 @@
+/*
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
+ *
+ * Copyright (C) 2005-2011 Team XBMC
+ *
+ * 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 AVCODEC_XVBA_H
+#define AVCODEC_XVBA_H
+
+#include <stdint.h>
+#include <X11/Xlib.h>
+#include <amd/amdxvba.h>
+
+
+/**
+ * \defgroup XVBA_Decoding VA API Decoding
+ * \ingroup Decoder
+ * @{
+ */
+
+/** \brief The videoSurface is used for rendering. */
+#define FF_XVBA_STATE_USED_FOR_RENDER 1
+
+/**
+ * \brief The videoSurface is needed for reference/prediction.
+ * The codec manipulates this.
+ */
+#define FF_XVBA_STATE_USED_FOR_REFERENCE 2
+
+/**
+ * \brief The videoSurface holds a decoded frame.
+ * The codec manipulates this.
+ */
+#define FF_XVBA_STATE_DECODED 4
+
+/* @} */
+
+struct xvba_bitstream_buffers {
+ const void *buffer;
+ unsigned int size;
+};
+
+struct xvba_render_state {
+ int state; ///< Holds FF_XVBA_STATE_* values.
+ void *surface;
+ XVBAPictureDescriptor *picture_descriptor;
+ XVBAQuantMatrixAvc *iq_matrix;
+ unsigned int num_slices;
+ struct xvba_bitstream_buffers *buffers;
+ uint32_t buffers_alllocated;
+};
+
+#endif /* AVCODEC_XVBA_H */
diff --git a/libavcodec/xvba_dec.c b/libavcodec/xvba_dec.c
new file mode 100644
index 0000000..d41fc9a
--- /dev/null
+++ b/libavcodec/xvba_dec.c
@@ -0,0 +1,261 @@
+/*
+ * Call hardware decode acceleration through XVBA API
+ *
+ * Copyright (C) 2013 Feng Duan <fengduan at multicorewareinc.com>
+ *
+ * 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 <string.h>
+#include "xvba_wrapper.h"
+#include "h264.h"
+#include "avcodec.h"
+#include "mpeg12.h"
+#include "libavutil/pixfmt.h"
+#include "internal.h"
+
+#if CONFIG_H264_XVBA_DECODER
+extern AVCodec ff_h264_decoder, ff_h264_xvba_decoder;
+#endif
+
+#if CONFIG_VC1_XVBA_DECODER
+extern AVCodec ff_vc1_decoder, ff_vc1_xvba_decoder;
+#endif
+
+static const enum PixelFormat xvba_pixfmts[] = {
+ AV_PIX_FMT_YUV420P,
+ AV_PIX_FMT_NONE
+};
+
+static int get_hw_soft_codec(struct AVCodecContext *avctx,
+ XVBADecoderContext * ctx)
+{
+ switch (avctx->codec_id) {
+#if CONFIG_H264_XVBA_DECODER
+ case AV_CODEC_ID_H264:
+ ctx->hwcodec = &ff_h264_xvba_decoder;
+ ctx->codec = &ff_h264_decoder;
+ return 0;
+#endif
+#if CONFIG_VC1_XVBA_DECODER
+ case AV_CODEC_ID_VC1:
+ ctx->hwcodec = &ff_vc1_xvba_decoder;
+ ctx->codec = &ff_vc1_decoder;
+ return 0;
+#endif
+ default:
+ return -1;
+ }
+}
+
+static int get_buffer2(struct AVCodecContext *avctx, AVFrame * pic,
+ int flags)
+{
+ XVBADecoderContext *ctx = (XVBADecoderContext *) avctx->priv_data;
+ XVBADecoder *xvba_decoder = &ctx->xvba_decoder;
+ int ret;
+ avctx->pix_fmt = ctx->pix_fmt;
+
+ ff_init_buffer_info(avctx, pic);
+
+ if ((ret = ctx->get_buffer2(avctx, pic, flags)) < 0) {
+ return ret;
+ }
+
+ if (xvba_decoder) {
+ struct xvba_render_state *render =
+ ff_get_render_surface(xvba_decoder);
+
+ pic->data[3] = (uint8_t *) render;
+ return 0;
+ } else {
+ av_log(avctx, AV_LOG_ERROR,
+ "XVBA invalid context, get buffer failed");
+ return AVERROR(EINVAL);
+ }
+}
+
+static enum PixelFormat get_format(AVCodecContext * p_context,
+ const enum PixelFormat *pi_fmt)
+{
+ return AV_PIX_FMT_XVBA_VLD;
+}
+
+static int xvba2dec_decode(AVCodecContext * avctx, void *data,
+ int *got_frame, AVPacket * avpkt)
+{
+ XVBADecoderContext *ctx = (XVBADecoderContext *) avctx->priv_data;
+ XVBADecoder *xvba = (XVBADecoder *) & ctx->xvba_decoder;
+ AVFrame *pic;
+ struct xvba_render_state *render;
+ int ret;
+ AVCodec *codec = ctx->codec;
+ ret = codec->decode(avctx, data, got_frame, avpkt);
+ if (*got_frame) {
+ pic = (AVFrame *) data;
+ render = (struct xvba_render_state *) pic->data[3];
+ if (!render) {
+ av_log(avctx, AV_LOG_ERROR, "XVBA::Decode - invalid render");
+ return -1;
+ }
+ ret = ff_xvba_get_surface(xvba, render);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR,
+ "XVBA::Decode - get surface failed");
+ return -1;
+ }
+
+ pic->format = ctx->pix_fmt;
+ pic->data[0] = xvba->databuffer;
+ pic->data[2] =
+ pic->data[0] +
+ (sizeof(uint8_t) * (xvba->conf.surface_width) *
+ (xvba->conf.surface_height));
+ pic->data[1] =
+ pic->data[2] +
+ ((sizeof(uint8_t) * (xvba->conf.surface_width) *
+ (xvba->conf.surface_height)) >> 2);
+ pic->linesize[0] = xvba->conf.surface_width;
+ pic->linesize[1] = xvba->conf.surface_width >> 1;
+ pic->linesize[2] = xvba->conf.surface_width >> 1;
+ render->state &= ~FF_XVBA_STATE_USED_FOR_REFERENCE;
+ }
+ return ret;
+}
+
+static av_cold int xvba2dec_close(AVCodecContext * avctx)
+{
+ XVBADecoderContext *ctx = avctx->priv_data;
+ XVBADecoder *xvba_dec = (XVBADecoder *) (&ctx->xvba_decoder);
+ AVCodec *codec = ctx->codec;
+ /* release buffers and decoder */
+ if (ctx->databuffer) {
+ av_free(ctx->databuffer);
+ }
+ /* close H.264 decoder */
+ if (ctx->initialized)
+ codec->close(avctx);
+ if (xvba_dec)
+ ff_release_xvba(xvba_dec);
+ return 0;
+}
+
+/**
+ * brief : xvbadec_init;
+ */
+
+static av_cold int xvba2dec_init(AVCodecContext * avctx)
+{
+ XVBADecoderContext *ctx = (XVBADecoderContext *) avctx->priv_data;
+ XVBADecoder *xvba_dec = (XVBADecoder *) (&ctx->xvba_decoder);
+ AVCodec *hwcodec;
+ AVCodec *codec;
+ int ret, height, width;
+ av_log(avctx, AV_LOG_INFO, "XVBA DECODE\n");
+ ret = get_hw_soft_codec(avctx, ctx);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR,
+ "XVBA unsupport codec_id, init failed\n");
+ goto failed;
+ }
+ hwcodec = ctx->hwcodec;
+ codec = ctx->codec;
+ ctx->initialized = 0;
+
+ /* init pix_fmts of codec */
+ if (!(hwcodec->pix_fmts)) {
+ hwcodec->pix_fmts = xvba_pixfmts;
+ }
+
+ /* init xvba */
+ memset(xvba_dec, 0, sizeof(XVBADecoder));
+ ret = ff_create_xvba(avctx->codec_id, xvba_dec);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "create xvba error");
+ goto failed;
+ }
+ ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
+
+ height = (avctx->height + 15) & ~15;
+ width = (avctx->width + 15) & ~15;
+ ret =
+ ff_setup_xvba(xvba_dec, &avctx->pix_fmt, avctx->width,
+ avctx->height);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "error XVBA setup %d", ret);
+ goto failed;
+ }
+
+ ctx->get_buffer2 = avctx->get_buffer2;
+ avctx->get_format = get_format;
+ avctx->get_buffer2 = get_buffer2;
+
+ /* init H.264 decoder */
+ ret = codec->init(avctx);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to open decoder");
+ goto failed;
+ }
+ ctx->initialized = 1;
+ ctx->databuffer_size = width * height * 3 / 2;
+ if (!ctx->databuffer)
+ ctx->databuffer =
+ av_malloc(sizeof(uint8_t) * ctx->databuffer_size);
+ xvba_dec->databuffer = ctx->databuffer;
+ return 0;
+
+ failed:
+ xvba2dec_close(avctx);
+ return -1;
+}
+
+static void xvba2dec_flush(AVCodecContext * avctx)
+{
+ XVBADecoderContext *ctx = (XVBADecoderContext *) avctx->priv_data;
+ AVCodec *codec = ctx->codec;
+ return codec->flush(avctx);
+}
+
+#if CONFIG_H264_XVBA_DECODER
+AVCodec ff_h264_xvba_decoder = {
+ .name = "h264_xvba",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_H264,
+ .priv_data_size = sizeof(XVBADecoderContext),
+ .init = xvba2dec_init,
+ .close = xvba2dec_close,
+ .decode = xvba2dec_decode,
+ .capabilities = CODEC_CAP_DELAY,
+ .flush = xvba2dec_flush,
+ .long_name = NULL_IF_CONFIG_SMALL("H.264 (XVBA acceleration)"),
+};
+#endif
+
+#if CONFIG_VC1_XVBA_DECODER
+AVCodec ff_vc1_xvba_decoder = {
+ .name = "vc1_xvba",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_VC1,
+ .priv_data_size = sizeof(XVBADecoderContext),
+ .init = xvba2dec_init,
+ .close = xvba2dec_close,
+ .decode = xvba2dec_decode,
+ .capabilities = CODEC_CAP_DELAY,
+ .flush = xvba2dec_flush,
+ .long_name = NULL_IF_CONFIG_SMALL("VC1 (XVBA acceleration)"),
+};
+#endif
diff --git a/libavcodec/xvba_h264.c b/libavcodec/xvba_h264.c
new file mode 100644
index 0000000..f2237cb
--- /dev/null
+++ b/libavcodec/xvba_h264.c
@@ -0,0 +1,229 @@
+/*
+ * H.264 HW decode acceleration through XVBA
+ *
+ * Copyright (C) 2005-2011 Team XBMC
+ * Copyright (C) 2013 Feng Duan <fengduan at multicorewareinc.com>
+ *
+ * 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 "xvba.h"
+#include "xvba_internal.h"
+#include "xvba_wrapper.h"
+#include "h264.h"
+#include <assert.h>
+#include <time.h>
+
+/** @file
+ * This file implements the glue code between FFmpeg's and XvBA API's
+ * structures for H.264 decoding.
+ */
+
+/** Initialize and start decoding a frame with XVBA. */
+static int xvba_h264_start_frame(AVCodecContext * avctx,
+ av_unused const uint8_t * buffer,
+ av_unused uint32_t size)
+{
+ H264Context *const h = avctx->priv_data;
+ struct xvba_render_state *render;
+ XVBAPictureDescriptor *pic_descriptor;
+ int i;
+
+ render = (struct xvba_render_state *) h->cur_pic_ptr->f.data[3];
+ assert(render);
+
+ if (render->picture_descriptor == 0)
+ return -1;
+
+ pic_descriptor = render->picture_descriptor;
+
+ for (i = 0; i < 2; ++i) {
+ int foc = h->cur_pic_ptr->field_poc[i];
+ if (foc == INT_MAX)
+ foc = 0;
+ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc;
+ }
+ pic_descriptor->avc_frame_num = h->frame_num;
+ render->num_slices = 0;
+
+ return 0;
+}
+
+/** End a hardware decoding based frame. */
+
+static int xvba_h264_end_frame(AVCodecContext * avctx)
+{
+ XVBADecoderContext *ctx = (XVBADecoderContext *) avctx->priv_data;
+ XVBADecoder *xvba = (XVBADecoder *) & ctx->xvba_decoder;
+ H264Context *const h = (H264Context *) & ctx->decoder_ctx;
+ //MpegEncContext * const s = &h->s;
+ struct xvba_render_state *render;
+ XVBAPictureDescriptor *pic_descriptor;
+ XVBAQuantMatrixAvc *iq_matrix;
+ static int got_first_iframe;
+ int ret;
+
+ render = (struct xvba_render_state *) h->cur_pic_ptr->f.data[3];
+ assert(render);
+
+ if (render->picture_descriptor == 0 || render->iq_matrix == 0)
+ return -1;
+
+ pic_descriptor = render->picture_descriptor;
+ iq_matrix = render->iq_matrix;
+
+ av_dlog(avctx, "end_frame()\n");
+
+ /* Fill in Picture Parameters */
+ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile);
+ pic_descriptor->level = avctx->level;
+ pic_descriptor->width_in_mb = h->mb_width;
+ pic_descriptor->height_in_mb = h->mb_height;
+ pic_descriptor->picture_structure = h->picture_structure;
+ pic_descriptor->chroma_format = 1;
+ pic_descriptor->avc_intra_flag =
+ (h->slice_type == AV_PICTURE_TYPE_I) ? 1 : 0;
+ pic_descriptor->avc_reference =
+ (h->cur_pic_ptr->reference & 3) ? 1 : 0;
+
+ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
+ pic_descriptor->avc_bit_depth_chroma_minus8 =
+ h->sps.bit_depth_chroma - 8;
+ pic_descriptor->avc_log2_max_frame_num_minus4 =
+ h->sps.log2_max_frame_num - 4;
+ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type;
+ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 =
+ h->sps.log2_max_poc_lsb - 4;
+ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count;
+ pic_descriptor->avc_reserved_8bit = 0;
+
+ /* Set a level that can decode stuff in every case without a lookup table
+ xvba seems to have problems only when the number of Reframes goes beyond
+ the max support number of Level4.1 at High. So in praxis decoding a Level 3.0
+ file that in deed has level4.1 at High specs does not matter. We use this fact
+ and check if the ref_frames stay in the range Level4.1 at high can decode if
+ not, we set Level5.1 */
+ if (pic_descriptor->avc_num_ref_frames > 4) {
+ const unsigned int mbw = pic_descriptor->width_in_mb;
+ const unsigned int mbh = pic_descriptor->height_in_mb;
+ const unsigned int max_ref_frames =
+ 12288 * 1024 / (mbw * mbh * 384);
+ const unsigned int num_ref_frames =
+ pic_descriptor->avc_num_ref_frames;
+ if (max_ref_frames < num_ref_frames)
+ pic_descriptor->level = 51;
+ }
+
+ pic_descriptor->avc_num_slice_groups_minus1 =
+ h->pps.slice_group_count - 1;
+ pic_descriptor->avc_num_ref_idx_l0_active_minus1 =
+ h->pps.ref_count[0] - 1;
+ pic_descriptor->avc_num_ref_idx_l1_active_minus1 =
+ h->pps.ref_count[1] - 1;
+
+ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26;
+ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26;
+ pic_descriptor->avc_chroma_qp_index_offset =
+ h->pps.chroma_qp_index_offset[0];
+ pic_descriptor->avc_second_chroma_qp_index_offset =
+ h->pps.chroma_qp_index_offset[1];
+ pic_descriptor->avc_slice_group_change_rate_minus1 = 0;
+ pic_descriptor->avc_reserved_16bit = 0;
+ memset(pic_descriptor->avc_field_order_cnt_list, 0,
+ sizeof(pic_descriptor->avc_field_order_cnt_list));
+ memset(pic_descriptor->avc_slice_group_map, 0,
+ sizeof(pic_descriptor->avc_slice_group_map));
+
+ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag =
+ h->sps.delta_pic_order_always_zero_flag;
+ pic_descriptor->sps_info.avc.direct_8x8_inference_flag =
+ h->sps.direct_8x8_inference_flag;
+ pic_descriptor->sps_info.avc.frame_mbs_only_flag =
+ h->sps.frame_mbs_only_flag;
+ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag =
+ h->sps.gaps_in_frame_num_allowed_flag;
+ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag =
+ h->sps.mb_aff;
+ pic_descriptor->sps_info.avc.residual_colour_transform_flag =
+ h->sps.residual_color_transform_flag;
+ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0;
+
+ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac;
+ pic_descriptor->pps_info.avc.pic_order_present_flag =
+ h->pps.pic_order_present;
+ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred;
+ pic_descriptor->pps_info.avc.weighted_bipred_idc =
+ h->pps.weighted_bipred_idc;
+ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag =
+ h->pps.deblocking_filter_parameters_present;
+ pic_descriptor->pps_info.avc.constrained_intra_pred_flag =
+ h->pps.constrained_intra_pred;
+ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag =
+ h->pps.redundant_pic_cnt_present;
+ pic_descriptor->pps_info.avc.transform_8x8_mode_flag =
+ h->pps.transform_8x8_mode;
+ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0;
+
+ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4,
+ sizeof(iq_matrix->bScalingLists4x4));
+ memcpy(iq_matrix->bScalingLists8x8[0], h->pps.scaling_matrix8[0],
+ sizeof(iq_matrix->bScalingLists8x8[0]));
+ memcpy(iq_matrix->bScalingLists8x8[1], h->pps.scaling_matrix8[3],
+ sizeof(iq_matrix->bScalingLists8x8[0]));
+
+ /* Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs */
+ if (got_first_iframe) {
+ if (h->slice_type != AV_PICTURE_TYPE_I
+ && h->slice_type != AV_PICTURE_TYPE_SI)
+ return -1;
+ got_first_iframe = 1;
+ }
+
+ ff_h264_draw_horiz_band(h, 0, h->avctx->height);
+ ret = ff_xvba_decode_slice(xvba, render);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "decode slice failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/** Decode the given H.264 slice with XVBA. */
+static int xvba_h264_decode_slice(AVCodecContext * avctx,
+ const uint8_t * buffer, uint32_t size)
+{
+ H264Context *const h = avctx->priv_data;
+ struct xvba_render_state *render;
+
+ render = (struct xvba_render_state *) h->cur_pic_ptr->f.data[3];
+ assert(render);
+
+ ff_xvba_add_slice_data(render, buffer, size);
+
+ return 0;
+}
+
+AVHWAccel ff_h264_xvba_hwaccel = {
+ .name = "h264_xvba",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_H264,
+ .pix_fmt = AV_PIX_FMT_XVBA_VLD,
+ .start_frame = xvba_h264_start_frame,
+ .end_frame = xvba_h264_end_frame,
+ .decode_slice = xvba_h264_decode_slice,
+};
diff --git a/libavcodec/xvba_internal.h b/libavcodec/xvba_internal.h
new file mode 100644
index 0000000..48d0a4d
--- /dev/null
+++ b/libavcodec/xvba_internal.h
@@ -0,0 +1,25 @@
+/*
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
+ *
+ * Copyright (C) 2005-2011 Team XBMC
+ *
+ * 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
+ */
+
+int ff_xvba_translate_profile(int profile);
+void ff_xvba_add_slice_data(struct xvba_render_state *render,
+ const uint8_t * buffer, uint32_t size);
diff --git a/libavcodec/xvba_vc1.c b/libavcodec/xvba_vc1.c
new file mode 100644
index 0000000..128050d
--- /dev/null
+++ b/libavcodec/xvba_vc1.c
@@ -0,0 +1,183 @@
+/*
+ * VC-1 HW decode acceleration through XVBA
+ *
+ * Copyright (C) 2005-2011 Team XBMC
+ *
+ * Copyright (C) 2013 Feng Duan <fengduan at multicorewareinc.com>
+ *
+ * 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 "xvba.h"
+#include "xvba_internal.h"
+#include "vc1.h"
+#include "vc1data.h"
+#include "xvba_wrapper.h"
+#include <assert.h>
+
+
+/** @file
+ * Implement structures of ffmpeg <-> XvBA
+ */
+/* Initialize and start decoding a frame with XvBA */
+static int xvba_vc1_start_frame(AVCodecContext * avctx,
+ av_unused const uint8_t * buffer,
+ av_unused uint32_t size)
+{
+ VC1Context *const v = avctx->priv_data;
+ MpegEncContext *const s = &v->s;
+ struct xvba_render_state *render;
+
+ render =
+ (struct xvba_render_state *) s->current_picture_ptr->f.data[3];
+ assert(render);
+ render->num_slices = 0;
+
+ return 0;
+}
+
+/* End a hardware decoding based frame */
+static int xvba_vc1_end_frame(AVCodecContext * avctx)
+{
+ XVBADecoderContext *ctx = (XVBADecoderContext *) avctx->priv_data;
+ XVBADecoder *xvba = (XVBADecoder *) & ctx->xvba_decoder;
+ VC1Context *const v = (VC1Context *) & ctx->decoder_ctx;
+ MpegEncContext *const s = &v->s;
+ struct xvba_render_state *render, *last, *next;
+ XVBAPictureDescriptor *pic_descriptor;
+ int ret;
+
+ render =
+ (struct xvba_render_state *) s->current_picture_ptr->f.data[3];
+ assert(render);
+
+ if (render->picture_descriptor == 0)
+ return -1;
+
+ pic_descriptor = render->picture_descriptor;
+
+ av_dlog(avctx, "xvba_vc1_end_frame()\n");
+
+ memset(pic_descriptor, 0, sizeof(*pic_descriptor));
+
+ /* Fill in Parameters - for reference see AMD sdk documentation */
+ pic_descriptor->profile = ff_xvba_translate_profile(v->profile);
+ pic_descriptor->level = v->level;
+ if (v->profile == PROFILE_ADVANCED) {
+ pic_descriptor->width_in_mb = s->avctx->coded_width;
+ pic_descriptor->height_in_mb = s->avctx->coded_height;
+ } else {
+ pic_descriptor->width_in_mb = s->mb_width;
+ pic_descriptor->height_in_mb = s->mb_height;
+ }
+ pic_descriptor->picture_structure = s->picture_structure;
+
+ pic_descriptor->chroma_format = 1;
+ pic_descriptor->avc_intra_flag = s->pict_type == AV_PICTURE_TYPE_I
+ || v->bi_type == 1;
+
+ pic_descriptor->avc_reference = 1;
+
+ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag;
+
+ pic_descriptor->sps_info.vc1.pulldown = v->broadcast;
+ pic_descriptor->sps_info.vc1.interlace = v->interlace;
+ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag;
+ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag;
+ pic_descriptor->sps_info.vc1.reserved = 1;
+ pic_descriptor->sps_info.vc1.psf = v->psf;
+ pic_descriptor->sps_info.vc1.second_field = !s->first_field;
+ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0;
+
+ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag;
+ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag;
+ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter;
+ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc;
+ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv;
+ pic_descriptor->pps_info.vc1.dquant = v->dquant;
+ pic_descriptor->pps_info.vc1.vstransform = v->vstransform;
+ pic_descriptor->pps_info.vc1.overlap = v->overlap;
+ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode;
+ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv;
+ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames;
+ pic_descriptor->pps_info.vc1.rangered =
+ (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered;
+ pic_descriptor->pps_info.vc1.syncmarker =
+ (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker;
+ pic_descriptor->pps_info.vc1.multires = v->multires;
+ pic_descriptor->pps_info.vc1.reserved = 1;
+ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag;
+ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy;
+ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag;
+ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv;
+ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0;
+
+ pic_descriptor->past_surface = 0;
+ pic_descriptor->future_surface = 0;
+ switch (s->pict_type) {
+ case AV_PICTURE_TYPE_B:
+ next = (struct xvba_render_state *) s->next_picture.f.data[3];
+ assert(next);
+ if (next)
+ pic_descriptor->past_surface = next->surface;
+ case AV_PICTURE_TYPE_P:
+ last = (struct xvba_render_state *) s->last_picture.f.data[3];
+ assert(last);
+ if (last)
+ pic_descriptor->future_surface = last->surface;
+ break;
+ }
+ ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
+ ret = ff_xvba_decode_slice(xvba, render);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "decode slice failed");
+ return -1;
+ }
+ return 0;
+}
+
+static int xvba_vc1_decode_slice(AVCodecContext * avctx,
+ const uint8_t * buffer, uint32_t size)
+{
+ VC1Context *const v = avctx->priv_data;
+ MpegEncContext *const s = &v->s;
+ struct xvba_render_state *render;
+
+ render =
+ (struct xvba_render_state *) s->current_picture_ptr->f.data[3];
+ assert(render);
+
+ if (avctx->codec_id == AV_CODEC_ID_VC1 &&
+ size >= 4 && IS_MARKER(AV_RB32(buffer))) {
+ buffer += 4;
+ size -= 4;
+ }
+
+ ff_xvba_add_slice_data(render, buffer, size);
+
+ return 0;
+}
+
+AVHWAccel ff_vc1_xvba_hwaccel = {
+ .name = "vc1_xvba",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_VC1,
+ .pix_fmt = AV_PIX_FMT_XVBA_VLD,
+ .start_frame = xvba_vc1_start_frame,
+ .end_frame = xvba_vc1_end_frame,
+ .decode_slice = xvba_vc1_decode_slice,
+};
diff --git a/libavcodec/xvba_wrapper.c b/libavcodec/xvba_wrapper.c
new file mode 100644
index 0000000..4f427e0
--- /dev/null
+++ b/libavcodec/xvba_wrapper.c
@@ -0,0 +1,489 @@
+/*
+* Call hardware decode acceleration through XVBA API
+*
+* Copyright (C) 2005-2011 Team XBMC
+* Copyright (C) 2013 Feng Duan <fengduan at multicorewareinc.com>
+*
+* 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 <string.h>
+#include <unistd.h>
+#include "xvba_wrapper.h"
+#include "h264.h"
+
+
+int ff_create_xvba(int codec_id, XVBADecoder * xvba_dec)
+{
+ Drawable drawable;
+ XVBA_Create_Context_Input context_input;
+ XVBA_Create_Context_Output context_output;
+ XVBA_GetSessionInfo_Input session_input;
+ XVBA_GetSessionInfo_Output session_output;
+ XVBA_GetCapDecode_Input cap_input;
+ XVBA_GetCapDecode_Output *cap_output;
+ int version;
+ int match = -1;
+ xvba_dec->conf.context.display = XOpenDisplay(NULL);
+ drawable = 0;
+
+ if (!XVBAQueryExtension(xvba_dec->conf.context.display, &version))
+ return -1;
+
+ context_input.size = sizeof(context_input);
+ context_input.display = xvba_dec->conf.context.display;
+ context_input.draw = drawable;
+ context_output.size = sizeof(context_output);
+ if (Success != XVBACreateContext(&context_input, &context_output))
+ return -1;
+
+ xvba_dec->conf.context.xvba_context = context_output.context;
+
+ session_input.size = sizeof(session_input);
+ session_input.context = xvba_dec->conf.context.xvba_context;
+ session_output.size = sizeof(session_output);
+ if (Success != XVBAGetSessionInfo(&session_input, &session_output))
+ return -1;
+ if (session_output.getcapdecode_output_size == 0)
+ return -1;
+
+ cap_input.size = sizeof(cap_input);
+ cap_input.context = xvba_dec->conf.context.xvba_context;
+ cap_output = (XVBA_GetCapDecode_Output *)
+ av_calloc(session_output.getcapdecode_output_size, 1);
+ cap_output->size = session_output.getcapdecode_output_size;
+ if (Success != XVBAGetCapDecode(&cap_input, cap_output))
+ return -1;
+
+ if (codec_id == AV_CODEC_ID_H264) {
+ for (unsigned int i = 0; i < cap_output->num_of_decodecaps; ++i) {
+ if (cap_output->decode_caps_list[i].capability_id == XVBA_H264
+ && cap_output->decode_caps_list[i].flags ==
+ XVBA_H264_HIGH) {
+ match = (int) i;
+ break;
+ }
+ }
+ if (match < 0)
+ return -1;
+ } else if (codec_id == AV_CODEC_ID_VC1) {
+ for (unsigned int i = 0; i < cap_output->num_of_decodecaps; ++i) {
+ if (cap_output->decode_caps_list[i].capability_id == XVBA_VC1
+ && cap_output->decode_caps_list[i].flags ==
+ XVBA_VC1_ADVANCED) {
+ match = (int) i;
+ break;
+ }
+ }
+ if (match < 0)
+ return -1;
+ }
+
+ if (match < 0) {
+ av_free(cap_output);
+ return -1;
+ }
+ xvba_dec->conf.decoder_cap = cap_output->decode_caps_list[match];
+
+ av_free(cap_output);
+ xvba_dec->conf.xvba_session = 0;
+ xvba_dec->video_surface_count = 0;
+ xvba_dec->codec_id = codec_id;
+
+ return 0;
+}
+
+int ff_setup_xvba(XVBADecoder * xvba_dec, enum PixelFormat *chroma,
+ int width, int height)
+{
+ XVBA_Create_Decode_Session_Input session_input;
+ XVBA_Create_Decode_Session_Output session_output;
+ XVBA_Create_DecodeBuff_Input buffer_input;
+ XVBA_Create_DecodeBuff_Output buffer_output;
+ int surface_width, surface_height;
+ if (width == 0 || height == 0)
+ return -1;
+
+ surface_width = (width + 15) & ~15;
+ surface_height = (height + 15) & ~15;
+ if (surface_height > 1544 || surface_width > 2048)
+ return -1;
+
+ xvba_dec->conf.surface_width = surface_width;
+ xvba_dec->conf.surface_height = surface_height;
+
+ xvba_dec->conf.vid_width = width;
+ xvba_dec->conf.vid_height = height;
+
+ session_input.size = sizeof(session_input);
+ session_input.width = surface_width;
+ session_input.height = surface_height;
+ session_input.context = xvba_dec->conf.context.xvba_context;
+ session_input.decode_cap = &xvba_dec->conf.decoder_cap;
+ session_output.size = sizeof(session_output);
+
+ if (Success != XVBACreateDecode(&session_input, &session_output))
+ return -1;
+
+ xvba_dec->conf.xvba_session = session_output.session;
+
+ buffer_input.size = sizeof(buffer_input);
+ buffer_input.session = xvba_dec->conf.xvba_session;
+ buffer_input.buffer_type = XVBA_PICTURE_DESCRIPTION_BUFFER;
+ buffer_input.num_of_buffers = 1;
+ buffer_output.size = sizeof(buffer_output);
+ if (Success != XVBACreateDecodeBuffers(&buffer_input, &buffer_output)
+ || buffer_output.num_of_buffers_in_list != 1)
+ return -1;
+
+ xvba_dec->pool.picture_descriptor_buffer = buffer_output.buffer_list;
+
+ buffer_input.buffer_type = XVBA_DATA_BUFFER;
+ if (Success != XVBACreateDecodeBuffers(&buffer_input, &buffer_output)
+ || buffer_output.num_of_buffers_in_list != 1)
+ return -1;
+
+ xvba_dec->pool.data_buffer = buffer_output.buffer_list;
+
+ buffer_input.buffer_type = XVBA_QM_BUFFER;
+ if (Success != XVBACreateDecodeBuffers(&buffer_input, &buffer_output)
+ || buffer_output.num_of_buffers_in_list != 1)
+ return -1;
+
+ xvba_dec->pool.iq_matrix_buffer = buffer_output.buffer_list;
+ xvba_dec->pool.ctrl_buffer_count = 0;
+
+ return 0;
+}
+
+void ff_release_xvba(XVBADecoder * xvba_dec)
+{
+ XVBA_Destroy_Decode_Buffers_Input buf_input;
+
+ buf_input.size = sizeof(buf_input);
+ buf_input.num_of_buffers_in_list = 1;
+ buf_input.session = xvba_dec->conf.xvba_session;
+
+ for (unsigned int i = 0; i < xvba_dec->pool.ctrl_buffer_count; ++i) {
+ buf_input.buffer_list = xvba_dec->pool.data_control_buffers[i];
+ XVBADestroyDecodeBuffers(&buf_input);
+ xvba_dec->pool.data_control_buffers[i] = 0;
+ }
+
+ if (xvba_dec->conf.xvba_session && xvba_dec->pool.data_buffer) {
+ buf_input.buffer_list = xvba_dec->pool.data_buffer;
+ XVBADestroyDecodeBuffers(&buf_input);
+ xvba_dec->pool.data_buffer = 0;
+ }
+
+ if (xvba_dec->conf.xvba_session
+ && xvba_dec->pool.picture_descriptor_buffer) {
+ buf_input.buffer_list = xvba_dec->pool.picture_descriptor_buffer;
+ XVBADestroyDecodeBuffers(&buf_input);
+ xvba_dec->pool.picture_descriptor_buffer = 0;
+ }
+
+ if (xvba_dec->conf.xvba_session && xvba_dec->pool.iq_matrix_buffer) {
+ buf_input.buffer_list = xvba_dec->pool.iq_matrix_buffer;
+ XVBADestroyDecodeBuffers(&buf_input);
+ xvba_dec->pool.iq_matrix_buffer = 0;
+ }
+
+ for (unsigned int i = 0; i < xvba_dec->video_surface_count; ++i) {
+ struct xvba_render_state *render = xvba_dec->video_surfaces[i];
+ if (xvba_dec->conf.xvba_session && render->surface) {
+ XVBADestroySurface(render->surface);
+ render->surface = 0;
+ render->state = 0;
+ render->picture_descriptor = 0;
+ render->iq_matrix = 0;
+ }
+ }
+
+ if (xvba_dec->conf.xvba_session) {
+ XVBADestroyDecode(xvba_dec->conf.xvba_session);
+ xvba_dec->conf.xvba_session = 0;
+ }
+
+ if (xvba_dec->conf.context.xvba_context) {
+ XVBADestroyContext(xvba_dec->conf.context.xvba_context);
+ xvba_dec->conf.context.xvba_context = 0;
+ }
+
+}
+
+static int is_surface_valid(XVBADecoder * xvba_dec,
+ struct xvba_render_state *render)
+{
+ int ret = -1;
+ unsigned int i;
+ for (i = 0; i < xvba_dec->video_surface_count; ++i) {
+ if (xvba_dec->video_surfaces[i] == render) {
+ ret = 0;
+ break;
+ }
+ }
+ if (ret < 0)
+ return ret;
+
+ if (xvba_dec->video_surfaces[i]->surface == NULL) {
+ xvba_dec->video_surfaces[i]->state = 0;
+ return -1;
+ }
+ return 0;
+}
+
+static int ensure_data_control_buffers(XVBADecoder * xvba_dec,
+ unsigned int num)
+{
+ XVBA_Create_DecodeBuff_Input buffer_input;
+ XVBA_Create_DecodeBuff_Output buffer_output;
+ unsigned int missing = num - xvba_dec->pool.ctrl_buffer_count;
+ if (xvba_dec->pool.ctrl_buffer_count >= num)
+ return 0;
+
+ buffer_input.size = sizeof(buffer_input);
+ buffer_input.session = xvba_dec->conf.xvba_session;
+ buffer_input.buffer_type = XVBA_DATA_CTRL_BUFFER;
+ buffer_input.num_of_buffers = 1;
+ buffer_output.size = sizeof(buffer_output);
+
+ for (unsigned int i = 0; i < missing; ++i) {
+ if (Success !=
+ XVBACreateDecodeBuffers(&buffer_input, &buffer_output)
+ || buffer_output.num_of_buffers_in_list != 1)
+ return -1;
+
+ xvba_dec->pool.data_control_buffers[xvba_dec->pool.
+ ctrl_buffer_count] =
+ buffer_output.buffer_list;
+ xvba_dec->pool.ctrl_buffer_count++;
+ }
+ return 0;
+}
+
+struct xvba_render_state *ff_get_render_surface(XVBADecoder * xvba)
+{
+ struct xvba_render_state *render = NULL;
+
+ for (unsigned int i = 0; i < xvba->video_surface_count; ++i) {
+ if (!
+ (xvba->video_surfaces[i]->
+ state & (FF_XVBA_STATE_USED_FOR_REFERENCE |
+ FF_XVBA_STATE_USED_FOR_RENDER))) {
+ render = xvba->video_surfaces[i];
+ render->state = 0;
+ break;
+ }
+ }
+
+ if (render == NULL) {
+ render = (struct xvba_render_state *)
+ av_calloc(sizeof(struct xvba_render_state), 1);
+ if (render == NULL)
+ return NULL;
+ render->surface = 0;
+ render->buffers_alllocated = 0;
+ xvba->video_surfaces[xvba->video_surface_count] = render;
+ xvba->video_surface_count++;
+ }
+
+ if (render->surface == 0) {
+ XVBA_Create_Surface_Input surface_input;
+ XVBA_Create_Surface_Output surface_output;
+ surface_input.size = sizeof(surface_input);
+ surface_input.surface_type = xvba->conf.decoder_cap.surface_type;
+ surface_input.width = xvba->conf.surface_width;
+ surface_input.height = xvba->conf.surface_height;
+ surface_input.session = xvba->conf.xvba_session;
+ surface_output.size = sizeof(surface_output);
+
+ if (Success != XVBACreateSurface(&surface_input, &surface_output))
+ return NULL;
+
+ render->surface = surface_output.surface;
+ render->picture_descriptor =
+ (XVBAPictureDescriptor *) xvba->pool.
+ picture_descriptor_buffer->bufferXVBA;
+ render->iq_matrix =
+ (XVBAQuantMatrixAvc *) xvba->pool.iq_matrix_buffer->bufferXVBA;
+ }
+
+ if (render == NULL)
+ return NULL;
+ render->state |= FF_XVBA_STATE_USED_FOR_REFERENCE;
+ render->state &= ~FF_XVBA_STATE_DECODED;
+
+ return render;
+}
+
+int ff_xvba_decode_slice(XVBADecoder * xvba,
+ struct xvba_render_state *render)
+{
+
+ XVBA_Decode_Picture_Start_Input start_input;
+ XVBA_Decode_Picture_Input pic_input;
+ XVBABufferDescriptor *list[2];
+ XVBADataCtrl *data_control;
+ int location = 0;
+ XVBA_Decode_Picture_End_Input end_input;
+ int start_code_size;
+ uint8_t start_code[] = { 0x00, 0x00, 0x01 };
+ uint8_t sdf;
+ unsigned int bytes_to_copy;
+ unsigned int free_buffer_size;
+ int buf_size;
+ int padding;
+ start_input.size = sizeof(start_input);
+ start_input.session = xvba->conf.xvba_session;
+ start_input.target_surface = render->surface;
+
+ if (Success != XVBAStartDecodePicture(&start_input))
+ return -1;
+
+ pic_input.size = sizeof(pic_input);
+ pic_input.session = xvba->conf.xvba_session;
+
+ pic_input.buffer_list = list;
+ list[0] = xvba->pool.picture_descriptor_buffer;
+ pic_input.num_of_buffers_in_list = 1;
+ if (xvba->codec_id == AV_CODEC_ID_H264) {
+ list[1] = xvba->pool.iq_matrix_buffer;
+ pic_input.num_of_buffers_in_list = 2;
+ }
+
+ if (Success != XVBADecodePicture(&pic_input))
+ return -1;
+
+ if (ensure_data_control_buffers(xvba, render->num_slices) < 0)
+ return -1;
+
+ xvba->pool.data_buffer->data_size_in_buffer = 0;
+ for (unsigned int j = 0; j < render->num_slices; ++j) {
+ start_code_size = 0;
+ if (xvba->codec_id == AV_CODEC_ID_H264) {
+ start_code_size = 3;
+ memcpy((uint8_t *) xvba->pool.data_buffer->bufferXVBA +
+ location, start_code, 3);
+ } else if (xvba->codec_id == AV_CODEC_ID_VC1
+ && (memcmp(render->buffers[j].buffer, start_code, 3) !=
+ 0)) {
+ start_code_size = 4;
+ sdf = 0x0d;
+ memcpy((uint8_t *) xvba->pool.data_buffer->bufferXVBA +
+ location, start_code, 3);
+ memcpy((uint8_t *) xvba->pool.data_buffer->bufferXVBA +
+ location + 3, &sdf, 1);
+ }
+ // check for potential buffer overwrite
+ bytes_to_copy = render->buffers[j].size;
+ free_buffer_size = xvba->pool.data_buffer->buffer_size -
+ xvba->pool.data_buffer->data_size_in_buffer;
+ if (bytes_to_copy >= free_buffer_size)
+ return -1;
+
+ memcpy((uint8_t *) xvba->pool.data_buffer->bufferXVBA + location +
+ start_code_size, render->buffers[j].buffer,
+ render->buffers[j].size);
+ data_control =
+ (XVBADataCtrl *) xvba->pool.
+ data_control_buffers[j]->bufferXVBA;
+ data_control->SliceDataLocation = location;
+ data_control->SliceBytesInBuffer =
+ render->buffers[j].size + start_code_size;
+ data_control->SliceBitsInBuffer =
+ data_control->SliceBytesInBuffer * 8;
+ xvba->pool.data_buffer->data_size_in_buffer +=
+ data_control->SliceBytesInBuffer;
+ location += data_control->SliceBytesInBuffer;
+ }
+
+ buf_size = xvba->pool.data_buffer->data_size_in_buffer;
+ padding = buf_size % 128;
+ if (padding) {
+ padding = 128 - padding;
+ xvba->pool.data_buffer->data_size_in_buffer += padding;
+ memset((uint8_t *) xvba->pool.data_buffer->bufferXVBA + buf_size,
+ 0, padding);
+ }
+
+ pic_input.num_of_buffers_in_list = 2;
+ for (unsigned int i = 0; i < render->num_slices; ++i) {
+ list[0] = xvba->pool.data_buffer;
+ list[0]->data_offset = 0;
+ list[1] = xvba->pool.data_control_buffers[i];
+ list[1]->data_size_in_buffer = sizeof(*data_control);
+ if (Success != XVBADecodePicture(&pic_input))
+ return -1;
+ }
+
+ end_input.size = sizeof(end_input);
+ end_input.session = xvba->conf.xvba_session;
+ if (Success != XVBAEndDecodePicture(&end_input))
+ return -1;
+
+ return 0;
+}
+
+int ff_xvba_get_surface(XVBADecoder * xvba,
+ struct xvba_render_state *render)
+{
+ XVBA_Surface_Sync_Input sync_input;
+ XVBA_Surface_Sync_Output sync_output;
+ XVBA_GetSurface_Target target;
+ XVBA_Get_Surface_Input input;
+
+ if (is_surface_valid(xvba, render) < 0)
+ return -1;
+
+ sync_input.size = sizeof(sync_input);
+ sync_input.session = xvba->conf.xvba_session;
+ sync_input.surface = render->surface;
+ sync_input.query_status = XVBA_GET_SURFACE_STATUS;
+ sync_output.size = sizeof(sync_output);
+
+ while (1) {
+ if (Success != XVBASyncSurface(&sync_input, &sync_output)) {
+ return -1;
+ }
+ if (!(sync_output.status_flags & XVBA_STILL_PENDING))
+ break;
+ }
+ render->state |= FF_XVBA_STATE_DECODED;
+
+ if (!(render->state & FF_XVBA_STATE_DECODED))
+ return -1;
+
+ target.size = sizeof(target);
+ target.surfaceType = XVBA_YV12;
+ target.flag = XVBA_FRAME;
+
+ input.size = sizeof(input);
+ input.session = xvba->conf.xvba_session;
+ input.src_surface = render->surface;
+ input.target_buffer = xvba->databuffer;
+ input.target_pitch = xvba->conf.surface_width;
+ input.target_width = xvba->conf.surface_width;
+ input.target_height = xvba->conf.surface_height;
+ input.target_parameter = target;
+
+ if (Success != XVBAGetSurface(&input))
+ return -1;
+
+ return 0;
+}
diff --git a/libavcodec/xvba_wrapper.h b/libavcodec/xvba_wrapper.h
new file mode 100644
index 0000000..74d8685
--- /dev/null
+++ b/libavcodec/xvba_wrapper.h
@@ -0,0 +1,115 @@
+/*
+ * Call hardware decode acceleration through xvba API
+ *
+ * Copyright (C) 2005-2011 Team XBMC
+ * Copyright (C) 2013 Feng Duan <fengduan at multicorewareinc.com>
+ *
+ * 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
+ */
+
+/*! \file
+ * \brief XvBAT types.
+ */
+#ifndef XVBA_WRAPPER_H
+#define XVBA_WRAPPER_H
+
+#include <X11/Xlib.h>
+#include <amd/amdxvba.h>
+#include "h264.h"
+#include "vc1.h"
+#include "vc1data.h"
+#include "mpeg12.h"
+#include "avcodec.h"
+#include "xvba.h"
+
+#define VA_XVBA_MAX_SURFACE_COUNT (64)
+#define VA_XVBA_MAX_SLICE_COUNT (64)
+typedef struct {
+ XVBABufferDescriptor *picture_descriptor_buffer;
+ XVBABufferDescriptor *iq_matrix_buffer;
+ XVBABufferDescriptor *data_buffer;
+ XVBABufferDescriptor *data_control_buffers[VA_XVBA_MAX_SLICE_COUNT];
+ unsigned int ctrl_buffer_count;
+} XVBABufferPool;
+
+typedef struct {
+ Display *display;
+ void *xvba_context;
+} XVBAContext;
+
+typedef struct {
+ int surface_width;
+ int surface_height;
+ int vid_width;
+ int vid_height;
+ int out_width;
+ int out_height;
+
+ XVBAContext context;
+ XVBADecodeCap decoder_cap;
+ void *xvba_session;
+} XVBAConfig;
+
+typedef struct {
+ XVBAConfig conf;
+ struct xvba_render_state *video_surfaces[VA_XVBA_MAX_SURFACE_COUNT];
+ unsigned int video_surface_count;
+ unsigned int codec_id;
+ uint8_t *databuffer;
+
+ XVBABufferPool pool;
+} XVBADecoder;
+
+typedef union {
+#if CONFIG_H264_XVBA_DECODER
+ H264Context h264_ctx;
+#endif
+#if CONFIG_VC1_XVBA_DECODER
+ VC1Context vc1_ctx;
+#endif
+} DecoderContext;
+
+typedef struct {
+ DecoderContext decoder_ctx;
+ int initialized;
+ enum AVPixelFormat pix_fmt;
+ int (*get_buffer2) (struct AVCodecContext * s, AVFrame * frame,
+ int flags);
+ AVCodec *hwcodec;
+ AVCodec *codec;
+ XVBADecoder xvba_decoder;
+ uint8_t *databuffer;
+ int databuffer_size;
+} XVBADecoderContext;
+
+int ff_create_xvba(int codec_id, XVBADecoder * xvba_dec);
+
+int ff_setup_xvba(XVBADecoder * xvba_dec, enum PixelFormat *chroma,
+ int width, int height);
+
+void ff_release_xvba(XVBADecoder * xvba_dec);
+
+struct xvba_render_state *ff_get_render_surface(XVBADecoder * xvba);
+
+int ff_xvba_decode_slice(XVBADecoder * xvba,
+ struct xvba_render_state *render);
+
+int ff_xvba_get_surface(XVBADecoder * xvba,
+ struct xvba_render_state *render);
+
+
+#endif /* defined(XVBAT_WRAPPER_H) */
diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
index 17f7e27..c467a1a 100644
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
@@ -1735,6 +1735,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
},
.flags = AV_PIX_FMT_FLAG_BE,
},
+ [AV_PIX_FMT_XVBA_VLD] = {
+ .name = "xvba_vld",
+ .log2_chroma_w = 1,
+ .log2_chroma_h = 1,
+ .flags = AV_PIX_FMT_FLAG_HWACCEL,
+ },
};
static enum AVPixelFormat get_pix_fmt_internal(const char *name)
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index 9a25c2c..b882ac6 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -238,6 +238,7 @@ enum AVPixelFormat {
AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian
AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian
AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of PIX_FMT_YUV411P and setting color_range
+ AV_PIX_FMT_XVBA_VLD, ///< HW decoding through XVBA, Picture.data[3] contains a XVBA surface.
AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
#if FF_API_PIX_FMT
--
1.7.9.5
More information about the ffmpeg-devel
mailing list