History

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.

Philip Langdale committed 7 years ago

Commit d7210ce1 parent d84a30e1 file · +43 −10Browse files

Unified · Split

libavutil/hwcontext.c+43−10
@@ -444,21 +444,54 @@ int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) · 443 unmodified lines
444444 if (!dst->buf[0])
445445 return transfer_data_alloc(dst, src, flags);
446446
447− if (src->hw_frames_ctx) {
448− ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
447+ /*
448+ * Hardware -> Hardware Transfer.
449+ * Unlike Software -> Hardware or Hardware -> Software, the transfer
450+ * function could be provided by either the src or dst, depending on
451+ * the specific combination of hardware.
452+ */
453+ if (src->hw_frames_ctx && dst->hw_frames_ctx) {
454+ AVHWFramesContext *src_ctx =
455+ (AVHWFramesContext*)src->hw_frames_ctx->data;
456+ AVHWFramesContext *dst_ctx =
457+ (AVHWFramesContext*)dst->hw_frames_ctx->data;
458+
459+ if (src_ctx->internal->source_frames) {
460+ av_log(src_ctx, AV_LOG_ERROR,
461+ "A device with a derived frame context cannot be used as "
462+ "the source of a HW -> HW transfer.");
463+ return AVERROR(ENOSYS);
464+ }
449465
450− ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
451− if (ret < 0)
452− return ret;
453− } else if (dst->hw_frames_ctx) {
454− ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
466+ if (dst_ctx->internal->source_frames) {
467+ av_log(src_ctx, AV_LOG_ERROR,
468+ "A device with a derived frame context cannot be used as "
469+ "the destination of a HW -> HW transfer.");
470+ return AVERROR(ENOSYS);
471+ }
455472
456− ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
473+ ret = src_ctx->internal->hw_type->transfer_data_from(src_ctx, dst, src);
474+ if (ret == AVERROR(ENOSYS))
475+ ret = dst_ctx->internal->hw_type->transfer_data_to(dst_ctx, dst, src);
457476 if (ret < 0)
458477 return ret;
459− } else
460− return AVERROR(ENOSYS);
478+ } else {
479+ if (src->hw_frames_ctx) {
480+ ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
481+
482+ ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
483+ if (ret < 0)
484+ return ret;
485+ } else if (dst->hw_frames_ctx) {
486+ ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
461487
488+ ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
489+ if (ret < 0)
490+ return ret;
491+ } else {
492+ return AVERROR(ENOSYS);
493+ }
494+ }
462495 return 0;
463496 }
464497

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t