[FFmpeg-devel] [PATCH 1/2] lavfi/vf_hwmap: make hwunmap from software frame work.
Ruiling Song
ruiling.song at intel.com
Thu Dec 13 03:50:03 EET 2018
This patch was used to fix the second hwmap filter issue:
[vaapi_frame] hwmap [software filters] hwmap [vaapi_frame]
For such case, we also need to allocate the hardware frame
and map it back to software.
Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
libavfilter/vf_hwmap.c | 125 +++++++++++++++++++++++++++++--------------------
1 file changed, 75 insertions(+), 50 deletions(-)
diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index 290559a..03cb325 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -50,6 +50,36 @@ static int hwmap_query_formats(AVFilterContext *avctx)
return 0;
}
+static int create_hwframe_context(HWMapContext *ctx, AVFilterContext *avctx,
+ AVBufferRef *device, int format,
+ int sw_format, int width, int height)
+{
+ int err;
+ AVHWFramesContext *frames;
+
+ ctx->hwframes_ref = av_hwframe_ctx_alloc(device);
+ if (!ctx->hwframes_ref) {
+ return AVERROR(ENOMEM);
+ }
+ frames = (AVHWFramesContext*)ctx->hwframes_ref->data;
+
+ frames->format = format;
+ frames->sw_format = sw_format;
+ frames->width = width;
+ frames->height = height;
+
+ if (avctx->extra_hw_frames >= 0)
+ frames->initial_pool_size = 2 + avctx->extra_hw_frames;
+
+ err = av_hwframe_ctx_init(ctx->hwframes_ref);
+ if (err < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
+ "target frames context: %d.\n", err);
+ return err;
+ }
+ return 0;
+}
+
static int hwmap_config_output(AVFilterLink *outlink)
{
AVFilterContext *avctx = outlink->src;
@@ -130,29 +160,11 @@ static int hwmap_config_output(AVFilterLink *outlink)
// overwrite the input hwframe context with a derived context
// mapped from that back to the source type.
AVBufferRef *source;
- AVHWFramesContext *frames;
-
- ctx->hwframes_ref = av_hwframe_ctx_alloc(device);
- if (!ctx->hwframes_ref) {
- err = AVERROR(ENOMEM);
+ err = create_hwframe_context(ctx, avctx, device, outlink->format,
+ hwfc->sw_format, hwfc->width,
+ hwfc->height);
+ if (err < 0)
goto fail;
- }
- frames = (AVHWFramesContext*)ctx->hwframes_ref->data;
-
- frames->format = outlink->format;
- frames->sw_format = hwfc->sw_format;
- frames->width = hwfc->width;
- frames->height = hwfc->height;
-
- if (avctx->extra_hw_frames >= 0)
- frames->initial_pool_size = 2 + avctx->extra_hw_frames;
-
- err = av_hwframe_ctx_init(ctx->hwframes_ref);
- if (err < 0) {
- av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
- "target frames context: %d.\n", err);
- goto fail;
- }
err = av_hwframe_ctx_create_derived(&source,
inlink->format,
@@ -175,10 +187,20 @@ static int hwmap_config_output(AVFilterLink *outlink)
inlink->hw_frames_ctx = source;
} else if ((outlink->format == hwfc->format &&
- inlink->format == hwfc->sw_format) ||
- inlink->format == hwfc->format) {
- // Map from a hardware format to a software format, or
- // undo an existing such mapping.
+ inlink->format == hwfc->sw_format)) {
+ // unmap a software frame back to hardware
+ ctx->reverse = 1;
+ // incase user does not provide filter device, use the device_ref
+ // from inlink
+ if (!device)
+ device = hwfc->device_ref;
+
+ err = create_hwframe_context(ctx, avctx, device, outlink->format,
+ inlink->format, inlink->w, inlink->h);
+ if (err < 0)
+ goto fail;
+ } else if (inlink->format == hwfc->format) {
+ // Map from a hardware format to a software format
ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
if (!ctx->hwframes_ref) {
@@ -212,29 +234,10 @@ static int hwmap_config_output(AVFilterLink *outlink)
}
ctx->reverse = 1;
-
- ctx->hwframes_ref = av_hwframe_ctx_alloc(device);
- if (!ctx->hwframes_ref) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
- hwfc = (AVHWFramesContext*)ctx->hwframes_ref->data;
-
- hwfc->format = outlink->format;
- hwfc->sw_format = inlink->format;
- hwfc->width = inlink->w;
- hwfc->height = inlink->h;
-
- if (avctx->extra_hw_frames >= 0)
- hwfc->initial_pool_size = 2 + avctx->extra_hw_frames;
-
- err = av_hwframe_ctx_init(ctx->hwframes_ref);
- if (err < 0) {
- av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
- "context for reverse mapping: %d.\n", err);
+ err = create_hwframe_context(ctx, avctx, device, outlink->format,
+ inlink->format, inlink->w, inlink->h);
+ if (err < 0)
goto fail;
- }
-
} else {
av_log(avctx, AV_LOG_ERROR, "Mapping requires a hardware "
"context (a device, or frames on input).\n");
@@ -266,8 +269,17 @@ static AVFrame *hwmap_get_buffer(AVFilterLink *inlink, int w, int h)
AVFilterContext *avctx = inlink->dst;
AVFilterLink *outlink = avctx->outputs[0];
HWMapContext *ctx = avctx->priv;
+ const AVPixFmtDescriptor *desc;
+
+ desc = av_pix_fmt_desc_get(inlink->format);
+ if (!desc) {
+ av_log(avctx, AV_LOG_ERROR, "Unknown pix format %d\n", inlink->format);
+ return NULL;
+ }
- if (ctx->reverse && !inlink->hw_frames_ctx) {
+ // if we are asking for software formats, we currently always
+ // allocate a hardware frame and map it reversely to software format.
+ if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
AVFrame *src, *dst;
int err;
@@ -306,12 +318,20 @@ static int hwmap_filter_frame(AVFilterLink *link, AVFrame *input)
AVFilterLink *outlink = avctx->outputs[0];
HWMapContext *ctx = avctx->priv;
AVFrame *map = NULL;
+ const AVPixFmtDescriptor *desc;
int err;
av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
av_get_pix_fmt_name(input->format),
input->width, input->height, input->pts);
+ desc = av_pix_fmt_desc_get(input->format);
+ if (!desc) {
+ av_log(avctx, AV_LOG_ERROR, "Unknown pix format %d\n", input->format);
+ err = AVERROR(EINVAL);
+ goto fail;
+ }
+
map = av_frame_alloc();
if (!map) {
err = AVERROR(ENOMEM);
@@ -319,7 +339,12 @@ static int hwmap_filter_frame(AVFilterLink *link, AVFrame *input)
}
map->format = outlink->format;
- map->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
+ // The software frame may be mapped in another frame context,
+ // so we also do the unmap in that frame context.
+ if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && input->hw_frames_ctx)
+ map->hw_frames_ctx = av_buffer_ref(input->hw_frames_ctx);
+ else
+ map->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
if (!map->hw_frames_ctx) {
err = AVERROR(ENOMEM);
goto fail;
--
2.7.4
More information about the ffmpeg-devel
mailing list