* commit '019ab88a95cb31b698506d90e8ce56695a7f1cc5': lavc: add an option for exporting cropping information to the caller
Unified · Split
| @@ -15,6 +15,10 @@ libavutil: 2015-08-28 · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | API changes, most recent first: | 16 | API changes, most recent first: |
| 17 | 17 | ||
| 18 | 2017-xx-xx - xxxxxxx - lavc 57.95.100 / 57.31.0 - avcodec.h | ||
| 19 | Add AVCodecContext.apply_cropping to control whether cropping | ||
| 20 | is handled by libavcodec or the caller. | ||
| 21 | |||
| 18 | 2017-xx-xx - xxxxxxx - lavu 55.62.100 / 55.30.0 - frame.h | 22 | 2017-xx-xx - xxxxxxx - lavu 55.62.100 / 55.30.0 - frame.h |
| 19 | Add AVFrame.crop_left/right/top/bottom fields for attaching cropping | 23 | Add AVFrame.crop_left/right/top/bottom fields for attaching cropping |
| 20 | information to video frames. | 24 | information to video frames. |
| @@ -3644,6 +3644,33 @@ typedef struct AVCodecContext { · 3643 unmodified lines | |||
| 3644 | * AVCodecContext.get_format callback) | 3644 | * AVCodecContext.get_format callback) |
| 3645 | */ | 3645 | */ |
| 3646 | int hwaccel_flags; | 3646 | int hwaccel_flags; |
| 3647 | |||
| 3648 | /** | ||
| 3649 | * Video decoding only. Certain video codecs support cropping, meaning that | ||
| 3650 | * only a sub-rectangle of the decoded frame is intended for display. This | ||
| 3651 | * option controls how cropping is handled by libavcodec. | ||
| 3652 | * | ||
| 3653 | * When set to 1 (the default), libavcodec will apply cropping internally. | ||
| 3654 | * I.e. it will modify the output frame width/height fields and offset the | ||
| 3655 | * data pointers (only by as much as possible while preserving alignment, or | ||
| 3656 | * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that | ||
| 3657 | * the frames output by the decoder refer only to the cropped area. The | ||
| 3658 | * crop_* fields of the output frames will be zero. | ||
| 3659 | * | ||
| 3660 | * When set to 0, the width/height fields of the output frames will be set | ||
| 3661 | * to the coded dimensions and the crop_* fields will describe the cropping | ||
| 3662 | * rectangle. Applying the cropping is left to the caller. | ||
| 3663 | * | ||
| 3664 | * @warning When hardware acceleration with opaque output frames is used, | ||
| 3665 | * libavcodec is unable to apply cropping from the top/left border. | ||
| 3666 | * | ||
| 3667 | * @note when this option is set to zero, the width/height fields of the | ||
| 3668 | * AVCodecContext and output AVFrames have different meanings. The codec | ||
| 3669 | * context fields store display dimensions (with the coded dimensions in | ||
| 3670 | * coded_width/height), while the frame fields store the coded dimensions | ||
| 3671 | * (with the display dimensions being determined by the crop_* fields). | ||
| 3672 | */ | ||
| 3673 | int apply_cropping; | ||
| 3647 | } AVCodecContext; | 3674 | } AVCodecContext; |
| 3648 | 3675 | ||
| 3649 | AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); | 3676 | AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | |||
| 35 | #include "libavutil/hwcontext.h" | 35 | #include "libavutil/hwcontext.h" |
| 36 | #include "libavutil/imgutils.h" | 36 | #include "libavutil/imgutils.h" |
| 37 | #include "libavutil/internal.h" | 37 | #include "libavutil/internal.h" |
| 38 | #include "libavutil/intmath.h" | ||
| 38 | 39 | ||
| 39 | #include "avcodec.h" | 40 | #include "avcodec.h" |
| 40 | #include "bytestream.h" | 41 | #include "bytestream.h" |
| @@ -682,6 +683,112 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke · 641 unmodified lines | |||
| 682 | return 0; | 683 | return 0; |
| 683 | } | 684 | } |
| 684 | 685 | ||
| 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 | |||
| 718 | static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) | ||
| 719 | { | ||
| 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 */ | ||
| 725 | if (frame->crop_left >= INT_MAX - frame->crop_right || | ||
| 726 | frame->crop_top >= INT_MAX - frame->crop_bottom || | ||
| 727 | (frame->crop_left + frame->crop_right) >= frame->width || | ||
| 728 | (frame->crop_top + frame->crop_bottom) >= frame->height) { | ||
| 729 | av_log(avctx, AV_LOG_WARNING, | ||
| 730 | "Invalid cropping information set by a decoder: " | ||
| 731 | "%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER" " | ||
| 732 | "(frame size %dx%d). This is a bug, please report it\n", | ||
| 733 | frame->crop_left, frame->crop_right, frame->crop_top, frame->crop_bottom, | ||
| 734 | frame->width, frame->height); | ||
| 735 | frame->crop_left = 0; | ||
| 736 | frame->crop_right = 0; | ||
| 737 | frame->crop_top = 0; | ||
| 738 | frame->crop_bottom = 0; | ||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | |||
| 742 | if (!avctx->apply_cropping) | ||
| 743 | return 0; | ||
| 744 | |||
| 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 min_log2_align = INT_MAX; | ||
| 767 | |||
| 768 | for (i = 0; frame->data[i]; i++) { | ||
| 769 | int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX; | ||
| 770 | min_log2_align = FFMIN(log2_align, min_log2_align); | ||
| 771 | } | ||
| 772 | |||
| 773 | if (min_log2_align < 5) { | ||
| 774 | frame->crop_left &= ~((1 << min_log2_align) - 1); | ||
| 775 | calc_cropping_offsets(offsets, frame, desc); | ||
| 776 | } | ||
| 777 | } | ||
| 778 | |||
| 779 | for (i = 0; frame->data[i]; i++) | ||
| 780 | frame->data[i] += offsets[i]; | ||
| 781 | |||
| 782 | frame->width -= (frame->crop_left + frame->crop_right); | ||
| 783 | frame->height -= (frame->crop_top + frame->crop_bottom); | ||
| 784 | frame->crop_left = 0; | ||
| 785 | frame->crop_right = 0; | ||
| 786 | frame->crop_top = 0; | ||
| 787 | frame->crop_bottom = 0; | ||
| 788 | |||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | |||
| 685 | int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) | 792 | int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) |
| 686 | { | 793 | { |
| 687 | AVCodecInternal *avci = avctx->internal; | 794 | AVCodecInternal *avci = avctx->internal; |
| @@ -704,6 +811,14 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr · 16 unmodified lines | |||
| 704 | return ret; | 811 | return ret; |
| 705 | } | 812 | } |
| 706 | 813 | ||
| 814 | if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { | ||
| 815 | ret = apply_cropping(avctx, frame); | ||
| 816 | if (ret < 0) { | ||
| 817 | av_frame_unref(frame); | ||
| 818 | return ret; | ||
| 819 | } | ||
| 820 | } | ||
| 821 | |||
| 707 | avctx->frame_number++; | 822 | avctx->frame_number++; |
| 708 | 823 | ||
| 709 | return 0; | 824 | return 0; |
| @@ -1611,7 +1726,8 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) · 901 unmodified lines | |||
| 1611 | validate_avframe_allocation(avctx, frame); | 1726 | validate_avframe_allocation(avctx, frame); |
| 1612 | 1727 | ||
| 1613 | end: | 1728 | end: |
| 1614 | if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { | 1729 | if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions && |
| 1730 | !(avctx->codec->caps_internal & FF_CODEC_CAP_EXPORTS_CROPPING)) { | ||
| 1615 | frame->width = avctx->width; | 1731 | frame->width = avctx->width; |
| 1616 | frame->height = avctx->height; | 1732 | frame->height = avctx->height; |
| 1617 | } | 1733 | } |
| @@ -58,6 +58,12 @@ · 57 unmodified lines | |||
| 58 | * skipped due to the skip_frame setting. | 58 | * skipped due to the skip_frame setting. |
| 59 | */ | 59 | */ |
| 60 | #define FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM (1 << 3) | 60 | #define FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM (1 << 3) |
| 61 | /** | ||
| 62 | * The decoder sets the cropping fields in the output frames manually. | ||
| 63 | * If this cap is set, the generic code will initialize output frame | ||
| 64 | * dimensions to coded rather than display values. | ||
| 65 | */ | ||
| 66 | #define FF_CODEC_CAP_EXPORTS_CROPPING (1 << 4) | ||
| 61 | 67 | ||
| 62 | #ifdef TRACE | 68 | #ifdef TRACE |
| 63 | # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) | 69 | # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) |
| @@ -561,6 +561,7 @@ static const AVOption avcodec_options[] = { · 560 unmodified lines | |||
| 561 | #if FF_API_SIDEDATA_ONLY_PKT | 561 | #if FF_API_SIDEDATA_ONLY_PKT |
| 562 | {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, A|V|E }, | 562 | {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, A|V|E }, |
| 563 | #endif | 563 | #endif |
| 564 | {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, V | D }, | ||
| 564 | {"skip_alpha", "Skip processing alpha", OFFSET(skip_alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, V|D }, | 565 | {"skip_alpha", "Skip processing alpha", OFFSET(skip_alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, V|D }, |
| 565 | {"field_order", "Field order", OFFSET(field_order), AV_OPT_TYPE_INT, {.i64 = AV_FIELD_UNKNOWN }, 0, 5, V|D|E, "field_order" }, | 566 | {"field_order", "Field order", OFFSET(field_order), AV_OPT_TYPE_INT, {.i64 = AV_FIELD_UNKNOWN }, 0, 5, V|D|E, "field_order" }, |
| 566 | {"progressive", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_PROGRESSIVE }, 0, 0, V|D|E, "field_order" }, | 567 | {"progressive", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_PROGRESSIVE }, 0, 0, V|D|E, "field_order" }, |
| @@ -28,8 +28,8 @@ · 27 unmodified lines | |||
| 28 | #include "libavutil/version.h" | 28 | #include "libavutil/version.h" |
| 29 | 29 | ||
| 30 | #define LIBAVCODEC_VERSION_MAJOR 57 | 30 | #define LIBAVCODEC_VERSION_MAJOR 57 |
| 31 | #define LIBAVCODEC_VERSION_MINOR 94 | 31 | #define LIBAVCODEC_VERSION_MINOR 95 |
| 32 | #define LIBAVCODEC_VERSION_MICRO 101 | 32 | #define LIBAVCODEC_VERSION_MICRO 100 |
| 33 | 33 | ||
| 34 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | 34 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |
| 35 | LIBAVCODEC_VERSION_MINOR, \ | 35 | LIBAVCODEC_VERSION_MINOR, \ |
| @@ -149,6 +149,7 @@ stream=0, decode=0 · 148 unmodified lines | |||
| 149 | sub_text_format=1 | 149 | sub_text_format=1 |
| 150 | refcounted_frames=false | 150 | refcounted_frames=false |
| 151 | side_data_only_packets=true | 151 | side_data_only_packets=true |
| 152 | apply_cropping=true | ||
| 152 | skip_alpha=false | 153 | skip_alpha=false |
| 153 | field_order=0 | 154 | field_order=0 |
| 154 | dump_separator= | 155 | dump_separator= |
| @@ -307,6 +308,7 @@ stream=0, decode=1 · 152 unmodified lines | |||
| 307 | sub_text_format=1 | 308 | sub_text_format=1 |
| 308 | refcounted_frames=false | 309 | refcounted_frames=false |
| 309 | side_data_only_packets=true | 310 | side_data_only_packets=true |
| 311 | apply_cropping=true | ||
| 310 | skip_alpha=false | 312 | skip_alpha=false |
| 311 | field_order=0 | 313 | field_order=0 |
| 312 | dump_separator= | 314 | dump_separator= |
| @@ -149,6 +149,7 @@ stream=0, decode=0 · 148 unmodified lines | |||
| 149 | sub_text_format=1 | 149 | sub_text_format=1 |
| 150 | refcounted_frames=false | 150 | refcounted_frames=false |
| 151 | side_data_only_packets=true | 151 | side_data_only_packets=true |
| 152 | apply_cropping=true | ||
| 152 | skip_alpha=false | 153 | skip_alpha=false |
| 153 | field_order=0 | 154 | field_order=0 |
| 154 | dump_separator= | 155 | dump_separator= |
| @@ -307,6 +308,7 @@ stream=0, decode=1 · 152 unmodified lines | |||
| 307 | sub_text_format=1 | 308 | sub_text_format=1 |
| 308 | refcounted_frames=false | 309 | refcounted_frames=false |
| 309 | side_data_only_packets=true | 310 | side_data_only_packets=true |
| 311 | apply_cropping=true | ||
| 310 | skip_alpha=false | 312 | skip_alpha=false |
| 311 | field_order=0 | 313 | field_order=0 |
| 312 | dump_separator= | 314 | dump_separator= |