|
|
|
@ -70,20 +70,12 @@ typedef struct VAAPIFramesContext { |
|
|
|
|
int derive_works; |
|
|
|
|
} VAAPIFramesContext; |
|
|
|
|
|
|
|
|
|
enum { |
|
|
|
|
VAAPI_MAP_READ = 0x01, |
|
|
|
|
VAAPI_MAP_WRITE = 0x02, |
|
|
|
|
VAAPI_MAP_DIRECT = 0x04, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
typedef struct VAAPISurfaceMap { |
|
|
|
|
// The source hardware frame of this mapping (with hw_frames_ctx set).
|
|
|
|
|
const AVFrame *source; |
|
|
|
|
// VAAPI_MAP_* flags which apply to this mapping.
|
|
|
|
|
int flags; |
|
|
|
|
typedef struct VAAPIMapping { |
|
|
|
|
// Handle to the derived or copied image which is mapped.
|
|
|
|
|
VAImage image; |
|
|
|
|
} VAAPISurfaceMap; |
|
|
|
|
// The mapping flags actually used.
|
|
|
|
|
int flags; |
|
|
|
|
} VAAPIMapping; |
|
|
|
|
|
|
|
|
|
#define MAP(va, rt, av) { \ |
|
|
|
|
VA_FOURCC_ ## va, \
|
|
|
|
@ -142,7 +134,8 @@ static int vaapi_get_image_format(AVHWDeviceContext *hwdev, |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ctx->nb_formats; i++) { |
|
|
|
|
if (ctx->formats[i].pix_fmt == pix_fmt) { |
|
|
|
|
*image_format = &ctx->formats[i].image_format; |
|
|
|
|
if (image_format) |
|
|
|
|
*image_format = &ctx->formats[i].image_format; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -636,17 +629,15 @@ static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void vaapi_unmap_frame(void *opaque, uint8_t *data) |
|
|
|
|
static void vaapi_unmap_frame(AVHWFramesContext *hwfc, |
|
|
|
|
HWMapDescriptor *hwmap) |
|
|
|
|
{ |
|
|
|
|
AVHWFramesContext *hwfc = opaque; |
|
|
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; |
|
|
|
|
VAAPISurfaceMap *map = (VAAPISurfaceMap*)data; |
|
|
|
|
const AVFrame *src; |
|
|
|
|
VAAPIMapping *map = hwmap->priv; |
|
|
|
|
VASurfaceID surface_id; |
|
|
|
|
VAStatus vas; |
|
|
|
|
|
|
|
|
|
src = map->source; |
|
|
|
|
surface_id = (VASurfaceID)(uintptr_t)src->data[3]; |
|
|
|
|
surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; |
|
|
|
|
av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id); |
|
|
|
|
|
|
|
|
|
vas = vaUnmapBuffer(hwctx->display, map->image.buf); |
|
|
|
@ -655,8 +646,8 @@ static void vaapi_unmap_frame(void *opaque, uint8_t *data) |
|
|
|
|
"%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((map->flags & VAAPI_MAP_WRITE) && |
|
|
|
|
!(map->flags & VAAPI_MAP_DIRECT)) { |
|
|
|
|
if ((map->flags & AV_HWFRAME_MAP_WRITE) && |
|
|
|
|
!(map->flags & AV_HWFRAME_MAP_DIRECT)) { |
|
|
|
|
vas = vaPutImage(hwctx->display, surface_id, map->image.image_id, |
|
|
|
|
0, 0, hwfc->width, hwfc->height, |
|
|
|
|
0, 0, hwfc->width, hwfc->height); |
|
|
|
@ -682,7 +673,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
VAAPIFramesContext *ctx = hwfc->internal->priv; |
|
|
|
|
VASurfaceID surface_id; |
|
|
|
|
VAImageFormat *image_format; |
|
|
|
|
VAAPISurfaceMap *map; |
|
|
|
|
VAAPIMapping *map; |
|
|
|
|
VAStatus vas; |
|
|
|
|
void *address = NULL; |
|
|
|
|
int err, i; |
|
|
|
@ -690,13 +681,13 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
surface_id = (VASurfaceID)(uintptr_t)src->data[3]; |
|
|
|
|
av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id); |
|
|
|
|
|
|
|
|
|
if (!ctx->derive_works && (flags & VAAPI_MAP_DIRECT)) { |
|
|
|
|
if (!ctx->derive_works && (flags & AV_HWFRAME_MAP_DIRECT)) { |
|
|
|
|
// Requested direct mapping but it is not possible.
|
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
if (dst->format == AV_PIX_FMT_NONE) |
|
|
|
|
dst->format = hwfc->sw_format; |
|
|
|
|
if (dst->format != hwfc->sw_format && (flags & VAAPI_MAP_DIRECT)) { |
|
|
|
|
if (dst->format != hwfc->sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) { |
|
|
|
|
// Requested direct mapping but the formats do not match.
|
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
@ -707,12 +698,10 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
map = av_malloc(sizeof(VAAPISurfaceMap)); |
|
|
|
|
map = av_malloc(sizeof(*map)); |
|
|
|
|
if (!map) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
map->source = src; |
|
|
|
|
map->flags = flags; |
|
|
|
|
map->flags = flags; |
|
|
|
|
map->image.image_id = VA_INVALID_ID; |
|
|
|
|
|
|
|
|
|
vas = vaSyncSurface(hwctx->display, surface_id); |
|
|
|
@ -730,8 +719,8 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
// faster with a copy routine which is aware of the limitation, but we
|
|
|
|
|
// assume for now that the user is not aware of that and would therefore
|
|
|
|
|
// prefer not to be given direct-mapped memory if they request read access.
|
|
|
|
|
if (ctx->derive_works && |
|
|
|
|
((flags & VAAPI_MAP_DIRECT) || !(flags & VAAPI_MAP_READ))) { |
|
|
|
|
if (ctx->derive_works && dst->format == hwfc->sw_format && |
|
|
|
|
((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) { |
|
|
|
|
vas = vaDeriveImage(hwctx->display, surface_id, &map->image); |
|
|
|
|
if (vas != VA_STATUS_SUCCESS) { |
|
|
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " |
|
|
|
@ -747,7 +736,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
err = AVERROR(EIO); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
map->flags |= VAAPI_MAP_DIRECT; |
|
|
|
|
map->flags |= AV_HWFRAME_MAP_DIRECT; |
|
|
|
|
} else { |
|
|
|
|
vas = vaCreateImage(hwctx->display, image_format, |
|
|
|
|
hwfc->width, hwfc->height, &map->image); |
|
|
|
@ -758,7 +747,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
err = AVERROR(EIO); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
if (flags & VAAPI_MAP_READ) { |
|
|
|
|
if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) { |
|
|
|
|
vas = vaGetImage(hwctx->display, surface_id, 0, 0, |
|
|
|
|
hwfc->width, hwfc->height, map->image.image_id); |
|
|
|
|
if (vas != VA_STATUS_SUCCESS) { |
|
|
|
@ -779,6 +768,11 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err = ff_hwframe_map_create(src->hw_frames_ctx, |
|
|
|
|
dst, src, &vaapi_unmap_frame, map); |
|
|
|
|
if (err < 0) |
|
|
|
|
goto fail; |
|
|
|
|
|
|
|
|
|
dst->width = src->width; |
|
|
|
|
dst->height = src->height; |
|
|
|
|
|
|
|
|
@ -795,13 +789,6 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, |
|
|
|
|
FFSWAP(uint8_t*, dst->data[1], dst->data[2]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dst->buf[0] = av_buffer_create((uint8_t*)map, sizeof(*map), |
|
|
|
|
&vaapi_unmap_frame, hwfc, 0); |
|
|
|
|
if (!dst->buf[0]) { |
|
|
|
|
err = AVERROR(ENOMEM); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
@ -829,7 +816,7 @@ static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
map->format = dst->format; |
|
|
|
|
|
|
|
|
|
err = vaapi_map_frame(hwfc, map, src, VAAPI_MAP_READ); |
|
|
|
|
err = vaapi_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ); |
|
|
|
|
if (err) |
|
|
|
|
goto fail; |
|
|
|
|
|
|
|
|
@ -860,7 +847,7 @@ static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
map->format = src->format; |
|
|
|
|
|
|
|
|
|
err = vaapi_map_frame(hwfc, map, dst, VAAPI_MAP_WRITE); |
|
|
|
|
err = vaapi_map_frame(hwfc, map, dst, AV_HWFRAME_MAP_WRITE | AV_HWFRAME_MAP_OVERWRITE); |
|
|
|
|
if (err) |
|
|
|
|
goto fail; |
|
|
|
|
|
|
|
|
@ -877,6 +864,28 @@ fail: |
|
|
|
|
return err; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
|
const AVFrame *src, int flags) |
|
|
|
|
{ |
|
|
|
|
int err; |
|
|
|
|
|
|
|
|
|
if (dst->format != AV_PIX_FMT_NONE) { |
|
|
|
|
err = vaapi_get_image_format(hwfc->device_ctx, dst->format, NULL); |
|
|
|
|
if (err < 0) |
|
|
|
|
return AVERROR(ENOSYS); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err = vaapi_map_frame(hwfc, dst, src, flags); |
|
|
|
|
if (err) |
|
|
|
|
return err; |
|
|
|
|
|
|
|
|
|
err = av_frame_copy_props(dst, src); |
|
|
|
|
if (err) |
|
|
|
|
return err; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void vaapi_device_free(AVHWDeviceContext *ctx) |
|
|
|
|
{ |
|
|
|
|
AVVAAPIDeviceContext *hwctx = ctx->hwctx; |
|
|
|
@ -999,6 +1008,8 @@ const HWContextType ff_hwcontext_type_vaapi = { |
|
|
|
|
.transfer_get_formats = &vaapi_transfer_get_formats, |
|
|
|
|
.transfer_data_to = &vaapi_transfer_data_to, |
|
|
|
|
.transfer_data_from = &vaapi_transfer_data_from, |
|
|
|
|
.map_to = NULL, |
|
|
|
|
.map_from = &vaapi_map_from, |
|
|
|
|
|
|
|
|
|
.pix_fmts = (const enum AVPixelFormat[]) { |
|
|
|
|
AV_PIX_FMT_VAAPI, |
|
|
|
|