aboutsummaryrefslogtreecommitdiffstats
path: root/libavutil
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2016-06-26 15:14:17 -0300
committerJames Almer <jamrial@gmail.com>2016-06-26 15:14:17 -0300
commit104c357b6a3ee181e1d657df68e38c17ba2bda77 (patch)
tree8de7acbcf90609e153169a3d0c65eba46b93b15c /libavutil
parentb2a74dd629c1ab3318ba0123f8814797a4fea3a4 (diff)
parente9394ca63dab3434bc8e869de019ecd86cb604ac (diff)
downloadffmpeg-104c357b6a3ee181e1d657df68e38c17ba2bda77.tar.gz
Merge branch 'master' into release/3.1
Merged-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavutil')
-rw-r--r--libavutil/hwcontext.c36
-rw-r--r--libavutil/hwcontext.h28
-rw-r--r--libavutil/hwcontext_cuda.c44
-rw-r--r--libavutil/hwcontext_dxva2.c133
-rw-r--r--libavutil/hwcontext_internal.h3
-rw-r--r--libavutil/hwcontext_vaapi.c123
-rw-r--r--libavutil/hwcontext_vdpau.c81
-rw-r--r--libavutil/version.h2
8 files changed, 449 insertions, 1 deletions
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index eeeb2880ff..1e9e91329c 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -452,3 +452,39 @@ void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
}
av_freep(constraints);
}
+
+int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
+ const char *device, AVDictionary *opts, int flags)
+{
+ AVBufferRef *device_ref = NULL;
+ AVHWDeviceContext *device_ctx;
+ int ret = 0;
+
+ device_ref = av_hwdevice_ctx_alloc(type);
+ if (!device_ref) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ device_ctx = (AVHWDeviceContext*)device_ref->data;
+
+ if (!device_ctx->internal->hw_type->device_create) {
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+
+ ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
+ opts, flags);
+ if (ret < 0)
+ goto fail;
+
+ ret = av_hwdevice_ctx_init(device_ref);
+ if (ret < 0)
+ goto fail;
+
+ *pdevice_ref = device_ref;
+ return 0;
+fail:
+ av_buffer_unref(&device_ref);
+ *pdevice_ref = NULL;
+ return ret;
+}
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index dc8169903b..4e9da0224d 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -242,6 +242,34 @@ AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type);
int av_hwdevice_ctx_init(AVBufferRef *ref);
/**
+ * Open a device of the specified type and create an AVHWDeviceContext for it.
+ *
+ * This is a convenience function intended to cover the simple cases. Callers
+ * who need to fine-tune device creation/management should open the device
+ * manually and then wrap it in an AVHWDeviceContext using
+ * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init().
+ *
+ * The returned context is already initialized and ready for use, the caller
+ * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of
+ * the created AVHWDeviceContext are set by this function and should not be
+ * touched by the caller.
+ *
+ * @param device_ctx On success, a reference to the newly-created device context
+ * will be written here. The reference is owned by the caller
+ * and must be released with av_buffer_unref() when no longer
+ * needed. On failure, NULL will be written to this pointer.
+ * @param type The type of the device to create.
+ * @param device A type-specific string identifying the device to open.
+ * @param opts A dictionary of additional (type-specific) options to use in
+ * opening the device. The dictionary remains owned by the caller.
+ * @param flags currently unused
+ *
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,
+ const char *device, AVDictionary *opts, int flags);
+
+/**
* Allocate an AVHWFramesContext tied to a given device context.
*
* @param device_ctx a reference to a AVHWDeviceContext. This function will make
diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c
index 2c5980d619..fa24c5d37b 100644
--- a/libavutil/hwcontext_cuda.c
+++ b/libavutil/hwcontext_cuda.c
@@ -253,6 +253,49 @@ static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
return 0;
}
+static void cuda_device_free(AVHWDeviceContext *ctx)
+{
+ AVCUDADeviceContext *hwctx = ctx->hwctx;
+ cuCtxDestroy(hwctx->cuda_ctx);
+}
+
+static int cuda_device_create(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags)
+{
+ AVCUDADeviceContext *hwctx = ctx->hwctx;
+ CUdevice cu_device;
+ CUcontext dummy;
+ CUresult err;
+ int device_idx = 0;
+
+ if (device)
+ device_idx = strtol(device, NULL, 0);
+
+ err = cuInit(0);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ err = cuDeviceGet(&cu_device, device_idx);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", device_idx);
+ return AVERROR_UNKNOWN;
+ }
+
+ err = cuCtxCreate(&hwctx->cuda_ctx, 0, cu_device);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ cuCtxPopCurrent(&dummy);
+
+ ctx->free = cuda_device_free;
+
+ return 0;
+}
+
const HWContextType ff_hwcontext_type_cuda = {
.type = AV_HWDEVICE_TYPE_CUDA,
.name = "CUDA",
@@ -260,6 +303,7 @@ const HWContextType ff_hwcontext_type_cuda = {
.device_hwctx_size = sizeof(AVCUDADeviceContext),
.frames_priv_size = sizeof(CUDAFramesContext),
+ .device_create = cuda_device_create,
.frames_init = cuda_frames_init,
.frames_get_buffer = cuda_get_buffer,
.transfer_get_formats = cuda_transfer_get_formats,
diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c
index ccee287ee6..e79254bb34 100644
--- a/libavutil/hwcontext_dxva2.c
+++ b/libavutil/hwcontext_dxva2.c
@@ -38,6 +38,9 @@
#include "pixdesc.h"
#include "pixfmt.h"
+typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
+typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **);
+
typedef struct DXVA2FramesContext {
IDirect3DSurface9 **surfaces_internal;
int nb_surfaces_used;
@@ -48,6 +51,16 @@ typedef struct DXVA2FramesContext {
D3DFORMAT format;
} DXVA2FramesContext;
+typedef struct DXVA2DevicePriv {
+ HMODULE d3dlib;
+ HMODULE dxva2lib;
+
+ HANDLE device_handle;
+
+ IDirect3D9 *d3d9;
+ IDirect3DDevice9 *d3d9device;
+} DXVA2DevicePriv;
+
static const struct {
D3DFORMAT d3d_format;
enum AVPixelFormat pix_fmt;
@@ -287,6 +300,125 @@ static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst,
return 0;
}
+static void dxva2_device_free(AVHWDeviceContext *ctx)
+{
+ AVDXVA2DeviceContext *hwctx = ctx->hwctx;
+ DXVA2DevicePriv *priv = ctx->user_opaque;
+
+ if (hwctx->devmgr && priv->device_handle != INVALID_HANDLE_VALUE)
+ IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, priv->device_handle);
+
+ if (hwctx->devmgr)
+ IDirect3DDeviceManager9_Release(hwctx->devmgr);
+
+ if (priv->d3d9device)
+ IDirect3DDevice9_Release(priv->d3d9device);
+
+ if (priv->d3d9)
+ IDirect3D9_Release(priv->d3d9);
+
+ if (priv->d3dlib)
+ FreeLibrary(priv->d3dlib);
+
+ if (priv->dxva2lib)
+ FreeLibrary(priv->dxva2lib);
+
+ av_freep(&ctx->user_opaque);
+}
+
+static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags)
+{
+ AVDXVA2DeviceContext *hwctx = ctx->hwctx;
+ DXVA2DevicePriv *priv;
+
+ pDirect3DCreate9 *createD3D = NULL;
+ pCreateDeviceManager9 *createDeviceManager = NULL;
+ D3DPRESENT_PARAMETERS d3dpp = {0};
+ D3DDISPLAYMODE d3ddm;
+ unsigned resetToken = 0;
+ UINT adapter = D3DADAPTER_DEFAULT;
+ HRESULT hr;
+
+ if (device)
+ adapter = atoi(device);
+
+ priv = av_mallocz(sizeof(*priv));
+ if (!priv)
+ return AVERROR(ENOMEM);
+
+ ctx->user_opaque = priv;
+ ctx->free = dxva2_device_free;
+
+ priv->device_handle = INVALID_HANDLE_VALUE;
+
+ priv->d3dlib = LoadLibrary("d3d9.dll");
+ if (!priv->d3dlib) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n");
+ return AVERROR_UNKNOWN;
+ }
+ priv->dxva2lib = LoadLibrary("dxva2.dll");
+ if (!priv->dxva2lib) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9");
+ if (!createD3D) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n");
+ return AVERROR_UNKNOWN;
+ }
+ createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(priv->dxva2lib,
+ "DXVA2CreateDirect3DDeviceManager9");
+ if (!createDeviceManager) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ priv->d3d9 = createD3D(D3D_SDK_VERSION);
+ if (!priv->d3d9) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm);
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = 640;
+ d3dpp.BackBufferHeight = 480;
+ d3dpp.BackBufferCount = 0;
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
+
+ hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(),
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
+ &d3dpp, &priv->d3d9device);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ hr = createDeviceManager(&resetToken, &hwctx->devmgr);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle);
+ if (FAILED(hr)) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n");
+ return AVERROR_UNKNOWN;
+ }
+
+ return 0;
+}
+
const HWContextType ff_hwcontext_type_dxva2 = {
.type = AV_HWDEVICE_TYPE_DXVA2,
.name = "DXVA2",
@@ -295,6 +427,7 @@ const HWContextType ff_hwcontext_type_dxva2 = {
.frames_hwctx_size = sizeof(AVDXVA2FramesContext),
.frames_priv_size = sizeof(DXVA2FramesContext),
+ .device_create = dxva2_device_create,
.frames_init = dxva2_frames_init,
.frames_uninit = dxva2_frames_uninit,
.frames_get_buffer = dxva2_get_buffer,
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index e62324ccda..cf832fecc9 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -64,6 +64,9 @@ typedef struct HWContextType {
*/
size_t frames_priv_size;
+ int (*device_create)(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags);
+
int (*device_init)(AVHWDeviceContext *ctx);
void (*device_uninit)(AVHWDeviceContext *ctx);
diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
index 7c3e4bd27b..3c1493be9a 100644
--- a/libavutil/hwcontext_vaapi.c
+++ b/libavutil/hwcontext_vaapi.c
@@ -16,6 +16,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
+
+#if HAVE_VAAPI_X11
+# include <va/va_x11.h>
+#endif
+#if HAVE_VAAPI_DRM
+# include <va/va_drm.h>
+#endif
+
+#include <fcntl.h>
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+
#include "avassert.h"
#include "buffer.h"
#include "common.h"
@@ -26,6 +41,14 @@
#include "pixdesc.h"
#include "pixfmt.h"
+typedef struct VAAPIDevicePriv {
+#if HAVE_VAAPI_X11
+ Display *x11_display;
+#endif
+
+ int drm_fd;
+} VAAPIDevicePriv;
+
typedef struct VAAPISurfaceFormat {
enum AVPixelFormat pix_fmt;
VAImageFormat image_format;
@@ -823,6 +846,105 @@ fail:
return err;
}
+static void vaapi_device_free(AVHWDeviceContext *ctx)
+{
+ AVVAAPIDeviceContext *hwctx = ctx->hwctx;
+ VAAPIDevicePriv *priv = ctx->user_opaque;
+
+ if (hwctx->display)
+ vaTerminate(hwctx->display);
+
+#if HAVE_VAAPI_X11
+ if (priv->x11_display)
+ XCloseDisplay(priv->x11_display);
+#endif
+
+ if (priv->drm_fd >= 0)
+ close(priv->drm_fd);
+
+ av_freep(&priv);
+}
+
+static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags)
+{
+ AVVAAPIDeviceContext *hwctx = ctx->hwctx;
+ VAAPIDevicePriv *priv;
+ VADisplay display = 0;
+ VAStatus vas;
+ int major, minor;
+
+ priv = av_mallocz(sizeof(*priv));
+ if (!priv)
+ return AVERROR(ENOMEM);
+
+ priv->drm_fd = -1;
+
+ ctx->user_opaque = priv;
+ ctx->free = vaapi_device_free;
+
+#if HAVE_VAAPI_X11
+ if (!display && !(device && device[0] == '/')) {
+ // Try to open the device as an X11 display.
+ priv->x11_display = XOpenDisplay(device);
+ if (!priv->x11_display) {
+ av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
+ "%s.\n", XDisplayName(device));
+ } else {
+ display = vaGetDisplay(priv->x11_display);
+ if (!display) {
+ av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
+ "from X11 display %s.\n", XDisplayName(device));
+ return AVERROR_UNKNOWN;
+ }
+
+ av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
+ "X11 display %s.\n", XDisplayName(device));
+ }
+ }
+#endif
+
+#if HAVE_VAAPI_DRM
+ if (!display && device) {
+ // Try to open the device as a DRM path.
+ priv->drm_fd = open(device, O_RDWR);
+ if (priv->drm_fd < 0) {
+ av_log(ctx, AV_LOG_VERBOSE, "Cannot open DRM device %s.\n",
+ device);
+ } else {
+ display = vaGetDisplayDRM(priv->drm_fd);
+ if (!display) {
+ av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
+ "from DRM device %s.\n", device);
+ return AVERROR_UNKNOWN;
+ }
+
+ av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
+ "DRM device %s.\n", device);
+ }
+ }
+#endif
+
+ if (!display) {
+ av_log(ctx, AV_LOG_ERROR, "No VA display found for "
+ "device: %s.\n", device ? device : "");
+ return AVERROR(EINVAL);
+ }
+
+ hwctx->display = display;
+
+ vas = vaInitialize(display, &major, &minor);
+ if (vas != VA_STATUS_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
+ "connection: %d (%s).\n", vas, vaErrorStr(vas));
+ return AVERROR(EIO);
+ }
+ av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
+ "version %d.%d\n", major, minor);
+
+ return 0;
+}
+
const HWContextType ff_hwcontext_type_vaapi = {
.type = AV_HWDEVICE_TYPE_VAAPI,
.name = "VAAPI",
@@ -833,6 +955,7 @@ const HWContextType ff_hwcontext_type_vaapi = {
.frames_hwctx_size = sizeof(AVVAAPIFramesContext),
.frames_priv_size = sizeof(VAAPIFramesContext),
+ .device_create = &vaapi_device_create,
.device_init = &vaapi_device_init,
.device_uninit = &vaapi_device_uninit,
.frames_get_constraints = &vaapi_frames_get_constraints,
diff --git a/libavutil/hwcontext_vdpau.c b/libavutil/hwcontext_vdpau.c
index 37b740eaad..2b0fad314c 100644
--- a/libavutil/hwcontext_vdpau.c
+++ b/libavutil/hwcontext_vdpau.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
+
#include <stdint.h>
#include <string.h>
@@ -388,6 +390,82 @@ static int vdpau_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
return 0;
}
+#if HAVE_VDPAU_X11
+#include <vdpau/vdpau_x11.h>
+#include <X11/Xlib.h>
+
+typedef struct VDPAUDevicePriv {
+ VdpDeviceDestroy *device_destroy;
+ Display *dpy;
+} VDPAUDevicePriv;
+
+static void vdpau_device_free(AVHWDeviceContext *ctx)
+{
+ AVVDPAUDeviceContext *hwctx = ctx->hwctx;
+ VDPAUDevicePriv *priv = ctx->user_opaque;
+
+ if (priv->device_destroy)
+ priv->device_destroy(hwctx->device);
+ if (priv->dpy)
+ XCloseDisplay(priv->dpy);
+ av_freep(&priv);
+}
+
+static int vdpau_device_create(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags)
+{
+ AVVDPAUDeviceContext *hwctx = ctx->hwctx;
+
+ VDPAUDevicePriv *priv;
+ VdpStatus err;
+ VdpGetInformationString *get_information_string;
+ const char *display, *vendor;
+
+ priv = av_mallocz(sizeof(*priv));
+ if (!priv)
+ return AVERROR(ENOMEM);
+
+ ctx->user_opaque = priv;
+ ctx->free = vdpau_device_free;
+
+ priv->dpy = XOpenDisplay(device);
+ if (!priv->dpy) {
+ av_log(ctx, AV_LOG_ERROR, "Cannot open the X11 display %s.\n",
+ XDisplayName(device));
+ return AVERROR_UNKNOWN;
+ }
+ display = XDisplayString(priv->dpy);
+
+ err = vdp_device_create_x11(priv->dpy, XDefaultScreen(priv->dpy),
+ &hwctx->device, &hwctx->get_proc_address);
+ if (err != VDP_STATUS_OK) {
+ av_log(ctx, AV_LOG_ERROR, "VDPAU device creation on X11 display %s failed.\n",
+ display);
+ return AVERROR_UNKNOWN;
+ }
+
+#define GET_CALLBACK(id, result) \
+do { \
+ void *tmp; \
+ err = hwctx->get_proc_address(hwctx->device, id, &tmp); \
+ if (err != VDP_STATUS_OK) { \
+ av_log(ctx, AV_LOG_ERROR, "Error getting the " #id " callback.\n"); \
+ return AVERROR_UNKNOWN; \
+ } \
+ result = tmp; \
+} while (0)
+
+ GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string);
+ GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY, priv->device_destroy);
+
+ get_information_string(&vendor);
+ av_log(ctx, AV_LOG_VERBOSE, "Successfully created a VDPAU device (%s) on "
+ "X11 display %s\n", vendor, display);
+
+ return 0;
+}
+#endif
+
const HWContextType ff_hwcontext_type_vdpau = {
.type = AV_HWDEVICE_TYPE_VDPAU,
.name = "VDPAU",
@@ -396,6 +474,9 @@ const HWContextType ff_hwcontext_type_vdpau = {
.device_priv_size = sizeof(VDPAUDeviceContext),
.frames_priv_size = sizeof(VDPAUFramesContext),
+#if HAVE_VDPAU_X11
+ .device_create = vdpau_device_create,
+#endif
.device_init = vdpau_device_init,
.device_uninit = vdpau_device_uninit,
.frames_init = vdpau_frames_init,
diff --git a/libavutil/version.h b/libavutil/version.h
index a282fa864d..aa10622840 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -64,7 +64,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 55
-#define LIBAVUTIL_VERSION_MINOR 26
+#define LIBAVUTIL_VERSION_MINOR 27
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \