FFmpeg  4.0
vf_procamp_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 #include <string.h>
19 
20 #include "libavutil/avassert.h"
21 #include "libavutil/mem.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 "vaapi_vpp.h"
29 
30 // ProcAmp Min/Max/Default Values
31 #define BRIGHTNESS_MIN -100.0F
32 #define BRIGHTNESS_MAX 100.0F
33 #define BRIGHTNESS_DEFAULT 0.0F
34 
35 #define CONTRAST_MIN 0.0F
36 #define CONTRAST_MAX 10.0F
37 #define CONTRAST_DEFAULT 1.0F
38 
39 #define HUE_MIN -180.0F
40 #define HUE_MAX 180.0F
41 #define HUE_DEFAULT 0.0F
42 
43 #define SATURATION_MIN 0.0F
44 #define SATURATION_MAX 10.0F
45 #define SATURATION_DEFAULT 1.0F
46 
47 typedef struct ProcampVAAPIContext {
48  VAAPIVPPContext vpp_ctx; // must be the first field
49 
50  float bright;
51  float hue;
52  float saturation;
53  float contrast;
55 
56 static float map(float x, float in_min, float in_max, float out_min, float out_max)
57 {
58  double slope, output;
59 
60  slope = 1.0 * (out_max - out_min) / (in_max - in_min);
61  output = out_min + slope * (x - in_min);
62 
63  return (float)output;
64 }
65 
67 {
68  VAAPIVPPContext *vpp_ctx = avctx->priv;
69  ProcampVAAPIContext *ctx = avctx->priv;
70  VAStatus vas;
71  VAProcFilterParameterBufferColorBalance procamp_params[4];
72  VAProcFilterCapColorBalance procamp_caps[VAProcColorBalanceCount];
73  int num_caps;
74  int i = 0;
75 
76  memset(&procamp_params, 0, sizeof(procamp_params));
77  memset(&procamp_caps, 0, sizeof(procamp_caps));
78 
79  num_caps = VAProcColorBalanceCount;
80  vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context,
81  VAProcFilterColorBalance, &procamp_caps, &num_caps);
82 
83  if (vas != VA_STATUS_SUCCESS) {
84  av_log(avctx, AV_LOG_ERROR, "Failed to query procamp "
85  "filter caps: %d (%s).\n", vas, vaErrorStr(vas));
86  return AVERROR(EIO);
87  }
88 
89  /* brightness */
90  procamp_params[i].type = VAProcFilterColorBalance;
91  procamp_params[i].attrib = VAProcColorBalanceBrightness;
92  procamp_params[i].value = map(ctx->bright, BRIGHTNESS_MIN, BRIGHTNESS_MAX,
93  procamp_caps[VAProcColorBalanceBrightness-1].range.min_value,
94  procamp_caps[VAProcColorBalanceBrightness-1].range.max_value);
95  i++;
96 
97  /* contrast */
98  procamp_params[i].type = VAProcFilterColorBalance;
99  procamp_params[i].attrib = VAProcColorBalanceContrast;
100  procamp_params[i].value = map(ctx->contrast, CONTRAST_MIN, CONTRAST_MAX,
101  procamp_caps[VAProcColorBalanceContrast-1].range.min_value,
102  procamp_caps[VAProcColorBalanceContrast-1].range.max_value);
103  i++;
104 
105  /* hue */
106  procamp_params[i].type = VAProcFilterColorBalance;
107  procamp_params[i].attrib = VAProcColorBalanceHue;
108  procamp_params[i].value = map(ctx->hue, HUE_MIN, HUE_MAX,
109  procamp_caps[VAProcColorBalanceHue-1].range.min_value,
110  procamp_caps[VAProcColorBalanceHue-1].range.max_value);
111  i++;
112 
113  /* saturation */
114  procamp_params[i].type = VAProcFilterColorBalance;
115  procamp_params[i].attrib = VAProcColorBalanceSaturation;
116  procamp_params[i].value = map(ctx->saturation, SATURATION_MIN, SATURATION_MAX,
117  procamp_caps[VAProcColorBalanceSaturation-1].range.min_value,
118  procamp_caps[VAProcColorBalanceSaturation-1].range.max_value);
119  i++;
120 
121  return ff_vaapi_vpp_make_param_buffers(avctx,
122  VAProcFilterParameterBufferType,
123  &procamp_params,
124  sizeof(procamp_params[0]),
125  i);
126 }
127 
128 static int procamp_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
129 {
130  AVFilterContext *avctx = inlink->dst;
131  AVFilterLink *outlink = avctx->outputs[0];
132  VAAPIVPPContext *vpp_ctx = avctx->priv;
134  VASurfaceID input_surface, output_surface;
135  VAProcPipelineParameterBuffer params;
136  VARectangle input_region;
137  int err;
138 
139  av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
140  av_get_pix_fmt_name(input_frame->format),
141  input_frame->width, input_frame->height, input_frame->pts);
142 
143  if (vpp_ctx->va_context == VA_INVALID_ID)
144  return AVERROR(EINVAL);
145 
146  input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
147  av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for procamp input.\n",
148  input_surface);
149 
150  output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,
151  vpp_ctx->output_height);
152  if (!output_frame) {
153  err = AVERROR(ENOMEM);
154  goto fail;
155  }
156 
157  output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];
158  av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for procamp output.\n",
159  output_surface);
160  memset(&params, 0, sizeof(params));
161  input_region = (VARectangle) {
162  .x = 0,
163  .y = 0,
164  .width = input_frame->width,
165  .height = input_frame->height,
166  };
167 
168  params.surface = input_surface;
169  params.surface_region = &input_region;
170  params.surface_color_standard =
172 
173  params.output_region = NULL;
174  params.output_background_color = 0xff000000;
175  params.output_color_standard = params.surface_color_standard;
176 
177  params.pipeline_flags = 0;
178  params.filter_flags = VA_FRAME_PICTURE;
179 
180  params.filters = &vpp_ctx->filter_buffers[0];
181  params.num_filters = 1;
182 
183  err = ff_vaapi_vpp_render_picture(avctx, &params, output_surface);
184  if (err < 0)
185  goto fail;
186 
187  err = av_frame_copy_props(output_frame, input_frame);
188  if (err < 0)
189  goto fail;
190  av_frame_free(&input_frame);
191 
192  av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n",
193  av_get_pix_fmt_name(output_frame->format),
194  output_frame->width, output_frame->height, output_frame->pts);
195 
196  return ff_filter_frame(outlink, output_frame);
197 
198 fail:
199  av_frame_free(&input_frame);
200  av_frame_free(&output_frame);
201  return err;
202 }
203 
205 {
206  VAAPIVPPContext *vpp_ctx = avctx->priv;
207 
208  ff_vaapi_vpp_ctx_init(avctx);
211  vpp_ctx->output_format = AV_PIX_FMT_NONE;
212 
213  return 0;
214 }
215 
216 #define OFFSET(x) offsetof(ProcampVAAPIContext, x)
217 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
218 static const AVOption procamp_vaapi_options[] = {
219  { "b", "Output video brightness",
221  { "brightness", "Output video brightness",
223  { "s", "Output video saturation",
225  { "saturatio", "Output video saturation",
227  { "c", "Output video contrast",
229  { "contrast", "Output video contrast",
231  { "h", "Output video hue",
232  OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = HUE_DEFAULT }, HUE_MIN, HUE_MAX, .flags = FLAGS },
233  { "hue", "Output video hue",
234  OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = HUE_DEFAULT }, HUE_MIN, HUE_MAX, .flags = FLAGS },
235  { NULL },
236 };
237 
238 AVFILTER_DEFINE_CLASS(procamp_vaapi);
239 
241  {
242  .name = "default",
243  .type = AVMEDIA_TYPE_VIDEO,
244  .filter_frame = &procamp_vaapi_filter_frame,
245  .config_props = &ff_vaapi_vpp_config_input,
246  },
247  { NULL }
248 };
249 
251  {
252  .name = "default",
253  .type = AVMEDIA_TYPE_VIDEO,
254  .config_props = &ff_vaapi_vpp_config_output,
255  },
256  { NULL }
257 };
258 
260  .name = "procamp_vaapi",
261  .description = NULL_IF_CONFIG_SMALL("ProcAmp (color balance) adjustments for hue, saturation, brightness, contrast"),
262  .priv_size = sizeof(ProcampVAAPIContext),
266  .inputs = procamp_vaapi_inputs,
267  .outputs = procamp_vaapi_outputs,
268  .priv_class = &procamp_vaapi_class,
269  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
270 };
#define NULL
Definition: coverity.c:32
#define CONTRAST_DEFAULT
#define HUE_MIN
#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:385
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
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.
#define HUE_DEFAULT
int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
Definition: vaapi_vpp.c:95
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
#define OFFSET(x)
const char * name
Pad name.
Definition: internal.h:60
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
static int procamp_vaapi_build_filter_params(AVFilterContext *avctx)
#define av_cold
Definition: attributes.h:82
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:279
AVOptions.
#define HUE_MAX
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:311
static float map(float x, float in_min, float in_max, float out_min, float out_max)
#define CONTRAST_MIN
#define BRIGHTNESS_MAX
#define av_log(a,...)
int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, VAProcPipelineParameterBuffer *params, VASurfaceID output_surface)
Definition: vaapi_vpp.c:280
A filter pad used for either input or output.
Definition: internal.h:54
int width
Definition: frame.h:276
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static int procamp_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
#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:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
#define SATURATION_MIN
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define SATURATION_MAX
enum AVColorSpace colorspace
YUV colorspace type.
Definition: frame.h:474
simple assert() macros that are a bit more flexible than ISO C assert().
static av_cold int procamp_vaapi_init(AVFilterContext *avctx)
#define BRIGHTNESS_DEFAULT
int ff_vaapi_vpp_make_param_buffers(AVFilterContext *avctx, int type, const void *data, size_t size, int count)
Definition: vaapi_vpp.c:251
#define fail()
Definition: checkasm.h:116
AVFilter ff_vf_procamp_vaapi
VAAPIVPPContext vpp_ctx
static const AVOption procamp_vaapi_options[]
void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx)
Definition: vaapi_vpp.c:44
static const AVFilterPad procamp_vaapi_outputs[]
AVFormatContext * ctx
Definition: movenc.c:48
AVFILTER_DEFINE_CLASS(procamp_vaapi)
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
#define CONTRAST_MAX
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
VADisplay display
The VADisplay handle, to be filled by the user.
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:291
#define FLAGS
VABufferID filter_buffers[VAProcFilterCount]
Definition: vaapi_vpp.h:47
static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
Definition: h264dec.c:836
Filter definition.
Definition: avfilter.h:144
const char * name
Filter name.
Definition: avfilter.h:148
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
VAContextID va_context
Definition: vaapi_vpp.h:38
enum AVPixelFormat output_format
Definition: vaapi_vpp.h:43
AVVAAPIDeviceContext * hwctx
Definition: vaapi_vpp.h:33
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
const char const char * params
Definition: avisynth_c.h:775
#define SATURATION_DEFAULT
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:351
static const AVFilterPad procamp_vaapi_inputs[]
int ff_vaapi_vpp_colour_standard(enum AVColorSpace av_cs)
Definition: vaapi_vpp.c:237
An instance of a filter.
Definition: avfilter.h:338
int height
Definition: frame.h:276
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:2279
int(* build_filter_params)(AVFilterContext *avctx)
Definition: vaapi_vpp.h:50
internal API functions
#define BRIGHTNESS_MIN
void(* pipeline_uninit)(AVFilterContext *avctx)
Definition: vaapi_vpp.h:52
void ff_vaapi_vpp_ctx_uninit(AVFilterContext *avctx)
Definition: vaapi_vpp.c:365
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:652