On 30/05/2024 03:04, James Almer wrote: > On 5/29/2024 10:01 PM, Lynne via ffmpeg-devel wrote: >> On 29/05/2024 23:46, James Almer wrote: >>> Signed-off-by: James Almer >>> --- >>>   fftools/ffmpeg.h        |  7 +++++++ >>>   fftools/ffmpeg_demux.c  | 16 ++++++++++++++++ >>>   fftools/ffmpeg_filter.c | 11 +++++++++++ >>>   fftools/ffmpeg_opt.c    |  3 +++ >>>   4 files changed, 37 insertions(+) >>> >>> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h >>> index fe75706afd..f908e16549 100644 >>> --- a/fftools/ffmpeg.h >>> +++ b/fftools/ffmpeg.h >>> @@ -155,6 +155,7 @@ typedef struct OptionsContext { >>>       SpecifierOptList hwaccel_devices; >>>       SpecifierOptList hwaccel_output_formats; >>>       SpecifierOptList autorotate; >>> +    SpecifierOptList apply_cropping; >>>       /* output options */ >>>       StreamMap *stream_maps; >>> @@ -239,6 +240,7 @@ enum IFilterFlags { >>>       IFILTER_FLAG_AUTOROTATE     = (1 << 0), >>>       IFILTER_FLAG_REINIT         = (1 << 1), >>>       IFILTER_FLAG_CFR            = (1 << 2), >>> +    IFILTER_FLAG_CROP           = (1 << 3), >>>   }; >>>   typedef struct InputFilterOptions { >>> @@ -254,6 +256,11 @@ typedef struct InputFilterOptions { >>>        * accurate */ >>>       AVRational          framerate; >>> +    unsigned crop_top; >>> +    unsigned crop_bottom; >>> +    unsigned crop_left; >>> +    unsigned crop_right; >>> + >>>       int                 sub2video_width; >>>       int                 sub2video_height; >>> diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c >>> index 1ca8d804ae..4178b8f840 100644 >>> --- a/fftools/ffmpeg_demux.c >>> +++ b/fftools/ffmpeg_demux.c >>> @@ -66,6 +66,7 @@ typedef struct DemuxStream { >>>       int                      have_sub2video; >>>       int                      reinit_filters; >>>       int                      autorotate; >>> +    int                      apply_cropping; >>>       int                      wrap_correction_done; >>> @@ -1000,11 +1001,20 @@ int ist_filter_add(InputStream *ist, >>> InputFilter *ifilter, int is_simple, >>>       ist->filters[ist->nb_filters - 1] = ifilter; >>>       if (ist->par->codec_type == AVMEDIA_TYPE_VIDEO) { >>> +        const AVPacketSideData *sd = >>> av_packet_side_data_get(ist->st->codecpar->coded_side_data, >>> + ist->st->codecpar->nb_coded_side_data, >>> + AV_PKT_DATA_FRAME_CROPPING); >>>           if (ist->framerate.num > 0 && ist->framerate.den > 0) { >>>               opts->framerate = ist->framerate; >>>               opts->flags |= IFILTER_FLAG_CFR; >>>           } else >>>               opts->framerate = av_guess_frame_rate(d->f.ctx, >>> ist->st, NULL); >>> +        if (sd && sd->size == sizeof(uint32_t) * 4) { >>> +            opts->crop_top    = AV_RL32(sd->data +  0); >>> +            opts->crop_bottom = AV_RL32(sd->data +  4); >>> +            opts->crop_left   = AV_RL32(sd->data +  8); >>> +            opts->crop_right  = AV_RL32(sd->data + 12); >>> +        } >>>       } else if (ist->par->codec_type == AVMEDIA_TYPE_SUBTITLE) { >>>           /* Compute the size of the canvas for the subtitles stream. >>>              If the subtitles codecpar has set a size, use it. >>> Otherwise use the >>> @@ -1059,6 +1069,7 @@ int ist_filter_add(InputStream *ist, >>> InputFilter *ifilter, int is_simple, >>>           return AVERROR(ENOMEM); >>>       opts->flags |= IFILTER_FLAG_AUTOROTATE * !!(ds->autorotate) | >>> +                   IFILTER_FLAG_CROP       * !!(ds->apply_cropping) | >>>                      IFILTER_FLAG_REINIT     * !!(ds->reinit_filters); >>>       return ds->sch_idx_dec; >>> @@ -1241,6 +1252,9 @@ static int ist_add(const OptionsContext *o, >>> Demuxer *d, AVStream *st) >>>       ds->autorotate = 1; >>>       MATCH_PER_STREAM_OPT(autorotate, i, ds->autorotate, ic, st); >>> +    ds->apply_cropping = 1; >>> +    MATCH_PER_STREAM_OPT(apply_cropping, i, ds->apply_cropping, ic, >>> st); >>> + >>>       MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); >>>       if (codec_tag) { >>>           uint32_t tag = strtol(codec_tag, &next, 0); >>> @@ -1362,6 +1376,8 @@ static int ist_add(const OptionsContext *o, >>> Demuxer *d, AVStream *st) >>>       ds->dec_opts.flags |= DECODER_FLAG_BITEXACT * !!o->bitexact; >>> +    av_dict_set_int(&ds->decoder_opts, "apply_cropping", >>> ds->apply_cropping, 0); >>> + >>>       /* Attached pics are sparse, therefore we would not want to >>> delay their decoding >>>        * till EOF. */ >>>       if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC) >>> diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c >>> index 12cca684b4..a31fa1be7f 100644 >>> --- a/fftools/ffmpeg_filter.c >>> +++ b/fftools/ffmpeg_filter.c >>> @@ -1701,6 +1701,17 @@ static int >>> configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph, >>>       desc = av_pix_fmt_desc_get(ifp->format); >>>       av_assert0(desc); >>> +    if ((ifp->opts.flags & IFILTER_FLAG_CROP) && >>> +        !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { >>> +        char crop_buf[64]; >>> +        snprintf(crop_buf, sizeof(crop_buf), "w=iw-%d-%d:h=ih-%d-%d", >>> +                 ifp->opts.crop_left, ifp->opts.crop_right, >>> +                 ifp->opts.crop_top, ifp->opts.crop_bottom); >>> +        ret = insert_filter(&last_filter, &pad_idx, "crop", crop_buf); >>> +        if (ret < 0) >>> +            return ret; >>> +    } >> >> The crop filter supports hardware frames too. > > It exports the values within the AVFrame fields. If that's acceptable > then i can remove this check. Sure, that's acceptable. If anything, it would help get better support for AVFrame's crop fields through the codebase.