FFmpeg  4.3.8
vf_scale_vaapi.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 <string.h>
20 
21 #include "libavutil/avassert.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 "scale_eval.h"
30 #include "video.h"
31 #include "vaapi_vpp.h"
32 
33 typedef struct ScaleVAAPIContext {
34  VAAPIVPPContext vpp_ctx; // must be the first field
35 
37 
38  int mode;
39 
40  char *w_expr; // width expression string
41  char *h_expr; // height expression string
42 
45 
51 
57 
58 static const char *scale_vaapi_mode_name(int mode)
59 {
60  switch (mode) {
61 #define D(name) case VA_FILTER_SCALING_ ## name: return #name
62  D(DEFAULT);
63  D(FAST);
64  D(HQ);
65  D(NL_ANAMORPHIC);
66 #undef D
67  default:
68  return "Invalid";
69  }
70 }
71 
72 
74 {
75  AVFilterLink *inlink = outlink->src->inputs[0];
76  AVFilterContext *avctx = outlink->src;
77  VAAPIVPPContext *vpp_ctx = avctx->priv;
78  ScaleVAAPIContext *ctx = avctx->priv;
79  int err;
80 
81  if ((err = ff_scale_eval_dimensions(ctx,
82  ctx->w_expr, ctx->h_expr,
83  inlink, outlink,
84  &vpp_ctx->output_width, &vpp_ctx->output_height)) < 0)
85  return err;
86 
87  ff_scale_adjust_dimensions(inlink, &vpp_ctx->output_width, &vpp_ctx->output_height,
89 
90  err = ff_vaapi_vpp_config_output(outlink);
91  if (err < 0)
92  return err;
93 
94  if (inlink->sample_aspect_ratio.num)
95  outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio);
96  else
97  outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
98 
99  return 0;
100 }
101 
102 static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
103 {
104  AVFilterContext *avctx = inlink->dst;
105  AVFilterLink *outlink = avctx->outputs[0];
106  VAAPIVPPContext *vpp_ctx = avctx->priv;
107  ScaleVAAPIContext *ctx = avctx->priv;
109  VAProcPipelineParameterBuffer params;
110  int err;
111 
112  av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
113  av_get_pix_fmt_name(input_frame->format),
114  input_frame->width, input_frame->height, input_frame->pts);
115 
116  if (vpp_ctx->va_context == VA_INVALID_ID)
117  return AVERROR(EINVAL);
118 
119  output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,
120  vpp_ctx->output_height);
121  if (!output_frame) {
122  err = AVERROR(ENOMEM);
123  goto fail;
124  }
125 
126  err = av_frame_copy_props(output_frame, input_frame);
127  if (err < 0)
128  goto fail;
129 
131  output_frame->color_primaries = ctx->colour_primaries;
133  output_frame->color_trc = ctx->colour_transfer;
135  output_frame->colorspace = ctx->colour_matrix;
137  output_frame->color_range = ctx->colour_range;
139  output_frame->chroma_location = ctx->chroma_location;
140 
141  err = ff_vaapi_vpp_init_params(avctx, &params,
142  input_frame, output_frame);
143  if (err < 0)
144  goto fail;
145 
146  params.filter_flags |= ctx->mode;
147 
148  err = ff_vaapi_vpp_render_picture(avctx, &params, output_frame);
149  if (err < 0)
150  goto fail;
151 
152  av_frame_free(&input_frame);
153 
154  av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64"), mode: %s.\n",
155  av_get_pix_fmt_name(output_frame->format),
156  output_frame->width, output_frame->height, output_frame->pts,
158 
159  return ff_filter_frame(outlink, output_frame);
160 
161 fail:
162  av_frame_free(&input_frame);
163  av_frame_free(&output_frame);
164  return err;
165 }
166 
168 {
169  VAAPIVPPContext *vpp_ctx = avctx->priv;
170  ScaleVAAPIContext *ctx = avctx->priv;
171 
172  ff_vaapi_vpp_ctx_init(avctx);
174 
175  if (ctx->output_format_string) {
177  if (vpp_ctx->output_format == AV_PIX_FMT_NONE) {
178  av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n");
179  return AVERROR(EINVAL);
180  }
181  } else {
182  // Use the input format once that is configured.
183  vpp_ctx->output_format = AV_PIX_FMT_NONE;
184  }
185 
186 #define STRING_OPTION(var_name, func_name, default_value) do { \
187  if (ctx->var_name ## _string) { \
188  int var = av_ ## func_name ## _from_name(ctx->var_name ## _string); \
189  if (var < 0) { \
190  av_log(avctx, AV_LOG_ERROR, "Invalid %s.\n", #var_name); \
191  return AVERROR(EINVAL); \
192  } \
193  ctx->var_name = var; \
194  } else { \
195  ctx->var_name = default_value; \
196  } \
197  } while (0)
198 
203 
204  return 0;
205 }
206 
207 #define OFFSET(x) offsetof(ScaleVAAPIContext, x)
208 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
209 static const AVOption scale_vaapi_options[] = {
210  { "w", "Output video width",
211  OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = FLAGS },
212  { "h", "Output video height",
213  OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS },
214  { "format", "Output video format (software format of hardware frames)",
216  { "mode", "Scaling mode",
217  OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = VA_FILTER_SCALING_HQ },
218  0, VA_FILTER_SCALING_NL_ANAMORPHIC, FLAGS, "mode" },
219  { "default", "Use the default (depend on the driver) scaling algorithm",
220  0, AV_OPT_TYPE_CONST, { .i64 = VA_FILTER_SCALING_DEFAULT }, 0, 0, FLAGS, "mode" },
221  { "fast", "Use fast scaling algorithm",
222  0, AV_OPT_TYPE_CONST, { .i64 = VA_FILTER_SCALING_FAST }, 0, 0, FLAGS, "mode" },
223  { "hq", "Use high quality scaling algorithm",
224  0, AV_OPT_TYPE_CONST, { .i64 = VA_FILTER_SCALING_HQ }, 0, 0, FLAGS, "mode" },
225  { "nl_anamorphic", "Use nolinear anamorphic scaling algorithm",
226  0, AV_OPT_TYPE_CONST, { .i64 = VA_FILTER_SCALING_NL_ANAMORPHIC }, 0, 0, FLAGS, "mode" },
227 
228  // These colour properties match the ones of the same name in vf_scale.
229  { "out_color_matrix", "Output colour matrix coefficient set",
230  OFFSET(colour_matrix_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
231  { "out_range", "Output colour range",
234  { "full", "Full range",
235  0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" },
236  { "limited", "Limited range",
237  0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" },
238  { "jpeg", "Full range",
239  0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" },
240  { "mpeg", "Limited range",
241  0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" },
242  { "tv", "Limited range",
243  0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" },
244  { "pc", "Full range",
245  0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" },
246  // These colour properties are new here.
247  { "out_color_primaries", "Output colour primaries",
249  { .str = NULL }, .flags = FLAGS },
250  { "out_color_transfer", "Output colour transfer characteristics",
252  { .str = NULL }, .flags = FLAGS },
253  { "out_chroma_location", "Output chroma sample location",
255  { .str = NULL }, .flags = FLAGS },
256  { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" },
257  { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },
258  { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
259  { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
260  { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS },
261 
262  { NULL },
263 };
264 
265 AVFILTER_DEFINE_CLASS(scale_vaapi);
266 
267 static const AVFilterPad scale_vaapi_inputs[] = {
268  {
269  .name = "default",
270  .type = AVMEDIA_TYPE_VIDEO,
271  .filter_frame = &scale_vaapi_filter_frame,
272  .config_props = &ff_vaapi_vpp_config_input,
273  },
274  { NULL }
275 };
276 
278  {
279  .name = "default",
280  .type = AVMEDIA_TYPE_VIDEO,
281  .config_props = &scale_vaapi_config_output,
282  },
283  { NULL }
284 };
285 
287  .name = "scale_vaapi",
288  .description = NULL_IF_CONFIG_SMALL("Scale to/from VAAPI surfaces."),
289  .priv_size = sizeof(ScaleVAAPIContext),
293  .inputs = scale_vaapi_inputs,
294  .outputs = scale_vaapi_outputs,
295  .priv_class = &scale_vaapi_class,
296  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
297 };
#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:365
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
char * output_format_string
int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
Definition: vaapi_vpp.c:70
AVOption.
Definition: opt.h:246
Main libavfilter public API header.
Memory handling functions.
int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
Definition: vaapi_vpp.c:95
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int num
Numerator.
Definition: rational.h:59
AVFILTER_DEFINE_CLASS(scale_vaapi)
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
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition: pixfmt.h:480
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1075
#define DEFAULT
Definition: avdct.c:28
#define av_cold
Definition: attributes.h:88
VAAPIVPPContext vpp_ctx
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:279
AVFilter ff_vf_scale_vaapi
AVOptions.
AVColorSpace
YUV colorspace type.
Definition: pixfmt.h:509
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:393
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition: pixfmt.h:455
#define av_log(a,...)
static const AVOption scale_vaapi_options[]
A filter pad used for either input or output.
Definition: internal.h:54
static av_cold int scale_vaapi_init(AVFilterContext *avctx)
int width
Definition: frame.h:358
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
Definition: scale_eval.c:57
#define AVERROR(e)
Definition: error.h:43
char * colour_primaries_string
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
static int scale_vaapi_config_output(AVFilterLink *outlink)
void * priv
private data for use by the filter
Definition: avfilter.h:353
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: frame.h:544
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
enum AVColorSpace colorspace
YUV colorspace type.
Definition: frame.h:555
simple assert() macros that are a bit more flexible than ISO C assert().
char * colour_transfer_string
static const AVFilterPad scale_vaapi_inputs[]
#define fail()
Definition: checkasm.h:123
static const char * scale_vaapi_mode_name(int mode)
char * chroma_location_string
void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx)
Definition: vaapi_vpp.c:44
enum AVColorPrimaries colour_primaries
static const struct ColorPrimaries color_primaries[AVCOL_PRI_NB]
AVFormatContext * ctx
Definition: movenc.c:48
enum AVChromaLocation chroma_location
char * colour_matrix_string
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
the normal 2^n-1 "JPEG" YUV ranges
Definition: pixfmt.h:535
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:373
enum AVColorTransferCharacteristic colour_transfer
#define FLAGS
#define STRING_OPTION(var_name, func_name, default_value)
static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
Definition: h264dec.c:853
Filter definition.
Definition: avfilter.h:144
Rational number (pair of numerator and denominator).
Definition: rational.h:58
static const AVFilterPad scale_vaapi_outputs[]
const char * name
Filter name.
Definition: avfilter.h:148
enum AVChromaLocation chroma_location
Definition: frame.h:557
#define D(name)
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
VAContextID va_context
Definition: vaapi_vpp.h:41
enum AVPixelFormat output_format
Definition: vaapi_vpp.h:47
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
Definition: scale_eval.c:113
int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, VAProcPipelineParameterBuffer *params, AVFrame *output_frame)
Definition: vaapi_vpp.c:592
the normal 219*2^(n-8) "MPEG" YUV ranges
Definition: pixfmt.h:534
int ff_vaapi_vpp_query_formats(AVFilterContext *avctx)
Definition: vaapi_vpp.c:27
static int query_formats(AVFilterContext *ctx)
Definition: aeval.c:244
void ff_vaapi_vpp_ctx_init(AVFilterContext *avctx)
Definition: vaapi_vpp.c:666
#define OFFSET(x)
enum AVColorPrimaries color_primaries
Definition: frame.h:546
An instance of a filter.
Definition: avfilter.h:338
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
enum AVColorSpace colour_matrix
int height
Definition: frame.h:358
AVChromaLocation
Location of chroma samples.
Definition: pixfmt.h:554
enum AVColorTransferCharacteristic color_trc
Definition: frame.h:548
int ff_vaapi_vpp_init_params(AVFilterContext *avctx, VAProcPipelineParameterBuffer *params, const AVFrame *input_frame, AVFrame *output_frame)
Definition: vaapi_vpp.c:515
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:2477
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:2465
internal API functions
static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
void(* pipeline_uninit)(AVFilterContext *avctx)
Definition: vaapi_vpp.h:56
void ff_vaapi_vpp_ctx_uninit(AVFilterContext *avctx)
Definition: vaapi_vpp.c:680
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:659