History

lavc/hevcdec: simplify output logic

Current code is written around the "simple" decode API's limitation that a single input packet (AU/coded frame) triggers the output of at most one output frame. However the spec contains two cases where a coded frame may cause multiple frames to be output (cf. C.5.2.2.2): * start of a new sequence * overflowing sps_max_dec_pic_buffering The decoder currently contains rather convoluted logic to handle these cases: * decode/output/per-frame sequence counters, * HEVC_FRAME_FLAG_BUMPING * ff_hevc_bump_frame() * special clauses in ff_hevc_output_frame() However, with the receive_frame() API none of that is necessary, as we can just output multiple frames at once. Previously added ContainerFifo allows that to be done in a straightforward and efficient manner.

Anton Khirnov committed 2 years ago

Commit 4b9adb31 parent 79afc453 files · +42 −127Browse files

Unified · Split

3 files
  1. libavcodec/hevc/hevcdec.c +13 −20
  2. libavcodec/hevc/hevcdec.h +10 −22
  3. libavcodec/hevc/refs.c +19 −85
libavcodec/hevc/hevcdec.c+13−20
@@ -2908,6 +2908,7 @@ static int hevc_frame_start(HEVCContext *s) · 2907 unmodified lines
29082908 const HEVCSPS *const sps = pps->sps;
29092909 int pic_size_in_ctb = ((sps->width >> sps->log2_min_cb_size) + 1) *
29102910 ((sps->height >> sps->log2_min_cb_size) + 1);
2911+ int new_sequence = IS_IDR(s) || IS_BLA(s) || s->last_eos;
29112912 int ret;
29122913
29132914 ff_refstruct_replace(&s->pps, pps);
@@ -2927,7 +2928,7 @@ static int hevc_frame_start(HEVCContext *s) · 13 unmodified lines
29272928 return pix_fmt;
29282929 s->avctx->pix_fmt = pix_fmt;
29292930
2930− s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
2931+ new_sequence = 1;
29312932 }
29322933
29332934 memset(s->horizontal_bs, 0, s->bs_width * s->bs_height);
@@ -2936,11 +2937,8 @@ static int hevc_frame_start(HEVCContext *s) · 2 unmodified lines
29362937 memset(s->is_pcm, 0, (sps->min_pu_width + 1) * (sps->min_pu_height + 1));
29372938 memset(s->tab_slice_address, -1, pic_size_in_ctb * sizeof(*s->tab_slice_address));
29382939
2939− if ((IS_IDR(s) || IS_BLA(s))) {
2940− s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
2941− if (IS_IDR(s))
2942− ff_hevc_clear_refs(s);
2943− }
2940+ if (IS_IDR(s))
2941+ ff_hevc_clear_refs(s);
29442942
29452943 s->slice_idx = 0;
29462944 s->first_nal_type = s->nal_unit_type;
@@ -2964,6 +2962,12 @@ static int hevc_frame_start(HEVCContext *s) · 17 unmodified lines
29642962 if (pps->tiles_enabled_flag)
29652963 s->local_ctx[0].end_of_tiles_x = pps->column_width[0] << sps->log2_ctb_size;
29662964
2965+ if (new_sequence) {
2966+ ret = ff_hevc_output_frames(s, 0, 0, s->sh.no_output_of_prior_pics_flag);
2967+ if (ret < 0)
2968+ return ret;
2969+ }
2970+
29672971 ret = export_stream_params_from_sei(s);
29682972 if (ret < 0)
29692973 return ret;
@@ -3016,10 +3020,8 @@ static int hevc_frame_start(HEVCContext *s) · 46 unmodified lines
30163020
30173021 s->cur_frame->f->pict_type = 3 - s->sh.slice_type;
30183022
3019− if (!IS_IRAP(s))
3020− ff_hevc_bump_frame(s);
3021−
3022− ret = ff_hevc_output_frame(s, 0);
3023+ ret = ff_hevc_output_frames(s, sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
3024+ sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering, 0);
30233025 if (ret < 0)
30243026 goto fail;
30253027
@@ -3267,8 +3269,6 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) · 241 unmodified lines
32673269 break;
32683270 case HEVC_NAL_EOS_NUT:
32693271 case HEVC_NAL_EOB_NUT:
3270− s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
3271− break;
32723272 case HEVC_NAL_AUD:
32733273 case HEVC_NAL_FD_NUT:
32743274 case HEVC_NAL_UNSPEC62:
@@ -3425,7 +3425,7 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame) · 150 unmodified lines
34253425 av_packet_unref(avpkt);
34263426 ret = ff_decode_get_packet(avctx, avpkt);
34273427 if (ret == AVERROR_EOF) {
3428− ret = ff_hevc_output_frame(s, 1);
3428+ ret = ff_hevc_output_frames(s, 0, 0, 0);
34293429 if (ret < 0)
34303430 return ret;
34313431 goto do_output;
@@ -3487,7 +3487,6 @@ static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame *src) · 55 unmodified lines
34873487 dst->poc = src->poc;
34883488 dst->ctb_count = src->ctb_count;
34893489 dst->flags = src->flags;
3490− dst->sequence = src->sequence;
34913490
34923491 ff_refstruct_replace(&dst->hwaccel_picture_private,
34933492 src->hwaccel_picture_private);
@@ -3611,8 +3610,6 @@ static int hevc_update_thread_context(AVCodecContext *dst, · 117 unmodified lines
36113610 if ((ret = set_sps(s, s0->ps.sps)) < 0)
36123611 return ret;
36133612
3614− s->seq_decode = s0->seq_decode;
3615− s->seq_output = s0->seq_output;
36163613 s->poc_tid0 = s0->poc_tid0;
36173614 s->eos = s0->eos;
36183615 s->no_rasl_output_flag = s0->no_rasl_output_flag;
@@ -3622,10 +3619,6 @@ static int hevc_update_thread_context(AVCodecContext *dst, · 3 unmodified lines
36223619
36233620 s->film_grain_warning_shown = s0->film_grain_warning_shown;
36243621
3625− if (s0->eos) {
3626− s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
3627− }
3628−
36293622 ret = ff_h2645_sei_ctx_replace(&s->sei.common, &s0->sei.common);
36303623 if (ret < 0)
36313624 return ret;
libavcodec/hevc/hevcdec.h+10−22
@@ -349,10 +349,7 @@ typedef struct DBParams { · 348 unmodified lines
349349 #define HEVC_FRAME_FLAG_OUTPUT (1 << 0)
350350 #define HEVC_FRAME_FLAG_SHORT_REF (1 << 1)
351351 #define HEVC_FRAME_FLAG_LONG_REF (1 << 2)
352−#define HEVC_FRAME_FLAG_BUMPING (1 << 3)
353−
354−#define HEVC_SEQUENCE_COUNTER_MASK 0xff
355−#define HEVC_SEQUENCE_COUNTER_INVALID (HEVC_SEQUENCE_COUNTER_MASK + 1)
352+#define HEVC_FRAME_FLAG_UNAVAILABLE (1 << 3)
356353
357354 typedef struct HEVCFrame {
358355 union {
@@ -374,12 +371,6 @@ typedef struct HEVCFrame { · 15 unmodified lines
374371
375372 void *hwaccel_picture_private; ///< RefStruct reference
376373
377− /**
378− * A sequence counter, so that old frames are output first
379− * after a POC reset
380− */
381− uint16_t sequence;
382−
383374 /**
384375 * A combination of HEVC_FRAME_FLAG_*
385376 */
@@ -518,13 +509,6 @@ typedef struct HEVCContext { · 132 unmodified lines
518509 uint8_t *checksum_buf;
519510 int checksum_buf_size;
520511
521− /**
522− * Sequence counters for decoded and output frames, so that old
523− * frames are output first after a POC reset
524− */
525− uint16_t seq_decode;
526− uint16_t seq_output;
527−
528512 /** The target for the common_cabac_state of the local contexts. */
529513 HEVCCABACState cabac;
530514
@@ -633,12 +617,16 @@ static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type) · 102 unmodified lines
633617 }
634618
635619 /**
636− * Find next frame in output order and put a reference to it in frame.
637− * @return 1 if a frame was output, 0 otherwise
620+ * Find frames in the DPB that are ready for output and either write them to the
621+ * output FIFO or drop their output flag, depending on the value of discard.
622+ *
623+ * @param max_output maximum number of output-pending frames that can be
624+ * present in the DPB before output is triggered
625+ * @param max_dpb maximum number of any frames that can be present in the DPB
626+ * before output is triggered
638627 */
639−int ff_hevc_output_frame(HEVCContext *s, int flush);
640−
641−void ff_hevc_bump_frame(HEVCContext *s);
628+int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
629+ unsigned max_dpb, int discard);
642630
643631 void ff_hevc_unref_frame(HEVCFrame *frame, int flags);
644632
libavcodec/hevc/refs.c+19−85
@@ -132,8 +132,7 @@ int ff_hevc_set_new_ref(HEVCContext *s, int poc) · 131 unmodified lines
132132 for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
133133 HEVCFrame *frame = &s->DPB[i];
134134
135− if (frame->f && frame->sequence == s->seq_decode &&
136− frame->poc == poc) {
135+ if (frame->f && frame->poc == poc) {
137136 av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n",
138137 poc);
139138 return AVERROR_INVALIDDATA;
@@ -153,7 +152,6 @@ int ff_hevc_set_new_ref(HEVCContext *s, int poc) · 13 unmodified lines
153152 ref->flags = HEVC_FRAME_FLAG_SHORT_REF;
154153
155154 ref->poc = poc;
156− ref->sequence = s->seq_decode;
157155 ref->f->crop_left = s->ps.sps->output_window.left_offset;
158156 ref->f->crop_right = s->ps.sps->output_window.right_offset;
159157 ref->f->crop_top = s->ps.sps->output_window.top_offset;
@@ -166,112 +164,49 @@ static void unref_missing_refs(HEVCContext *s) · 6 unmodified lines
166164 {
167165 for (int i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
168166 HEVCFrame *frame = &s->DPB[i];
169− if (frame->sequence == HEVC_SEQUENCE_COUNTER_INVALID) {
167+ if (frame->flags & HEVC_FRAME_FLAG_UNAVAILABLE) {
170168 ff_hevc_unref_frame(frame, ~0);
171169 }
172170 }
173171 }
174172
175−int ff_hevc_output_frame(HEVCContext *s, int flush)
173+int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
174+ unsigned max_dpb, int discard)
176175 {
177− if (IS_IRAP(s) && s->no_rasl_output_flag == 1) {
178− const static int mask = HEVC_FRAME_FLAG_BUMPING | HEVC_FRAME_FLAG_OUTPUT;
179− for (int i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
180− HEVCFrame *frame = &s->DPB[i];
181− if ((frame->flags & mask) == HEVC_FRAME_FLAG_OUTPUT &&
182− frame->sequence != s->seq_decode) {
183− if (s->sh.no_output_of_prior_pics_flag == 1)
184− ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
185− else
186− frame->flags |= HEVC_FRAME_FLAG_BUMPING;
187− }
188− }
189− }
190− do {
176+ while (1) {
177+ int nb_dpb = 0;
191178 int nb_output = 0;
192179 int min_poc = INT_MAX;
193180 int i, min_idx, ret;
194181
195182 for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
196183 HEVCFrame *frame = &s->DPB[i];
197− if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) &&
198− frame->sequence == s->seq_output) {
184+ if (frame->flags & HEVC_FRAME_FLAG_OUTPUT) {
199185 nb_output++;
200186 if (frame->poc < min_poc || nb_output == 1) {
201187 min_poc = frame->poc;
202188 min_idx = i;
203189 }
204190 }
191+ nb_dpb += !!frame->flags;
205192 }
206193
207− /* wait for more frames before output */
208− if (!flush && s->seq_output == s->seq_decode && s->ps.sps &&
209− nb_output <= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].num_reorder_pics)
210− return 0;
211−
212− if (nb_output) {
194+ if (nb_output > max_output ||
195+ (nb_output && nb_dpb > max_dpb)) {
213196 HEVCFrame *frame = &s->DPB[min_idx];
214197
215− ret = ff_container_fifo_write(s->output_fifo,
198+ ret = discard ? 0 :
199+ ff_container_fifo_write(s->output_fifo,
216200 frame->needs_fg ? frame->frame_grain : frame->f);
217− if (frame->flags & HEVC_FRAME_FLAG_BUMPING)
218− ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING);
219− else
220− ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
201+ ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
221202 if (ret < 0)
222203 return ret;
223204
224− av_log(s->avctx, AV_LOG_DEBUG,
225− "Output frame with POC %d.\n", frame->poc);
226− return 1;
227− }
228−
229− if (s->seq_output != s->seq_decode)
230− s->seq_output = (s->seq_output + 1) & HEVC_SEQUENCE_COUNTER_MASK;
231− else
232− break;
233− } while (1);
234−
235− return 0;
236−}
237−
238−void ff_hevc_bump_frame(HEVCContext *s)
239−{
240− int dpb = 0;
241− int min_poc = INT_MAX;
242− int i;
243−
244− for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
245− HEVCFrame *frame = &s->DPB[i];
246− if ((frame->flags) &&
247− frame->sequence == s->seq_output &&
248− frame->poc != s->poc) {
249− dpb++;
250− }
251− }
252−
253− if (s->ps.sps && dpb >= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].max_dec_pic_buffering) {
254− for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
255− HEVCFrame *frame = &s->DPB[i];
256− if ((frame->flags) &&
257− frame->sequence == s->seq_output &&
258− frame->poc != s->poc) {
259− if (frame->flags == HEVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
260− min_poc = frame->poc;
261− }
262− }
263− }
264−
265− for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
266− HEVCFrame *frame = &s->DPB[i];
267− if (frame->flags & HEVC_FRAME_FLAG_OUTPUT &&
268− frame->sequence == s->seq_output &&
269− frame->poc <= min_poc) {
270− frame->flags |= HEVC_FRAME_FLAG_BUMPING;
271− }
205+ av_log(s->avctx, AV_LOG_DEBUG, "%s frame with POC %d.\n",
206+ discard ? "Discarded" : "Output", frame->poc);
207+ continue;
272208 }
273−
274− dpb--;
209+ return 0;
275210 }
276211 }
277212
@@ -385,7 +320,7 @@ static HEVCFrame *find_ref_idx(HEVCContext *s, int poc, uint8_t use_msb) · 107 unmodified lines
385320
386321 for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
387322 HEVCFrame *ref = &s->DPB[i];
388− if (ref->f && ref->sequence == s->seq_decode) {
323+ if (ref->f) {
389324 if ((ref->poc & mask) == poc && (use_msb || ref->poc != s->poc))
390325 return ref;
391326 }
@@ -428,8 +363,7 @@ static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc) · 36 unmodified lines
428363 }
429364
430365 frame->poc = poc;
431− frame->sequence = HEVC_SEQUENCE_COUNTER_INVALID;
432− frame->flags = 0;
366+ frame->flags = HEVC_FRAME_FLAG_UNAVAILABLE;
433367
434368 if (s->avctx->active_thread_type == FF_THREAD_FRAME)
435369 ff_progress_frame_report(&frame->tf, INT_MAX);

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