static int query_formats(AVFilterContext *ctx)
{
AVFilterFormats *formats = NULL;
- int fmt, ret;
-
- for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
- if (!(desc->flags & (AV_PIX_FMT_FLAG_HWACCEL | AV_PIX_FMT_FLAG_BITSTREAM)) &&
- !((desc->log2_chroma_w || desc->log2_chroma_h) && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) &&
- (ret = ff_add_format(&formats, fmt)) < 0)
- return ret;
- }
+ int ret;
+ ret = ff_formats_pixdesc_filter(&formats, 0, AV_PIX_FMT_FLAG_BITSTREAM | FF_PIX_FMT_FLAG_SW_FLAT_SUB);
+ if (ret < 0)
+ return ret;
return ff_set_common_formats(ctx, formats);
}
s->var_values[VAR_POS] = NAN;
av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc);
- s->hsub = pix_desc->log2_chroma_w;
- s->vsub = pix_desc->log2_chroma_h;
- if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr),
- var_names, s->var_values,
- NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
- goto fail_expr;
+ if (pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+ s->hsub = 1;
+ s->vsub = 1;
+ } else {
+ s->hsub = pix_desc->log2_chroma_w;
+ s->vsub = pix_desc->log2_chroma_h;
+ }
+
+ av_expr_parse_and_eval(&res, (expr = s->w_expr),
+ var_names, s->var_values,
+ NULL, NULL, NULL, NULL, NULL, 0, ctx);
s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr),
var_names, s->var_values,
return 0;
fail_expr:
- av_log(NULL, AV_LOG_ERROR, "Error when evaluating the expression '%s'\n", expr);
+ av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'\n", expr);
return ret;
}
static int config_output(AVFilterLink *link)
{
CropContext *s = link->src->priv;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
- link->w = s->w;
- link->h = s->h;
+ if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+ // Hardware frames adjust the cropping regions rather than
+ // changing the frame size.
+ } else {
+ link->w = s->w;
+ link->h = s->h;
+ }
link->sample_aspect_ratio = s->out_sar;
return 0;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
int i;
- frame->width = s->w;
- frame->height = s->h;
-
s->var_values[VAR_N] = link->frame_count_out;
s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
NAN : frame->pts * av_q2d(link->time_base);
(int)s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS],
s->x, s->y, s->x+s->w, s->y+s->h);
- frame->data[0] += s->y * frame->linesize[0];
- frame->data[0] += s->x * s->max_step[0];
-
- if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & FF_PSEUDOPAL)) {
- for (i = 1; i < 3; i ++) {
- if (frame->data[i]) {
- frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
- frame->data[i] += (s->x * s->max_step[i]) >> s->hsub;
+ if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+ frame->crop_top += s->y;
+ frame->crop_left += s->x;
+ frame->crop_bottom = frame->height - frame->crop_top - frame->crop_bottom - s->h;
+ frame->crop_right = frame->width - frame->crop_left - frame->crop_right - s->w;
+ } else {
+ frame->width = s->w;
+ frame->height = s->h;
+
+ frame->data[0] += s->y * frame->linesize[0];
+ frame->data[0] += s->x * s->max_step[0];
+
+ if (!(desc->flags & AV_PIX_FMT_FLAG_PAL)) {
+ for (i = 1; i < 3; i ++) {
+ if (frame->data[i]) {
+ frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
+ frame->data[i] += (s->x * s->max_step[i]) >> s->hsub;
+ }
}
}
- }
- /* alpha plane */
- if (frame->data[3]) {
- frame->data[3] += s->y * frame->linesize[3];
- frame->data[3] += s->x * s->max_step[3];
+ /* alpha plane */
+ if (frame->data[3]) {
+ frame->data[3] += s->y * frame->linesize[3];
+ frame->data[3] += s->x * s->max_step[3];
+ }
}
return ff_filter_frame(link->dst->outputs[0], frame);
#define OFFSET(x) offsetof(CropContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
static const AVOption crop_options[] = {
- { "out_w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "out_h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "x", "set the x crop area expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "y", "set the y crop area expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
+ { "out_w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, TFLAGS },
+ { "w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, TFLAGS },
+ { "out_h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, TFLAGS },
+ { "h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, TFLAGS },
+ { "x", "set the x crop area expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, 0, 0, TFLAGS },
+ { "y", "set the y crop area expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, 0, 0, TFLAGS },
{ "keep_aspect", "keep aspect ratio", OFFSET(keep_aspect), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
{ "exact", "do exact cropping", OFFSET(exact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
{ NULL }