FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vf_hwmap.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "libavutil/buffer.h"
20 #include "libavutil/hwcontext.h"
21 #include "libavutil/log.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/pixdesc.h"
24 
25 #include "avfilter.h"
26 #include "formats.h"
27 #include "internal.h"
28 #include "video.h"
29 
30 typedef struct HWMapContext {
31  const AVClass *class;
32 
35 
36  int mode;
38 } HWMapContext;
39 
41 {
42  int ret;
43 
45  &avctx->inputs[0]->out_formats)) < 0 ||
47  &avctx->outputs[0]->in_formats)) < 0)
48  return ret;
49 
50  return 0;
51 }
52 
53 static int hwmap_config_output(AVFilterLink *outlink)
54 {
55  AVFilterContext *avctx = outlink->src;
56  HWMapContext *ctx = avctx->priv;
57  AVFilterLink *inlink = avctx->inputs[0];
58  AVHWFramesContext *hwfc;
59  const AVPixFmtDescriptor *desc;
60  int err;
61 
62  av_log(avctx, AV_LOG_DEBUG, "Configure hwmap %s -> %s.\n",
63  av_get_pix_fmt_name(inlink->format),
64  av_get_pix_fmt_name(outlink->format));
65 
66  if (inlink->hw_frames_ctx) {
67  hwfc = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
68 
69  desc = av_pix_fmt_desc_get(outlink->format);
70  if (!desc)
71  return AVERROR(EINVAL);
72 
73  if (inlink->format == hwfc->format &&
74  (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
75  // Map between two hardware formats (including the case of
76  // undoing an existing mapping).
77 
79  if (!ctx->hwdevice_ref) {
80  err = AVERROR(ENOMEM);
81  goto fail;
82  }
83 
85  outlink->format,
86  ctx->hwdevice_ref,
87  inlink->hw_frames_ctx, 0);
88  if (err < 0)
89  goto fail;
90 
91  } else if ((outlink->format == hwfc->format &&
92  inlink->format == hwfc->sw_format) ||
93  inlink->format == hwfc->format) {
94  // Map from a hardware format to a software format, or
95  // undo an existing such mapping.
96 
97  ctx->hwdevice_ref = NULL;
98 
100  if (!ctx->hwframes_ref) {
101  err = AVERROR(ENOMEM);
102  goto fail;
103  }
104 
105  } else {
106  // Non-matching formats - not supported.
107 
108  av_log(avctx, AV_LOG_ERROR, "Unsupported formats for "
109  "hwmap: from %s (%s) to %s.\n",
110  av_get_pix_fmt_name(inlink->format),
112  av_get_pix_fmt_name(outlink->format));
113  err = AVERROR(EINVAL);
114  goto fail;
115  }
116  } else if (avctx->hw_device_ctx) {
117  // Map from a software format to a hardware format. This
118  // creates a new hwframe context like hwupload, but then
119  // returns frames mapped from that to the previous link in
120  // order to fill them without an additional copy.
121 
122  ctx->map_backwards = 1;
123 
125  if (!ctx->hwdevice_ref) {
126  err = AVERROR(ENOMEM);
127  goto fail;
128  }
129 
131  if (!ctx->hwframes_ref) {
132  err = AVERROR(ENOMEM);
133  goto fail;
134  }
135  hwfc = (AVHWFramesContext*)ctx->hwframes_ref->data;
136 
137  hwfc->format = outlink->format;
138  hwfc->sw_format = inlink->format;
139  hwfc->width = inlink->w;
140  hwfc->height = inlink->h;
141 
142  err = av_hwframe_ctx_init(ctx->hwframes_ref);
143  if (err < 0) {
144  av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
145  "context for backward mapping: %d.\n", err);
146  goto fail;
147  }
148 
149  } else {
150  av_log(avctx, AV_LOG_ERROR, "Mapping requires a hardware "
151  "context (a device, or frames on input).\n");
152  return AVERROR(EINVAL);
153  }
154 
155  outlink->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
156  if (!outlink->hw_frames_ctx) {
157  err = AVERROR(ENOMEM);
158  goto fail;
159  }
160 
161  outlink->w = inlink->w;
162  outlink->h = inlink->h;
163 
164  return 0;
165 
166 fail:
169  return err;
170 }
171 
172 static AVFrame *hwmap_get_buffer(AVFilterLink *inlink, int w, int h)
173 {
174  AVFilterContext *avctx = inlink->dst;
175  AVFilterLink *outlink = avctx->outputs[0];
176  HWMapContext *ctx = avctx->priv;
177 
178  if (ctx->map_backwards) {
179  AVFrame *src, *dst;
180  int err;
181 
182  src = ff_get_video_buffer(outlink, w, h);
183  if (!src) {
184  av_log(avctx, AV_LOG_ERROR, "Failed to allocate source "
185  "frame for software mapping.\n");
186  return NULL;
187  }
188 
189  dst = av_frame_alloc();
190  if (!dst) {
191  av_frame_free(&src);
192  return NULL;
193  }
194 
195  err = av_hwframe_map(dst, src, ctx->mode);
196  if (err) {
197  av_log(avctx, AV_LOG_ERROR, "Failed to map frame to "
198  "software: %d.\n", err);
199  av_frame_free(&src);
200  av_frame_free(&dst);
201  return NULL;
202  }
203 
204  av_frame_free(&src);
205  return dst;
206  } else {
207  return ff_default_get_video_buffer(inlink, w, h);
208  }
209 }
210 
211 static int hwmap_filter_frame(AVFilterLink *link, AVFrame *input)
212 {
213  AVFilterContext *avctx = link->dst;
214  AVFilterLink *outlink = avctx->outputs[0];
215  HWMapContext *ctx = avctx->priv;
216  AVFrame *map = NULL;
217  int err;
218 
219  av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
220  av_get_pix_fmt_name(input->format),
221  input->width, input->height, input->pts);
222 
223  map = av_frame_alloc();
224  if (!map) {
225  err = AVERROR(ENOMEM);
226  goto fail;
227  }
228 
229  map->format = outlink->format;
231  if (!map->hw_frames_ctx) {
232  err = AVERROR(ENOMEM);
233  goto fail;
234  }
235 
236  if (ctx->map_backwards && !input->hw_frames_ctx) {
237  // If we mapped backwards from hardware to software, we need
238  // to attach the hardware frame context to the input frame to
239  // make the mapping visible to av_hwframe_map().
241  if (!input->hw_frames_ctx) {
242  err = AVERROR(ENOMEM);
243  goto fail;
244  }
245  }
246 
247  err = av_hwframe_map(map, input, ctx->mode);
248  if (err < 0) {
249  av_log(avctx, AV_LOG_ERROR, "Failed to map frame: %d.\n", err);
250  goto fail;
251  }
252 
253  err = av_frame_copy_props(map, input);
254  if (err < 0)
255  goto fail;
256 
257  av_frame_free(&input);
258 
259  av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n",
261  map->width, map->height, map->pts);
262 
263  return ff_filter_frame(outlink, map);
264 
265 fail:
266  av_frame_free(&input);
267  av_frame_free(&map);
268  return err;
269 }
270 
272 {
273  HWMapContext *ctx = avctx->priv;
274 
277 }
278 
279 #define OFFSET(x) offsetof(HWMapContext, x)
280 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
281 static const AVOption hwmap_options[] = {
282  { "mode", "Frame mapping mode",
285  0, INT_MAX, FLAGS, "mode" },
286 
287  { "read", "Mapping should be readable",
288  0, AV_OPT_TYPE_CONST, { .i64 = AV_HWFRAME_MAP_READ },
289  INT_MIN, INT_MAX, FLAGS, "mode" },
290  { "write", "Mapping should be writeable",
292  INT_MIN, INT_MAX, FLAGS, "mode" },
293  { "overwrite", "Mapping will always overwrite the entire frame",
295  INT_MIN, INT_MAX, FLAGS, "mode" },
296  { "direct", "Mapping should not involve any copying",
298  INT_MIN, INT_MAX, FLAGS, "mode" },
299 
300  { NULL }
301 };
302 
303 AVFILTER_DEFINE_CLASS(hwmap);
304 
305 static const AVFilterPad hwmap_inputs[] = {
306  {
307  .name = "default",
308  .type = AVMEDIA_TYPE_VIDEO,
309  .get_video_buffer = hwmap_get_buffer,
310  .filter_frame = hwmap_filter_frame,
311  },
312  { NULL }
313 };
314 
315 static const AVFilterPad hwmap_outputs[] = {
316  {
317  .name = "default",
318  .type = AVMEDIA_TYPE_VIDEO,
319  .config_props = hwmap_config_output,
320  },
321  { NULL }
322 };
323 
325  .name = "hwmap",
326  .description = NULL_IF_CONFIG_SMALL("Map hardware frames"),
327  .uninit = hwmap_uninit,
328  .priv_size = sizeof(HWMapContext),
329  .priv_class = &hwmap_class,
331  .inputs = hwmap_inputs,
332  .outputs = hwmap_outputs,
333  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
334 };
#define NULL
Definition: coverity.c:32
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition: internal.h:393
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2333
This structure describes decoded (raw) audio or video data.
Definition: frame.h:187
AVOption.
Definition: opt.h:246
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:454
The mapping must be writeable.
Definition: hwcontext.h:448
static int hwmap_filter_frame(AVFilterLink *link, AVFrame *input)
Definition: vf_hwmap.c:211
Main libavfilter public API header.
const char * desc
Definition: nvenc.c:60
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:222
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in...
Definition: avfilter.h:379
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:202
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:92
static av_cold void hwmap_uninit(AVFilterContext *avctx)
Definition: vf_hwmap.c:271
#define src
Definition: vp8dsp.c:254
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:515
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:331
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1125
int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, enum AVPixelFormat format, AVBufferRef *derived_device_ctx, AVBufferRef *source_frame_ctx, int flags)
Create and initialise an AVHWFramesContext as a mapping of another existing AVHWFramesContext on a di...
Definition: hwcontext.c:663
#define av_cold
Definition: attributes.h:82
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:150
AVOptions.
static int hwmap_query_formats(AVFilterContext *avctx)
Definition: vf_hwmap.c:40
AVFILTER_DEFINE_CLASS(hwmap)
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:271
static const AVOption hwmap_options[]
Definition: vf_hwmap.c:281
static const AVFilterPad hwmap_inputs[]
Definition: vf_hwmap.c:305
#define av_log(a,...)
AVFilterFormats * ff_all_formats(enum AVMediaType type)
Return a list of all formats supported by FFmpeg for the given media type.
Definition: formats.c:350
A filter pad used for either input or output.
Definition: internal.h:54
int width
width and height of the video frame
Definition: frame.h:239
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVBufferRef * hwframes_ref
Definition: vf_hwmap.c:34
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:163
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:179
void * priv
private data for use by the filter
Definition: avfilter.h:338
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:140
#define OFFSET(x)
Definition: vf_hwmap.c:279
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:268
#define fail()
Definition: checkasm.h:89
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
int map_backwards
Definition: vf_hwmap.c:37
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:440
AVFormatContext * ctx
Definition: movenc.c:48
#define FLAGS
Definition: vf_hwmap.c:280
static const AVFilterPad outputs[]
Definition: af_afftfilt.c:386
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:251
static AVFrame * hwmap_get_buffer(AVFilterLink *inlink, int w, int h)
Definition: vf_hwmap.c:172
static const AVFilterPad inputs[]
Definition: af_afftfilt.c:376
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
uint8_t * data
The data buffer.
Definition: buffer.h:89
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:117
AVBufferRef * hwdevice_ref
Definition: vf_hwmap.c:33
refcounted data buffer API
const char * name
Filter name.
Definition: avfilter.h:148
const VDPAUPixFmtMap * map
static const AVFilterPad hwmap_outputs[]
Definition: vf_hwmap.c:315
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:335
The mapping must be readable.
Definition: hwcontext.h:444
AVFrame * ff_default_get_video_buffer(AVFilterLink *link, int w, int h)
Definition: video.c:44
static int hwmap_config_output(AVFilterLink *outlink)
Definition: vf_hwmap.c:53
AVFilter ff_vf_hwmap
Definition: vf_hwmap.c:324
A reference to a data buffer.
Definition: buffer.h:81
static int query_formats(AVFilterContext *ctx)
Definition: aeval.c:244
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:605
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:182
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
The mapping must be direct.
Definition: hwcontext.h:460
An instance of a filter.
Definition: avfilter.h:323
int height
Definition: frame.h:239
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2249
internal API functions
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:215
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:596