X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_crop.c;h=9cc9ec28441ffe89672529a9d2cbb40db3d4a047;hb=a04ad248a05e7b613abe09b3bb067f555108d794;hp=84be4c7d0d2405e14fd301fdec05dfb4ef4c7cd7;hpb=762c2b5dcd99a08452299cd1f83070f88115f1f3;p=ffmpeg diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 84be4c7d0d2..9cc9ec28441 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -94,16 +94,11 @@ typedef struct CropContext { 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); } @@ -157,13 +152,18 @@ static int config_input(AVFilterLink *link) 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, @@ -230,16 +230,22 @@ static int config_input(AVFilterLink *link) 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; @@ -252,9 +258,6 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) 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); @@ -285,22 +288,32 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) (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); @@ -344,14 +357,15 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar #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 } @@ -378,7 +392,7 @@ static const AVFilterPad avfilter_vf_crop_outputs[] = { { NULL } }; -AVFilter ff_vf_crop = { +const AVFilter ff_vf_crop = { .name = "crop", .description = NULL_IF_CONFIG_SMALL("Crop the input video."), .priv_size = sizeof(CropContext),