QSVScaleContext and VPPContext have the same base context, and all features in scale_qsv are implemented in vpp_qsv filter, so scale_qsv can be taken as a special case of vpp_qsv filter, and we may use VPPContext with a different option array, preinit callback and supported pixel formats to implement scale_qsv then remove QSVScaleContext
Showing the changes to libavfilter (3 of 3 files). Show all
Unified · Split
| @@ -446,7 +446,7 @@ OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o scale_eval.o · 445 unmodified lines | ||
| 446 | 446 | OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \ |
| 447 | 447 | vf_scale_cuda.ptx.o cuda/load_helper.o |
| 448 | 448 | OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o scale_eval.o |
| 449 | −OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o | |
| 449 | +OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_vpp_qsv.o | |
| 450 | 450 | OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o |
| 451 | 451 | OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o vulkan_filter.o |
| 452 | 452 | OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o |
| @@ -1,290 +0,0 @@ | ||
| 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 | −/** | |
| 20 | − * @file | |
| 21 | − * scale video filter - QSV | |
| 22 | − */ | |
| 23 | − | |
| 24 | −#include <mfxvideo.h> | |
| 25 | − | |
| 26 | −#include <stdio.h> | |
| 27 | −#include <string.h> | |
| 28 | − | |
| 29 | −#include "libavutil/avstring.h" | |
| 30 | −#include "libavutil/common.h" | |
| 31 | −#include "libavutil/eval.h" | |
| 32 | −#include "libavutil/hwcontext.h" | |
| 33 | −#include "libavutil/hwcontext_qsv.h" | |
| 34 | −#include "libavutil/internal.h" | |
| 35 | −#include "libavutil/mathematics.h" | |
| 36 | −#include "libavutil/opt.h" | |
| 37 | −#include "libavutil/pixdesc.h" | |
| 38 | −#include "libavutil/time.h" | |
| 39 | −#include "libavfilter/qsvvpp.h" | |
| 40 | − | |
| 41 | −#include "avfilter.h" | |
| 42 | −#include "formats.h" | |
| 43 | −#include "internal.h" | |
| 44 | −#include "video.h" | |
| 45 | − | |
| 46 | −static const char *const var_names[] = { | |
| 47 | − "in_w", "iw", | |
| 48 | − "in_h", "ih", | |
| 49 | − "out_w", "ow", | |
| 50 | − "out_h", "oh", | |
| 51 | − "a", "dar", | |
| 52 | − "sar", | |
| 53 | − NULL | |
| 54 | −}; | |
| 55 | − | |
| 56 | −enum var_name { | |
| 57 | − VAR_IN_W, VAR_IW, | |
| 58 | − VAR_IN_H, VAR_IH, | |
| 59 | − VAR_OUT_W, VAR_OW, | |
| 60 | − VAR_OUT_H, VAR_OH, | |
| 61 | − VAR_A, VAR_DAR, | |
| 62 | − VAR_SAR, | |
| 63 | − VARS_NB | |
| 64 | −}; | |
| 65 | − | |
| 66 | −#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) | |
| 67 | − | |
| 68 | −typedef struct QSVScaleContext { | |
| 69 | − QSVVPPContext qsv; | |
| 70 | − | |
| 71 | − mfxExtVPPScaling scale_conf; | |
| 72 | − int mode; | |
| 73 | − | |
| 74 | − /** | |
| 75 | − * New dimensions. Special values are: | |
| 76 | − * 0 = original width/height | |
| 77 | − * -1 = keep original aspect | |
| 78 | − */ | |
| 79 | − int w, h; | |
| 80 | − | |
| 81 | − /** | |
| 82 | − * Output sw format. AV_PIX_FMT_NONE for no conversion. | |
| 83 | − */ | |
| 84 | − enum AVPixelFormat format; | |
| 85 | − | |
| 86 | − char *w_expr; ///< width expression string | |
| 87 | − char *h_expr; ///< height expression string | |
| 88 | − char *format_str; | |
| 89 | −} QSVScaleContext; | |
| 90 | − | |
| 91 | −static av_cold int qsvscale_init(AVFilterContext *ctx) | |
| 92 | −{ | |
| 93 | − QSVScaleContext *s = ctx->priv; | |
| 94 | − | |
| 95 | − if (!strcmp(s->format_str, "same")) { | |
| 96 | − s->format = AV_PIX_FMT_NONE; | |
| 97 | − } else { | |
| 98 | − s->format = av_get_pix_fmt(s->format_str); | |
| 99 | − if (s->format == AV_PIX_FMT_NONE) { | |
| 100 | − av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str); | |
| 101 | − return AVERROR(EINVAL); | |
| 102 | − } | |
| 103 | − } | |
| 104 | − | |
| 105 | − return 0; | |
| 106 | −} | |
| 107 | − | |
| 108 | −static av_cold void qsvscale_uninit(AVFilterContext *ctx) | |
| 109 | −{ | |
| 110 | − ff_qsvvpp_close(ctx); | |
| 111 | −} | |
| 112 | − | |
| 113 | −static int qsvscale_config_props(AVFilterLink *outlink) | |
| 114 | −{ | |
| 115 | − AVFilterContext *ctx = outlink->src; | |
| 116 | − AVFilterLink *inlink = outlink->src->inputs[0]; | |
| 117 | − QSVScaleContext *s = ctx->priv; | |
| 118 | − QSVVPPParam param = { NULL }; | |
| 119 | − mfxExtBuffer *ext_buf[1]; | |
| 120 | − int64_t w, h; | |
| 121 | − double var_values[VARS_NB], res; | |
| 122 | − char *expr; | |
| 123 | − int ret; | |
| 124 | − enum AVPixelFormat in_format; | |
| 125 | − | |
| 126 | − var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; | |
| 127 | − var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; | |
| 128 | − var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; | |
| 129 | − var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; | |
| 130 | − var_values[VAR_A] = (double) inlink->w / inlink->h; | |
| 131 | − var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? | |
| 132 | − (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; | |
| 133 | − var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; | |
| 134 | − | |
| 135 | − /* evaluate width and height */ | |
| 136 | − av_expr_parse_and_eval(&res, (expr = s->w_expr), | |
| 137 | − var_names, var_values, | |
| 138 | − NULL, NULL, NULL, NULL, NULL, 0, ctx); | |
| 139 | − s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; | |
| 140 | − if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr), | |
| 141 | − var_names, var_values, | |
| 142 | − NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) | |
| 143 | − goto fail; | |
| 144 | − s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; | |
| 145 | − /* evaluate again the width, as it may depend on the output height */ | |
| 146 | − if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), | |
| 147 | − var_names, var_values, | |
| 148 | − NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) | |
| 149 | − goto fail; | |
| 150 | − s->w = res; | |
| 151 | − | |
| 152 | − w = s->w; | |
| 153 | − h = s->h; | |
| 154 | − | |
| 155 | − /* sanity check params */ | |
| 156 | − if (w < -1 || h < -1) { | |
| 157 | − av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); | |
| 158 | − return AVERROR(EINVAL); | |
| 159 | − } | |
| 160 | − if (w == -1 && h == -1) | |
| 161 | − s->w = s->h = 0; | |
| 162 | − | |
| 163 | − if (!(w = s->w)) | |
| 164 | − w = inlink->w; | |
| 165 | − if (!(h = s->h)) | |
| 166 | − h = inlink->h; | |
| 167 | − if (w == -1) | |
| 168 | − w = av_rescale(h, inlink->w, inlink->h); | |
| 169 | − if (h == -1) | |
| 170 | − h = av_rescale(w, inlink->h, inlink->w); | |
| 171 | − | |
| 172 | − if (w > INT_MAX || h > INT_MAX || | |
| 173 | − (h * inlink->w) > INT_MAX || | |
| 174 | − (w * inlink->h) > INT_MAX) | |
| 175 | − av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); | |
| 176 | − | |
| 177 | − outlink->w = w; | |
| 178 | − outlink->h = h; | |
| 179 | − | |
| 180 | − if (inlink->format == AV_PIX_FMT_QSV) { | |
| 181 | − if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) | |
| 182 | − return AVERROR(EINVAL); | |
| 183 | − else | |
| 184 | − in_format = ((AVHWFramesContext*)inlink->hw_frames_ctx->data)->sw_format; | |
| 185 | − } else | |
| 186 | − in_format = inlink->format; | |
| 187 | − | |
| 188 | − if (s->format == AV_PIX_FMT_NONE) | |
| 189 | − s->format = in_format; | |
| 190 | − | |
| 191 | − outlink->frame_rate = inlink->frame_rate; | |
| 192 | − outlink->time_base = av_inv_q(inlink->frame_rate); | |
| 193 | − param.out_sw_format = s->format; | |
| 194 | − | |
| 195 | − param.ext_buf = ext_buf; | |
| 196 | − memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling)); | |
| 197 | − s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; | |
| 198 | − s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); | |
| 199 | − s->scale_conf.ScalingMode = s->mode; | |
| 200 | − param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf; | |
| 201 | − av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode); | |
| 202 | − | |
| 203 | − ret = ff_qsvvpp_init(ctx, ¶m); | |
| 204 | − if (ret < 0) | |
| 205 | − return ret; | |
| 206 | − | |
| 207 | − av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n", | |
| 208 | − inlink->w, inlink->h, outlink->w, outlink->h); | |
| 209 | − | |
| 210 | − if (inlink->sample_aspect_ratio.num) | |
| 211 | − outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, | |
| 212 | − outlink->w*inlink->h}, | |
| 213 | − inlink->sample_aspect_ratio); | |
| 214 | − else | |
| 215 | − outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | |
| 216 | − | |
| 217 | − return 0; | |
| 218 | − | |
| 219 | −fail: | |
| 220 | − av_log(ctx, AV_LOG_ERROR, | |
| 221 | − "Error when evaluating the expression '%s'\n", expr); | |
| 222 | − return ret; | |
| 223 | −} | |
| 224 | − | |
| 225 | −static int qsvscale_filter_frame(AVFilterLink *link, AVFrame *in) | |
| 226 | −{ | |
| 227 | − int ret = 0; | |
| 228 | − AVFilterContext *ctx = link->dst; | |
| 229 | − QSVVPPContext *qsv = ctx->priv; | |
| 230 | − | |
| 231 | − ret = ff_qsvvpp_filter_frame(qsv, link, in); | |
| 232 | − av_frame_free(&in); | |
| 233 | − return ret; | |
| 234 | −} | |
| 235 | − | |
| 236 | −#define OFFSET(x) offsetof(QSVScaleContext, x) | |
| 237 | −#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | |
| 238 | −static const AVOption options[] = { | |
| 239 | − { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, | |
| 240 | − { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, | |
| 241 | − { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, | |
| 242 | − | |
| 243 | − { "mode", "set scaling mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, | |
| 244 | − { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"}, | |
| 245 | − { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"}, | |
| 246 | − | |
| 247 | − { NULL }, | |
| 248 | −}; | |
| 249 | − | |
| 250 | −static const AVClass qsvscale_class = { | |
| 251 | − .class_name = "scale_qsv", | |
| 252 | − .item_name = av_default_item_name, | |
| 253 | − .option = options, | |
| 254 | − .version = LIBAVUTIL_VERSION_INT, | |
| 255 | −}; | |
| 256 | − | |
| 257 | −static const AVFilterPad qsvscale_inputs[] = { | |
| 258 | − { | |
| 259 | − .name = "default", | |
| 260 | − .type = AVMEDIA_TYPE_VIDEO, | |
| 261 | − .filter_frame = qsvscale_filter_frame, | |
| 262 | − .get_buffer.video = ff_qsvvpp_get_video_buffer, | |
| 263 | − }, | |
| 264 | −}; | |
| 265 | − | |
| 266 | −static const AVFilterPad qsvscale_outputs[] = { | |
| 267 | − { | |
| 268 | − .name = "default", | |
| 269 | − .type = AVMEDIA_TYPE_VIDEO, | |
| 270 | − .config_props = qsvscale_config_props, | |
| 271 | − }, | |
| 272 | −}; | |
| 273 | − | |
| 274 | −const AVFilter ff_vf_scale_qsv = { | |
| 275 | − .name = "scale_qsv", | |
| 276 | − .description = NULL_IF_CONFIG_SMALL("QuickSync video scaling and format conversion"), | |
| 277 | − | |
| 278 | − .init = qsvscale_init, | |
| 279 | − .uninit = qsvscale_uninit, | |
| 280 | − | |
| 281 | − .priv_size = sizeof(QSVScaleContext), | |
| 282 | − .priv_class = &qsvscale_class, | |
| 283 | − | |
| 284 | − FILTER_INPUTS(qsvscale_inputs), | |
| 285 | − FILTER_OUTPUTS(qsvscale_outputs), | |
| 286 | − | |
| 287 | − FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV), | |
| 288 | − | |
| 289 | − .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, | |
| 290 | −}; | |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | #include <float.h> |
| 25 | 25 | |
| 26 | +#include "config_components.h" | |
| 27 | + | |
| 26 | 28 | #include "libavutil/opt.h" |
| 27 | 29 | #include "libavutil/eval.h" |
| 28 | 30 | #include "libavutil/hwcontext.h" |
| @@ -101,48 +103,6 @@ typedef struct VPPContext{ · 72 unmodified lines | ||
| 101 | 103 | int has_passthrough; /* apply pass through mode if possible */ |
| 102 | 104 | } VPPContext; |
| 103 | 105 | |
| 104 | −static const AVOption options[] = { | |
| 105 | − { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced", OFFSET(deinterlace), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MFX_DEINTERLACING_ADVANCED, .flags = FLAGS, "deinterlace" }, | |
| 106 | − { "bob", "Bob deinterlace mode.", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_BOB }, .flags = FLAGS, "deinterlace" }, | |
| 107 | − { "advanced", "Advanced deinterlace mode. ", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_ADVANCED }, .flags = FLAGS, "deinterlace" }, | |
| 108 | − | |
| 109 | − { "denoise", "denoise level [0, 100]", OFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, | |
| 110 | − { "detail", "enhancement level [0, 100]", OFFSET(detail), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, | |
| 111 | − { "framerate", "output framerate", OFFSET(framerate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 },0, DBL_MAX, .flags = FLAGS }, | |
| 112 | − { "procamp", "Enable ProcAmp", OFFSET(procamp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS}, | |
| 113 | − { "hue", "ProcAmp hue", OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -180.0, 180.0, .flags = FLAGS}, | |
| 114 | − { "saturation", "ProcAmp saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, | |
| 115 | − { "contrast", "ProcAmp contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, | |
| 116 | − { "brightness", "ProcAmp brightness", OFFSET(brightness), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -100.0, 100.0, .flags = FLAGS}, | |
| 117 | − | |
| 118 | − { "transpose", "set transpose direction", OFFSET(transpose), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, FLAGS, "transpose"}, | |
| 119 | − { "cclock_hflip", "rotate counter-clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 120 | − { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "transpose" }, | |
| 121 | − { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "transpose" }, | |
| 122 | − { "clock_hflip", "rotate clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 123 | − { "reversal", "rotate by half-turn", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "transpose" }, | |
| 124 | − { "hflip", "flip horizontally", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 125 | − { "vflip", "flip vertically", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 126 | − | |
| 127 | − { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, 0, 0, FLAGS }, | |
| 128 | − { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, 0, 0, FLAGS }, | |
| 129 | − { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, 0, 0, FLAGS }, | |
| 130 | − { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, 0, 0, FLAGS }, | |
| 131 | − | |
| 132 | − { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, | |
| 133 | − { "width", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, | |
| 134 | − { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, | |
| 135 | − { "height", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, | |
| 136 | − { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, | |
| 137 | − { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, | |
| 138 | − { "scale_mode", "scale & format conversion mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" }, | |
| 139 | − { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, | |
| 140 | − { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, | |
| 141 | − { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, | |
| 142 | − | |
| 143 | − { NULL } | |
| 144 | −}; | |
| 145 | − | |
| 146 | 106 | static const char *const var_names[] = { |
| 147 | 107 | "iw", "in_w", |
| 148 | 108 | "ih", "in_h", |
| @@ -633,6 +593,30 @@ eof: · 484 unmodified lines | ||
| 633 | 593 | return 0; |
| 634 | 594 | } |
| 635 | 595 | |
| 596 | +static av_cold void vpp_uninit(AVFilterContext *ctx) | |
| 597 | +{ | |
| 598 | + ff_qsvvpp_close(ctx); | |
| 599 | +} | |
| 600 | + | |
| 601 | +static const AVFilterPad vpp_inputs[] = { | |
| 602 | + { | |
| 603 | + .name = "default", | |
| 604 | + .type = AVMEDIA_TYPE_VIDEO, | |
| 605 | + .config_props = config_input, | |
| 606 | + .get_buffer.video = ff_qsvvpp_get_video_buffer, | |
| 607 | + }, | |
| 608 | +}; | |
| 609 | + | |
| 610 | +static const AVFilterPad vpp_outputs[] = { | |
| 611 | + { | |
| 612 | + .name = "default", | |
| 613 | + .type = AVMEDIA_TYPE_VIDEO, | |
| 614 | + .config_props = config_output, | |
| 615 | + }, | |
| 616 | +}; | |
| 617 | + | |
| 618 | +#if CONFIG_VPP_QSV_FILTER | |
| 619 | + | |
| 636 | 620 | static int query_formats(AVFilterContext *ctx) |
| 637 | 621 | { |
| 638 | 622 | int ret; |
| @@ -660,10 +644,47 @@ static int query_formats(AVFilterContext *ctx) · 21 unmodified lines | ||
| 660 | 644 | &ctx->outputs[0]->incfg.formats); |
| 661 | 645 | } |
| 662 | 646 | |
| 663 | −static av_cold void vpp_uninit(AVFilterContext *ctx) | |
| 664 | −{ | |
| 665 | − ff_qsvvpp_close(ctx); | |
| 666 | −} | |
| 647 | +static const AVOption options[] = { | |
| 648 | + { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced", OFFSET(deinterlace), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MFX_DEINTERLACING_ADVANCED, .flags = FLAGS, "deinterlace" }, | |
| 649 | + { "bob", "Bob deinterlace mode.", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_BOB }, .flags = FLAGS, "deinterlace" }, | |
| 650 | + { "advanced", "Advanced deinterlace mode. ", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_ADVANCED }, .flags = FLAGS, "deinterlace" }, | |
| 651 | + | |
| 652 | + { "denoise", "denoise level [0, 100]", OFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, | |
| 653 | + { "detail", "enhancement level [0, 100]", OFFSET(detail), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, | |
| 654 | + { "framerate", "output framerate", OFFSET(framerate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 },0, DBL_MAX, .flags = FLAGS }, | |
| 655 | + { "procamp", "Enable ProcAmp", OFFSET(procamp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS}, | |
| 656 | + { "hue", "ProcAmp hue", OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -180.0, 180.0, .flags = FLAGS}, | |
| 657 | + { "saturation", "ProcAmp saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, | |
| 658 | + { "contrast", "ProcAmp contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, | |
| 659 | + { "brightness", "ProcAmp brightness", OFFSET(brightness), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -100.0, 100.0, .flags = FLAGS}, | |
| 660 | + | |
| 661 | + { "transpose", "set transpose direction", OFFSET(transpose), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, FLAGS, "transpose"}, | |
| 662 | + { "cclock_hflip", "rotate counter-clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 663 | + { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "transpose" }, | |
| 664 | + { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "transpose" }, | |
| 665 | + { "clock_hflip", "rotate clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 666 | + { "reversal", "rotate by half-turn", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "transpose" }, | |
| 667 | + { "hflip", "flip horizontally", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 668 | + { "vflip", "flip vertically", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .flags=FLAGS, .unit = "transpose" }, | |
| 669 | + | |
| 670 | + { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, 0, 0, FLAGS }, | |
| 671 | + { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, 0, 0, FLAGS }, | |
| 672 | + { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, 0, 0, FLAGS }, | |
| 673 | + { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, 0, 0, FLAGS }, | |
| 674 | + | |
| 675 | + { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, | |
| 676 | + { "width", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, | |
| 677 | + { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, | |
| 678 | + { "height", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, | |
| 679 | + { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, | |
| 680 | + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, | |
| 681 | + { "scale_mode", "scale & format conversion mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" }, | |
| 682 | + { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, | |
| 683 | + { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, | |
| 684 | + { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, | |
| 685 | + | |
| 686 | + { NULL } | |
| 687 | +}; | |
| 667 | 688 | |
| 668 | 689 | static const AVClass vpp_class = { |
| 669 | 690 | .class_name = "vpp_qsv", |
| @@ -672,23 +693,6 @@ static const AVClass vpp_class = { · 2 unmodified lines | ||
| 672 | 693 | .version = LIBAVUTIL_VERSION_INT, |
| 673 | 694 | }; |
| 674 | 695 | |
| 675 | −static const AVFilterPad vpp_inputs[] = { | |
| 676 | − { | |
| 677 | − .name = "default", | |
| 678 | − .type = AVMEDIA_TYPE_VIDEO, | |
| 679 | − .config_props = config_input, | |
| 680 | − .get_buffer.video = ff_qsvvpp_get_video_buffer, | |
| 681 | − }, | |
| 682 | −}; | |
| 683 | − | |
| 684 | −static const AVFilterPad vpp_outputs[] = { | |
| 685 | − { | |
| 686 | − .name = "default", | |
| 687 | − .type = AVMEDIA_TYPE_VIDEO, | |
| 688 | − .config_props = config_output, | |
| 689 | − }, | |
| 690 | −}; | |
| 691 | − | |
| 692 | 696 | const AVFilter ff_vf_vpp_qsv = { |
| 693 | 697 | .name = "vpp_qsv", |
| 694 | 698 | .description = NULL_IF_CONFIG_SMALL("Quick Sync Video VPP."), |
| @@ -703,3 +707,59 @@ const AVFilter ff_vf_vpp_qsv = { · 8 unmodified lines | ||
| 703 | 707 | .priv_class = &vpp_class, |
| 704 | 708 | .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, |
| 705 | 709 | }; |
| 710 | + | |
| 711 | +#endif | |
| 712 | + | |
| 713 | +#if CONFIG_SCALE_QSV_FILTER | |
| 714 | + | |
| 715 | +static const AVOption qsvscale_options[] = { | |
| 716 | + { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, | |
| 717 | + { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, | |
| 718 | + { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, | |
| 719 | + | |
| 720 | + { "mode", "set scaling mode", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, | |
| 721 | + { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"}, | |
| 722 | + { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"}, | |
| 723 | + | |
| 724 | + { NULL }, | |
| 725 | +}; | |
| 726 | + | |
| 727 | +static av_cold int qsvscale_preinit(AVFilterContext *ctx) | |
| 728 | +{ | |
| 729 | + VPPContext *vpp = ctx->priv; | |
| 730 | + | |
| 731 | + vpp_preinit(ctx); | |
| 732 | + vpp->has_passthrough = 0; | |
| 733 | + | |
| 734 | + return 0; | |
| 735 | +} | |
| 736 | + | |
| 737 | +static const AVClass qsvscale_class = { | |
| 738 | + .class_name = "scale_qsv", | |
| 739 | + .item_name = av_default_item_name, | |
| 740 | + .option = qsvscale_options, | |
| 741 | + .version = LIBAVUTIL_VERSION_INT, | |
| 742 | +}; | |
| 743 | + | |
| 744 | +const AVFilter ff_vf_scale_qsv = { | |
| 745 | + .name = "scale_qsv", | |
| 746 | + .description = NULL_IF_CONFIG_SMALL("Quick Sync Video scaling and format conversion"), | |
| 747 | + | |
| 748 | + .preinit = qsvscale_preinit, | |
| 749 | + .init = vpp_init, | |
| 750 | + .uninit = vpp_uninit, | |
| 751 | + | |
| 752 | + .priv_size = sizeof(VPPContext), | |
| 753 | + .priv_class = &qsvscale_class, | |
| 754 | + | |
| 755 | + FILTER_INPUTS(vpp_inputs), | |
| 756 | + FILTER_OUTPUTS(vpp_outputs), | |
| 757 | + | |
| 758 | + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV), | |
| 759 | + | |
| 760 | + .activate = activate, | |
| 761 | + | |
| 762 | + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, | |
| 763 | +}; | |
| 764 | + | |
| 765 | +#endif | |