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
1313
1414 API changes, most recent first:
1515
16+2017-xx-xx - xxxxxxx - lavu 56.3.0 - frame.h
17+ Add av_frame_apply_cropping().
18+
1619 2017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h
1720 DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API,
1821 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
446446 return 0;
447447 }
448448
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−
481449 static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)
482450 {
483− const AVPixFmtDescriptor *desc;
484− size_t offsets[4];
485− int i;
486−
487451 /* make sure we are noisy about decoders returning invalid cropping data */
488452 if (frame->crop_left >= INT_MAX - frame->crop_right ||
489453 frame->crop_top >= INT_MAX - frame->crop_bottom ||
@@ -504,57 +468,8 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) · 14 unmodified lines
504468 if (!avctx->apply_cropping)
505469 return 0;
506470
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);
558473 }
559474
560475 int 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
596596 }
597597 }
598598 }
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+}
libavutil/frame.h+34−0
@@ -580,6 +580,40 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, · 579 unmodified lines
580580 */
581581 void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
582582
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+
583617 /**
584618 * @}
585619 */
libavutil/version.h+1−1
@@ -54,7 +54,7 @@ · 53 unmodified lines
5454 */
5555
5656 #define LIBAVUTIL_VERSION_MAJOR 56
57−#define LIBAVUTIL_VERSION_MINOR 2
57+#define LIBAVUTIL_VERSION_MINOR 3
5858 #define LIBAVUTIL_VERSION_MICRO 0
5959
6060 #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