|
|
|
@ -884,8 +884,8 @@ fail: |
|
|
|
|
return err; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
|
const AVFrame *src, int flags) |
|
|
|
|
static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
|
const AVFrame *src, int flags) |
|
|
|
|
{ |
|
|
|
|
int err; |
|
|
|
|
|
|
|
|
@ -1060,6 +1060,97 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc, |
|
|
|
|
HWMapDescriptor *hwmap) |
|
|
|
|
{ |
|
|
|
|
AVDRMFrameDescriptor *drm_desc = hwmap->priv; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < drm_desc->nb_objects; i++) |
|
|
|
|
close(drm_desc->objects[i].fd); |
|
|
|
|
|
|
|
|
|
av_freep(&drm_desc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
|
const AVFrame *src, int flags) |
|
|
|
|
{ |
|
|
|
|
#if CONFIG_VAAPI_1 |
|
|
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; |
|
|
|
|
VASurfaceID surface_id; |
|
|
|
|
VAStatus vas; |
|
|
|
|
VADRMPRIMESurfaceDescriptor va_desc; |
|
|
|
|
AVDRMFrameDescriptor *drm_desc = NULL; |
|
|
|
|
int err, i, j; |
|
|
|
|
|
|
|
|
|
surface_id = (VASurfaceID)(uintptr_t)src->data[3]; |
|
|
|
|
|
|
|
|
|
vas = vaExportSurfaceHandle(hwctx->display, surface_id, |
|
|
|
|
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, |
|
|
|
|
VA_EXPORT_SURFACE_READ_ONLY | |
|
|
|
|
VA_EXPORT_SURFACE_SEPARATE_LAYERS, |
|
|
|
|
&va_desc); |
|
|
|
|
if (vas != VA_STATUS_SUCCESS) { |
|
|
|
|
if (vas == VA_STATUS_ERROR_UNIMPLEMENTED) |
|
|
|
|
return AVERROR(ENOSYS); |
|
|
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: " |
|
|
|
|
"%d (%s).\n", surface_id, vas, vaErrorStr(vas)); |
|
|
|
|
return AVERROR(EIO); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drm_desc = av_mallocz(sizeof(*drm_desc)); |
|
|
|
|
if (!drm_desc) { |
|
|
|
|
err = AVERROR(ENOMEM); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// By some bizarre coincidence, these structures are very similar...
|
|
|
|
|
drm_desc->nb_objects = va_desc.num_objects; |
|
|
|
|
for (i = 0; i < va_desc.num_objects; i++) { |
|
|
|
|
drm_desc->objects[i].fd = va_desc.objects[i].fd; |
|
|
|
|
drm_desc->objects[i].size = va_desc.objects[i].size; |
|
|
|
|
drm_desc->objects[i].format_modifier = |
|
|
|
|
va_desc.objects[i].drm_format_modifier; |
|
|
|
|
} |
|
|
|
|
drm_desc->nb_layers = va_desc.num_layers; |
|
|
|
|
for (i = 0; i < va_desc.num_layers; i++) { |
|
|
|
|
drm_desc->layers[i].format = va_desc.layers[i].drm_format; |
|
|
|
|
drm_desc->layers[i].nb_planes = va_desc.layers[i].num_planes; |
|
|
|
|
for (j = 0; j < va_desc.layers[i].num_planes; j++) { |
|
|
|
|
drm_desc->layers[i].planes[j].object_index = |
|
|
|
|
va_desc.layers[i].object_index[j]; |
|
|
|
|
drm_desc->layers[i].planes[j].offset = |
|
|
|
|
va_desc.layers[i].offset[j]; |
|
|
|
|
drm_desc->layers[i].planes[j].pitch = |
|
|
|
|
va_desc.layers[i].pitch[j]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, |
|
|
|
|
&vaapi_unmap_to_drm, drm_desc); |
|
|
|
|
if (err < 0) |
|
|
|
|
goto fail; |
|
|
|
|
|
|
|
|
|
dst->width = src->width; |
|
|
|
|
dst->height = src->height; |
|
|
|
|
dst->data[0] = (uint8_t*)drm_desc; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
|
for (i = 0; i < va_desc.num_objects; i++) |
|
|
|
|
close(va_desc.objects[i].fd); |
|
|
|
|
av_freep(&drm_desc); |
|
|
|
|
return err; |
|
|
|
|
#else |
|
|
|
|
// Older versions without vaExportSurfaceHandle() are not supported -
|
|
|
|
|
// in theory this is possible with a combination of vaDeriveImage()
|
|
|
|
|
// and vaAcquireBufferHandle(), but it doesn't carry enough metadata
|
|
|
|
|
// to actually use the result in a generic way.
|
|
|
|
|
return AVERROR(ENOSYS); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
@ -1075,6 +1166,19 @@ static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, |
|
|
|
|
const AVFrame *src, int flags) |
|
|
|
|
{ |
|
|
|
|
switch (dst->format) { |
|
|
|
|
#if CONFIG_LIBDRM |
|
|
|
|
case AV_PIX_FMT_DRM_PRIME: |
|
|
|
|
return vaapi_map_to_drm(hwfc, dst, src, flags); |
|
|
|
|
#endif |
|
|
|
|
default: |
|
|
|
|
return vaapi_map_to_memory(hwfc, dst, src, flags); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void vaapi_device_free(AVHWDeviceContext *ctx) |
|
|
|
|
{ |
|
|
|
|
AVVAAPIDeviceContext *hwctx = ctx->hwctx; |
|
|
|
|