On 7/12/17 5:02 PM, wm4 wrote:
> TODO: APIchanges entry, version bump.
> ---
> Now with flags instead of a bool parameter.
> ---
> libavcodec/decode.c | 89 ++-------------------------------------------
> libavutil/frame.c | 101
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
> libavutil/frame.h | 32 +++++++++++++++++
> 3 files changed, 135 insertions(+), 87 deletions(-)
>
> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
> index 175a6fae4c..9644e89f48 100644
> --- a/libavcodec/decode.c
> +++ b/libavcodec/decode.c
> @@ -446,44 +446,8 @@ int attribute_align_arg
> avcodec_send_packet(AVCodecContext *avctx, const AVPacke
> return 0;
> }
>
> -static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
> - const AVPixFmtDescriptor *desc)
> -{
> - int i, j;
> -
> - for (i = 0; frame->data[i]; i++) {
> - const AVComponentDescriptor *comp = NULL;
> - int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
> - int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
> -
> - if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL)
> && i == 1) {
> - offsets[i] = 0;
> - break;
> - }
> -
> - /* find any component descriptor for this plane */
> - for (j = 0; j < desc->nb_components; j++) {
> - if (desc->comp[j].plane == i) {
> - comp = &desc->comp[j];
> - break;
> - }
> - }
> - if (!comp)
> - return AVERROR_BUG;
> -
> - offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
> - (frame->crop_left >> shift_x) * comp->step;
> - }
> -
> - return 0;
> -}
> -
> static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)
> {
> - const AVPixFmtDescriptor *desc;
> - size_t offsets[4];
> - int i;
> -
> /* make sure we are noisy about decoders returning invalid cropping data
> */
> if (frame->crop_left >= INT_MAX - frame->crop_right ||
> frame->crop_top >= INT_MAX - frame->crop_bottom ||
> @@ -504,57 +468,8 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame
> *frame)
> if (!avctx->apply_cropping)
> return 0;
>
> - desc = av_pix_fmt_desc_get(frame->format);
> - if (!desc)
> - return AVERROR_BUG;
> -
> - /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
> - * formats cannot be easily handled here either (and corresponding
> decoders
> - * should not export any cropping anyway), so do the same for those as
> well.
> - * */
> - if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL))
> {
> - frame->width -= frame->crop_right;
> - frame->height -= frame->crop_bottom;
> - frame->crop_right = 0;
> - frame->crop_bottom = 0;
> - return 0;
> - }
> -
> - /* calculate the offsets for each plane */
> - calc_cropping_offsets(offsets, frame, desc);
> -
> - /* adjust the offsets to avoid breaking alignment */
> - if (!(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) {
> - int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) :
> INT_MAX;
> - int min_log2_align = INT_MAX;
> -
> - for (i = 0; frame->data[i]; i++) {
> - int log2_align = offsets[i] ? av_ctz(offsets[i]) : INT_MAX;
> - min_log2_align = FFMIN(log2_align, min_log2_align);
> - }
> -
> - /* we assume, and it should always be true, that the data alignment
> is
> - * related to the cropping alignment by a constant power-of-2 factor
> */
> - if (log2_crop_align < min_log2_align)
> - return AVERROR_BUG;
> -
> - if (min_log2_align < 5) {
> - frame->crop_left &= ~((1 << (5 + log2_crop_align -
> min_log2_align)) - 1);
> - calc_cropping_offsets(offsets, frame, desc);
> - }
> - }
> -
> - for (i = 0; frame->data[i]; i++)
> - frame->data[i] += offsets[i];
> -
> - frame->width -= (frame->crop_left + frame->crop_right);
> - frame->height -= (frame->crop_top + frame->crop_bottom);
> - frame->crop_left = 0;
> - frame->crop_right = 0;
> - frame->crop_top = 0;
> - frame->crop_bottom = 0;
> -
> - return 0;
> + return av_frame_apply_cropping(frame, avctx->flags &
> AV_CODEC_FLAG_UNALIGNED ?
> + AV_FRAME_CROP_UNALIGNED : 0);
> }
>
> int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame
> *frame)
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index 9cd5f9ab37..c17a113570 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -596,3 +596,104 @@ void av_frame_remove_side_data(AVFrame *frame, enum
> AVFrameSideDataType type)
> }
> }
> }
> +
> +static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
> + const AVPixFmtDescriptor *desc)
> +{
> + int i, j;
> +
> + for (i = 0; frame->data[i]; i++) {
> + const AVComponentDescriptor *comp = NULL;
> + int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
> + int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
> +
> + if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL)
> && i == 1) {
> + offsets[i] = 0;
> + break;
> + }
> +
> + /* find any component descriptor for this plane */
> + for (j = 0; j < desc->nb_components; j++) {
> + if (desc->comp[j].plane == i) {
> + comp = &desc->comp[j];
> + break;
> + }
> + }
> + if (!comp)
> + return AVERROR_BUG;
> +
> + offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
> + (frame->crop_left >> shift_x) * comp->step;
> + }
> +
> + return 0;
> +}
> +
> +int av_frame_apply_cropping(AVFrame *frame, int flags)
> +{
> + const AVPixFmtDescriptor *desc;
> + size_t offsets[4];
> + int i;
> +
> + if (!(frame->width > 0 && frame->height > 0))
> + return AVERROR(EINVAL);
> +
> + /* make sure we are noisy about decoders returning invalid cropping data
> */
> + if (frame->crop_left >= INT_MAX - frame->crop_right ||
> + frame->crop_top >= INT_MAX - frame->crop_bottom ||
> + (frame->crop_left + frame->crop_right) >= frame->width ||
> + (frame->crop_top + frame->crop_bottom) >= frame->height)
> + return AVERROR(ERANGE);
> +
> + desc = av_pix_fmt_desc_get(frame->format);
> + if (!desc)
> + return AVERROR_BUG;
> +
> + /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
> + * formats cannot be easily handled here either (and corresponding
> decoders
> + * should not export any cropping anyway), so do the same for those as
> well.
> + * */
> + if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL))
> {
> + frame->width -= frame->crop_right;
> + frame->height -= frame->crop_bottom;
> + frame->crop_right = 0;
> + frame->crop_bottom = 0;
> + return 0;
> + }
> +
> + /* calculate the offsets for each plane */
> + calc_cropping_offsets(offsets, frame, desc);
> +
> + /* adjust the offsets to avoid breaking alignment */
> + if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
> + int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) :
> INT_MAX;
> + int min_log2_align = INT_MAX;
> +
> + for (i = 0; frame->data[i]; i++) {
> + int log2_align = offsets[i] ? av_ctz(offsets[i]) : INT_MAX;
> + min_log2_align = FFMIN(log2_align, min_log2_align);
> + }
> +
> + /* we assume, and it should always be true, that the data alignment
> is
> + * related to the cropping alignment by a constant power-of-2 factor
> */
> + if (log2_crop_align < min_log2_align)
> + return AVERROR_BUG;
> +
> + if (min_log2_align < 5) {
> + frame->crop_left &= ~((1 << (5 + log2_crop_align -
> min_log2_align)) - 1);
> + calc_cropping_offsets(offsets, frame, desc);
> + }
> + }
> +
> + for (i = 0; frame->data[i]; i++)
> + frame->data[i] += offsets[i];
> +
> + frame->width -= (frame->crop_left + frame->crop_right);
> + frame->height -= (frame->crop_top + frame->crop_bottom);
> + frame->crop_left = 0;
> + frame->crop_right = 0;
> + frame->crop_top = 0;
> + frame->crop_bottom = 0;
> +
> + return 0;
> +}
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index f9ffb5bbbf..eb1fa0cba5 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -580,6 +580,38 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame
> *frame,
> */
> void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType
> type);
>
> +
> +/**
> + * Flags for frame cropping.
> + */
> +enum {
> + /**
> + * Apply the maximum possible cropping, even if it requires setting the
> + * AVFrame.data[] entries to unaligned pointers. Using this is strongly
> + * discouraged, especially if the data is to be fed back to Libav API. It
> + * can cause performance issues, and in some cases crashes.
> + */
> + AV_FRAME_CROP_UNALIGNED = 1 << 0,
> +};
> +
> +/**
> + * Crop the given video AVFrame according to its
> crop_left/crop_top/crop_right/
> + * crop_bottom fields. If cropping is successful, the function will adjust
> the
> + * data pointers and the width/height fields, and set the crop fields to 0.
> + *
> + * In all cases, the cropping boundaries will be rounded to the inherent
> + * alignment of the pixel format. In some cases, such as for opaque hwaccel
> + * formats, the left/top cropping is ignored. The crop fields are set to 0
> even
> + * if the cropping was rounded or ignored.
> + *
> + * @param frame the frame which should be cropped
> + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0.
> + *
> + * @return >= 0 on success, a negative AVERROR on error. If the cropping
> fields
> + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed.
> + */
> +int av_frame_apply_cropping(AVFrame *frame, int flags);
> +
> /**
> * @}
> */
>
I like it better. Thank you :)
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel