| @@ -16,6 +16,21 @@ | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * 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 "avassert.h" | ||||
| #include "buffer.h" | #include "buffer.h" | ||||
| #include "common.h" | #include "common.h" | ||||
| @@ -26,6 +41,14 @@ | |||||
| #include "pixdesc.h" | #include "pixdesc.h" | ||||
| #include "pixfmt.h" | #include "pixfmt.h" | ||||
| typedef struct VAAPIDevicePriv { | |||||
| #if HAVE_VAAPI_X11 | |||||
| Display *x11_display; | |||||
| #endif | |||||
| int drm_fd; | |||||
| } VAAPIDevicePriv; | |||||
| typedef struct VAAPISurfaceFormat { | typedef struct VAAPISurfaceFormat { | ||||
| enum AVPixelFormat pix_fmt; | enum AVPixelFormat pix_fmt; | ||||
| VAImageFormat image_format; | VAImageFormat image_format; | ||||
| @@ -823,6 +846,105 @@ fail: | |||||
| return err; | 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 = { | const HWContextType ff_hwcontext_type_vaapi = { | ||||
| .type = AV_HWDEVICE_TYPE_VAAPI, | .type = AV_HWDEVICE_TYPE_VAAPI, | ||||
| .name = "VAAPI", | .name = "VAAPI", | ||||
| @@ -833,6 +955,7 @@ const HWContextType ff_hwcontext_type_vaapi = { | |||||
| .frames_hwctx_size = sizeof(AVVAAPIFramesContext), | .frames_hwctx_size = sizeof(AVVAAPIFramesContext), | ||||
| .frames_priv_size = sizeof(VAAPIFramesContext), | .frames_priv_size = sizeof(VAAPIFramesContext), | ||||
| .device_create = &vaapi_device_create, | |||||
| .device_init = &vaapi_device_init, | .device_init = &vaapi_device_init, | ||||
| .device_uninit = &vaapi_device_uninit, | .device_uninit = &vaapi_device_uninit, | ||||
| .frames_get_constraints = &vaapi_frames_get_constraints, | .frames_get_constraints = &vaapi_frames_get_constraints, | ||||