mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-03-02 18:48:27 +00:00
lavu/hwcontext: Add support for HW -> HW transfers
We are beginning to consider scenarios where a given HW Context may be able to transfer frames to another HW Context without passing via system memory - this would usually be when two contexts represent different APIs on the same device (eg: Vulkan and CUDA). This is modelled as a transfer, as we have today, but where both the src and the dst are hardware frames with hw contexts. We need to be careful to ensure the contexts are compatible - particularly, we cannot do transfers where one of the frames has been mapped via a derived frames context - we can only do transfers for frames that were directly allocated by the specified context. Additionally, as we have two hardware contexts, the transfer function could be implemented by either (or indeed both). To handle this uncertainty, we explicitly look for ENOSYS as an indicator to try the transfer in the other direction before giving up.
This commit is contained in:
parent
d84a30e123
commit
d7210ce7f5
@ -444,21 +444,54 @@ int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
|
||||
if (!dst->buf[0])
|
||||
return transfer_data_alloc(dst, src, flags);
|
||||
|
||||
if (src->hw_frames_ctx) {
|
||||
ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
|
||||
/*
|
||||
* Hardware -> Hardware Transfer.
|
||||
* Unlike Software -> Hardware or Hardware -> Software, the transfer
|
||||
* function could be provided by either the src or dst, depending on
|
||||
* the specific combination of hardware.
|
||||
*/
|
||||
if (src->hw_frames_ctx && dst->hw_frames_ctx) {
|
||||
AVHWFramesContext *src_ctx =
|
||||
(AVHWFramesContext*)src->hw_frames_ctx->data;
|
||||
AVHWFramesContext *dst_ctx =
|
||||
(AVHWFramesContext*)dst->hw_frames_ctx->data;
|
||||
|
||||
ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
|
||||
if (src_ctx->internal->source_frames) {
|
||||
av_log(src_ctx, AV_LOG_ERROR,
|
||||
"A device with a derived frame context cannot be used as "
|
||||
"the source of a HW -> HW transfer.");
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
if (dst_ctx->internal->source_frames) {
|
||||
av_log(src_ctx, AV_LOG_ERROR,
|
||||
"A device with a derived frame context cannot be used as "
|
||||
"the destination of a HW -> HW transfer.");
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
ret = src_ctx->internal->hw_type->transfer_data_from(src_ctx, dst, src);
|
||||
if (ret == AVERROR(ENOSYS))
|
||||
ret = dst_ctx->internal->hw_type->transfer_data_to(dst_ctx, dst, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (dst->hw_frames_ctx) {
|
||||
ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
|
||||
} else {
|
||||
if (src->hw_frames_ctx) {
|
||||
ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
|
||||
|
||||
ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else
|
||||
return AVERROR(ENOSYS);
|
||||
ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (dst->hw_frames_ctx) {
|
||||
ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
|
||||
|
||||
ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user