[FFmpeg-devel] [PATCH v3 1/2] vf_crop: Add support for cropping hardware frames
Philip Langdale
philipl at overt.org
Mon Mar 25 06:58:03 EET 2019
On Sat, 23 Mar 2019 16:18:48 +0000
Mark Thompson <sw at jkqxz.net> wrote:
> Set the cropping fields in the AVFrame.
> ---
> libavfilter/vf_crop.c | 74
> +++++++++++++++++++++++++++++-------------- 1 file changed, 51
> insertions(+), 23 deletions(-)
>
> There is the slightly unfortunate effect the filter links don't carry
> the cropping information, so we don't know how big the cropped output
> is in following links until we actually get a frame.
>
> For example, to get the middle ninth of a stream:
>
> ./ffmpeg_g -y -hwaccel vaapi -hwaccel_device /dev/dri/renderD128
> -hwaccel_output_format vaapi -i in.mp4 -an -vf
> "crop=iw/3:ih/3:iw/3:ih/3,scale_vaapi=iw/3:ih/3" -c:v h264_vaapi
> out.mp4
>
> Without the extra arguments to scale it will take the cropped part
> correctly but then scale it to the original size.
>
> diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
> index 84be4c7d0d..7f6b0f03d3 100644
> --- a/libavfilter/vf_crop.c
> +++ b/libavfilter/vf_crop.c
> @@ -98,9 +98,17 @@ static int query_formats(AVFilterContext *ctx)
>
> 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)
> + if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
> + continue;
> + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
> + // Not usable if there is any subsampling but the format
> is
> + // not planar (e.g. YUYV422).
> + if ((desc->log2_chroma_w || desc->log2_chroma_h) &&
> + !(desc->flags & AV_PIX_FMT_FLAG_PLANAR))
> + continue;
> + }
> + ret = ff_add_format(&formats, fmt);
> + if (ret < 0)
> return ret;
> }
>
> @@ -157,8 +165,14 @@ 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 (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;
> + }
>
> if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr),
> var_names, s->var_values,
> @@ -237,9 +251,15 @@ fail_expr:
> 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 +272,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 +302,33 @@ 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 || 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;
> + }
> }
> }
> - }
>
> - /* 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);
Ship it.
--phil
More information about the ffmpeg-devel
mailing list