Coverage Report

Created: 2026-09-01 06:57

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