diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index 49e712269b..74a0257073 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -49,6 +49,7 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, HEVCPPS *pps; HEVCSPS *sps; + HEVCWindow *ow; unsigned int pps_id; get_bits1(gb); // first slice in pic @@ -62,12 +63,13 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, } pps = (HEVCPPS*)ctx->ps.pps_list[pps_id]->data; sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data; + ow = &sps->output_window; /* export the stream parameters */ s->coded_width = sps->width; s->coded_height = sps->height; - s->width = sps->output_width; - s->height = sps->output_height; + s->width = sps->width - ow->left_offset - ow->right_offset; + s->height = sps->height - ow->top_offset - ow->bottom_offset; s->format = sps->pix_fmt; avctx->profile = sps->ptl.general_ptl.profile_idc; avctx->level = sps->ptl.general_ptl.level_idc; diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 2471907077..4a5a47e20e 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -682,6 +682,7 @@ static int map_pixel_format(AVCodecContext *avctx, HEVCSPS *sps) int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx) { + HEVCWindow *ow; int ret = 0; int log2_diff_max_min_transform_block_size; int bit_depth_chroma, start, vui_present, sublayer_ordering_info; @@ -902,32 +903,21 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, sps->output_window.top_offset += sps->vui.def_disp_win.top_offset; sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_offset; } - if (sps->output_window.left_offset & (0x1F >> (sps->pixel_shift)) && - !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { - sps->output_window.left_offset &= ~(0x1F >> (sps->pixel_shift)); - av_log(avctx, AV_LOG_WARNING, "Reducing left output window to %d " - "chroma samples to preserve alignment.\n", - sps->output_window.left_offset); - } - sps->output_width = sps->width - - (sps->output_window.left_offset + sps->output_window.right_offset); - sps->output_height = sps->height - - (sps->output_window.top_offset + sps->output_window.bottom_offset); - if (sps->output_width <= 0 || sps->output_height <= 0) { - av_log(avctx, AV_LOG_WARNING, "Invalid visible frame dimensions: %dx%d.\n", - sps->output_width, sps->output_height); + + ow = &sps->output_window; + if (ow->left_offset >= INT_MAX - ow->right_offset || + ow->top_offset >= INT_MAX - ow->bottom_offset || + ow->left_offset + ow->right_offset >= sps->width || + ow->top_offset + ow->bottom_offset >= sps->height) { + av_log(avctx, AV_LOG_WARNING, "Invalid cropping offsets: %u/%u/%u/%u\n", + ow->left_offset, ow->right_offset, ow->top_offset, ow->bottom_offset); if (avctx->err_recognition & AV_EF_EXPLODE) { ret = AVERROR_INVALIDDATA; goto err; } av_log(avctx, AV_LOG_WARNING, "Displaying the whole video surface.\n"); - sps->output_window.left_offset = - sps->output_window.right_offset = - sps->output_window.top_offset = - sps->output_window.bottom_offset = 0; - sps->output_width = sps->width; - sps->output_height = sps->height; + memset(ow, 0, sizeof(*ow)); } // Inferred parameters @@ -1008,7 +998,8 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, "Parsed SPS: id %d; coded wxh: %dx%d; " "cropped wxh: %dx%d; pix_fmt: %s.\n", sps_id, sps->width, sps->height, - sps->output_width, sps->output_height, + sps->width - (sps->output_window.left_offset + sps->output_window.right_offset), + sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset), av_get_pix_fmt_name(sps->pix_fmt)); } diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index d95aa519e6..89a481ba8e 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -141,8 +141,6 @@ typedef struct HEVCSPS { int chroma_format_idc; uint8_t separate_colour_plane_flag; - ///< output (i.e. cropped) values - int output_width, output_height; HEVCWindow output_window; HEVCWindow pic_conf_win; diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 30409bae5f..0c1918793e 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -162,7 +162,10 @@ int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc) ref->poc = poc; ref->sequence = s->seq_decode; - ref->window = s->ps.sps->output_window; + ref->frame->crop_left = s->ps.sps->output_window.left_offset; + ref->frame->crop_right = s->ps.sps->output_window.right_offset; + ref->frame->crop_top = s->ps.sps->output_window.top_offset; + ref->frame->crop_bottom = s->ps.sps->output_window.bottom_offset; return 0; } @@ -193,26 +196,12 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) if (nb_output) { HEVCFrame *frame = &s->DPB[min_idx]; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->frame->format); - int pixel_shift; - - if (!desc) - return AVERROR_BUG; - - pixel_shift = desc->comp[0].depth > 8; ret = av_frame_ref(out, frame->frame); ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT); if (ret < 0) return ret; - for (i = 0; i < 3; i++) { - int hshift = (i > 0) ? desc->log2_chroma_w : 0; - int vshift = (i > 0) ? desc->log2_chroma_h : 0; - int off = ((frame->window.left_offset >> hshift) << pixel_shift) + - (frame->window.top_offset >> vshift) * out->linesize[i]; - out->data[i] += off; - } av_log(s->avctx, AV_LOG_DEBUG, "Output frame with POC %d.\n", frame->poc); return 1; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 700b5f09a0..a4c936ee05 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -338,13 +338,14 @@ static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps, const HEVCSPS *sps) { const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data; + const HEVCWindow *ow = &sps->output_window; unsigned int num = 0, den = 0; avctx->pix_fmt = sps->pix_fmt; avctx->coded_width = sps->width; avctx->coded_height = sps->height; - avctx->width = sps->output_width; - avctx->height = sps->output_height; + avctx->width = sps->width - ow->left_offset - ow->right_offset; + avctx->height = sps->height - ow->top_offset - ow->bottom_offset; avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; avctx->profile = sps->ptl.general_ptl.profile_idc; avctx->level = sps->ptl.general_ptl.level_idc; @@ -2864,7 +2865,6 @@ static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src) dst->poc = src->poc; dst->ctb_count = src->ctb_count; - dst->window = src->window; dst->flags = src->flags; dst->sequence = src->sequence; @@ -3092,4 +3092,5 @@ AVCodec ff_hevc_decoder = { .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), + .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING, }; diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 82adad20c6..ff192f67ae 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -374,8 +374,6 @@ typedef struct HEVCFrame { int poc; struct HEVCFrame *collocated_ref; - HEVCWindow window; - AVBufferRef *tab_mvf_buf; AVBufferRef *rpl_tab_buf; AVBufferRef *rpl_buf;