You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
avcodec/hevc: Add support for output_corrupt/showall flags
Also handle gradual decoding refresh stream. Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
This commit is contained in:
@@ -3306,9 +3306,19 @@ static int hevc_frame_start(HEVCContext *s, HEVCLayerContext *l,
|
||||
s->first_nal_type = s->nal_unit_type;
|
||||
s->poc = s->sh.poc;
|
||||
|
||||
if (IS_IRAP(s))
|
||||
if (IS_IRAP(s)) {
|
||||
s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) ||
|
||||
(s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos);
|
||||
s->recovery_poc = HEVC_RECOVERY_END;
|
||||
}
|
||||
|
||||
if (s->recovery_poc != HEVC_RECOVERY_END &&
|
||||
s->sei.recovery_point.has_recovery_poc) {
|
||||
if (s->recovery_poc == HEVC_RECOVERY_UNSPECIFIED)
|
||||
s->recovery_poc = s->poc + s->sei.recovery_point.recovery_poc_cnt;
|
||||
else if (s->poc >= s->recovery_poc)
|
||||
s->recovery_poc = HEVC_RECOVERY_END;
|
||||
}
|
||||
|
||||
/* 8.3.1 */
|
||||
if (s->temporal_id == 0 &&
|
||||
@@ -3684,6 +3694,12 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void decode_reset_recovery_point(HEVCContext *s)
|
||||
{
|
||||
s->recovery_poc = HEVC_RECOVERY_UNSPECIFIED;
|
||||
s->sei.recovery_point.has_recovery_poc = 0;
|
||||
}
|
||||
|
||||
static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
||||
{
|
||||
int i, ret = 0;
|
||||
@@ -3694,6 +3710,8 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
||||
s->last_eos = s->eos;
|
||||
s->eos = 0;
|
||||
s->slice_initialized = 0;
|
||||
if (s->last_eos)
|
||||
decode_reset_recovery_point(s);
|
||||
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++) {
|
||||
HEVCLayerContext *l = &s->layers[i];
|
||||
@@ -3715,6 +3733,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
||||
s->pkt.nals[i].type == HEVC_NAL_EOS_NUT) {
|
||||
if (eos_at_start) {
|
||||
s->last_eos = 1;
|
||||
decode_reset_recovery_point(s);
|
||||
} else {
|
||||
s->eos = 1;
|
||||
}
|
||||
@@ -4088,6 +4107,7 @@ static int hevc_update_thread_context(AVCodecContext *dst,
|
||||
s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer;
|
||||
s->sei.tdrdi = s0->sei.tdrdi;
|
||||
s->sei.recovery_point = s0->sei.recovery_point;
|
||||
s->recovery_poc = s0->recovery_poc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -78,6 +78,10 @@
|
||||
(s)->nal_unit_type == HEVC_NAL_BLA_N_LP)
|
||||
#define IS_IRAP(s) ((s)->nal_unit_type >= HEVC_NAL_BLA_W_LP && (s)->nal_unit_type <= HEVC_NAL_RSV_IRAP_VCL23)
|
||||
|
||||
#define HEVC_RECOVERY_UNSPECIFIED INT_MAX
|
||||
#define HEVC_RECOVERY_END INT_MIN
|
||||
#define HEVC_IS_RECOVERING(s) ((s)->recovery_poc != HEVC_RECOVERY_UNSPECIFIED && (s)->recovery_poc != HEVC_RECOVERY_END)
|
||||
|
||||
enum RPSType {
|
||||
ST_CURR_BEF = 0,
|
||||
ST_CURR_AFT,
|
||||
@@ -353,6 +357,7 @@ typedef struct DBParams {
|
||||
#define HEVC_FRAME_FLAG_SHORT_REF (1 << 1)
|
||||
#define HEVC_FRAME_FLAG_LONG_REF (1 << 2)
|
||||
#define HEVC_FRAME_FLAG_UNAVAILABLE (1 << 3)
|
||||
#define HEVC_FRAME_FLAG_CORRUPT (1 << 4)
|
||||
|
||||
typedef struct HEVCFrame {
|
||||
union {
|
||||
@@ -523,6 +528,7 @@ typedef struct HEVCContext {
|
||||
int slice_idx; ///< number of the slice being currently decoded
|
||||
int eos; ///< current packet contains an EOS/EOB NAL
|
||||
int last_eos; ///< last packet contains an EOS/EOB NAL
|
||||
int recovery_poc;
|
||||
|
||||
// NoRaslOutputFlag associated with the last IRAP frame
|
||||
int no_rasl_output_flag;
|
||||
|
@@ -34,6 +34,8 @@
|
||||
void ff_hevc_unref_frame(HEVCFrame *frame, int flags)
|
||||
{
|
||||
frame->flags &= ~flags;
|
||||
if (!(frame->flags & ~HEVC_FRAME_FLAG_CORRUPT))
|
||||
frame->flags = 0;
|
||||
if (!frame->flags) {
|
||||
ff_progress_frame_unref(&frame->tf);
|
||||
av_frame_unref(frame->frame_grain);
|
||||
@@ -208,6 +210,7 @@ int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext *l, int poc)
|
||||
{
|
||||
HEVCFrame *ref;
|
||||
int i;
|
||||
int no_output;
|
||||
|
||||
/* check that this POC doesn't already exist */
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
|
||||
@@ -231,7 +234,10 @@ int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext *l, int poc)
|
||||
ref->base_layer_frame = (l != &s->layers[0] && s->layers[0].cur_frame) ?
|
||||
s->layers[0].cur_frame - s->layers[0].DPB : -1;
|
||||
|
||||
if (s->sh.pic_output_flag)
|
||||
no_output = !IS_IRAP(s) && (s->poc < s->recovery_poc) &&
|
||||
!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
|
||||
!(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL);
|
||||
if (s->sh.pic_output_flag && !no_output)
|
||||
ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF;
|
||||
else
|
||||
ref->flags = HEVC_FRAME_FLAG_SHORT_REF;
|
||||
@@ -298,6 +304,8 @@ int ff_hevc_output_frames(HEVCContext *s,
|
||||
int output = !discard && (layers_active_output & (1 << min_layer));
|
||||
|
||||
if (output) {
|
||||
if (frame->flags & HEVC_FRAME_FLAG_CORRUPT)
|
||||
f->flags |= AV_FRAME_FLAG_CORRUPT;
|
||||
f->pkt_dts = s->pkt_dts;
|
||||
ret = av_container_fifo_write(s->output_fifo, f, AV_CONTAINER_FIFO_FLAG_REF);
|
||||
}
|
||||
@@ -494,6 +502,20 @@ static int add_candidate_ref(HEVCContext *s, HEVCLayerContext *l,
|
||||
if (ref == s->cur_frame || list->nb_refs >= HEVC_MAX_REFS)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
if (!IS_IRAP(s)) {
|
||||
int ref_corrupt = !ref || ref->flags & (HEVC_FRAME_FLAG_CORRUPT |
|
||||
HEVC_FRAME_FLAG_UNAVAILABLE);
|
||||
int recovering = HEVC_IS_RECOVERING(s);
|
||||
|
||||
if (ref_corrupt && !recovering) {
|
||||
if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
|
||||
!(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
s->cur_frame->flags |= HEVC_FRAME_FLAG_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ref) {
|
||||
ref = generate_missing_ref(s, l, poc);
|
||||
if (!ref)
|
||||
|
@@ -89,6 +89,7 @@ static int decode_nal_sei_recovery_point(HEVCSEI *s, GetBitContext *gb)
|
||||
rec->recovery_poc_cnt = recovery_poc_cnt;
|
||||
rec->exact_match_flag = get_bits1(gb);
|
||||
rec->broken_link_flag = get_bits1(gb);
|
||||
rec->has_recovery_poc = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -99,6 +99,7 @@ typedef struct HEVCSEIRecoveryPoint {
|
||||
int16_t recovery_poc_cnt;
|
||||
uint8_t exact_match_flag;
|
||||
uint8_t broken_link_flag;
|
||||
uint8_t has_recovery_poc;
|
||||
} HEVCSEIRecoveryPoint;
|
||||
|
||||
typedef struct HEVCSEI {
|
||||
|
@@ -207,7 +207,7 @@ $(HEVC_TESTS_444_8BIT): SCALE_OPTS := -pix_fmt yuv444p
|
||||
$(HEVC_TESTS_10BIT): SCALE_OPTS := -pix_fmt yuv420p10le -vf scale
|
||||
$(HEVC_TESTS_422_10BIT) $(HEVC_TESTS_422_10BIN): SCALE_OPTS := -pix_fmt yuv422p10le -vf scale
|
||||
$(HEVC_TESTS_444_12BIT): SCALE_OPTS := -pix_fmt yuv444p12le -vf scale
|
||||
fate-hevc-conformance-%: CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit $(SCALE_OPTS)
|
||||
fate-hevc-conformance-%: CMD = framecrc -flags output_corrupt -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit $(SCALE_OPTS)
|
||||
$(HEVC_TESTS_422_10BIN): CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bin $(SCALE_OPTS)
|
||||
$(HEVC_TESTS_MULTIVIEW): CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit \
|
||||
-pix_fmt yuv420p -map "0:view:0" -map "0:view:1" -vf setpts=N:strip_fps=1
|
||||
@@ -248,7 +248,7 @@ FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-paired-fields
|
||||
fate-hevc-monochrome-crop: CMD = probeframes -show_entries frame=width,height:stream=width,height $(TARGET_SAMPLES)/hevc/hevc-monochrome.hevc
|
||||
FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-monochrome-crop
|
||||
|
||||
fate-hevc-afd-tc-sei: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -bitexact -show_entries frame_side_data_list -select_streams v $(TARGET_SAMPLES)/mpegts/loewe.ts
|
||||
fate-hevc-afd-tc-sei: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -bitexact -flags output_corrupt -show_entries frame_side_data_list -select_streams v $(TARGET_SAMPLES)/mpegts/loewe.ts
|
||||
FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-afd-tc-sei
|
||||
|
||||
fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc
|
||||
|
Reference in New Issue
Block a user