History

lavc, lavu: move frame cropping to a convenience function

Signed-off-by: Anton Khirnov <anton@khirnov.net> Merged from Libav commit 47399ccdfd.

wm4 committed 9 years ago

Commit caa12021 parent 45759545 files · +140 −88Browse files

Unified · Split

5 files
  1. doc/APIchanges +3 −0
  2. libavcodec/decode.c +2 −87
  3. libavutil/frame.c +100 −0
  4. libavutil/frame.h +34 −0
  5. libavutil/version.h +1 −1
doc/APIchanges+3−0
@@ -15,6 +15,9 @@ libavutil: 2015-08-28 · 14 unmodified lines
15 15
16API changes, most recent first:16API changes, most recent first:
17 17
182017-08-08 - xxxxxxx - lavu 55.71.100 - frame.h
19 Add av_frame_apply_cropping().
20
182017-07-25 - 24de4fddca - lavu 55.69.100 - frame.h212017-07-25 - 24de4fddca - lavu 55.69.100 - frame.h
19 Add AV_FRAME_DATA_ICC_PROFILE side data type.22 Add AV_FRAME_DATA_ICC_PROFILE side data type.
20 23
libavcodec/decode.c+2−87
@@ -683,44 +683,8 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke · 682 unmodified lines
683 return 0;683 return 0;
684}684}
685 685
686static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
687 const AVPixFmtDescriptor *desc)
688{
689 int i, j;
690
691 for (i = 0; frame->data[i]; i++) {
692 const AVComponentDescriptor *comp = NULL;
693 int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
694 int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
695
696 if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) {
697 offsets[i] = 0;
698 break;
699 }
700
701 /* find any component descriptor for this plane */
702 for (j = 0; j < desc->nb_components; j++) {
703 if (desc->comp[j].plane == i) {
704 comp = &desc->comp[j];
705 break;
706 }
707 }
708 if (!comp)
709 return AVERROR_BUG;
710
711 offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
712 (frame->crop_left >> shift_x) * comp->step;
713 }
714
715 return 0;
716}
717
718static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)686static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)
719{687{
720 const AVPixFmtDescriptor *desc;
721 size_t offsets[4];
722 int i;
723
724 /* make sure we are noisy about decoders returning invalid cropping data */688 /* make sure we are noisy about decoders returning invalid cropping data */
725 if (frame->crop_left >= INT_MAX - frame->crop_right ||689 if (frame->crop_left >= INT_MAX - frame->crop_right ||
726 frame->crop_top >= INT_MAX - frame->crop_bottom ||690 frame->crop_top >= INT_MAX - frame->crop_bottom ||
@@ -742,57 +706,8 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) · 15 unmodified lines
742 if (!avctx->apply_cropping)706 if (!avctx->apply_cropping)
743 return 0;707 return 0;
744 708
745 desc = av_pix_fmt_desc_get(frame->format);709 return av_frame_apply_cropping(frame, avctx->flags & AV_CODEC_FLAG_UNALIGNED ?
746 if (!desc)710 AV_FRAME_CROP_UNALIGNED : 0);
747 return AVERROR_BUG;
748
749 /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
750 * formats cannot be easily handled here either (and corresponding decoders
751 * should not export any cropping anyway), so do the same for those as well.
752 * */
753 if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
754 frame->width -= frame->crop_right;
755 frame->height -= frame->crop_bottom;
756 frame->crop_right = 0;
757 frame->crop_bottom = 0;
758 return 0;
759 }
760
761 /* calculate the offsets for each plane */
762 calc_cropping_offsets(offsets, frame, desc);
763
764 /* adjust the offsets to avoid breaking alignment */
765 if (!(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) {
766 int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
767 int min_log2_align = INT_MAX;
768
769 for (i = 0; frame->data[i]; i++) {
770 int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
771 min_log2_align = FFMIN(log2_align, min_log2_align);
772 }
773
774 /* we assume, and it should always be true, that the data alignment is
775 * related to the cropping alignment by a constant power-of-2 factor */
776 if (log2_crop_align < min_log2_align)
777 return AVERROR_BUG;
778
779 if (min_log2_align < 5) {
780 frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
781 calc_cropping_offsets(offsets, frame, desc);
782 }
783 }
784
785 for (i = 0; frame->data[i]; i++)
786 frame->data[i] += offsets[i];
787
788 frame->width -= (frame->crop_left + frame->crop_right);
789 frame->height -= (frame->crop_top + frame->crop_bottom);
790 frame->crop_left = 0;
791 frame->crop_right = 0;
792 frame->crop_top = 0;
793 frame->crop_bottom = 0;
794
795 return 0;
796}711}
797 712
798int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)713int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
libavutil/frame.c+100−0
@@ -782,3 +782,103 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) · 781 unmodified lines
782 }782 }
783 return NULL;783 return NULL;
784}784}
785
786static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
787 const AVPixFmtDescriptor *desc)
788{
789 int i, j;
790
791 for (i = 0; frame->data[i]; i++) {
792 const AVComponentDescriptor *comp = NULL;
793 int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
794 int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
795
796 if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) {
797 offsets[i] = 0;
798 break;
799 }
800
801 /* find any component descriptor for this plane */
802 for (j = 0; j < desc->nb_components; j++) {
803 if (desc->comp[j].plane == i) {
804 comp = &desc->comp[j];
805 break;
806 }
807 }
808 if (!comp)
809 return AVERROR_BUG;
810
811 offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
812 (frame->crop_left >> shift_x) * comp->step;
813 }
814
815 return 0;
816}
817
818int av_frame_apply_cropping(AVFrame *frame, int flags)
819{
820 const AVPixFmtDescriptor *desc;
821 size_t offsets[4];
822 int i;
823
824 if (!(frame->width > 0 && frame->height > 0))
825 return AVERROR(EINVAL);
826
827 if (frame->crop_left >= INT_MAX - frame->crop_right ||
828 frame->crop_top >= INT_MAX - frame->crop_bottom ||
829 (frame->crop_left + frame->crop_right) >= frame->width ||
830 (frame->crop_top + frame->crop_bottom) >= frame->height)
831 return AVERROR(ERANGE);
832
833 desc = av_pix_fmt_desc_get(frame->format);
834 if (!desc)
835 return AVERROR_BUG;
836
837 /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
838 * formats cannot be easily handled here either (and corresponding decoders
839 * should not export any cropping anyway), so do the same for those as well.
840 * */
841 if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
842 frame->width -= frame->crop_right;
843 frame->height -= frame->crop_bottom;
844 frame->crop_right = 0;
845 frame->crop_bottom = 0;
846 return 0;
847 }
848
849 /* calculate the offsets for each plane */
850 calc_cropping_offsets(offsets, frame, desc);
851
852 /* adjust the offsets to avoid breaking alignment */
853 if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
854 int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
855 int min_log2_align = INT_MAX;
856
857 for (i = 0; frame->data[i]; i++) {
858 int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
859 min_log2_align = FFMIN(log2_align, min_log2_align);
860 }
861
862 /* we assume, and it should always be true, that the data alignment is
863 * related to the cropping alignment by a constant power-of-2 factor */
864 if (log2_crop_align < min_log2_align)
865 return AVERROR_BUG;
866
867 if (min_log2_align < 5) {
868 frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
869 calc_cropping_offsets(offsets, frame, desc);
870 }
871 }
872
873 for (i = 0; frame->data[i]; i++)
874 frame->data[i] += offsets[i];
875
876 frame->width -= (frame->crop_left + frame->crop_right);
877 frame->height -= (frame->crop_top + frame->crop_bottom);
878 frame->crop_left = 0;
879 frame->crop_right = 0;
880 frame->crop_top = 0;
881 frame->crop_bottom = 0;
882
883 return 0;
884}
libavutil/frame.h+34−0
@@ -773,6 +773,40 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, · 772 unmodified lines
773 */773 */
774void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);774void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
775 775
776
777/**
778 * Flags for frame cropping.
779 */
780enum {
781 /**
782 * Apply the maximum possible cropping, even if it requires setting the
783 * AVFrame.data[] entries to unaligned pointers. Passing unaligned data
784 * to Libav API is generally not allowed, and causes undefined behavior
785 * (such as crashes). You can pass unaligned data only to Libav APIs that
786 * are explicitly documented to accept it. Use this flag only if you
787 * absolutely know what you are doing.
788 */
789 AV_FRAME_CROP_UNALIGNED = 1 << 0,
790};
791
792/**
793 * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/
794 * crop_bottom fields. If cropping is successful, the function will adjust the
795 * data pointers and the width/height fields, and set the crop fields to 0.
796 *
797 * In all cases, the cropping boundaries will be rounded to the inherent
798 * alignment of the pixel format. In some cases, such as for opaque hwaccel
799 * formats, the left/top cropping is ignored. The crop fields are set to 0 even
800 * if the cropping was rounded or ignored.
801 *
802 * @param frame the frame which should be cropped
803 * @param flags Some combination of AV_FRAME_CROP_* flags, or 0.
804 *
805 * @return >= 0 on success, a negative AVERROR on error. If the cropping fields
806 * were invalid, AVERROR(ERANGE) is returned, and nothing is changed.
807 */
808int av_frame_apply_cropping(AVFrame *frame, int flags);
809
776/**810/**
777 * @return a string identifying the side data type811 * @return a string identifying the side data type
778 */812 */
libavutil/version.h+1−1
@@ -80,7 +80,7 @@ · 79 unmodified lines
80 80
81 81
82#define LIBAVUTIL_VERSION_MAJOR 5582#define LIBAVUTIL_VERSION_MAJOR 55
83#define LIBAVUTIL_VERSION_MINOR 7083#define LIBAVUTIL_VERSION_MINOR 71
84#define LIBAVUTIL_VERSION_MICRO 10084#define LIBAVUTIL_VERSION_MICRO 100
85 85
86#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \86#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t