Coverage Report

Created: 2026-08-31 06:22

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.36k
static INLINE int get_relative_dist(const OrderHintInfo* oh, int a, int b) {
88
3.36k
    if (!oh->enable_order_hint) {
89
0
        return 0;
90
0
    }
91
92
3.36k
    const int bits = oh->order_hint_bits;
93
94
3.36k
    assert(bits >= 1);
95
3.36k
    assert(a >= 0 && a < (1 << bits));
96
3.36k
    assert(b >= 0 && b < (1 << bits));
97
98
3.36k
    int       diff = a - b;
99
3.36k
    const int m    = 1 << (bits - 1);
100
3.36k
    diff           = (diff & (m - 1)) - (diff & m);
101
3.36k
    return diff;
102
3.36k
}
103
104
481
void svt_av1_setup_skip_mode_allowed(PictureParentControlSet* pcs) {
105
481
    FrameHeader*               frm_hdr         = &pcs->frm_hdr;
106
481
    const OrderHintInfo* const order_hint_info = &pcs->scs->seq_header.order_hint_info;
107
481
    SkipModeInfo* const        skip_mode_info  = &frm_hdr->skip_mode_params;
108
109
481
    skip_mode_info->skip_mode_allowed = 0;
110
481
    skip_mode_info->ref_frame_idx_0   = INVALID_IDX;
111
481
    skip_mode_info->ref_frame_idx_1   = INVALID_IDX;
112
113
481
    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
481
    if (!order_hint_info->enable_order_hint || pcs->slice_type == I_SLICE /*frame_is_intra_only(cm)*/ ||
117
481
        frm_hdr->reference_mode == SINGLE_REFERENCE) {
118
481
        return;
119
481
    }
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
481
#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
481
static void picture_decision_context_dctor(EbPtr p) {
180
481
    EbThreadContext*        thread_ctx = (EbThreadContext*)p;
181
481
    PictureDecisionContext* obj        = (PictureDecisionContext*)thread_ctx->priv;
182
183
481
    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
481
    EB_FREE_2D(obj->ahd_running_avg);
200
481
    EB_FREE_2D(obj->ahd_running_avg_cr);
201
481
    EB_FREE_2D(obj->ahd_running_avg_cb);
202
481
    EB_FREE_ARRAY(obj);
203
481
}
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
481
                                                  uint8_t calc_hist) {
210
481
    PictureDecisionContext* pd_ctx;
211
481
    EB_CALLOC_ARRAY(pd_ctx, 1);
212
481
    thread_ctx->priv  = pd_ctx;
213
481
    thread_ctx->dctor = picture_decision_context_dctor;
214
215
481
    memset(pd_ctx->tf_pic_array, 0, (1 << MAX_TEMPORAL_LAYERS) * sizeof(PictureParentControlSet*));
216
481
    pd_ctx->tf_pic_arr_cnt                          = 0;
217
481
    pd_ctx->picture_analysis_results_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
218
481
        enc_handle_ptr->picture_analysis_results_resource_ptr, 0);
219
481
    pd_ctx->picture_decision_results_output_fifo_ptr = svt_system_resource_get_producer_fifo(
220
481
        enc_handle_ptr->picture_decision_results_resource_ptr, 0);
221
481
    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
481
    pd_ctx->reset_running_avg = true;
241
481
    pd_ctx->me_fifo_ptr       = svt_system_resource_get_producer_fifo(enc_handle_ptr->me_pool_ptr, 0);
242
243
481
    pd_ctx->mg_progress_id                    = 0;
244
481
    pd_ctx->last_i_noise_levels_log1p_fp16[0] = 0;
245
481
    pd_ctx->transition_detected               = -1;
246
481
    pd_ctx->sframe_poc                        = 0;
247
481
    pd_ctx->sframe_due                        = 0;
248
481
    pd_ctx->last_long_base_pic                = 0;
249
481
    pd_ctx->enable_startup_mg                 = false;
250
481
    pd_ctx->is_startup_gop                    = false;
251
481
    pd_ctx->sframe_hier_lvls                  = 0;
252
481
    pd_ctx->sframe_last_arf                   = 0;
253
481
    pd_ctx->next_arf_is_s                     = false;
254
481
    pd_ctx->current_input_poc                 = -1;
255
481
    return EB_ErrorNone;
256
481
}
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
481
EbErrorType release_prev_picture_from_reorder_queue(EncodeContext* enc_ctx) {
382
481
    EbErrorType return_error = EB_ErrorNone;
383
384
481
    PictureDecisionReorderEntry* queue_previous_entry_ptr;
385
481
    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
481
    previous_entry_index     = (enc_ctx->picture_decision_reorder_queue_head_index == 0)
390
481
            ? enc_ctx->picture_decision_reorder_queue_size - 1
391
481
            : enc_ctx->picture_decision_reorder_queue_head_index - 1;
392
481
    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
481
    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
481
    return return_error;
403
481
}
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
481
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
481
    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
481
        pcs->pred_struct_ptr->pred_type == RANDOM_ACCESS && pcs->idr_flag == false && pcs->cra_flag == false) {
935
0
        return 1;
936
481
    } else {
937
481
        return 0;
938
481
    }
939
481
}
940
941
/***************************************************************************************************
942
* Gets the pred struct for each frame in the mini-gop(s) that we have available
943
***************************************************************************************************/
944
481
static void get_pred_struct_for_all_frames(PictureDecisionContext* ctx, EncodeContext* enc_ctx) {
945
    // Loop over all mini GOPs
946
962
    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
481
        for (unsigned int pic_idx = ctx->mini_gop_start_index[mini_gop_index];
949
962
             pic_idx <= ctx->mini_gop_end_index[mini_gop_index];
950
481
             pic_idx++) {
951
481
            PictureParentControlSet* pcs =
952
481
                (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
953
481
            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
481
            pcs->pred_structure      = scs->static_config.pred_structure;
970
481
            pcs->hierarchical_levels = pcs->idr_flag ? scs->static_config.hierarchical_levels
971
481
                                                     : (uint8_t)ctx->mini_gop_hierarchical_levels[mini_gop_index];
972
481
            pcs->pred_struct_ptr     = svt_aom_get_prediction_structure(
973
481
                enc_ctx->prediction_structure_group_ptr, pcs->pred_structure, pcs->hierarchical_levels);
974
975
481
            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
481
            if (pcs->idr_flag && pcs->picture_number == 0) {
983
481
                ctx->is_startup_gop = true;
984
481
            } else if (pcs->idr_flag || pcs->cra_flag) {
985
0
                ctx->is_startup_gop = false;
986
0
            }
987
481
            pcs->is_startup_gop = ctx->is_startup_gop;
988
481
        }
989
481
    }
990
481
}
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.31k
bool svt_aom_is_pic_skipped(PictureParentControlSet* pcs) {
999
7.31k
    if (!pcs->is_ref && pcs->scs->rc_stat_gen_pass_mode && !pcs->first_frame_in_minigop) {
1000
0
        return true;
1001
0
    }
1002
7.31k
    return false;
1003
7.31k
}
1004
1005
static void prune_sframe_refs(PictureDecisionContext* ctx, PictureParentControlSet* ppcs,
1006
481
                              MvReferenceFrame ref_frame_arr[], uint8_t* tot_ref_frames) {
1007
481
    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
481
}
1044
1045
//set the ref frame types used for this picture,
1046
static void set_all_ref_frame_type(PictureDecisionContext* ctx, PictureParentControlSet* ppcs,
1047
481
                                   MvReferenceFrame ref_frame_arr[], uint8_t* tot_ref_frames) {
1048
481
    MvReferenceFrame rf[2];
1049
481
    *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
481
    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
481
    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
481
    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
481
    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
481
    prune_sframe_refs(ctx, ppcs, ref_frame_arr, tot_ref_frames);
1100
481
}
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
481
static void ref_mgmt_reset_state(PictureDecisionContext* ctx) {
1165
481
    memset(ctx->pic_id_per_dpb_slot, 0, sizeof(ctx->pic_id_per_dpb_slot));
1166
481
}
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
481
static uint8_t ref_mgmt_stored_mask(const PictureDecisionContext* ctx) {
1175
481
    uint8_t m = 0;
1176
4.32k
    for (uint8_t i = 0; i < REF_FRAMES; ++i) {
1177
3.84k
        if (ctx->pic_id_per_dpb_slot[i] != 0) {
1178
0
            m |= (uint8_t)(1u << i);
1179
0
        }
1180
3.84k
    }
1181
481
    return m;
1182
481
}
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
481
static void apply_ref_mgmt_events(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1381
481
    uint8_t    new_store_slot = (uint8_t)REF_FRAMES;
1382
481
    const bool have_event     = pcs->ref_mgmt.store_id != 0 || pcs->ref_mgmt.clear_id != 0 || pcs->ref_mgmt.use_id != 0;
1383
481
    bool       events_ok      = have_event;
1384
1385
481
    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
481
    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
481
    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
481
    {
1445
481
        const uint8_t stored_mask   = ref_mgmt_stored_mask(ctx);
1446
481
        const uint8_t preserve_mask = (new_store_slot < REF_FRAMES)
1447
481
            ? (uint8_t)(stored_mask & ~(uint8_t)(1u << new_store_slot))
1448
481
            : stored_mask;
1449
481
        const uint8_t orig          = pcs->av1_ref_signal.refresh_frame_mask;
1450
481
        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
481
        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
481
    }
1465
1466
    // Phase 4: USE — override refs, then recovery-point refresh.
1467
481
    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
481
}
1481
1482
481
static void set_key_frame_rps(PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
1483
481
    FrameHeader* frm_hdr = &pcs->frm_hdr;
1484
481
    pd_ctx->lay0_toggle  = 0;
1485
481
    pd_ctx->lay1_toggle  = 0;
1486
    // KF refreshes all 8 DPB slots, so all previously-STOREd refs are invalidated.
1487
481
    ref_mgmt_reset_state(pd_ctx);
1488
1489
481
    frm_hdr->show_frame    = true;
1490
481
    pcs->has_show_existing = false;
1491
481
    return;
1492
481
}
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
962
                                uint32_t referencing_scheme, bool is_overlay) {
1774
962
    if (is_overlay) {
1775
0
        return false;
1776
0
    }
1777
1778
    // Frames below top layer are always used as ref
1779
962
    if (temporal_layer < hierarchical_levels) {
1780
0
        return true;
1781
0
    }
1782
1783
962
    switch (hierarchical_levels) {
1784
0
    case 0:
1785
0
        return true;
1786
0
    case 1:
1787
0
        return referencing_scheme == 0 ? false : true;
1788
962
    case 2:
1789
962
        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
962
    }
1802
1803
0
    return true;
1804
962
}
1805
1806
481
static void set_ref_list_counts(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1807
481
    if (pcs->slice_type == I_SLICE) {
1808
481
        pcs->ref_list0_count = 0;
1809
481
        pcs->ref_list1_count = 0;
1810
481
        return;
1811
481
    }
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
481
                                  uint32_t pic_idx, uint32_t mg_idx) {
1915
481
    Av1RpsNode*         av1_rps             = &pcs->av1_ref_signal;
1916
481
    FrameHeader*        frm_hdr             = &pcs->frm_hdr;
1917
481
    SequenceControlSet* scs                 = pcs->scs;
1918
481
    const uint8_t       hierarchical_levels = pcs->hierarchical_levels;
1919
481
    const uint8_t       temporal_layer      = pcs->temporal_layer_index;
1920
481
#if CONFIG_ENABLE_RANDOM_ACCESS
1921
481
    const uint8_t more_5L_refs = pcs->scs->mrp_ctrls.more_5L_refs;
1922
481
#endif
1923
1924
481
    if (scs->allintra) {
1925
481
        pcs->is_ref = false;
1926
481
    } 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
481
    if (pcs->slice_type == I_SLICE) {
1933
481
        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
481
        if (frm_hdr->frame_type == KEY_FRAME) {
1938
481
            set_key_frame_rps(pcs, ctx);
1939
481
            set_ref_list_counts(pcs, ctx);
1940
481
            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
481
            apply_ref_mgmt_events(pcs, ctx);
1946
481
            return;
1947
481
        }
1948
481
    } 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.40k
bool svt_aom_is_delayed_intra(PictureParentControlSet* pcs) {
3631
2.40k
    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.40k
    } else {
3642
2.40k
        return 0;
3643
2.40k
    }
3644
2.40k
}
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
481
static void mctf_frame(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
4209
481
#if CONFIG_ENABLE_TEMPORAL_FILTERING
4210
481
    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
481
    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
481
    } else {
4255
481
        pcs->do_tf = false; // set temporal filtering flag OFF for current picture
4256
481
    }
4257
#else
4258
    (void)scs;
4259
    pcs->do_tf = false; // temporal filtering compiled out
4260
#endif
4261
4262
481
    pcs->is_noise_level = (pd_ctx->last_i_noise_levels_log1p_fp16[0] >= VQ_NOISE_LVL_TH);
4263
4264
481
#if CONFIG_ENABLE_TEMPORAL_FILTERING
4265
481
    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
481
#endif
4270
481
}
4271
4272
481
bool get_similar_ref_brightness(PictureParentControlSet* pcs) {
4273
481
    bool similar_brightness_refs = false;
4274
481
    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
481
    return similar_brightness_refs;
4287
481
}
4288
4289
481
static void send_picture_out(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4290
481
    EbObjectWrapper* me_wrapper;
4291
481
    EbObjectWrapper* out_results_wrapper;
4292
4293
    //every picture enherits latest motion direction from TF
4294
481
    pcs->tf_motion_direction = ctx->tf_motion_direction;
4295
481
    MrpCtrls* mrp_ctrl       = &(scs->mrp_ctrls);
4296
4297
481
    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
481
    pcs->similar_brightness_refs = get_similar_ref_brightness(pcs);
4327
481
    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
481
    if (pcs->me_data_wrapper == NULL) {
4337
481
        svt_get_empty_object(ctx->me_fifo_ptr, &me_wrapper);
4338
481
        pcs->me_data_wrapper = me_wrapper;
4339
481
        pcs->pa_me_data      = (MotionEstimationData*)me_wrapper->object_ptr;
4340
481
        me_update_param(pcs->pa_me_data, scs);
4341
481
    }
4342
4343
481
    uint8_t ref_count_used_list0 = MAX(mrp_ctrl->base_ref_list0_count, mrp_ctrl->non_base_ref_list0_count);
4344
481
    uint8_t ref_count_used_list1 = MAX(mrp_ctrl->base_ref_list1_count, mrp_ctrl->non_base_ref_list1_count);
4345
4346
481
    uint8_t max_ref_to_alloc, max_cand_to_alloc;
4347
4348
481
    svt_aom_get_max_allocated_me_refs(
4349
481
        ref_count_used_list0, ref_count_used_list1, &max_ref_to_alloc, &max_cand_to_alloc);
4350
4351
481
    pcs->pa_me_data->max_cand = max_cand_to_alloc;
4352
481
    pcs->pa_me_data->max_refs = max_ref_to_alloc;
4353
481
    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
481
    if (scs->static_config.pass == ENC_SINGLE_PASS) {
4363
481
        if (scs->static_config.resize_mode > RESIZE_NONE || scs->static_config.superres_mode == SUPERRES_FIXED ||
4364
481
            scs->static_config.superres_mode == SUPERRES_RANDOM) {
4365
0
            svt_aom_init_resize_picture(scs, pcs);
4366
0
        }
4367
481
    }
4368
481
    bool super_res_off = pcs->frame_superres_enabled == false && scs->static_config.resize_mode == RESIZE_NONE;
4369
481
    svt_aom_set_gm_controls(pcs, svt_aom_derive_gm_level(pcs, super_res_off));
4370
481
    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
481
    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
481
    const uint32_t me_segments_total_count = pcs->me_segments_total_count;
4385
4386
962
    for (uint32_t segment_index = 0; segment_index < me_segments_total_count; ++segment_index) {
4387
        // Get Empty Results Object
4388
481
        svt_get_empty_object(ctx->picture_decision_results_output_fifo_ptr, &out_results_wrapper);
4389
4390
481
        PictureDecisionResults* out_results = (PictureDecisionResults*)out_results_wrapper->object_ptr;
4391
481
        out_results->pcs_wrapper            = pcs->p_pcs_wrapper_ptr;
4392
481
        out_results->segment_index          = segment_index;
4393
481
        out_results->task_type              = TASK_PAME;
4394
        //Post the Full Results Object
4395
481
        svt_post_full_object(out_results_wrapper);
4396
481
    }
4397
481
}
4398
4399
/***************************************************************************************************
4400
* Store the pcs pointers in the gf group, set the gf_interval and gf_update_due
4401
***************************************************************************************************/
4402
481
void store_gf_group(PictureParentControlSet* pcs, PictureDecisionContext* ctx, uint32_t mg_size) {
4403
481
    if (pcs->slice_type == I_SLICE || (!svt_aom_is_delayed_intra(pcs) && pcs->temporal_layer_index == 0) ||
4404
481
        svt_aom_is_incomp_mg_frame(pcs)) {
4405
481
        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
481
        } else {
4410
481
            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
481
            svt_memcpy(&pcs->gf_group[0], ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
4414
481
            pcs->gf_interval = mg_size;
4415
481
        }
4416
4417
481
        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
962
        for (int pic_i = 0; pic_i < pcs->gf_interval; ++pic_i) {
4423
481
            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
481
                svt_aom_is_incomp_mg_frame(pcs->gf_group[pic_i])) {
4426
481
                pcs->gf_group[pic_i]->gf_update_due = 1;
4427
481
            } 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
481
            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
481
        }
4441
481
    }
4442
481
}
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
481
static void copy_tf_params(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4493
    // Map TF settings scs -> pcs
4494
481
    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
481
    if ((pcs->frm_hdr.frame_type == KEY_FRAME && !scs->static_config.enable_tf_key) || pcs->is_overlay ||
4511
481
        pcs->temporal_layer_index == pcs->hierarchical_levels) {
4512
0
        pcs->tf_ctrls.enabled = 0;
4513
481
    } else if (svt_aom_is_delayed_intra(pcs)) {
4514
0
        pcs->tf_ctrls = scs->tf_params_per_type[0];
4515
481
    } else if (pcs->temporal_layer_index == 0) { // BASE
4516
481
        pcs->tf_ctrls = scs->tf_params_per_type[1];
4517
481
    } 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
481
}
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
481
void update_count_try(SequenceControlSet* scs, PictureParentControlSet* pcs) {
4532
481
    MrpCtrls* mrp_ctrl = &scs->mrp_ctrls;
4533
481
    if (frame_is_boosted(pcs)) {
4534
481
        pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->base_ref_list0_count);
4535
481
        pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->base_ref_list1_count);
4536
481
    } 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
481
}
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
481
static void update_rc_param_queue(PictureParentControlSet* ppcs, EncodeContext* enc_cxt) {
4572
481
    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
481
    ppcs->rate_control_param_ptr = enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index];
4594
481
}
4595
4596
/****************************************************************************************
4597
* set_layer_depth()
4598
* Set the layer depth per frame based on frame type, temporal layer
4599
****************************************************************************************/
4600
481
static void set_layer_depth(PictureParentControlSet* ppcs) {
4601
    // SequenceControlSet *scs = ppcs->scs;
4602
481
    if (ppcs->frm_hdr.frame_type == KEY_FRAME) {
4603
481
        ppcs->layer_depth = 0;
4604
481
    } else {
4605
0
        ppcs->layer_depth = ppcs->temporal_layer_index + 1;
4606
0
    }
4607
481
}
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
481
static void set_frame_update_type(PictureParentControlSet* ppcs) {
4616
481
    if (ppcs->frm_hdr.frame_type == KEY_FRAME) {
4617
481
        ppcs->update_type = SVT_AV1_KF_UPDATE;
4618
481
    } 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
481
}
4635
4636
481
static void set_gf_group_param(PictureParentControlSet* ppcs) {
4637
481
    set_frame_update_type(ppcs);
4638
481
    set_layer_depth(ppcs);
4639
481
}
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
481
                                      PictureDecisionReorderEntry* queue_entry, bool* window_avail, bool* eos_reached) {
4663
481
    *eos_reached  = ((PictureParentControlSet*)(queue_entry->ppcs_wrapper->object_ptr))->end_of_sequence_flag == true;
4664
481
    *window_avail = true;
4665
4666
481
    unsigned int previous_entry_index = QUEUE_GET_PREVIOUS_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4667
481
                                                                enc_ctx->picture_decision_reorder_queue_size);
4668
481
    memset(pcs->pd_window, 0, (2 + scs->scd_delay) * sizeof(PictureParentControlSet*));
4669
    //for poc 0, ignore previous frame check
4670
481
    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
481
    } 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
481
        pcs->pd_window[0] = queue_entry->picture_number > 0
4677
481
            ? (PictureParentControlSet*)enc_ctx->picture_decision_reorder_queue[previous_entry_index]
4678
0
                  ->ppcs_wrapper->object_ptr
4679
481
            : NULL;
4680
481
        pcs->pd_window[1] = (PictureParentControlSet*)enc_ctx
4681
481
                                ->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index]
4682
481
                                ->ppcs_wrapper->object_ptr;
4683
481
        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
481
    }
4703
481
}
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
481
                                   PictureDecisionContext* ctx) {
4746
481
    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
481
    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
481
    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
481
    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
481
    ctx->mini_gop_start_index[0] = 0;
4763
481
    ctx->mini_gop_end_index[0]   = enc_ctx->pre_assignment_buffer_count - 1;
4764
481
    ctx->mini_gop_length[0]      = enc_ctx->pre_assignment_buffer_count;
4765
4766
481
    ctx->mini_gop_hierarchical_levels[0]           = next_mg_hierarchical_levels;
4767
481
    ctx->mini_gop_intra_count[0]                   = enc_ctx->pre_assignment_buffer_intra_count;
4768
481
    ctx->mini_gop_idr_count[0]                     = enc_ctx->pre_assignment_buffer_idr_count;
4769
481
    ctx->total_number_of_mini_gops                 = 1;
4770
481
    enc_ctx->previous_mini_gop_hierarchical_levels = (pcs->picture_number == 0)
4771
481
        ? next_mg_hierarchical_levels
4772
481
        : enc_ctx->previous_mini_gop_hierarchical_levels;
4773
481
    enc_ctx->mini_gop_cnt_per_gop = (enc_ctx->pre_assignment_buffer_idr_count) ? 0 : enc_ctx->mini_gop_cnt_per_gop + 1;
4774
481
    assert(IMPLIES(enc_ctx->pre_assignment_buffer_intra_count == enc_ctx->pre_assignment_buffer_count,
4775
481
                   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
481
    if (enc_ctx->pre_assignment_buffer_count > 1 ||
4781
481
        (!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
481
    get_pred_struct_for_all_frames(ctx, enc_ctx);
4790
481
}
4791
4792
// Set whether the picture is to be considered as SC; for single-threaded mode we perform SC detection here
4793
481
static void perform_sc_detection(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4794
481
    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
481
        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
481
        ctx->last_i_picture_sc_class0      = pcs->sc_class0;
4820
481
        ctx->last_i_picture_sc_class1      = pcs->sc_class1;
4821
481
        ctx->last_i_picture_sc_class2      = pcs->sc_class2;
4822
481
        ctx->last_i_picture_sc_class3      = pcs->sc_class3;
4823
481
        ctx->last_i_picture_sc_class4      = pcs->sc_class4;
4824
481
        ctx->last_i_picture_sc_class5      = pcs->sc_class5;
4825
481
        ctx->last_i_is_luma_dominant_input = pcs->is_luma_dominant_input;
4826
481
    } 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
481
}
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
481
                                            SliceType* picture_type, PredictionStructureEntry** pred_position_ptr) {
4842
481
    (void)scs;
4843
    // Keep track of the mini GOP size to which the input picture belongs - needed @ PictureManagerProcess()
4844
481
    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
481
    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
481
    } else {
4857
        // Set the Picture Type
4858
481
        *picture_type = (pcs->idr_flag || pcs->cra_flag) ? I_SLICE : B_SLICE;
4859
481
    }
4860
    // If mini GOP switch, reset position
4861
481
    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
481
    if (pcs->idr_flag == true) {
4867
481
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
4868
481
    } 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
481
    if (pcs->idr_flag == true) {
4884
481
        enc_ctx->last_idr_picture = pcs->picture_number;
4885
481
    } else {
4886
0
        pcs->last_idr_picture = enc_ctx->last_idr_picture;
4887
0
    }
4888
    // Cycle the PredStructPosition if its overflowed
4889
481
    enc_ctx->pred_struct_position = (enc_ctx->pred_struct_position == pcs->pred_struct_ptr->pred_struct_entry_count)
4890
481
        ? enc_ctx->pred_struct_position - pcs->pred_struct_ptr->pred_struct_entry_count
4891
481
        : enc_ctx->pred_struct_position;
4892
4893
481
    *pred_position_ptr = pcs->pred_struct_ptr->pred_struct_entry_ptr_array[enc_ctx->pred_struct_position];
4894
481
}
4895
4896
static uint32_t get_pic_idx_in_mg(SequenceControlSet* scs, EncodeContext* enc_ctx, PictureParentControlSet* pcs,
4897
481
                                  PictureDecisionContext* ctx, uint32_t pic_idx, uint32_t mini_gop_index) {
4898
481
    uint32_t pic_idx_in_mg = 0;
4899
481
    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
481
    } 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
481
    return pic_idx_in_mg;
4916
481
}
4917
4918
481
static void set_ref_frame_sign_bias(SequenceControlSet* scs, PictureParentControlSet* pcs) {
4919
481
    memset(pcs->av1_cm->ref_frame_sign_bias, 0, 8 * sizeof(int32_t));
4920
4921
481
    if (scs->seq_header.order_hint_info.enable_order_hint) {
4922
3.84k
        for (MvReferenceFrame ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
4923
3.36k
            pcs->av1_cm->ref_frame_sign_bias[ref_frame] = (get_relative_dist(&scs->seq_header.order_hint_info,
4924
3.36k
                                                                             pcs->ref_order_hint[ref_frame - 1],
4925
3.36k
                                                                             (int)pcs->cur_order_hint) <= 0)
4926
3.36k
                ? 0
4927
3.36k
                : 1;
4928
3.36k
        }
4929
481
    }
4930
481
}
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
481
static void init_pic_settings(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4935
481
    FrameHeader* frm_hdr        = &pcs->frm_hdr;
4936
481
    pcs->allow_comp_inter_inter = pcs->slice_type != I_SLICE;
4937
481
    frm_hdr->reference_mode     = pcs->slice_type == I_SLICE ? (ReferenceMode)0xFF
4938
481
            : svt_aom_is_incomp_mg_frame(pcs)                ? SINGLE_REFERENCE
4939
0
                                                             : REFERENCE_MODE_SELECT;
4940
4941
481
    pcs->av1_cm->mi_cols = pcs->aligned_width >> MI_SIZE_LOG2;
4942
481
    pcs->av1_cm->mi_rows = pcs->aligned_height >> MI_SIZE_LOG2;
4943
4944
    // Initialize the order hints
4945
481
    const OrderHintInfo* const order_hint_info = &pcs->scs->seq_header.order_hint_info;
4946
481
    uint32_t*                  ref_order_hint  = pcs->ref_order_hint;
4947
3.84k
    for (uint8_t i = 0; i < INTER_REFS_PER_FRAME; ++i) {
4948
3.36k
        ref_order_hint[i] = pcs->av1_ref_signal.ref_poc_array[i] % (uint64_t)(1 << (order_hint_info->order_hint_bits));
4949
3.36k
    }
4950
481
    pcs->cur_order_hint = pcs->picture_number % (uint64_t)(1 << (order_hint_info->order_hint_bits));
4951
4952
481
    set_ref_frame_sign_bias(scs, pcs);
4953
4954
    // TODO: put this in EbMotionEstimationProcess?
4955
481
    copy_tf_params(scs, pcs, ctx);
4956
    // TODO: put this in EbMotionEstimationProcess?
4957
    // ME Kernel Multi-Processes Signal(s) derivation
4958
481
    const bool rtc_tune = SVT_RTC_TUNE(scs);
4959
481
    const bool allintra = SVT_ALLINTRA(scs);
4960
481
    allintra       ? svt_aom_sig_deriv_multi_processes_allintra(scs, pcs)
4961
481
        : rtc_tune ? svt_aom_sig_deriv_multi_processes_rtc(scs, pcs)
4962
0
                   : svt_aom_sig_deriv_multi_processes_default(scs, pcs);
4963
4964
481
    update_count_try(scs, pcs);
4965
4966
481
    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
481
    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
481
    assert(pcs->ref_list0_count_try <= pcs->ref_list0_count);
4977
481
    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
481
    svt_av1_setup_skip_mode_allowed(pcs);
4981
481
    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
481
    set_all_ref_frame_type(ctx, pcs, pcs->ref_frame_type_arr, &pcs->tot_ref_frame_types);
4985
481
}
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
481
static void store_mg_picture_arrays(PictureDecisionContext* ctx) {
4990
481
    const unsigned int mg_size = ctx->mg_size;
4991
4992
    // mg_pictures_array arrives in display order, so copy into display order array
4993
481
    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
481
    PictureParentControlSet** mg_pics = &ctx->mg_pictures_array[0];
4997
481
    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
481
}
5007
5008
// return true if the frame is part of an incomplete MG (at the end of a GOP)
5009
1.44k
bool svt_aom_is_incomp_mg_frame(PictureParentControlSet* pcs) {
5010
1.44k
    return (pcs->pred_struct_ptr->pred_type == LOW_DELAY && pcs->scs->static_config.pred_structure == RANDOM_ACCESS);
5011
1.44k
}
5012
5013
static void assign_and_release_pa_refs(EncodeContext* enc_ctx, PictureParentControlSet* pcs,
5014
481
                                       PictureDecisionContext* ctx) {
5015
481
    const unsigned int mg_size = ctx->mg_size;
5016
962
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5017
481
        pcs = ctx->mg_pictures_array[pic_i];
5018
481
        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
481
        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
481
        if (pcs->av1_ref_signal.refresh_frame_mask) {
5048
            //assert(!pcs->is_overlay); // is this true?
5049
            //Update the DPB
5050
4.32k
            for (uint8_t i = 0; i < REF_FRAMES; i++) {
5051
3.84k
                if ((pcs->av1_ref_signal.refresh_frame_mask >> i) & 1) {
5052
3.84k
                    svt_block_on_mutex(enc_ctx->pd_dpb_mutex);
5053
                    // Get the current entry at that spot in the DPB
5054
3.84k
                    PaReferenceEntry* input_entry = enc_ctx->pd_dpb[i];
5055
5056
                    // If DPB entry is occupied, release the current entry
5057
3.84k
                    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.84k
                    input_entry->input_object_ptr = pcs->pa_ref_pic_wrapper;
5087
3.84k
                    input_entry->picture_number   = pcs->picture_number;
5088
3.84k
                    input_entry->is_valid         = true;
5089
3.84k
                    input_entry->decode_order     = pcs->decode_order;
5090
3.84k
                    input_entry->is_alt_ref       = pcs->is_alt_ref;
5091
3.84k
                    input_entry->y8b_wrapper      = pcs->y8b_wrapper;
5092
5093
3.84k
                    svt_object_inc_live_count(input_entry->input_object_ptr, 1);
5094
5095
3.84k
                    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.84k
                        svt_object_inc_live_count(input_entry->y8b_wrapper, 1);
5098
3.84k
                    }
5099
3.84k
                    svt_release_mutex(enc_ctx->pd_dpb_mutex);
5100
3.84k
                }
5101
3.84k
            }
5102
481
        } else {
5103
0
            assert(!pcs->is_ref);
5104
0
        }
5105
481
        pcs->released_pics_count = released_pics_idx;
5106
481
    }
5107
481
}
5108
5109
// Send pictures to TF and ME
5110
481
static void process_pics(SequenceControlSet* scs, PictureDecisionContext* ctx) {
5111
481
    PictureParentControlSet* pcs     = NULL; // init'd to quiet build warnings
5112
481
    const unsigned int       mg_size = ctx->mg_size;
5113
    // Process previous delayed Intra if we have one
5114
481
    if (ctx->prev_delayed_intra) {
5115
0
        pcs = ctx->prev_delayed_intra;
5116
0
        store_gf_group(pcs, ctx, mg_size);
5117
481
    } else {
5118
962
        for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5119
481
            pcs = ctx->mg_pictures_array_disp_order[pic_i];
5120
481
            if (svt_aom_is_delayed_intra(pcs) == false) {
5121
481
                store_gf_group(pcs, ctx, mg_size);
5122
481
            }
5123
481
        }
5124
481
    }
5125
    //Process previous delayed Intra if we have one
5126
481
    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
962
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5137
481
        pcs = ctx->mg_pictures_array_disp_order[pic_i];
5138
5139
481
        if (svt_aom_is_delayed_intra(pcs) == false) {
5140
481
            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
481
            pcs->filt_to_unfilt_diff = ctx->filt_to_unfilt_diff;
5146
481
            mctf_frame(scs, pcs, ctx);
5147
481
            ctx->filt_to_unfilt_diff = pcs->slice_type == I_SLICE ? pcs->filt_to_unfilt_diff : ctx->filt_to_unfilt_diff;
5148
481
            ctx->gm_pp_last_detected = pcs->gm_pp_enabled ? pcs->gm_pp_detected : ctx->gm_pp_last_detected;
5149
481
        }
5150
481
    }
5151
5152
481
    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
481
    uint8_t ldp_delayi_mg = 0;
5160
481
    uint8_t ldp_i_eos_mg  = 0;
5161
5162
    // Special considerations for I_SLICE after incomplete MG pic
5163
481
    if (ctx->mg_pictures_array[mg_size - 1]->slice_type == I_SLICE &&
5164
481
        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
962
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5174
481
        pcs = ctx->mg_pictures_array[pic_i];
5175
481
        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
481
        } else {
5185
481
            pcs->ext_mg_id   = ctx->mg_progress_id;
5186
481
            pcs->ext_mg_size = ldp_delayi_mg || ldp_i_eos_mg ? mg_size - 1 : mg_size;
5187
5188
481
            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
481
            pcs->gm_pp_detected = ctx->gm_pp_last_detected;
5194
481
            send_picture_out(scs, pcs, ctx);
5195
481
        }
5196
481
    }
5197
5198
481
    ctx->mg_progress_id++;
5199
481
}
5200
5201
// update the DPB stored in the PD context
5202
481
static void update_dpb(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
5203
481
    Av1RpsNode* av1_rps = &pcs->av1_ref_signal;
5204
481
    if (av1_rps->refresh_frame_mask) {
5205
4.32k
        for (int i = 0; i < REF_FRAMES; i++) {
5206
3.84k
            if ((av1_rps->refresh_frame_mask >> i) & 1) {
5207
3.84k
                ctx->dpb[i].picture_number       = pcs->picture_number;
5208
3.84k
                ctx->dpb[i].decode_order         = pcs->decode_order;
5209
3.84k
                ctx->dpb[i].temporal_layer_index = pcs->temporal_layer_index;
5210
3.84k
            }
5211
3.84k
        }
5212
481
    }
5213
481
}
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
962
EbErrorType svt_aom_picture_decision_kernel_iter(void* context) {
5341
962
    PictureDecisionContext* ctx = (PictureDecisionContext*)context;
5342
5343
962
    PictureParentControlSet* pcs;
5344
5345
962
    EncodeContext*          enc_ctx;
5346
962
    SequenceControlSet*     scs;
5347
962
    EbObjectWrapper*        in_results_wrapper_ptr;
5348
962
    PictureAnalysisResults* in_results_ptr;
5349
5350
962
    PredictionStructureEntry* pred_position_ptr;
5351
5352
962
    PictureDecisionReorderEntry* queue_entry_ptr;
5353
5354
962
    unsigned int pic_idx;
5355
5356
    // Get Input Full Object
5357
962
    EB_GET_FULL_OBJECT(ctx->picture_analysis_results_input_fifo_ptr, &in_results_wrapper_ptr);
5358
5359
481
    in_results_ptr      = (PictureAnalysisResults*)in_results_wrapper_ptr->object_ptr;
5360
481
    pcs                 = (PictureParentControlSet*)in_results_ptr->pcs_wrapper->object_ptr;
5361
481
    scs                 = pcs->scs;
5362
481
    enc_ctx             = scs->enc_ctx;
5363
481
    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
481
    if (!pcs->is_overlay) {
5369
481
        int queue_entry_index =
5370
481
            (int)(pcs->picture_number -
5371
481
                  enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index]
5372
481
                      ->picture_number);
5373
481
        queue_entry_index += enc_ctx->picture_decision_reorder_queue_head_index;
5374
481
        queue_entry_index = (queue_entry_index > (int)(enc_ctx->picture_decision_reorder_queue_size - 1))
5375
481
            ? queue_entry_index - (int)enc_ctx->picture_decision_reorder_queue_size
5376
481
            : queue_entry_index;
5377
481
        queue_entry_ptr   = enc_ctx->picture_decision_reorder_queue[queue_entry_index];
5378
481
        if (queue_entry_ptr->ppcs_wrapper != NULL) {
5379
0
            CHECK_REPORT_ERROR_NC(enc_ctx->app_callback_ptr, EB_ENC_PD_ERROR8);
5380
481
        } else {
5381
481
            queue_entry_ptr->ppcs_wrapper   = in_results_ptr->pcs_wrapper;
5382
481
            queue_entry_ptr->picture_number = pcs->picture_number;
5383
481
        }
5384
5385
481
        pcs->pic_decision_reorder_queue_idx = queue_entry_index;
5386
481
        pcs->first_pass_done                = 0;
5387
481
    }
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
481
    queue_entry_ptr = enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index];
5391
5392
962
    while (queue_entry_ptr->ppcs_wrapper != NULL) {
5393
481
        if (scs->lap_rc) {
5394
0
            process_first_pass(scs, enc_ctx);
5395
0
        }
5396
5397
481
        pcs = (PictureParentControlSet*)queue_entry_ptr->ppcs_wrapper->object_ptr;
5398
481
        bool window_avail, eos_reached;
5399
481
        check_window_availability(scs, enc_ctx, pcs, queue_entry_ptr, &window_avail, &eos_reached);
5400
5401
481
        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
481
        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
481
        enc_ctx->pre_assignment_buffer[enc_ctx->pre_assignment_buffer_count] = queue_entry_ptr->ppcs_wrapper;
5420
5421
        // Set the POC Number
5422
481
        pcs->picture_number                 = ++ctx->current_input_poc;
5423
481
        pcs->pred_structure                 = scs->static_config.pred_structure;
5424
481
        pcs->hierarchical_layers_diff       = 0;
5425
481
        pcs->init_pred_struct_position_flag = false;
5426
481
        pcs->tpl_group_size                 = 0;
5427
481
        if (pcs->picture_number == 0) {
5428
481
            ctx->prev_delayed_intra = NULL;
5429
481
        }
5430
481
        if (pcs->picture_number == 0) {
5431
481
            ctx->sframe_hier_lvls = scs->static_config.hierarchical_levels;
5432
481
        }
5433
5434
481
        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
481
        if (allintra) {
5438
481
            pcs->idr_flag = true;
5439
481
            pcs->cra_flag = false;
5440
481
        }
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
481
        pcs->idr_flag = (scs->static_config.intra_refresh_type != SVT_AV1_KF_REFRESH)            ? pcs->idr_flag
5456
481
            : (pcs->scene_change_flag == true || pcs->input_ptr->pic_type == EB_AV1_KEY_PICTURE) ? true
5457
481
                                                                                                 : pcs->idr_flag;
5458
481
        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
481
        enc_ctx->pre_assignment_buffer_eos_flag = (pcs->end_of_sequence_flag) ? (uint32_t)true
5469
481
                                                                              : 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
481
        if (scs->calc_hist) {
5474
0
            copy_histograms(pcs, ctx);
5475
0
        }
5476
5477
        // Increment the Pre-Assignment Buffer Intra Count
5478
481
        enc_ctx->pre_assignment_buffer_intra_count += (pcs->idr_flag || pcs->cra_flag);
5479
481
        enc_ctx->pre_assignment_buffer_idr_count += pcs->idr_flag;
5480
481
        enc_ctx->pre_assignment_buffer_count += 1;
5481
5482
        // Increment the Intra Period Position
5483
481
        enc_ctx->intra_period_position = ((enc_ctx->intra_period_position ==
5484
481
                                           (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
481
            ? 0
5488
481
            : 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
481
        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
481
        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
481
        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
481
        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
481
            (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
481
            set_mini_gop_structure(scs, enc_ctx, pcs, ctx);
5512
5513
            // Loop over Mini GOPs
5514
962
            for (unsigned int mini_gop_index = 0; mini_gop_index < ctx->total_number_of_mini_gops; ++mini_gop_index) {
5515
481
                bool pre_assignment_buffer_first_pass_flag = true;
5516
5517
                // Get the 1st PCS in the mini-GOP
5518
481
                pcs = (PictureParentControlSet*)enc_ctx
5519
481
                          ->pre_assignment_buffer[ctx->mini_gop_start_index[mini_gop_index]]
5520
481
                          ->object_ptr;
5521
5522
                // Derive the temporal layer difference between the current mini GOP and the previous mini GOP
5523
481
                pcs->hierarchical_layers_diff = (int32_t)enc_ctx->previous_mini_gop_hierarchical_levels -
5524
481
                    (int32_t)pcs->hierarchical_levels;
5525
5526
                // Set init_pred_struct_position_flag to true if mini-GOP switch
5527
481
                pcs->init_pred_struct_position_flag = enc_ctx->is_mini_gop_changed = (pcs->hierarchical_layers_diff !=
5528
481
                                                                                      0);
5529
5530
                // Keep track of the number of hierarchical levels of the latest implemented mini GOP
5531
481
                enc_ctx->previous_mini_gop_hierarchical_levels = ctx->mini_gop_hierarchical_levels[mini_gop_index];
5532
481
                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
481
                for (pic_idx = ctx->mini_gop_start_index[mini_gop_index];
5536
962
                     pic_idx <= ctx->mini_gop_end_index[mini_gop_index];
5537
481
                     ++pic_idx) {
5538
481
                    pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
5539
481
                    scs = pcs->scs;
5540
5541
481
                    update_pred_struct_and_pic_type(scs,
5542
481
                                                    enc_ctx,
5543
481
                                                    pcs,
5544
481
                                                    ctx,
5545
481
                                                    mini_gop_index,
5546
481
                                                    pre_assignment_buffer_first_pass_flag,
5547
481
                                                    &pcs->slice_type,
5548
481
                                                    &pred_position_ptr);
5549
5550
481
                    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
481
                    pcs->pic_idx_in_mg = get_pic_idx_in_mg(scs, enc_ctx, pcs, ctx, pic_idx, mini_gop_index);
5572
5573
962
                    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
481
                        if (loop_index == 1) {
5576
0
                            pcs = pcs->overlay_ppcs_ptr;
5577
0
                            initialize_overlay_frame(pcs);
5578
481
                        } else {
5579
481
                            assert(!pcs->is_overlay);
5580
481
                            pcs->pred_struct_index    = (uint8_t)enc_ctx->pred_struct_position;
5581
481
                            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
481
                            pcs->is_highest_layer = (pcs->temporal_layer_index == pcs->hierarchical_levels) &&
5584
0
                                pcs->hierarchical_levels != 0;
5585
481
                            switch (pcs->slice_type) {
5586
481
                            case I_SLICE:
5587
5588
                                // Reset Prediction Structure Position & Reference Struct Position
5589
481
                                if (pcs->picture_number == 0) {
5590
481
                                    enc_ctx->intra_period_position = 0;
5591
481
                                }
5592
481
                                enc_ctx->elapsed_non_cra_count = 0;
5593
5594
                                // I_SLICE cannot be CRA and IDR
5595
481
                                pcs->cra_flag = !pcs->idr_flag;
5596
5597
481
                                if (pcs->idr_flag) {
5598
481
                                    enc_ctx->elapsed_non_idr_count = 0; // Reset the pictures since last IDR counter
5599
481
                                    ctx->key_poc                   = pcs->picture_number; // log latest key frame poc
5600
481
                                }
5601
481
                                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
481
                            }
5624
481
                        }
5625
5626
481
                        CHECK_REPORT_ERROR((pcs->pred_struct_ptr->pred_struct_entry_count * REF_LIST_MAX_DEPTH <
5627
481
                                            MAX_ELAPSED_IDR_COUNT),
5628
481
                                           enc_ctx->app_callback_ptr,
5629
481
                                           EB_ENC_PD_ERROR5);
5630
481
                    }
5631
481
                    pre_assignment_buffer_first_pass_flag = false;
5632
481
                }
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
481
                const uint32_t has_overlay = ((PictureParentControlSet*)enc_ctx
5638
481
                                                  ->pre_assignment_buffer[ctx->mini_gop_end_index[mini_gop_index]]
5639
481
                                                  ->object_ptr)
5640
481
                                                 ->is_alt_ref
5641
481
                    ? 1
5642
481
                    : 0;
5643
481
                for (pic_idx = ctx->mini_gop_start_index[mini_gop_index];
5644
962
                     pic_idx <= ctx->mini_gop_end_index[mini_gop_index] + has_overlay;
5645
481
                     ++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
481
                    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
481
                    } else {
5653
481
                        pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
5654
481
                    }
5655
5656
481
                    pcs->picture_number_alt = enc_ctx->picture_number_alt++;
5657
5658
                    // Set the Decode Order
5659
481
                    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
481
                    } else {
5665
481
                        pcs->decode_order = pcs->picture_number_alt;
5666
481
                    }
5667
5668
481
                    perform_sc_detection(scs, pcs, ctx);
5669
                    // Update the RC param queue
5670
481
                    update_rc_param_queue(pcs, enc_ctx);
5671
                    // Reset the PA Reference Lists
5672
481
                    EB_MEMSET(pcs->ref_pa_pic_ptr_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5673
481
                    EB_MEMSET(pcs->ref_pa_pic_ptr_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5674
481
                    EB_MEMSET(pcs->ref_y8b_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5675
481
                    EB_MEMSET(pcs->ref_y8b_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5676
481
                    EB_MEMSET(pcs->ref_pic_poc_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(uint64_t));
5677
481
                    EB_MEMSET(pcs->ref_pic_poc_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(uint64_t));
5678
5679
481
                    uint32_t pic_it                = pic_idx - ctx->mini_gop_start_index[mini_gop_index];
5680
481
                    ctx->mg_pictures_array[pic_it] = pcs;
5681
481
                    if (pic_idx == ctx->mini_gop_end_index[mini_gop_index] + has_overlay) {
5682
                        // Increment the Decode Base Number
5683
481
                        enc_ctx->decode_base_number += ctx->mini_gop_length[mini_gop_index] + has_overlay;
5684
481
                    }
5685
481
                }
5686
5687
481
                ctx->mg_size = ctx->mini_gop_end_index[mini_gop_index] + has_overlay -
5688
481
                    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
481
                store_mg_picture_arrays(ctx);
5693
5694
481
                const unsigned int mg_size = ctx->mg_size;
5695
962
                for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5696
                    // Loop over pics in decode order
5697
481
                    pcs = ctx->mg_pictures_array[pic_i];
5698
481
                    if (pcs->slice_type == I_SLICE) {
5699
481
                        pcs->frm_hdr.frame_type = pcs->idr_flag ? KEY_FRAME : INTRA_ONLY_FRAME;
5700
481
                    } else {
5701
0
                        pcs->frm_hdr.frame_type = INTER_FRAME;
5702
0
                    }
5703
481
                    set_gf_group_param(pcs);
5704
481
                    av1_generate_rps_info(pcs, enc_ctx, ctx, pcs->pic_idx_in_mg, mini_gop_index);
5705
5706
481
                    if (scs->static_config.sframe_dist != 0 || !pcs->is_not_scaled ||
5707
481
                        scs->static_config.sframe_posi.sframe_posis) {
5708
0
                        update_sframe_ref_order_hint(pcs, ctx);
5709
0
                    }
5710
5711
481
                    update_dpb(pcs, ctx);
5712
5713
                    // Set picture settings, incl. normative frame header fields and feature levels in signal_derivation function
5714
481
                    init_pic_settings(scs, pcs, ctx);
5715
481
                }
5716
5717
962
                for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5718
481
                    PictureParentControlSet* pcs_1 = ctx->mg_pictures_array_disp_order[pic_i];
5719
481
                    pcs_1->first_frame_in_minigop  = !pic_i;
5720
481
                    if (pcs_1->is_alt_ref) {
5721
0
                        ctx->mg_pictures_array_disp_order[pic_i - 1]->has_show_existing = false;
5722
0
                    }
5723
481
                }
5724
5725
                // Loop over pics in MG and assign their PA reference buffers; release buffers when no longer needed
5726
481
                assign_and_release_pa_refs(enc_ctx, pcs, ctx);
5727
5728
                // Send the pictures in the MG to TF and ME
5729
481
                process_pics(scs, ctx);
5730
481
            } // End MINI GOPs loop
5731
            // Reset the Pre-Assignment Buffer
5732
481
            enc_ctx->pre_assignment_buffer_count       = 0;
5733
481
            enc_ctx->pre_assignment_buffer_idr_count   = 0;
5734
481
            enc_ctx->pre_assignment_buffer_intra_count = 0;
5735
481
            enc_ctx->pre_assignment_buffer_eos_flag    = false;
5736
481
        }
5737
        // Increment the Picture Decision Reordering Queue Head Ptr
5738
481
        enc_ctx->picture_decision_reorder_queue_head_index = (enc_ctx->picture_decision_reorder_queue_head_index ==
5739
481
                                                              enc_ctx->picture_decision_reorder_queue_size - 1)
5740
481
            ? 0
5741
481
            : 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
481
        queue_entry_ptr = enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index];
5745
481
    }
5746
5747
481
    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
481
    svt_release_object(in_results_wrapper_ptr);
5755
481
    return EB_ErrorNone;
5756
481
}
5757
5758
481
void* svt_aom_picture_decision_kernel(void* input_ptr) {
5759
481
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
5760
962
    for (;;) {
5761
962
        EbErrorType err = svt_aom_picture_decision_kernel_iter(thread_ctx->priv);
5762
962
        if (err == EB_NoErrorFifoShutdown) {
5763
481
            return NULL;
5764
481
        }
5765
962
    }
5766
0
    return NULL;
5767
481
}