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, \
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;
}
}
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);
"%#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);
VAAPIFramesContext *ctx = hwfc->internal->priv;
VASurfaceID surface_id;
VAImageFormat *image_format;
- VAAPISurfaceMap *map;
+ VAAPIMapping *map;
VAStatus vas;
void *address = NULL;
int err, i;
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);
}
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);
// 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 "
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);
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) {
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;
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:
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;
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;
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;
.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,