@@ -49,6 +49,7 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, | |||||
HEVCPPS *pps; | HEVCPPS *pps; | ||||
HEVCSPS *sps; | HEVCSPS *sps; | ||||
HEVCWindow *ow; | |||||
unsigned int pps_id; | unsigned int pps_id; | ||||
get_bits1(gb); // first slice in pic | 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; | pps = (HEVCPPS*)ctx->ps.pps_list[pps_id]->data; | ||||
sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data; | sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data; | ||||
ow = &sps->output_window; | |||||
/* export the stream parameters */ | /* export the stream parameters */ | ||||
s->coded_width = sps->width; | s->coded_width = sps->width; | ||||
s->coded_height = sps->height; | 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; | s->format = sps->pix_fmt; | ||||
avctx->profile = sps->ptl.general_ptl.profile_idc; | avctx->profile = sps->ptl.general_ptl.profile_idc; | ||||
avctx->level = sps->ptl.general_ptl.level_idc; | avctx->level = sps->ptl.general_ptl.level_idc; | ||||
@@ -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 ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, | ||||
int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx) | int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx) | ||||
{ | { | ||||
HEVCWindow *ow; | |||||
int ret = 0; | int ret = 0; | ||||
int log2_diff_max_min_transform_block_size; | int log2_diff_max_min_transform_block_size; | ||||
int bit_depth_chroma, start, vui_present, sublayer_ordering_info; | 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.top_offset += sps->vui.def_disp_win.top_offset; | ||||
sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_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) { | if (avctx->err_recognition & AV_EF_EXPLODE) { | ||||
ret = AVERROR_INVALIDDATA; | ret = AVERROR_INVALIDDATA; | ||||
goto err; | goto err; | ||||
} | } | ||||
av_log(avctx, AV_LOG_WARNING, | av_log(avctx, AV_LOG_WARNING, | ||||
"Displaying the whole video surface.\n"); | "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 | // Inferred parameters | ||||
@@ -1008,7 +998,8 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, | |||||
"Parsed SPS: id %d; coded wxh: %dx%d; " | "Parsed SPS: id %d; coded wxh: %dx%d; " | ||||
"cropped wxh: %dx%d; pix_fmt: %s.\n", | "cropped wxh: %dx%d; pix_fmt: %s.\n", | ||||
sps_id, sps->width, sps->height, | 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)); | av_get_pix_fmt_name(sps->pix_fmt)); | ||||
} | } | ||||
@@ -141,8 +141,6 @@ typedef struct HEVCSPS { | |||||
int chroma_format_idc; | int chroma_format_idc; | ||||
uint8_t separate_colour_plane_flag; | uint8_t separate_colour_plane_flag; | ||||
///< output (i.e. cropped) values | |||||
int output_width, output_height; | |||||
HEVCWindow output_window; | HEVCWindow output_window; | ||||
HEVCWindow pic_conf_win; | HEVCWindow pic_conf_win; | ||||
@@ -162,7 +162,10 @@ int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc) | |||||
ref->poc = poc; | ref->poc = poc; | ||||
ref->sequence = s->seq_decode; | 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; | return 0; | ||||
} | } | ||||
@@ -193,26 +196,12 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) | |||||
if (nb_output) { | if (nb_output) { | ||||
HEVCFrame *frame = &s->DPB[min_idx]; | 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); | ret = av_frame_ref(out, frame->frame); | ||||
ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT); | ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT); | ||||
if (ret < 0) | if (ret < 0) | ||||
return ret; | 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, | av_log(s->avctx, AV_LOG_DEBUG, | ||||
"Output frame with POC %d.\n", frame->poc); | "Output frame with POC %d.\n", frame->poc); | ||||
return 1; | return 1; | ||||
@@ -338,13 +338,14 @@ static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps, | |||||
const HEVCSPS *sps) | const HEVCSPS *sps) | ||||
{ | { | ||||
const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data; | const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data; | ||||
const HEVCWindow *ow = &sps->output_window; | |||||
unsigned int num = 0, den = 0; | unsigned int num = 0, den = 0; | ||||
avctx->pix_fmt = sps->pix_fmt; | avctx->pix_fmt = sps->pix_fmt; | ||||
avctx->coded_width = sps->width; | avctx->coded_width = sps->width; | ||||
avctx->coded_height = sps->height; | 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->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; | ||||
avctx->profile = sps->ptl.general_ptl.profile_idc; | avctx->profile = sps->ptl.general_ptl.profile_idc; | ||||
avctx->level = sps->ptl.general_ptl.level_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->poc = src->poc; | ||||
dst->ctb_count = src->ctb_count; | dst->ctb_count = src->ctb_count; | ||||
dst->window = src->window; | |||||
dst->flags = src->flags; | dst->flags = src->flags; | ||||
dst->sequence = src->sequence; | dst->sequence = src->sequence; | ||||
@@ -3092,4 +3092,5 @@ AVCodec ff_hevc_decoder = { | |||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | | .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | | ||||
AV_CODEC_CAP_FRAME_THREADS, | AV_CODEC_CAP_FRAME_THREADS, | ||||
.profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), | .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), | ||||
.caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING, | |||||
}; | }; |
@@ -374,8 +374,6 @@ typedef struct HEVCFrame { | |||||
int poc; | int poc; | ||||
struct HEVCFrame *collocated_ref; | struct HEVCFrame *collocated_ref; | ||||
HEVCWindow window; | |||||
AVBufferRef *tab_mvf_buf; | AVBufferRef *tab_mvf_buf; | ||||
AVBufferRef *rpl_tab_buf; | AVBufferRef *rpl_tab_buf; | ||||
AVBufferRef *rpl_buf; | AVBufferRef *rpl_buf; | ||||