Unified · Split
| @@ -13,6 +13,9 @@ libavutil: 2017-03-23 · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | API changes, most recent first: |
| 15 | 15 | |
| 16 | +2017-xx-xx - xxxxxxx - lavu 56.3.0 - frame.h | |
| 17 | + Add av_frame_apply_cropping(). | |
| 18 | + | |
| 16 | 19 | 2017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h |
| 17 | 20 | DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API, |
| 18 | 21 | which can create the decoder context and allocate hardware frame automatically. |
| @@ -446,44 +446,8 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke · 445 unmodified lines | ||
| 446 | 446 | return 0; |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | −static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, | |
| 450 | − const AVPixFmtDescriptor *desc) | |
| 451 | −{ | |
| 452 | − int i, j; | |
| 453 | − | |
| 454 | − for (i = 0; frame->data[i]; i++) { | |
| 455 | − const AVComponentDescriptor *comp = NULL; | |
| 456 | − int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0; | |
| 457 | − int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; | |
| 458 | − | |
| 459 | − if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) { | |
| 460 | − offsets[i] = 0; | |
| 461 | − break; | |
| 462 | − } | |
| 463 | − | |
| 464 | − /* find any component descriptor for this plane */ | |
| 465 | − for (j = 0; j < desc->nb_components; j++) { | |
| 466 | − if (desc->comp[j].plane == i) { | |
| 467 | − comp = &desc->comp[j]; | |
| 468 | − break; | |
| 469 | − } | |
| 470 | − } | |
| 471 | − if (!comp) | |
| 472 | − return AVERROR_BUG; | |
| 473 | − | |
| 474 | − offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] + | |
| 475 | − (frame->crop_left >> shift_x) * comp->step; | |
| 476 | − } | |
| 477 | − | |
| 478 | − return 0; | |
| 479 | −} | |
| 480 | − | |
| 481 | 449 | static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) |
| 482 | 450 | { |
| 483 | − const AVPixFmtDescriptor *desc; | |
| 484 | − size_t offsets[4]; | |
| 485 | − int i; | |
| 486 | − | |
| 487 | 451 | /* make sure we are noisy about decoders returning invalid cropping data */ |
| 488 | 452 | if (frame->crop_left >= INT_MAX - frame->crop_right || |
| 489 | 453 | frame->crop_top >= INT_MAX - frame->crop_bottom || |
| @@ -504,57 +468,8 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) · 14 unmodified lines | ||
| 504 | 468 | if (!avctx->apply_cropping) |
| 505 | 469 | return 0; |
| 506 | 470 | |
| 507 | − desc = av_pix_fmt_desc_get(frame->format); | |
| 508 | − if (!desc) | |
| 509 | − return AVERROR_BUG; | |
| 510 | − | |
| 511 | − /* Apply just the right/bottom cropping for hwaccel formats. Bitstream | |
| 512 | − * formats cannot be easily handled here either (and corresponding decoders | |
| 513 | − * should not export any cropping anyway), so do the same for those as well. | |
| 514 | − * */ | |
| 515 | − if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) { | |
| 516 | − frame->width -= frame->crop_right; | |
| 517 | − frame->height -= frame->crop_bottom; | |
| 518 | − frame->crop_right = 0; | |
| 519 | − frame->crop_bottom = 0; | |
| 520 | − return 0; | |
| 521 | − } | |
| 522 | − | |
| 523 | − /* calculate the offsets for each plane */ | |
| 524 | − calc_cropping_offsets(offsets, frame, desc); | |
| 525 | − | |
| 526 | − /* adjust the offsets to avoid breaking alignment */ | |
| 527 | − if (!(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { | |
| 528 | − int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) : INT_MAX; | |
| 529 | − int min_log2_align = INT_MAX; | |
| 530 | − | |
| 531 | − for (i = 0; frame->data[i]; i++) { | |
| 532 | − int log2_align = offsets[i] ? av_ctz(offsets[i]) : INT_MAX; | |
| 533 | − min_log2_align = FFMIN(log2_align, min_log2_align); | |
| 534 | − } | |
| 535 | − | |
| 536 | − /* we assume, and it should always be true, that the data alignment is | |
| 537 | − * related to the cropping alignment by a constant power-of-2 factor */ | |
| 538 | − if (log2_crop_align < min_log2_align) | |
| 539 | − return AVERROR_BUG; | |
| 540 | − | |
| 541 | − if (min_log2_align < 5) { | |
| 542 | − frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1); | |
| 543 | − calc_cropping_offsets(offsets, frame, desc); | |
| 544 | − } | |
| 545 | − } | |
| 546 | − | |
| 547 | − for (i = 0; frame->data[i]; i++) | |
| 548 | − frame->data[i] += offsets[i]; | |
| 549 | − | |
| 550 | − frame->width -= (frame->crop_left + frame->crop_right); | |
| 551 | − frame->height -= (frame->crop_top + frame->crop_bottom); | |
| 552 | − frame->crop_left = 0; | |
| 553 | − frame->crop_right = 0; | |
| 554 | − frame->crop_top = 0; | |
| 555 | − frame->crop_bottom = 0; | |
| 556 | − | |
| 557 | − return 0; | |
| 471 | + return av_frame_apply_cropping(frame, avctx->flags & AV_CODEC_FLAG_UNALIGNED ? | |
| 472 | + AV_FRAME_CROP_UNALIGNED : 0); | |
| 558 | 473 | } |
| 559 | 474 | |
| 560 | 475 | int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) |
| @@ -596,3 +596,103 @@ void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) · 595 unmodified lines | ||
| 596 | 596 | } |
| 597 | 597 | } |
| 598 | 598 | } |
| 599 | + | |
| 600 | +static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, | |
| 601 | + const AVPixFmtDescriptor *desc) | |
| 602 | +{ | |
| 603 | + int i, j; | |
| 604 | + | |
| 605 | + for (i = 0; frame->data[i]; i++) { | |
| 606 | + const AVComponentDescriptor *comp = NULL; | |
| 607 | + int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0; | |
| 608 | + int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; | |
| 609 | + | |
| 610 | + if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) { | |
| 611 | + offsets[i] = 0; | |
| 612 | + break; | |
| 613 | + } | |
| 614 | + | |
| 615 | + /* find any component descriptor for this plane */ | |
| 616 | + for (j = 0; j < desc->nb_components; j++) { | |
| 617 | + if (desc->comp[j].plane == i) { | |
| 618 | + comp = &desc->comp[j]; | |
| 619 | + break; | |
| 620 | + } | |
| 621 | + } | |
| 622 | + if (!comp) | |
| 623 | + return AVERROR_BUG; | |
| 624 | + | |
| 625 | + offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] + | |
| 626 | + (frame->crop_left >> shift_x) * comp->step; | |
| 627 | + } | |
| 628 | + | |
| 629 | + return 0; | |
| 630 | +} | |
| 631 | + | |
| 632 | +int av_frame_apply_cropping(AVFrame *frame, int flags) | |
| 633 | +{ | |
| 634 | + const AVPixFmtDescriptor *desc; | |
| 635 | + size_t offsets[4]; | |
| 636 | + int i; | |
| 637 | + | |
| 638 | + if (!(frame->width > 0 && frame->height > 0)) | |
| 639 | + return AVERROR(EINVAL); | |
| 640 | + | |
| 641 | + if (frame->crop_left >= INT_MAX - frame->crop_right || | |
| 642 | + frame->crop_top >= INT_MAX - frame->crop_bottom || | |
| 643 | + (frame->crop_left + frame->crop_right) >= frame->width || | |
| 644 | + (frame->crop_top + frame->crop_bottom) >= frame->height) | |
| 645 | + return AVERROR(ERANGE); | |
| 646 | + | |
| 647 | + desc = av_pix_fmt_desc_get(frame->format); | |
| 648 | + if (!desc) | |
| 649 | + return AVERROR_BUG; | |
| 650 | + | |
| 651 | + /* Apply just the right/bottom cropping for hwaccel formats. Bitstream | |
| 652 | + * formats cannot be easily handled here either (and corresponding decoders | |
| 653 | + * should not export any cropping anyway), so do the same for those as well. | |
| 654 | + * */ | |
| 655 | + if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) { | |
| 656 | + frame->width -= frame->crop_right; | |
| 657 | + frame->height -= frame->crop_bottom; | |
| 658 | + frame->crop_right = 0; | |
| 659 | + frame->crop_bottom = 0; | |
| 660 | + return 0; | |
| 661 | + } | |
| 662 | + | |
| 663 | + /* calculate the offsets for each plane */ | |
| 664 | + calc_cropping_offsets(offsets, frame, desc); | |
| 665 | + | |
| 666 | + /* adjust the offsets to avoid breaking alignment */ | |
| 667 | + if (!(flags & AV_FRAME_CROP_UNALIGNED)) { | |
| 668 | + int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) : INT_MAX; | |
| 669 | + int min_log2_align = INT_MAX; | |
| 670 | + | |
| 671 | + for (i = 0; frame->data[i]; i++) { | |
| 672 | + int log2_align = offsets[i] ? av_ctz(offsets[i]) : INT_MAX; | |
| 673 | + min_log2_align = FFMIN(log2_align, min_log2_align); | |
| 674 | + } | |
| 675 | + | |
| 676 | + /* we assume, and it should always be true, that the data alignment is | |
| 677 | + * related to the cropping alignment by a constant power-of-2 factor */ | |
| 678 | + if (log2_crop_align < min_log2_align) | |
| 679 | + return AVERROR_BUG; | |
| 680 | + | |
| 681 | + if (min_log2_align < 5) { | |
| 682 | + frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1); | |
| 683 | + calc_cropping_offsets(offsets, frame, desc); | |
| 684 | + } | |
| 685 | + } | |
| 686 | + | |
| 687 | + for (i = 0; frame->data[i]; i++) | |
| 688 | + frame->data[i] += offsets[i]; | |
| 689 | + | |
| 690 | + frame->width -= (frame->crop_left + frame->crop_right); | |
| 691 | + frame->height -= (frame->crop_top + frame->crop_bottom); | |
| 692 | + frame->crop_left = 0; | |
| 693 | + frame->crop_right = 0; | |
| 694 | + frame->crop_top = 0; | |
| 695 | + frame->crop_bottom = 0; | |
| 696 | + | |
| 697 | + return 0; | |
| 698 | +} | |
| @@ -580,6 +580,40 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, · 579 unmodified lines | ||
| 580 | 580 | */ |
| 581 | 581 | void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); |
| 582 | 582 | |
| 583 | + | |
| 584 | +/** | |
| 585 | + * Flags for frame cropping. | |
| 586 | + */ | |
| 587 | +enum { | |
| 588 | + /** | |
| 589 | + * Apply the maximum possible cropping, even if it requires setting the | |
| 590 | + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data | |
| 591 | + * to Libav API is generally not allowed, and causes undefined behavior | |
| 592 | + * (such as crashes). You can pass unaligned data only to Libav APIs that | |
| 593 | + * are explicitly documented to accept it. Use this flag only if you | |
| 594 | + * absolutely know what you are doing. | |
| 595 | + */ | |
| 596 | + AV_FRAME_CROP_UNALIGNED = 1 << 0, | |
| 597 | +}; | |
| 598 | + | |
| 599 | +/** | |
| 600 | + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ | |
| 601 | + * crop_bottom fields. If cropping is successful, the function will adjust the | |
| 602 | + * data pointers and the width/height fields, and set the crop fields to 0. | |
| 603 | + * | |
| 604 | + * In all cases, the cropping boundaries will be rounded to the inherent | |
| 605 | + * alignment of the pixel format. In some cases, such as for opaque hwaccel | |
| 606 | + * formats, the left/top cropping is ignored. The crop fields are set to 0 even | |
| 607 | + * if the cropping was rounded or ignored. | |
| 608 | + * | |
| 609 | + * @param frame the frame which should be cropped | |
| 610 | + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. | |
| 611 | + * | |
| 612 | + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields | |
| 613 | + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. | |
| 614 | + */ | |
| 615 | +int av_frame_apply_cropping(AVFrame *frame, int flags); | |
| 616 | + | |
| 583 | 617 | /** |
| 584 | 618 | * @} |
| 585 | 619 | */ |
| @@ -54,7 +54,7 @@ · 53 unmodified lines | ||
| 54 | 54 | */ |
| 55 | 55 | |
| 56 | 56 | #define LIBAVUTIL_VERSION_MAJOR 56 |
| 57 | −#define LIBAVUTIL_VERSION_MINOR 2 | |
| 57 | +#define LIBAVUTIL_VERSION_MINOR 3 | |
| 58 | 58 | #define LIBAVUTIL_VERSION_MICRO 0 |
| 59 | 59 | |
| 60 | 60 | #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ |