Coverage Report

Created: 2026-06-15 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/pd_process.c
Line
Count
Source
1
#include "enc_mode_config.h"
2
/*
3
* Copyright(c) 2019 Intel Corporation
4
* Copyright(c) 2019 Netflix, Inc.
5
*
6
* This source code is subject to the terms of the BSD 3-Clause Clear License and
7
* the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License
8
* was not distributed with this source code in the LICENSE file, you can
9
* obtain it at https://www.aomedia.org/license. If the Alliance for Open
10
* Media Patent License 1.0 was not distributed with this source code in the
11
* PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
12
*/
13
14
#include <stdlib.h>
15
#include <string.h>
16
#include <limits.h>
17
18
#include "pd_process.h"
19
#include "definitions.h"
20
#include "enc_handle.h"
21
#include "pcs.h"
22
#include "sequence_control_set.h"
23
#include "pic_analysis_process.h"
24
#include "pic_analysis_results.h"
25
#include "pd_results.h"
26
#include "reference_object.h"
27
#include "EbSvtAv1ErrorCodes.h"
28
#include "temporal_filtering.h"
29
#include "object.h"
30
#include "utility.h"
31
#include "svt_log.h"
32
#include "common_dsp_rtcd.h"
33
#include "resize.h"
34
#include "svt_malloc.h"
35
#include "inter_prediction.h"
36
#include "aom_dsp_rtcd.h"
37
38
#include "pic_operators.h"
39
#if CONFIG_SINGLE_THREAD_KERNEL
40
#include "me_process.h" // MotionEstimationContext_t for inline TF in ST mode
41
#endif
42
/************************************************
43
 * Defines
44
 ************************************************/
45
0
#define LAY1_OFF 3
46
0
#define LAY2_OFF 5
47
0
#define LAY3_OFF 6
48
0
#define LAY4_OFF 7
49
50
void             svt_aom_get_max_allocated_me_refs(uint8_t ref_count_used_list0, uint8_t ref_count_used_list1,
51
                                                   uint8_t* max_ref_to_alloc, uint8_t* max_cand_to_alloc);
52
void             svt_aom_init_resize_picture(SequenceControlSet* scs, PictureParentControlSet* pcs);
53
MvReferenceFrame svt_get_ref_frame_type(uint8_t list, uint8_t ref_idx);
54
55
static uint32_t calc_ahd(SequenceControlSet* scs, PictureParentControlSet* input_pcs, PictureParentControlSet* ref_pcs,
56
0
                         uint8_t* active_region_cnt) {
57
0
    uint32_t ahd           = 0;
58
0
    uint32_t region_width  = ref_pcs->enhanced_pic->width / scs->picture_analysis_number_of_regions_per_width;
59
0
    uint32_t region_height = ref_pcs->enhanced_pic->height / scs->picture_analysis_number_of_regions_per_height;
60
    // Loop over regions inside the picture
61
0
    for (uint32_t region_in_picture_width_index = 0;
62
0
         region_in_picture_width_index < scs->picture_analysis_number_of_regions_per_width;
63
0
         region_in_picture_width_index++) { // loop over horizontal regions
64
0
        for (uint32_t region_in_picture_height_index = 0;
65
0
             region_in_picture_height_index < scs->picture_analysis_number_of_regions_per_height;
66
0
             region_in_picture_height_index++) { // loop over vertical regions
67
0
            uint32_t ahd_per_region = 0;
68
0
            for (int bin = 0; bin < HISTOGRAM_NUMBER_OF_BINS; ++bin) {
69
0
                ahd_per_region += ABS(
70
0
                    (int32_t)input_pcs
71
0
                        ->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin] -
72
0
                    (int32_t)
73
0
                        ref_pcs->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin]);
74
0
            }
75
76
0
            ahd += ahd_per_region;
77
0
            if (ahd_per_region > (region_width * region_height)) {
78
0
                (*active_region_cnt)++;
79
0
            }
80
0
        }
81
0
    }
82
0
    return ahd;
83
0
}
84
85
3.01k
static INLINE int get_relative_dist(const OrderHintInfo* oh, int a, int b) {
86
3.01k
    if (!oh->enable_order_hint) {
87
0
        return 0;
88
0
    }
89
90
3.01k
    const int bits = oh->order_hint_bits;
91
92
3.01k
    assert(bits >= 1);
93
3.01k
    assert(a >= 0 && a < (1 << bits));
94
3.01k
    assert(b >= 0 && b < (1 << bits));
95
96
3.01k
    int       diff = a - b;
97
3.01k
    const int m    = 1 << (bits - 1);
98
3.01k
    diff           = (diff & (m - 1)) - (diff & m);
99
3.01k
    return diff;
100
3.01k
}
101
102
431
void svt_av1_setup_skip_mode_allowed(PictureParentControlSet* pcs) {
103
431
    FrameHeader*               frm_hdr         = &pcs->frm_hdr;
104
431
    const OrderHintInfo* const order_hint_info = &pcs->scs->seq_header.order_hint_info;
105
431
    SkipModeInfo* const        skip_mode_info  = &frm_hdr->skip_mode_params;
106
107
431
    skip_mode_info->skip_mode_allowed = 0;
108
431
    skip_mode_info->ref_frame_idx_0   = INVALID_IDX;
109
431
    skip_mode_info->ref_frame_idx_1   = INVALID_IDX;
110
111
431
    uint32_t* ref_order_hint = pcs->ref_order_hint;
112
113
    // If these conditions are true, skip mode is not allowed, so return early
114
431
    if (!order_hint_info->enable_order_hint || pcs->slice_type == I_SLICE /*frame_is_intra_only(cm)*/ ||
115
431
        frm_hdr->reference_mode == SINGLE_REFERENCE) {
116
431
        return;
117
431
    }
118
119
0
    const int cur_order_hint     = (int)pcs->cur_order_hint;
120
0
    int       ref_order_hints[2] = {-1, INT_MAX};
121
0
    int       ref_idx[2]         = {INVALID_IDX, INVALID_IDX};
122
123
    // Identify the nearest forward and backward references.
124
0
    for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
125
0
        const int ref_hint = (const int)ref_order_hint[i]; // buf->order_hint;
126
0
        if (get_relative_dist(order_hint_info, ref_hint, cur_order_hint) < 0) {
127
            // Forward reference
128
0
            if (ref_order_hints[0] == -1 || get_relative_dist(order_hint_info, ref_hint, ref_order_hints[0]) > 0) {
129
0
                ref_order_hints[0] = ref_hint;
130
0
                ref_idx[0]         = i;
131
0
            }
132
0
        } else if (get_relative_dist(order_hint_info, ref_hint, cur_order_hint) > 0) {
133
            // Backward reference
134
0
            if (ref_order_hints[1] == INT_MAX || get_relative_dist(order_hint_info, ref_hint, ref_order_hints[1]) < 0) {
135
0
                ref_order_hints[1] = ref_hint;
136
0
                ref_idx[1]         = i;
137
0
            }
138
0
        }
139
0
    }
140
141
0
    if (ref_idx[0] != INVALID_IDX && ref_idx[1] != INVALID_IDX) {
142
        // == Bi-directional prediction ==
143
0
        skip_mode_info->skip_mode_allowed = 1;
144
0
        skip_mode_info->ref_frame_idx_0   = LAST_FRAME + MIN(ref_idx[0], ref_idx[1]);
145
0
        skip_mode_info->ref_frame_idx_1   = LAST_FRAME + MAX(ref_idx[0], ref_idx[1]);
146
0
    } else if (ref_idx[0] != INVALID_IDX && ref_idx[1] == INVALID_IDX) {
147
        // == Forward prediction only ==
148
        // Identify the second nearest forward reference.
149
0
        ref_order_hints[1] = -1;
150
0
        for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
151
0
            const int ref_hint = (const int)ref_order_hint[i]; // buf->order_hint;
152
0
            if ((ref_order_hints[0] != -1 && get_relative_dist(order_hint_info, ref_hint, ref_order_hints[0]) < 0) &&
153
0
                (ref_order_hints[1] == -1 || get_relative_dist(order_hint_info, ref_hint, ref_order_hints[1]) > 0)) {
154
                // Second closest forward reference
155
0
                ref_order_hints[1] = ref_hint;
156
0
                ref_idx[1]         = i;
157
0
            }
158
0
        }
159
0
        if (ref_order_hints[1] != -1) {
160
0
            skip_mode_info->skip_mode_allowed = 1;
161
0
            skip_mode_info->ref_frame_idx_0   = LAST_FRAME + MIN(ref_idx[0], ref_idx[1]);
162
0
            skip_mode_info->ref_frame_idx_1   = LAST_FRAME + MAX(ref_idx[0], ref_idx[1]);
163
0
        }
164
0
    }
165
0
}
166
167
0
uint8_t circ_inc(uint8_t max, uint8_t off, uint8_t input) {
168
0
    input++;
169
0
    if (input >= max) {
170
0
        input = 0;
171
0
    }
172
173
0
    if (off == 2) {
174
0
        input++;
175
0
        if (input >= max) {
176
0
            input = 0;
177
0
        }
178
0
    }
179
180
0
    return input;
181
0
}
182
183
0
#define FLASH_TH 5
184
0
#define FADE_TH 3
185
0
#define SCENE_TH 3000
186
0
#define NUM64x64INPIC(w, h) ((w * h) >> (svt_log2f(BLOCK_SIZE_64) << 1))
187
431
#define QUEUE_GET_PREVIOUS_SPOT(h, size) (((h) == 0) ? (size) - 1 : (h) - 1)
188
0
#define QUEUE_GET_NEXT_SPOT(h, off, size) (((int)(h + off) >= (int)(size)) ? h + off - (int)(size) : h + off)
189
190
431
static void picture_decision_context_dctor(EbPtr p) {
191
431
    EbThreadContext*        thread_ctx = (EbThreadContext*)p;
192
431
    PictureDecisionContext* obj        = (PictureDecisionContext*)thread_ctx->priv;
193
194
431
    if (obj->prev_picture_histogram) {
195
0
        for (int region_in_picture_width_index = 0; region_in_picture_width_index < MAX_NUMBER_OF_REGIONS_IN_WIDTH;
196
0
             region_in_picture_width_index++) {
197
0
            if (obj->prev_picture_histogram[region_in_picture_width_index]) {
198
0
                for (int region_in_picture_height_index = 0;
199
0
                     region_in_picture_height_index < MAX_NUMBER_OF_REGIONS_IN_HEIGHT;
200
0
                     region_in_picture_height_index++) {
201
0
                    EB_FREE_ARRAY(
202
0
                        obj->prev_picture_histogram[region_in_picture_width_index][region_in_picture_height_index]);
203
0
                }
204
0
            }
205
0
            EB_FREE_PTR_ARRAY(obj->prev_picture_histogram[region_in_picture_width_index],
206
0
                              MAX_NUMBER_OF_REGIONS_IN_HEIGHT);
207
0
        }
208
0
        EB_FREE_PTR_ARRAY(obj->prev_picture_histogram, MAX_NUMBER_OF_REGIONS_IN_WIDTH);
209
0
    }
210
431
    EB_FREE_2D(obj->ahd_running_avg);
211
431
    EB_FREE_2D(obj->ahd_running_avg_cr);
212
431
    EB_FREE_2D(obj->ahd_running_avg_cb);
213
431
    EB_FREE_ARRAY(obj);
214
431
}
215
216
/************************************************
217
  * Picture Analysis Context Constructor
218
  ************************************************/
219
EbErrorType svt_aom_picture_decision_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr,
220
431
                                                  uint8_t calc_hist) {
221
431
    PictureDecisionContext* pd_ctx;
222
431
    EB_CALLOC_ARRAY(pd_ctx, 1);
223
431
    thread_ctx->priv  = pd_ctx;
224
431
    thread_ctx->dctor = picture_decision_context_dctor;
225
226
431
    memset(pd_ctx->tf_pic_array, 0, (1 << MAX_TEMPORAL_LAYERS) * sizeof(PictureParentControlSet*));
227
431
    pd_ctx->tf_pic_arr_cnt                          = 0;
228
431
    pd_ctx->picture_analysis_results_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
229
431
        enc_handle_ptr->picture_analysis_results_resource_ptr, 0);
230
431
    pd_ctx->picture_decision_results_output_fifo_ptr = svt_system_resource_get_producer_fifo(
231
431
        enc_handle_ptr->picture_decision_results_resource_ptr, 0);
232
431
    if (calc_hist) {
233
0
        EB_ALLOC_PTR_ARRAY(pd_ctx->prev_picture_histogram, MAX_NUMBER_OF_REGIONS_IN_WIDTH);
234
0
        for (uint32_t region_in_picture_width_index = 0; region_in_picture_width_index < MAX_NUMBER_OF_REGIONS_IN_WIDTH;
235
0
             region_in_picture_width_index++) { // loop over horizontal regions
236
0
            EB_ALLOC_PTR_ARRAY(pd_ctx->prev_picture_histogram[region_in_picture_width_index],
237
0
                               MAX_NUMBER_OF_REGIONS_IN_HEIGHT);
238
0
            for (uint32_t region_in_picture_height_index = 0;
239
0
                 region_in_picture_height_index < MAX_NUMBER_OF_REGIONS_IN_HEIGHT;
240
0
                 region_in_picture_height_index++) {
241
0
                EB_CALLOC_ARRAY(
242
0
                    pd_ctx->prev_picture_histogram[region_in_picture_width_index][region_in_picture_height_index],
243
0
                    HISTOGRAM_NUMBER_OF_BINS * sizeof(uint32_t));
244
0
            }
245
0
        }
246
247
0
        EB_CALLOC_2D(pd_ctx->ahd_running_avg,
248
0
                     MAX_NUMBER_OF_REGIONS_IN_WIDTH * sizeof(uint32_t),
249
0
                     MAX_NUMBER_OF_REGIONS_IN_HEIGHT * sizeof(uint32_t));
250
0
    }
251
431
    pd_ctx->reset_running_avg = true;
252
431
    pd_ctx->me_fifo_ptr       = svt_system_resource_get_producer_fifo(enc_handle_ptr->me_pool_ptr, 0);
253
254
431
    pd_ctx->mg_progress_id                    = 0;
255
431
    pd_ctx->last_i_noise_levels_log1p_fp16[0] = 0;
256
431
    pd_ctx->transition_detected               = -1;
257
431
    pd_ctx->sframe_poc                        = 0;
258
431
    pd_ctx->sframe_due                        = 0;
259
431
    pd_ctx->last_long_base_pic                = 0;
260
431
    pd_ctx->enable_startup_mg                 = false;
261
431
    pd_ctx->is_startup_gop                    = false;
262
431
    pd_ctx->sframe_hier_lvls                  = 0;
263
431
    pd_ctx->sframe_last_arf                   = 0;
264
431
    pd_ctx->next_arf_is_s                     = false;
265
431
    pd_ctx->current_input_poc                 = -1;
266
431
    return EB_ErrorNone;
267
431
}
268
269
static bool scene_transition_detector(PictureDecisionContext* pd_ctx, SequenceControlSet* scs,
270
0
                                      PictureParentControlSet** parent_pcs_window) {
271
0
    PictureParentControlSet* current_pcs_ptr = parent_pcs_window[1];
272
0
    PictureParentControlSet* future_pcs_ptr  = parent_pcs_window[2];
273
274
    // calculating the frame threshold based on the number of 64x64 blocks in the frame
275
0
    uint32_t region_threshold;
276
277
0
    bool is_abrupt_change; // this variable signals an abrupt change (scene change or flash)
278
0
    bool is_scene_change; // this variable signals a frame representing a scene change
279
280
0
    uint32_t** ahd_running_avg = pd_ctx->ahd_running_avg;
281
282
0
    uint32_t region_in_picture_width_index;
283
0
    uint32_t region_in_picture_height_index;
284
285
0
    uint32_t region_width;
286
0
    uint32_t region_height;
287
0
    uint32_t region_width_offset;
288
0
    uint32_t region_height_offset;
289
290
0
    uint32_t is_abrupt_change_count = 0;
291
0
    uint32_t is_scene_change_count  = 0;
292
293
0
    uint32_t region_count_threshold = (uint32_t)(((float)((scs->picture_analysis_number_of_regions_per_width *
294
0
                                                           scs->picture_analysis_number_of_regions_per_height) *
295
0
                                                          50) /
296
0
                                                  100) +
297
0
                                                 0.5);
298
299
0
    region_width  = parent_pcs_window[1]->enhanced_pic->width / scs->picture_analysis_number_of_regions_per_width;
300
0
    region_height = parent_pcs_window[1]->enhanced_pic->height / scs->picture_analysis_number_of_regions_per_height;
301
302
    // Loop over regions inside the picture
303
0
    for (region_in_picture_width_index = 0;
304
0
         region_in_picture_width_index < scs->picture_analysis_number_of_regions_per_width;
305
0
         region_in_picture_width_index++) { // loop over horizontal regions
306
0
        for (region_in_picture_height_index = 0;
307
0
             region_in_picture_height_index < scs->picture_analysis_number_of_regions_per_height;
308
0
             region_in_picture_height_index++) { // loop over vertical regions
309
310
0
            is_abrupt_change = false;
311
0
            is_scene_change  = false;
312
313
            // accumulative histogram (absolute) differences between the past and current frame
314
0
            uint32_t ahd = 0;
315
316
0
            region_width_offset = (region_in_picture_width_index ==
317
0
                                   scs->picture_analysis_number_of_regions_per_width - 1)
318
0
                ? parent_pcs_window[1]->enhanced_pic->width -
319
0
                    (scs->picture_analysis_number_of_regions_per_width * region_width)
320
0
                : 0;
321
322
0
            region_height_offset = (region_in_picture_height_index ==
323
0
                                    scs->picture_analysis_number_of_regions_per_height - 1)
324
0
                ? parent_pcs_window[1]->enhanced_pic->height -
325
0
                    (scs->picture_analysis_number_of_regions_per_height * region_height)
326
0
                : 0;
327
328
0
            region_width += region_width_offset;
329
0
            region_height += region_height_offset;
330
331
0
            region_threshold = SCENE_TH * NUM64x64INPIC(region_width, region_height);
332
333
0
            for (int bin = 0; bin < HISTOGRAM_NUMBER_OF_BINS; ++bin) {
334
0
                ahd += ABS((int32_t)current_pcs_ptr
335
0
                               ->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin] -
336
0
                           (int32_t)pd_ctx->prev_picture_histogram[region_in_picture_width_index]
337
0
                                                                  [region_in_picture_height_index][bin]);
338
0
            }
339
340
0
            if (pd_ctx->reset_running_avg) {
341
0
                ahd_running_avg[region_in_picture_width_index][region_in_picture_height_index] = ahd;
342
0
            }
343
344
0
            uint32_t ahd_error = ABS(
345
0
                (int32_t)ahd_running_avg[region_in_picture_width_index][region_in_picture_height_index] - (int32_t)ahd);
346
347
0
            if (ahd_error > region_threshold && ahd >= ahd_error) {
348
0
                is_abrupt_change = true;
349
0
            }
350
0
            if (is_abrupt_change) {
351
                // this variable denotes the average intensity difference between the next and the past frames
352
0
                uint8_t aid_future_past = (uint8_t)ABS(
353
0
                    (int16_t)future_pcs_ptr
354
0
                        ->average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index] -
355
0
                    (int16_t)pd_ctx->prev_average_intensity_per_region[region_in_picture_width_index]
356
0
                                                                      [region_in_picture_height_index]);
357
0
                uint8_t aid_future_present = (uint8_t)ABS(
358
0
                    (int16_t)future_pcs_ptr
359
0
                        ->average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index] -
360
0
                    (int16_t)current_pcs_ptr
361
0
                        ->average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index]);
362
0
                uint8_t aid_present_past = (uint8_t)ABS(
363
0
                    (int16_t)current_pcs_ptr
364
0
                        ->average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index] -
365
0
                    (int16_t)pd_ctx->prev_average_intensity_per_region[region_in_picture_width_index]
366
0
                                                                      [region_in_picture_height_index]);
367
368
0
                if (aid_future_past < FLASH_TH && aid_future_present >= FLASH_TH && aid_present_past >= FLASH_TH) {
369
                    //SVT_LOG ("\nFlash in frame# %i , %i\n", current_pcs_ptr->picture_number,aid_future_past);
370
0
                } else if (aid_future_present < FADE_TH && aid_present_past < FADE_TH) {
371
                    //SVT_LOG ("\nFlash in frame# %i , %i\n", current_pcs_ptr->picture_number,aid_future_past);
372
0
                } else {
373
0
                    is_scene_change = true;
374
                    //SVT_LOG ("\nScene Change in frame# %i , %i\n", current_pcs_ptr->picture_number,aid_future_past);
375
0
                }
376
0
            } else {
377
0
                ahd_running_avg[region_in_picture_width_index][region_in_picture_height_index] =
378
0
                    (3 * ahd_running_avg[region_in_picture_width_index][region_in_picture_height_index] + ahd) / 4;
379
0
            }
380
0
            is_abrupt_change_count += is_abrupt_change;
381
0
            is_scene_change_count += is_scene_change;
382
0
        }
383
0
    }
384
385
0
    pd_ctx->reset_running_avg = is_abrupt_change_count >= region_count_threshold;
386
0
    return is_scene_change_count >= region_count_threshold;
387
0
}
388
389
/***************************************************************************************************
390
* release_prev_picture_from_reorder_queue
391
***************************************************************************************************/
392
431
EbErrorType release_prev_picture_from_reorder_queue(EncodeContext* enc_ctx) {
393
431
    EbErrorType return_error = EB_ErrorNone;
394
395
431
    PictureDecisionReorderEntry* queue_previous_entry_ptr;
396
431
    int32_t                      previous_entry_index;
397
398
    // Get the previous entry from the Picture Decision Reordering Queue (Entry N-1)
399
    // P.S. The previous entry in display order is needed for Scene Change Detection
400
431
    previous_entry_index     = (enc_ctx->picture_decision_reorder_queue_head_index == 0)
401
431
            ? enc_ctx->picture_decision_reorder_queue_size - 1
402
431
            : enc_ctx->picture_decision_reorder_queue_head_index - 1;
403
431
    queue_previous_entry_ptr = enc_ctx->picture_decision_reorder_queue[previous_entry_index];
404
405
    // SB activity classification based on (0,0) SAD & picture activity derivation
406
431
    if (queue_previous_entry_ptr->ppcs_wrapper) {
407
        // Reset the Picture Decision Reordering Queue Entry
408
        // P.S. The reset of the Picture Decision Reordering Queue Entry could not be done before running the Scene Change Detector
409
0
        queue_previous_entry_ptr->picture_number += enc_ctx->picture_decision_reorder_queue_size;
410
0
        queue_previous_entry_ptr->ppcs_wrapper = NULL;
411
0
    }
412
413
431
    return return_error;
414
431
}
415
416
static void early_hme_b64(uint8_t* sixteenth_b64_buffer, uint32_t sixteenth_b64_buffer_stride,
417
                          uint8_t  hme_search_method, //
418
                          int16_t  org_x, // Block position in the horizontal direction- sixteenth resolution
419
                          int16_t  org_y, // Block position in the vertical direction- sixteenth resolution
420
                          uint32_t block_width, // Block width - sixteenth resolution
421
                          uint32_t block_height, // Block height - sixteenth resolution
422
                          int16_t  sa_width, // search area width
423
                          int16_t  sa_height, // search area height
424
                          EbPictureBufferDesc* sixteenth_ref_pic_ptr, // sixteenth-downsampled reference picture
425
                          uint64_t*            best_sad, // output: Level0 SAD
426
                          Mv*                  sr_center // output: Level0 xMV, Level0 yMV
427
0
) {
428
    // round up the search region width to nearest multiple of 8 because the SAD calculation performance (for
429
    // intrinsic functions) is the same for search region width from 1 to 8
430
0
    sa_width           = (int16_t)((sa_width + 7) & ~0x07);
431
0
    int16_t pad_width  = (int16_t)(sixteenth_ref_pic_ptr->border) - 1;
432
0
    int16_t pad_height = (int16_t)(sixteenth_ref_pic_ptr->border) - 1;
433
434
0
    int16_t sa_origin_x = -(int16_t)(sa_width >> 1);
435
0
    int16_t sa_origin_y = -(int16_t)(sa_height >> 1);
436
437
    // Correct the left edge of the Search Area if it is not on the reference picture
438
0
    if (((org_x + sa_origin_x) < -pad_width)) {
439
0
        sa_origin_x = -pad_width - org_x;
440
0
        sa_width    = sa_width - (-pad_width - (org_x + sa_origin_x));
441
0
    }
442
443
    // Correct the right edge of the Search Area if its not on the reference picture
444
0
    if (((org_x + sa_origin_x) > (int16_t)sixteenth_ref_pic_ptr->width - 1)) {
445
0
        sa_origin_x = sa_origin_x - ((org_x + sa_origin_x) - ((int16_t)sixteenth_ref_pic_ptr->width - 1));
446
0
    }
447
448
0
    if (((org_x + sa_origin_x + sa_width) > (int16_t)sixteenth_ref_pic_ptr->width)) {
449
0
        sa_width = MAX(1, sa_width - ((org_x + sa_origin_x + sa_width) - (int16_t)sixteenth_ref_pic_ptr->width));
450
0
    }
451
    // Constrain x_HME_L1 to be a multiple of 8 (round down as cropping alrea performed)
452
0
    sa_width = (sa_width < 8) ? sa_width : sa_width & ~0x07;
453
    // Correct the top edge of the Search Area if it is not on the reference picture
454
0
    if (((org_y + sa_origin_y) < -pad_height)) {
455
0
        sa_origin_y = -pad_height - org_y;
456
0
        sa_height   = sa_height - (-pad_height - (org_y + sa_origin_y));
457
0
    }
458
459
    // Correct the bottom edge of the Search Area if its not on the reference picture
460
0
    if (((org_y + sa_origin_y) > (int16_t)sixteenth_ref_pic_ptr->height - 1)) {
461
0
        sa_origin_y = sa_origin_y - ((org_y + sa_origin_y) - ((int16_t)sixteenth_ref_pic_ptr->height - 1));
462
0
    }
463
464
0
    if ((org_y + sa_origin_y + sa_height > (int16_t)sixteenth_ref_pic_ptr->height)) {
465
0
        sa_height = MAX(1, sa_height - ((org_y + sa_origin_y + sa_height) - (int16_t)sixteenth_ref_pic_ptr->height));
466
0
    }
467
468
    // Move to the top left of the search region
469
0
    int16_t x_top_left_search_region = (org_x) + sa_origin_x;
470
0
    int16_t y_top_left_search_region = (org_y) + sa_origin_y;
471
0
    int32_t search_region_index = x_top_left_search_region + y_top_left_search_region * sixteenth_ref_pic_ptr->y_stride;
472
473
    // Put the first search location into level0 results
474
0
    svt_sad_loop_kernel(
475
0
        &sixteenth_b64_buffer[0],
476
0
        (hme_search_method == FULL_SAD_SEARCH) ? sixteenth_b64_buffer_stride : sixteenth_b64_buffer_stride * 2,
477
0
        &sixteenth_ref_pic_ptr->y_buffer[search_region_index],
478
0
        (hme_search_method == FULL_SAD_SEARCH) ? sixteenth_ref_pic_ptr->y_stride : sixteenth_ref_pic_ptr->y_stride * 2,
479
0
        (hme_search_method == FULL_SAD_SEARCH) ? block_height : block_height >> 1,
480
0
        block_width,
481
        /* results */
482
0
        best_sad,
483
0
        &sr_center->x,
484
0
        &sr_center->y,
485
        /* range */
486
0
        sixteenth_ref_pic_ptr->y_stride,
487
0
        0, // skip search line
488
0
        sa_width,
489
0
        sa_height);
490
491
0
    *best_sad = (hme_search_method == FULL_SAD_SEARCH)
492
0
        ? *best_sad
493
0
        : *best_sad * 2; // Multiply by 2 because considered only ever other line
494
495
0
    sr_center->x += sa_origin_x;
496
0
    sr_center->x *= 4; // Multiply by 4 because operating on 1/4 resolution
497
0
    sr_center->y += sa_origin_y;
498
0
    sr_center->y *= 4; // Multiply by 4 because operating on 1/4 resolution
499
500
0
    return;
501
0
}
502
#if OPT_MRP_HME_L0_DETECT
503
// Compute the total HME-L0 SAD between ppcs (current frame, 1/16 DS) and ref_sixt_ds_pic.
504
// Used to compare reference quality before deciding to prune weaker L0 refs.
505
0
uint64_t mrp_detector_hme_level0(PictureParentControlSet* ppcs, EbPictureBufferDesc* ref_sixt_ds_pic) {
506
0
    EbPictureBufferDesc* src_sixt_ds_pic =
507
0
        ((EbPaReferenceObject*)ppcs->pa_ref_pic_wrapper->object_ptr)->sixteenth_downsampled_picture_ptr;
508
509
0
    int16_t  sa_width          = 8;
510
0
    int16_t  sa_height         = 8;
511
0
    Mv       sr_center         = {.as_int = 0};
512
0
    uint8_t  hme_search_method = FULL_SAD_SEARCH;
513
0
    uint32_t pic_width_in_b64  = (ppcs->aligned_width + ppcs->scs->b64_size - 1) / ppcs->scs->b64_size;
514
0
    uint32_t pic_height_in_b64 = (ppcs->aligned_height + ppcs->scs->b64_size - 1) / ppcs->scs->b64_size;
515
0
    uint64_t tot_dist          = 0;
516
517
0
    for (uint32_t y_b64_idx = 0; y_b64_idx < pic_height_in_b64; ++y_b64_idx) {
518
0
        for (uint32_t x_b64_idx = 0; x_b64_idx < pic_width_in_b64; ++x_b64_idx) {
519
0
            uint64_t hme_level0_sad = (uint64_t)~0;
520
0
            uint32_t b64_origin_x   = x_b64_idx * 64;
521
0
            uint32_t b64_origin_y   = y_b64_idx * 64;
522
523
0
            uint32_t buffer_index = ((b64_origin_y >> 2)) * src_sixt_ds_pic->y_stride + (b64_origin_x >> 2);
524
525
0
            early_hme_b64(&src_sixt_ds_pic->y_buffer[buffer_index],
526
0
                          src_sixt_ds_pic->y_stride,
527
0
                          hme_search_method,
528
0
                          ((int16_t)b64_origin_x) >> 2,
529
0
                          ((int16_t)b64_origin_y) >> 2,
530
0
                          16,
531
0
                          16,
532
0
                          sa_width,
533
0
                          sa_height,
534
0
                          ref_sixt_ds_pic,
535
0
                          &hme_level0_sad,
536
0
                          &sr_center);
537
538
0
            tot_dist += hme_level0_sad;
539
0
        }
540
0
    }
541
542
0
    return tot_dist;
543
0
}
544
#endif
545
546
0
void dg_detector_hme_level0(PictureParentControlSet* ppcs, uint32_t seg_idx) {
547
0
    EbPictureBufferDesc* src_sixt_ds_pic =
548
0
        ((EbPaReferenceObject*)ppcs->pa_ref_pic_wrapper->object_ptr)->sixteenth_downsampled_picture_ptr;
549
550
0
    EbPictureBufferDesc* ref_sixt_ds_pic =
551
0
        ((EbPaReferenceObject*)ppcs->dg_detector->ref_pic->pa_ref_pic_wrapper->object_ptr)
552
0
            ->sixteenth_downsampled_picture_ptr;
553
554
0
    int16_t sa_width  = ppcs->input_resolution <= INPUT_SIZE_360p_RANGE ? 16
555
0
         : ppcs->input_resolution <= INPUT_SIZE_480p_RANGE              ? 64
556
0
                                                                        : 128;
557
0
    int16_t sa_height = ppcs->input_resolution <= INPUT_SIZE_360p_RANGE ? 16
558
0
        : ppcs->input_resolution <= INPUT_SIZE_480p_RANGE               ? 64
559
0
                                                                        : 128;
560
561
0
    uint64_t hme_level0_sad = (uint64_t)~0;
562
0
    Mv       sr_center      = {.as_int = 0};
563
564
0
    uint8_t hme_search_method = FULL_SAD_SEARCH;
565
566
    // determine the starting and ending block for each segment
567
0
    uint32_t pic_width_in_b64  = (ppcs->aligned_width + ppcs->scs->b64_size - 1) / ppcs->scs->b64_size;
568
0
    uint32_t pic_height_in_b64 = (ppcs->aligned_height + ppcs->scs->b64_size - 1) / ppcs->scs->b64_size;
569
0
    uint32_t y_seg_idx;
570
0
    uint32_t x_seg_idx;
571
572
0
    SEGMENT_CONVERT_IDX_TO_XY(seg_idx, x_seg_idx, y_seg_idx, ppcs->me_segments_column_count);
573
0
    uint32_t x_b64_start_idx = SEGMENT_START_IDX(x_seg_idx, pic_width_in_b64, ppcs->me_segments_column_count);
574
0
    uint32_t x_b64_end_idx   = SEGMENT_END_IDX(x_seg_idx, pic_width_in_b64, ppcs->me_segments_column_count);
575
0
    uint32_t y_b64_start_idx = SEGMENT_START_IDX(y_seg_idx, pic_height_in_b64, ppcs->me_segments_row_count);
576
0
    uint32_t y_b64_end_idx   = SEGMENT_END_IDX(y_seg_idx, pic_height_in_b64, ppcs->me_segments_row_count);
577
578
0
    for (uint32_t y_b64_idx = y_b64_start_idx; y_b64_idx < y_b64_end_idx; ++y_b64_idx) {
579
0
        for (uint32_t x_b64_idx = x_b64_start_idx; x_b64_idx < x_b64_end_idx; ++x_b64_idx) {
580
0
            uint32_t b64_origin_x = x_b64_idx * 64;
581
0
            uint32_t b64_origin_y = y_b64_idx * 64;
582
583
0
            uint32_t buffer_index = ((b64_origin_y >> 2)) * src_sixt_ds_pic->y_stride + (b64_origin_x >> 2);
584
585
0
            early_hme_b64(&src_sixt_ds_pic->y_buffer[buffer_index],
586
0
                          src_sixt_ds_pic->y_stride,
587
0
                          hme_search_method,
588
0
                          ((int16_t)b64_origin_x) >> 2,
589
0
                          ((int16_t)b64_origin_y) >> 2,
590
0
                          16,
591
0
                          16,
592
0
                          sa_width,
593
0
                          sa_height,
594
0
                          ref_sixt_ds_pic,
595
0
                          &hme_level0_sad,
596
0
                          &sr_center);
597
598
            // lock the dg metrics calculation using a mutex, only one segment can modify the data at a time
599
0
            svt_block_on_mutex(ppcs->dg_detector->metrics_mutex);
600
0
            ppcs->dg_detector->metrics.tot_dist += hme_level0_sad;
601
602
0
            ppcs->dg_detector->metrics.tot_cplx += (hme_level0_sad > (16 * 16 * 30));
603
0
            ppcs->dg_detector->metrics.tot_active += ((abs(sr_center.x) > 0) || (abs(sr_center.y) > 0));
604
0
            if (y_b64_idx < pic_height_in_b64 / 2) {
605
0
                if (sr_center.y > 0) {
606
0
                    --ppcs->dg_detector->metrics.sum_in_vectors;
607
0
                } else if (sr_center.y < 0) {
608
0
                    ++ppcs->dg_detector->metrics.sum_in_vectors;
609
0
                }
610
0
            } else if (y_b64_idx > pic_height_in_b64 / 2) {
611
0
                if (sr_center.y > 0) {
612
0
                    ++ppcs->dg_detector->metrics.sum_in_vectors;
613
0
                } else if (sr_center.y < 0) {
614
0
                    --ppcs->dg_detector->metrics.sum_in_vectors;
615
0
                }
616
0
            }
617
618
            // Does the col vector point inwards or outwards?
619
0
            if (x_b64_idx < pic_width_in_b64 / 2) {
620
0
                if (sr_center.x > 0) {
621
0
                    --ppcs->dg_detector->metrics.sum_in_vectors;
622
0
                } else if (sr_center.x < 0) {
623
0
                    ++ppcs->dg_detector->metrics.sum_in_vectors;
624
0
                }
625
0
            } else if (x_b64_idx > pic_width_in_b64 / 2) {
626
0
                if (sr_center.x > 0) {
627
0
                    ++ppcs->dg_detector->metrics.sum_in_vectors;
628
0
                } else if (sr_center.x < 0) {
629
0
                    --ppcs->dg_detector->metrics.sum_in_vectors;
630
0
                }
631
0
            }
632
0
            svt_release_mutex(ppcs->dg_detector->metrics_mutex);
633
0
        }
634
0
    }
635
0
    svt_block_on_mutex(ppcs->dg_detector->metrics_mutex);
636
0
    ppcs->dg_detector->metrics.seg_completed++;
637
0
    if (ppcs->dg_detector->metrics.seg_completed == (ppcs->me_segments_column_count * ppcs->me_segments_row_count)) {
638
        // signal that all the hme_level0 segments have been performed and dg metrics collected for the frame
639
0
        svt_post_semaphore(ppcs->dg_detector->frame_done_sem);
640
0
    }
641
0
    svt_release_mutex(ppcs->dg_detector->metrics_mutex);
642
0
}
643
644
0
static void early_hme(PictureDecisionContext* ctx, PictureParentControlSet* src_pcs, PictureParentControlSet* ref_pcs) {
645
    // store the ref pic so it can be used by dg detector when the src picture is sent to the motion estimation kernel
646
0
    src_pcs->dg_detector->ref_pic = ref_pcs;
647
648
0
    uint16_t dg_detector_seg_total_count = (uint16_t)(src_pcs->me_segments_column_count) *
649
0
        (uint16_t)(src_pcs->me_segments_row_count);
650
    // reset all metrics for the frame, must be performed here since the frame can be used again in a future comparison
651
0
    src_pcs->dg_detector->metrics.seg_completed  = 0;
652
0
    src_pcs->dg_detector->metrics.sum_in_vectors = 0;
653
0
    src_pcs->dg_detector->metrics.tot_dist       = 0;
654
0
    src_pcs->dg_detector->metrics.tot_cplx       = 0;
655
0
    src_pcs->dg_detector->metrics.tot_active     = 0;
656
657
0
#if CONFIG_SINGLE_THREAD_KERNEL
658
0
    if (src_pcs->scs->lp == 1) {
659
        // ST mode: run DG detector segments inline to avoid dispatching to ME
660
        // FIFO and blocking on the semaphore (same pattern as mctf_frame_st).
661
0
        for (uint16_t seg_idx = 0; seg_idx < dg_detector_seg_total_count; ++seg_idx) {
662
0
            dg_detector_hme_level0(src_pcs, seg_idx);
663
0
        }
664
        // dg_detector_hme_level0 posts frame_done_sem on the last segment — consume it.
665
0
        svt_block_on_semaphore(src_pcs->dg_detector->frame_done_sem);
666
0
    } else
667
0
#endif
668
0
    {
669
        // create segments for the dg detector and send them to the motion estimation kernel
670
0
        for (uint16_t seg_idx = 0; seg_idx < dg_detector_seg_total_count; ++seg_idx) {
671
0
            EbObjectWrapper*        out_results_wrp;
672
0
            PictureDecisionResults* out_results;
673
0
            svt_get_empty_object(ctx->picture_decision_results_output_fifo_ptr, &out_results_wrp);
674
0
            out_results                = (PictureDecisionResults*)out_results_wrp->object_ptr;
675
0
            out_results->pcs_wrapper   = src_pcs->p_pcs_wrapper_ptr;
676
0
            out_results->segment_index = seg_idx;
677
0
            out_results->task_type     = TASK_DG_DETECTOR_HME;
678
0
            svt_post_full_object(out_results_wrp);
679
0
        }
680
681
        // wait for all segments to complete before the frame based calculations can be performed using the dg metrics
682
0
        svt_block_on_semaphore(src_pcs->dg_detector->frame_done_sem);
683
0
    }
684
685
    // 64x64 Block Loop
686
0
    uint32_t pic_width_in_b64  = (src_pcs->aligned_width + 63) / 64;
687
0
    uint32_t pic_height_in_b64 = (src_pcs->aligned_height + 63) / 64;
688
689
0
    ctx->mv_in_out_count = src_pcs->dg_detector->metrics.sum_in_vectors * 100 /
690
0
        (int)(pic_height_in_b64 * pic_width_in_b64);
691
0
    ctx->norm_dist   = src_pcs->dg_detector->metrics.tot_dist / (pic_height_in_b64 * pic_width_in_b64);
692
0
    ctx->perc_cplx   = (src_pcs->dg_detector->metrics.tot_cplx * 100) / (pic_height_in_b64 * pic_width_in_b64);
693
0
    ctx->perc_active = (src_pcs->dg_detector->metrics.tot_active * 100) / (pic_height_in_b64 * pic_width_in_b64);
694
0
}
695
696
0
#define HIGH_DIST_TH 16 * 16 * 18
697
0
#define LOW_DIST_TH 16 * 16 * 2
698
699
static void calc_mini_gop_activity(PictureDecisionContext* ctx, EncodeContext* enc_ctx, uint64_t top_layer_idx,
700
                                   uint64_t top_layer_dist, uint8_t top_layer_perc_active, uint8_t top_layer_perc_cplx,
701
                                   uint64_t sub_layer_idx0, uint64_t sub_layer_dist0, uint8_t sub_layer0_perc_active,
702
                                   uint8_t sub_layer0_perc_cplx, uint64_t sub_layer_idx1, uint64_t sub_layer_dist1,
703
                                   uint8_t sub_layer1_perc_active, uint8_t sub_layer1_perc_cplx,
704
                                   int16_t top_layer_mv_in_out_count, int16_t sub_layer_mv_in_out_count1,
705
0
                                   int16_t sub_layer_mv_in_out_count2) {
706
0
    (void)top_layer_mv_in_out_count;
707
    // The bias is function of the previous mini-gop structure towards less switch(es) within the same gop
708
    // 6L will be maintained unless the presence of a significant change compared to the previous mini-gop
709
    // To do: make the bias function of the preset; higher is the preset, higher is the bias towards less 6L
710
0
    int bias = (enc_ctx->mini_gop_cnt_per_gop > 1 && enc_ctx->previous_mini_gop_hierarchical_levels == 5) ? 25 : 75;
711
0
    const bool cond1 = top_layer_perc_active >= 95 && !(sub_layer0_perc_active >= 95 && sub_layer1_perc_active < 75) &&
712
0
        !(sub_layer0_perc_active < 75 && sub_layer1_perc_active >= 95);
713
0
    const bool cond2 = top_layer_dist > LOW_DIST_TH && sub_layer_dist0 < HIGH_DIST_TH &&
714
0
        sub_layer_dist1 < HIGH_DIST_TH && top_layer_perc_cplx > 0 && sub_layer0_perc_cplx < 25 &&
715
0
        sub_layer1_perc_cplx < 25 && (((sub_layer_dist0 + sub_layer_dist1) / 2) < ((bias * top_layer_dist) / 100));
716
717
0
    const bool cond3 = MIN(sub_layer_mv_in_out_count1, sub_layer_mv_in_out_count2) > 40 &&
718
0
        MAX(sub_layer_mv_in_out_count1, sub_layer_mv_in_out_count2) > 55;
719
720
0
    if (cond1 && (cond2 || cond3)) {
721
0
        ctx->mini_gop_activity_array[top_layer_idx]  = true;
722
0
        ctx->mini_gop_activity_array[sub_layer_idx0] = false;
723
0
        ctx->mini_gop_activity_array[sub_layer_idx1] = false;
724
0
    }
725
0
}
726
727
static void eval_sub_mini_gop(PictureDecisionContext* ctx, EncodeContext* enc_ctx, uint64_t top_layer_idx,
728
                              uint64_t sub_layer_idx0, uint64_t sub_layer_idx1, PictureParentControlSet* start_pcs,
729
0
                              PictureParentControlSet* mid_pcs, PictureParentControlSet* end_pcs) {
730
0
    early_hme(ctx, end_pcs, start_pcs);
731
732
0
    uint64_t dist_end_start            = ctx->norm_dist;
733
0
    uint8_t  perc_cplx_end_start       = ctx->perc_cplx;
734
0
    uint8_t  perc_active_end_start     = ctx->perc_active;
735
0
    int16_t  mv_in_out_count_end_start = ctx->mv_in_out_count;
736
0
    early_hme(ctx, end_pcs, mid_pcs);
737
738
0
    uint64_t dist_end_mid            = ctx->norm_dist;
739
0
    uint8_t  perc_cplx_end_mid       = ctx->perc_cplx;
740
0
    uint8_t  perc_active_end_mid     = ctx->perc_active;
741
0
    int16_t  mv_in_out_count_end_mid = ctx->mv_in_out_count;
742
743
0
    early_hme(ctx, mid_pcs, start_pcs);
744
745
0
    uint64_t dist_mid_start            = ctx->norm_dist;
746
0
    uint8_t  perc_cplx_mid_start       = ctx->perc_cplx;
747
0
    uint8_t  perc_active_mid_start     = ctx->perc_active;
748
0
    int16_t  mv_in_out_count_mid_start = ctx->mv_in_out_count;
749
750
0
    calc_mini_gop_activity(ctx,
751
0
                           enc_ctx,
752
0
                           top_layer_idx,
753
0
                           dist_end_start,
754
0
                           perc_active_end_start,
755
0
                           perc_cplx_end_start,
756
0
                           sub_layer_idx0,
757
0
                           dist_mid_start,
758
0
                           perc_active_mid_start,
759
0
                           perc_cplx_mid_start,
760
0
                           sub_layer_idx1,
761
0
                           dist_end_mid,
762
0
                           perc_active_end_mid,
763
0
                           perc_cplx_end_mid,
764
0
                           mv_in_out_count_end_start,
765
0
                           mv_in_out_count_end_mid,
766
0
                           mv_in_out_count_mid_start);
767
0
}
768
769
/***************************************************************************************************
770
* Initializes mini GOP activity array
771
*
772
***************************************************************************************************/
773
static void initialize_mini_gop_activity_array(SequenceControlSet* scs, PictureParentControlSet* pcs,
774
0
                                               EncodeContext* enc_ctx, PictureDecisionContext* ctx) {
775
0
    (void)scs;
776
777
    // Loop over all mini GOPs to initialize the activity
778
0
    for (uint32_t gopindex = 0; gopindex < MINI_GOP_MAX_COUNT; ++gopindex) {
779
0
        ctx->mini_gop_activity_array[gopindex] = svt_aom_get_mini_gop_stats(gopindex)->hierarchical_levels >
780
0
            MIN_HIERARCHICAL_LEVEL;
781
0
    }
782
783
    // Assign the MGs to be used; if the MG is incomplete, the pre-assignment buffer will hold
784
    // fewer than (1 << scs->static_config.hierarchical_levels) pics
785
0
    if (enc_ctx->pre_assignment_buffer_count >= 32 && !(enc_ctx->pre_assignment_buffer_count == 32 && pcs->idr_flag)) {
786
0
        ctx->mini_gop_activity_array[L6_INDEX] = false;
787
0
    } else if (enc_ctx->pre_assignment_buffer_count >= 16 &&
788
0
               !(enc_ctx->pre_assignment_buffer_count == 16 && pcs->idr_flag)) {
789
0
        ctx->mini_gop_activity_array[L5_0_INDEX] = false;
790
791
0
        if ((enc_ctx->pre_assignment_buffer_count - 16) >= 8 &&
792
0
            !((enc_ctx->pre_assignment_buffer_count - 16) == 8 && pcs->idr_flag)) {
793
0
            ctx->mini_gop_activity_array[L4_2_INDEX] = false;
794
795
0
            if ((enc_ctx->pre_assignment_buffer_count - 16 - 8) >= 4 &&
796
0
                !((enc_ctx->pre_assignment_buffer_count - 16 - 8) == 4 && pcs->idr_flag)) {
797
0
                ctx->mini_gop_activity_array[L3_6_INDEX] = false;
798
799
0
                if ((enc_ctx->pre_assignment_buffer_count - 16 - 8 - 4) >= 2 &&
800
0
                    !((enc_ctx->pre_assignment_buffer_count - 16 - 8 - 4) == 2 && pcs->idr_flag)) {
801
0
                    ctx->mini_gop_activity_array[L2_14_INDEX] = false;
802
0
                }
803
0
            } else if ((enc_ctx->pre_assignment_buffer_count - 16 - 8) >= 2 &&
804
0
                       !((enc_ctx->pre_assignment_buffer_count - 16 - 8) == 2 && pcs->idr_flag)) {
805
0
                ctx->mini_gop_activity_array[L2_12_INDEX] = false;
806
0
            }
807
0
        } else if ((enc_ctx->pre_assignment_buffer_count - 16) >= 4 &&
808
0
                   !((enc_ctx->pre_assignment_buffer_count - 16) == 4 && pcs->idr_flag)) {
809
0
            ctx->mini_gop_activity_array[L3_4_INDEX] = false;
810
811
0
            if ((enc_ctx->pre_assignment_buffer_count - 16 - 4) >= 2 &&
812
0
                !((enc_ctx->pre_assignment_buffer_count - 16 - 4) == 2 && pcs->idr_flag)) {
813
0
                ctx->mini_gop_activity_array[L2_10_INDEX] = false;
814
0
            }
815
0
        } else if ((enc_ctx->pre_assignment_buffer_count - 16) >= 2 &&
816
0
                   !((enc_ctx->pre_assignment_buffer_count - 16) == 2 && pcs->idr_flag)) {
817
0
            ctx->mini_gop_activity_array[L2_8_INDEX] = false;
818
0
        }
819
0
    } else if (enc_ctx->pre_assignment_buffer_count >= 8 &&
820
0
               !(enc_ctx->pre_assignment_buffer_count == 8 && pcs->idr_flag)) {
821
0
        ctx->mini_gop_activity_array[L4_0_INDEX] = false;
822
823
0
        if ((enc_ctx->pre_assignment_buffer_count - 8) >= 4 &&
824
0
            !((enc_ctx->pre_assignment_buffer_count - 8) == 4 && pcs->idr_flag)) {
825
0
            ctx->mini_gop_activity_array[L3_2_INDEX] = false;
826
827
0
            if ((enc_ctx->pre_assignment_buffer_count - 8 - 4) >= 2 &&
828
0
                !((enc_ctx->pre_assignment_buffer_count - 8 - 4) == 2 && pcs->idr_flag)) {
829
0
                ctx->mini_gop_activity_array[L2_6_INDEX] = false;
830
0
            }
831
0
        } else if ((enc_ctx->pre_assignment_buffer_count - 8) >= 2 &&
832
0
                   !((enc_ctx->pre_assignment_buffer_count - 8) == 2 && pcs->idr_flag)) {
833
0
            ctx->mini_gop_activity_array[L2_4_INDEX] = false;
834
0
        }
835
0
    } else if (enc_ctx->pre_assignment_buffer_count >= 4 &&
836
0
               !(enc_ctx->pre_assignment_buffer_count == 4 && pcs->idr_flag)) {
837
0
        ctx->mini_gop_activity_array[L3_0_INDEX] = false;
838
839
0
        if ((enc_ctx->pre_assignment_buffer_count - 4) >= 2 &&
840
0
            !((enc_ctx->pre_assignment_buffer_count - 4) == 2 && pcs->idr_flag)) {
841
0
            ctx->mini_gop_activity_array[L2_2_INDEX] = false;
842
0
        }
843
0
    } else if ((enc_ctx->pre_assignment_buffer_count) >= 2 &&
844
0
               !((enc_ctx->pre_assignment_buffer_count) == 2 && pcs->idr_flag)) {
845
0
        ctx->mini_gop_activity_array[L2_0_INDEX] = false;
846
0
    }
847
848
    // 6L vs. 5L
849
0
    if (scs->enable_dg && ctx->mini_gop_activity_array[L6_INDEX] == false) {
850
0
        PictureParentControlSet* start_pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[0]->object_ptr;
851
0
        PictureParentControlSet* mid_pcs =
852
0
            (PictureParentControlSet*)enc_ctx
853
0
                ->pre_assignment_buffer[((1 << scs->static_config.hierarchical_levels) >> 1) - 1]
854
0
                ->object_ptr;
855
0
        PictureParentControlSet* end_pcs = (PictureParentControlSet*)enc_ctx
856
0
                                               ->pre_assignment_buffer[enc_ctx->pre_assignment_buffer_count - 1]
857
0
                                               ->object_ptr;
858
0
        eval_sub_mini_gop(ctx, enc_ctx, L6_INDEX, L5_0_INDEX, L5_1_INDEX, start_pcs, mid_pcs, end_pcs);
859
0
    }
860
0
    ctx->list0_only = 0;
861
0
    if (scs->list0_only_base) {
862
0
        ctx->list0_only = 1;
863
0
    }
864
0
}
865
866
/***************************************************************************************************
867
* Generates block picture map
868
*
869
*
870
***************************************************************************************************/
871
0
static EbErrorType generate_picture_window_split(PictureDecisionContext* pd_ctx, EncodeContext* enc_ctx) {
872
0
    pd_ctx->total_number_of_mini_gops = 0;
873
    // Loop over all mini GOPs
874
0
    for (uint32_t gopindex = 0; gopindex < MINI_GOP_MAX_COUNT; gopindex += pd_ctx->mini_gop_activity_array[gopindex]
875
0
             ? 1
876
0
             : mini_gop_offset[svt_aom_get_mini_gop_stats(gopindex)->hierarchical_levels - MIN_HIERARCHICAL_LEVEL]) {
877
        // Only for a valid mini GOP
878
0
        if (svt_aom_get_mini_gop_stats(gopindex)->end_index < enc_ctx->pre_assignment_buffer_count &&
879
0
            !pd_ctx->mini_gop_activity_array[gopindex]) {
880
0
            pd_ctx->mini_gop_start_index[pd_ctx->total_number_of_mini_gops] =
881
0
                svt_aom_get_mini_gop_stats(gopindex)->start_index;
882
0
            pd_ctx->mini_gop_end_index[pd_ctx->total_number_of_mini_gops] =
883
0
                svt_aom_get_mini_gop_stats(gopindex)->end_index;
884
0
            pd_ctx->mini_gop_length[pd_ctx->total_number_of_mini_gops] = svt_aom_get_mini_gop_stats(gopindex)->length;
885
0
            pd_ctx->mini_gop_hierarchical_levels[pd_ctx->total_number_of_mini_gops] =
886
0
                svt_aom_get_mini_gop_stats(gopindex)->hierarchical_levels;
887
0
            pd_ctx->mini_gop_intra_count[pd_ctx->total_number_of_mini_gops] = 0;
888
0
            pd_ctx->mini_gop_idr_count[pd_ctx->total_number_of_mini_gops]   = 0;
889
0
            pd_ctx->total_number_of_mini_gops++;
890
0
        }
891
0
    }
892
    // Only in presence of at least 1 valid mini GOP
893
0
    if (pd_ctx->total_number_of_mini_gops != 0) {
894
0
        pd_ctx->mini_gop_intra_count[pd_ctx->total_number_of_mini_gops - 1] =
895
0
            enc_ctx->pre_assignment_buffer_intra_count;
896
0
        pd_ctx->mini_gop_idr_count[pd_ctx->total_number_of_mini_gops - 1] = enc_ctx->pre_assignment_buffer_idr_count;
897
0
    }
898
0
    return EB_ErrorNone;
899
0
}
900
901
/***************************************************************************************************
902
* Handles an incomplete picture window map
903
*
904
*
905
***************************************************************************************************/
906
static EbErrorType handle_incomplete_picture_window_map(uint32_t hierarchical_level, PictureDecisionContext* pd_ctx,
907
0
                                                        EncodeContext* enc_ctx) {
908
0
    EbErrorType return_error = EB_ErrorNone;
909
0
    if (pd_ctx->total_number_of_mini_gops == 0) {
910
0
        hierarchical_level = MIN(MIN_HIERARCHICAL_LEVEL, hierarchical_level);
911
0
        pd_ctx->mini_gop_start_index[pd_ctx->total_number_of_mini_gops] = 0;
912
0
        pd_ctx->mini_gop_end_index[pd_ctx->total_number_of_mini_gops]   = enc_ctx->pre_assignment_buffer_count - 1;
913
0
        pd_ctx->mini_gop_length[pd_ctx->total_number_of_mini_gops]      = enc_ctx->pre_assignment_buffer_count -
914
0
            pd_ctx->mini_gop_start_index[pd_ctx->total_number_of_mini_gops];
915
0
        pd_ctx->mini_gop_hierarchical_levels[pd_ctx->total_number_of_mini_gops] = hierarchical_level;
916
917
0
        pd_ctx->total_number_of_mini_gops++;
918
0
    } else if (pd_ctx->mini_gop_end_index[pd_ctx->total_number_of_mini_gops - 1] <
919
0
               enc_ctx->pre_assignment_buffer_count - 1) {
920
0
        pd_ctx->mini_gop_start_index[pd_ctx->total_number_of_mini_gops] =
921
0
            pd_ctx->mini_gop_end_index[pd_ctx->total_number_of_mini_gops - 1] + 1;
922
0
        pd_ctx->mini_gop_end_index[pd_ctx->total_number_of_mini_gops] = enc_ctx->pre_assignment_buffer_count - 1;
923
0
        pd_ctx->mini_gop_length[pd_ctx->total_number_of_mini_gops]    = enc_ctx->pre_assignment_buffer_count -
924
0
            pd_ctx->mini_gop_start_index[pd_ctx->total_number_of_mini_gops];
925
0
        pd_ctx->mini_gop_hierarchical_levels[pd_ctx->total_number_of_mini_gops] = MIN_HIERARCHICAL_LEVEL;
926
0
        pd_ctx->mini_gop_intra_count[pd_ctx->total_number_of_mini_gops - 1]     = 0;
927
0
        pd_ctx->mini_gop_idr_count[pd_ctx->total_number_of_mini_gops - 1]       = 0;
928
929
0
        pd_ctx->total_number_of_mini_gops++;
930
0
    }
931
932
0
    pd_ctx->mini_gop_intra_count[pd_ctx->total_number_of_mini_gops - 1] = enc_ctx->pre_assignment_buffer_intra_count;
933
0
    pd_ctx->mini_gop_idr_count[pd_ctx->total_number_of_mini_gops - 1]   = enc_ctx->pre_assignment_buffer_idr_count;
934
935
0
    return return_error;
936
0
}
937
938
/*
939
   This function tells if a picture is part of a short
940
   mg in RA configuration
941
*/
942
431
uint8_t is_pic_cutting_short_ra_mg(PictureDecisionContext* pd_ctx, PictureParentControlSet* pcs, uint32_t mg_idx) {
943
    //if the size < complete MG or if there is usage of closed GOP
944
431
    if ((pd_ctx->mini_gop_length[mg_idx] < pcs->pred_struct_ptr->pred_struct_entry_count ||
945
0
         pd_ctx->mini_gop_idr_count[mg_idx] > 0) &&
946
431
        pcs->pred_struct_ptr->pred_type == RANDOM_ACCESS && pcs->idr_flag == false && pcs->cra_flag == false) {
947
0
        return 1;
948
431
    } else {
949
431
        return 0;
950
431
    }
951
431
}
952
953
/***************************************************************************************************
954
* Gets the pred struct for each frame in the mini-gop(s) that we have available
955
***************************************************************************************************/
956
431
static void get_pred_struct_for_all_frames(PictureDecisionContext* ctx, EncodeContext* enc_ctx) {
957
    // Loop over all mini GOPs
958
862
    for (unsigned int mini_gop_index = 0; mini_gop_index < ctx->total_number_of_mini_gops; ++mini_gop_index) {
959
        // Loop over picture within the mini GOP
960
431
        for (unsigned int pic_idx = ctx->mini_gop_start_index[mini_gop_index];
961
862
             pic_idx <= ctx->mini_gop_end_index[mini_gop_index];
962
431
             pic_idx++) {
963
431
            PictureParentControlSet* pcs =
964
431
                (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
965
431
            SequenceControlSet* scs = pcs->scs;
966
#if DEBUG_STARTUP_MG_SIZE
967
            if (pcs->idr_flag || pcs->cra_flag) {
968
                SVT_LOG("Frame %d, key-frame\n", (int)pcs->picture_number);
969
            }
970
            if (pic_idx == ctx->mini_gop_start_index[mini_gop_index]) {
971
                SVT_LOG("mGOP start %d, mGOP length %d, startup mini-GOP %d\n",
972
                        (int)pcs->picture_number,
973
                        ctx->mini_gop_length[mini_gop_index],
974
                        ctx->enable_startup_mg);
975
            }
976
            if (pic_idx == ctx->mini_gop_end_index[mini_gop_index]) {
977
                SVT_LOG(
978
                    "mGOP end %d, mGOP length %d\n", (int)pcs->picture_number, ctx->mini_gop_length[mini_gop_index]);
979
            }
980
#endif
981
431
            pcs->pred_structure      = scs->static_config.pred_structure;
982
431
            pcs->hierarchical_levels = pcs->idr_flag ? scs->static_config.hierarchical_levels
983
431
                                                     : (uint8_t)ctx->mini_gop_hierarchical_levels[mini_gop_index];
984
431
            pcs->pred_struct_ptr     = svt_aom_get_prediction_structure(
985
431
                enc_ctx->prediction_structure_group_ptr, pcs->pred_structure, pcs->hierarchical_levels);
986
987
431
            if (scs->static_config.startup_mg_size != 0) {
988
0
                if (pcs->idr_flag || pcs->cra_flag) {
989
0
                    ctx->enable_startup_mg = true;
990
0
                } else if (ctx->enable_startup_mg) {
991
0
                    ctx->enable_startup_mg = false;
992
0
                }
993
0
            }
994
431
            if (pcs->idr_flag && pcs->picture_number == 0) {
995
431
                ctx->is_startup_gop = true;
996
431
            } else if (pcs->idr_flag || pcs->cra_flag) {
997
0
                ctx->is_startup_gop = false;
998
0
            }
999
431
            pcs->is_startup_gop = ctx->is_startup_gop;
1000
431
        }
1001
431
    }
1002
431
}
1003
1004
0
void svt_aom_get_gm_needed_resolutions(uint8_t ds_lvl, bool* gm_need_full, bool* gm_need_quart, bool* gm_need_sixteen) {
1005
0
    *gm_need_full    = (ds_lvl == GM_FULL) || (ds_lvl == GM_ADAPT_0);
1006
0
    *gm_need_quart   = (ds_lvl == GM_DOWN) || (ds_lvl == GM_ADAPT_0) || (ds_lvl == GM_ADAPT_1);
1007
0
    *gm_need_sixteen = (ds_lvl == GM_DOWN16) || (ds_lvl == GM_ADAPT_1);
1008
0
}
1009
1010
6.57k
bool svt_aom_is_pic_skipped(PictureParentControlSet* pcs) {
1011
6.57k
    if (!pcs->is_ref && pcs->scs->rc_stat_gen_pass_mode && !pcs->first_frame_in_minigop) {
1012
0
        return true;
1013
0
    }
1014
6.57k
    return false;
1015
6.57k
}
1016
1017
static void prune_sframe_refs(PictureDecisionContext* ctx, PictureParentControlSet* ppcs,
1018
431
                              MvReferenceFrame ref_frame_arr[], uint8_t* tot_ref_frames) {
1019
431
    if (ctx->sframe_poc > 0 && ppcs->picture_number < ctx->sframe_poc && ppcs->scs->mfmv_enabled) {
1020
#if DEBUG_SFRAME
1021
        fprintf(stderr, "frame[%u] ref before prune:\t", ppcs->picture_number);
1022
        for (uint8_t i = 0; i < *tot_ref_frames; i++) {
1023
            fprintf(stderr, "%u\t", ref_frame_arr[i]);
1024
        }
1025
#endif // DEBUG_SFRAME
1026
        // check every reference frames, if it's in ref_list0 and direct to S-Frame, remove it from array
1027
0
        uint32_t sframe_poc = ctx->sframe_poc %
1028
0
            ((uint64_t)1 << (ppcs->scs->seq_header.order_hint_info.order_hint_bits));
1029
0
        uint8_t ref_idx = 0;
1030
0
        while (ref_idx < *tot_ref_frames) {
1031
0
            MvReferenceFrame rf[2];
1032
0
            av1_set_ref_frame(rf, ref_frame_arr[ref_idx]);
1033
0
            if ((rf[0] < BWDREF_FRAME && ppcs->ref_order_hint[rf[0]] == sframe_poc) ||
1034
0
                (rf[1] < BWDREF_FRAME && ppcs->ref_order_hint[rf[1]] == sframe_poc)) {
1035
0
                (*tot_ref_frames)--;
1036
0
                for (uint8_t i = ref_idx; i < *tot_ref_frames; i++) {
1037
0
                    ref_frame_arr[i] = ref_frame_arr[i + 1];
1038
0
                }
1039
0
                ppcs->sframe_ref_pruned = true;
1040
                // ref_idx not increase to prevent skipping next item
1041
0
                continue;
1042
0
            }
1043
0
            ref_idx++;
1044
0
        };
1045
        // only prune ref_list0 will not make the array zero item, but still add assertion here
1046
0
        assert(*tot_ref_frames > 0);
1047
#if DEBUG_SFRAME
1048
        fprintf(stderr, "\nframe[%u] ref after prune:\t", ppcs->picture_number);
1049
        for (uint8_t i = 0; i < *tot_ref_frames; i++) {
1050
            fprintf(stderr, "%u\t", ref_frame_arr[i]);
1051
        }
1052
        fprintf(stderr, "\n");
1053
#endif // DEBUG_SFRAME
1054
0
    }
1055
431
}
1056
1057
//set the ref frame types used for this picture,
1058
static void set_all_ref_frame_type(PictureDecisionContext* ctx, PictureParentControlSet* ppcs,
1059
431
                                   MvReferenceFrame ref_frame_arr[], uint8_t* tot_ref_frames) {
1060
431
    MvReferenceFrame rf[2];
1061
431
    *tot_ref_frames = 0;
1062
1063
    //SVT_LOG("POC %i  totRef L0:%i   totRef L1: %i\n", ppcs->picture_number, ppcs->ref_list0_count, ppcs->ref_list1_count);
1064
1065
    //single ref - List0
1066
431
    for (uint8_t ref_idx0 = 0; ref_idx0 < ppcs->ref_list0_count_try; ++ref_idx0) {
1067
0
        rf[0]                              = svt_get_ref_frame_type(REF_LIST_0, ref_idx0);
1068
0
        ref_frame_arr[(*tot_ref_frames)++] = rf[0];
1069
0
    }
1070
1071
    //single ref - List1
1072
431
    for (uint8_t ref_idx1 = 0; ref_idx1 < ppcs->ref_list1_count_try; ++ref_idx1) {
1073
0
        rf[1]                              = svt_get_ref_frame_type(REF_LIST_1, ref_idx1);
1074
0
        ref_frame_arr[(*tot_ref_frames)++] = rf[1];
1075
0
    }
1076
1077
    //compound Bi-Dir
1078
431
    for (uint8_t ref_idx0 = 0; ref_idx0 < ppcs->ref_list0_count_try; ++ref_idx0) {
1079
0
        for (uint8_t ref_idx1 = 0; ref_idx1 < ppcs->ref_list1_count_try; ++ref_idx1) {
1080
0
            rf[0]                              = svt_get_ref_frame_type(REF_LIST_0, ref_idx0);
1081
0
            rf[1]                              = svt_get_ref_frame_type(REF_LIST_1, ref_idx1);
1082
0
            ref_frame_arr[(*tot_ref_frames)++] = av1_ref_frame_type(rf);
1083
0
        }
1084
0
    }
1085
431
    if (ppcs->slice_type == B_SLICE) {
1086
        //compound Uni-Dir
1087
0
        if (ppcs->ref_list0_count_try > 1) {
1088
0
            rf[0]                              = LAST_FRAME;
1089
0
            rf[1]                              = LAST2_FRAME;
1090
0
            ref_frame_arr[(*tot_ref_frames)++] = av1_ref_frame_type(rf);
1091
0
            if (ppcs->ref_list0_count_try > 2) {
1092
0
                rf[1]                              = LAST3_FRAME;
1093
0
                ref_frame_arr[(*tot_ref_frames)++] = av1_ref_frame_type(rf);
1094
0
                if (ppcs->ref_list0_count_try > 3) {
1095
0
                    rf[1]                              = GOLDEN_FRAME;
1096
0
                    ref_frame_arr[(*tot_ref_frames)++] = av1_ref_frame_type(rf);
1097
0
                }
1098
0
            }
1099
0
        }
1100
0
        if (ppcs->ref_list1_count_try > 2) {
1101
0
            rf[0]                              = BWDREF_FRAME;
1102
0
            rf[1]                              = ALTREF_FRAME;
1103
0
            ref_frame_arr[(*tot_ref_frames)++] = av1_ref_frame_type(rf);
1104
0
        }
1105
0
    }
1106
1107
    // The S-Frame feature in RA mode refreshes all reference frames at the S-Frame position (ARF).
1108
    // However, in decode order, the remaining frames in this mini-GOP reference the S-Frame through
1109
    // [LAST, LAST2, LAST3, GOLD]. When MFMV is enabled, the reference MVs to the S-Frame are duplicated
1110
    // and have reversed direction. Prune the S-Frame reference types from ref_list0 to avoid conflicts.
1111
431
    prune_sframe_refs(ctx, ppcs, ref_frame_arr, tot_ref_frames);
1112
431
}
1113
1114
0
static void prune_refs(Av1RpsNode* av1_rps, unsigned ref_list0_count, unsigned ref_list1_count) {
1115
0
    if (ref_list0_count < 4) {
1116
0
        av1_rps->ref_dpb_index[GOLD] = av1_rps->ref_dpb_index[LAST];
1117
0
        av1_rps->ref_poc_array[GOLD] = av1_rps->ref_poc_array[LAST];
1118
0
    }
1119
0
    if (ref_list0_count < 3) {
1120
0
        av1_rps->ref_dpb_index[LAST3] = av1_rps->ref_dpb_index[LAST];
1121
0
        av1_rps->ref_poc_array[LAST3] = av1_rps->ref_poc_array[LAST];
1122
0
    }
1123
0
    if (ref_list0_count < 2) {
1124
0
        av1_rps->ref_dpb_index[LAST2] = av1_rps->ref_dpb_index[LAST];
1125
0
        av1_rps->ref_poc_array[LAST2] = av1_rps->ref_poc_array[LAST];
1126
0
    }
1127
1128
    // If not list 1 refs are used, set the refs to the list 0 ref
1129
0
    if (ref_list1_count < 1) {
1130
0
        av1_rps->ref_dpb_index[BWD] = av1_rps->ref_dpb_index[LAST];
1131
0
        av1_rps->ref_poc_array[BWD] = av1_rps->ref_poc_array[LAST];
1132
0
    }
1133
0
    if (ref_list1_count < 3) {
1134
0
        av1_rps->ref_dpb_index[ALT] = av1_rps->ref_dpb_index[BWD];
1135
0
        av1_rps->ref_poc_array[ALT] = av1_rps->ref_poc_array[BWD];
1136
0
    }
1137
0
    if (ref_list1_count < 2) {
1138
0
        av1_rps->ref_dpb_index[ALT2] = av1_rps->ref_dpb_index[BWD];
1139
0
        av1_rps->ref_poc_array[ALT2] = av1_rps->ref_poc_array[BWD];
1140
0
    }
1141
0
}
1142
1143
// Set the show_frame and show_existing_frame for current picture if it's:
1144
// 1)Low delay P, 2)Low delay b and 3)I frames of RA
1145
// For b frames of RA, need to set it manually based on picture_index
1146
static bool set_frame_display_params(PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx,
1147
0
                                     uint32_t mini_gop_index) {
1148
0
    FrameHeader* frm_hdr = &pcs->frm_hdr;
1149
1150
0
    if (pcs->pred_struct_ptr->pred_type == LOW_DELAY || pcs->is_overlay) {
1151
0
        frm_hdr->show_frame    = true;
1152
0
        pcs->has_show_existing = false;
1153
0
    } else {
1154
        //Decide on Show Mecanism
1155
0
        if (pcs->slice_type == I_SLICE) {
1156
            //3 cases for I slice:  1:Key Frame treated above.  2: broken MiniGop due to sc or intra refresh  3: complete miniGop due to sc or intra refresh
1157
0
            if (pd_ctx->mini_gop_length[mini_gop_index] < pcs->pred_struct_ptr->pred_struct_entry_count) {
1158
                //Scene Change that breaks the mini gop and switch to LDP (if I scene change happens to be aligned with a complete miniGop, then we do not break the pred structure)
1159
0
                frm_hdr->show_frame    = true;
1160
0
                pcs->has_show_existing = false;
1161
0
            } else {
1162
0
                frm_hdr->show_frame    = false;
1163
0
                pcs->has_show_existing = false;
1164
0
            }
1165
0
        } else {
1166
0
            if (pd_ctx->mini_gop_length[mini_gop_index] != pcs->pred_struct_ptr->pred_struct_entry_count) {
1167
0
                SVT_LOG("Error in GOP indexing3\n");
1168
0
            }
1169
            // Handle b frame of Random Access out
1170
0
            return false;
1171
0
        }
1172
0
    }
1173
0
    return true;
1174
0
}
1175
1176
431
static void ref_mgmt_reset_state(PictureDecisionContext* ctx) {
1177
431
    memset(ctx->pic_id_per_dpb_slot, 0, sizeof(ctx->pic_id_per_dpb_slot));
1178
431
}
1179
1180
// Bitmask of currently-STOREd DPB slots, derived from pic_id_per_dpb_slot:
1181
// bit i is set iff slot i holds a nonzero app pic_id. pic_id 0 is the
1182
// "no id" sentinel and a STORE always records a nonzero id, so a nonzero
1183
// entry is exactly a held STORE. This keeps pic_id_per_dpb_slot the single
1184
// source of truth (no separate mask to keep in sync). Called per-frame in
1185
// pd_process; REF_FRAMES==8, not on the per-block hot path.
1186
431
static uint8_t ref_mgmt_stored_mask(const PictureDecisionContext* ctx) {
1187
431
    uint8_t m = 0;
1188
3.87k
    for (uint8_t i = 0; i < REF_FRAMES; ++i) {
1189
3.44k
        if (ctx->pic_id_per_dpb_slot[i] != 0) {
1190
0
            m |= (uint8_t)(1u << i);
1191
0
        }
1192
3.44k
    }
1193
431
    return m;
1194
431
}
1195
1196
// Ref-frame management helpers — operate on PictureDecisionContext state
1197
// (pic_id_per_dpb_slot; the STOREd-slot bitmask is derived on demand via
1198
// ref_mgmt_stored_mask). STOREd slots are allocated dynamically: the
1199
// encoder picks a slot the short-term allocator was already going to
1200
// refresh this frame, then locks it by recording its pic_id. CLEAR
1201
// releases a slot back to the ST allocator. The post-branch refresh-guard
1202
// masks out STOREd-slot bits so the encoder never overwrites a locked slot.
1203
1204
// Find DPB slot currently holding `pic_id` (must be STOREd). Returns REF_FRAMES on miss.
1205
0
static uint8_t ref_mgmt_find_slot(const PictureDecisionContext* ctx, uint32_t pic_id) {
1206
0
    if (pic_id == 0) {
1207
0
        return (uint8_t)REF_FRAMES; // 0 = "no id" sentinel
1208
0
    }
1209
0
    for (uint8_t i = 0; i < REF_FRAMES; ++i) {
1210
0
        if (ctx->pic_id_per_dpb_slot[i] == pic_id) {
1211
0
            return i;
1212
0
        }
1213
0
    }
1214
0
    return (uint8_t)REF_FRAMES;
1215
0
}
1216
1217
// CLEAR: release a previously-STOREd pic_id. Warns + no-ops if id unknown.
1218
0
static void apply_ref_clear(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1219
0
    const uint32_t pid  = pcs->ref_mgmt.clear_id;
1220
0
    const uint8_t  slot = ref_mgmt_find_slot(ctx, pid);
1221
0
    if (slot >= REF_FRAMES) {
1222
0
        SVT_ERROR("Ref-frame mgmt: CLEAR pic_id=%u not found in DPB; no-op (poc=%lu)\n",
1223
0
                  (unsigned)pid,
1224
0
                  (unsigned long)pcs->picture_number);
1225
0
        return;
1226
0
    }
1227
0
    ctx->pic_id_per_dpb_slot[slot] = 0;
1228
0
}
1229
1230
// STORE-safe DPB slot pool: complement of the slots that some active LD-CBR
1231
// pred-struct branch refreshes as the sole bit of refresh_frame_mask.
1232
// Locking one of those slots would collapse the branch's refresh mask to 0
1233
// in apply_ref_mgmt_events Phase 3 → crash in assign_and_release_pa_refs.
1234
// Mirror of av1_generate_rps_info LD-CBR branch (line 2024-2126); keep in
1235
// sync when refresh_frame_mask assignments there change. LTR is gated to
1236
// LD-CBR in enc_settings.c — LD-CRF's shifted lay1_offset would need its
1237
// own branch here. Slot 7's long-base period-128 refresh is silently
1238
// suppressed when STOREd by the same Phase 3 guard, so it stays safe.
1239
0
static uint8_t exclusive_write_slots_mask_ld_cbr(const SequenceControlSet* scs) {
1240
0
    uint8_t       mask      = 0;
1241
0
    const uint8_t hier      = scs->static_config.hierarchical_levels;
1242
0
    const uint8_t ld_reduce = scs->mrp_ctrls.ld_reduce_ref_buffs;
1243
1244
    // TID-0: single-bit `1 << lay0_toggle` (toggle ∈ {0,1,2}) only at
1245
    // ld_reduce=0; backup bits (`| 0xf0` / `| 0xfc`) make it non-exclusive otherwise.
1246
0
    if (ld_reduce == 0) {
1247
0
        mask |= 0x07u;
1248
0
    }
1249
    // TID-1: always single-bit; slot depends on ld_reduce.
1250
0
    if (hier >= 1) {
1251
0
        switch (ld_reduce) {
1252
0
        case 0:
1253
0
            mask |= (uint8_t)((1u << LAY1_OFF) | (1u << (LAY1_OFF + 1)));
1254
0
            break;
1255
0
        case 1:
1256
0
            mask |= (uint8_t)(1u << LAY1_OFF);
1257
0
            break;
1258
0
        case 2:
1259
0
            mask |= (uint8_t)(1u << 1);
1260
0
            break;
1261
0
        default:
1262
0
            assert(0 && "unhandled ld_reduce_ref_buffs");
1263
0
            break;
1264
0
        }
1265
0
    }
1266
    // TID-2: ld_reduce > 0 force-zeros TID-2 refresh, so only exclusive at ld_reduce=0.
1267
0
    if (hier >= 2 && ld_reduce == 0) {
1268
0
        mask |= (uint8_t)(1u << LAY2_OFF);
1269
0
    }
1270
0
    return mask;
1271
0
}
1272
1273
0
uint8_t svt_aom_ref_mgmt_storeable_slots_mask(const SequenceControlSet* scs) {
1274
    // Flat IPP (hier=0): regular refs only ever occupy slots [0..flat_max_refs-1]
1275
    // (flat_max_refs <= 4) and lay0_toggle rotates through them, while slots 4-7
1276
    // are the per-frame `| 0xf0` refresh/clear backup and are never read as refs.
1277
    // Returning 0xFF is crash-safe (the 0xf0 backup keeps the Phase-3 refresh
1278
    // guard from collapsing refresh_frame_mask to 0), but STOREing into a bottom
1279
    // slot would let the Phase-3 guard freeze a slot the toggle still rotates
1280
    // through, silently dropping a live ref out of the window. Restrict STORE to
1281
    // the top 4 so it never interferes with the regular sliding-window refs.
1282
0
    if (scs->use_flat_ipp) {
1283
0
        return 0xF0u;
1284
0
    }
1285
0
    if (scs->static_config.pred_structure == LOW_DELAY && scs->static_config.hierarchical_levels >= 1) {
1286
0
        return (uint8_t)(~exclusive_write_slots_mask_ld_cbr(scs) & 0xFFu);
1287
0
    }
1288
    // RA / other paths: not LTR-eligible (rejected in enc_settings.c).
1289
0
    return 0xFFu;
1290
0
}
1291
1292
// STORE: place the current frame into the lowest free STORE-safe DPB slot
1293
// and force-refresh that bit so the reconstruction lands there regardless
1294
// of the branch's natural refresh choice.
1295
//
1296
// Failure modes (warn + no-op; caller scrubs store_id so packetization
1297
// does NOT stamp the output flag):
1298
//   - duplicate pic_id (already STOREd; app must CLEAR first)
1299
//   - simultaneous-STORE cap reached (popcount of STOREd slots ==
1300
//     scs->static_config.max_managed_refs); matches buffer-pool sizing.
1301
//   - safe slot pool full (see svt_aom_ref_mgmt_storeable_slots_mask)
1302
// Returns the picked slot, or REF_FRAMES on failure.
1303
0
static uint8_t apply_ref_store(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1304
0
    const uint32_t pid = pcs->ref_mgmt.store_id;
1305
0
    if (ref_mgmt_find_slot(ctx, pid) < REF_FRAMES) {
1306
0
        SVT_ERROR("Ref-frame mgmt: STORE pic_id=%u already STOREd; no-op (poc=%lu)\n",
1307
0
                  (unsigned)pid,
1308
0
                  (unsigned long)pcs->picture_number);
1309
0
        return (uint8_t)REF_FRAMES;
1310
0
    }
1311
    // Enforce the simultaneous-hold cap to match buffer-pool sizing.
1312
0
    const uint8_t held = (uint8_t)svt_numbits(ref_mgmt_stored_mask(ctx));
1313
0
    if (held >= pcs->scs->static_config.max_managed_refs) {
1314
0
        SVT_ERROR(
1315
0
            "Ref-frame mgmt: STORE pic_id=%u — already at max_managed_refs cap (%u held); CLEAR something first "
1316
0
            "(poc=%lu)\n",
1317
0
            (unsigned)pid,
1318
0
            (unsigned)pcs->scs->static_config.max_managed_refs,
1319
0
            (unsigned long)pcs->picture_number);
1320
0
        return (uint8_t)REF_FRAMES;
1321
0
    }
1322
0
    const uint8_t storeable_mask = svt_aom_ref_mgmt_storeable_slots_mask(pcs->scs);
1323
0
    const uint8_t free           = (uint8_t)(storeable_mask & ~ref_mgmt_stored_mask(ctx));
1324
0
    if (free == 0) {
1325
0
        SVT_ERROR("Ref-frame mgmt: STORE pic_id=%u — safe slot pool (0x%02x) is full; no-op (poc=%lu)\n",
1326
0
                  (unsigned)pid,
1327
0
                  (unsigned)storeable_mask,
1328
0
                  (unsigned long)pcs->picture_number);
1329
0
        return (uint8_t)REF_FRAMES;
1330
0
    }
1331
0
    const uint8_t slot = (uint8_t)svt_ctz(free);
1332
    // Force-refresh the picked slot so the current frame's reconstruction
1333
    // lands there, independent of what the branch's RPS chose. This is
1334
    // why the safe-pool design works even on TL=1/TL=2 frames whose
1335
    // refresh_frame_mask wouldn't otherwise include slot 6/7.
1336
0
    pcs->av1_ref_signal.refresh_frame_mask |= (uint8_t)(1u << slot);
1337
0
    ctx->pic_id_per_dpb_slot[slot] = pid;
1338
0
    return slot;
1339
0
}
1340
1341
// USE: redirect every AV1 ref position to the STOREd slot holding pic_id
1342
// and clamp ref_list counts to (1,0). Warns + no-ops on unknown pic_id.
1343
// Returns true on success.
1344
//
1345
// (a) splattering the slot index into all 7 ref_dpb_index[] entries
1346
//     guarantees that even if the encoder's mode decision picks
1347
//     LAST2..ALT for some block, it still resolves to the same DPB slot;
1348
// (b) clamping ref_list counts to (1,0) tells the mode decision not to
1349
//     try compound prediction with other refs.
1350
0
static bool apply_ref_use(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1351
0
    const uint32_t pid  = pcs->ref_mgmt.use_id;
1352
0
    const uint8_t  slot = ref_mgmt_find_slot(ctx, pid);
1353
0
    if (slot >= REF_FRAMES) {
1354
0
        SVT_ERROR("Ref-frame mgmt: USE pic_id=%u not found in DPB; no-op (poc=%lu)\n",
1355
0
                  (unsigned)pid,
1356
0
                  (unsigned long)pcs->picture_number);
1357
0
        return false;
1358
0
    }
1359
0
    Av1RpsNode*    rps = &pcs->av1_ref_signal;
1360
0
    const uint64_t poc = ctx->dpb[slot].picture_number;
1361
    /* AV1 ref positions LAST..ALT = INTER_REFS_PER_FRAME (7) entries. */
1362
0
    for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
1363
0
        rps->ref_dpb_index[i] = slot;
1364
0
        rps->ref_poc_array[i] = poc;
1365
0
    }
1366
0
    pcs->ref_list0_count = 1;
1367
0
    pcs->ref_list1_count = 0;
1368
0
    return true;
1369
0
}
1370
1371
// Dispatcher: applies CLEAR/STORE/USE events on the just-computed RPS.
1372
// Called for every frame at the end of av1_generate_rps_info.
1373
//
1374
// Order: CLEAR (free slots) → STORE (allocate a slot for current frame) →
1375
// USE (override refs + recovery-point refresh). CLEAR runs first so a
1376
// same-frame STORE can use a slot just freed.
1377
//
1378
// Refresh guard: the encoder must never overwrite a STOREd slot. We take the
1379
// derived STOREd-slot mask (ref_mgmt_stored_mask), exclude this frame's new
1380
// STORE slot (if any) so the current frame's data lands there, and mask the
1381
// rest out of refresh_frame_mask.
1382
//
1383
// Gates (silently no-op + warning when violated):
1384
//   - AV1 overlay frames: refresh_frame_mask is force-zeroed downstream,
1385
//     so events would corrupt bookkeeping.
1386
//   - Non-base temporal-layer frames: can't be standalone anchors.
1387
//   - Same pic_id used in multiple events on the same frame: invalid.
1388
//
1389
// Always-on refresh guard (even for event-less frames): when any slot is
1390
// STOREd, that slot must never be in refresh_frame_mask. With no STOREs the
1391
// derived mask is 0, making this a no-op and preserving bit-exact legacy.
1392
431
static void apply_ref_mgmt_events(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1393
431
    uint8_t    new_store_slot = (uint8_t)REF_FRAMES;
1394
431
    const bool have_event     = pcs->ref_mgmt.store_id != 0 || pcs->ref_mgmt.clear_id != 0 || pcs->ref_mgmt.use_id != 0;
1395
431
    bool       events_ok      = have_event;
1396
1397
431
    if (have_event) {
1398
0
        if (pcs->is_overlay) {
1399
0
            SVT_ERROR("Ref-frame mgmt: ignoring events on AV1 overlay frame poc=%lu\n",
1400
0
                      (unsigned long)pcs->picture_number);
1401
0
            events_ok = false;
1402
0
        } else {
1403
0
            const bool is_base = pcs->scs->use_flat_ipp || pcs->temporal_layer_index == 0;
1404
0
            if (!is_base) {
1405
0
                SVT_ERROR("Ref-frame mgmt: ignoring events on non-base frame poc=%lu temporal_layer=%u\n",
1406
0
                          (unsigned long)pcs->picture_number,
1407
0
                          (unsigned)pcs->temporal_layer_index);
1408
0
                events_ok = false;
1409
0
            } else {
1410
                // Reject pic_id collisions across same-frame events.
1411
0
                const uint32_t s = pcs->ref_mgmt.store_id;
1412
0
                const uint32_t c = pcs->ref_mgmt.clear_id;
1413
0
                const uint32_t u = pcs->ref_mgmt.use_id;
1414
0
                if ((s != 0 && s == c) || (s != 0 && s == u) || (c != 0 && c == u)) {
1415
0
                    SVT_ERROR(
1416
0
                        "Ref-frame mgmt: duplicate pic_id across STORE/CLEAR/USE on same frame poc=%lu "
1417
0
                        "(store=%u clear=%u use=%u); ignoring all\n",
1418
0
                        (unsigned long)pcs->picture_number,
1419
0
                        (unsigned)s,
1420
0
                        (unsigned)c,
1421
0
                        (unsigned)u);
1422
0
                    events_ok = false;
1423
0
                }
1424
0
            }
1425
0
        }
1426
0
        if (!events_ok) {
1427
0
            pcs->ref_mgmt.store_id = pcs->ref_mgmt.clear_id = pcs->ref_mgmt.use_id = 0;
1428
0
        }
1429
0
    }
1430
1431
    // Phase 1: CLEAR — frees slots before STORE so freed slots can be reused.
1432
431
    if (pcs->ref_mgmt.clear_id != 0) {
1433
0
        apply_ref_clear(pcs, ctx);
1434
        // apply_ref_clear() warns on miss; clear the field so downstream
1435
        // consumers don't see a "phantom" CLEAR after the warning.
1436
0
        pcs->ref_mgmt.clear_id = 0;
1437
0
    }
1438
1439
    // Phase 2: STORE — claim a free slot from refresh_frame_mask.
1440
    // On failure (duplicate id, no candidate slot), the helper warns AND
1441
    // we must scrub store_id here so packetization_process.c does NOT
1442
    // stamp EB_BUFFERFLAG_REF_STORED on the output (the flag is the
1443
    // ground-truth signal to the wrapper; tagging a failed STORE would
1444
    // break its anchor-tracking state machine).
1445
431
    if (pcs->ref_mgmt.store_id != 0) {
1446
0
        new_store_slot = apply_ref_store(pcs, ctx);
1447
0
        if (new_store_slot >= REF_FRAMES) {
1448
0
            pcs->ref_mgmt.store_id = 0;
1449
0
        }
1450
0
    }
1451
1452
    // Phase 3: refresh guard — preserve all previously-STOREd slots from
1453
    // overwrite. The new STORE's slot (if any) is excluded from the preserve
1454
    // set so the current frame's data lands there. Always runs (even without
1455
    // events) so a held slot from an earlier frame is never overwritten.
1456
431
    {
1457
431
        const uint8_t stored_mask   = ref_mgmt_stored_mask(ctx);
1458
431
        const uint8_t preserve_mask = (new_store_slot < REF_FRAMES)
1459
431
            ? (uint8_t)(stored_mask & ~(uint8_t)(1u << new_store_slot))
1460
431
            : stored_mask;
1461
431
        const uint8_t orig          = pcs->av1_ref_signal.refresh_frame_mask;
1462
431
        pcs->av1_ref_signal.refresh_frame_mask &= (uint8_t)~preserve_mask;
1463
        // Diagnostic: detect the degenerate case where every bit the branch
1464
        // wanted to refresh is locked by a STORE. The frame is valid AV1 but
1465
        // its reconstruction is not inserted into the DPB; future inter
1466
        // frames will reference older content. Caller should CLEAR sooner.
1467
431
        if (orig != 0 && pcs->av1_ref_signal.refresh_frame_mask == 0 && !pcs->is_overlay) {
1468
0
            SVT_WARN(
1469
0
                "Ref-frame mgmt: refresh_frame_mask collapsed to 0 at poc=%lu "
1470
0
                "(branch wanted 0x%02x, all bits locked by STOREs 0x%02x); "
1471
0
                "this frame will NOT be inserted into the DPB\n",
1472
0
                (unsigned long)pcs->picture_number,
1473
0
                (unsigned)orig,
1474
0
                (unsigned)preserve_mask);
1475
0
        }
1476
431
    }
1477
1478
    // Phase 4: USE — override refs, then recovery-point refresh.
1479
431
    if (pcs->ref_mgmt.use_id != 0) {
1480
0
        if (apply_ref_use(pcs, ctx)) {
1481
            // Recovery-point refresh: every non-STOREd slot gets the current
1482
            // frame so future frames can only reference STOREd anchors or
1483
            // this recovery point.
1484
0
            uint8_t refresh_mask = (uint8_t)(0xFFu & ~ref_mgmt_stored_mask(ctx));
1485
0
            if (new_store_slot < REF_FRAMES) {
1486
                // The just-STOREd slot must also receive current frame data.
1487
0
                refresh_mask |= (uint8_t)(1u << new_store_slot);
1488
0
            }
1489
0
            pcs->av1_ref_signal.refresh_frame_mask = refresh_mask;
1490
0
        }
1491
0
    }
1492
431
}
1493
1494
431
static void set_key_frame_rps(PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
1495
431
    FrameHeader* frm_hdr = &pcs->frm_hdr;
1496
431
    pd_ctx->lay0_toggle  = 0;
1497
431
    pd_ctx->lay1_toggle  = 0;
1498
    // KF refreshes all 8 DPB slots, so all previously-STOREd refs are invalidated.
1499
431
    ref_mgmt_reset_state(pd_ctx);
1500
1501
431
    frm_hdr->show_frame    = true;
1502
431
    pcs->has_show_existing = false;
1503
431
    return;
1504
431
}
1505
1506
// returns the distance to the nearest S-Frame, and dist_to_next_s will be filled if current is an S-Frame
1507
// dist_to_next_s is for there being more than one S-Frame inserted within one miniGOP size
1508
0
static int32_t get_dist_to_s(SvtAv1SFramePositions const* sframe_posi, uint64_t picture_num, int32_t* dist_to_next_s) {
1509
0
    *dist_to_next_s = -1;
1510
0
    for (uint32_t i = 0; i < sframe_posi->sframe_num; i++) {
1511
0
        if (sframe_posi->sframe_posis[i] >= picture_num) {
1512
0
            if (sframe_posi->sframe_posis[i] == picture_num) {
1513
0
                *dist_to_next_s = (i < sframe_posi->sframe_num - 1)
1514
0
                    ? (int32_t)(sframe_posi->sframe_posis[i + 1] - picture_num)
1515
0
                    : -1;
1516
0
            }
1517
0
            return (int32_t)(sframe_posi->sframe_posis[i] - picture_num);
1518
0
        }
1519
0
    }
1520
0
    return -1; // all s-frame spots are expired
1521
0
}
1522
1523
0
static uint8_t get_sframe_qp(SvtAv1SFramePositions const* sframe_posi, uint64_t picture_num) {
1524
0
    if (sframe_posi->sframe_qps == NULL) {
1525
0
        return 0;
1526
0
    }
1527
0
    if (sframe_posi->sframe_posis == NULL) {
1528
        // always return first QP if not use flexible S-Frame position list
1529
0
        return sframe_posi->sframe_qps[0];
1530
0
    }
1531
0
    for (uint32_t i = 0; i < sframe_posi->sframe_num; i++) {
1532
0
        if (sframe_posi->sframe_posis[i] == picture_num) {
1533
0
            return sframe_posi->sframe_qps[i];
1534
0
        }
1535
0
    }
1536
0
    return 0; // not find the picture
1537
0
}
1538
1539
0
static int8_t get_sframe_qp_offset(SvtAv1SFramePositions const* sframe_posi, uint64_t picture_num) {
1540
0
    if (sframe_posi->sframe_qp_offsets == NULL) {
1541
0
        return 0;
1542
0
    }
1543
0
    if (sframe_posi->sframe_posis == NULL) {
1544
        // always return first QP offset if not use flexible S-Frame position list
1545
0
        return sframe_posi->sframe_qp_offsets[0];
1546
0
    }
1547
0
    for (uint32_t i = 0; i < sframe_posi->sframe_num; i++) {
1548
0
        if (sframe_posi->sframe_posis[i] == picture_num) {
1549
0
            return sframe_posi->sframe_qp_offsets[i];
1550
0
        }
1551
0
    }
1552
0
    return 0; // not find the picture
1553
0
}
1554
1555
0
static void setup_sframe_qp(PictureParentControlSet* ppcs) {
1556
0
    SequenceControlSet* scs       = ppcs->scs;
1557
0
    uint64_t            pic_num   = scs->static_config.sframe_mode == SFRAME_DEC_POSI_BASE ? ppcs->decode_order
1558
0
                                                                                           : ppcs->picture_number;
1559
0
    uint8_t             sframe_qp = scs->static_config.sframe_qp > 0 ? scs->static_config.sframe_qp
1560
0
                                                                     : get_sframe_qp(&scs->static_config.sframe_posi, pic_num);
1561
0
    if (sframe_qp > 0) {
1562
0
        ppcs->picture_qp = (uint8_t)CLIP3(
1563
0
            (int8_t)scs->static_config.min_qp_allowed, (int8_t)scs->static_config.max_qp_allowed, (int8_t)sframe_qp);
1564
0
        ppcs->qp_on_the_fly = true;
1565
0
    }
1566
0
    int8_t sframe_qp_offset = scs->static_config.sframe_qp_offset != 0
1567
0
        ? scs->static_config.sframe_qp_offset
1568
0
        : get_sframe_qp_offset(&scs->static_config.sframe_posi, pic_num);
1569
0
    if (sframe_qp_offset != 0) {
1570
0
        ppcs->sframe_qp_offset = sframe_qp_offset;
1571
0
    }
1572
0
}
1573
1574
// Adjust the S-frame position offset for S-frame decode order mode.
1575
// In low-delay mode, the decode order is the same as the display order,
1576
// so the offset adjustment is unnecessary.
1577
0
static int32_t sframe_position_offset(SequenceControlSet* scs) {
1578
0
    return (scs->static_config.sframe_mode == SFRAME_DEC_POSI_BASE &&
1579
0
            scs->static_config.pred_structure == RANDOM_ACCESS)
1580
0
        ? 1
1581
0
        : 0;
1582
0
}
1583
1584
// Decide whether to make an inter frame into an S-Frame
1585
0
static void set_sframe_type(PictureParentControlSet* ppcs, EncodeContext* enc_ctx, PictureDecisionContext* pd_ctx) {
1586
0
    FrameHeader*       frm_hdr     = &ppcs->frm_hdr;
1587
0
    const int          sframe_dist = enc_ctx->sf_cfg.sframe_dist;
1588
0
    const EbSFrameMode sframe_mode = enc_ctx->sf_cfg.sframe_mode;
1589
1590
0
    const int      is_arf           = ppcs->temporal_layer_index == 0 ? true : false;
1591
0
    const uint64_t frames_since_key = ppcs->picture_number - pd_ctx->key_poc;
1592
0
    if (sframe_mode == SFRAME_STRICT_BASE) {
1593
        // SFRAME_STRICT_ARF: insert sframe if it matches altref frame.
1594
0
        if (is_arf && (frames_since_key % sframe_dist) == 0) {
1595
0
            frm_hdr->frame_type = S_FRAME;
1596
0
        }
1597
0
    } else if (sframe_mode == SFRAME_NEAREST_BASE) {
1598
        // SFRAME_NEAREST_ARF: if sframe will be inserted at the next available altref frame
1599
0
        if (ppcs->scs->static_config.pred_structure == RANDOM_ACCESS) {
1600
            // frames in PD are in decode order, when ARF position is in this miniGop range,
1601
            // the ARF should be the next S-Frame
1602
0
            if (is_arf && (frames_since_key % sframe_dist) < pd_ctx->mg_size) {
1603
0
                frm_hdr->frame_type = S_FRAME;
1604
0
            }
1605
0
        } else {
1606
0
            if ((frames_since_key % sframe_dist) == 0) {
1607
0
                pd_ctx->sframe_due = 1;
1608
0
            }
1609
0
            if (pd_ctx->sframe_due && is_arf) {
1610
0
                frm_hdr->frame_type = S_FRAME;
1611
0
                pd_ctx->sframe_due  = 0;
1612
0
            }
1613
0
        }
1614
0
    } else {
1615
        // SFRAME_FLEXIBLE_ARF: if the considered frame is not an altref frame, modify the mini-GOP structure to promote it to an altref frame
1616
0
        if (is_arf) {
1617
            // SFRAME_DEC_POSI_BASE: adjust the frame before insert position to be ARF, and set the next ARF as S-Frame
1618
0
            int32_t sframe_offset = sframe_position_offset(ppcs->scs);
1619
            // set this ARF to S-Frame if it is decided by previous processing
1620
0
            if (pd_ctx->next_arf_is_s) {
1621
0
                frm_hdr->frame_type   = S_FRAME;
1622
0
                pd_ctx->next_arf_is_s = false; // reset flag of next ARF setting to S-Frame
1623
0
            }
1624
1625
0
            uint32_t next_mg_size = 1 << pd_ctx->sframe_hier_lvls;
1626
0
            if (ppcs->scs->static_config.sframe_posi.sframe_posis) {
1627
                // When the user specifies the positions of S-Frames, the encoder retrieves the distances to the next two S-Frames
1628
                // to assist in deciding the mini-GOP structure.
1629
0
                int32_t dist_to_next_s = 0;
1630
0
                int32_t dist_to_s      = get_dist_to_s(
1631
0
                    &ppcs->scs->static_config.sframe_posi, ppcs->picture_number + sframe_offset, &dist_to_next_s);
1632
0
                if (dist_to_s == 0) {
1633
0
                    if (sframe_offset) {
1634
0
                        pd_ctx->next_arf_is_s = true; // delay setting SFRAME
1635
0
                    } else {
1636
0
                        frm_hdr->frame_type = S_FRAME;
1637
0
                    }
1638
1639
                    // After inserting a new S-Frame, reset sframe_hier_lvls and use it for the next mini-GOP evaluation.
1640
0
                    pd_ctx->sframe_hier_lvls = ppcs->scs->static_config.hierarchical_levels;
1641
0
                    next_mg_size             = 1 << pd_ctx->sframe_hier_lvls;
1642
0
                    dist_to_s                = dist_to_next_s;
1643
0
                }
1644
0
                if (dist_to_s > 0 && dist_to_s < (int32_t)next_mg_size) {
1645
0
                    for (int32_t lvl = 0; lvl < pd_ctx->sframe_hier_lvls; lvl++) {
1646
0
                        if (dist_to_s < (1 << (lvl + 1))) {
1647
0
                            pd_ctx->sframe_hier_lvls = lvl;
1648
0
                            break;
1649
0
                        }
1650
0
                    }
1651
0
                    assert(pd_ctx->sframe_hier_lvls >= 0 &&
1652
0
                           pd_ctx->sframe_hier_lvls <= (int32_t)ppcs->scs->static_config.hierarchical_levels);
1653
0
                }
1654
0
            } else {
1655
0
                if (((frames_since_key + sframe_offset) % sframe_dist) == 0) {
1656
0
                    if (sframe_offset) {
1657
0
                        pd_ctx->next_arf_is_s = true; // delay setting SFRAME
1658
0
                    } else {
1659
0
                        frm_hdr->frame_type = S_FRAME;
1660
0
                    }
1661
1662
                    // After inserting a new S-Frame, reset sframe_hier_lvls and use it for the next mini-GOP evaluation.
1663
0
                    pd_ctx->sframe_hier_lvls = ppcs->scs->static_config.hierarchical_levels;
1664
0
                    next_mg_size             = 1 << pd_ctx->sframe_hier_lvls;
1665
0
                }
1666
                // check the next key frame position for if the distance of next sframe being available
1667
0
                if (sframe_mode != SFRAME_DEC_POSI_BASE || ppcs->scs->static_config.intra_period_length <= 0 ||
1668
0
                    (frames_since_key + next_mg_size <= (uint64_t)ppcs->scs->static_config.intra_period_length)) {
1669
                    // modify hierarchical level of next miniGOP
1670
0
                    uint32_t gap_arf = (frames_since_key + sframe_offset + next_mg_size) % sframe_dist;
1671
0
                    if (gap_arf != 0 && gap_arf < next_mg_size) {
1672
                        // Downgrade the next mini-GOP if it contains the upcoming S-Frame.
1673
0
                        int32_t arf_dist = next_mg_size - gap_arf;
1674
0
                        for (int32_t lvl = 0; lvl < pd_ctx->sframe_hier_lvls; lvl++) {
1675
0
                            if (arf_dist < (1 << (lvl + 1))) {
1676
0
                                pd_ctx->sframe_hier_lvls = lvl;
1677
0
                                break;
1678
0
                            }
1679
0
                        }
1680
0
                        assert(pd_ctx->sframe_hier_lvls >= 0 &&
1681
0
                               pd_ctx->sframe_hier_lvls <= (int32_t)ppcs->scs->static_config.hierarchical_levels);
1682
0
                    }
1683
0
                }
1684
0
            }
1685
0
            pd_ctx->sframe_last_arf = frames_since_key;
1686
0
        }
1687
0
    }
1688
1689
0
    if (frm_hdr->frame_type == S_FRAME) {
1690
0
        setup_sframe_qp(ppcs);
1691
0
    }
1692
1693
0
    ppcs->sframe_ref_pruned = false;
1694
#if DEBUG_SFRAME
1695
    if (frm_hdr->frame_type == S_FRAME) {
1696
        fprintf(stderr, "\nFrame %d - set sframe\n", (int)ppcs->picture_number);
1697
    }
1698
#endif
1699
0
    return;
1700
0
}
1701
1702
// Determine the size of the first mini-GOP after inserting a key frame
1703
0
static void decide_sframe_mg(PictureParentControlSet* ppcs, EncodeContext* enc_ctx, PictureDecisionContext* pd_ctx) {
1704
0
    SequenceControlSet* scs           = ppcs->scs;
1705
0
    int32_t             sframe_dist   = enc_ctx->sf_cfg.sframe_dist;
1706
0
    int32_t             sframe_offset = sframe_position_offset(scs);
1707
    // reset next_arf_sframe when key frame inserted
1708
0
    pd_ctx->next_arf_is_s = false;
1709
    // reset sframe_hier_lvls when key frame inserted
1710
0
    pd_ctx->sframe_hier_lvls = scs->static_config.hierarchical_levels;
1711
1712
0
    int32_t next_mg_size = 1 << pd_ctx->sframe_hier_lvls;
1713
0
    if (scs->static_config.sframe_posi.sframe_posis) {
1714
0
        int32_t dist_to_next_s = 0;
1715
0
        int32_t dist_to_s      = get_dist_to_s(
1716
0
            &ppcs->scs->static_config.sframe_posi, ppcs->picture_number + sframe_offset, &dist_to_next_s);
1717
0
        if (dist_to_s > 0) {
1718
0
            sframe_dist = (uint32_t)dist_to_s;
1719
0
        } else if (dist_to_s == 0 && dist_to_next_s > 0) {
1720
0
            sframe_dist = (uint32_t)dist_to_next_s;
1721
0
        } else {
1722
0
            return;
1723
0
        }
1724
0
    }
1725
0
    if (sframe_dist < next_mg_size) {
1726
        // If the S-Frame falls within the next mini-GOP, downgrade the next mini-GOP.
1727
0
        for (int32_t lvl = 0; lvl < pd_ctx->sframe_hier_lvls; lvl++) {
1728
0
            if (sframe_dist < (1 << (lvl + 1))) {
1729
0
                pd_ctx->sframe_hier_lvls = lvl;
1730
0
                break;
1731
0
            }
1732
0
        }
1733
0
        assert(pd_ctx->sframe_hier_lvls >= 0 &&
1734
0
               pd_ctx->sframe_hier_lvls <= (int32_t)scs->static_config.hierarchical_levels);
1735
0
    }
1736
0
    return;
1737
0
}
1738
1739
// Update RPS info for S-Frame
1740
0
static void set_sframe_rps(PictureParentControlSet* ppcs, EncodeContext* enc_ctx, PictureDecisionContext* pd_ctx) {
1741
0
    ppcs->frm_hdr.error_resilient_mode      = 1;
1742
0
    ppcs->av1_ref_signal.refresh_frame_mask = 0xFF;
1743
1744
0
    pd_ctx->lay0_toggle = 0;
1745
0
    pd_ctx->lay1_toggle = 0;
1746
    // Bookmark latest switch frame poc to prevent following frames referencing frames before the switch frame
1747
0
    pd_ctx->sframe_poc = ppcs->picture_number;
1748
    // Reset pred_struct_position
1749
0
    enc_ctx->elapsed_non_cra_count = 0;
1750
0
    return;
1751
0
}
1752
1753
/*************************************************
1754
* AV1 Reference Picture Signalling:
1755
* Stateless derivation of RPS info to be stored in
1756
* Picture Header
1757
*
1758
* This function uses the picture index from the just
1759
* collected miniGop to derive the RPS(refIndexes+refresh)
1760
* the miniGop is always 4L but could be complete (8 pictures)
1761
or non-complete (less than 8 pictures).
1762
* We get to this function if the picture is:
1763
* 1) first Key frame
1764
* 2) part of a complete RA MiniGop where the last frame could be a regular I for open GOP
1765
* 3) part of complete LDP MiniGop where the last frame could be Key frame for closed GOP
1766
* 4) part of non-complete LDP MiniGop where the last frame is a regularI+SceneChange.
1767
This miniGOP has P frames with predStruct=LDP, and the last frame=I with pred struct=RA.
1768
* 5) part of non-complete LDP MiniGop at the end of the stream.This miniGOP has P frames with
1769
predStruct=LDP, and the last frame=I with pred struct=RA.
1770
*
1771
*Note: the  SceneChange I has pred_type = RANDOM_ACCESS. if SChange is aligned on the miniGop,
1772
we do not break the GOP.
1773
*************************************************/
1774
/*
1775
 * Return true if a picture is used as a reference, false otherwise.
1776
 *
1777
 * Whether a picture is used as a reference depends on its position in the hierarchical structure, and on the referencing_scheme used.
1778
 * referencing_scheme = 0 means that no top-layer pictures will be used as a reference
1779
 * referencing_scheme = 1 means that all top-layer pictures may be used as a reference
1780
 * referencing_scheme = 2 means that some top-layer pictures will be used as a reference (depending on their position in the MG)
1781
 *
1782
 * Interal pictures (non-top-layer pictures) are always used as a reference.  Overlay pictures are never used as a reference.
1783
 */
1784
bool svt_aom_is_pic_used_as_ref(uint32_t hierarchical_levels, uint32_t temporal_layer, uint32_t picture_index,
1785
862
                                uint32_t referencing_scheme, bool is_overlay) {
1786
862
    if (is_overlay) {
1787
0
        return false;
1788
0
    }
1789
1790
    // Frames below top layer are always used as ref
1791
862
    if (temporal_layer < hierarchical_levels) {
1792
0
        return true;
1793
0
    }
1794
1795
862
    switch (hierarchical_levels) {
1796
0
#if OPT_USE_HL0_FLAT
1797
0
    case 0:
1798
0
        return true;
1799
0
    case 1:
1800
0
        return referencing_scheme == 0 ? false : true;
1801
#else
1802
    case 0:
1803
    case 1:
1804
        return true;
1805
#endif
1806
862
    case 2:
1807
862
        return referencing_scheme == 0 ? false : referencing_scheme == 1 ? true : (picture_index == 0);
1808
0
    case 3:
1809
0
        return referencing_scheme == 0 ? false : referencing_scheme == 1 ? true : (picture_index == 0);
1810
0
    case 4:
1811
0
        return referencing_scheme == 0 ? false
1812
0
            : referencing_scheme == 1  ? true
1813
0
                                       : (picture_index == 0 || picture_index == 8);
1814
0
    case 5:
1815
0
        return false;
1816
0
    default:
1817
0
        assert(0 && "Invalid hierarchical structure\n");
1818
0
        break;
1819
862
    }
1820
1821
0
    return true;
1822
862
}
1823
1824
431
static void set_ref_list_counts(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1825
431
    if (pcs->slice_type == I_SLICE) {
1826
431
        pcs->ref_list0_count = 0;
1827
431
        pcs->ref_list1_count = 0;
1828
431
        return;
1829
431
    }
1830
1831
0
    Av1RpsNode*           av1_rps   = &pcs->av1_ref_signal;
1832
0
    const MrpCtrls* const mrp_ctrls = &pcs->scs->mrp_ctrls;
1833
0
    const bool            is_base   = pcs->temporal_layer_index == 0;
1834
#if !TUNE_SIMPLIFY_SETTINGS
1835
    const bool is_sc = pcs->sc_class1;
1836
#endif
1837
1838
    // Get list0 count
1839
0
    uint8_t list0_count   = 1;
1840
0
    bool    breakout_flag = false;
1841
    // When have duplicate refs in same list or get invalid ref, cap the count
1842
0
    for (REF_FRAME_MINUS1 i = LAST2; i <= GOLD; i++) {
1843
0
        if (breakout_flag) {
1844
0
            break;
1845
0
        }
1846
0
        for (REF_FRAME_MINUS1 j = LAST; j < i; j++) {
1847
            /*
1848
            TODO: [PW] Add a check so that if we try accessing a top-layer pic when top-layer pics
1849
            are not allowed (e.g. ref scheme 0) then we breakout.  A check to ensure that the picture
1850
            being referenced is actually the picture intended to be referenced would also be useful
1851
            for debugging.
1852
1853
            For example, if top-layer refs are disallowed and prev. MG is 4L and current MG is 5L
1854
            then pics may try to access layer 3 pics from previous MG.  However, those pics won't
1855
            be from the previous MG as expected, since they would not have been added to the DPB.
1856
            Note that the reference in the DPB will be valid, but the actual picture being referenced
1857
            will be different than expected.
1858
            */
1859
0
            if (av1_rps->ref_poc_array[i] == av1_rps->ref_poc_array[j]) {
1860
0
                breakout_flag = true;
1861
0
                break;
1862
0
            }
1863
0
        }
1864
        // if no matching reference were found, increase the count
1865
0
        if (!breakout_flag) {
1866
0
            list0_count++;
1867
0
        }
1868
0
    }
1869
0
#if TUNE_SIMPLIFY_SETTINGS
1870
0
    pcs->ref_list0_count = MIN(list0_count,
1871
0
                               (is_base ? mrp_ctrls->base_ref_list0_count : mrp_ctrls->non_base_ref_list0_count));
1872
#else
1873
    pcs->ref_list0_count = MIN(
1874
        list0_count,
1875
        is_sc ? (is_base ? mrp_ctrls->sc_base_ref_list0_count : mrp_ctrls->sc_non_base_ref_list0_count)
1876
              : (is_base ? mrp_ctrls->base_ref_list0_count : mrp_ctrls->non_base_ref_list0_count));
1877
#endif
1878
0
    assert(pcs->ref_list0_count);
1879
1880
0
    if (svt_aom_is_incomp_mg_frame(pcs) || pcs->is_overlay) {
1881
0
        pcs->ref_list1_count = 0;
1882
0
        return;
1883
0
    }
1884
1885
    // Get list1 count
1886
0
    uint8_t list1_count = 0;
1887
0
    breakout_flag       = false;
1888
    // When have duplicate refs in both lists or get invalid ref, cap the count
1889
0
    for (REF_FRAME_MINUS1 i = BWD; i <= ALT; i++) {
1890
0
        if (breakout_flag) {
1891
0
            break;
1892
0
        }
1893
        // BWD and LAST are allowed to have matching references, as in base layer
1894
0
        for (REF_FRAME_MINUS1 j = (i == BWD) ? LAST2 : LAST; j < i; j++) {
1895
0
            if (j <= GOLD && j + 1 > pcs->ref_list0_count) {
1896
0
                continue;
1897
0
            }
1898
            // in S-Frame of RA mode, since the ref_list0 will be pruned in set_all_ref_frame_type(),
1899
            // the rest frames in S-Frame miniGop should not remove the duplicated ref_list1, which
1900
            // causes no ref frames in ref_list1, skip the following check only for S-Frame miniGOP
1901
0
            if (pcs->scs->static_config.pred_structure == RANDOM_ACCESS && pcs->picture_number < ctx->sframe_poc &&
1902
0
                j <= GOLD && av1_rps->ref_poc_array[j] == ctx->sframe_poc) {
1903
0
                continue;
1904
0
            }
1905
            /*
1906
            TODO: [PW] Add a check so that if we try accessing a top-layer pic when top-layer pics
1907
            are not allowed (e.g. ref scheme 0) then we breakout.  A check to ensure that the picture
1908
            being referenced is actually the picture intended to be referenced would also be useful
1909
            for debugging.
1910
1911
            For example, if top-layer refs are disallowed and prev. MG is 4L and current MG is 5L
1912
            then pics may try to access layer 3 pics from previous MG.  However, those pics won't
1913
            be from the previous MG as expected, since they would not have been added to the DPB.
1914
            Note that the reference in the DPB will be valid, but the actual picture being referenced
1915
            will be different than expected.
1916
            */
1917
0
            if (av1_rps->ref_poc_array[i] == av1_rps->ref_poc_array[j]) {
1918
0
                breakout_flag = 1;
1919
0
                break;
1920
0
            }
1921
0
        }
1922
        // if no matching reference were found, increase the count
1923
0
        if (!breakout_flag) {
1924
0
            list1_count++;
1925
0
        }
1926
0
    }
1927
0
#if TUNE_SIMPLIFY_SETTINGS
1928
0
    pcs->ref_list1_count = MIN(list1_count,
1929
0
                               (is_base ? mrp_ctrls->base_ref_list1_count : mrp_ctrls->non_base_ref_list1_count));
1930
#else
1931
    pcs->ref_list1_count = MIN(
1932
        list1_count,
1933
        is_sc ? (is_base ? mrp_ctrls->sc_base_ref_list1_count : mrp_ctrls->sc_non_base_ref_list1_count)
1934
              : (is_base ? mrp_ctrls->base_ref_list1_count : mrp_ctrls->non_base_ref_list1_count));
1935
#endif
1936
#if !OPT_USE_HL0_FLAT
1937
    // Old assert fails when M13 uses non-zero mrp
1938
    assert(!(pcs->ref_list1_count == 0 && pcs->scs->static_config.pred_structure == RANDOM_ACCESS));
1939
#endif
1940
0
}
1941
1942
0
static INLINE void update_ref_poc_array(uint8_t* ref_dpb_idx, uint64_t* ref_poc_array, DpbEntry* dpb) {
1943
0
    ref_poc_array[LAST]  = dpb[ref_dpb_idx[LAST]].picture_number;
1944
0
    ref_poc_array[LAST2] = dpb[ref_dpb_idx[LAST2]].picture_number;
1945
0
    ref_poc_array[LAST3] = dpb[ref_dpb_idx[LAST3]].picture_number;
1946
0
    ref_poc_array[GOLD]  = dpb[ref_dpb_idx[GOLD]].picture_number;
1947
0
    ref_poc_array[BWD]   = dpb[ref_dpb_idx[BWD]].picture_number;
1948
0
    ref_poc_array[ALT2]  = dpb[ref_dpb_idx[ALT2]].picture_number;
1949
0
    ref_poc_array[ALT]   = dpb[ref_dpb_idx[ALT]].picture_number;
1950
0
}
1951
1952
static void av1_generate_rps_info(PictureParentControlSet* pcs, EncodeContext* enc_ctx, PictureDecisionContext* ctx,
1953
431
                                  uint32_t pic_idx, uint32_t mg_idx) {
1954
431
    Av1RpsNode*         av1_rps             = &pcs->av1_ref_signal;
1955
431
    FrameHeader*        frm_hdr             = &pcs->frm_hdr;
1956
431
    SequenceControlSet* scs                 = pcs->scs;
1957
431
    const uint8_t       hierarchical_levels = pcs->hierarchical_levels;
1958
431
    const uint8_t       temporal_layer      = pcs->temporal_layer_index;
1959
431
    const uint8_t       more_5L_refs        = pcs->scs->mrp_ctrls.more_5L_refs;
1960
431
    if (scs->allintra) {
1961
431
        pcs->is_ref = false;
1962
431
    } else {
1963
0
        pcs->is_ref = scs->use_flat_ipp
1964
0
            ? true
1965
0
            : svt_aom_is_pic_used_as_ref(
1966
0
                  hierarchical_levels, temporal_layer, pic_idx, scs->mrp_ctrls.referencing_scheme, pcs->is_overlay);
1967
0
    }
1968
1969
    //Set frame type
1970
431
    if (pcs->slice_type == I_SLICE) {
1971
431
        frm_hdr->frame_type                    = pcs->idr_flag ? KEY_FRAME : INTRA_ONLY_FRAME;
1972
431
        pcs->av1_ref_signal.refresh_frame_mask = 0xFF;
1973
#if DEBUG_SFRAME
1974
        fprintf(stderr, "\nFrame %d - key frame\n", (int)pcs->picture_number);
1975
#endif
1976
431
        if (frm_hdr->frame_type == KEY_FRAME) {
1977
431
            set_key_frame_rps(pcs, ctx);
1978
431
            set_ref_list_counts(pcs, ctx);
1979
431
            if (IS_SFRAME_FLEXIBLE_INSERT(scs->static_config.sframe_mode)) {
1980
0
                decide_sframe_mg(pcs, enc_ctx, ctx);
1981
0
            }
1982
            // KF refreshes all 8 slots; set_key_frame_rps already reset the
1983
            // managed-ref state. If the app STOREd this KF, record (slot, pic_id) now.
1984
431
            apply_ref_mgmt_events(pcs, ctx);
1985
431
            return;
1986
431
        }
1987
431
    } else {
1988
0
        frm_hdr->frame_type = INTER_FRAME;
1989
1990
        // test s-frame on base layer inter frames
1991
0
        if (enc_ctx->sf_cfg.sframe_dist > 0 || scs->static_config.sframe_posi.sframe_posis) {
1992
0
            set_sframe_type(pcs, enc_ctx, ctx);
1993
0
        }
1994
0
    }
1995
1996
0
    uint8_t*  ref_dpb_index = av1_rps->ref_dpb_index;
1997
0
    uint64_t* ref_poc_array = av1_rps->ref_poc_array;
1998
1999
0
    if (scs->use_flat_ipp) {
2000
0
        const uint8_t max_refs = scs->mrp_ctrls.flat_max_refs;
2001
0
        assert(max_refs <= 4);
2002
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2003
2004
        // Use up to 4 previous frames as refs
2005
0
        const uint8_t pic0_idx = QUEUE_GET_PREVIOUS_SPOT(lay0_toggle, max_refs); // newest pic
2006
0
        const uint8_t pic1_idx = QUEUE_GET_PREVIOUS_SPOT(pic0_idx, max_refs);
2007
0
        const uint8_t pic2_idx = QUEUE_GET_PREVIOUS_SPOT(pic1_idx, max_refs);
2008
0
        const uint8_t pic3_idx = QUEUE_GET_PREVIOUS_SPOT(pic2_idx, max_refs);
2009
2010
        // Only use the previous frames as ref
2011
0
        ref_dpb_index[LAST]  = pic0_idx;
2012
0
        ref_dpb_index[LAST2] = pic1_idx;
2013
0
        ref_dpb_index[LAST3] = pic2_idx;
2014
0
        ref_dpb_index[GOLD]  = pic3_idx;
2015
2016
0
        ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2017
0
        ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2018
0
        ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2019
2020
        // Only max_refs DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2021
0
        av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xf0);
2022
0
        for (int i = 3; i >= max_refs; i--) {
2023
0
            av1_rps->refresh_frame_mask |= 1 << i;
2024
0
        }
2025
        //Layer0 toggle 0->1->2->3
2026
0
        ctx->lay0_toggle = circ_inc(max_refs, 1, ctx->lay0_toggle);
2027
2028
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2029
0
        set_ref_list_counts(pcs, ctx);
2030
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2031
0
        set_frame_display_params(pcs, ctx, mg_idx);
2032
0
    } else if (scs->static_config.pred_structure == LOW_DELAY &&
2033
0
               scs->static_config.rate_control_mode == SVT_AV1_RC_MODE_CQP_OR_CRF) {
2034
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2035
0
        uint8_t lay1_toggle = ctx->lay1_toggle; // lay1 toggle is for all non-base pics in LD
2036
2037
        // For LD, the prediction structure is generally the previous 3 non-base frames + the previous 3 base frames + 1 long-term ref
2038
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
2039
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
2040
0
        const uint8_t base2_idx = scs->mrp_ctrls.ld_reduce_ref_buffs ? 0
2041
0
            : lay0_toggle == 0                                       ? 2
2042
0
            : lay0_toggle == 1                                       ? 0
2043
0
                                                                     : 1; //the newest L0 picture in the DPB
2044
2045
0
        const uint8_t  lay1_offset   = scs->mrp_ctrls.ld_reduce_ref_buffs == 0 ? LAY1_OFF : 1;
2046
0
        const uint8_t  lay1_0_idx    = lay1_toggle == 0 ? lay1_offset + 0
2047
0
                : lay1_toggle == 1                      ? lay1_offset + 1
2048
0
                                                        : lay1_offset + 2; //the oldest L1/2 picture in the DPB
2049
0
        const uint8_t  lay1_1_idx    = lay1_toggle == 0 ? lay1_offset + 1
2050
0
                : lay1_toggle == 1                      ? lay1_offset + 2
2051
0
                                                        : lay1_offset + 0; //the middle L1/2 picture in the DPB
2052
0
        const uint8_t  lay1_2_idx    = scs->mrp_ctrls.ld_reduce_ref_buffs == 2 ? 1
2053
0
                : lay1_toggle == 0                                             ? lay1_offset + 2
2054
0
                : lay1_toggle == 1                                             ? lay1_offset + 0
2055
0
                                   : lay1_offset + 1; //the newest L1/2 picture in the DPB
2056
0
        const uint8_t  long_base_idx = 7;
2057
0
        const uint16_t long_base_pic = 128;
2058
2059
0
        assert(!pcs->is_overlay && "overlays not supported in LD");
2060
2061
0
        const MrpCtrls* const mrp_ctrls = &pcs->scs->mrp_ctrls;
2062
0
        const bool            is_base   = temporal_layer == 0;
2063
0
#if TUNE_SIMPLIFY_SETTINGS
2064
0
        uint8_t ref_list1_count = is_base ? mrp_ctrls->base_ref_list1_count : mrp_ctrls->non_base_ref_list1_count;
2065
#else
2066
        const bool is_sc           = pcs->sc_class1;
2067
        uint8_t    ref_list1_count = is_sc
2068
               ? (is_base ? mrp_ctrls->sc_base_ref_list1_count : mrp_ctrls->sc_non_base_ref_list1_count)
2069
               : (is_base ? mrp_ctrls->base_ref_list1_count : mrp_ctrls->non_base_ref_list1_count);
2070
#endif
2071
2072
0
        const uint8_t lay1_pic_idx = (hierarchical_levels == 0) ? 0 : ((1 << (hierarchical_levels - 1)) - 1);
2073
        // When list1 is not used, the pics after the layer 1 pic should use the layer 1 pic as ref instead of previous base
2074
0
        ref_dpb_index[LAST]  = (pic_idx > lay1_pic_idx) && !is_base && ref_list1_count == 0 ? lay1_2_idx : base2_idx;
2075
0
        ref_dpb_index[LAST2] = lay1_1_idx;
2076
0
        ref_dpb_index[LAST3] = long_base_idx;
2077
0
        ref_dpb_index[GOLD]  = base0_idx;
2078
2079
0
        ref_dpb_index[BWD]  = lay1_2_idx;
2080
0
        ref_dpb_index[ALT2] = lay1_0_idx;
2081
0
        ref_dpb_index[ALT]  = base1_idx;
2082
2083
0
        if (temporal_layer == 0) {
2084
0
            if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2085
                // Only 2 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2086
0
                av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xfc);
2087
0
            } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2088
                // Only 4 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2089
0
                av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xf0);
2090
0
            } else {
2091
0
                av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2092
                //Layer0 toggle 0->1->2
2093
0
                ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2094
0
            }
2095
0
        } else {
2096
0
            if (pcs->is_ref) {
2097
0
                if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2098
0
                    av1_rps->refresh_frame_mask = 1 << 1;
2099
0
                } else {
2100
0
                    av1_rps->refresh_frame_mask = 1 << (lay1_offset + ctx->lay1_toggle);
2101
                    //Layer1 toggle 0->1->2
2102
0
                    ctx->lay1_toggle = circ_inc(3, 1, ctx->lay1_toggle);
2103
0
                }
2104
0
            } else {
2105
0
                av1_rps->refresh_frame_mask = 0;
2106
0
            }
2107
0
        }
2108
2109
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2110
2111
0
        set_ref_list_counts(pcs, ctx);
2112
        // to make sure the long base reference is in base layer
2113
0
        if (/*scs->static_config.pred_structure == LOW_DELAY &&*/ (pcs->picture_number - ctx->last_long_base_pic) >=
2114
0
                long_base_pic &&
2115
0
            pcs->temporal_layer_index == 0) {
2116
0
            av1_rps->refresh_frame_mask |= (1 << long_base_idx);
2117
0
            ctx->last_long_base_pic = pcs->picture_number;
2118
0
        }
2119
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2120
0
        set_frame_display_params(pcs, ctx, mg_idx);
2121
        //frm_hdr->show_frame = true;
2122
        //pcs->has_show_existing = false;
2123
0
    } else if (scs->static_config.pred_structure == LOW_DELAY &&
2124
0
               scs->static_config.rate_control_mode == SVT_AV1_RC_MODE_CBR) {
2125
0
        assert(!pcs->is_overlay && "overlays not supported in LD");
2126
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2127
0
        uint8_t lay1_toggle = ctx->lay1_toggle;
2128
2129
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
2130
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
2131
0
        const uint8_t base2_idx = scs->mrp_ctrls.ld_reduce_ref_buffs == 2 ? 0
2132
0
            : lay0_toggle == 0                                            ? 2
2133
0
            : lay0_toggle == 1                                            ? 0
2134
0
                                                                          : 1; //the newest L0 picture in the DPB
2135
2136
0
        const uint8_t  lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
2137
0
        const uint8_t  lay1_1_idx = scs->mrp_ctrls.ld_reduce_ref_buffs == 2 ? 1
2138
0
             : scs->mrp_ctrls.ld_reduce_ref_buffs == 1                      ? LAY1_OFF
2139
0
             : lay1_toggle == 0                                             ? LAY1_OFF + 1
2140
0
                                : LAY1_OFF + 0; //the newest L1 picture in the DPB
2141
0
        const uint8_t  lay2_idx   = LAY2_OFF; //the newest L2 picture in the DPB
2142
0
        const uint8_t  long_base_idx = 7;
2143
0
        const uint16_t long_base_pic = 128;
2144
2145
0
#if OPT_USE_HL0_FLAT
2146
0
        if (hierarchical_levels == 1) {
2147
0
            switch (temporal_layer) {
2148
0
            case 0:
2149
0
                ref_dpb_index[LAST]  = base2_idx;
2150
0
                ref_dpb_index[LAST2] = base1_idx;
2151
0
                ref_dpb_index[LAST3] = long_base_idx;
2152
0
                ref_dpb_index[GOLD]  = base0_idx;
2153
2154
0
                ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2155
0
                ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2156
0
                ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2157
2158
0
                if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2159
                    // Only 2 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2160
0
                    av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xfc);
2161
0
                } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2162
                    // Only 5 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2163
0
                    av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xf0);
2164
                    //Layer0 toggle 0->1->2
2165
0
                    ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2166
0
                } else {
2167
0
                    av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2168
                    //Layer0 toggle 0->1->2
2169
0
                    ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2170
0
                }
2171
0
                break;
2172
0
            case 1:
2173
0
                ref_dpb_index[LAST]  = base2_idx;
2174
0
                ref_dpb_index[LAST2] = scs->mrp_ctrls.referencing_scheme == 0 ? base1_idx : lay1_1_idx;
2175
0
                ref_dpb_index[LAST3] = base1_idx;
2176
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2177
2178
0
                ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2179
0
                ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2180
0
                ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2181
2182
0
                av1_rps->refresh_frame_mask = 0;
2183
0
                if (pcs->is_ref) {
2184
0
                    if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2185
0
                        av1_rps->refresh_frame_mask = 1 << 1;
2186
0
                    } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2187
0
                        av1_rps->refresh_frame_mask = 1 << LAY1_OFF;
2188
0
                    } else {
2189
0
                        av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
2190
                        // Layer1 toggle 3->4
2191
0
                        ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2192
0
                    }
2193
0
                }
2194
0
                break;
2195
0
            default:
2196
0
                SVT_ERROR("unexpected picture mini Gop number\n");
2197
0
                break;
2198
0
            }
2199
0
        } else {
2200
            // LD CBR only supports flat/1L/2L
2201
0
            assert(hierarchical_levels == 2);
2202
0
            switch (temporal_layer) {
2203
0
            case 0:
2204
0
                ref_dpb_index[LAST]  = base2_idx;
2205
0
                ref_dpb_index[LAST2] = base0_idx;
2206
0
                ref_dpb_index[LAST3] = long_base_idx;
2207
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2208
2209
0
                ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2210
0
                ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2211
0
                ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2212
2213
0
                if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2214
                    // Only 2 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2215
0
                    av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xfc);
2216
0
                } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2217
                    // Only 5 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2218
0
                    av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xf0);
2219
                    //Layer0 toggle 0->1->2
2220
0
                    ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2221
0
                } else {
2222
0
                    av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2223
                    //Layer0 toggle 0->1->2
2224
0
                    ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2225
0
                }
2226
0
                break;
2227
2228
0
            case 1: // Phoenix
2229
0
                ref_dpb_index[LAST]  = base2_idx;
2230
0
                ref_dpb_index[LAST2] = lay1_1_idx;
2231
0
                ref_dpb_index[LAST3] = base1_idx;
2232
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2233
2234
0
                ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2235
0
                ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2236
0
                ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2237
2238
0
                if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2239
0
                    av1_rps->refresh_frame_mask = 1 << 1;
2240
0
                } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2241
0
                    av1_rps->refresh_frame_mask = 1 << LAY1_OFF;
2242
0
                } else {
2243
0
                    av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
2244
                    // Layer1 toggle 3->4
2245
0
                    ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2246
0
                }
2247
0
                break;
2248
2249
0
            case 2:
2250
0
                if (pic_idx == 0) {
2251
0
                    ref_dpb_index[LAST]  = base2_idx;
2252
0
                    ref_dpb_index[LAST2] = lay1_1_idx;
2253
0
                    ref_dpb_index[LAST3] = base1_idx;
2254
0
                    ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2255
2256
0
                    ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2257
0
                    ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2258
0
                    ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2259
0
                } else if (pic_idx == 2) {
2260
0
                    ref_dpb_index[LAST]  = lay1_1_idx;
2261
0
                    ref_dpb_index[LAST2] = base2_idx;
2262
0
                    ref_dpb_index[LAST3] = lay1_0_idx;
2263
0
                    ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2264
2265
0
                    ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2266
0
                    ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2267
0
                    ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2268
0
                } else {
2269
0
                    SVT_LOG("Error in GOp indexing\n");
2270
0
                }
2271
2272
0
                assert(IMPLIES(scs->mrp_ctrls.ld_reduce_ref_buffs,
2273
0
                               !pcs->is_ref && scs->mrp_ctrls.referencing_scheme == 0));
2274
0
                av1_rps->refresh_frame_mask = (pcs->is_ref) ? 1 << (lay2_idx) : 0;
2275
                // This check should be redundant, but is added to avoid hangs if settings are not set correctly
2276
0
                if (scs->mrp_ctrls.ld_reduce_ref_buffs) {
2277
0
                    av1_rps->refresh_frame_mask = 0;
2278
0
                }
2279
0
                break;
2280
0
            default:
2281
0
                SVT_ERROR("unexpected picture mini Gop number\n");
2282
0
                break;
2283
0
            }
2284
0
        }
2285
#else
2286
        switch (temporal_layer) {
2287
        case 0:
2288
            ref_dpb_index[LAST]  = base2_idx;
2289
            ref_dpb_index[LAST2] = base0_idx;
2290
            ref_dpb_index[LAST3] = long_base_idx;
2291
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2292
2293
            ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2294
            ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2295
            ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2296
2297
            if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2298
                // Only 2 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2299
                av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xfc);
2300
            } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2301
                // Only 5 DPB entries should be used, so fill in remaining entries to remove old pics (free up ref buffers)
2302
                av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle | (0xf0);
2303
                //Layer0 toggle 0->1->2
2304
                ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2305
            } else {
2306
                av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2307
                //Layer0 toggle 0->1->2
2308
                ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2309
            }
2310
            break;
2311
2312
        case 1: // Phoenix
2313
            ref_dpb_index[LAST]  = base2_idx;
2314
            ref_dpb_index[LAST2] = lay1_1_idx;
2315
            ref_dpb_index[LAST3] = base1_idx;
2316
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2317
2318
            ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2319
            ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2320
            ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2321
2322
            if (scs->mrp_ctrls.ld_reduce_ref_buffs == 2) {
2323
                av1_rps->refresh_frame_mask = 1 << 1;
2324
            } else if (scs->mrp_ctrls.ld_reduce_ref_buffs == 1) {
2325
                av1_rps->refresh_frame_mask = 1 << LAY1_OFF;
2326
            } else {
2327
                av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
2328
                // Layer1 toggle 3->4
2329
                ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2330
            }
2331
            break;
2332
2333
        case 2:
2334
            if (pic_idx == 0) {
2335
                ref_dpb_index[LAST]  = base2_idx;
2336
                ref_dpb_index[LAST2] = lay1_1_idx;
2337
                ref_dpb_index[LAST3] = base1_idx;
2338
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2339
2340
                ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2341
                ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2342
                ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2343
            } else if (pic_idx == 2) {
2344
                ref_dpb_index[LAST]  = lay1_1_idx;
2345
                ref_dpb_index[LAST2] = base2_idx;
2346
                ref_dpb_index[LAST3] = lay1_0_idx;
2347
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2348
2349
                ref_dpb_index[BWD]  = ref_dpb_index[LAST];
2350
                ref_dpb_index[ALT2] = ref_dpb_index[LAST];
2351
                ref_dpb_index[ALT]  = ref_dpb_index[LAST];
2352
            } else {
2353
                SVT_LOG("Error in GOp indexing\n");
2354
            }
2355
2356
            assert(IMPLIES(scs->mrp_ctrls.ld_reduce_ref_buffs, !pcs->is_ref && scs->mrp_ctrls.referencing_scheme == 0));
2357
            av1_rps->refresh_frame_mask = (pcs->is_ref) ? 1 << (lay2_idx) : 0;
2358
            // This check should be redundant, but is added to avoid hangs if settings are not set correctly
2359
            if (scs->mrp_ctrls.ld_reduce_ref_buffs) {
2360
                av1_rps->refresh_frame_mask = 0;
2361
            }
2362
            break;
2363
        default:
2364
            SVT_ERROR("unexpected picture mini Gop number\n");
2365
            break;
2366
        }
2367
#endif
2368
2369
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2370
2371
0
        set_ref_list_counts(pcs, ctx);
2372
        // to make sure the long base reference is in base layer
2373
0
        if (scs->static_config.pred_structure == LOW_DELAY &&
2374
0
            (pcs->picture_number - ctx->last_long_base_pic) >= long_base_pic && pcs->temporal_layer_index == 0) {
2375
0
            av1_rps->refresh_frame_mask |= (1 << long_base_idx);
2376
0
            ctx->last_long_base_pic = pcs->picture_number;
2377
0
        }
2378
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2379
0
        set_frame_display_params(pcs, ctx, mg_idx);
2380
0
    } else if (hierarchical_levels == 0) {
2381
0
        const uint8_t base0_idx = (ctx->lay0_toggle + 8 - 1) % 8; // the newest L0 picture in the DPB
2382
0
        const uint8_t base1_idx = (ctx->lay0_toggle + 8 - 2) % 8; // the 2nd-newest L0 picture in the DPB
2383
0
        const uint8_t base2_idx = (ctx->lay0_toggle + 8 - 3) % 8; // the 3rd-newest L0 picture in the DPB
2384
0
        const uint8_t base3_idx = (ctx->lay0_toggle + 8 - 4) % 8; // the 4th-newest L0 picture in the DPB
2385
0
        const uint8_t base4_idx = (ctx->lay0_toggle + 8 - 5) % 8; // the 5th-newest L0 picture in the DPB
2386
0
        const uint8_t base5_idx = (ctx->lay0_toggle + 8 - 6) % 8; // the 6th-newest L0 picture in the DPB
2387
0
        const uint8_t base7_idx = (ctx->lay0_toggle + 8 - 7) % 8; // the oldest L0 picture in the DPB
2388
2389
        // {1, 3, 5, 7},   // GOP Index 0 - Ref List 0
2390
        // { 2, 4, 6, 0 }  // GOP Index 0 - Ref List 1
2391
0
        ref_dpb_index[LAST]  = base0_idx;
2392
0
        ref_dpb_index[LAST2] = base2_idx;
2393
0
        ref_dpb_index[LAST3] = base4_idx;
2394
0
        ref_dpb_index[GOLD]  = base7_idx;
2395
2396
0
        ref_dpb_index[BWD]  = base1_idx;
2397
0
        ref_dpb_index[ALT2] = base3_idx;
2398
0
        ref_dpb_index[ALT]  = base5_idx;
2399
2400
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2401
2402
0
        set_ref_list_counts(pcs, ctx);
2403
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2404
2405
0
        av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2406
2407
        // Flat mode, output all frames
2408
0
        set_frame_display_params(pcs, ctx, mg_idx);
2409
0
        frm_hdr->show_frame    = true;
2410
0
        pcs->has_show_existing = false;
2411
0
        ctx->lay0_toggle       = (1 + ctx->lay0_toggle) % 8;
2412
0
    } else if (hierarchical_levels == 1) {
2413
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2414
0
        uint8_t lay1_toggle = ctx->lay1_toggle;
2415
        /* The default toggling assumes that the toggle is updated in decode order for an RA configuration.
2416
        For low-delay configurations, the decode order is the display order, so instead of having the base
2417
        toggle updated before all other pictures, it is now updated last.  Hence, we need to adjust the toggle
2418
        for low-delay configurations to ensure that all indices will still correspond to the proper reference
2419
        (i.e. newest base, middle base, oldest base, etc.). Lay 1 pics in RA will typically be decoded second
2420
        (right after base) so all higher level pics will assume that layer 1 was toggled before them.  For low-
2421
        delay, the first half of the higher level pics will be before the layer 1 toggle, while the second half
2422
        will come after the toggle.  Hence, the layer 1 toggle only needs to be updated for the first half of
2423
        the pictures. */
2424
0
        if (pcs->pred_struct_ptr->pred_type != RANDOM_ACCESS && temporal_layer) {
2425
0
            assert(IMPLIES(scs->static_config.pred_structure == RANDOM_ACCESS, ctx->cut_short_ra_mg));
2426
0
            lay0_toggle = circ_inc(3, 1, lay0_toggle);
2427
            // No layer 1 toggling needed because there's only one non-base frame
2428
0
        }
2429
2430
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
2431
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
2432
0
        const uint8_t base2_idx = lay0_toggle == 0 ? 2 : lay0_toggle == 1 ? 0 : 1; //the newest L0 picture in the DPB
2433
2434
0
#if OPT_USE_HL0_FLAT
2435
0
        const uint8_t lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
2436
#else
2437
        //const uint8_t  lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
2438
#endif
2439
0
        const uint8_t lay1_1_idx = lay1_toggle == 0 ? LAY1_OFF + 1 : LAY1_OFF + 0; //the newest L1 picture in the DPB
2440
        //const uint8_t  lay2_idx = LAY2_OFF; //the newest L2 picture in the DPB
2441
2442
0
        switch (temporal_layer) {
2443
0
        case 0:
2444
            //{ 2, 6, 0, 0},  // GOP Index 0 - Ref List 0
2445
            //{ 2, 4, 0, 0 } // GOP Index 0 - Ref List 1
2446
0
            ref_dpb_index[LAST]  = base2_idx;
2447
0
            ref_dpb_index[LAST2] = base0_idx;
2448
0
            ref_dpb_index[LAST3] = ref_dpb_index[LAST];
2449
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2450
2451
0
            ref_dpb_index[BWD]  = base2_idx;
2452
0
            ref_dpb_index[ALT2] = base1_idx;
2453
0
            ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2454
2455
0
            av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2456
            //Layer0 toggle 0->1->2
2457
0
            ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2458
0
            break;
2459
0
        case 1:
2460
0
            if (pcs->is_overlay) {
2461
                // update RPS for the overlay frame.
2462
                //{ 0, 0, 0, 0}         // GOP Index 1 - Ref List 0
2463
                //{ 0, 0, 0, 0 }       // GOP Index 1 - Ref List 1
2464
0
                ref_dpb_index[LAST]  = base2_idx;
2465
0
                ref_dpb_index[LAST2] = base2_idx;
2466
0
                ref_dpb_index[LAST3] = base2_idx;
2467
0
                ref_dpb_index[GOLD]  = base2_idx;
2468
0
                ref_dpb_index[BWD]   = base2_idx;
2469
0
                ref_dpb_index[ALT2]  = base2_idx;
2470
0
                ref_dpb_index[ALT]   = base2_idx;
2471
0
                assert(!pcs->is_ref);
2472
0
#if OPT_USE_HL0_FLAT
2473
0
                av1_rps->refresh_frame_mask = 0;
2474
0
#endif
2475
0
            } else {
2476
                //{ 1, 2, 3,  0},   // GOP Index 4 - Ref List 0
2477
                //{-1,  0, 0,  0}     // GOP Index 4 - Ref List 1
2478
0
                ref_dpb_index[LAST] = base1_idx;
2479
0
#if OPT_USE_HL0_FLAT
2480
0
                ref_dpb_index[LAST2] = scs->mrp_ctrls.referencing_scheme == 0 ? base0_idx : lay1_1_idx;
2481
#else
2482
                ref_dpb_index[LAST2] = lay1_1_idx;
2483
#endif
2484
0
                ref_dpb_index[LAST3] = base0_idx;
2485
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2486
2487
0
                ref_dpb_index[BWD] = base2_idx;
2488
0
#if OPT_USE_HL0_FLAT
2489
0
                ref_dpb_index[ALT2] = scs->mrp_ctrls.referencing_scheme == 0 ? ref_dpb_index[BWD] : lay1_0_idx;
2490
#else
2491
                ref_dpb_index[ALT2] = ref_dpb_index[BWD];
2492
#endif
2493
0
                ref_dpb_index[ALT] = ref_dpb_index[BWD];
2494
2495
0
#if OPT_USE_HL0_FLAT
2496
0
                av1_rps->refresh_frame_mask = pcs->is_ref ? 1 << (LAY1_OFF + ctx->lay1_toggle) : 0;
2497
0
#endif
2498
                //Layer1 toggle 3->4
2499
0
                ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2500
0
            }
2501
#if !OPT_USE_HL0_FLAT
2502
            av1_rps->refresh_frame_mask = pcs->is_ref ? 1 << (LAY1_OFF + ctx->lay1_toggle) : 0;
2503
#endif
2504
0
            break;
2505
0
        default:
2506
0
            SVT_ERROR("unexpected picture mini Gop number\n");
2507
0
            break;
2508
0
        }
2509
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2510
2511
0
        set_ref_list_counts(pcs, ctx);
2512
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2513
2514
0
        if (!set_frame_display_params(pcs, ctx, mg_idx)) {
2515
0
            if (temporal_layer < hierarchical_levels) {
2516
0
                frm_hdr->show_frame    = false;
2517
0
                pcs->has_show_existing = false;
2518
0
            } else {
2519
0
                frm_hdr->show_frame    = true;
2520
0
                pcs->has_show_existing = true;
2521
2522
0
                if (pic_idx == 0) {
2523
0
                    frm_hdr->show_existing_frame = base2_idx;
2524
0
                } else {
2525
0
                    SVT_LOG("Error in GOP indexing for hierarchical level %d\n", pcs->hierarchical_levels);
2526
0
                }
2527
0
            }
2528
0
        }
2529
0
    } else if (hierarchical_levels == 2) {
2530
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2531
0
        uint8_t lay1_toggle = ctx->lay1_toggle;
2532
        /* The default toggling assumes that the toggle is updated in decode order for an RA configuration.
2533
        For low-delay configurations, the decode order is the display order, so instead of having the base
2534
        toggle updated before all other pictures, it is now updated last.  Hence, we need to adjust the toggle
2535
        for low-delay configurations to ensure that all indices will still correspond to the proper reference
2536
        (i.e. newest base, middle base, oldest base, etc.). Lay 1 pics in RA will typically be decoded second
2537
        (right after base) so all higher level pics will assume that layer 1 was toggled before them.  For low-
2538
        delay, the first half of the higher level pics will be before the layer 1 toggle, while the second half
2539
        will come after the toggle.  Hence, the layer 1 toggle only needs to be updated for the first half of
2540
        the pictures. */
2541
0
        if (pcs->pred_struct_ptr->pred_type != RANDOM_ACCESS && temporal_layer) {
2542
0
            assert(IMPLIES(scs->static_config.pred_structure == RANDOM_ACCESS, ctx->cut_short_ra_mg));
2543
0
            lay0_toggle = circ_inc(3, 1, lay0_toggle);
2544
0
            if (pic_idx == 0) {
2545
0
                lay1_toggle = 1 - lay1_toggle;
2546
0
            }
2547
0
        }
2548
2549
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
2550
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
2551
0
        const uint8_t base2_idx = lay0_toggle == 0 ? 2 : lay0_toggle == 1 ? 0 : 1; //the newest L0 picture in the DPB
2552
2553
0
        const uint8_t  lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
2554
0
        const uint8_t  lay1_1_idx = lay1_toggle == 0 ? LAY1_OFF + 1 : LAY1_OFF + 0; //the newest L1 picture in the DPB
2555
0
        const uint8_t  lay2_idx   = LAY2_OFF; //the newest L2 picture in the DPB
2556
0
        const uint8_t  long_base_idx = 7;
2557
0
        const uint16_t long_base_pic = 128;
2558
2559
0
        switch (temporal_layer) {
2560
0
        case 0:
2561
            //{4, 12, 0, 0}, // GOP Index 0 - Ref List 0
2562
            //{ 4, 8, 0, 0 } // GOP Index 0 - Ref List 1
2563
0
            ref_dpb_index[LAST]  = base2_idx;
2564
0
            ref_dpb_index[LAST2] = base0_idx;
2565
0
            if (scs->static_config.pred_structure == LOW_DELAY) {
2566
0
                ref_dpb_index[LAST3] = long_base_idx;
2567
0
            } else {
2568
0
                ref_dpb_index[LAST3] = ref_dpb_index[LAST];
2569
0
            }
2570
0
            ref_dpb_index[GOLD] = ref_dpb_index[LAST];
2571
2572
0
            ref_dpb_index[BWD]  = base2_idx;
2573
0
            ref_dpb_index[ALT2] = base1_idx;
2574
0
            ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2575
2576
0
            av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2577
            //Layer0 toggle 0->1->2
2578
0
            ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2579
0
            break;
2580
2581
0
        case 1: // Phoenix
2582
            //{ 2, 4, 6, 0}   // GOP Index 2 - Ref List 0
2583
            //{-2, 0, 0, 0}   // GOP Index 2 - Ref List 1
2584
0
            ref_dpb_index[LAST]  = base1_idx;
2585
0
            ref_dpb_index[LAST2] = lay1_1_idx;
2586
0
            ref_dpb_index[LAST3] = base0_idx;
2587
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2588
2589
0
            ref_dpb_index[BWD]  = base2_idx;
2590
0
            ref_dpb_index[ALT2] = ref_dpb_index[BWD];
2591
0
            ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2592
2593
0
            av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
2594
            //Layer1 toggle 3->4
2595
0
            ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2596
0
            break;
2597
2598
0
        case 2:
2599
0
            if (pcs->is_overlay) {
2600
                // update RPS for the overlay frame.
2601
                //{ 0, 0, 0, 0}         // GOP Index 1 - Ref List 0
2602
                //{ 0, 0, 0, 0 }       // GOP Index 1 - Ref List 1
2603
0
                ref_dpb_index[LAST]  = base2_idx;
2604
0
                ref_dpb_index[LAST2] = base2_idx;
2605
0
                ref_dpb_index[LAST3] = base2_idx;
2606
0
                ref_dpb_index[GOLD]  = base2_idx;
2607
0
                ref_dpb_index[BWD]   = base2_idx;
2608
0
                ref_dpb_index[ALT2]  = base2_idx;
2609
0
                ref_dpb_index[ALT]   = base2_idx;
2610
0
            } else if (pic_idx == 0) {
2611
                //{ 1, 3, 5, 0}      // GOP Index 1 - Ref List 0
2612
                //{ -1, -3, 0, 0}    // GOP Index 1 - Ref List 1
2613
0
                ref_dpb_index[LAST]  = base1_idx;
2614
0
                ref_dpb_index[LAST2] = lay1_0_idx;
2615
0
                ref_dpb_index[LAST3] = base0_idx;
2616
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2617
2618
0
                ref_dpb_index[BWD]  = lay1_1_idx;
2619
0
                ref_dpb_index[ALT2] = base2_idx;
2620
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2621
0
            } else if (pic_idx == 2) {
2622
                // { 1, 3, 2, 0},     // GOP Index 3 - Ref List 0
2623
                // { -1,0, 0, 0}      // GOP Index 3 - Ref List 1
2624
0
                ref_dpb_index[LAST]  = lay1_1_idx;
2625
0
                ref_dpb_index[LAST2] = base1_idx;
2626
0
                ref_dpb_index[LAST3] = lay2_idx;
2627
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2628
2629
0
                ref_dpb_index[BWD]  = base2_idx;
2630
0
                ref_dpb_index[ALT2] = ref_dpb_index[BWD];
2631
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2632
0
            } else {
2633
0
                SVT_LOG("Error in GOp indexing\n");
2634
0
            }
2635
2636
0
            av1_rps->refresh_frame_mask = (pcs->is_ref) ? 1 << (lay2_idx) : 0;
2637
0
            break;
2638
0
        default:
2639
0
            SVT_ERROR("unexpected picture mini Gop number\n");
2640
0
            break;
2641
0
        }
2642
2643
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2644
2645
0
        set_ref_list_counts(pcs, ctx);
2646
        // to make sure the long base reference is in base layer
2647
0
        if (scs->static_config.pred_structure == LOW_DELAY &&
2648
0
            (pcs->picture_number - ctx->last_long_base_pic) >= long_base_pic && pcs->temporal_layer_index == 0) {
2649
0
            av1_rps->refresh_frame_mask |= (1 << long_base_idx);
2650
0
            ctx->last_long_base_pic = pcs->picture_number;
2651
0
        }
2652
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2653
2654
0
        if (!set_frame_display_params(pcs, ctx, mg_idx)) {
2655
0
            if (temporal_layer < hierarchical_levels) {
2656
0
                frm_hdr->show_frame    = false;
2657
0
                pcs->has_show_existing = false;
2658
0
            } else {
2659
0
                frm_hdr->show_frame    = true;
2660
0
                pcs->has_show_existing = true;
2661
2662
0
                if (pic_idx == 0) {
2663
0
                    frm_hdr->show_existing_frame = lay1_1_idx;
2664
0
                } else if (pic_idx == 2) {
2665
0
                    frm_hdr->show_existing_frame = base2_idx;
2666
0
                } else {
2667
0
                    SVT_LOG("Error in GOP indexing for hierarchical level %d\n", pcs->hierarchical_levels);
2668
0
                }
2669
0
            }
2670
0
        }
2671
0
    } else if (hierarchical_levels == 3) {
2672
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2673
0
        uint8_t lay1_toggle = ctx->lay1_toggle;
2674
        /* The default toggling assumes that the toggle is updated in decode order for an RA configuration.
2675
        For low-delay configurations, the decode order is the display order, so instead of having the base
2676
        toggle updated before all other pictures, it is now updated last.  Hence, we need to adjust the toggle
2677
        for low-delay configurations to ensure that all indices will still correspond to the proper reference
2678
        (i.e. newest base, middle base, oldest base, etc.). Lay 1 pics in RA will typically be decoded second
2679
        (right after base) so all higher level pics will assume that layer 1 was toggled before them.  For low-
2680
        delay, the first half of the higher level pics will be before the layer 1 toggle, while the second half
2681
        will come after the toggle.  Hence, the layer 1 toggle only needs to be updated for the first half of
2682
        the pictures. */
2683
0
        if (pcs->pred_struct_ptr->pred_type != RANDOM_ACCESS && temporal_layer) {
2684
0
            assert(IMPLIES(scs->static_config.pred_structure == RANDOM_ACCESS, ctx->cut_short_ra_mg));
2685
0
            lay0_toggle = circ_inc(3, 1, lay0_toggle);
2686
0
            if (pic_idx < 3) {
2687
0
                lay1_toggle = 1 - lay1_toggle;
2688
0
            }
2689
0
        }
2690
2691
        //pic_idx has this order:
2692
        //         0     2    4      6
2693
        //            1          5
2694
        //                 3
2695
        //                              7(could be an I)
2696
2697
        //DPB: Loc7|Loc6|Loc5|Loc4|Loc3|Loc2|Loc1|Loc0
2698
        //Layer 0 : circular move 0-1-2
2699
        //Layer 1 : circular move 3-4
2700
        //Layer 2 : circular move 5-6
2701
        //Layer 3 : 7
2702
        //pic_num
2703
        //         1     3    5      7    9     11     13      15
2704
        //            2          6           10            14
2705
        //                 4                        12
2706
        //
2707
        //base0:0                   base1:8                          base2:16
2708
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
2709
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
2710
0
        const uint8_t base2_idx = lay0_toggle == 0 ? 2 : lay0_toggle == 1 ? 0 : 1; //the newest L0 picture in the DPB
2711
2712
0
        const uint8_t lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
2713
0
        const uint8_t lay1_1_idx = lay1_toggle == 0 ? LAY1_OFF + 1 : LAY1_OFF + 0; //the newest L1 picture in the DPB
2714
0
        const uint8_t lay2_idx   = LAY2_OFF; //the newest L2 picture in the DPB
2715
0
        const uint8_t lay3_idx   = LAY3_OFF; //the newest L3 picture in the DPB
2716
2717
0
        switch (temporal_layer) {
2718
0
        case 0:
2719
            //{8, 24, 0, 0},  // GOP Index 0 - Ref List 0
2720
            //{ 8, 16, 0, 0 } // GOP Index 0 - Ref List 1
2721
0
            ref_dpb_index[LAST]  = base2_idx;
2722
0
            ref_dpb_index[LAST2] = base0_idx;
2723
0
            ref_dpb_index[LAST3] = ref_dpb_index[LAST];
2724
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2725
2726
0
            ref_dpb_index[BWD]  = base2_idx;
2727
0
            ref_dpb_index[ALT2] = base1_idx;
2728
0
            ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2729
2730
0
            av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2731
            //Layer0 toggle 0->1->2
2732
0
            ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2733
0
            break;
2734
0
        case 1:
2735
            //{ 4, 8, 12,  0},   // GOP Index 4 - Ref List 0
2736
            //{-4,  0, 0,  0}     // GOP Index 4 - Ref List 1
2737
0
            ref_dpb_index[LAST]  = base1_idx;
2738
0
            ref_dpb_index[LAST2] = lay1_1_idx;
2739
0
            ref_dpb_index[LAST3] = base0_idx;
2740
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2741
2742
0
            ref_dpb_index[BWD]  = base2_idx;
2743
0
            ref_dpb_index[ALT2] = ref_dpb_index[BWD];
2744
0
            ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2745
2746
0
            av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
2747
            //Layer1 toggle 3->4
2748
0
            ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2749
0
            break;
2750
0
        case 2:
2751
0
            if (pic_idx == 1) {
2752
                //{  2,  4,  6,  10}    // GOP Index 2 - Ref List 0
2753
                //{ -2, -6,  0,   0}    // GOP Index 2 - Ref List 1
2754
0
                ref_dpb_index[LAST]  = base1_idx;
2755
0
                ref_dpb_index[LAST2] = lay2_idx;
2756
0
                ref_dpb_index[LAST3] = lay1_0_idx;
2757
0
                ref_dpb_index[GOLD]  = base0_idx;
2758
2759
0
                ref_dpb_index[BWD]  = lay1_1_idx;
2760
0
                ref_dpb_index[ALT2] = base2_idx;
2761
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2762
0
            } else if (pic_idx == 5) {
2763
                //{ 2, 4, 6, 10}    // GOP Index 6 - Ref List 0
2764
                //{ -2,  0, 0,  0 } // GOP Index 6 - Ref List 1
2765
0
                ref_dpb_index[LAST]  = lay1_1_idx;
2766
0
                ref_dpb_index[LAST2] = lay2_idx;
2767
0
                ref_dpb_index[LAST3] = base1_idx;
2768
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
2769
2770
0
                ref_dpb_index[BWD]  = base2_idx;
2771
0
                ref_dpb_index[ALT2] = ref_dpb_index[BWD];
2772
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2773
0
            }
2774
2775
0
            av1_rps->refresh_frame_mask = 1 << (lay2_idx);
2776
0
            break;
2777
0
        case 3:
2778
0
            if (pcs->is_overlay) {
2779
                // update RPS for the overlay frame.
2780
                //{ 0, 0, 0, 0}        // GOP Index 1 - Ref List 0
2781
                //{ 0, 0, 0, 0 }       // GOP Index 1 - Ref List 1
2782
0
                ref_dpb_index[LAST]  = base2_idx;
2783
0
                ref_dpb_index[LAST2] = base2_idx;
2784
0
                ref_dpb_index[LAST3] = base2_idx;
2785
0
                ref_dpb_index[GOLD]  = base2_idx;
2786
0
                ref_dpb_index[BWD]   = base2_idx;
2787
0
                ref_dpb_index[ALT2]  = base2_idx;
2788
0
                ref_dpb_index[ALT]   = base2_idx;
2789
0
            } else if (pic_idx == 0) {
2790
                //{1, 5, 8, 0},     // GOP Index 1 - Ref List 0
2791
                //{ -1, -3, -7, 0 } // GOP Index 1 - Ref List 1
2792
0
                ref_dpb_index[LAST]  = base1_idx;
2793
0
                ref_dpb_index[LAST2] = lay1_0_idx;
2794
0
                ref_dpb_index[LAST3] = lay3_idx;
2795
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2796
2797
0
                ref_dpb_index[BWD]  = lay2_idx;
2798
0
                ref_dpb_index[ALT2] = lay1_1_idx;
2799
0
                ref_dpb_index[ALT]  = base2_idx;
2800
0
            } else if (pic_idx == 2) {
2801
                //{1, 3, 2, 0}, // GOP Index 3 - Ref List 0
2802
                //{ -1,  -5, 0,  0 } // GOP Index 3 - Ref List 1
2803
0
                ref_dpb_index[LAST]  = lay2_idx;
2804
0
                ref_dpb_index[LAST2] = base1_idx;
2805
0
                ref_dpb_index[LAST3] = lay3_idx;
2806
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2807
2808
0
                ref_dpb_index[BWD]  = lay1_1_idx;
2809
0
                ref_dpb_index[ALT2] = base2_idx;
2810
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2811
0
            } else if (pic_idx == 4) {
2812
                //{1, 5, 4, 0},    // GOP Index 5 - Ref List 0
2813
                //{ -1, -3, 0, 0 } // GOP Index 5 - Ref List 1
2814
0
                ref_dpb_index[LAST]  = lay1_1_idx;
2815
0
                ref_dpb_index[LAST2] = base1_idx;
2816
0
                ref_dpb_index[LAST3] = lay3_idx;
2817
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2818
2819
0
                ref_dpb_index[BWD]  = lay2_idx;
2820
0
                ref_dpb_index[ALT2] = base2_idx;
2821
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2822
0
            } else if (pic_idx == 6) {
2823
                //{1, 3, 6, 0},   // GOP Index 7 - Ref List 0
2824
                //{ -1, 0, 0, 0 } // GOP Index 7 - Ref List 1
2825
0
                ref_dpb_index[LAST]  = lay2_idx;
2826
0
                ref_dpb_index[LAST2] = lay1_1_idx;
2827
0
                ref_dpb_index[LAST3] = lay3_idx;
2828
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2829
2830
0
                ref_dpb_index[BWD]  = base2_idx;
2831
0
                ref_dpb_index[ALT2] = ref_dpb_index[BWD];
2832
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
2833
0
            } else {
2834
0
                SVT_LOG("Error in GOp indexing\n");
2835
0
            }
2836
2837
0
            av1_rps->refresh_frame_mask = (pcs->is_ref) ? 1 << (lay3_idx) : 0;
2838
0
            break;
2839
2840
0
        default:
2841
0
            SVT_ERROR("unexpected picture mini Gop number\n");
2842
0
            break;
2843
0
        }
2844
2845
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
2846
2847
0
        set_ref_list_counts(pcs, ctx);
2848
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
2849
2850
0
        if (!set_frame_display_params(pcs, ctx, mg_idx)) {
2851
0
            if (temporal_layer < hierarchical_levels) {
2852
0
                frm_hdr->show_frame    = false;
2853
0
                pcs->has_show_existing = false;
2854
0
            } else {
2855
0
                frm_hdr->show_frame    = true;
2856
0
                pcs->has_show_existing = true;
2857
2858
0
                if (pic_idx == 0) {
2859
0
                    frm_hdr->show_existing_frame = lay2_idx;
2860
0
                } else if (pic_idx == 2) {
2861
0
                    frm_hdr->show_existing_frame = lay1_1_idx;
2862
0
                } else if (pic_idx == 4) {
2863
0
                    frm_hdr->show_existing_frame = lay2_idx;
2864
0
                } else if (pic_idx == 6) {
2865
0
                    frm_hdr->show_existing_frame = base2_idx;
2866
0
                } else {
2867
0
                    SVT_LOG("Error in GOP indexing for hierarchical level %d\n", pcs->hierarchical_levels);
2868
0
                }
2869
0
            }
2870
0
        }
2871
0
    } else if (hierarchical_levels == 4) {
2872
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
2873
0
        uint8_t lay1_toggle = ctx->lay1_toggle;
2874
        /* The default toggling assumes that the toggle is updated in decode order for an RA configuration.
2875
        For low-delay configurations, the decode order is the display order, so instead of having the base
2876
        toggle updated before all other pictures, it is now updated last.  Hence, we need to adjust the toggle
2877
        for low-delay configurations to ensure that all indices will still correspond to the proper reference
2878
        (i.e. newest base, middle base, oldest base, etc.). Lay 1 pics in RA will typically be decoded second
2879
        (right after base) so all higher level pics will assume that layer 1 was toggled before them.  For low-
2880
        delay, the first half of the higher level pics will be before the layer 1 toggle, while the second half
2881
        will come after the toggle.  Hence, the layer 1 toggle only needs to be updated for the first half of
2882
        the pictures. */
2883
0
        if (pcs->pred_struct_ptr->pred_type != RANDOM_ACCESS && temporal_layer) {
2884
0
            assert(IMPLIES(scs->static_config.pred_structure == RANDOM_ACCESS, ctx->cut_short_ra_mg));
2885
0
            lay0_toggle = circ_inc(3, 1, lay0_toggle);
2886
0
            if (pic_idx < 7) {
2887
0
                lay1_toggle = 1 - lay1_toggle;
2888
0
            }
2889
0
        }
2890
        //pic_idx has this order:
2891
        //         0     2    4      6    8     10     12      14
2892
        //            1          5           9            13
2893
        //                 3                        11
2894
        //                              7
2895
        //                                                          15(could be an I)
2896
2897
        //DPB: Loc7|Loc6|Loc5|Loc4|Loc3|Loc2|Loc1|Loc0
2898
        //Layer 0 : circular move 0-1-2
2899
        //Layer 1 : circular move 3-4
2900
        //Layer 2 : DPB Location 5
2901
        //Layer 3 : DPB Location 6
2902
        //Layer 4 : DPB Location 7
2903
        //pic_num                  for poc 17
2904
        //         1     3    5      7    9     11     13      15         17    19     21    23   25     27    29    31
2905
        //            2          6           10            14                18           22          26          30
2906
        //                 4                        12:L2_0                         20:L2_1                 28
2907
        //                              8:L1_0                                                       24:L1_1
2908
        //base0:0                                               base1:16                                           base2:32
2909
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
2910
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
2911
0
        const uint8_t base2_idx = lay0_toggle == 0 ? 2 : lay0_toggle == 1 ? 0 : 1; //the newest L0 picture in the DPB
2912
2913
0
        const uint8_t lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
2914
0
        const uint8_t lay1_1_idx = lay1_toggle == 0 ? LAY1_OFF + 1 : LAY1_OFF + 0; //the newest L1 picture in the DPB
2915
0
        const uint8_t lay2_idx   = LAY2_OFF; //the newest L2 picture in the DPB
2916
0
        const uint8_t lay3_idx   = LAY3_OFF; //the newest L3 picture in the DPB
2917
0
        const uint8_t lay4_idx   = LAY4_OFF; //the newest L4 picture in the DPB
2918
2919
0
        switch (temporal_layer) {
2920
0
        case 0:
2921
2922
            //{16, 48, 0, 0},      // GOP Index 0 - Ref List 0
2923
            //{16, 32, 0, 0}       // GOP Index 0 - Ref List 1
2924
0
            ref_dpb_index[LAST]  = base2_idx;
2925
0
            ref_dpb_index[LAST2] = base0_idx;
2926
0
            ref_dpb_index[LAST3] = more_5L_refs ? lay1_1_idx : ref_dpb_index[LAST]; //48:p24
2927
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2928
2929
0
            ref_dpb_index[BWD]  = base2_idx;
2930
0
            ref_dpb_index[ALT2] = base1_idx;
2931
0
            ref_dpb_index[ALT]  = more_5L_refs ? lay1_0_idx : ref_dpb_index[BWD]; //48:p8
2932
2933
0
            av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
2934
            //Layer0 toggle 0->1->2
2935
0
            ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
2936
0
            break;
2937
2938
0
        case 1:
2939
            //{  8, 16, 24, 0},   // GOP Index 8 - Ref List 0
2940
            //{ -8, 0, 0, 0}      // GOP Index 8 - Ref List 1
2941
0
            ref_dpb_index[LAST]  = base1_idx;
2942
0
            ref_dpb_index[LAST2] = lay1_1_idx;
2943
0
            ref_dpb_index[LAST3] = base0_idx;
2944
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
2945
2946
0
            ref_dpb_index[BWD]  = base2_idx;
2947
0
            ref_dpb_index[ALT2] = lay2_idx;
2948
0
            ref_dpb_index[ALT]  = ref_dpb_index[BWD]; //40:-30
2949
2950
0
            av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
2951
            //Layer1 toggle 3->4
2952
0
            ctx->lay1_toggle = 1 - ctx->lay1_toggle;
2953
0
            break;
2954
2955
0
        case 2:
2956
0
            if (pic_idx == 3) {
2957
                //{  4,   8,  12,  20 },  // GOP Index 4 - Ref List 0
2958
                //{ -4, -12,  0,  0 }     // GOP Index 4 - Ref List 1
2959
0
                ref_dpb_index[LAST]  = base1_idx;
2960
0
                ref_dpb_index[LAST2] = lay2_idx;
2961
0
                ref_dpb_index[LAST3] = lay1_0_idx;
2962
0
                ref_dpb_index[GOLD]  = base0_idx;
2963
2964
0
                ref_dpb_index[BWD]  = lay1_1_idx;
2965
0
                ref_dpb_index[ALT2] = base2_idx;
2966
0
                ref_dpb_index[ALT]  = more_5L_refs ? lay3_idx : ref_dpb_index[BWD]; //36:+30
2967
0
            } else if (pic_idx == 11) {
2968
                //{ 4, 8, 12, 0},       // GOP Index 12 - Ref List 0
2969
                //{ -4,  0, 0,  0 }     // GOP Index 12 - Ref List 1
2970
0
                ref_dpb_index[LAST]  = lay1_1_idx;
2971
0
                ref_dpb_index[LAST2] = lay2_idx;
2972
0
                ref_dpb_index[LAST3] = base1_idx;
2973
0
                ref_dpb_index[GOLD]  = lay3_idx;
2974
2975
0
                ref_dpb_index[BWD]  = base2_idx;
2976
0
                ref_dpb_index[ALT2] = lay4_idx;
2977
0
                ref_dpb_index[ALT]  = more_5L_refs ? lay1_0_idx : ref_dpb_index[BWD]; //44:+24
2978
0
            }
2979
2980
0
            av1_rps->refresh_frame_mask = 1 << (LAY2_OFF);
2981
0
            break;
2982
2983
0
        case 3:
2984
0
            if (pic_idx == 1) {
2985
                //{ 2, 4, 10, 18},        // GOP Index 2 - Ref List 0
2986
                //{ -2, -6, -14,  0 }   // GOP Index 2 - Ref List 1
2987
0
                ref_dpb_index[LAST]  = base1_idx;
2988
0
                ref_dpb_index[LAST2] = lay3_idx;
2989
0
                ref_dpb_index[LAST3] = lay1_0_idx;
2990
0
                ref_dpb_index[GOLD]  = base0_idx;
2991
0
                ref_dpb_index[BWD]   = lay2_idx;
2992
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
2993
0
                ref_dpb_index[ALT]   = base2_idx;
2994
0
            } else if (pic_idx == 5) {
2995
                //{ 2, 4, 6, 14},        // GOP Index 6 - Ref List 0
2996
                //{ -2, -10,  0,  0 }   // GOP Index 6 - Ref List 1
2997
0
                ref_dpb_index[LAST]  = lay2_idx;
2998
0
                ref_dpb_index[LAST2] = lay3_idx;
2999
0
                ref_dpb_index[LAST3] = base1_idx;
3000
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3001
0
                ref_dpb_index[BWD]   = lay1_1_idx;
3002
0
                ref_dpb_index[ALT2]  = base2_idx;
3003
0
                ref_dpb_index[ALT]   = more_5L_refs ? lay4_idx : ref_dpb_index[BWD]; // 38:p35
3004
0
            } else if (pic_idx == 9) {
3005
                //{ 2, 4, 10, 18},       // GOP Index 10 - Ref List 0
3006
                //{ -2, -6,  0,  0 }    // GOP Index 10 - Ref List 1
3007
0
                ref_dpb_index[LAST]  = lay1_1_idx;
3008
0
                ref_dpb_index[LAST2] = lay3_idx;
3009
0
                ref_dpb_index[LAST3] = base1_idx;
3010
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3011
0
                ref_dpb_index[BWD]   = lay2_idx;
3012
0
                ref_dpb_index[ALT2]  = base2_idx;
3013
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3014
0
            } else if (pic_idx == 13) {
3015
                //{ 2, 4, 6, 14},    // GOP Index 14 - Ref List 0
3016
                //{ -2, 0,  0, 0 }   // GOP Index 14 - Ref List 1
3017
0
                ref_dpb_index[LAST]  = lay2_idx;
3018
0
                ref_dpb_index[LAST2] = lay3_idx;
3019
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3020
0
                ref_dpb_index[GOLD]  = base1_idx;
3021
3022
0
                ref_dpb_index[BWD]  = base2_idx;
3023
0
                ref_dpb_index[ALT2] = lay4_idx;
3024
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
3025
0
            } else {
3026
0
                SVT_LOG("Error in GOp indexing\n");
3027
0
            }
3028
3029
0
            av1_rps->refresh_frame_mask = 1 << (lay3_idx);
3030
0
            break;
3031
3032
0
        case 4:
3033
0
            if (pcs->is_overlay) {
3034
                // update RPS for the overlay frame.
3035
                //{ 0, 0, 0, 0}  // GOP Index 1 - Ref List 0
3036
                //{ 0, 0, 0, 0 } // GOP Index 1 - Ref List 1
3037
0
                ref_dpb_index[LAST]  = base2_idx;
3038
0
                ref_dpb_index[LAST2] = base2_idx;
3039
0
                ref_dpb_index[LAST3] = base2_idx;
3040
0
                ref_dpb_index[GOLD]  = base2_idx;
3041
0
                ref_dpb_index[BWD]   = base2_idx;
3042
0
                ref_dpb_index[ALT2]  = base2_idx;
3043
0
                ref_dpb_index[ALT]   = base2_idx;
3044
0
            } else if (pic_idx == 0) {
3045
                //{ 1, 9, 8, 17},   // GOP Index 1 - Ref List 0
3046
                //{ -1, -3, -7, 0 } // GOP Index 1 - Ref List 1
3047
0
                ref_dpb_index[LAST]  = base1_idx;
3048
0
                ref_dpb_index[LAST2] = lay1_0_idx;
3049
0
                ref_dpb_index[LAST3] = lay4_idx;
3050
0
                ref_dpb_index[GOLD]  = base0_idx;
3051
0
                ref_dpb_index[BWD]   = lay3_idx;
3052
0
                ref_dpb_index[ALT2]  = lay2_idx;
3053
0
                ref_dpb_index[ALT]   = lay1_1_idx;
3054
0
            } else if (pic_idx == 2) {
3055
                //{ 1, 3, 2, 11},  // GOP Index 3 - Ref List 0
3056
                //{ -1, -5, -13, 0 }   // GOP Index 3 - Ref List 1
3057
0
                ref_dpb_index[LAST]  = lay3_idx;
3058
0
                ref_dpb_index[LAST2] = base1_idx;
3059
0
                ref_dpb_index[LAST3] = lay4_idx;
3060
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3061
0
                ref_dpb_index[BWD]   = lay2_idx;
3062
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3063
0
                ref_dpb_index[ALT]   = base2_idx;
3064
0
            } else if (pic_idx == 4) {
3065
                //{ 1, 5, 4, 13},  // GOP Index 5 - Ref List 0
3066
                //{ -1, -3, -11, 0 }   // GOP Index 5 - Ref List 1
3067
0
                ref_dpb_index[LAST]  = lay2_idx;
3068
0
                ref_dpb_index[LAST2] = base1_idx;
3069
0
                ref_dpb_index[LAST3] = lay4_idx;
3070
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3071
0
                ref_dpb_index[BWD]   = lay3_idx;
3072
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3073
0
                ref_dpb_index[ALT]   = base2_idx;
3074
0
            } else if (pic_idx == 6) {
3075
                //{ 1, 3, 6, 7},  // GOP Index 7 - Ref List 0
3076
                //{ -1, -9, 0, 0 }   // GOP Index 7 - Ref List 1
3077
0
                ref_dpb_index[LAST]  = lay3_idx;
3078
0
                ref_dpb_index[LAST2] = lay2_idx;
3079
0
                ref_dpb_index[LAST3] = lay4_idx;
3080
0
                ref_dpb_index[GOLD]  = base1_idx;
3081
0
                ref_dpb_index[BWD]   = lay1_1_idx;
3082
0
                ref_dpb_index[ALT2]  = base2_idx;
3083
0
                ref_dpb_index[ALT]   = more_5L_refs ? lay1_0_idx : ref_dpb_index[BWD]; //39:p24
3084
0
            } else if (pic_idx == 8) {
3085
                //{ 1, 9, 8, 17},  // GOP Index 9 - Ref List 0
3086
                //{ -1, -3, -7, 0 }   // GOP Index 9 - Ref List 1
3087
0
                ref_dpb_index[LAST]  = lay1_1_idx;
3088
0
                ref_dpb_index[LAST2] = base1_idx;
3089
0
                ref_dpb_index[LAST3] = lay4_idx;
3090
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3091
0
                ref_dpb_index[BWD]   = lay3_idx;
3092
0
                ref_dpb_index[ALT2]  = lay2_idx;
3093
0
                ref_dpb_index[ALT]   = base2_idx;
3094
0
            } else if (pic_idx == 10) {
3095
                //{ 1, 3, 2, 11},  // GOP Index 11 - Ref List 0
3096
                //{ -1, -5, 0, 0 }   // GOP Index 11 - Ref List 1
3097
0
                ref_dpb_index[LAST]  = lay3_idx;
3098
0
                ref_dpb_index[LAST2] = lay1_1_idx;
3099
0
                ref_dpb_index[LAST3] = lay4_idx;
3100
0
                ref_dpb_index[GOLD]  = base1_idx;
3101
0
                ref_dpb_index[BWD]   = lay2_idx;
3102
0
                ref_dpb_index[ALT2]  = base2_idx;
3103
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3104
0
            } else if (pic_idx == 12) {
3105
                //{ 1, 5, 4, 13},  // GOP Index 13 - Ref List 0
3106
                //{ -1, -3, 0, 0 }   // GOP Index 13 - Ref List 1
3107
0
                ref_dpb_index[LAST]  = lay2_idx;
3108
0
                ref_dpb_index[LAST2] = lay1_1_idx;
3109
0
                ref_dpb_index[LAST3] = lay4_idx;
3110
0
                ref_dpb_index[GOLD]  = base1_idx;
3111
0
                ref_dpb_index[BWD]   = lay3_idx;
3112
0
                ref_dpb_index[ALT2]  = base2_idx;
3113
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3114
0
            } else if (pic_idx == 14) {
3115
                //{ 1, 3, 6, 7},  // GOP Index 15 - Ref List 0
3116
                //{ -1, 0, 0, 0 }   // GOP Index 15 - Ref List 1
3117
0
                ref_dpb_index[LAST]  = lay3_idx;
3118
0
                ref_dpb_index[LAST2] = lay2_idx;
3119
0
                ref_dpb_index[LAST3] = lay4_idx;
3120
0
                ref_dpb_index[GOLD]  = lay1_1_idx;
3121
0
                ref_dpb_index[BWD]   = base2_idx;
3122
0
                ref_dpb_index[ALT2]  = base1_idx;
3123
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3124
0
            } else {
3125
0
                SVT_LOG("Error in GOp indexing\n");
3126
0
            }
3127
3128
0
            av1_rps->refresh_frame_mask = (pcs->is_ref) ? 1 << (lay4_idx) : 0;
3129
0
            break;
3130
3131
0
        default:
3132
0
            SVT_ERROR("unexpected picture mini Gop number\n");
3133
0
            break;
3134
0
        }
3135
3136
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
3137
3138
0
        set_ref_list_counts(pcs, ctx);
3139
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
3140
3141
0
        if (!set_frame_display_params(pcs, ctx, mg_idx)) {
3142
0
            if (temporal_layer < hierarchical_levels) {
3143
0
                frm_hdr->show_frame    = false;
3144
0
                pcs->has_show_existing = false;
3145
0
            } else {
3146
0
                frm_hdr->show_frame    = true;
3147
0
                pcs->has_show_existing = true;
3148
3149
0
                if (pic_idx == 0) {
3150
0
                    frm_hdr->show_existing_frame = lay3_idx;
3151
0
                } else if (pic_idx == 2) {
3152
0
                    frm_hdr->show_existing_frame = lay2_idx;
3153
0
                } else if (pic_idx == 4) {
3154
0
                    frm_hdr->show_existing_frame = lay3_idx;
3155
0
                } else if (pic_idx == 6) {
3156
0
                    frm_hdr->show_existing_frame = lay1_1_idx;
3157
0
                } else if (pic_idx == 8) {
3158
0
                    frm_hdr->show_existing_frame = lay3_idx;
3159
0
                } else if (pic_idx == 10) {
3160
0
                    frm_hdr->show_existing_frame = lay2_idx;
3161
0
                } else if (pic_idx == 12) {
3162
0
                    frm_hdr->show_existing_frame = lay3_idx;
3163
0
                } else if (pic_idx == 14) {
3164
0
                    frm_hdr->show_existing_frame = base2_idx;
3165
0
                } else {
3166
0
                    SVT_LOG("Error in GOP indexing for hierarchical level %d\n", pcs->hierarchical_levels);
3167
0
                }
3168
0
            }
3169
0
        }
3170
0
    } else if (hierarchical_levels == 5) {
3171
0
        uint8_t lay0_toggle = ctx->lay0_toggle;
3172
0
        uint8_t lay1_toggle = ctx->lay1_toggle;
3173
        /* The default toggling assumes that the toggle is updated in decode order for an RA configuration.
3174
        For low-delay configurations, the decode order is the display order, so instead of having the base
3175
        toggle updated before all other pictures, it is now updated last.  Hence, we need to adjust the toggle
3176
        for low-delay configurations to ensure that all indices will still correspond to the proper reference
3177
        (i.e. newest base, middle base, oldest base, etc.). Lay 1 pics in RA will typically be decoded second
3178
        (right after base) so all higher level pics will assume that layer 1 was toggled before them.  For low-
3179
        delay, the first half of the higher level pics will be before the layer 1 toggle, while the second half
3180
        will come after the toggle.  Hence, the layer 1 toggle only needs to be updated for the first half of
3181
        the pictures. */
3182
0
        if (pcs->pred_struct_ptr->pred_type != RANDOM_ACCESS && temporal_layer) {
3183
0
            assert(IMPLIES(scs->static_config.pred_structure == RANDOM_ACCESS, ctx->cut_short_ra_mg));
3184
0
            lay0_toggle = circ_inc(3, 1, lay0_toggle);
3185
0
            if (pic_idx < 15) {
3186
0
                lay1_toggle = 1 - lay1_toggle;
3187
0
            }
3188
0
        }
3189
3190
        //DPB: Loc7|Loc6|Loc5|Loc4|Loc3|Loc2|Loc1|Loc0
3191
        //Layer 0 : circular move 0-1-2
3192
        //Layer 1 : circular move 3-4
3193
        //Layer 2 : DPB Location 5
3194
        //Layer 3 : DPB Location 6
3195
        //Layer 4 : DPB Location 7
3196
0
        const uint8_t base0_idx = lay0_toggle == 0 ? 0 : lay0_toggle == 1 ? 1 : 2; //the oldest L0 picture in the DPB
3197
0
        const uint8_t base1_idx = lay0_toggle == 0 ? 1 : lay0_toggle == 1 ? 2 : 0; //the middle L0 picture in the DPB
3198
0
        const uint8_t base2_idx = lay0_toggle == 0 ? 2 : lay0_toggle == 1 ? 0 : 1; //the newest L0 picture in the DPB
3199
3200
0
        const uint8_t lay1_0_idx = lay1_toggle == 0 ? LAY1_OFF + 0 : LAY1_OFF + 1; //the oldest L1 picture in the DPB
3201
0
        const uint8_t lay1_1_idx = lay1_toggle == 0 ? LAY1_OFF + 1 : LAY1_OFF + 0; //the newest L1 picture in the DPB
3202
0
        const uint8_t lay2_idx   = LAY2_OFF; //the newest L2 picture in the DPB
3203
0
        const uint8_t lay3_idx   = LAY3_OFF; //the newest L3 picture in the DPB
3204
0
        const uint8_t lay4_idx   = LAY4_OFF; //the newest L4 picture in the DPB
3205
3206
0
        switch (temporal_layer) {
3207
0
        case 0:
3208
            //{32, 64, 96, 0}, // GOP Index 0 - Ref List 0
3209
            //{ 32, 48, 0, 0 } // GOP Index 0 - Ref List 1
3210
0
            ref_dpb_index[LAST]  = base2_idx;
3211
0
            ref_dpb_index[LAST2] = base1_idx;
3212
0
            ref_dpb_index[LAST3] = base0_idx;
3213
0
            ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3214
0
            ref_dpb_index[BWD]   = base2_idx;
3215
0
            ref_dpb_index[ALT2]  = lay1_1_idx;
3216
0
            ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3217
3218
0
            av1_rps->refresh_frame_mask = 1 << ctx->lay0_toggle;
3219
            //Layer0 toggle 0->1->2
3220
0
            ctx->lay0_toggle = circ_inc(3, 1, ctx->lay0_toggle);
3221
0
            break;
3222
3223
0
        case 1:
3224
            //{16, 32, 48, 64}, // GOP Index 16 - Ref List 0
3225
            //{-16, 24, 20, 0} // GOP Index 16 - Ref List 1
3226
0
            ref_dpb_index[LAST]  = base1_idx;
3227
0
            ref_dpb_index[LAST2] = lay1_1_idx;
3228
0
            ref_dpb_index[LAST3] = base0_idx;
3229
0
            ref_dpb_index[GOLD]  = lay1_0_idx;
3230
3231
0
            ref_dpb_index[BWD]  = base2_idx;
3232
0
            ref_dpb_index[ALT2] = lay2_idx;
3233
0
            ref_dpb_index[ALT]  = lay3_idx;
3234
3235
0
            av1_rps->refresh_frame_mask = 1 << (LAY1_OFF + ctx->lay1_toggle);
3236
            //Layer1 toggle 2->3
3237
0
            ctx->lay1_toggle = 1 - ctx->lay1_toggle;
3238
0
            break;
3239
0
        case 2:
3240
0
            if (pic_idx == 7) {
3241
                //{8, 16, 24, 0}, // GOP Index 8 - Ref List 0
3242
                //{-8, -24, 12, 0 } // GOP Index 8 - Ref List 1
3243
0
                ref_dpb_index[LAST]  = base1_idx;
3244
0
                ref_dpb_index[LAST2] = lay2_idx;
3245
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3246
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3247
3248
0
                ref_dpb_index[BWD]  = lay1_1_idx;
3249
0
                ref_dpb_index[ALT2] = base2_idx;
3250
0
                ref_dpb_index[ALT]  = lay3_idx;
3251
0
            } else if (pic_idx == 23) {
3252
                //{8, 16, 24, 0}    // GOP Index 24 - Ref List 0
3253
                //{-8, 10, 40, 0} // GOP Index 24 - Ref List 1
3254
0
                ref_dpb_index[LAST]  = lay1_1_idx;
3255
0
                ref_dpb_index[LAST2] = lay2_idx;
3256
0
                ref_dpb_index[LAST3] = base1_idx;
3257
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3258
3259
0
                ref_dpb_index[BWD]  = base2_idx;
3260
0
                ref_dpb_index[ALT2] = lay4_idx;
3261
0
                ref_dpb_index[ALT]  = lay1_0_idx;
3262
0
            }
3263
3264
0
            av1_rps->refresh_frame_mask = 1 << (LAY2_OFF);
3265
0
            break;
3266
3267
0
        case 3:
3268
0
            if (pic_idx == 3) {
3269
                //{4, 8, 20, 36}, // GOP Index 4 - Ref List 0
3270
                //{-4, -12, -28, 0} // GOP Index 4 - Ref List 1
3271
0
                ref_dpb_index[LAST]  = base1_idx;
3272
0
                ref_dpb_index[LAST2] = lay3_idx;
3273
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3274
0
                ref_dpb_index[GOLD]  = base0_idx;
3275
0
                ref_dpb_index[BWD]   = lay2_idx;
3276
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3277
0
                ref_dpb_index[ALT]   = base2_idx;
3278
0
            } else if (pic_idx == 11) {
3279
                //{1, 3, 11, 27}, // GOP Index 12 - Ref List 0
3280
                //{-4, -20, 5, 0} // GOP Index 12 - Ref List 1
3281
0
                ref_dpb_index[LAST]  = lay2_idx;
3282
0
                ref_dpb_index[LAST2] = lay3_idx;
3283
0
                ref_dpb_index[LAST3] = base1_idx;
3284
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3285
0
                ref_dpb_index[BWD]   = lay1_1_idx;
3286
0
                ref_dpb_index[ALT2]  = base2_idx;
3287
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3288
0
            } else if (pic_idx == 19) {
3289
                //{4, 8, 20, 0}, // GOP Index 20 - Ref List 0
3290
                //{-4, -12, 0, 0} // GOP Index 20 - Ref List 1
3291
0
                ref_dpb_index[LAST]  = lay1_1_idx;
3292
0
                ref_dpb_index[LAST2] = lay3_idx;
3293
0
                ref_dpb_index[LAST3] = base1_idx;
3294
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3295
0
                ref_dpb_index[BWD]   = lay2_idx;
3296
0
                ref_dpb_index[ALT2]  = base2_idx;
3297
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3298
0
            } else if (pic_idx == 27) {
3299
                //{4, 8, 12, 28}, // GOP Index 28 - Ref List 0
3300
                //{-4, 60, 0, 0} // GOP Index 28 - Ref List 1
3301
0
                ref_dpb_index[LAST]  = lay2_idx;
3302
0
                ref_dpb_index[LAST2] = lay3_idx;
3303
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3304
0
                ref_dpb_index[GOLD]  = base1_idx;
3305
3306
0
                ref_dpb_index[BWD]  = base2_idx;
3307
0
                ref_dpb_index[ALT2] = base0_idx;
3308
0
                ref_dpb_index[ALT]  = ref_dpb_index[BWD];
3309
0
            } else {
3310
0
                SVT_LOG("Error in GOp indexing\n");
3311
0
            }
3312
3313
0
            av1_rps->refresh_frame_mask = 1 << (LAY3_OFF);
3314
0
            break;
3315
3316
0
        case 4:
3317
0
            if (pic_idx == 1) {
3318
                //{2, 4, 18, -30}, // GOP Index 2 - Ref List 0
3319
                //{-2, -6, -14, 0} // GOP Index 2 - Ref List 1
3320
0
                ref_dpb_index[LAST]  = base1_idx;
3321
0
                ref_dpb_index[LAST2] = lay4_idx;
3322
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3323
0
                ref_dpb_index[GOLD]  = base2_idx;
3324
0
                ref_dpb_index[BWD]   = lay3_idx;
3325
0
                ref_dpb_index[ALT2]  = lay2_idx;
3326
0
                ref_dpb_index[ALT]   = lay1_1_idx;
3327
0
            } else if (pic_idx == 5) {
3328
                //{2, 4, 6, 22}, // GOP Index 6 - Ref List 0
3329
                //{-2, -10, -26, 0} // GOP Index 6 - Ref List 1
3330
0
                ref_dpb_index[LAST]  = lay3_idx;
3331
0
                ref_dpb_index[LAST2] = lay4_idx;
3332
0
                ref_dpb_index[LAST3] = base1_idx;
3333
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3334
0
                ref_dpb_index[BWD]   = lay2_idx;
3335
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3336
0
                ref_dpb_index[ALT]   = base2_idx;
3337
0
            } else if (pic_idx == 9) {
3338
                //{2, 4, 10, 26}, // GOP Index 10 - Ref List 0
3339
                //{-2, -6, -22, 0} // GOP Index 10 - Ref List 1
3340
0
                ref_dpb_index[LAST]  = lay2_idx;
3341
0
                ref_dpb_index[LAST2] = lay4_idx;
3342
0
                ref_dpb_index[LAST3] = base1_idx;
3343
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3344
0
                ref_dpb_index[BWD]   = lay3_idx;
3345
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3346
0
                ref_dpb_index[ALT]   = base2_idx;
3347
0
            } else if (pic_idx == 13) {
3348
                //{2, 4, 6, 14}, // GOP Index 14 - Ref List 0
3349
                //{-2, -18, 0, 0} // GOP Index 14 - Ref List 1
3350
0
                ref_dpb_index[LAST]  = lay3_idx;
3351
0
                ref_dpb_index[LAST2] = lay4_idx;
3352
0
                ref_dpb_index[LAST3] = lay2_idx;
3353
0
                ref_dpb_index[GOLD]  = base1_idx;
3354
0
                ref_dpb_index[BWD]   = lay1_1_idx;
3355
0
                ref_dpb_index[ALT2]  = base2_idx;
3356
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3357
0
            } else if (pic_idx == 17) {
3358
                //{2, 4, 18,  34}, // GOP Index 18 - Ref List 0
3359
                //{-2, -6, -14, 0} // GOP Index 18 - Ref List 1
3360
0
                ref_dpb_index[LAST]  = lay1_1_idx;
3361
0
                ref_dpb_index[LAST2] = lay4_idx;
3362
0
                ref_dpb_index[LAST3] = base1_idx;
3363
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3364
0
                ref_dpb_index[BWD]   = lay3_idx;
3365
0
                ref_dpb_index[ALT2]  = lay2_idx;
3366
0
                ref_dpb_index[ALT]   = base2_idx;
3367
0
            } else if (pic_idx == 21) {
3368
                //{2, 4, 6, 22}, // GOP Index 22 - Ref List 0
3369
                //{-2, -10, 0, 0} // GOP Index 22 - Ref List 1
3370
0
                ref_dpb_index[LAST]  = lay3_idx;
3371
0
                ref_dpb_index[LAST2] = lay4_idx;
3372
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3373
0
                ref_dpb_index[GOLD]  = base1_idx;
3374
0
                ref_dpb_index[BWD]   = lay2_idx;
3375
0
                ref_dpb_index[ALT2]  = base2_idx;
3376
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3377
0
            } else if (pic_idx == 25) {
3378
                //{2, 4, 10, 26}, // GOP Index 26 - Ref List 0
3379
                //{-2, -6, 0, 0} // GOP Index 26 - Ref List 1
3380
0
                ref_dpb_index[LAST]  = lay2_idx;
3381
0
                ref_dpb_index[LAST2] = lay4_idx;
3382
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3383
0
                ref_dpb_index[GOLD]  = base1_idx;
3384
0
                ref_dpb_index[BWD]   = lay3_idx;
3385
0
                ref_dpb_index[ALT2]  = base2_idx;
3386
0
                ref_dpb_index[ALT]   = ref_dpb_index[BWD];
3387
0
            } else if (pic_idx == 29) {
3388
                //{2, 4, 6, 14}, // GOP Index 30 - Ref List 0
3389
                //{-2, 30, 62, 0} // GOP Index 30 - Ref List 1
3390
0
                ref_dpb_index[LAST]  = lay3_idx;
3391
0
                ref_dpb_index[LAST2] = lay4_idx;
3392
0
                ref_dpb_index[LAST3] = lay2_idx;
3393
0
                ref_dpb_index[GOLD]  = lay1_1_idx;
3394
0
                ref_dpb_index[BWD]   = base2_idx;
3395
0
                ref_dpb_index[ALT2]  = base1_idx;
3396
0
                ref_dpb_index[ALT]   = base0_idx;
3397
0
            } else {
3398
0
                SVT_LOG("Error in GOp indexing\n");
3399
0
            }
3400
3401
0
            av1_rps->refresh_frame_mask = 1 << (LAY4_OFF);
3402
0
            break;
3403
3404
0
        case 5:
3405
0
            if (pcs->is_overlay) {
3406
                // update RPS for the overlay frame.
3407
                //{ 0, 0, 0, 0}  // GOP Index 1 - Ref List 0
3408
                //{ 0, 0, 0, 0 } // GOP Index 1 - Ref List 1
3409
0
                ref_dpb_index[LAST]  = base2_idx;
3410
0
                ref_dpb_index[LAST2] = base2_idx;
3411
0
                ref_dpb_index[LAST3] = base2_idx;
3412
0
                ref_dpb_index[GOLD]  = base2_idx;
3413
0
                ref_dpb_index[BWD]   = base2_idx;
3414
0
                ref_dpb_index[ALT2]  = base2_idx;
3415
0
                ref_dpb_index[ALT]   = base2_idx;
3416
0
            } else if (pic_idx == 0) {
3417
                //{1, 17, -15, -31}, // GOP Index 1 - Ref List 0
3418
                //{-1, -3, -7, 0} // GOP Index 1 - Ref List 1
3419
0
                ref_dpb_index[LAST]  = base1_idx;
3420
0
                ref_dpb_index[LAST2] = lay1_0_idx;
3421
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3422
0
                ref_dpb_index[GOLD]  = base2_idx;
3423
0
                ref_dpb_index[BWD]   = lay4_idx;
3424
0
                ref_dpb_index[ALT2]  = lay3_idx;
3425
0
                ref_dpb_index[ALT]   = lay2_idx;
3426
0
            } else if (pic_idx == 2) {
3427
                //{1, 3, 19, -29}, // GOP Index 3 - Ref List 0
3428
                //{-1, -5, -13, 0} // GOP Index 3 - Ref List 1
3429
0
                ref_dpb_index[LAST]  = lay4_idx;
3430
0
                ref_dpb_index[LAST2] = base1_idx;
3431
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3432
0
                ref_dpb_index[GOLD]  = base2_idx;
3433
0
                ref_dpb_index[BWD]   = lay3_idx;
3434
0
                ref_dpb_index[ALT2]  = lay2_idx;
3435
0
                ref_dpb_index[ALT]   = lay1_1_idx;
3436
0
            } else if (pic_idx == 4) {
3437
                //{1, 5, 21, 0}, // GOP Index 5 - Ref List 0
3438
                //{-1, -3, -11, 0} // GOP Index 5 - Ref List 1
3439
0
                ref_dpb_index[LAST]  = lay3_idx;
3440
0
                ref_dpb_index[LAST2] = base1_idx;
3441
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3442
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3443
0
                ref_dpb_index[BWD]   = lay4_idx;
3444
0
                ref_dpb_index[ALT2]  = lay2_idx;
3445
0
                ref_dpb_index[ALT]   = lay1_1_idx;
3446
0
            } else if (pic_idx == 6) {
3447
                //{1, 3, 7, 0}, // GOP Index 7 - Ref List 0
3448
                //{-1, -9, -25, 0} // GOP Index 7 - Ref List 1
3449
0
                ref_dpb_index[LAST]  = lay4_idx;
3450
0
                ref_dpb_index[LAST2] = lay3_idx;
3451
0
                ref_dpb_index[LAST3] = base1_idx;
3452
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3453
0
                ref_dpb_index[BWD]   = lay2_idx;
3454
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3455
0
                ref_dpb_index[ALT]   = base2_idx;
3456
0
            } else if (pic_idx == 8) {
3457
                //{1, 9, 25, 0}, // GOP Index 9 - Ref List 0
3458
                //{-1, -3, -7, 0} // GOP Index 9 - Ref List 1
3459
0
                ref_dpb_index[LAST]  = lay2_idx;
3460
0
                ref_dpb_index[LAST2] = base1_idx;
3461
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3462
0
                ref_dpb_index[GOLD]  = ref_dpb_index[LAST];
3463
0
                ref_dpb_index[BWD]   = lay4_idx;
3464
0
                ref_dpb_index[ALT2]  = lay3_idx;
3465
0
                ref_dpb_index[ALT]   = lay1_1_idx;
3466
0
            } else if (pic_idx == 10) {
3467
                //{1, 3, 11, 27}, // GOP Index 11 - Ref List 0
3468
                //{-1, -5, -21, 0} // GOP Index 11 - Ref List 1
3469
0
                ref_dpb_index[LAST]  = lay4_idx;
3470
0
                ref_dpb_index[LAST2] = lay2_idx;
3471
0
                ref_dpb_index[LAST3] = base1_idx;
3472
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3473
0
                ref_dpb_index[BWD]   = lay3_idx;
3474
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3475
0
                ref_dpb_index[ALT]   = base2_idx;
3476
0
            } else if (pic_idx == 12) {
3477
                //{1, 5, 13, 29}, // GOP Index 13 - Ref List 0
3478
                //{-1, -3, -19, 0} // GOP Index 13 - Ref List 1
3479
0
                ref_dpb_index[LAST]  = lay3_idx;
3480
0
                ref_dpb_index[LAST2] = lay2_idx;
3481
0
                ref_dpb_index[LAST3] = base1_idx;
3482
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3483
0
                ref_dpb_index[BWD]   = lay4_idx;
3484
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3485
0
                ref_dpb_index[ALT]   = base2_idx;
3486
0
            } else if (pic_idx == 14) {
3487
                //{1, 3, 7, 31}, // GOP Index 15 - Ref List 0
3488
                //{ -1, -17, 15, 0 } // GOP Index 15 - Ref List 1
3489
0
                ref_dpb_index[LAST]  = lay4_idx;
3490
0
                ref_dpb_index[LAST2] = lay3_idx;
3491
0
                ref_dpb_index[LAST3] = lay2_idx;
3492
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3493
0
                ref_dpb_index[BWD]   = lay1_1_idx;
3494
0
                ref_dpb_index[ALT2]  = base2_idx;
3495
0
                ref_dpb_index[ALT]   = base1_idx;
3496
0
            } else if (pic_idx == 16) {
3497
                //{1, 17, 33, -15}, // GOP Index 17 - Ref List 0
3498
                //{-1, -3, -7, 0} // GOP Index 17 - Ref List 1
3499
0
                ref_dpb_index[LAST]  = lay1_1_idx;
3500
0
                ref_dpb_index[LAST2] = base1_idx;
3501
0
                ref_dpb_index[LAST3] = lay1_0_idx;
3502
0
                ref_dpb_index[GOLD]  = base2_idx;
3503
0
                ref_dpb_index[BWD]   = lay4_idx;
3504
0
                ref_dpb_index[ALT2]  = lay3_idx;
3505
0
                ref_dpb_index[ALT]   = lay2_idx;
3506
0
            } else if (pic_idx == 18) {
3507
                //{1, 3, 19, 35}, // GOP Index 19 - Ref List 0
3508
                //{-1, -5, -13, 0} // GOP Index 19 - Ref List 1
3509
0
                ref_dpb_index[LAST]  = lay4_idx;
3510
0
                ref_dpb_index[LAST2] = lay1_1_idx;
3511
0
                ref_dpb_index[LAST3] = base1_idx;
3512
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3513
0
                ref_dpb_index[BWD]   = lay3_idx;
3514
0
                ref_dpb_index[ALT2]  = lay2_idx;
3515
0
                ref_dpb_index[ALT]   = base2_idx;
3516
0
            } else if (pic_idx == 20) {
3517
                //{1, 5, 21, 37}, // GOP Index 21 - Ref List 0
3518
                //{-1, -3, -11, 0} // GOP Index 21 - Ref List 1
3519
0
                ref_dpb_index[LAST]  = lay3_idx;
3520
0
                ref_dpb_index[LAST2] = lay1_1_idx;
3521
0
                ref_dpb_index[LAST3] = base1_idx;
3522
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3523
0
                ref_dpb_index[BWD]   = lay4_idx;
3524
0
                ref_dpb_index[ALT2]  = lay2_idx;
3525
0
                ref_dpb_index[ALT]   = base2_idx;
3526
0
            } else if (pic_idx == 22) {
3527
                //{1, 3, 7, 23}, // GOP Index 23 - Ref List 0
3528
                //{-1, -9, 55, 0} // GOP Index 23 - Ref List 1
3529
0
                ref_dpb_index[LAST]  = lay4_idx;
3530
0
                ref_dpb_index[LAST2] = lay3_idx;
3531
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3532
0
                ref_dpb_index[GOLD]  = base1_idx;
3533
0
                ref_dpb_index[BWD]   = lay2_idx;
3534
0
                ref_dpb_index[ALT2]  = base2_idx;
3535
0
                ref_dpb_index[ALT]   = base0_idx;
3536
0
            } else if (pic_idx == 24) {
3537
                //{1, 9, 25, 41}, // GOP Index 25 - Ref List 0
3538
                //{-1, -3, -7, 0} // GOP Index 25 - Ref List 1
3539
0
                ref_dpb_index[LAST]  = lay2_idx;
3540
0
                ref_dpb_index[LAST2] = lay1_1_idx;
3541
0
                ref_dpb_index[LAST3] = base1_idx;
3542
0
                ref_dpb_index[GOLD]  = lay1_0_idx;
3543
0
                ref_dpb_index[BWD]   = lay4_idx;
3544
0
                ref_dpb_index[ALT2]  = lay3_idx;
3545
0
                ref_dpb_index[ALT]   = base2_idx;
3546
0
            } else if (pic_idx == 26) {
3547
                //{1, 3, 11, 27}, // GOP Index 27 - Ref List 0
3548
                //{-1, -5, 59, 0} // GOP Index 27 - Ref List 1
3549
0
                ref_dpb_index[LAST]  = lay4_idx;
3550
0
                ref_dpb_index[LAST2] = lay2_idx;
3551
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3552
0
                ref_dpb_index[GOLD]  = base1_idx;
3553
0
                ref_dpb_index[BWD]   = lay3_idx;
3554
0
                ref_dpb_index[ALT2]  = base2_idx;
3555
0
                ref_dpb_index[ALT]   = base0_idx;
3556
0
            } else if (pic_idx == 28) {
3557
                //{1, 5, 13, 29}, // GOP Index 29 - Ref List 0
3558
                //{-1, -3, 61, 0} // GOP Index 29 - Ref List 1
3559
0
                ref_dpb_index[LAST]  = lay3_idx;
3560
0
                ref_dpb_index[LAST2] = lay2_idx;
3561
0
                ref_dpb_index[LAST3] = lay1_1_idx;
3562
0
                ref_dpb_index[GOLD]  = base1_idx;
3563
0
                ref_dpb_index[BWD]   = lay4_idx;
3564
0
                ref_dpb_index[ALT2]  = base2_idx;
3565
0
                ref_dpb_index[ALT]   = base0_idx;
3566
0
            } else if (pic_idx == 30) {
3567
                //{1, 3, 7, 31}, // GOP Index 31 - Ref List 0
3568
                //{ -1, 15, 63, 0 } // GOP Index 31 - Ref List 1
3569
0
                ref_dpb_index[LAST]  = lay4_idx;
3570
0
                ref_dpb_index[LAST2] = lay3_idx;
3571
0
                ref_dpb_index[LAST3] = lay2_idx;
3572
0
                ref_dpb_index[GOLD]  = base1_idx;
3573
0
                ref_dpb_index[BWD]   = base2_idx;
3574
0
                ref_dpb_index[ALT2]  = lay1_1_idx;
3575
0
                ref_dpb_index[ALT]   = base0_idx;
3576
0
            } else {
3577
0
                SVT_LOG("Error in GOp indexing\n");
3578
0
            }
3579
3580
0
            av1_rps->refresh_frame_mask = 0;
3581
0
            break;
3582
3583
0
        default:
3584
0
            SVT_ERROR("unexpected picture mini Gop number\n");
3585
0
            break;
3586
0
        }
3587
3588
0
        update_ref_poc_array(ref_dpb_index, ref_poc_array, ctx->dpb);
3589
3590
0
        set_ref_list_counts(pcs, ctx);
3591
0
        prune_refs(av1_rps, pcs->ref_list0_count, pcs->ref_list1_count);
3592
3593
0
        if (!set_frame_display_params(pcs, ctx, mg_idx)) {
3594
0
            if (temporal_layer < hierarchical_levels) {
3595
0
                frm_hdr->show_frame    = false;
3596
0
                pcs->has_show_existing = false;
3597
0
            } else {
3598
0
                frm_hdr->show_frame    = true;
3599
0
                pcs->has_show_existing = true;
3600
3601
0
                if (pic_idx == 0) {
3602
0
                    frm_hdr->show_existing_frame = lay4_idx;
3603
0
                } else if (pic_idx == 2) {
3604
0
                    frm_hdr->show_existing_frame = lay3_idx;
3605
0
                } else if (pic_idx == 4) {
3606
0
                    frm_hdr->show_existing_frame = lay4_idx;
3607
0
                } else if (pic_idx == 6) {
3608
0
                    frm_hdr->show_existing_frame = lay2_idx;
3609
0
                } else if (pic_idx == 8) {
3610
0
                    frm_hdr->show_existing_frame = lay4_idx;
3611
0
                } else if (pic_idx == 10) {
3612
0
                    frm_hdr->show_existing_frame = lay3_idx;
3613
0
                } else if (pic_idx == 12) {
3614
0
                    frm_hdr->show_existing_frame = lay4_idx;
3615
0
                } else if (pic_idx == 14) {
3616
0
                    frm_hdr->show_existing_frame = lay1_1_idx;
3617
0
                } else if (pic_idx == 16) {
3618
0
                    frm_hdr->show_existing_frame = lay4_idx;
3619
0
                } else if (pic_idx == 18) {
3620
0
                    frm_hdr->show_existing_frame = lay3_idx;
3621
0
                } else if (pic_idx == 20) {
3622
0
                    frm_hdr->show_existing_frame = lay4_idx;
3623
0
                } else if (pic_idx == 22) {
3624
0
                    frm_hdr->show_existing_frame = lay2_idx;
3625
0
                } else if (pic_idx == 24) {
3626
0
                    frm_hdr->show_existing_frame = lay4_idx;
3627
0
                } else if (pic_idx == 26) {
3628
0
                    frm_hdr->show_existing_frame = lay3_idx;
3629
0
                } else if (pic_idx == 28) {
3630
0
                    frm_hdr->show_existing_frame = lay4_idx;
3631
0
                } else if (pic_idx == 30) {
3632
0
                    frm_hdr->show_existing_frame = base2_idx;
3633
0
                } else {
3634
0
                    SVT_LOG("Error in GOP indexing for hierarchical level %d\n", pcs->hierarchical_levels);
3635
0
                }
3636
0
            }
3637
0
        }
3638
0
    } else {
3639
0
        SVT_ERROR("Not supported GOP structure!");
3640
0
        exit(0);
3641
0
    }
3642
3643
0
    if (frm_hdr->frame_type == S_FRAME) {
3644
0
        set_sframe_rps(pcs, enc_ctx, ctx);
3645
0
    }
3646
3647
    // Ref-frame management: apply STORE/USE events after any branch-specific
3648
    // RPS computation (incl. S-FRAME) but before the AV1-overlay refresh
3649
    // reset below. No-op when no STORE/CLEAR/USE event is queued AND no
3650
    // slot is currently STOREd in this ctx.
3651
0
    apply_ref_mgmt_events(pcs, ctx);
3652
3653
    // This should already be the case
3654
0
    if (pcs->is_overlay) {
3655
0
        av1_rps->refresh_frame_mask = 0;
3656
0
    }
3657
0
}
3658
3659
/***************************************************************************************************
3660
// Perform Required Picture Analysis Processing for the Overlay frame
3661
***************************************************************************************************/
3662
0
void perform_simple_picture_analysis_for_overlay(PictureParentControlSet* pcs) {
3663
0
    EbPictureBufferDesc* input_padded_pic;
3664
0
    EbPictureBufferDesc* input_pic;
3665
0
    EbPaReferenceObject* pa_ref_obj_;
3666
3667
0
    SequenceControlSet* scs = pcs->scs;
3668
0
    input_pic               = pcs->enhanced_pic;
3669
0
    pa_ref_obj_             = (EbPaReferenceObject*)pcs->pa_ref_pic_wrapper->object_ptr;
3670
0
    input_padded_pic        = (EbPictureBufferDesc*)pa_ref_obj_->input_padded_pic;
3671
3672
    // Pad pictures to multiple min cu size
3673
0
    svt_aom_pad_picture_to_multiple_of_min_blk_size_dimensions(scs, input_pic);
3674
3675
    // Pre processing operations performed on the input picture
3676
0
    svt_aom_picture_pre_processing_operations(pcs, scs);
3677
3678
0
    if (input_pic->color_format >= EB_YUV422) {
3679
        // Jing: Do the conversion of 422/444=>420 here since it's multi-threaded kernel
3680
        //       Reuse the Y, only add cb/cr in the newly created buffer desc
3681
        //       NOTE: since denoise may change the src, so this part is after svt_aom_picture_pre_processing_operations()
3682
0
        pcs->chroma_downsampled_pic->y_buffer = input_pic->y_buffer;
3683
0
        svt_aom_down_sample_chroma(input_pic, pcs->chroma_downsampled_pic);
3684
0
    } else {
3685
0
        pcs->chroma_downsampled_pic = input_pic;
3686
0
    }
3687
3688
    // R2R FIX: copying input_pic to input_padded_pic for motion_estimate_sb needs it
3689
0
    {
3690
0
        uint8_t* pa = input_padded_pic->y_buffer;
3691
0
        uint8_t* in = input_pic->y_buffer;
3692
0
        for (uint32_t row = 0; row < input_pic->height; row++) {
3693
0
            svt_memcpy(pa + row * input_padded_pic->y_stride,
3694
0
                       in + row * input_pic->y_stride,
3695
0
                       sizeof(uint8_t) * input_pic->width);
3696
0
        }
3697
0
    }
3698
3699
    // Pad input picture to complete border SBs
3700
0
    svt_aom_pad_picture_to_multiple_of_sb_dimensions(input_padded_pic);
3701
    // 1/4 & 1/16 input picture downsampling through filtering
3702
0
    svt_aom_downsample_filtering_input_picture(pcs,
3703
0
                                               input_padded_pic,
3704
0
                                               (EbPictureBufferDesc*)pa_ref_obj_->quarter_downsampled_picture_ptr,
3705
0
                                               (EbPictureBufferDesc*)pa_ref_obj_->sixteenth_downsampled_picture_ptr);
3706
3707
    // Gathering statistics of input picture, including Variance Calculation, Histogram Bins
3708
0
    svt_aom_gathering_picture_statistics(scs, pcs, input_padded_pic, pa_ref_obj_->sixteenth_downsampled_picture_ptr);
3709
3710
0
    pcs->sc_class0 = pcs->alt_ref_ppcs_ptr->sc_class0;
3711
0
    pcs->sc_class1 = pcs->alt_ref_ppcs_ptr->sc_class1;
3712
0
    pcs->sc_class2 = pcs->alt_ref_ppcs_ptr->sc_class2;
3713
0
    pcs->sc_class3 = pcs->alt_ref_ppcs_ptr->sc_class3;
3714
0
    pcs->sc_class4 = pcs->alt_ref_ppcs_ptr->sc_class4;
3715
0
}
3716
3717
/***************************************************************************************************
3718
 * Initialize the overlay frame
3719
***************************************************************************************************/
3720
0
void initialize_overlay_frame(PictureParentControlSet* pcs) {
3721
0
    pcs->scene_change_flag              = false;
3722
0
    pcs->cra_flag                       = false;
3723
0
    pcs->idr_flag                       = false;
3724
0
    pcs->last_idr_picture               = pcs->alt_ref_ppcs_ptr->last_idr_picture;
3725
0
    pcs->pred_structure                 = pcs->alt_ref_ppcs_ptr->pred_structure;
3726
0
    pcs->pred_struct_ptr                = pcs->alt_ref_ppcs_ptr->pred_struct_ptr;
3727
0
    pcs->pred_struct_index              = pcs->alt_ref_ppcs_ptr->pred_struct_index;
3728
0
    pcs->pic_idx_in_mg                  = pcs->alt_ref_ppcs_ptr->pic_idx_in_mg;
3729
0
    pcs->hierarchical_levels            = pcs->alt_ref_ppcs_ptr->hierarchical_levels;
3730
0
    pcs->hierarchical_layers_diff       = 0;
3731
0
    pcs->init_pred_struct_position_flag = false;
3732
0
    pcs->pre_assignment_buffer_count    = pcs->alt_ref_ppcs_ptr->pre_assignment_buffer_count;
3733
0
    pcs->slice_type                     = B_SLICE;
3734
    // set the overlay frame as non reference frame with max temporal layer index
3735
0
    pcs->temporal_layer_index = (uint8_t)pcs->hierarchical_levels;
3736
0
    pcs->is_highest_layer     = true;
3737
0
    pcs->ref_list0_count      = 1;
3738
0
    pcs->ref_list1_count      = 0;
3739
3740
0
    perform_simple_picture_analysis_for_overlay(pcs);
3741
0
}
3742
3743
/*
3744
  ret number of past picture(not including current) in mg buffer.
3745
3746
*/
3747
0
static int32_t avail_past_pictures(PictureParentControlSet** buf, uint32_t buf_size, uint64_t input_pic) {
3748
    //buffer has at least curr picture
3749
0
    int32_t tot_past = 0;
3750
0
    for (uint32_t pic = 0; pic < buf_size; pic++) {
3751
0
        if (buf[pic]->picture_number < input_pic) {
3752
0
            tot_past++;
3753
0
        }
3754
0
    }
3755
0
    return tot_past;
3756
0
}
3757
3758
/*
3759
  searches a picture in a given pcs buffer
3760
*/
3761
0
int32_t search_this_pic(PictureParentControlSet** buf, uint32_t buf_size, uint64_t input_pic) {
3762
0
    int32_t index = -1;
3763
0
    for (uint32_t pic = 0; pic < buf_size; pic++) {
3764
0
        if (buf[pic]->picture_number == input_pic) {
3765
0
            index = (int32_t)pic;
3766
0
            break;
3767
0
        }
3768
0
    }
3769
0
    return index;
3770
0
}
3771
3772
/*
3773
  Tells if an Intra picture should be delayed to get next mini-gop
3774
*/
3775
2.15k
bool svt_aom_is_delayed_intra(PictureParentControlSet* pcs) {
3776
2.15k
    if ((pcs->idr_flag || pcs->cra_flag) && pcs->pred_structure == RANDOM_ACCESS) {
3777
0
        if (pcs->scs->static_config.intra_period_length == 0 || pcs->end_of_sequence_flag) {
3778
0
            return 0;
3779
0
        } else if (pcs->idr_flag ||
3780
0
                   (pcs->cra_flag &&
3781
0
                    pcs->pre_assignment_buffer_count < pcs->pred_struct_ptr->pred_struct_entry_count)) {
3782
0
            return 1;
3783
0
        } else {
3784
0
            return 0;
3785
0
        }
3786
2.15k
    } else {
3787
2.15k
        return 0;
3788
2.15k
    }
3789
2.15k
}
3790
3791
void first_pass_frame_end_one_pass(PictureParentControlSet* pcs);
3792
3793
/* modulate_ref_pics()
3794
 For INTRA, the modulation uses the noise level, and towards increasing the number of ref_pics
3795
 For BASE and L1, the modulation uses the filt_INTRA-to-unfilterd_INTRA distortion range, and towards decreasing the number of ref_pics
3796
*/
3797
0
static int ref_pics_modulation(PictureParentControlSet* pcs, int32_t noise_levels_log1p_fp16) {
3798
0
    int offset = 0;
3799
3800
0
    if (pcs->slice_type == I_SLICE) {
3801
        // Adjust number of filtering frames based on noise and quantization factor.
3802
        // Basically, we would like to use more frames to filter low-noise frame such
3803
        // that the filtered frame can provide better predictions for more frames.
3804
        // Also, when the quantization factor is small enough (lossless compression),
3805
        // we will not change the number of frames for key frame filtering, which is
3806
        // to avoid visual quality drop.
3807
0
        if (noise_levels_log1p_fp16 < 26572 /*FLOAT2FP(log1p(0.5), 16, int32_t)*/) {
3808
0
            offset = 6;
3809
0
        } else if (noise_levels_log1p_fp16 < 45426 /*FLOAT2FP(log1p(1.0), 16, int32_t)*/) {
3810
0
            offset = 4;
3811
0
        } else if (noise_levels_log1p_fp16 < 71998 /*FLOAT2FP(log1p(2.0), 16, int32_t)*/) {
3812
0
            offset = 2;
3813
0
        }
3814
0
    } else if (pcs->temporal_layer_index == 0) {
3815
0
        int ratio = noise_levels_log1p_fp16 ? (pcs->filt_to_unfilt_diff * 100) / noise_levels_log1p_fp16 : 0;
3816
0
        switch (pcs->tf_ctrls.modulate_pics) {
3817
0
        case 0:
3818
0
            offset = 0;
3819
0
            break;
3820
0
        case 1:
3821
0
            if (ratio < 100) {
3822
0
                offset = 5;
3823
0
            } else {
3824
0
                offset = TF_MAX_EXTENSION;
3825
0
            }
3826
0
            break;
3827
0
        case 2:
3828
0
            if (ratio < 50) {
3829
0
                offset = 3;
3830
0
            } else if (ratio < 100) {
3831
0
                offset = 5;
3832
0
            } else {
3833
0
                offset = TF_MAX_EXTENSION;
3834
0
            }
3835
0
            break;
3836
0
        case 3:
3837
0
            if (ratio < 50) {
3838
0
                offset = 3;
3839
0
            } else if (ratio < 100) {
3840
0
                offset = 4;
3841
0
            } else {
3842
0
                offset = 5;
3843
0
            }
3844
0
            break;
3845
0
        case 4:
3846
0
            if (ratio < 50) {
3847
0
                offset = 0;
3848
0
            } else if (ratio < 100) {
3849
0
                offset = 1;
3850
0
            } else {
3851
0
                offset = 2;
3852
0
            }
3853
0
            break;
3854
0
        default:
3855
0
            break;
3856
0
        }
3857
0
    } else {
3858
0
        int ratio = noise_levels_log1p_fp16 ? (pcs->filt_to_unfilt_diff * 100) / noise_levels_log1p_fp16 : 0;
3859
0
        switch (pcs->tf_ctrls.modulate_pics) {
3860
0
        case 0:
3861
0
            offset = 0;
3862
0
            break;
3863
0
        case 1:
3864
0
            if (ratio < 25) {
3865
0
                offset = 0;
3866
0
            } else {
3867
0
                offset = 1;
3868
0
            }
3869
0
            break;
3870
0
        case 2:
3871
0
            if (ratio < 50) {
3872
0
                offset = 0;
3873
0
            } else {
3874
0
                offset = 1;
3875
0
            }
3876
3877
0
            break;
3878
0
        case 3:
3879
0
            if (ratio < 75) {
3880
0
                offset = 0;
3881
0
            } else {
3882
0
                offset = 1;
3883
0
            }
3884
0
            break;
3885
0
        default:
3886
0
            break;
3887
0
        }
3888
0
    }
3889
    // Modulate offset using qp
3890
0
    if (pcs->tf_ctrls.qp_opt) {
3891
0
        uint32_t q_weight, q_weight_denom;
3892
0
        svt_aom_get_qp_based_th_scaling_factors(pcs->scs->qp_based_th_scaling_ctrls.tf_ref_qp_based_th_scaling,
3893
0
                                                &q_weight,
3894
0
                                                &q_weight_denom,
3895
0
                                                pcs->scs->static_config.qp);
3896
0
        offset = DIVIDE_AND_ROUND(offset * q_weight, q_weight_denom);
3897
0
    }
3898
0
    return offset;
3899
0
}
3900
3901
static EbErrorType derive_tf_window_params(SequenceControlSet* scs, EncodeContext* enc_ctx,
3902
0
                                           PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
3903
0
    PictureParentControlSet* centre_pcs          = pcs;
3904
0
    EbPictureBufferDesc*     central_picture_ptr = centre_pcs->enhanced_pic;
3905
3906
    // chroma subsampling
3907
0
    uint32_t ss_x                    = centre_pcs->scs->subsampling_x;
3908
0
    uint32_t ss_y                    = centre_pcs->scs->subsampling_y;
3909
0
    int32_t* noise_levels_log1p_fp16 = &(centre_pcs->noise_levels_log1p_fp16[0]);
3910
0
    int32_t  noise_level_fp16;
3911
3912
0
    uint8_t do_noise_est = pcs->tf_ctrls.use_intra_for_noise_est ? 0 : 1;
3913
0
    if (centre_pcs->slice_type == I_SLICE) {
3914
0
        do_noise_est = 1;
3915
0
    }
3916
    // allocate 16 bit buffer
3917
0
#if CONFIG_ENABLE_HIGH_BIT_DEPTH
3918
0
    uint32_t encoder_bit_depth = centre_pcs->scs->static_config.encoder_bit_depth;
3919
0
    bool     is_highbd         = (encoder_bit_depth == 8) ? (uint8_t)false : (uint8_t)true;
3920
0
    if (is_highbd) {
3921
0
        EB_MALLOC_ARRAY(centre_pcs->altref_buffer_highbd[PLANE_Y], central_picture_ptr->luma_size);
3922
0
        if (pcs->tf_ctrls.chroma_lvl) {
3923
0
            EB_MALLOC_ARRAY(centre_pcs->altref_buffer_highbd[PLANE_U], central_picture_ptr->chroma_size);
3924
0
            EB_MALLOC_ARRAY(centre_pcs->altref_buffer_highbd[PLANE_V], central_picture_ptr->chroma_size);
3925
0
        }
3926
3927
        // pack byte buffers to 16 bit buffer
3928
0
        svt_aom_pack_highbd_pic(central_picture_ptr, centre_pcs->altref_buffer_highbd, ss_x, ss_y);
3929
        // Estimate source noise level
3930
0
        uint16_t* altref_buffer_highbd_start[MAX_PLANES];
3931
0
        altref_buffer_highbd_start[PLANE_Y] = centre_pcs->altref_buffer_highbd[PLANE_Y] +
3932
0
            central_picture_ptr->border * central_picture_ptr->y_stride + central_picture_ptr->border;
3933
0
        if (pcs->tf_ctrls.chroma_lvl) {
3934
0
            altref_buffer_highbd_start[PLANE_U] = centre_pcs->altref_buffer_highbd[PLANE_U] +
3935
0
                (central_picture_ptr->border >> ss_y) * central_picture_ptr->u_stride +
3936
0
                (central_picture_ptr->border >> ss_x);
3937
3938
0
            altref_buffer_highbd_start[PLANE_V] = centre_pcs->altref_buffer_highbd[PLANE_V] +
3939
0
                (central_picture_ptr->border >> ss_y) * central_picture_ptr->v_stride +
3940
0
                (central_picture_ptr->border >> ss_x);
3941
0
        } else {
3942
0
            altref_buffer_highbd_start[PLANE_U] = NOT_USED_VALUE;
3943
0
            altref_buffer_highbd_start[PLANE_V] = NOT_USED_VALUE;
3944
0
        }
3945
3946
0
        if (do_noise_est) {
3947
0
            noise_level_fp16 = svt_estimate_noise_highbd_fp16(altref_buffer_highbd_start[PLANE_Y], // Y only
3948
0
                                                              central_picture_ptr->width,
3949
0
                                                              central_picture_ptr->height,
3950
0
                                                              central_picture_ptr->y_stride,
3951
0
                                                              encoder_bit_depth);
3952
0
            noise_levels_log1p_fp16[PLANE_Y] = svt_aom_noise_log1p_fp16(noise_level_fp16);
3953
0
        }
3954
0
        if (pcs->tf_ctrls.chroma_lvl) {
3955
0
            noise_level_fp16 = svt_estimate_noise_highbd_fp16(altref_buffer_highbd_start[PLANE_U], // U only
3956
0
                                                              (central_picture_ptr->width >> 1),
3957
0
                                                              (central_picture_ptr->height >> 1),
3958
0
                                                              central_picture_ptr->u_stride,
3959
0
                                                              encoder_bit_depth);
3960
0
            noise_levels_log1p_fp16[PLANE_U] = svt_aom_noise_log1p_fp16(noise_level_fp16);
3961
3962
0
            noise_level_fp16 = svt_estimate_noise_highbd_fp16(altref_buffer_highbd_start[PLANE_V], // V only
3963
0
                                                              (central_picture_ptr->width >> 1),
3964
0
                                                              (central_picture_ptr->height >> 1),
3965
0
                                                              central_picture_ptr->u_stride,
3966
0
                                                              encoder_bit_depth);
3967
0
            noise_levels_log1p_fp16[PLANE_V] = svt_aom_noise_log1p_fp16(noise_level_fp16);
3968
0
        }
3969
0
    } else
3970
0
#endif
3971
0
    {
3972
0
        EbByte y_buffer = central_picture_ptr->y_buffer;
3973
0
        EbByte buffer_u = central_picture_ptr->u_buffer;
3974
0
        EbByte buffer_v = central_picture_ptr->v_buffer;
3975
3976
0
        if (do_noise_est) {
3977
0
            noise_level_fp16                 = svt_estimate_noise_fp16(y_buffer, // Y
3978
0
                                                       central_picture_ptr->width,
3979
0
                                                       central_picture_ptr->height,
3980
0
                                                       central_picture_ptr->y_stride);
3981
0
            noise_levels_log1p_fp16[PLANE_Y] = svt_aom_noise_log1p_fp16(noise_level_fp16);
3982
0
        }
3983
0
        if (pcs->tf_ctrls.chroma_lvl) {
3984
0
            noise_level_fp16                 = svt_estimate_noise_fp16(buffer_u, // U
3985
0
                                                       (central_picture_ptr->width >> ss_x),
3986
0
                                                       (central_picture_ptr->height >> ss_y),
3987
0
                                                       central_picture_ptr->u_stride);
3988
0
            noise_levels_log1p_fp16[PLANE_U] = svt_aom_noise_log1p_fp16(noise_level_fp16);
3989
3990
0
            noise_level_fp16                 = svt_estimate_noise_fp16(buffer_v, // V
3991
0
                                                       (central_picture_ptr->width >> ss_x),
3992
0
                                                       (central_picture_ptr->height >> ss_y),
3993
0
                                                       central_picture_ptr->v_stride);
3994
0
            noise_levels_log1p_fp16[PLANE_V] = svt_aom_noise_log1p_fp16(noise_level_fp16);
3995
0
        }
3996
0
    }
3997
0
    if (do_noise_est) {
3998
0
        pd_ctx->last_i_noise_levels_log1p_fp16[0] = noise_levels_log1p_fp16[0];
3999
0
    } else {
4000
0
        noise_levels_log1p_fp16[0] = pd_ctx->last_i_noise_levels_log1p_fp16[0];
4001
0
    }
4002
    // Set is_noise_level for the tf off case
4003
0
    pcs->is_noise_level = (pd_ctx->last_i_noise_levels_log1p_fp16[0] >= VQ_NOISE_LVL_TH);
4004
    // Adjust the number of filtering frames
4005
0
    int offset = pcs->tf_ctrls.modulate_pics ? ref_pics_modulation(pcs, noise_levels_log1p_fp16[0]) : 0;
4006
0
    if (scs->static_config.pred_structure != RANDOM_ACCESS) {
4007
0
        int num_past_pics   = pcs->tf_ctrls.num_past_pics + (pcs->tf_ctrls.modulate_pics ? offset : 0);
4008
0
        num_past_pics       = MIN(pcs->tf_ctrls.max_num_past_pics, num_past_pics);
4009
0
        int num_future_pics = pcs->tf_ctrls.num_future_pics + (pcs->tf_ctrls.modulate_pics ? offset : 0);
4010
0
        num_future_pics     = MIN(pcs->tf_ctrls.max_num_future_pics, num_future_pics);
4011
        //initilize list
4012
0
        for (int pic_itr = 0; pic_itr < ALTREF_MAX_NFRAMES; pic_itr++) {
4013
0
            pcs->temp_filt_pcs_list[pic_itr] = NULL;
4014
0
        }
4015
4016
        //get previous
4017
0
        for (int pic_itr = 0; pic_itr < num_past_pics; pic_itr++) {
4018
0
            int32_t idx = search_this_pic(
4019
0
                pd_ctx->tf_pic_array, pd_ctx->tf_pic_arr_cnt, pcs->picture_number - num_past_pics + pic_itr);
4020
0
            if (idx >= 0) {
4021
0
                pcs->temp_filt_pcs_list[pic_itr] = pd_ctx->tf_pic_array[idx];
4022
0
            }
4023
0
        }
4024
4025
        //get central
4026
0
        pcs->temp_filt_pcs_list[num_past_pics] = pcs;
4027
4028
0
        int actual_past_pics   = num_past_pics;
4029
0
        int actual_future_pics = 0;
4030
0
        int pic_i;
4031
        //search reord-queue to get the future pictures
4032
0
        for (pic_i = 0; pic_i < num_future_pics; pic_i++) {
4033
0
            int32_t q_index = QUEUE_GET_NEXT_SPOT(
4034
0
                pcs->pic_decision_reorder_queue_idx, pic_i + 1, enc_ctx->picture_decision_reorder_queue_size);
4035
0
            if (enc_ctx->picture_decision_reorder_queue[q_index]->ppcs_wrapper != NULL) {
4036
0
                PictureParentControlSet* pcs_itr = (PictureParentControlSet*)enc_ctx
4037
0
                                                       ->picture_decision_reorder_queue[q_index]
4038
0
                                                       ->ppcs_wrapper->object_ptr;
4039
                // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4040
0
                if (pcs_itr->frame_width != pcs->frame_width || pcs_itr->frame_height != pcs->frame_height) {
4041
0
                    break;
4042
0
                }
4043
0
                pcs->temp_filt_pcs_list[pic_i + num_past_pics + 1] = pcs_itr;
4044
0
                actual_future_pics++;
4045
0
            } else {
4046
0
                break;
4047
0
            }
4048
0
        }
4049
4050
        //search in pre-ass if still short
4051
0
        if (pic_i < num_future_pics) {
4052
0
            for (int pic_i_future = pic_i; pic_i_future < num_future_pics; pic_i_future++) {
4053
0
                for (uint32_t pic_i_pa = 0; pic_i_pa < enc_ctx->pre_assignment_buffer_count; pic_i_pa++) {
4054
0
                    PictureParentControlSet* pcs_itr =
4055
0
                        (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_i_pa]->object_ptr;
4056
                    // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4057
0
                    if (pcs_itr->picture_number == pcs->picture_number + pic_i_future + 1 &&
4058
0
                        pcs_itr->frame_width == pcs->frame_width && pcs_itr->frame_height == pcs->frame_height) {
4059
0
                        pcs->temp_filt_pcs_list[pic_i_future + num_past_pics + 1] = pcs_itr;
4060
0
                        actual_future_pics++;
4061
0
                        break; //exist the pre-ass loop, go search the next
4062
0
                    }
4063
0
                }
4064
0
            }
4065
0
        }
4066
0
        pcs->past_altref_nframes   = actual_past_pics;
4067
0
        pcs->future_altref_nframes = actual_future_pics;
4068
4069
        // adjust the temporal filtering pcs buffer to remove unused past pictures
4070
0
        if (actual_past_pics != num_past_pics) {
4071
0
            pic_i = 0;
4072
0
            while (pcs->temp_filt_pcs_list[pic_i] != NULL) {
4073
0
                pcs->temp_filt_pcs_list[pic_i] = pcs->temp_filt_pcs_list[pic_i + num_past_pics - actual_past_pics];
4074
0
                pic_i++;
4075
0
            }
4076
0
        }
4077
0
    } else {
4078
0
        if (svt_aom_is_delayed_intra(pcs)) {
4079
            //initilize list
4080
0
            for (int pic_itr = 0; pic_itr < ALTREF_MAX_NFRAMES; pic_itr++) {
4081
0
                pcs->temp_filt_pcs_list[pic_itr] = NULL;
4082
0
            }
4083
4084
0
            pcs->temp_filt_pcs_list[0] = pcs;
4085
0
            uint32_t num_future_pics   = pcs->tf_ctrls.num_future_pics + (pcs->tf_ctrls.modulate_pics ? offset : 0);
4086
0
            num_future_pics            = MIN(pcs->tf_ctrls.max_num_future_pics, num_future_pics);
4087
            // Update the key frame pred structure;
4088
0
            int32_t idx = search_this_pic(pd_ctx->mg_pictures_array, pd_ctx->mg_size, pcs->picture_number + 1);
4089
4090
0
            if (centre_pcs->hierarchical_levels != pcs->temp_filt_pcs_list[0]->hierarchical_levels ||
4091
0
                centre_pcs->hierarchical_levels != pd_ctx->mg_pictures_array[idx]->hierarchical_levels) {
4092
0
                centre_pcs->hierarchical_levels = pcs->temp_filt_pcs_list[0]->hierarchical_levels =
4093
0
                    pd_ctx->mg_pictures_array[idx]->hierarchical_levels;
4094
0
            }
4095
0
            num_future_pics = MIN((uint8_t)num_future_pics,
4096
0
                                  svt_aom_tf_max_ref_per_struct(pcs->hierarchical_levels, 0, 1));
4097
0
            uint32_t pic_i;
4098
0
            for (pic_i = 0; pic_i < num_future_pics; pic_i++) {
4099
0
                int32_t idx_1 = search_this_pic(
4100
0
                    pd_ctx->mg_pictures_array, pd_ctx->mg_size, pcs->picture_number + pic_i + 1);
4101
0
                if (idx_1 >= 0) {
4102
                    // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4103
0
                    if (pd_ctx->mg_pictures_array[idx_1]->frame_width != pcs->frame_width ||
4104
0
                        pd_ctx->mg_pictures_array[idx_1]->frame_height != pcs->frame_height) {
4105
0
                        break;
4106
0
                    }
4107
0
                    pcs->temp_filt_pcs_list[pic_i + 1]                        = pd_ctx->mg_pictures_array[idx_1];
4108
0
                    uint8_t active_region_cnt                                 = 0;
4109
0
                    pd_ctx->mg_pictures_array[idx_1]->tf_ahd_error_to_central = calc_ahd(
4110
0
                        scs, pcs, pd_ctx->mg_pictures_array[idx_1], &active_region_cnt);
4111
0
                    pd_ctx->mg_pictures_array[idx_1]->tf_active_region_present = active_region_cnt > 0;
4112
0
                } else {
4113
0
                    break;
4114
0
                }
4115
0
            }
4116
4117
0
            pcs->past_altref_nframes   = 0;
4118
0
            pcs->future_altref_nframes = pic_i;
4119
0
        } else {
4120
0
            if (pcs->idr_flag) {
4121
                //initilize list
4122
0
                for (int pic_itr = 0; pic_itr < ALTREF_MAX_NFRAMES; pic_itr++) {
4123
0
                    pcs->temp_filt_pcs_list[pic_itr] = NULL;
4124
0
                }
4125
4126
0
                pcs->temp_filt_pcs_list[0] = pcs;
4127
0
                uint32_t num_future_pics   = pcs->tf_ctrls.num_future_pics + (pcs->tf_ctrls.modulate_pics ? offset : 0);
4128
0
                num_future_pics            = MIN(pcs->tf_ctrls.max_num_future_pics, num_future_pics);
4129
0
                num_future_pics            = MIN((uint8_t)num_future_pics,
4130
0
                                      svt_aom_tf_max_ref_per_struct(pcs->hierarchical_levels, 0, 1));
4131
0
                uint32_t num_past_pics     = 0;
4132
0
                uint32_t pic_i;
4133
                //search reord-queue to get the future pictures
4134
0
                for (pic_i = 0; pic_i < num_future_pics; pic_i++) {
4135
0
                    int32_t q_index = QUEUE_GET_NEXT_SPOT(
4136
0
                        pcs->pic_decision_reorder_queue_idx, pic_i + 1, enc_ctx->picture_decision_reorder_queue_size);
4137
0
                    if (enc_ctx->picture_decision_reorder_queue[q_index]->ppcs_wrapper != NULL) {
4138
0
                        PictureParentControlSet* pcs_itr = (PictureParentControlSet*)enc_ctx
4139
0
                                                               ->picture_decision_reorder_queue[q_index]
4140
0
                                                               ->ppcs_wrapper->object_ptr;
4141
                        // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4142
0
                        if (pcs_itr->frame_width != pcs->frame_width || pcs_itr->frame_height != pcs->frame_height) {
4143
0
                            break;
4144
0
                        }
4145
0
                        pcs->temp_filt_pcs_list[pic_i + num_past_pics + 1] = pcs_itr;
4146
0
                        uint8_t active_region_cnt                          = 0;
4147
0
                        pcs_itr->tf_ahd_error_to_central  = calc_ahd(scs, pcs, pcs_itr, &active_region_cnt);
4148
0
                        pcs_itr->tf_active_region_present = active_region_cnt > 0;
4149
0
                    } else {
4150
0
                        break;
4151
0
                    }
4152
0
                }
4153
4154
0
                pcs->past_altref_nframes   = 0;
4155
0
                pcs->future_altref_nframes = pic_i;
4156
0
            }
4157
4158
0
            else {
4159
0
                int num_past_pics   = MAX(1, (int)pcs->tf_ctrls.num_past_pics + offset);
4160
0
                int num_future_pics = MAX(1, (int)pcs->tf_ctrls.num_future_pics + offset);
4161
0
                num_past_pics       = MIN(pcs->tf_ctrls.max_num_past_pics, num_past_pics);
4162
0
                num_future_pics     = MIN(pcs->tf_ctrls.max_num_future_pics, num_future_pics);
4163
0
                num_past_pics       = MIN(
4164
0
                    num_past_pics,
4165
0
                    svt_aom_tf_max_ref_per_struct(pcs->hierarchical_levels, pcs->temporal_layer_index ? 2 : 1, 0));
4166
0
                num_future_pics = MIN(
4167
0
                    num_future_pics,
4168
0
                    svt_aom_tf_max_ref_per_struct(pcs->hierarchical_levels, pcs->temporal_layer_index ? 2 : 1, 1));
4169
4170
                // Initialize list
4171
0
                for (int pic_itr = 0; pic_itr < ALTREF_MAX_NFRAMES; pic_itr++) {
4172
0
                    pcs->temp_filt_pcs_list[pic_itr] = NULL;
4173
0
                }
4174
                // limit the number of pictures to make sure there are enough pictures in the buffer. i.e. Intra CRA case
4175
                // limit the number of pictures to make sure there are enough pictures in the buffer. i.e. Intra CRA case
4176
0
                num_past_pics = MIN(
4177
0
                    num_past_pics,
4178
0
                    avail_past_pictures(pd_ctx->mg_pictures_array, pd_ctx->mg_size, pcs->picture_number));
4179
                // get previous+current pictures from the the pre-assign buffer
4180
0
                for (int pic_itr = 0; pic_itr <= num_past_pics; pic_itr++) {
4181
0
                    int32_t idx = search_this_pic(
4182
0
                        pd_ctx->mg_pictures_array, pd_ctx->mg_size, pcs->picture_number - num_past_pics + pic_itr);
4183
0
                    if (idx >= 0) {
4184
                        // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4185
0
                        if (pd_ctx->mg_pictures_array[idx]->frame_width != pcs->frame_width ||
4186
0
                            pd_ctx->mg_pictures_array[idx]->frame_height != pcs->frame_height) {
4187
0
                            break;
4188
0
                        }
4189
0
                        pcs->temp_filt_pcs_list[pic_itr]                        = pd_ctx->mg_pictures_array[idx];
4190
0
                        uint8_t active_region_cnt                               = 0;
4191
0
                        pd_ctx->mg_pictures_array[idx]->tf_ahd_error_to_central = calc_ahd(
4192
0
                            scs, pcs, pd_ctx->mg_pictures_array[idx], &active_region_cnt);
4193
0
                        pd_ctx->mg_pictures_array[idx]->tf_active_region_present = active_region_cnt > 0;
4194
0
                    }
4195
0
                }
4196
0
                int actual_past_pics   = num_past_pics;
4197
0
                int actual_future_pics = 0;
4198
0
                int pic_i;
4199
                //search reord-queue to get the future pictures
4200
0
                for (pic_i = 0; pic_i < num_future_pics; pic_i++) {
4201
0
                    int32_t q_index = QUEUE_GET_NEXT_SPOT(
4202
0
                        pcs->pic_decision_reorder_queue_idx, pic_i + 1, enc_ctx->picture_decision_reorder_queue_size);
4203
0
                    if (enc_ctx->picture_decision_reorder_queue[q_index]->ppcs_wrapper != NULL) {
4204
0
                        PictureParentControlSet* pcs_itr = (PictureParentControlSet*)enc_ctx
4205
0
                                                               ->picture_decision_reorder_queue[q_index]
4206
0
                                                               ->ppcs_wrapper->object_ptr;
4207
                        // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4208
0
                        if (pcs_itr->frame_width != pcs->frame_width || pcs_itr->frame_height != pcs->frame_height) {
4209
0
                            break;
4210
0
                        }
4211
0
                        pcs->temp_filt_pcs_list[pic_i + num_past_pics + 1] = pcs_itr;
4212
0
                        uint8_t active_region_cnt                          = 0;
4213
0
                        pcs_itr->tf_ahd_error_to_central  = calc_ahd(scs, pcs, pcs_itr, &active_region_cnt);
4214
0
                        pcs_itr->tf_active_region_present = active_region_cnt > 0;
4215
0
                        actual_future_pics++;
4216
0
                    } else {
4217
0
                        break;
4218
0
                    }
4219
0
                }
4220
4221
                //search in pre-ass if still short
4222
0
                if (pic_i < num_future_pics) {
4223
0
                    for (int pic_i_future = pic_i; pic_i_future < num_future_pics; pic_i_future++) {
4224
0
                        for (uint32_t pic_i_pa = 0; pic_i_pa < enc_ctx->pre_assignment_buffer_count; pic_i_pa++) {
4225
0
                            PictureParentControlSet* pcs_itr =
4226
0
                                (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_i_pa]->object_ptr;
4227
                            // if resolution has changed, and the pcs with new resolution should not be used in temporal filtering
4228
0
                            if (pcs_itr->picture_number == pcs->picture_number + pic_i_future + 1 &&
4229
0
                                pcs_itr->frame_width == pcs->frame_width &&
4230
0
                                pcs_itr->frame_height == pcs->frame_height) {
4231
0
                                pcs->temp_filt_pcs_list[pic_i_future + num_past_pics + 1] = pcs_itr;
4232
0
                                uint8_t active_region_cnt                                 = 0;
4233
0
                                pcs_itr->tf_ahd_error_to_central  = calc_ahd(scs, pcs, pcs_itr, &active_region_cnt);
4234
0
                                pcs_itr->tf_active_region_present = active_region_cnt > 0;
4235
0
                                actual_future_pics++;
4236
0
                                break; //exist the pre-ass loop, go search the next
4237
0
                            }
4238
0
                        }
4239
0
                    }
4240
0
                }
4241
0
                pcs->past_altref_nframes   = actual_past_pics;
4242
0
                pcs->future_altref_nframes = actual_future_pics;
4243
4244
                // adjust the temporal filtering pcs buffer to remove unused past pictures
4245
0
                if (actual_past_pics != num_past_pics) {
4246
0
                    pic_i = 0;
4247
0
                    while (pcs->temp_filt_pcs_list[pic_i] != NULL) {
4248
0
                        pcs->temp_filt_pcs_list[pic_i] =
4249
0
                            pcs->temp_filt_pcs_list[pic_i + num_past_pics - actual_past_pics];
4250
0
                        pic_i++;
4251
0
                    }
4252
0
                }
4253
0
            }
4254
0
        }
4255
4256
        // Calc the avg_ahd_error
4257
0
        centre_pcs->tf_avg_ahd_error = 0;
4258
0
        if (centre_pcs->past_altref_nframes + centre_pcs->future_altref_nframes) {
4259
0
            uint64_t tot_luma = 0;
4260
0
            int      tot_err  = 0;
4261
4262
0
            for (int i = 0; i < (centre_pcs->past_altref_nframes + centre_pcs->future_altref_nframes + 1); i++) {
4263
0
                if (i != centre_pcs->past_altref_nframes) {
4264
0
                    tot_luma += pcs->temp_filt_pcs_list[i]->avg_luma;
4265
0
                    tot_err += pcs->temp_filt_pcs_list[i]->tf_ahd_error_to_central;
4266
0
                }
4267
0
            }
4268
0
            centre_pcs->tf_avg_luma = tot_luma / (centre_pcs->past_altref_nframes + centre_pcs->future_altref_nframes);
4269
0
            centre_pcs->tf_avg_ahd_error = tot_err /
4270
0
                (centre_pcs->past_altref_nframes + centre_pcs->future_altref_nframes);
4271
0
        }
4272
0
    }
4273
0
    return EB_ErrorNone;
4274
0
}
4275
4276
/*
4277
store this input  picture to be used for TF-ing of upcoming base
4278
increment live count of the required ressources to be used by TF of upcoming base.
4279
will be released once TF is done
4280
*/
4281
static void low_delay_store_tf_pictures(SequenceControlSet* scs, PictureParentControlSet* pcs,
4282
0
                                        PictureDecisionContext* ctx) {
4283
0
    const uint32_t mg_size  = 1 << (IS_SFRAME_FLEXIBLE_INSERT(scs->static_config.sframe_mode)
4284
0
                                        ? (uint32_t)ctx->sframe_hier_lvls
4285
0
                                        : scs->static_config.hierarchical_levels);
4286
0
    const uint32_t tot_past = scs->tf_params_per_type[1].max_num_past_pics;
4287
0
    if (pcs->temporal_layer_index != 0 && pcs->pic_idx_in_mg + 1 + tot_past >= mg_size) {
4288
        //store this picture to be used for TF-ing upcoming base
4289
0
        ctx->tf_pic_array[ctx->tf_pic_arr_cnt++] = pcs;
4290
4291
        //increment live count of these ressources to be used by TF of upcoming base. will be released once TF is done.
4292
0
        svt_object_inc_live_count(pcs->p_pcs_wrapper_ptr, 1);
4293
0
        svt_object_inc_live_count(pcs->input_pic_wrapper, 1);
4294
0
        svt_object_inc_live_count(pcs->pa_ref_pic_wrapper, 1);
4295
0
        svt_object_inc_live_count(pcs->scs_wrapper, 1);
4296
0
        if (pcs->y8b_wrapper) {
4297
0
            svt_object_inc_live_count(pcs->y8b_wrapper, 1);
4298
0
        }
4299
0
    }
4300
0
}
4301
4302
/*
4303
 TF is done, release ressources and reset the tf picture buffer.
4304
*/
4305
0
static void low_delay_release_tf_pictures(PictureDecisionContext* ctx) {
4306
0
    for (uint32_t pic_it = 0; pic_it < ctx->tf_pic_arr_cnt; pic_it++) {
4307
0
        PictureParentControlSet* past_pcs = ctx->tf_pic_array[pic_it];
4308
4309
0
        svt_release_object(past_pcs->input_pic_wrapper);
4310
4311
0
        if (past_pcs->y8b_wrapper) {
4312
0
            svt_release_object(past_pcs->y8b_wrapper);
4313
0
        }
4314
4315
0
        svt_release_object(past_pcs->pa_ref_pic_wrapper);
4316
0
        svt_release_object(past_pcs->scs_wrapper);
4317
        //ppcs should be the last one to release
4318
0
        svt_release_object(past_pcs->p_pcs_wrapper_ptr);
4319
0
    }
4320
4321
0
    memset(ctx->tf_pic_array, 0, ctx->tf_pic_arr_cnt * sizeof(PictureParentControlSet*));
4322
0
    ctx->tf_pic_arr_cnt = 0;
4323
0
}
4324
4325
#if CONFIG_SINGLE_THREAD_KERNEL
4326
/*
4327
  Single-thread MCTF: run TF segments inline instead of dispatching to ME FIFO.
4328
*/
4329
0
static void mctf_frame_st(SequenceControlSet* scs, PictureParentControlSet* pcs) {
4330
0
    MotionEstimationContext_t* me_ctx_ptr = (MotionEstimationContext_t*)scs->enc_ctx->st_me_context;
4331
0
    me_ctx_ptr->me_ctx->me_type           = ME_MCTF;
4332
0
    svt_aom_sig_deriv_me_tf(pcs, me_ctx_ptr->me_ctx);
4333
0
    if (pcs->gm_ctrls.pp_enabled && pcs->gm_pp_enabled) {
4334
0
        svt_aom_gm_pre_processor(pcs, pcs->temp_filt_pcs_list);
4335
0
    }
4336
0
    for (int16_t seg_idx = 0; seg_idx < pcs->tf_segments_total_count; ++seg_idx) {
4337
0
        svt_av1_init_temporal_filtering(pcs->temp_filt_pcs_list, pcs, me_ctx_ptr, seg_idx);
4338
0
    }
4339
    // Consume the semaphore posted by svt_av1_init_temporal_filtering
4340
    // on the last segment (prevents assertion on semaphore disposal).
4341
0
    svt_block_on_semaphore(pcs->temp_filt_done_semaphore);
4342
0
}
4343
#endif
4344
4345
/*
4346
  Performs Motion Compensated Temporal Filtering in ME process
4347
*/
4348
431
static void mctf_frame(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
4349
431
    if (scs->static_config.pred_structure != RANDOM_ACCESS && scs->tf_params_per_type[1].enabled) {
4350
0
        low_delay_store_tf_pictures(scs, pcs, pd_ctx);
4351
0
    }
4352
431
    if (pcs->tf_ctrls.enabled) {
4353
0
        derive_tf_window_params(scs, scs->enc_ctx, pcs, pd_ctx);
4354
0
        pcs->temp_filt_prep_done = 0;
4355
0
        pcs->tf_tot_horz_blks = pcs->tf_tot_vert_blks = 0;
4356
4357
        // Start Filtering in ME processes
4358
0
        {
4359
            // Initialize Segments
4360
0
            pcs->tf_segments_column_count = scs->tf_segment_column_count;
4361
0
            pcs->tf_segments_row_count    = scs->tf_segment_row_count;
4362
0
            pcs->tf_segments_total_count  = (uint16_t)(pcs->tf_segments_column_count * pcs->tf_segments_row_count);
4363
0
            pcs->temp_filt_seg_acc        = 0;
4364
0
#if CONFIG_SINGLE_THREAD_KERNEL
4365
0
            if (scs->lp == 1) {
4366
0
                mctf_frame_st(scs, pcs);
4367
0
            } else
4368
0
#endif
4369
0
            {
4370
0
                for (int16_t seg_idx = 0; seg_idx < pcs->tf_segments_total_count; ++seg_idx) {
4371
0
                    EbObjectWrapper*        out_results_wrapper;
4372
0
                    PictureDecisionResults* out_results;
4373
4374
0
                    svt_get_empty_object(pd_ctx->picture_decision_results_output_fifo_ptr, &out_results_wrapper);
4375
0
                    out_results                = (PictureDecisionResults*)out_results_wrapper->object_ptr;
4376
0
                    out_results->pcs_wrapper   = pcs->p_pcs_wrapper_ptr;
4377
0
                    out_results->segment_index = seg_idx;
4378
0
                    out_results->task_type     = 1;
4379
0
                    svt_post_full_object(out_results_wrapper);
4380
0
                }
4381
4382
0
                svt_block_on_semaphore(pcs->temp_filt_done_semaphore);
4383
0
            }
4384
0
        }
4385
4386
0
        if (pcs->tf_tot_horz_blks > pcs->tf_tot_vert_blks * 6 / 4) {
4387
0
            pd_ctx->tf_motion_direction = 0;
4388
0
        } else if (pcs->tf_tot_vert_blks > pcs->tf_tot_horz_blks * 6 / 4) {
4389
0
            pd_ctx->tf_motion_direction = 1;
4390
0
        } else {
4391
0
            pd_ctx->tf_motion_direction = -1;
4392
0
        }
4393
431
    } else {
4394
431
        pcs->do_tf = false; // set temporal filtering flag OFF for current picture
4395
431
    }
4396
4397
431
    pcs->is_noise_level = (pd_ctx->last_i_noise_levels_log1p_fp16[0] >= VQ_NOISE_LVL_TH);
4398
4399
431
    if (scs->static_config.pred_structure != RANDOM_ACCESS && scs->tf_params_per_type[1].enabled &&
4400
0
        pcs->temporal_layer_index == 0) {
4401
0
        low_delay_release_tf_pictures(pd_ctx);
4402
0
    }
4403
431
}
4404
4405
431
bool get_similar_ref_brightness(PictureParentControlSet* pcs) {
4406
431
    bool similar_brightness_refs = false;
4407
431
    if (pcs->slice_type == B_SLICE && pcs->hierarchical_levels > 0 && pcs->ref_list1_count_try > 0) {
4408
0
        EbPaReferenceObject* ref_obj_0 = (EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[0][0]->object_ptr;
4409
0
        EbPaReferenceObject* ref_obj_1 = (EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[1][0]->object_ptr;
4410
0
        if (ref_obj_0->avg_luma != INVALID_LUMA && ref_obj_1->avg_luma != INVALID_LUMA) {
4411
0
            const int32_t luma_th = 5;
4412
0
            if (ABS((int)ref_obj_0->avg_luma - (int)pcs->avg_luma) < luma_th &&
4413
0
                ABS((int)ref_obj_1->avg_luma - (int)pcs->avg_luma) < luma_th) {
4414
0
                similar_brightness_refs = true;
4415
0
            }
4416
0
        }
4417
0
    }
4418
4419
431
    return similar_brightness_refs;
4420
431
}
4421
4422
431
static void send_picture_out(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4423
431
    EbObjectWrapper* me_wrapper;
4424
431
    EbObjectWrapper* out_results_wrapper;
4425
4426
    //every picture enherits latest motion direction from TF
4427
431
    pcs->tf_motion_direction = ctx->tf_motion_direction;
4428
431
    MrpCtrls* mrp_ctrl       = &(scs->mrp_ctrls);
4429
4430
431
#if OPT_MRP_HME_L0_DETECT
4431
431
    if (scs->static_config.rtc && mrp_ctrl->early_hme_l0_prune_th && pcs->ref_list0_count_try > 1) {
4432
0
        if (scs->use_flat_ipp) {
4433
0
            EbPictureBufferDesc* ref_last_ds =
4434
0
                ((EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[0][0]->object_ptr)->sixteenth_downsampled_picture_ptr;
4435
0
            EbPictureBufferDesc* ref_last2_ds =
4436
0
                ((EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[0][1]->object_ptr)->sixteenth_downsampled_picture_ptr;
4437
0
            uint64_t last_dist  = mrp_detector_hme_level0(pcs, ref_last_ds);
4438
0
            uint64_t last2_dist = mrp_detector_hme_level0(pcs, ref_last2_ds);
4439
            // Prune LAST2 when it is >= early_hme_l0_prune_th% worse than LAST.
4440
0
            if (last2_dist * 100 >= last_dist * mrp_ctrl->early_hme_l0_prune_th) {
4441
0
                pcs->ref_list0_count_try = MIN(pcs->ref_list0_count_try, 1);
4442
0
                set_all_ref_frame_type(ctx, pcs, pcs->ref_frame_type_arr, &pcs->tot_ref_frame_types);
4443
0
            }
4444
0
        } else {
4445
0
            if (pcs->temporal_layer_index == 0 && pcs->ref_list0_count_try >= 3) {
4446
0
                EbPictureBufferDesc* ref_last_ds = ((EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[0][0]->object_ptr)
4447
0
                                                       ->sixteenth_downsampled_picture_ptr;
4448
0
                EbPictureBufferDesc* ref_last3_ds = ((EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[0][2]->object_ptr)
4449
0
                                                        ->sixteenth_downsampled_picture_ptr;
4450
0
                uint64_t last_dist  = mrp_detector_hme_level0(pcs, ref_last_ds);
4451
0
                uint64_t last3_dist = mrp_detector_hme_level0(pcs, ref_last3_ds);
4452
                // Prune LAST3 when it is >= early_hme_l0_prune_th% worse than LAST.
4453
0
                if (last3_dist * 100 >= last_dist * mrp_ctrl->early_hme_l0_prune_th) {
4454
0
                    pcs->ref_list0_count_try = MIN(pcs->ref_list0_count_try, 2);
4455
0
                    set_all_ref_frame_type(ctx, pcs, pcs->ref_frame_type_arr, &pcs->tot_ref_frame_types);
4456
0
                }
4457
0
            }
4458
0
        }
4459
0
    }
4460
431
#endif
4461
431
    pcs->similar_brightness_refs = get_similar_ref_brightness(pcs);
4462
431
    if (scs->mrp_ctrls.safe_limit_nref == 2 && pcs->slice_type == B_SLICE && pcs->hierarchical_levels > 0 &&
4463
0
        (pcs->temporal_layer_index >= pcs->hierarchical_levels - 1)) {
4464
0
        if (pcs->similar_brightness_refs) {
4465
            // TODO: The ref list counts should not be updated after set_all_ref_frame_type()
4466
0
            pcs->ref_list0_count_try = MIN(pcs->ref_list0_count_try, 1);
4467
0
            pcs->ref_list1_count_try = MIN(pcs->ref_list1_count_try, 1);
4468
0
        }
4469
0
    }
4470
    //get a new ME data buffer
4471
431
    if (pcs->me_data_wrapper == NULL) {
4472
431
        svt_get_empty_object(ctx->me_fifo_ptr, &me_wrapper);
4473
431
        pcs->me_data_wrapper = me_wrapper;
4474
431
        pcs->pa_me_data      = (MotionEstimationData*)me_wrapper->object_ptr;
4475
431
        me_update_param(pcs->pa_me_data, scs);
4476
431
    }
4477
4478
431
#if TUNE_SIMPLIFY_SETTINGS
4479
431
    uint8_t ref_count_used_list0 = MAX(mrp_ctrl->base_ref_list0_count, mrp_ctrl->non_base_ref_list0_count);
4480
431
    uint8_t ref_count_used_list1 = MAX(mrp_ctrl->base_ref_list1_count, mrp_ctrl->non_base_ref_list1_count);
4481
#else
4482
    uint8_t ref_count_used_list0 = MAX(
4483
        mrp_ctrl->sc_base_ref_list0_count,
4484
        MAX(mrp_ctrl->base_ref_list0_count,
4485
            MAX(mrp_ctrl->sc_non_base_ref_list0_count, mrp_ctrl->non_base_ref_list0_count)));
4486
    uint8_t ref_count_used_list1 = MAX(
4487
        mrp_ctrl->sc_base_ref_list1_count,
4488
        MAX(mrp_ctrl->base_ref_list1_count,
4489
            MAX(mrp_ctrl->sc_non_base_ref_list1_count, mrp_ctrl->non_base_ref_list1_count)));
4490
#endif
4491
4492
431
    uint8_t max_ref_to_alloc, max_cand_to_alloc;
4493
4494
431
    svt_aom_get_max_allocated_me_refs(
4495
431
        ref_count_used_list0, ref_count_used_list1, &max_ref_to_alloc, &max_cand_to_alloc);
4496
4497
431
    pcs->pa_me_data->max_cand = max_cand_to_alloc;
4498
431
    pcs->pa_me_data->max_refs = max_ref_to_alloc;
4499
431
    pcs->pa_me_data->max_l0   = ref_count_used_list0;
4500
4501
    //****************************************************
4502
    // Picture resizing for super-res tool
4503
    //****************************************************
4504
4505
    // Scale picture if super-res is used
4506
    // Handle SUPERRES_FIXED and SUPERRES_RANDOM modes here.
4507
    // SUPERRES_QTHRESH and SUPERRES_AUTO modes are handled in rate control process because these modes depend on qindex
4508
431
    if (scs->static_config.pass == ENC_SINGLE_PASS) {
4509
431
        if (scs->static_config.resize_mode > RESIZE_NONE || scs->static_config.superres_mode == SUPERRES_FIXED ||
4510
431
            scs->static_config.superres_mode == SUPERRES_RANDOM) {
4511
0
            svt_aom_init_resize_picture(scs, pcs);
4512
0
        }
4513
431
    }
4514
431
    bool super_res_off = pcs->frame_superres_enabled == false && scs->static_config.resize_mode == RESIZE_NONE;
4515
431
    svt_aom_set_gm_controls(pcs, svt_aom_derive_gm_level(pcs, super_res_off));
4516
431
    pcs->me_processed_b64_count = 0;
4517
4518
    // NB: overlay frames should be non-ref
4519
    // Before sending pics out to pic mgr, ensure that pic mgr can handle them
4520
431
    if (pcs->is_ref) {
4521
0
#if CONFIG_SINGLE_THREAD_KERNEL
4522
        // In ST mode, ref buffer availability is guaranteed by the pool pump
4523
        // in svt_get_empty_object. Skip the semaphore to avoid imbalance at shutdown.
4524
0
        if (scs->lp != 1)
4525
0
#endif
4526
0
            svt_block_on_semaphore(scs->ref_buffer_available_semaphore);
4527
0
    }
4528
4529
862
    for (uint32_t segment_index = 0; segment_index < pcs->me_segments_total_count; ++segment_index) {
4530
        // Get Empty Results Object
4531
431
        svt_get_empty_object(ctx->picture_decision_results_output_fifo_ptr, &out_results_wrapper);
4532
4533
431
        PictureDecisionResults* out_results = (PictureDecisionResults*)out_results_wrapper->object_ptr;
4534
431
        out_results->pcs_wrapper            = pcs->p_pcs_wrapper_ptr;
4535
431
        out_results->segment_index          = segment_index;
4536
431
        out_results->task_type              = TASK_PAME;
4537
        //Post the Full Results Object
4538
431
        svt_post_full_object(out_results_wrapper);
4539
431
    }
4540
431
}
4541
4542
/***************************************************************************************************
4543
* Store the pcs pointers in the gf group, set the gf_interval and gf_update_due
4544
***************************************************************************************************/
4545
431
void store_gf_group(PictureParentControlSet* pcs, PictureDecisionContext* ctx, uint32_t mg_size) {
4546
431
    if (pcs->slice_type == I_SLICE || (!svt_aom_is_delayed_intra(pcs) && pcs->temporal_layer_index == 0) ||
4547
431
        svt_aom_is_incomp_mg_frame(pcs)) {
4548
431
        if (svt_aom_is_delayed_intra(pcs)) {
4549
0
            pcs->gf_group[0] = pcs;
4550
0
            svt_memcpy(&pcs->gf_group[1], ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
4551
0
            pcs->gf_interval = 1 + mg_size;
4552
431
        } else {
4553
431
            if (svt_aom_is_incomp_mg_frame(pcs) && mg_size > 0 && ctx->mg_pictures_array[mg_size - 1]->idr_flag) {
4554
0
                mg_size = MAX(0, (int)mg_size - 1);
4555
0
            }
4556
431
            svt_memcpy(&pcs->gf_group[0], ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
4557
431
            pcs->gf_interval = mg_size;
4558
431
        }
4559
4560
431
        if (pcs->slice_type == I_SLICE && pcs->end_of_sequence_flag) {
4561
0
            pcs->gf_interval = 1;
4562
0
            pcs->gf_group[0] = pcs;
4563
0
        }
4564
4565
862
        for (int pic_i = 0; pic_i < pcs->gf_interval; ++pic_i) {
4566
431
            if (pcs->gf_group[pic_i]->slice_type == I_SLICE ||
4567
0
                (!svt_aom_is_delayed_intra(pcs) && pcs->gf_group[pic_i]->temporal_layer_index == 0) ||
4568
431
                svt_aom_is_incomp_mg_frame(pcs->gf_group[pic_i])) {
4569
431
                pcs->gf_group[pic_i]->gf_update_due = 1;
4570
431
            } else {
4571
0
                pcs->gf_group[pic_i]->gf_update_due = 0;
4572
0
            }
4573
4574
            // For P picture that come after I, we need to set the gf_group pictures. It is used later in RC
4575
431
            if (pcs->slice_type == I_SLICE && svt_aom_is_incomp_mg_frame(pcs->gf_group[pic_i]) &&
4576
0
                pcs->picture_number < pcs->gf_group[pic_i]->picture_number) {
4577
0
                pcs->gf_group[pic_i]->gf_interval = pcs->gf_interval - 1;
4578
0
                svt_memcpy(&pcs->gf_group[pic_i]->gf_group[0],
4579
0
                           &ctx->mg_pictures_array[1],
4580
0
                           pcs->gf_group[pic_i]->gf_interval * sizeof(PictureParentControlSet*));
4581
0
                pcs->gf_group[pic_i]->gf_update_due = 0;
4582
0
            }
4583
431
        }
4584
431
    }
4585
431
}
4586
4587
#if LAD_MG_PRINT
4588
/* prints content of pre-assignment buffer */
4589
void print_pre_ass_buffer(EncodeContext* ctx, PictureParentControlSet* pcs, uint8_t log) {
4590
    if (log) {
4591
        if (ctx->pre_assignment_buffer_intra_count > 0) {
4592
            SVT_LOG(
4593
                "PRE-ASSIGN INTRA   (%i pictures)  POC:%lld \n", ctx->pre_assignment_buffer_count, pcs->picture_number);
4594
        }
4595
        if (ctx->pre_assignment_buffer_count == (uint32_t)(1 << pcs->scs->static_config.hierarchical_levels)) {
4596
            SVT_LOG("PRE-ASSIGN COMPLETE   (%i pictures)  POC:%lld \n",
4597
                    ctx->pre_assignment_buffer_count,
4598
                    pcs->picture_number);
4599
        }
4600
        if (ctx->pre_assignment_buffer_eos_flag == 1) {
4601
            SVT_LOG(
4602
                "PRE-ASSIGN EOS   (%i pictures)  POC:%lld \n", ctx->pre_assignment_buffer_count, pcs->picture_number);
4603
        }
4604
        if (pcs->pred_structure == LOW_DELAY) {
4605
            SVT_LOG(
4606
                "PRE-ASSIGN LD   (%i pictures)  POC:%lld \n", ctx->pre_assignment_buffer_count, pcs->picture_number);
4607
        }
4608
4609
        SVT_LOG("\n Pre-Assign(%i):  ", ctx->pre_assignment_buffer_count);
4610
        for (uint32_t pic = 0; pic < ctx->pre_assignment_buffer_count; pic++) {
4611
            PictureParentControlSet* pcs = (PictureParentControlSet*)ctx->pre_assignment_buffer[pic]->object_ptr;
4612
            SVT_LOG("%ld ", pcs->picture_number);
4613
        }
4614
        SVT_LOG("\n");
4615
    }
4616
}
4617
#endif
4618
4619
0
static PaReferenceEntry* search_ref_in_ref_queue_pa(EncodeContext* enc_ctx, uint64_t ref_poc) {
4620
0
    PaReferenceEntry* ref_entry_ptr = NULL;
4621
0
    for (uint8_t i = 0; i < REF_FRAMES; i++) {
4622
0
        ref_entry_ptr = enc_ctx->pd_dpb[i];
4623
4624
0
        if (ref_entry_ptr && ref_entry_ptr->picture_number == ref_poc) {
4625
0
            return ref_entry_ptr;
4626
0
        }
4627
0
    }
4628
4629
0
    return NULL;
4630
0
}
4631
4632
/*
4633
 * Copy TF params: scs -> pcs
4634
 */
4635
431
static void copy_tf_params(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4636
    // Map TF settings scs -> pcs
4637
431
    if (scs->static_config.pred_structure == LOW_DELAY) {
4638
0
        if (pcs->slice_type != I_SLICE && pcs->temporal_layer_index == 0) {
4639
0
            pcs->tf_ctrls = scs->tf_params_per_type[1];
4640
0
        } else {
4641
0
            pcs->tf_ctrls.enabled = 0;
4642
0
        }
4643
        // When the hierarchical level reaches zero during flexible S-Frame insertion, tf_pic_arr_cnt is reset to zero upon mini-GOP closure.
4644
        // Add additional protection for TF handling.
4645
0
        if (IS_SFRAME_FLEXIBLE_INSERT(scs->static_config.sframe_mode) && pcs->tf_ctrls.enabled &&
4646
0
            ctx->tf_pic_arr_cnt == 0) {
4647
0
            pcs->tf_ctrls.enabled = 0;
4648
0
        }
4649
4650
0
        return;
4651
0
    }
4652
    // Don't perform TF for overlay pics or pics in the highest layer (relevant for 2L)
4653
431
    if ((pcs->frm_hdr.frame_type == KEY_FRAME && !scs->static_config.enable_tf_key) || pcs->is_overlay ||
4654
431
        pcs->temporal_layer_index == pcs->hierarchical_levels) {
4655
0
        pcs->tf_ctrls.enabled = 0;
4656
431
    } else if (svt_aom_is_delayed_intra(pcs)) {
4657
0
        pcs->tf_ctrls = scs->tf_params_per_type[0];
4658
431
    } else if (pcs->temporal_layer_index == 0) { // BASE
4659
431
        pcs->tf_ctrls = scs->tf_params_per_type[1];
4660
431
    } else if (pcs->temporal_layer_index == 1) { // L1
4661
0
        pcs->tf_ctrls = scs->tf_params_per_type[2];
4662
0
    } else {
4663
0
        pcs->tf_ctrls.enabled = 0;
4664
0
    }
4665
431
}
4666
4667
void svt_aom_is_screen_content(PictureParentControlSet* pcs);
4668
void svt_aom_is_screen_content_antialiasing_aware(PictureParentControlSet* pcs);
4669
4670
/*
4671
* Update the list0 count try and the list1 count try based on the Enc-Mode, whether BASE or not, whether SC or not
4672
*/
4673
431
void update_count_try(SequenceControlSet* scs, PictureParentControlSet* pcs) {
4674
431
    MrpCtrls* mrp_ctrl = &scs->mrp_ctrls;
4675
431
#if TUNE_SIMPLIFY_SETTINGS
4676
431
    if (pcs->temporal_layer_index == 0) {
4677
431
        pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->base_ref_list0_count);
4678
431
        pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->base_ref_list1_count);
4679
431
    } else {
4680
0
        pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->non_base_ref_list0_count);
4681
0
        pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->non_base_ref_list1_count);
4682
0
    }
4683
#else
4684
    if (pcs->sc_class1) {
4685
        if (pcs->temporal_layer_index == 0) {
4686
            pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->sc_base_ref_list0_count);
4687
            pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->sc_base_ref_list1_count);
4688
        } else {
4689
            pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->sc_non_base_ref_list0_count);
4690
            pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->sc_non_base_ref_list1_count);
4691
        }
4692
    } else {
4693
        if (pcs->temporal_layer_index == 0) {
4694
            pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->base_ref_list0_count);
4695
            pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->base_ref_list1_count);
4696
        } else {
4697
            pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->non_base_ref_list0_count);
4698
            pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->non_base_ref_list1_count);
4699
        }
4700
    }
4701
#endif
4702
431
}
4703
4704
/*
4705
* Switch frame's pcs->dpb_order_hint[8] will be packed to uncompressed_header as ref_order_hint[8], ref to spec 5.9.2.
4706
*/
4707
0
static void update_sframe_ref_order_hint(PictureParentControlSet* ppcs, PictureDecisionContext* pd_ctx) {
4708
0
    assert(sizeof(ppcs->dpb_order_hint) == sizeof(pd_ctx->ref_order_hint));
4709
0
    if (ppcs->pred_structure == LOW_DELAY) {
4710
0
        for (int32_t i = 0; i < REF_FRAMES; i++) {
4711
            // dpd_order_hint should be updated with relative position of key frame
4712
0
            ppcs->dpb_order_hint[i] = (uint32_t)(pd_ctx->ref_order_hint[i] - pd_ctx->key_poc);
4713
0
        }
4714
0
    } else {
4715
0
        memcpy(ppcs->dpb_order_hint, pd_ctx->ref_order_hint, sizeof(ppcs->dpb_order_hint));
4716
0
    }
4717
0
    if (ppcs->av1_ref_signal.refresh_frame_mask != 0) {
4718
0
        const uint32_t cur_order_hint = ppcs->picture_number %
4719
0
            ((uint64_t)1 << (ppcs->scs->seq_header.order_hint_info.order_hint_bits));
4720
0
        for (int32_t i = 0; i < REF_FRAMES; i++) {
4721
0
            if ((ppcs->av1_ref_signal.refresh_frame_mask >> i) & 1) {
4722
0
                pd_ctx->ref_order_hint[i] = cur_order_hint;
4723
0
            }
4724
0
        }
4725
0
    }
4726
0
}
4727
4728
/*****************************************************************
4729
* Update the RC param queue
4730
* Set the size of the previous Gop/param, Check if all the frames in gop are processed, if yes reset
4731
* Increament the head index to assign a new spot in the queue for the new gop
4732
*****************************************************************/
4733
431
static void update_rc_param_queue(PictureParentControlSet* ppcs, EncodeContext* enc_cxt) {
4734
431
    if (ppcs->idr_flag == true && ppcs->picture_number > 0) {
4735
0
        svt_block_on_mutex(enc_cxt->rc_param_queue_mutex);
4736
        // Set the size of the previous Gop/param
4737
0
        enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size =
4738
0
            (int32_t)(ppcs->picture_number - enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->first_poc);
4739
        // Check if all the frames in gop are processed, if yes reset
4740
0
        if (enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size ==
4741
0
            enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->processed_frame_number) {
4742
0
            enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size                   = -1;
4743
0
            enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->processed_frame_number = 0;
4744
0
        }
4745
        // Increament the head index to assign a new spot in the queue for the new gop
4746
0
        enc_cxt->rc_param_queue_head_index = (enc_cxt->rc_param_queue_head_index == PARALLEL_GOP_MAX_NUMBER - 1)
4747
0
            ? 0
4748
0
            : enc_cxt->rc_param_queue_head_index + 1;
4749
0
        svt_aom_assert_err(enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size == -1,
4750
0
                           "The head in rc paramqueue is not empty");
4751
0
        enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->first_poc = ppcs->picture_number;
4752
0
        svt_release_mutex(enc_cxt->rc_param_queue_mutex);
4753
0
    }
4754
    // Store the pointer to the right spot in the RC param queue under PCS
4755
431
    ppcs->rate_control_param_ptr = enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index];
4756
431
}
4757
4758
/****************************************************************************************
4759
* set_layer_depth()
4760
* Set the layer depth per frame based on frame type, temporal layer
4761
****************************************************************************************/
4762
431
static void set_layer_depth(PictureParentControlSet* ppcs) {
4763
    // SequenceControlSet *scs = ppcs->scs;
4764
431
    if (ppcs->frm_hdr.frame_type == KEY_FRAME) {
4765
431
        ppcs->layer_depth = 0;
4766
431
    } else {
4767
0
        ppcs->layer_depth = ppcs->temporal_layer_index + 1;
4768
0
    }
4769
431
}
4770
4771
/****************************************************************************************
4772
* set_frame_update_type()
4773
* Set the update type per frame based on frame type, temporal layer and prediction structure
4774
* For Low delay, there is a special case where all non key frames are treated as LF_UPDATE.
4775
* Every MAX_GF_INTERVAL frames, update type is set to GF_UPDATE
4776
****************************************************************************************/
4777
431
static void set_frame_update_type(PictureParentControlSet* ppcs) {
4778
431
    SequenceControlSet* scs = ppcs->scs;
4779
431
    if (ppcs->frm_hdr.frame_type == KEY_FRAME) {
4780
431
        ppcs->update_type = SVT_AV1_KF_UPDATE;
4781
431
    } else if (scs->max_temporal_layers > 0 && ppcs->pred_structure != LOW_DELAY) {
4782
0
        if (ppcs->temporal_layer_index == 0) {
4783
0
            ppcs->update_type = SVT_AV1_ARF_UPDATE;
4784
0
        } else if (ppcs->temporal_layer_index == ppcs->hierarchical_levels) {
4785
0
            ppcs->update_type = SVT_AV1_LF_UPDATE;
4786
0
        } else {
4787
0
            ppcs->update_type = SVT_AV1_INTNL_ARF_UPDATE;
4788
0
        }
4789
0
    } else if (ppcs->pred_structure == LOW_DELAY && (ppcs->frame_offset % MAX_GF_INTERVAL) == 0) {
4790
0
        ppcs->update_type = SVT_AV1_GF_UPDATE;
4791
0
    } else {
4792
0
        ppcs->update_type = SVT_AV1_LF_UPDATE;
4793
0
    }
4794
431
}
4795
4796
431
static void set_gf_group_param(PictureParentControlSet* ppcs) {
4797
431
    set_frame_update_type(ppcs);
4798
431
    set_layer_depth(ppcs);
4799
431
}
4800
4801
0
static void process_first_pass(SequenceControlSet* scs, EncodeContext* enc_ctx) {
4802
0
    for (unsigned int window_index = 0; window_index < scs->scd_delay + 1; window_index++) {
4803
0
        unsigned int entry_index = QUEUE_GET_NEXT_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4804
0
                                                       window_index,
4805
0
                                                       enc_ctx->picture_decision_reorder_queue_size);
4806
0
        PictureDecisionReorderEntry* first_pass_queue_entry = enc_ctx->picture_decision_reorder_queue[entry_index];
4807
0
        if (first_pass_queue_entry->ppcs_wrapper == NULL) {
4808
0
            break;
4809
0
        }
4810
4811
0
        PictureParentControlSet* first_pass_pcs = (PictureParentControlSet*)
4812
0
                                                      first_pass_queue_entry->ppcs_wrapper->object_ptr;
4813
0
        if (!first_pass_pcs->first_pass_done) {
4814
0
            first_pass_frame_end_one_pass(first_pass_pcs);
4815
0
            first_pass_pcs->first_pass_done = 1;
4816
0
        }
4817
0
    }
4818
0
}
4819
4820
// Check if have enough frames to do scene change detection or if the EOS has been reached
4821
static void check_window_availability(SequenceControlSet* scs, EncodeContext* enc_ctx, PictureParentControlSet* pcs,
4822
431
                                      PictureDecisionReorderEntry* queue_entry, bool* window_avail, bool* eos_reached) {
4823
431
    *eos_reached  = ((PictureParentControlSet*)(queue_entry->ppcs_wrapper->object_ptr))->end_of_sequence_flag == true;
4824
431
    *window_avail = true;
4825
4826
431
    unsigned int previous_entry_index = QUEUE_GET_PREVIOUS_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4827
431
                                                                enc_ctx->picture_decision_reorder_queue_size);
4828
431
    memset(pcs->pd_window, 0, (2 + scs->scd_delay) * sizeof(PictureParentControlSet*));
4829
    //for poc 0, ignore previous frame check
4830
431
    if (queue_entry->picture_number > 0 &&
4831
0
        enc_ctx->picture_decision_reorder_queue[previous_entry_index]->ppcs_wrapper == NULL) {
4832
0
        *window_avail = false;
4833
431
    } else {
4834
        //TODO: risk of a race condition accessing prev(pcs0 is released, and pcs1 still doing sc).
4835
        //Actually we don't need to keep prev, just keep previous copy of histograms.
4836
431
        pcs->pd_window[0] = queue_entry->picture_number > 0
4837
431
            ? (PictureParentControlSet*)enc_ctx->picture_decision_reorder_queue[previous_entry_index]
4838
0
                  ->ppcs_wrapper->object_ptr
4839
431
            : NULL;
4840
431
        pcs->pd_window[1] = (PictureParentControlSet*)enc_ctx
4841
431
                                ->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index]
4842
431
                                ->ppcs_wrapper->object_ptr;
4843
431
        for (unsigned int window_index = 0; window_index < scs->scd_delay; window_index++) {
4844
0
            unsigned int entry_index = QUEUE_GET_NEXT_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4845
0
                                                           window_index + 1,
4846
0
                                                           enc_ctx->picture_decision_reorder_queue_size);
4847
0
            if (enc_ctx->picture_decision_reorder_queue[entry_index]->ppcs_wrapper == NULL) {
4848
0
                *window_avail = false;
4849
0
                break;
4850
0
            } else if (((PictureParentControlSet*)(enc_ctx->picture_decision_reorder_queue[entry_index]
4851
0
                                                       ->ppcs_wrapper->object_ptr))
4852
0
                           ->end_of_sequence_flag == true) {
4853
0
                *window_avail = false;
4854
0
                *eos_reached  = true;
4855
0
                break;
4856
0
            } else {
4857
0
                pcs->pd_window[2 + window_index] = (PictureParentControlSet*)enc_ctx
4858
0
                                                       ->picture_decision_reorder_queue[entry_index]
4859
0
                                                       ->ppcs_wrapper->object_ptr;
4860
0
            }
4861
0
        }
4862
431
    }
4863
431
}
4864
4865
// Perform scene change detection and update relevant signals
4866
static void perform_scene_change_detection(SequenceControlSet* scs, PictureParentControlSet* pcs,
4867
0
                                           PictureDecisionContext* ctx) {
4868
0
    if (scs->static_config.scene_change_detection) {
4869
0
        pcs->scene_change_flag = scene_transition_detector(ctx, scs, (PictureParentControlSet**)pcs->pd_window);
4870
4871
0
    } else {
4872
0
        pcs->scene_change_flag = false;
4873
4874
0
        if (scs->vq_ctrls.sharpness_ctrls.scene_transition &&
4875
0
            (ctx->transition_detected == -1 || ctx->transition_detected == 0)) {
4876
0
            ctx->transition_detected = scene_transition_detector(ctx, scs, (PictureParentControlSet**)pcs->pd_window);
4877
0
        }
4878
0
    }
4879
4880
0
    pcs->cra_flag = (pcs->scene_change_flag == true) ? true : pcs->cra_flag;
4881
4882
    // Store scene change in context
4883
0
    ctx->is_scene_change_detected = pcs->scene_change_flag;
4884
0
}
4885
4886
// Copy current pic's histogram to temporary buffer to be used by next input pic (N + 1) for scene change detection
4887
0
static void copy_histograms(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4888
0
    for (unsigned int region_in_picture_width_index = 0; region_in_picture_width_index < MAX_NUMBER_OF_REGIONS_IN_WIDTH;
4889
0
         region_in_picture_width_index++) {
4890
0
        for (unsigned int region_in_picture_height_index = 0;
4891
0
             region_in_picture_height_index < MAX_NUMBER_OF_REGIONS_IN_HEIGHT;
4892
0
             region_in_picture_height_index++) {
4893
0
            svt_memcpy(&(ctx->prev_picture_histogram[region_in_picture_width_index][region_in_picture_height_index][0]),
4894
0
                       &(pcs->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][0]),
4895
0
                       HISTOGRAM_NUMBER_OF_BINS * sizeof(uint32_t));
4896
4897
0
            ctx->prev_average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index] =
4898
0
                pcs->average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index];
4899
0
        }
4900
0
    }
4901
0
}
4902
4903
// Decide what mini-gop sizes to use and init the relevant fields
4904
static void set_mini_gop_structure(SequenceControlSet* scs, EncodeContext* enc_ctx, PictureParentControlSet* pcs,
4905
431
                                   PictureDecisionContext* ctx) {
4906
431
    uint32_t next_mg_hierarchical_levels = scs->static_config.hierarchical_levels;
4907
    // Overwrite next_mg_hierarchical_levels when an S-Frame needs to modify the mini-GOP size.
4908
431
    if (ctx->sframe_hier_lvls != (int32_t)scs->static_config.hierarchical_levels) {
4909
0
        next_mg_hierarchical_levels = ctx->sframe_hier_lvls;
4910
0
    }
4911
431
    if (ctx->enable_startup_mg) {
4912
0
        next_mg_hierarchical_levels = scs->static_config.startup_mg_size;
4913
0
    }
4914
    // Initialize Picture Block Params
4915
431
    ctx->mini_gop_start_index[0] = 0;
4916
431
    ctx->mini_gop_end_index[0]   = enc_ctx->pre_assignment_buffer_count - 1;
4917
431
    ctx->mini_gop_length[0]      = enc_ctx->pre_assignment_buffer_count;
4918
4919
431
    ctx->mini_gop_hierarchical_levels[0]           = next_mg_hierarchical_levels;
4920
431
    ctx->mini_gop_intra_count[0]                   = enc_ctx->pre_assignment_buffer_intra_count;
4921
431
    ctx->mini_gop_idr_count[0]                     = enc_ctx->pre_assignment_buffer_idr_count;
4922
431
    ctx->total_number_of_mini_gops                 = 1;
4923
431
    enc_ctx->previous_mini_gop_hierarchical_levels = (pcs->picture_number == 0)
4924
431
        ? next_mg_hierarchical_levels
4925
431
        : enc_ctx->previous_mini_gop_hierarchical_levels;
4926
431
    enc_ctx->mini_gop_cnt_per_gop = (enc_ctx->pre_assignment_buffer_idr_count) ? 0 : enc_ctx->mini_gop_cnt_per_gop + 1;
4927
431
    assert(IMPLIES(enc_ctx->pre_assignment_buffer_intra_count == enc_ctx->pre_assignment_buffer_count,
4928
431
                   enc_ctx->pre_assignment_buffer_count == 1));
4929
431
#if OPT_USE_HL0_FLAT
4930
    // In RA, if the only picture is an I_SLICE, use default settings (set above). If treat the solo I_SLICE
4931
    // as a regular MG, you will change the hierarchical_levels to the minimum.
4932
    // For low-delay pred strucutres, pre_assignment_buffer_count will be 1, but no need to change the default
4933
    // hierarchical levels.
4934
431
    if (enc_ctx->pre_assignment_buffer_count > 1 ||
4935
#else
4936
    // TODO: Why special case? Why no check on enc_ctx->pre_assignment_buffer_count > 1
4937
    if (next_mg_hierarchical_levels == 1) {
4938
        //minigop 2 case
4939
        ctx->mini_gop_start_index[ctx->total_number_of_mini_gops] = 0;
4940
        ctx->mini_gop_end_index[ctx->total_number_of_mini_gops]   = enc_ctx->pre_assignment_buffer_count - 1;
4941
        ctx->mini_gop_length[ctx->total_number_of_mini_gops]      = enc_ctx->pre_assignment_buffer_count -
4942
            ctx->mini_gop_start_index[ctx->total_number_of_mini_gops];
4943
        ctx->mini_gop_hierarchical_levels[ctx->total_number_of_mini_gops] = 2;
4944
    }
4945
    // In RA, if the only picture is an I_SLICE, use default settings (set above). If treat the solo I_SLICE
4946
    // as a regular MG, you will change the hierarchical_levels to the minimum.
4947
    // For low-delay pred strucutres, pre_assignment_buffer_count will be 1, but no need to change the default
4948
    // hierarchical levels.
4949
    else if (enc_ctx->pre_assignment_buffer_count > 1 ||
4950
#endif
4951
431
        (!enc_ctx->pre_assignment_buffer_intra_count && scs->static_config.pred_structure == RANDOM_ACCESS)) {
4952
0
        initialize_mini_gop_activity_array(scs, pcs, enc_ctx, ctx);
4953
4954
0
        generate_picture_window_split(ctx, enc_ctx);
4955
4956
0
        handle_incomplete_picture_window_map(next_mg_hierarchical_levels, ctx, enc_ctx);
4957
0
    }
4958
4959
431
    get_pred_struct_for_all_frames(ctx, enc_ctx);
4960
431
}
4961
4962
// Set whether the picture is to be considered as SC; for single-threaded mode we perform SC detection here
4963
431
static void perform_sc_detection(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4964
431
    if (pcs->slice_type == I_SLICE) {
4965
        // If running multi-threaded mode, perform SC detection in svt_aom_picture_analysis_kernel, else in svt_aom_picture_decision_kernel
4966
431
        if (scs->static_config.level_of_parallelism == 1) {
4967
0
            switch (scs->static_config.screen_content_mode) {
4968
0
#if OPT_SC_STILL_IMAGE
4969
0
            case 0:
4970
0
                pcs->sc_class0 = pcs->sc_class1 = pcs->sc_class2 = pcs->sc_class3 = pcs->sc_class4 = pcs->sc_class5 = 0;
4971
0
                break;
4972
0
            case 1:
4973
0
                pcs->sc_class0 = pcs->sc_class1 = pcs->sc_class2 = pcs->sc_class3 = pcs->sc_class4 = pcs->sc_class5 = 1;
4974
0
                break;
4975
#else
4976
            case 0:
4977
                pcs->sc_class0 = pcs->sc_class1 = pcs->sc_class2 = pcs->sc_class3 = pcs->sc_class4 = 0;
4978
                break;
4979
            case 1:
4980
                pcs->sc_class0 = pcs->sc_class1 = pcs->sc_class2 = pcs->sc_class3 = pcs->sc_class4 = 1;
4981
                break;
4982
#endif
4983
0
            case 2:
4984
                // SC Detection is OFF for 4K and higher
4985
0
                if (scs->input_resolution <= INPUT_SIZE_1080p_RANGE) {
4986
0
                    svt_aom_is_screen_content(pcs);
4987
0
                }
4988
0
                break;
4989
0
            case 3:
4990
0
                svt_aom_is_screen_content_antialiasing_aware(pcs);
4991
0
                break;
4992
0
            }
4993
0
        }
4994
431
        ctx->last_i_picture_sc_class0 = pcs->sc_class0;
4995
431
        ctx->last_i_picture_sc_class1 = pcs->sc_class1;
4996
431
        ctx->last_i_picture_sc_class2 = pcs->sc_class2;
4997
431
        ctx->last_i_picture_sc_class3 = pcs->sc_class3;
4998
431
        ctx->last_i_picture_sc_class4 = pcs->sc_class4;
4999
431
#if TUNE_SIMPLIFY_SETTINGS
5000
431
        ctx->last_i_picture_sc_class5 = pcs->sc_class5;
5001
431
#endif
5002
5003
431
    } else {
5004
0
        pcs->sc_class0 = ctx->last_i_picture_sc_class0;
5005
0
        pcs->sc_class1 = ctx->last_i_picture_sc_class1;
5006
0
        pcs->sc_class2 = ctx->last_i_picture_sc_class2;
5007
0
        pcs->sc_class3 = ctx->last_i_picture_sc_class3;
5008
0
        pcs->sc_class4 = ctx->last_i_picture_sc_class4;
5009
0
#if TUNE_SIMPLIFY_SETTINGS
5010
0
        pcs->sc_class5 = ctx->last_i_picture_sc_class5;
5011
0
#endif
5012
0
    }
5013
431
}
5014
5015
// Update pred struct info and pic type for non-overlay pictures
5016
static void update_pred_struct_and_pic_type(SequenceControlSet* scs, EncodeContext* enc_ctx,
5017
                                            PictureParentControlSet* pcs, PictureDecisionContext* ctx,
5018
                                            unsigned int mini_gop_index, bool pre_assignment_buffer_first_pass_flag,
5019
431
                                            SliceType* picture_type, PredictionStructureEntry** pred_position_ptr) {
5020
431
    (void)scs;
5021
    // Keep track of the mini GOP size to which the input picture belongs - needed @ PictureManagerProcess()
5022
431
    pcs->pre_assignment_buffer_count = ctx->mini_gop_length[mini_gop_index];
5023
5024
    // Update the Pred Structure if cutting short a Random Access period
5025
431
    if (is_pic_cutting_short_ra_mg(ctx, pcs, mini_gop_index)) {
5026
        // Correct the Pred Index before switching structures
5027
0
        if (pre_assignment_buffer_first_pass_flag == true) {
5028
0
            enc_ctx->pred_struct_position -= pcs->pred_struct_ptr->init_pic_index;
5029
0
        }
5030
0
        pcs->pred_struct_ptr = svt_aom_get_prediction_structure(
5031
0
            enc_ctx->prediction_structure_group_ptr, LOW_DELAY, pcs->hierarchical_levels);
5032
0
        *picture_type        = B_SLICE;
5033
0
        ctx->cut_short_ra_mg = 1;
5034
431
    } else {
5035
        // Set the Picture Type
5036
431
        *picture_type = (pcs->idr_flag || pcs->cra_flag) ? I_SLICE : B_SLICE;
5037
431
    }
5038
    // If mini GOP switch, reset position
5039
431
    if (pcs->init_pred_struct_position_flag) {
5040
0
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
5041
0
    }
5042
5043
    // If Intra, reset position
5044
431
    if (pcs->idr_flag == true) {
5045
431
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
5046
431
    } else if (pcs->cra_flag == true &&
5047
0
               ctx->mini_gop_length[mini_gop_index] < pcs->pred_struct_ptr->pred_struct_entry_count) {
5048
0
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
5049
0
    } else if (enc_ctx->elapsed_non_cra_count == 0) {
5050
        // If we are the picture directly after a CRA, we have to not use references that violate the CRA
5051
0
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index + 1;
5052
0
    }
5053
    // Else, Increment the position normally
5054
0
    else {
5055
0
        ++enc_ctx->pred_struct_position;
5056
0
    }
5057
    // The poc number of the latest IDR picture is stored so that last_idr_picture (present in PCS) for the incoming pictures can be updated.
5058
    // The last_idr_picture is used in reseting the poc (in entropy coding) whenever IDR is encountered.
5059
    // Note IMP: This logic only works when display and decode order are the same. Currently for Random Access, IDR is inserted (similar to CRA) by using trailing P pictures (low delay fashion) and breaking prediction structure.
5060
    // Note: When leading P pictures are implemented, this logic has to change..
5061
431
    if (pcs->idr_flag == true) {
5062
431
        enc_ctx->last_idr_picture = pcs->picture_number;
5063
431
    } else {
5064
0
        pcs->last_idr_picture = enc_ctx->last_idr_picture;
5065
0
    }
5066
    // Cycle the PredStructPosition if its overflowed
5067
431
    enc_ctx->pred_struct_position = (enc_ctx->pred_struct_position == pcs->pred_struct_ptr->pred_struct_entry_count)
5068
431
        ? enc_ctx->pred_struct_position - pcs->pred_struct_ptr->pred_struct_entry_count
5069
431
        : enc_ctx->pred_struct_position;
5070
5071
431
    *pred_position_ptr = pcs->pred_struct_ptr->pred_struct_entry_ptr_array[enc_ctx->pred_struct_position];
5072
431
}
5073
5074
static uint32_t get_pic_idx_in_mg(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx,
5075
431
                                  uint32_t pic_idx, uint32_t mini_gop_index) {
5076
431
    uint32_t pic_idx_in_mg = 0;
5077
431
    if (scs->static_config.pred_structure == RANDOM_ACCESS) {
5078
0
        pic_idx_in_mg = pic_idx - ctx->mini_gop_start_index[mini_gop_index];
5079
431
    } else if (scs->static_config.pred_structure == LOW_DELAY) {
5080
0
        uint64_t distance_to_last_idr = pcs->picture_number - scs->enc_ctx->last_idr_picture;
5081
        // For low delay P or low delay b case, get the the picture_index by mini_gop size
5082
0
        if (scs->static_config.intra_period_length >= 0) {
5083
0
            pic_idx_in_mg = (distance_to_last_idr == 0)
5084
0
                ? 0
5085
0
                : (uint32_t)(((distance_to_last_idr - 1) % (scs->static_config.intra_period_length + 1)) %
5086
0
                             pcs->pred_struct_ptr->pred_struct_entry_count);
5087
0
        } else {
5088
            // intra-period=-1 case, no gop
5089
0
            pic_idx_in_mg = (distance_to_last_idr == 0)
5090
0
                ? 0
5091
0
                : (uint32_t)((distance_to_last_idr - 1) % pcs->pred_struct_ptr->pred_struct_entry_count);
5092
0
        }
5093
        // In S-Frame flexible insertion mode, hierarchical levels are adjusted based on the S-Frame position.
5094
        // Picture indices in the low-delay mini-GOP are calculated from the last saved ARF.
5095
0
        if (IS_SFRAME_FLEXIBLE_INSERT(scs->static_config.sframe_mode)) {
5096
0
            pic_idx_in_mg = distance_to_last_idr > ctx->sframe_last_arf
5097
0
                ? (uint32_t)(distance_to_last_idr - ctx->sframe_last_arf - 1)
5098
0
                : 0;
5099
0
        }
5100
0
        pcs->frame_offset = distance_to_last_idr;
5101
0
    }
5102
5103
431
    return pic_idx_in_mg;
5104
431
}
5105
5106
431
static void set_ref_frame_sign_bias(SequenceControlSet* scs, PictureParentControlSet* pcs) {
5107
431
    memset(pcs->av1_cm->ref_frame_sign_bias, 0, 8 * sizeof(int32_t));
5108
5109
431
    if (scs->seq_header.order_hint_info.enable_order_hint) {
5110
3.44k
        for (MvReferenceFrame ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
5111
3.01k
            pcs->av1_cm->ref_frame_sign_bias[ref_frame] = (get_relative_dist(&scs->seq_header.order_hint_info,
5112
3.01k
                                                                             pcs->ref_order_hint[ref_frame - 1],
5113
3.01k
                                                                             (int)pcs->cur_order_hint) <= 0)
5114
3.01k
                ? 0
5115
3.01k
                : 1;
5116
3.01k
        }
5117
431
    }
5118
431
}
5119
5120
// Derive settings used to encode the picture
5121
// Both normative (e.g. frame header info) and non-normative (e.g. feature levels) are set here
5122
431
static void init_pic_settings(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
5123
431
    FrameHeader* frm_hdr        = &pcs->frm_hdr;
5124
431
    pcs->allow_comp_inter_inter = pcs->slice_type != I_SLICE;
5125
431
    frm_hdr->reference_mode     = pcs->slice_type == I_SLICE ? (ReferenceMode)0xFF
5126
431
            : svt_aom_is_incomp_mg_frame(pcs)                ? SINGLE_REFERENCE
5127
0
                                                             : REFERENCE_MODE_SELECT;
5128
5129
431
    pcs->av1_cm->mi_cols = pcs->aligned_width >> MI_SIZE_LOG2;
5130
431
    pcs->av1_cm->mi_rows = pcs->aligned_height >> MI_SIZE_LOG2;
5131
5132
    // Initialize the order hints
5133
431
    const OrderHintInfo* const order_hint_info = &pcs->scs->seq_header.order_hint_info;
5134
431
    uint32_t*                  ref_order_hint  = pcs->ref_order_hint;
5135
3.44k
    for (uint8_t i = 0; i < INTER_REFS_PER_FRAME; ++i) {
5136
3.01k
        ref_order_hint[i] = pcs->av1_ref_signal.ref_poc_array[i] % (uint64_t)(1 << (order_hint_info->order_hint_bits));
5137
3.01k
    }
5138
431
    pcs->cur_order_hint = pcs->picture_number % (uint64_t)(1 << (order_hint_info->order_hint_bits));
5139
5140
431
    set_ref_frame_sign_bias(scs, pcs);
5141
5142
    // TODO: put this in EbMotionEstimationProcess?
5143
431
    copy_tf_params(scs, pcs, ctx);
5144
    // TODO: put this in EbMotionEstimationProcess?
5145
    // ME Kernel Multi-Processes Signal(s) derivation
5146
431
    const bool rtc_tune = scs->static_config.rtc;
5147
431
    const bool allintra = scs->allintra;
5148
5149
431
    allintra       ? svt_aom_sig_deriv_multi_processes_allintra(scs, pcs)
5150
431
        : rtc_tune ? svt_aom_sig_deriv_multi_processes_rtc(scs, pcs)
5151
0
                   : svt_aom_sig_deriv_multi_processes_default(scs, pcs);
5152
5153
431
    update_count_try(scs, pcs);
5154
5155
431
    if (ctx->transition_detected == 1) {
5156
0
        if (pcs->temporal_layer_index == 0) {
5157
0
            pcs->transition_present  = 1;
5158
0
            ctx->transition_detected = 0;
5159
0
        }
5160
0
    }
5161
5162
431
    if (ctx->list0_only && pcs->slice_type == B_SLICE && pcs->temporal_layer_index == 0) {
5163
0
        pcs->ref_list1_count_try = 0;
5164
0
    }
5165
431
    assert(pcs->ref_list0_count_try <= pcs->ref_list0_count);
5166
431
    assert(pcs->ref_list1_count_try <= pcs->ref_list1_count);
5167
5168
    // Setup the skip mode syntax, see: spec 5.9.22 - Skip mode params syntax
5169
431
    svt_av1_setup_skip_mode_allowed(pcs);
5170
431
    frm_hdr->skip_mode_params.skip_mode_flag = frm_hdr->skip_mode_params.skip_mode_allowed;
5171
5172
    //set the ref frame types used for this picture,
5173
431
    set_all_ref_frame_type(ctx, pcs, pcs->ref_frame_type_arr, &pcs->tot_ref_frame_types);
5174
431
}
5175
5176
// Create MG arrays with pics in decode order (ctx->mg_pictures_array) and dispaly order (ctx->mg_pictures_array_disp_order)
5177
// Input is ctx->mg_pictures_array with all pics in the MG sorted by display order
5178
431
static void store_mg_picture_arrays(PictureDecisionContext* ctx) {
5179
431
    const unsigned int mg_size = ctx->mg_size;
5180
5181
    // mg_pictures_array arrives in display order, so copy into display order array
5182
431
    svt_memcpy(ctx->mg_pictures_array_disp_order, ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
5183
5184
    // Sort MG pics into decode order
5185
431
    PictureParentControlSet** mg_pics = &ctx->mg_pictures_array[0];
5186
431
    for (unsigned int i = 0; i < mg_size - 1; ++i) {
5187
0
        for (unsigned int j = i + 1; j < mg_size; ++j) {
5188
0
            if (mg_pics[j]->decode_order < mg_pics[i]->decode_order) {
5189
0
                PictureParentControlSet* temp = mg_pics[i];
5190
0
                mg_pics[i]                    = ctx->mg_pictures_array[j];
5191
0
                mg_pics[j]                    = temp;
5192
0
            }
5193
0
        }
5194
0
    }
5195
431
}
5196
5197
// return true if the frame is part of an incomplete MG (at the end of a GOP)
5198
1.29k
bool svt_aom_is_incomp_mg_frame(PictureParentControlSet* pcs) {
5199
1.29k
    return (pcs->pred_struct_ptr->pred_type == LOW_DELAY && pcs->scs->static_config.pred_structure == RANDOM_ACCESS);
5200
1.29k
}
5201
5202
static void assign_and_release_pa_refs(EncodeContext* enc_ctx, PictureParentControlSet* pcs,
5203
431
                                       PictureDecisionContext* ctx) {
5204
431
    const unsigned int mg_size = ctx->mg_size;
5205
862
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5206
431
        pcs = ctx->mg_pictures_array[pic_i];
5207
431
        if (pcs->slice_type == B_SLICE) {
5208
0
            for (REF_FRAME_MINUS1 ref = LAST; ref < ALT + 1; ref++) {
5209
                // hardcode the reference for the overlay frame
5210
0
                uint64_t ref_poc = pcs->is_overlay ? pcs->picture_number : pcs->av1_ref_signal.ref_poc_array[ref];
5211
5212
0
                uint8_t list_idx = get_list_idx(ref + 1);
5213
0
                uint8_t ref_idx  = get_ref_frame_idx(ref + 1);
5214
0
                svt_block_on_mutex(enc_ctx->pd_dpb_mutex);
5215
0
                PaReferenceEntry* pa_ref_entry = search_ref_in_ref_queue_pa(enc_ctx, ref_poc);
5216
0
                assert(pa_ref_entry != NULL);
5217
                // Set the Reference Object
5218
0
                pcs->ref_pa_pic_ptr_array[list_idx][ref_idx] = pa_ref_entry->input_object_ptr;
5219
0
                pcs->ref_pic_poc_array[list_idx][ref_idx]    = ref_poc;
5220
                // Increment the PA Reference's liveCount by the number of tiles in the input picture
5221
0
                svt_object_inc_live_count(pa_ref_entry->input_object_ptr, 1);
5222
5223
0
                pcs->ref_y8b_array[list_idx][ref_idx] = pa_ref_entry->y8b_wrapper;
5224
5225
0
                if (pa_ref_entry->y8b_wrapper) {
5226
                    //y8b follows longest life cycle of pa ref and input. so it needs to build on top of live count of pa ref
5227
0
                    svt_object_inc_live_count(pa_ref_entry->y8b_wrapper, 1);
5228
0
                }
5229
0
                svt_release_mutex(enc_ctx->pd_dpb_mutex);
5230
0
            }
5231
0
        }
5232
5233
431
        uint8_t released_pics_idx = 0;
5234
5235
        // If the pic is added to DPB, add to ref list until all frames that use it have had a chance to reference it
5236
431
        if (pcs->av1_ref_signal.refresh_frame_mask) {
5237
            //assert(!pcs->is_overlay); // is this true?
5238
            //Update the DPB
5239
3.87k
            for (uint8_t i = 0; i < REF_FRAMES; i++) {
5240
3.44k
                if ((pcs->av1_ref_signal.refresh_frame_mask >> i) & 1) {
5241
3.44k
                    svt_block_on_mutex(enc_ctx->pd_dpb_mutex);
5242
                    // Get the current entry at that spot in the DPB
5243
3.44k
                    PaReferenceEntry* input_entry = enc_ctx->pd_dpb[i];
5244
5245
                    // If DPB entry is occupied, release the current entry
5246
3.44k
                    if (input_entry->is_valid) {
5247
0
                        bool still_in_dpb = 0;
5248
0
                        for (uint8_t j = 0; j < REF_FRAMES; j++) {
5249
0
                            if (j == i) {
5250
0
                                continue;
5251
0
                            }
5252
0
                            if (enc_ctx->pd_dpb[j]->is_valid &&
5253
0
                                enc_ctx->pd_dpb[j]->picture_number == input_entry->picture_number) {
5254
0
                                still_in_dpb = 1;
5255
0
                            }
5256
0
                        }
5257
0
                        if (!still_in_dpb) {
5258
0
                            pcs->released_pics[released_pics_idx++] = input_entry->decode_order;
5259
0
                        }
5260
5261
                        // Release the entry at that DPB spot
5262
                        // Release the nominal live_count value
5263
0
                        svt_release_object(input_entry->input_object_ptr);
5264
5265
0
                        if (input_entry->y8b_wrapper) {
5266
                            //y8b needs to get decremented at the same time of pa ref
5267
0
                            svt_release_object(input_entry->y8b_wrapper);
5268
0
                        }
5269
5270
0
                        input_entry->input_object_ptr = (EbObjectWrapper*)NULL;
5271
0
                    }
5272
5273
                    // Update the list entry with the info of the new pic that is replacing the old pic in the DPB
5274
                    // Place Picture in Picture Decision PA Reference Queue
5275
3.44k
                    input_entry->input_object_ptr = pcs->pa_ref_pic_wrapper;
5276
3.44k
                    input_entry->picture_number   = pcs->picture_number;
5277
3.44k
                    input_entry->is_valid         = true;
5278
3.44k
                    input_entry->decode_order     = pcs->decode_order;
5279
3.44k
                    input_entry->is_alt_ref       = pcs->is_alt_ref;
5280
3.44k
                    input_entry->y8b_wrapper      = pcs->y8b_wrapper;
5281
5282
3.44k
                    svt_object_inc_live_count(input_entry->input_object_ptr, 1);
5283
5284
3.44k
                    if (input_entry->y8b_wrapper) {
5285
                        //y8b follows longest life cycle of pa ref and input. so it needs to build on top of live count of pa ref
5286
3.44k
                        svt_object_inc_live_count(input_entry->y8b_wrapper, 1);
5287
3.44k
                    }
5288
3.44k
                    svt_release_mutex(enc_ctx->pd_dpb_mutex);
5289
3.44k
                }
5290
3.44k
            }
5291
431
        } else {
5292
0
            assert(!pcs->is_ref);
5293
0
        }
5294
431
        pcs->released_pics_count = released_pics_idx;
5295
431
    }
5296
431
}
5297
5298
// Send pictures to TF and ME
5299
431
static void process_pics(SequenceControlSet* scs, PictureDecisionContext* ctx) {
5300
431
    PictureParentControlSet* pcs     = NULL; // init'd to quiet build warnings
5301
431
    const unsigned int       mg_size = ctx->mg_size;
5302
    // Process previous delayed Intra if we have one
5303
431
    if (ctx->prev_delayed_intra) {
5304
0
        pcs = ctx->prev_delayed_intra;
5305
0
        store_gf_group(pcs, ctx, mg_size);
5306
431
    } else {
5307
862
        for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5308
431
            pcs = ctx->mg_pictures_array_disp_order[pic_i];
5309
431
            if (svt_aom_is_delayed_intra(pcs) == false) {
5310
431
                store_gf_group(pcs, ctx, mg_size);
5311
431
            }
5312
431
        }
5313
431
    }
5314
    //Process previous delayed Intra if we have one
5315
431
    if (ctx->prev_delayed_intra) {
5316
0
        pcs                      = ctx->prev_delayed_intra;
5317
0
        ctx->base_counter        = 0;
5318
0
        ctx->gm_pp_last_detected = 0;
5319
0
        pcs->filt_to_unfilt_diff = ctx->filt_to_unfilt_diff = (uint32_t)~0;
5320
0
        mctf_frame(scs, pcs, ctx);
5321
0
        ctx->filt_to_unfilt_diff = pcs->slice_type == I_SLICE ? pcs->filt_to_unfilt_diff : ctx->filt_to_unfilt_diff;
5322
0
    }
5323
5324
    //Do TF loop in display order
5325
862
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5326
431
        pcs = ctx->mg_pictures_array_disp_order[pic_i];
5327
5328
431
        if (svt_aom_is_delayed_intra(pcs) == false) {
5329
431
            if (pcs->slice_type == B_SLICE && pcs->temporal_layer_index == 0) {
5330
0
                pcs->gm_pp_enabled = ctx->base_counter == 0 ? 1 : 0;
5331
0
                ctx->base_counter  = 1 - ctx->base_counter;
5332
0
            }
5333
5334
431
            pcs->filt_to_unfilt_diff = ctx->filt_to_unfilt_diff;
5335
431
            mctf_frame(scs, pcs, ctx);
5336
431
            ctx->filt_to_unfilt_diff = pcs->slice_type == I_SLICE ? pcs->filt_to_unfilt_diff : ctx->filt_to_unfilt_diff;
5337
431
            ctx->gm_pp_last_detected = pcs->gm_pp_enabled ? pcs->gm_pp_detected : ctx->gm_pp_last_detected;
5338
431
        }
5339
431
    }
5340
5341
431
    if (ctx->prev_delayed_intra) {
5342
0
        pcs                     = ctx->prev_delayed_intra;
5343
0
        ctx->prev_delayed_intra = NULL;
5344
0
        send_picture_out(scs, pcs, ctx);
5345
0
    }
5346
5347
    //split MG into two for these two special cases
5348
431
    uint8_t ldp_delayi_mg = 0;
5349
431
    uint8_t ldp_i_eos_mg  = 0;
5350
5351
    // Special considerations for I_SLICE after incomplete MG pic
5352
431
    if (ctx->mg_pictures_array[mg_size - 1]->slice_type == I_SLICE &&
5353
431
        svt_aom_is_incomp_mg_frame(ctx->mg_pictures_array[0])) {
5354
0
        if (svt_aom_is_delayed_intra(ctx->mg_pictures_array[mg_size - 1])) {
5355
0
            ldp_delayi_mg = 1;
5356
0
        } else if (ctx->mg_pictures_array[mg_size - 1]->slice_type == I_SLICE &&
5357
0
                   ctx->mg_pictures_array[mg_size - 1]->end_of_sequence_flag) {
5358
0
            ldp_i_eos_mg = 1;
5359
0
        }
5360
0
    }
5361
5362
862
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5363
431
        pcs = ctx->mg_pictures_array[pic_i];
5364
431
        if (svt_aom_is_delayed_intra(pcs)) {
5365
0
            ctx->prev_delayed_intra = pcs;
5366
5367
0
            if (ldp_delayi_mg) {
5368
0
                ctx->mg_progress_id++;
5369
0
            }
5370
5371
0
            pcs->ext_mg_id   = ctx->mg_progress_id;
5372
0
            pcs->ext_mg_size = 1;
5373
431
        } else {
5374
431
            pcs->ext_mg_id   = ctx->mg_progress_id;
5375
431
            pcs->ext_mg_size = ldp_delayi_mg || ldp_i_eos_mg ? mg_size - 1 : mg_size;
5376
5377
431
            if (ldp_i_eos_mg && pcs->slice_type == I_SLICE) {
5378
0
                ctx->mg_progress_id++;
5379
0
                pcs->ext_mg_id   = ctx->mg_progress_id;
5380
0
                pcs->ext_mg_size = 1;
5381
0
            }
5382
431
            pcs->gm_pp_detected = ctx->gm_pp_last_detected;
5383
431
            send_picture_out(scs, pcs, ctx);
5384
431
        }
5385
431
    }
5386
5387
431
    ctx->mg_progress_id++;
5388
431
}
5389
5390
// update the DPB stored in the PD context
5391
431
static void update_dpb(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
5392
431
    Av1RpsNode* av1_rps = &pcs->av1_ref_signal;
5393
431
    if (av1_rps->refresh_frame_mask) {
5394
3.87k
        for (int i = 0; i < REF_FRAMES; i++) {
5395
3.44k
            if ((av1_rps->refresh_frame_mask >> i) & 1) {
5396
3.44k
                ctx->dpb[i].picture_number       = pcs->picture_number;
5397
3.44k
                ctx->dpb[i].decode_order         = pcs->decode_order;
5398
3.44k
                ctx->dpb[i].temporal_layer_index = pcs->temporal_layer_index;
5399
3.44k
            }
5400
3.44k
        }
5401
431
    }
5402
431
}
5403
5404
0
static uint32_t calc_ahd_pd(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
5405
    // accumulative histogram (absolute) differences between the past and current frame
5406
0
    uint32_t ahd = 0;
5407
0
    uint32_t region_in_picture_width_index;
5408
0
    uint32_t region_in_picture_height_index;
5409
    // Loop over regions inside the picture
5410
0
    for (region_in_picture_width_index = 0;
5411
0
         region_in_picture_width_index < scs->picture_analysis_number_of_regions_per_width;
5412
0
         region_in_picture_width_index++) { // loop over horizontal regions
5413
0
        for (region_in_picture_height_index = 0;
5414
0
             region_in_picture_height_index < scs->picture_analysis_number_of_regions_per_height;
5415
0
             region_in_picture_height_index++) { // loop over vertical regions
5416
5417
0
            for (int bin = 0; bin < HISTOGRAM_NUMBER_OF_BINS; ++bin) {
5418
0
                ahd += ABS(
5419
0
                    (int32_t)
5420
0
                        pcs->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin] -
5421
0
                    (int32_t)ctx
5422
0
                        ->prev_picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin]);
5423
0
            }
5424
0
        }
5425
0
    }
5426
0
    return (ahd);
5427
0
}
5428
5429
/* Picture Decision Kernel */
5430
5431
/***************************************************************************************************
5432
*
5433
* @brief
5434
*  The Picture Decision process performs multi-picture level decisions, including setting of the prediction structure,
5435
*  setting the picture type and performing scene change detection.
5436
*
5437
* @par Description:
5438
*  Since the prior Picture Analysis process stage is multithreaded, inputs to the Picture Decision Process can arrive
5439
*  out-of-display-order, so a reordering queue is used to enforce processing of pictures in display order. The algorithms
5440
*  employed in the Picture Decision process are dependent on prior pictures’ statistics, so the order in which pictures are
5441
*  processed must be strictly enforced. Additionally, the Picture Decision process uses the reorder queue to hold input pictures
5442
*  until they can be started into the Motion Estimation process while following the proper prediction structure.
5443
*
5444
* @param[in] Pictures
5445
*  The Picture Decision Process takes images spontaneously as they arive and perform multi-picture level decisions,
5446
*  including setting of the picture structure, setting the picture type and scene change detection.
5447
*
5448
* @param[out] Picture Control Set
5449
*  Picture Control Set with fully available Picture Analysis Reference List
5450
*
5451
* @remarks
5452
*  For Low Delay Sequences, pictures are started into the encoder pipeline immediately.
5453
*
5454
*  For Random Access Sequences, pictures are held for up to a PredictionStructurePeriod
5455
*    in order to determine if a Scene Change or Intra Frame is forthcoming. Either of
5456
*    those events (and additionally a End of Sequence Flag) will change the expected
5457
*    prediction structure.
5458
*
5459
*  Below is an example worksheet for how Intra Flags and Scene Change Flags interact
5460
*    together to affect the prediction structure.
5461
*
5462
*  The base prediction structure for this example is a 3-Level Hierarchical Random Access,
5463
*    Single Reference Prediction Structure:
5464
*
5465
*        b   b
5466
*       / \ / \
5467
*      /   b   \
5468
*     /   / \   \
5469
*    I-----------b
5470
*
5471
*  From this base structure, the following RPS positions are derived:
5472
*
5473
*    p   p       b   b       p   p
5474
*     \   \     / \ / \     /   /
5475
*      P   \   /   b   \   /   P
5476
*       \   \ /   / \   \ /   /
5477
*        ----I-----------b----
5478
*
5479
*    L L L   I  [ Normal ]   T T T
5480
*    2 1 0   n               0 1 2
5481
*            t
5482
*            r
5483
*            a
5484
*
5485
*  The RPS is composed of Leading Picture [L2-L0], Intra (CRA), Base/Normal Pictures,
5486
*    and Trailing Pictures [T0-t2]. Generally speaking, Leading Pictures are useful
5487
*    for handling scene changes without adding extraneous I-pictures and the Trailing
5488
*    pictures are useful for terminating GOPs.
5489
*
5490
*  Here is a table of possible combinations of pictures needed to handle intra and
5491
*    scene changes happening in quick succession.
5492
*
5493
*        Distance to scene change ------------>
5494
*
5495
*                  0              1                 2                3+
5496
*   I
5497
*   n
5498
*   t   0        I   I           n/a               n/a              n/a
5499
*   r
5500
*   a              p              p
5501
*                   \            /
5502
*   P   1        I   I          I   I              n/a              n/a
5503
*   e
5504
*   r               p                               p
5505
*   i                \                             /
5506
*   o            p    \         p   p             /   p
5507
*   d             \    \       /     \           /   /
5508
*       2     I    -----I     I       I         I----    I          n/a
5509
*   |
5510
*   |            p   p           p   p            p   p            p   p
5511
*   |             \   \         /     \          /     \          /   /
5512
*   |              P   \       /   p   \        /   p   \        /   P
5513
*   |               \   \     /     \   \      /   /     \      /   /
5514
*   V   3+   I       ----I   I       ----I    I----       I    I----       I
5515
*
5516
*   The table is interpreted as follows:
5517
*
5518
*   If there are no SCs or Intras encountered for a PredPeriod, then the normal
5519
*     prediction structure is applied.
5520
*
5521
*   If there is an intra in the PredPeriod, then one of the above combinations of
5522
*     Leading and Trailing pictures is used.  If there is no scene change, the last
5523
*     valid column consisting of Trailing Pictures only is used.  However, if there
5524
*     is an upcoming scene change before the next intra, then one of the above patterns
5525
*     is used. In the case of End of Sequence flags, only the last valid column of Trailing
5526
*     Pictures is used. The intention here is that any combination of Intra Flag and Scene
5527
*     Change flag can be coded.
5528
***************************************************************************************************/
5529
862
EbErrorType svt_aom_picture_decision_kernel_iter(void* context) {
5530
862
    PictureDecisionContext* ctx = (PictureDecisionContext*)context;
5531
5532
862
    PictureParentControlSet* pcs;
5533
5534
862
    EncodeContext*          enc_ctx;
5535
862
    SequenceControlSet*     scs;
5536
862
    EbObjectWrapper*        in_results_wrapper_ptr;
5537
862
    PictureAnalysisResults* in_results_ptr;
5538
5539
862
    PredictionStructureEntry* pred_position_ptr;
5540
5541
862
    PictureDecisionReorderEntry* queue_entry_ptr;
5542
5543
862
    unsigned int pic_idx;
5544
5545
    // Get Input Full Object
5546
862
    EB_GET_FULL_OBJECT(ctx->picture_analysis_results_input_fifo_ptr, &in_results_wrapper_ptr);
5547
5548
431
    in_results_ptr      = (PictureAnalysisResults*)in_results_wrapper_ptr->object_ptr;
5549
431
    pcs                 = (PictureParentControlSet*)in_results_ptr->pcs_wrapper->object_ptr;
5550
431
    scs                 = pcs->scs;
5551
431
    enc_ctx             = scs->enc_ctx;
5552
431
    const bool allintra = scs->allintra;
5553
    // Input Picture Analysis Results into the Picture Decision Reordering Queue
5554
    // Since the prior Picture Analysis processes stage is multithreaded, inputs to the Picture Decision Process
5555
    // can arrive out-of-display-order, so a the Picture Decision Reordering Queue is used to enforce processing of
5556
    // pictures in display order
5557
431
    if (!pcs->is_overlay) {
5558
431
        int queue_entry_index =
5559
431
            (int)(pcs->picture_number -
5560
431
                  enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index]
5561
431
                      ->picture_number);
5562
431
        queue_entry_index += enc_ctx->picture_decision_reorder_queue_head_index;
5563
431
        queue_entry_index = (queue_entry_index > (int)(enc_ctx->picture_decision_reorder_queue_size - 1))
5564
431
            ? queue_entry_index - (int)enc_ctx->picture_decision_reorder_queue_size
5565
431
            : queue_entry_index;
5566
431
        queue_entry_ptr   = enc_ctx->picture_decision_reorder_queue[queue_entry_index];
5567
431
        if (queue_entry_ptr->ppcs_wrapper != NULL) {
5568
0
            CHECK_REPORT_ERROR_NC(enc_ctx->app_callback_ptr, EB_ENC_PD_ERROR8);
5569
431
        } else {
5570
431
            queue_entry_ptr->ppcs_wrapper   = in_results_ptr->pcs_wrapper;
5571
431
            queue_entry_ptr->picture_number = pcs->picture_number;
5572
431
        }
5573
5574
431
        pcs->pic_decision_reorder_queue_idx = queue_entry_index;
5575
431
        pcs->first_pass_done                = 0;
5576
431
    }
5577
    // Process the head of the Picture Decision Reordering Queue (Entry N)
5578
    // The Picture Decision Reordering Queue should be parsed in the display order to be able to construct a pred structure
5579
431
    queue_entry_ptr = enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index];
5580
5581
862
    while (queue_entry_ptr->ppcs_wrapper != NULL) {
5582
431
        if (scs->lap_rc) {
5583
0
            process_first_pass(scs, enc_ctx);
5584
0
        }
5585
5586
431
        pcs = (PictureParentControlSet*)queue_entry_ptr->ppcs_wrapper->object_ptr;
5587
431
        bool window_avail, eos_reached;
5588
431
        check_window_availability(scs, enc_ctx, pcs, queue_entry_ptr, &window_avail, &eos_reached);
5589
5590
431
        if (!allintra) {
5591
0
            pcs->ahd_error = (uint32_t)~0;
5592
0
            if (window_avail == true && queue_entry_ptr->picture_number > 0 && scs->calc_hist) {
5593
0
                pcs->ahd_error = calc_ahd_pd(scs, pcs, ctx);
5594
0
            }
5595
            // If the relevant frames are available, perform scene change detection
5596
0
            if (window_avail == true && queue_entry_ptr->picture_number > 0) {
5597
0
                perform_scene_change_detection(scs, pcs, ctx);
5598
0
            }
5599
0
        }
5600
5601
        // If the required lookahead frames aren't available, and we haven't reached EOS, must wait for more frames before continuing
5602
431
        if (!window_avail && !eos_reached) {
5603
0
            break;
5604
0
        }
5605
5606
        // Place the PCS into the Pre-Assignment Buffer
5607
        // The Pre-Assignment Buffer is used to store a whole pre-structure
5608
431
        enc_ctx->pre_assignment_buffer[enc_ctx->pre_assignment_buffer_count] = queue_entry_ptr->ppcs_wrapper;
5609
5610
        // Set the POC Number
5611
431
        pcs->picture_number                 = ++ctx->current_input_poc;
5612
431
        pcs->pred_structure                 = scs->static_config.pred_structure;
5613
431
        pcs->hierarchical_layers_diff       = 0;
5614
431
        pcs->init_pred_struct_position_flag = false;
5615
431
        pcs->tpl_group_size                 = 0;
5616
431
        if (pcs->picture_number == 0) {
5617
431
            ctx->prev_delayed_intra = NULL;
5618
431
        }
5619
431
        if (pcs->picture_number == 0) {
5620
431
            ctx->sframe_hier_lvls = scs->static_config.hierarchical_levels;
5621
431
        }
5622
5623
431
        release_prev_picture_from_reorder_queue(enc_ctx);
5624
5625
        // If the Intra period length is 0, then introduce an intra for every picture
5626
431
        if (allintra) {
5627
431
            pcs->idr_flag = true;
5628
431
            pcs->cra_flag = false;
5629
431
        }
5630
        // If an #IntraPeriodLength has passed since the last Intra, then introduce a CRA or IDR based on Intra Refresh type
5631
0
        else if (scs->static_config.intra_period_length != -1) {
5632
0
            pcs->cra_flag = (scs->static_config.intra_refresh_type != SVT_AV1_FWDKF_REFRESH) ? pcs->cra_flag
5633
0
                : ((enc_ctx->intra_period_position == (uint32_t)scs->static_config.intra_period_length) ||
5634
0
                   (pcs->scene_change_flag == true))
5635
0
                ? true
5636
0
                : pcs->cra_flag;
5637
5638
0
            pcs->idr_flag = (scs->static_config.intra_refresh_type != SVT_AV1_KF_REFRESH)            ? pcs->idr_flag
5639
0
                : enc_ctx->intra_period_position == (uint32_t)scs->static_config.intra_period_length ?
5640
5641
0
                                                                                                     true
5642
0
                                                                                                     : pcs->idr_flag;
5643
0
        }
5644
431
        pcs->idr_flag = (scs->static_config.intra_refresh_type != SVT_AV1_KF_REFRESH)            ? pcs->idr_flag
5645
431
            : (pcs->scene_change_flag == true || pcs->input_ptr->pic_type == EB_AV1_KEY_PICTURE) ? true
5646
431
                                                                                                 : pcs->idr_flag;
5647
431
        if (!allintra && pcs->picture_number > 0 && scs->static_config.sframe_posi.sframe_posis &&
5648
0
            (pcs->cra_flag || pcs->idr_flag)) {
5649
            // if this key frame position is set to an S-frame by sframe-posi, replace this I frame with B frame,
5650
            // and then the S_FRAME will be set in set_sframe_type()
5651
0
            int32_t dist_next_s = 0;
5652
0
            if (get_dist_to_s(&scs->static_config.sframe_posi, pcs->picture_number, &dist_next_s) == 0) {
5653
0
                pcs->cra_flag = false;
5654
0
                pcs->idr_flag = false;
5655
0
            }
5656
0
        }
5657
431
        enc_ctx->pre_assignment_buffer_eos_flag = (pcs->end_of_sequence_flag) ? (uint32_t)true
5658
431
                                                                              : enc_ctx->pre_assignment_buffer_eos_flag;
5659
5660
        // Histogram data to be used at the next input (N + 1)
5661
        // TODO: can this be moved to the end of perform_scene_change_detection? Histograms aren't needed if at EOS
5662
431
        if (scs->calc_hist) {
5663
0
            copy_histograms(pcs, ctx);
5664
0
        }
5665
5666
        // Increment the Pre-Assignment Buffer Intra Count
5667
431
        enc_ctx->pre_assignment_buffer_intra_count += (pcs->idr_flag || pcs->cra_flag);
5668
431
        enc_ctx->pre_assignment_buffer_idr_count += pcs->idr_flag;
5669
431
        enc_ctx->pre_assignment_buffer_count += 1;
5670
5671
        // Increment the Intra Period Position
5672
431
        enc_ctx->intra_period_position = ((enc_ctx->intra_period_position ==
5673
431
                                           (uint32_t)scs->static_config.intra_period_length) ||
5674
0
                                          (pcs->scene_change_flag == true) ||
5675
0
                                          pcs->input_ptr->pic_type == EB_AV1_KEY_PICTURE)
5676
431
            ? 0
5677
431
            : enc_ctx->intra_period_position + 1;
5678
5679
#if LAD_MG_PRINT
5680
        print_pre_ass_buffer(enc_ctx, pcs, 1);
5681
#endif
5682
5683
431
        uint32_t next_mg_hierarchical_levels = scs->static_config.hierarchical_levels;
5684
        // Overwrite next_mg_hierarchical_levels when an S-Frame needs to modify the mini-GOP size.
5685
431
        if (ctx->sframe_hier_lvls != (int32_t)scs->static_config.hierarchical_levels) {
5686
0
            next_mg_hierarchical_levels = ctx->sframe_hier_lvls;
5687
0
        }
5688
431
        if (ctx->enable_startup_mg) {
5689
0
            next_mg_hierarchical_levels = scs->static_config.startup_mg_size;
5690
0
        }
5691
        // Determine if Pictures can be released from the Pre-Assignment Buffer
5692
431
        if ((enc_ctx->pre_assignment_buffer_intra_count > 0) ||
5693
0
            (enc_ctx->pre_assignment_buffer_count == (uint32_t)(1 << next_mg_hierarchical_levels)) ||
5694
0
            (enc_ctx->pre_assignment_buffer_eos_flag == true) ||
5695
431
            (pcs->pred_structure == LOW_DELAY || pcs->pred_structure == ALL_INTRA)) {
5696
#if LAD_MG_PRINT
5697
            print_pre_ass_buffer(enc_ctx, pcs, 0);
5698
#endif
5699
            // Once there are enough frames in the pre-assignement buffer, we can setup the mini-gops
5700
431
            set_mini_gop_structure(scs, enc_ctx, pcs, ctx);
5701
5702
            // Loop over Mini GOPs
5703
862
            for (unsigned int mini_gop_index = 0; mini_gop_index < ctx->total_number_of_mini_gops; ++mini_gop_index) {
5704
431
                bool pre_assignment_buffer_first_pass_flag = true;
5705
5706
                // Get the 1st PCS in the mini-GOP
5707
431
                pcs = (PictureParentControlSet*)enc_ctx
5708
431
                          ->pre_assignment_buffer[ctx->mini_gop_start_index[mini_gop_index]]
5709
431
                          ->object_ptr;
5710
5711
                // Derive the temporal layer difference between the current mini GOP and the previous mini GOP
5712
431
                pcs->hierarchical_layers_diff = (int32_t)enc_ctx->previous_mini_gop_hierarchical_levels -
5713
431
                    (int32_t)pcs->hierarchical_levels;
5714
5715
                // Set init_pred_struct_position_flag to true if mini-GOP switch
5716
431
                pcs->init_pred_struct_position_flag = enc_ctx->is_mini_gop_changed = (pcs->hierarchical_layers_diff !=
5717
431
                                                                                      0);
5718
5719
                // Keep track of the number of hierarchical levels of the latest implemented mini GOP
5720
431
                enc_ctx->previous_mini_gop_hierarchical_levels = ctx->mini_gop_hierarchical_levels[mini_gop_index];
5721
431
                ctx->cut_short_ra_mg                           = 0;
5722
                // 1st Loop over Pictures in the Pre-Assignment Buffer
5723
                // Setup the pred strucutre and picture types for all frames in the mini-GOP (including overlay pics)
5724
431
                for (pic_idx = ctx->mini_gop_start_index[mini_gop_index];
5725
862
                     pic_idx <= ctx->mini_gop_end_index[mini_gop_index];
5726
431
                     ++pic_idx) {
5727
431
                    pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
5728
431
                    scs = pcs->scs;
5729
5730
431
                    update_pred_struct_and_pic_type(scs,
5731
431
                                                    enc_ctx,
5732
431
                                                    pcs,
5733
431
                                                    ctx,
5734
431
                                                    mini_gop_index,
5735
431
                                                    pre_assignment_buffer_first_pass_flag,
5736
431
                                                    &pcs->slice_type,
5737
431
                                                    &pred_position_ptr);
5738
5739
431
                    if (scs->static_config.enable_overlays == true) {
5740
                        // At this stage we know the prediction structure and the location of ALT_REF pictures.
5741
                        // For every ALTREF picture, there is an overlay picture. They extra pictures are released
5742
                        // is_alt_ref flag is set for non-slice base layer pictures
5743
0
                        if (pred_position_ptr->temporal_layer_index == 0 && pcs->slice_type != I_SLICE) {
5744
0
                            pcs->is_alt_ref         = 1;
5745
0
                            pcs->frm_hdr.show_frame = 0;
5746
0
                        }
5747
                        // release the overlay PCS for non alt ref pictures. First picture does not have overlay PCS
5748
0
                        else if (pcs->picture_number) {
5749
0
                            svt_release_object(pcs->overlay_ppcs_ptr->input_pic_wrapper);
5750
                            // release the pa_reference_picture
5751
0
                            svt_release_object(pcs->overlay_ppcs_ptr->pa_ref_pic_wrapper);
5752
0
                            svt_release_object(pcs->overlay_ppcs_ptr->scs_wrapper);
5753
                            // release the parent pcs
5754
                            // Note: this release will recycle ppcs to empty fifo if not live_count+1 in ResourceCoordination.
5755
0
                            svt_release_object(pcs->overlay_ppcs_ptr->p_pcs_wrapper_ptr);
5756
0
                            pcs->overlay_ppcs_ptr = NULL;
5757
0
                        }
5758
0
                    }
5759
5760
431
                    pcs->pic_idx_in_mg = get_pic_idx_in_mg(scs, pcs, ctx, pic_idx, mini_gop_index);
5761
5762
862
                    for (uint8_t loop_index = 0; loop_index <= pcs->is_alt_ref; loop_index++) {
5763
                        // Init pred strucutre info - different for overlay/non-overlay
5764
431
                        if (loop_index == 1) {
5765
0
                            pcs = pcs->overlay_ppcs_ptr;
5766
0
                            initialize_overlay_frame(pcs);
5767
431
                        } else {
5768
431
                            assert(!pcs->is_overlay);
5769
431
                            pcs->pred_struct_index    = (uint8_t)enc_ctx->pred_struct_position;
5770
431
                            pcs->temporal_layer_index = (uint8_t)pred_position_ptr->temporal_layer_index;
5771
431
#if OPT_USE_HL0_FLAT
5772
                            // For flat, set is_highest_layer to false to avoid using aggressive settings for all pictures
5773
431
                            pcs->is_highest_layer = (pcs->temporal_layer_index == pcs->hierarchical_levels) &&
5774
0
                                pcs->hierarchical_levels != 0;
5775
#else
5776
                            pcs->is_highest_layer = (pcs->temporal_layer_index == pcs->hierarchical_levels);
5777
#endif
5778
431
                            switch (pcs->slice_type) {
5779
431
                            case I_SLICE:
5780
5781
                                // Reset Prediction Structure Position & Reference Struct Position
5782
431
                                if (pcs->picture_number == 0) {
5783
431
                                    enc_ctx->intra_period_position = 0;
5784
431
                                }
5785
431
                                enc_ctx->elapsed_non_cra_count = 0;
5786
5787
                                // I_SLICE cannot be CRA and IDR
5788
431
                                pcs->cra_flag = !pcs->idr_flag;
5789
5790
431
                                if (pcs->idr_flag) {
5791
431
                                    enc_ctx->elapsed_non_idr_count = 0; // Reset the pictures since last IDR counter
5792
431
                                    ctx->key_poc                   = pcs->picture_number; // log latest key frame poc
5793
431
                                }
5794
431
                                break;
5795
0
                            case B_SLICE:
5796
                                // Reset CRA and IDR Flag
5797
0
                                pcs->cra_flag = false;
5798
0
                                pcs->idr_flag = false;
5799
5800
                                // Increment & Clip the elapsed Non-IDR Counter. This is clipped rather than allowed to free-run
5801
                                // inorder to avoid rollover issues.  This assumes that any the GOP period is less than MAX_ELAPSED_IDR_COUNT
5802
0
                                enc_ctx->elapsed_non_idr_count = MIN(enc_ctx->elapsed_non_idr_count + 1,
5803
0
                                                                     MAX_ELAPSED_IDR_COUNT);
5804
0
                                enc_ctx->elapsed_non_cra_count = MIN(enc_ctx->elapsed_non_cra_count + 1,
5805
0
                                                                     MAX_ELAPSED_IDR_COUNT);
5806
5807
0
                                CHECK_REPORT_ERROR(
5808
0
                                    (pcs->pred_struct_ptr->pred_struct_entry_count < MAX_ELAPSED_IDR_COUNT),
5809
0
                                    enc_ctx->app_callback_ptr,
5810
0
                                    EB_ENC_PD_ERROR1);
5811
5812
0
                                break;
5813
0
                            default:
5814
0
                                CHECK_REPORT_ERROR_NC(enc_ctx->app_callback_ptr, EB_ENC_PD_ERROR2);
5815
0
                                break;
5816
431
                            }
5817
431
                        }
5818
5819
431
                        CHECK_REPORT_ERROR((pcs->pred_struct_ptr->pred_struct_entry_count * REF_LIST_MAX_DEPTH <
5820
431
                                            MAX_ELAPSED_IDR_COUNT),
5821
431
                                           enc_ctx->app_callback_ptr,
5822
431
                                           EB_ENC_PD_ERROR5);
5823
431
                    }
5824
431
                    pre_assignment_buffer_first_pass_flag = false;
5825
431
                }
5826
5827
                // 2nd Loop over Pictures in the Pre-Assignment Buffer
5828
                // Init picture settings
5829
                // Add 1 to the loop for the overlay picture. If the last picture is alt ref, increase the loop by 1 to add the overlay picture
5830
431
                const uint32_t has_overlay = ((PictureParentControlSet*)enc_ctx
5831
431
                                                  ->pre_assignment_buffer[ctx->mini_gop_end_index[mini_gop_index]]
5832
431
                                                  ->object_ptr)
5833
431
                                                 ->is_alt_ref
5834
431
                    ? 1
5835
431
                    : 0;
5836
431
                for (pic_idx = ctx->mini_gop_start_index[mini_gop_index];
5837
862
                     pic_idx <= ctx->mini_gop_end_index[mini_gop_index] + has_overlay;
5838
431
                     ++pic_idx) {
5839
                    // Assign the overlay pcs. Since Overlay picture is not added to the picture_decision_pa_reference_queue, in the next stage, the loop finds the alt_ref picture. The reference for overlay frame is hardcoded later
5840
431
                    if (has_overlay && pic_idx == ctx->mini_gop_end_index[mini_gop_index] + has_overlay) {
5841
0
                        pcs = ((PictureParentControlSet*)enc_ctx
5842
0
                                   ->pre_assignment_buffer[ctx->mini_gop_end_index[mini_gop_index]]
5843
0
                                   ->object_ptr)
5844
0
                                  ->overlay_ppcs_ptr;
5845
431
                    } else {
5846
431
                        pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
5847
431
                    }
5848
5849
431
                    pcs->picture_number_alt = enc_ctx->picture_number_alt++;
5850
5851
                    // Set the Decode Order
5852
431
                    if ((ctx->mini_gop_idr_count[mini_gop_index] == 0) &&
5853
0
                        (ctx->mini_gop_length[mini_gop_index] == pcs->pred_struct_ptr->pred_struct_entry_count) &&
5854
0
                        (scs->static_config.pred_structure == RANDOM_ACCESS) && !pcs->is_overlay) {
5855
0
                        pcs->decode_order = enc_ctx->decode_base_number +
5856
0
                            pcs->pred_struct_ptr->pred_struct_entry_ptr_array[pcs->pred_struct_index]->decode_order;
5857
431
                    } else {
5858
431
                        pcs->decode_order = pcs->picture_number_alt;
5859
431
                    }
5860
5861
431
                    perform_sc_detection(scs, pcs, ctx);
5862
                    // Update the RC param queue
5863
431
                    update_rc_param_queue(pcs, enc_ctx);
5864
                    // Reset the PA Reference Lists
5865
431
                    EB_MEMSET(pcs->ref_pa_pic_ptr_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5866
431
                    EB_MEMSET(pcs->ref_pa_pic_ptr_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5867
431
                    EB_MEMSET(pcs->ref_y8b_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5868
431
                    EB_MEMSET(pcs->ref_y8b_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5869
431
                    EB_MEMSET(pcs->ref_pic_poc_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(uint64_t));
5870
431
                    EB_MEMSET(pcs->ref_pic_poc_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(uint64_t));
5871
5872
431
                    uint32_t pic_it                = pic_idx - ctx->mini_gop_start_index[mini_gop_index];
5873
431
                    ctx->mg_pictures_array[pic_it] = pcs;
5874
431
                    if (pic_idx == ctx->mini_gop_end_index[mini_gop_index] + has_overlay) {
5875
                        // Increment the Decode Base Number
5876
431
                        enc_ctx->decode_base_number += ctx->mini_gop_length[mini_gop_index] + has_overlay;
5877
431
                    }
5878
431
                }
5879
5880
431
                ctx->mg_size = ctx->mini_gop_end_index[mini_gop_index] + has_overlay -
5881
431
                    ctx->mini_gop_start_index[mini_gop_index] + 1;
5882
5883
                // Store pics in ctx->mg_pictures_array in decode order
5884
                // and pics in ctx->mg_pictures_array_disp_order in display order
5885
431
                store_mg_picture_arrays(ctx);
5886
5887
431
                const unsigned int mg_size = ctx->mg_size;
5888
862
                for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5889
                    // Loop over pics in decode order
5890
431
                    pcs = ctx->mg_pictures_array[pic_i];
5891
431
                    av1_generate_rps_info(pcs, enc_ctx, ctx, pcs->pic_idx_in_mg, mini_gop_index);
5892
5893
431
                    if (scs->static_config.sframe_dist != 0 || !pcs->is_not_scaled ||
5894
431
                        scs->static_config.sframe_posi.sframe_posis) {
5895
0
                        update_sframe_ref_order_hint(pcs, ctx);
5896
0
                    }
5897
5898
431
                    update_dpb(pcs, ctx);
5899
5900
                    // Set picture settings, incl. normative frame header fields and feature levels in signal_derivation function
5901
431
                    init_pic_settings(scs, pcs, ctx);
5902
431
                }
5903
5904
862
                for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5905
431
                    PictureParentControlSet* pcs_1 = ctx->mg_pictures_array_disp_order[pic_i];
5906
431
                    pcs_1->first_frame_in_minigop  = !pic_i;
5907
431
                    set_gf_group_param(pcs_1);
5908
431
                    if (pcs_1->is_alt_ref) {
5909
0
                        ctx->mg_pictures_array_disp_order[pic_i - 1]->has_show_existing = false;
5910
0
                    }
5911
431
                }
5912
5913
                // Loop over pics in MG and assign their PA reference buffers; release buffers when no longer needed
5914
431
                assign_and_release_pa_refs(enc_ctx, pcs, ctx);
5915
5916
                // Send the pictures in the MG to TF and ME
5917
431
                process_pics(scs, ctx);
5918
431
            } // End MINI GOPs loop
5919
            // Reset the Pre-Assignment Buffer
5920
431
            enc_ctx->pre_assignment_buffer_count       = 0;
5921
431
            enc_ctx->pre_assignment_buffer_idr_count   = 0;
5922
431
            enc_ctx->pre_assignment_buffer_intra_count = 0;
5923
431
            enc_ctx->pre_assignment_buffer_eos_flag    = false;
5924
431
        }
5925
        // Increment the Picture Decision Reordering Queue Head Ptr
5926
431
        enc_ctx->picture_decision_reorder_queue_head_index = (enc_ctx->picture_decision_reorder_queue_head_index ==
5927
431
                                                              enc_ctx->picture_decision_reorder_queue_size - 1)
5928
431
            ? 0
5929
431
            : enc_ctx->picture_decision_reorder_queue_head_index + 1;
5930
5931
        // Get the next entry from the Picture Decision Reordering Queue (Entry N+1)
5932
431
        queue_entry_ptr = enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index];
5933
431
    }
5934
5935
431
    if (scs->static_config.enable_overlays == true) {
5936
0
        svt_release_object(((PictureParentControlSet*)in_results_ptr->pcs_wrapper->object_ptr)->scs_wrapper);
5937
        // release ppcs, since live_count + 1 before post in ResourceCoordination
5938
0
        svt_release_object(in_results_ptr->pcs_wrapper);
5939
0
    }
5940
5941
    // Release the Input Results
5942
431
    svt_release_object(in_results_wrapper_ptr);
5943
431
    return EB_ErrorNone;
5944
431
}
5945
5946
431
void* svt_aom_picture_decision_kernel(void* input_ptr) {
5947
431
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
5948
862
    for (;;) {
5949
862
        EbErrorType err = svt_aom_picture_decision_kernel_iter(thread_ctx->priv);
5950
862
        if (err == EB_NoErrorFifoShutdown) {
5951
431
            return NULL;
5952
431
        }
5953
862
    }
5954
0
    return NULL;
5955
431
}