On 20/02/17 06:16, wm4 wrote: > On Sun, 19 Feb 2017 18:46:33 +0000 > Mark Thompson <[email protected]> wrote: > >> Also refactor a little and improve error messages to make failure >> cases easier to understand. >> --- >> libavfilter/vf_hwmap.c | 67 >> +++++++++++++++++++++++++++++++++++++++----------- >> 1 file changed, 52 insertions(+), 15 deletions(-) >> >> diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c >> index 11595bd6c..6e890dae3 100644 >> --- a/libavfilter/vf_hwmap.c >> +++ b/libavfilter/vf_hwmap.c >> @@ -34,6 +34,7 @@ typedef struct HWMapContext { >> AVBufferRef *hwframes_ref; >> >> int mode; >> + char *derive_device_type; >> int map_backwards; >> } HWMapContext; >> >> @@ -52,6 +53,7 @@ static int hwmap_config_output(AVFilterLink *outlink) >> HWMapContext *ctx = avctx->priv; >> AVFilterLink *inlink = avctx->inputs[0]; >> AVHWFramesContext *hwfc; >> + AVBufferRef *device; >> const AVPixFmtDescriptor *desc; >> int err; >> >> @@ -59,30 +61,61 @@ static int hwmap_config_output(AVFilterLink *outlink) >> av_get_pix_fmt_name(inlink->format), >> av_get_pix_fmt_name(outlink->format)); >> >> + av_buffer_unref(&ctx->hwframes_ref); >> + av_buffer_unref(&ctx->hwdevice_ref); >> + >> + device = avctx->hw_device_ctx; >> + >> if (inlink->hw_frames_ctx) { >> hwfc = (AVHWFramesContext*)inlink->hw_frames_ctx->data; >> >> + if (ctx->derive_device_type) { >> + enum AVHWDeviceType type; >> + >> + type = av_hwdevice_find_type_by_name(ctx->derive_device_type); >> + if (type == -1) { >> + av_log(avctx, AV_LOG_ERROR, "Invalid device type.\n"); >> + goto fail; >> + } >> + >> + err = av_hwdevice_ctx_create_derived(&ctx->hwdevice_ref, type, >> + hwfc->device_ref, 0); >> + if (err < 0) { >> + av_log(avctx, AV_LOG_ERROR, "Failed to created derived " >> + "device context: %d.\n", err); >> + goto fail; >> + } >> + >> + device = ctx->hwdevice_ref; >> + } >> + >> desc = av_pix_fmt_desc_get(outlink->format); >> - if (!desc) >> - return AVERROR(EINVAL); >> + if (!desc) { >> + err = AVERROR(EINVAL); >> + goto fail; >> + } >> >> if (inlink->format == hwfc->format && >> (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { >> // Map between two hardware formats (including the case of >> // undoing an existing mapping). >> >> - ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); >> - if (!ctx->hwdevice_ref) { >> - err = AVERROR(ENOMEM); >> + if (!device) { >> + av_log(avctx, AV_LOG_ERROR, "A device reference is " >> + "required to map to a hardware format.\n"); >> + err = AVERROR(EINVAL); >> goto fail; >> } >> >> err = av_hwframe_ctx_create_derived(&ctx->hwframes_ref, >> outlink->format, >> - ctx->hwdevice_ref, >> + device, >> inlink->hw_frames_ctx, 0); >> - if (err < 0) >> + if (err < 0) { >> + av_log(avctx, AV_LOG_ERROR, "Failed to create derived " >> + "frames context: %d.\n", err); >> goto fail; >> + } >> >> } else if ((outlink->format == hwfc->format && >> inlink->format == hwfc->sw_format) || >> @@ -90,8 +123,6 @@ static int hwmap_config_output(AVFilterLink *outlink) >> // Map from a hardware format to a software format, or >> // undo an existing such mapping. >> >> - ctx->hwdevice_ref = NULL; >> - >> ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx); >> if (!ctx->hwframes_ref) { >> err = AVERROR(ENOMEM); >> @@ -115,15 +146,17 @@ static int hwmap_config_output(AVFilterLink *outlink) >> // returns frames mapped from that to the previous link in >> // order to fill them without an additional copy. >> >> - ctx->map_backwards = 1; >> - >> - ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); >> - if (!ctx->hwdevice_ref) { >> - err = AVERROR(ENOMEM); >> + if (!device) { >> + av_log(avctx, AV_LOG_ERROR, "A device reference is " >> + "required to create new frames with backwards " >> + "mapping.\n"); >> + err = AVERROR(EINVAL); >> goto fail; >> } >> >> - ctx->hwframes_ref = av_hwframe_ctx_alloc(ctx->hwdevice_ref); >> + ctx->map_backwards = 1; >> + >> + ctx->hwframes_ref = av_hwframe_ctx_alloc(device); >> if (!ctx->hwframes_ref) { >> err = AVERROR(ENOMEM); >> goto fail; >> @@ -293,6 +326,10 @@ static const AVOption hwmap_options[] = { >> 0, AV_OPT_TYPE_CONST, { .i64 = AV_HWFRAME_MAP_DIRECT }, >> INT_MIN, INT_MAX, FLAGS, "mode" }, >> >> + { "derive_device", "Derive a new device of this type", >> + OFFSET(derive_device_type), AV_OPT_TYPE_STRING, >> + { .str = NULL }, 0, 0, FLAGS }, >> + >> { NULL }, >> }; >> > > Maybe I don't fully understand how this filter works, but doesn't it > already support derived frames contexts in git master? What's the > difference to derived device contexts?
It already supports derived frames contexts, but only to the single filter device (hw_device_ctx, or now -filter_hw_device). Deriving devices inside hwmap allows us to more magical things without having to make all the devices at the top level and pass them into lavfi. (Yes, I am using this to duck the multiple-devices-in-lavfi problem. I am not ashamed.) _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
