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 libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel