FFmpeg  4.4.6
vf_hwdownload.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/mem.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/pixdesc.h"
25 
26 #include "avfilter.h"
27 #include "formats.h"
28 #include "internal.h"
29 #include "video.h"
30 
31 typedef struct HWDownloadContext {
32  const AVClass *class;
33 
37 
39 {
40  AVFilterFormats *fmts;
41  int err;
42 
43  if ((err = ff_formats_pixdesc_filter(&fmts, AV_PIX_FMT_FLAG_HWACCEL, 0)) ||
44  (err = ff_formats_ref(fmts, &avctx->inputs[0]->outcfg.formats)) ||
46  (err = ff_formats_ref(fmts, &avctx->outputs[0]->incfg.formats)))
47  return err;
48 
49  return 0;
50 }
51 
53 {
54  AVFilterContext *avctx = inlink->dst;
55  HWDownloadContext *ctx = avctx->priv;
56 
57  av_buffer_unref(&ctx->hwframes_ref);
58 
59  if (!inlink->hw_frames_ctx) {
60  av_log(ctx, AV_LOG_ERROR, "The input must have a hardware frame "
61  "reference.\n");
62  return AVERROR(EINVAL);
63  }
64 
65  ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
66  if (!ctx->hwframes_ref)
67  return AVERROR(ENOMEM);
68 
69  ctx->hwframes = (AVHWFramesContext*)ctx->hwframes_ref->data;
70 
71  return 0;
72 }
73 
75 {
76  AVFilterContext *avctx = outlink->src;
77  AVFilterLink *inlink = avctx->inputs[0];
78  HWDownloadContext *ctx = avctx->priv;
79  enum AVPixelFormat *formats;
80  int err, i, found;
81 
82  if (!ctx->hwframes_ref)
83  return AVERROR(EINVAL);
84 
85  err = av_hwframe_transfer_get_formats(ctx->hwframes_ref,
87  &formats, 0);
88  if (err < 0)
89  return err;
90 
91  found = 0;
92  for (i = 0; formats[i] != AV_PIX_FMT_NONE; i++) {
93  if (formats[i] == outlink->format) {
94  found = 1;
95  break;
96  }
97  }
98  av_freep(&formats);
99 
100  if (!found) {
101  av_log(ctx, AV_LOG_ERROR, "Invalid output format %s for hwframe "
102  "download.\n", av_get_pix_fmt_name(outlink->format));
103  return AVERROR(EINVAL);
104  }
105 
106  outlink->w = inlink->w;
107  outlink->h = inlink->h;
108 
109  return 0;
110 }
111 
113 {
114  AVFilterContext *avctx = link->dst;
115  AVFilterLink *outlink = avctx->outputs[0];
116  HWDownloadContext *ctx = avctx->priv;
117  AVFrame *output = NULL;
118  int err;
119 
120  if (!ctx->hwframes_ref || !input->hw_frames_ctx) {
121  av_log(ctx, AV_LOG_ERROR, "Input frames must have hardware context.\n");
122  err = AVERROR(EINVAL);
123  goto fail;
124  }
125  if ((void*)ctx->hwframes != input->hw_frames_ctx->data) {
126  av_log(ctx, AV_LOG_ERROR, "Input frame is not the in the configured "
127  "hwframe context.\n");
128  err = AVERROR(EINVAL);
129  goto fail;
130  }
131 
132  output = ff_get_video_buffer(outlink, ctx->hwframes->width,
133  ctx->hwframes->height);
134  if (!output) {
135  err = AVERROR(ENOMEM);
136  goto fail;
137  }
138 
139  err = av_hwframe_transfer_data(output, input, 0);
140  if (err < 0) {
141  av_log(ctx, AV_LOG_ERROR, "Failed to download frame: %d.\n", err);
142  goto fail;
143  }
144 
145  output->width = outlink->w;
146  output->height = outlink->h;
147 
148  err = av_frame_copy_props(output, input);
149  if (err < 0)
150  goto fail;
151 
152  av_frame_free(&input);
153 
154  return ff_filter_frame(avctx->outputs[0], output);
155 
156 fail:
157  av_frame_free(&input);
158  av_frame_free(&output);
159  return err;
160 }
161 
163 {
164  HWDownloadContext *ctx = avctx->priv;
165 
166  av_buffer_unref(&ctx->hwframes_ref);
167 }
168 
169 static const AVClass hwdownload_class = {
170  .class_name = "hwdownload",
171  .item_name = av_default_item_name,
172  .option = NULL,
173  .version = LIBAVUTIL_VERSION_INT,
174 };
175 
176 static const AVFilterPad hwdownload_inputs[] = {
177  {
178  .name = "default",
179  .type = AVMEDIA_TYPE_VIDEO,
180  .config_props = hwdownload_config_input,
181  .filter_frame = hwdownload_filter_frame,
182  },
183  { NULL }
184 };
185 
186 static const AVFilterPad hwdownload_outputs[] = {
187  {
188  .name = "default",
189  .type = AVMEDIA_TYPE_VIDEO,
190  .config_props = hwdownload_config_output,
191  },
192  { NULL }
193 };
194 
196  .name = "hwdownload",
197  .description = NULL_IF_CONFIG_SMALL("Download a hardware frame to a normal frame"),
198  .uninit = hwdownload_uninit,
199  .query_formats = hwdownload_query_formats,
200  .priv_size = sizeof(HWDownloadContext),
201  .priv_class = &hwdownload_class,
204  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
205 };
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define av_cold
Definition: attributes.h:88
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
Main libavfilter public API header.
refcounted data buffer API
#define fail()
Definition: checkasm.h:133
#define NULL
Definition: coverity.c:32
int ff_formats_pixdesc_filter(AVFilterFormats **rfmts, unsigned want, unsigned rej)
Construct a formats list containing all pixel formats with certain properties.
Definition: formats.c:367
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add ref as a new reference to formats.
Definition: formats.c:466
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
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
#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:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats, int flags)
Get a list of possible source or target formats usable in av_hwframe_transfer_data().
Definition: hwcontext.c:385
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:443
@ AV_HWFRAME_TRANSFER_DIRECTION_FROM
Transfer the data from the queried hw frame.
Definition: hwcontext.h:419
int i
Definition: input.c:407
#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:339
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
Memory handling functions.
AVOptions.
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:2489
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:140
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
formats
Definition: signature.h:48
A reference to a data buffer.
Definition: buffer.h:84
uint8_t * data
The data buffer.
Definition: buffer.h:92
Describe the class of an AVClass context structure.
Definition: log.h:67
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
An instance of a filter.
Definition: avfilter.h:341
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:349
void * priv
private data for use by the filter
Definition: avfilter.h:356
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:353
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition: avfilter.h:445
A list of supported formats for one end of a filter link.
Definition: formats.h:65
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
int width
Definition: frame.h:376
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:657
int height
Definition: frame.h:376
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
AVBufferRef * hwframes_ref
Definition: vf_hwdownload.c:34
AVHWFramesContext * hwframes
Definition: vf_hwdownload.c:35
#define av_freep(p)
#define av_log(a,...)
AVFormatContext * ctx
Definition: movenc.c:48
static const AVClass hwdownload_class
static const AVFilterPad hwdownload_outputs[]
static int hwdownload_config_input(AVFilterLink *inlink)
Definition: vf_hwdownload.c:52
static int hwdownload_config_output(AVFilterLink *outlink)
Definition: vf_hwdownload.c:74
static av_cold void hwdownload_uninit(AVFilterContext *avctx)
static const AVFilterPad hwdownload_inputs[]
static int hwdownload_filter_frame(AVFilterLink *link, AVFrame *input)
AVFilter ff_vf_hwdownload
static int hwdownload_query_formats(AVFilterContext *avctx)
Definition: vf_hwdownload.c:38
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:104