History

avcodec/hevc: Add support for output_corrupt/showall flags

Also handle gradual decoding refresh stream.

Zhao Zhili committed 1 year ago

Commit bc1a3bf1 parent b6652116 files · +54 −4Browse files

Unified · Split

6 files
  1. libavcodec/hevc/hevcdec.c +21 −1
  2. libavcodec/hevc/hevcdec.h +6 −0
  3. libavcodec/hevc/refs.c +23 −1
  4. libavcodec/hevc/sei.c +1 −0
  5. libavcodec/hevc/sei.h +1 −0
  6. tests/fate/hevc.mak +2 −2
libavcodec/hevc/hevcdec.c+21−1
@@ -3306,9 +3306,19 @@ static int hevc_frame_start(HEVCContext *s, HEVCLayerContext *l, · 3305 unmodified lines
3306 s->first_nal_type = s->nal_unit_type;3306 s->first_nal_type = s->nal_unit_type;
3307 s->poc = s->sh.poc;3307 s->poc = s->sh.poc;
3308 3308
3309 if (IS_IRAP(s))3309 if (IS_IRAP(s)) {
3310 s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) ||3310 s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) ||
3311 (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos);3311 (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos);
3312 s->recovery_poc = HEVC_RECOVERY_END;
3313 }
3314
3315 if (s->recovery_poc != HEVC_RECOVERY_END &&
3316 s->sei.recovery_point.has_recovery_poc) {
3317 if (s->recovery_poc == HEVC_RECOVERY_UNSPECIFIED)
3318 s->recovery_poc = s->poc + s->sei.recovery_point.recovery_poc_cnt;
3319 else if (s->poc >= s->recovery_poc)
3320 s->recovery_poc = HEVC_RECOVERY_END;
3321 }
3312 3322
3313 /* 8.3.1 */3323 /* 8.3.1 */
3314 if (s->temporal_id == 0 &&3324 if (s->temporal_id == 0 &&
@@ -3684,6 +3694,12 @@ fail: · 369 unmodified lines
3684 return ret;3694 return ret;
3685}3695}
3686 3696
3697static void decode_reset_recovery_point(HEVCContext *s)
3698{
3699 s->recovery_poc = HEVC_RECOVERY_UNSPECIFIED;
3700 s->sei.recovery_point.has_recovery_poc = 0;
3701}
3702
3687static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)3703static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
3688{3704{
3689 int i, ret = 0;3705 int i, ret = 0;
@@ -3694,6 +3710,8 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) · 4 unmodified lines
3694 s->last_eos = s->eos;3710 s->last_eos = s->eos;
3695 s->eos = 0;3711 s->eos = 0;
3696 s->slice_initialized = 0;3712 s->slice_initialized = 0;
3713 if (s->last_eos)
3714 decode_reset_recovery_point(s);
3697 3715
3698 for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++) {3716 for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++) {
3699 HEVCLayerContext *l = &s->layers[i];3717 HEVCLayerContext *l = &s->layers[i];
@@ -3715,6 +3733,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) · 15 unmodified lines
3715 s->pkt.nals[i].type == HEVC_NAL_EOS_NUT) {3733 s->pkt.nals[i].type == HEVC_NAL_EOS_NUT) {
3716 if (eos_at_start) {3734 if (eos_at_start) {
3717 s->last_eos = 1;3735 s->last_eos = 1;
3736 decode_reset_recovery_point(s);
3718 } else {3737 } else {
3719 s->eos = 1;3738 s->eos = 1;
3720 }3739 }
@@ -4088,6 +4107,7 @@ static int hevc_update_thread_context(AVCodecContext *dst, · 367 unmodified lines
4088 s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer;4107 s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer;
4089 s->sei.tdrdi = s0->sei.tdrdi;4108 s->sei.tdrdi = s0->sei.tdrdi;
4090 s->sei.recovery_point = s0->sei.recovery_point;4109 s->sei.recovery_point = s0->sei.recovery_point;
4110 s->recovery_poc = s0->recovery_poc;
4091 4111
4092 return 0;4112 return 0;
4093}4113}
libavcodec/hevc/hevcdec.h+6−0
@@ -78,6 +78,10 @@ · 77 unmodified lines
78 (s)->nal_unit_type == HEVC_NAL_BLA_N_LP)78 (s)->nal_unit_type == HEVC_NAL_BLA_N_LP)
79#define IS_IRAP(s) ((s)->nal_unit_type >= HEVC_NAL_BLA_W_LP && (s)->nal_unit_type <= HEVC_NAL_RSV_IRAP_VCL23)79#define IS_IRAP(s) ((s)->nal_unit_type >= HEVC_NAL_BLA_W_LP && (s)->nal_unit_type <= HEVC_NAL_RSV_IRAP_VCL23)
80 80
81#define HEVC_RECOVERY_UNSPECIFIED INT_MAX
82#define HEVC_RECOVERY_END INT_MIN
83#define HEVC_IS_RECOVERING(s) ((s)->recovery_poc != HEVC_RECOVERY_UNSPECIFIED && (s)->recovery_poc != HEVC_RECOVERY_END)
84
81enum RPSType {85enum RPSType {
82 ST_CURR_BEF = 0,86 ST_CURR_BEF = 0,
83 ST_CURR_AFT,87 ST_CURR_AFT,
@@ -353,6 +357,7 @@ typedef struct DBParams { · 269 unmodified lines
353#define HEVC_FRAME_FLAG_SHORT_REF (1 << 1)357#define HEVC_FRAME_FLAG_SHORT_REF (1 << 1)
354#define HEVC_FRAME_FLAG_LONG_REF (1 << 2)358#define HEVC_FRAME_FLAG_LONG_REF (1 << 2)
355#define HEVC_FRAME_FLAG_UNAVAILABLE (1 << 3)359#define HEVC_FRAME_FLAG_UNAVAILABLE (1 << 3)
360#define HEVC_FRAME_FLAG_CORRUPT (1 << 4)
356 361
357typedef struct HEVCFrame {362typedef struct HEVCFrame {
358 union {363 union {
@@ -523,6 +528,7 @@ typedef struct HEVCContext { · 164 unmodified lines
523 int slice_idx; ///< number of the slice being currently decoded528 int slice_idx; ///< number of the slice being currently decoded
524 int eos; ///< current packet contains an EOS/EOB NAL529 int eos; ///< current packet contains an EOS/EOB NAL
525 int last_eos; ///< last packet contains an EOS/EOB NAL530 int last_eos; ///< last packet contains an EOS/EOB NAL
531 int recovery_poc;
526 532
527 // NoRaslOutputFlag associated with the last IRAP frame533 // NoRaslOutputFlag associated with the last IRAP frame
528 int no_rasl_output_flag;534 int no_rasl_output_flag;
libavcodec/hevc/refs.c+23−1
@@ -34,6 +34,8 @@ · 33 unmodified lines
34void ff_hevc_unref_frame(HEVCFrame *frame, int flags)34void ff_hevc_unref_frame(HEVCFrame *frame, int flags)
35{35{
36 frame->flags &= ~flags;36 frame->flags &= ~flags;
37 if (!(frame->flags & ~HEVC_FRAME_FLAG_CORRUPT))
38 frame->flags = 0;
37 if (!frame->flags) {39 if (!frame->flags) {
38 ff_progress_frame_unref(&frame->tf);40 ff_progress_frame_unref(&frame->tf);
39 av_frame_unref(frame->frame_grain);41 av_frame_unref(frame->frame_grain);
@@ -208,6 +210,7 @@ int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext *l, int poc) · 168 unmodified lines
208{210{
209 HEVCFrame *ref;211 HEVCFrame *ref;
210 int i;212 int i;
213 int no_output;
211 214
212 /* check that this POC doesn't already exist */215 /* check that this POC doesn't already exist */
213 for (i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {216 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) · 17 unmodified lines
231 ref->base_layer_frame = (l != &s->layers[0] && s->layers[0].cur_frame) ?234 ref->base_layer_frame = (l != &s->layers[0] && s->layers[0].cur_frame) ?
232 s->layers[0].cur_frame - s->layers[0].DPB : -1;235 s->layers[0].cur_frame - s->layers[0].DPB : -1;
233 236
234 if (s->sh.pic_output_flag)237 no_output = !IS_IRAP(s) && (s->poc < s->recovery_poc) &&
238 !(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
239 !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL);
240 if (s->sh.pic_output_flag && !no_output)
235 ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF;241 ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF;
236 else242 else
237 ref->flags = HEVC_FRAME_FLAG_SHORT_REF;243 ref->flags = HEVC_FRAME_FLAG_SHORT_REF;
@@ -298,6 +304,8 @@ int ff_hevc_output_frames(HEVCContext *s, · 60 unmodified lines
298 int output = !discard && (layers_active_output & (1 << min_layer));304 int output = !discard && (layers_active_output & (1 << min_layer));
299 305
300 if (output) {306 if (output) {
307 if (frame->flags & HEVC_FRAME_FLAG_CORRUPT)
308 f->flags |= AV_FRAME_FLAG_CORRUPT;
301 f->pkt_dts = s->pkt_dts;309 f->pkt_dts = s->pkt_dts;
302 ret = av_container_fifo_write(s->output_fifo, f, AV_CONTAINER_FIFO_FLAG_REF);310 ret = av_container_fifo_write(s->output_fifo, f, AV_CONTAINER_FIFO_FLAG_REF);
303 }311 }
@@ -494,6 +502,20 @@ static int add_candidate_ref(HEVCContext *s, HEVCLayerContext *l, · 190 unmodified lines
494 if (ref == s->cur_frame || list->nb_refs >= HEVC_MAX_REFS)502 if (ref == s->cur_frame || list->nb_refs >= HEVC_MAX_REFS)
495 return AVERROR_INVALIDDATA;503 return AVERROR_INVALIDDATA;
496 504
505 if (!IS_IRAP(s)) {
506 int ref_corrupt = !ref || ref->flags & (HEVC_FRAME_FLAG_CORRUPT |
507 HEVC_FRAME_FLAG_UNAVAILABLE);
508 int recovering = HEVC_IS_RECOVERING(s);
509
510 if (ref_corrupt && !recovering) {
511 if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
512 !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
513 return AVERROR_INVALIDDATA;
514
515 s->cur_frame->flags |= HEVC_FRAME_FLAG_CORRUPT;
516 }
517 }
518
497 if (!ref) {519 if (!ref) {
498 ref = generate_missing_ref(s, l, poc);520 ref = generate_missing_ref(s, l, poc);
499 if (!ref)521 if (!ref)
libavcodec/hevc/sei.c+1−0
@@ -89,6 +89,7 @@ static int decode_nal_sei_recovery_point(HEVCSEI *s, GetBitContext *gb) · 88 unmodified lines
89 rec->recovery_poc_cnt = recovery_poc_cnt;89 rec->recovery_poc_cnt = recovery_poc_cnt;
90 rec->exact_match_flag = get_bits1(gb);90 rec->exact_match_flag = get_bits1(gb);
91 rec->broken_link_flag = get_bits1(gb);91 rec->broken_link_flag = get_bits1(gb);
92 rec->has_recovery_poc = 1;
92 93
93 return 0;94 return 0;
94}95}
libavcodec/hevc/sei.h+1−0
@@ -99,6 +99,7 @@ typedef struct HEVCSEIRecoveryPoint { · 98 unmodified lines
99 int16_t recovery_poc_cnt;99 int16_t recovery_poc_cnt;
100 uint8_t exact_match_flag;100 uint8_t exact_match_flag;
101 uint8_t broken_link_flag;101 uint8_t broken_link_flag;
102 uint8_t has_recovery_poc;
102} HEVCSEIRecoveryPoint;103} HEVCSEIRecoveryPoint;
103 104
104typedef struct HEVCSEI {105typedef struct HEVCSEI {
tests/fate/hevc.mak+2−2
@@ -207,7 +207,7 @@ $(HEVC_TESTS_444_8BIT): SCALE_OPTS := -pix_fmt yuv444p · 206 unmodified lines
207$(HEVC_TESTS_10BIT): SCALE_OPTS := -pix_fmt yuv420p10le -vf scale207$(HEVC_TESTS_10BIT): SCALE_OPTS := -pix_fmt yuv420p10le -vf scale
208$(HEVC_TESTS_422_10BIT) $(HEVC_TESTS_422_10BIN): SCALE_OPTS := -pix_fmt yuv422p10le -vf scale208$(HEVC_TESTS_422_10BIT) $(HEVC_TESTS_422_10BIN): SCALE_OPTS := -pix_fmt yuv422p10le -vf scale
209$(HEVC_TESTS_444_12BIT): SCALE_OPTS := -pix_fmt yuv444p12le -vf scale209$(HEVC_TESTS_444_12BIT): SCALE_OPTS := -pix_fmt yuv444p12le -vf scale
210fate-hevc-conformance-%: CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit $(SCALE_OPTS)210fate-hevc-conformance-%: CMD = framecrc -flags output_corrupt -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit $(SCALE_OPTS)
211$(HEVC_TESTS_422_10BIN): CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bin $(SCALE_OPTS)211$(HEVC_TESTS_422_10BIN): CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bin $(SCALE_OPTS)
212$(HEVC_TESTS_MULTIVIEW): CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit \212$(HEVC_TESTS_MULTIVIEW): CMD = framecrc -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit \
213 -pix_fmt yuv420p -map "0:view:0" -map "0:view:1" -vf setpts=N:strip_fps=1213 -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 · 34 unmodified lines
248fate-hevc-monochrome-crop: CMD = probeframes -show_entries frame=width,height:stream=width,height $(TARGET_SAMPLES)/hevc/hevc-monochrome.hevc248fate-hevc-monochrome-crop: CMD = probeframes -show_entries frame=width,height:stream=width,height $(TARGET_SAMPLES)/hevc/hevc-monochrome.hevc
249FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-monochrome-crop249FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-monochrome-crop
250 250
251fate-hevc-afd-tc-sei: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -bitexact -show_entries frame_side_data_list -select_streams v $(TARGET_SAMPLES)/mpegts/loewe.ts251fate-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
252FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-afd-tc-sei252FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-afd-tc-sei
253 253
254fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc254fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc

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