X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavutil%2Fhwcontext_vaapi.c;h=8624369bb9f14b61fe49b1b9fd4ea5d2e3bbb053;hb=2d2af23349cae0d84c8ed51c249bfc1e6f2e28a2;hp=53a5b02822efdbeab16662f26456fd50a8c975a9;hpb=23ba9b3fd1fe8fe7a67387aaaff2b173bd7c3d2c;p=ffmpeg diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 53a5b02822e..8624369bb9f 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -87,57 +87,82 @@ typedef struct VAAPIMapping { int flags; } VAAPIMapping; -#define MAP(va, rt, av) { \ +typedef struct VAAPIFormat { + unsigned int fourcc; + unsigned int rt_format; + enum AVPixelFormat pix_fmt; + int chroma_planes_swapped; +} VAAPIFormatDescriptor; + +#define MAP(va, rt, av, swap_uv) { \ VA_FOURCC_ ## va, \ VA_RT_FORMAT_ ## rt, \ - AV_PIX_FMT_ ## av \ + AV_PIX_FMT_ ## av, \ + swap_uv, \ } // The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V // plane swap cases. The frame handling below tries to hide these. -static const struct { - unsigned int fourcc; - unsigned int rt_format; - enum AVPixelFormat pix_fmt; -} vaapi_format_map[] = { - MAP(NV12, YUV420, NV12), - MAP(YV12, YUV420, YUV420P), // With U/V planes swapped. - MAP(IYUV, YUV420, YUV420P), +static const VAAPIFormatDescriptor vaapi_format_map[] = { + MAP(NV12, YUV420, NV12, 0), #ifdef VA_FOURCC_I420 - MAP(I420, YUV420, YUV420P), + MAP(I420, YUV420, YUV420P, 0), #endif + MAP(YV12, YUV420, YUV420P, 1), + MAP(IYUV, YUV420, YUV420P, 0), + MAP(422H, YUV422, YUV422P, 0), #ifdef VA_FOURCC_YV16 - MAP(YV16, YUV422, YUV422P), // With U/V planes swapped. + MAP(YV16, YUV422, YUV422P, 1), #endif - MAP(422H, YUV422, YUV422P), - MAP(UYVY, YUV422, UYVY422), - MAP(YUY2, YUV422, YUYV422), - MAP(411P, YUV411, YUV411P), - MAP(422V, YUV422, YUV440P), - MAP(444P, YUV444, YUV444P), - MAP(Y800, YUV400, GRAY8), + MAP(UYVY, YUV422, UYVY422, 0), + MAP(YUY2, YUV422, YUYV422, 0), + MAP(411P, YUV411, YUV411P, 0), + MAP(422V, YUV422, YUV440P, 0), + MAP(444P, YUV444, YUV444P, 0), + MAP(Y800, YUV400, GRAY8, 0), #ifdef VA_FOURCC_P010 - MAP(P010, YUV420_10BPP, P010), + MAP(P010, YUV420_10BPP, P010, 0), #endif - MAP(BGRA, RGB32, BGRA), - MAP(BGRX, RGB32, BGR0), - MAP(RGBA, RGB32, RGBA), - MAP(RGBX, RGB32, RGB0), + MAP(BGRA, RGB32, BGRA, 0), + MAP(BGRX, RGB32, BGR0, 0), + MAP(RGBA, RGB32, RGBA, 0), + MAP(RGBX, RGB32, RGB0, 0), #ifdef VA_FOURCC_ABGR - MAP(ABGR, RGB32, ABGR), - MAP(XBGR, RGB32, 0BGR), + MAP(ABGR, RGB32, ABGR, 0), + MAP(XBGR, RGB32, 0BGR, 0), #endif - MAP(ARGB, RGB32, ARGB), - MAP(XRGB, RGB32, 0RGB), + MAP(ARGB, RGB32, ARGB, 0), + MAP(XRGB, RGB32, 0RGB, 0), }; #undef MAP -static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc) +static const VAAPIFormatDescriptor * + vaapi_format_from_fourcc(unsigned int fourcc) { int i; for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) if (vaapi_format_map[i].fourcc == fourcc) - return vaapi_format_map[i].pix_fmt; - return AV_PIX_FMT_NONE; + return &vaapi_format_map[i]; + return NULL; +} + +static const VAAPIFormatDescriptor * + vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) + if (vaapi_format_map[i].pix_fmt == pix_fmt) + return &vaapi_format_map[i]; + return NULL; +} + +static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc) +{ + const VAAPIFormatDescriptor *desc; + desc = vaapi_format_from_fourcc(fourcc); + if (desc) + return desc->pix_fmt; + else + return AV_PIX_FMT_NONE; } static int vaapi_get_image_format(AVHWDeviceContext *hwdev, @@ -279,11 +304,14 @@ static const struct { const char *match_string; unsigned int quirks; } vaapi_driver_quirks_table[] = { +#if !VA_CHECK_VERSION(1, 0, 0) + // The i965 driver did not conform before version 2.0. { "Intel i965 (Quick Sync)", "i965", AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS, }, +#endif { "Intel iHD", "ubit", @@ -344,29 +372,37 @@ static int vaapi_device_init(AVHWDeviceContext *hwdev) } } + vendor_string = vaQueryVendorString(hwctx->display); + if (vendor_string) + av_log(hwdev, AV_LOG_VERBOSE, "VAAPI driver: %s.\n", vendor_string); + if (hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_USER_SET) { - av_log(hwdev, AV_LOG_VERBOSE, "Not detecting driver: " - "quirks set by user.\n"); + av_log(hwdev, AV_LOG_VERBOSE, "Using quirks set by user (%#x).\n", + hwctx->driver_quirks); } else { // Detect the driver in use and set quirk flags if necessary. - vendor_string = vaQueryVendorString(hwctx->display); hwctx->driver_quirks = 0; if (vendor_string) { for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) { if (strstr(vendor_string, vaapi_driver_quirks_table[i].match_string)) { - av_log(hwdev, AV_LOG_VERBOSE, "Matched \"%s\" as known " - "driver \"%s\".\n", vendor_string, - vaapi_driver_quirks_table[i].friendly_name); + av_log(hwdev, AV_LOG_VERBOSE, "Matched driver string " + "as known nonstandard driver \"%s\", setting " + "quirks (%#x).\n", + vaapi_driver_quirks_table[i].friendly_name, + vaapi_driver_quirks_table[i].quirks); hwctx->driver_quirks |= vaapi_driver_quirks_table[i].quirks; break; } } if (!(i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table))) { - av_log(hwdev, AV_LOG_VERBOSE, "Unknown driver \"%s\", " - "assuming standard behaviour.\n", vendor_string); + av_log(hwdev, AV_LOG_VERBOSE, "Driver not found in known " + "nonstandard list, using standard behaviour.\n"); } + } else { + av_log(hwdev, AV_LOG_VERBOSE, "Driver has no vendor string, " + "assuming standard behaviour.\n"); } } @@ -450,22 +486,16 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc) AVVAAPIFramesContext *avfc = hwfc->hwctx; VAAPIFramesContext *ctx = hwfc->internal->priv; AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + const VAAPIFormatDescriptor *desc; VAImageFormat *expected_format; AVBufferRef *test_surface = NULL; VASurfaceID test_surface_id; VAImage test_image; VAStatus vas; int err, i; - unsigned int fourcc, rt_format; - for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) { - if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) { - fourcc = vaapi_format_map[i].fourcc; - rt_format = vaapi_format_map[i].rt_format; - break; - } - } - if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) { + desc = vaapi_format_from_pix_fmt(hwfc->sw_format); + if (!desc) { av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n", av_get_pix_fmt_name(hwfc->sw_format)); return AVERROR(EINVAL); @@ -506,7 +536,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc) .type = VASurfaceAttribPixelFormat, .flags = VA_SURFACE_ATTRIB_SETTABLE, .value.type = VAGenericValueTypeInteger, - .value.value.i = fourcc, + .value.value.i = desc->fourcc, }; } av_assert0(i == ctx->nb_attributes); @@ -515,7 +545,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc) ctx->nb_attributes = 0; } - ctx->rt_format = rt_format; + ctx->rt_format = desc->rt_format; if (hwfc->initial_pool_size > 0) { // This pool will be usable as a render target, so we need to store @@ -705,6 +735,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; VAAPIFramesContext *ctx = hwfc->internal->priv; VASurfaceID surface_id; + const VAAPIFormatDescriptor *desc; VAImageFormat *image_format; VAAPIMapping *map; VAStatus vas; @@ -813,11 +844,9 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, dst->data[i] = (uint8_t*)address + map->image.offsets[i]; dst->linesize[i] = map->image.pitches[i]; } - if ( -#ifdef VA_FOURCC_YV16 - map->image.format.fourcc == VA_FOURCC_YV16 || -#endif - map->image.format.fourcc == VA_FOURCC_YV12) { + + desc = vaapi_format_from_fourcc(map->image.format.fourcc); + if (desc && desc->chroma_planes_swapped) { // Chroma planes are YVU rather than YUV, so swap them. FFSWAP(uint8_t*, dst->data[1], dst->data[2]); } @@ -970,9 +999,10 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; + const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; VAStatus vas; - uint32_t va_fourcc, va_rt_format; + uint32_t va_fourcc; int err, i, j, k; unsigned long buffer_handle; @@ -1023,10 +1053,8 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as " "%08x.\n", desc->objects[0].fd, va_fourcc); - for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) { - if (vaapi_format_map[i].fourcc == va_fourcc) - va_rt_format = vaapi_format_map[i].rt_format; - } + format_desc = vaapi_format_from_fourcc(va_fourcc); + av_assert0(format_desc); buffer_handle = desc->objects[0].fd; buffer_desc.pixel_format = va_fourcc; @@ -1047,7 +1075,13 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, } buffer_desc.num_planes = k; - vas = vaCreateSurfaces(dst_dev->display, va_rt_format, + if (format_desc->chroma_planes_swapped && + buffer_desc.num_planes == 3) { + FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]); + FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]); + } + + vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, src->width, src->height, &surface_id, 1, attrs, FF_ARRAY_ELEMS(attrs)); @@ -1164,6 +1198,7 @@ fail: } #endif +#if VA_CHECK_VERSION(0, 36, 0) typedef struct VAAPIDRMImageBufferMapping { VAImage image; VABufferInfo buffer_info; @@ -1323,6 +1358,7 @@ fail: av_freep(&mapping); return err; } +#endif static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) @@ -1333,7 +1369,10 @@ static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, if (err != AVERROR(ENOSYS)) return err; #endif +#if VA_CHECK_VERSION(0, 36, 0) return vaapi_map_to_drm_abh(hwfc, dst, src, flags); +#endif + return AVERROR(ENOSYS); } #endif /* CONFIG_LIBDRM */