History

lavc, lavu: move frame cropping to a convenience function

wm4 committed 9 years ago

Commit 47399cc1 parent 80e919b5 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
@@ -13,6 +13,9 @@ libavutil: 2017-03-23 · 12 unmodified lines
13 13
14API changes, most recent first:14API changes, most recent first:
15 15
162017-xx-xx - xxxxxxx - lavu 56.3.0 - frame.h
17 Add av_frame_apply_cropping().
18
162017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h192017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h
17 DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API,20 DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API,
18 which can create the decoder context and allocate hardware frame automatically.21 which can create the decoder context and allocate hardware frame automatically.
libavcodec/decode.c+2−87
@@ -446,44 +446,8 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke · 445 unmodified lines
446 return 0;446 return 0;
447}447}
448 448
449static 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
481static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)449static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)
482{450{
483 const AVPixFmtDescriptor *desc;
484 size_t offsets[4];
485 int i;
486
487 /* make sure we are noisy about decoders returning invalid cropping data */451 /* make sure we are noisy about decoders returning invalid cropping data */
488 if (frame->crop_left >= INT_MAX - frame->crop_right ||452 if (frame->crop_left >= INT_MAX - frame->crop_right ||
489 frame->crop_top >= INT_MAX - frame->crop_bottom ||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 if (!avctx->apply_cropping)468 if (!avctx->apply_cropping)
505 return 0;469 return 0;
506 470
507 desc = av_pix_fmt_desc_get(frame->format);471 return av_frame_apply_cropping(frame, avctx->flags & AV_CODEC_FLAG_UNALIGNED ?
508 if (!desc)472 AV_FRAME_CROP_UNALIGNED : 0);
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;
558}473}
559 474
560int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)475int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
libavutil/frame.c+100−0
@@ -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
600static 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
632int 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}
libavutil/frame.h+34−0
@@ -580,6 +580,40 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, · 579 unmodified lines
580 */580 */
581void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);581void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
582 582
583
584/**
585 * Flags for frame cropping.
586 */
587enum {
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 */
615int av_frame_apply_cropping(AVFrame *frame, int flags);
616
583/**617/**
584 * @}618 * @}
585 */619 */
libavutil/version.h+1−1
@@ -54,7 +54,7 @@ · 53 unmodified lines
54 */54 */
55 55
56#define LIBAVUTIL_VERSION_MAJOR 5656#define LIBAVUTIL_VERSION_MAJOR 56
57#define LIBAVUTIL_VERSION_MINOR 257#define LIBAVUTIL_VERSION_MINOR 3
58#define LIBAVUTIL_VERSION_MICRO 058#define LIBAVUTIL_VERSION_MICRO 0
59 59
60#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \60#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