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
1515
1616 API changes, most recent first:
1717
18+2017-08-08 - xxxxxxx - lavu 55.71.100 - frame.h
19+ Add av_frame_apply_cropping().
20+
1821 2017-07-25 - 24de4fddca - lavu 55.69.100 - frame.h
1922 Add AV_FRAME_DATA_ICC_PROFILE side data type.
2023
libavcodec/decode.c+2−87
@@ -683,44 +683,8 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke · 682 unmodified lines
683683 return 0;
684684 }
685685
686−static 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−
718686 static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)
719687 {
720− const AVPixFmtDescriptor *desc;
721− size_t offsets[4];
722− int i;
723−
724688 /* make sure we are noisy about decoders returning invalid cropping data */
725689 if (frame->crop_left >= INT_MAX - frame->crop_right ||
726690 frame->crop_top >= INT_MAX - frame->crop_bottom ||
@@ -742,57 +706,8 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) · 15 unmodified lines
742706 if (!avctx->apply_cropping)
743707 return 0;
744708
745− desc = av_pix_fmt_desc_get(frame->format);
746− if (!desc)
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;
709+ return av_frame_apply_cropping(frame, avctx->flags & AV_CODEC_FLAG_UNALIGNED ?
710+ AV_FRAME_CROP_UNALIGNED : 0);
796711 }
797712
798713 int 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
782782 }
783783 return NULL;
784784 }
785+
786+static 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+
818+int 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
773773 */
774774 void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
775775
776+
777+/**
778+ * Flags for frame cropping.
779+ */
780+enum {
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+ */
808+int av_frame_apply_cropping(AVFrame *frame, int flags);
809+
776810 /**
777811 * @return a string identifying the side data type
778812 */
libavutil/version.h+1−1
@@ -80,7 +80,7 @@ · 79 unmodified lines
8080
8181
8282 #define LIBAVUTIL_VERSION_MAJOR 55
83−#define LIBAVUTIL_VERSION_MINOR 70
83+#define LIBAVUTIL_VERSION_MINOR 71
8484 #define LIBAVUTIL_VERSION_MICRO 100
8585
8686 #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