Coverage Report

Created: 2026-07-30 06:27

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.39k
static INLINE int get_relative_dist(const OrderHintInfo* oh, int a, int b) {
88
3.39k
    if (!oh->enable_order_hint) {
89
0
        return 0;
90
0
    }
91
92
3.39k
    const int bits = oh->order_hint_bits;
93
94
3.39k
    assert(bits >= 1);
95
3.39k
    assert(a >= 0 && a < (1 << bits));
96
3.39k
    assert(b >= 0 && b < (1 << bits));
97
98
3.39k
    int       diff = a - b;
99
3.39k
    const int m    = 1 << (bits - 1);
100
3.39k
    diff           = (diff & (m - 1)) - (diff & m);
101
3.39k
    return diff;
102
3.39k
}
103
104
485
void svt_av1_setup_skip_mode_allowed(PictureParentControlSet* pcs) {
105
485
    FrameHeader*               frm_hdr         = &pcs->frm_hdr;
106
485
    const OrderHintInfo* const order_hint_info = &pcs->scs->seq_header.order_hint_info;
107
485
    SkipModeInfo* const        skip_mode_info  = &frm_hdr->skip_mode_params;
108
109
485
    skip_mode_info->skip_mode_allowed = 0;
110
485
    skip_mode_info->ref_frame_idx_0   = INVALID_IDX;
111
485
    skip_mode_info->ref_frame_idx_1   = INVALID_IDX;
112
113
485
    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
485
    if (!order_hint_info->enable_order_hint || pcs->slice_type == I_SLICE /*frame_is_intra_only(cm)*/ ||
117
485
        frm_hdr->reference_mode == SINGLE_REFERENCE) {
118
485
        return;
119
485
    }
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
485
#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
485
static void picture_decision_context_dctor(EbPtr p) {
180
485
    EbThreadContext*        thread_ctx = (EbThreadContext*)p;
181
485
    PictureDecisionContext* obj        = (PictureDecisionContext*)thread_ctx->priv;
182
183
485
    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
485
    EB_FREE_2D(obj->ahd_running_avg);
200
485
    EB_FREE_2D(obj->ahd_running_avg_cr);
201
485
    EB_FREE_2D(obj->ahd_running_avg_cb);
202
485
    EB_FREE_ARRAY(obj);
203
485
}
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
485
                                                  uint8_t calc_hist) {
210
485
    PictureDecisionContext* pd_ctx;
211
485
    EB_CALLOC_ARRAY(pd_ctx, 1);
212
485
    thread_ctx->priv  = pd_ctx;
213
485
    thread_ctx->dctor = picture_decision_context_dctor;
214
215
485
    memset(pd_ctx->tf_pic_array, 0, (1 << MAX_TEMPORAL_LAYERS) * sizeof(PictureParentControlSet*));
216
485
    pd_ctx->tf_pic_arr_cnt                          = 0;
217
485
    pd_ctx->picture_analysis_results_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
218
485
        enc_handle_ptr->picture_analysis_results_resource_ptr, 0);
219
485
    pd_ctx->picture_decision_results_output_fifo_ptr = svt_system_resource_get_producer_fifo(
220
485
        enc_handle_ptr->picture_decision_results_resource_ptr, 0);
221
485
    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
485
    pd_ctx->reset_running_avg = true;
241
485
    pd_ctx->me_fifo_ptr       = svt_system_resource_get_producer_fifo(enc_handle_ptr->me_pool_ptr, 0);
242
243
485
    pd_ctx->mg_progress_id                    = 0;
244
485
    pd_ctx->last_i_noise_levels_log1p_fp16[0] = 0;
245
485
    pd_ctx->transition_detected               = -1;
246
485
    pd_ctx->sframe_poc                        = 0;
247
485
    pd_ctx->sframe_due                        = 0;
248
485
    pd_ctx->last_long_base_pic                = 0;
249
485
    pd_ctx->enable_startup_mg                 = false;
250
485
    pd_ctx->is_startup_gop                    = false;
251
485
    pd_ctx->sframe_hier_lvls                  = 0;
252
485
    pd_ctx->sframe_last_arf                   = 0;
253
485
    pd_ctx->next_arf_is_s                     = false;
254
485
    pd_ctx->current_input_poc                 = -1;
255
485
    return EB_ErrorNone;
256
485
}
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
485
EbErrorType release_prev_picture_from_reorder_queue(EncodeContext* enc_ctx) {
382
485
    EbErrorType return_error = EB_ErrorNone;
383
384
485
    PictureDecisionReorderEntry* queue_previous_entry_ptr;
385
485
    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
485
    previous_entry_index     = (enc_ctx->picture_decision_reorder_queue_head_index == 0)
390
485
            ? enc_ctx->picture_decision_reorder_queue_size - 1
391
485
            : enc_ctx->picture_decision_reorder_queue_head_index - 1;
392
485
    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
485
    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
485
    return return_error;
403
485
}
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
485
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
485
    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
485
        pcs->pred_struct_ptr->pred_type == RANDOM_ACCESS && pcs->idr_flag == false && pcs->cra_flag == false) {
935
0
        return 1;
936
485
    } else {
937
485
        return 0;
938
485
    }
939
485
}
940
941
/***************************************************************************************************
942
* Gets the pred struct for each frame in the mini-gop(s) that we have available
943
***************************************************************************************************/
944
485
static void get_pred_struct_for_all_frames(PictureDecisionContext* ctx, EncodeContext* enc_ctx) {
945
    // Loop over all mini GOPs
946
970
    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
485
        for (unsigned int pic_idx = ctx->mini_gop_start_index[mini_gop_index];
949
970
             pic_idx <= ctx->mini_gop_end_index[mini_gop_index];
950
485
             pic_idx++) {
951
485
            PictureParentControlSet* pcs =
952
485
                (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
953
485
            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
485
            pcs->pred_structure      = scs->static_config.pred_structure;
970
485
            pcs->hierarchical_levels = pcs->idr_flag ? scs->static_config.hierarchical_levels
971
485
                                                     : (uint8_t)ctx->mini_gop_hierarchical_levels[mini_gop_index];
972
485
            pcs->pred_struct_ptr     = svt_aom_get_prediction_structure(
973
485
                enc_ctx->prediction_structure_group_ptr, pcs->pred_structure, pcs->hierarchical_levels);
974
975
485
            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
485
            if (pcs->idr_flag && pcs->picture_number == 0) {
983
485
                ctx->is_startup_gop = true;
984
485
            } else if (pcs->idr_flag || pcs->cra_flag) {
985
0
                ctx->is_startup_gop = false;
986
0
            }
987
485
            pcs->is_startup_gop = ctx->is_startup_gop;
988
485
        }
989
485
    }
990
485
}
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.51k
bool svt_aom_is_pic_skipped(PictureParentControlSet* pcs) {
999
7.51k
    if (!pcs->is_ref && pcs->scs->rc_stat_gen_pass_mode && !pcs->first_frame_in_minigop) {
1000
0
        return true;
1001
0
    }
1002
7.51k
    return false;
1003
7.51k
}
1004
1005
static void prune_sframe_refs(PictureDecisionContext* ctx, PictureParentControlSet* ppcs,
1006
485
                              MvReferenceFrame ref_frame_arr[], uint8_t* tot_ref_frames) {
1007
485
    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
485
}
1044
1045
//set the ref frame types used for this picture,
1046
static void set_all_ref_frame_type(PictureDecisionContext* ctx, PictureParentControlSet* ppcs,
1047
485
                                   MvReferenceFrame ref_frame_arr[], uint8_t* tot_ref_frames) {
1048
485
    MvReferenceFrame rf[2];
1049
485
    *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
485
    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
485
    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
485
    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
485
    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
485
    prune_sframe_refs(ctx, ppcs, ref_frame_arr, tot_ref_frames);
1100
485
}
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
485
static void ref_mgmt_reset_state(PictureDecisionContext* ctx) {
1165
485
    memset(ctx->pic_id_per_dpb_slot, 0, sizeof(ctx->pic_id_per_dpb_slot));
1166
485
}
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
485
static uint8_t ref_mgmt_stored_mask(const PictureDecisionContext* ctx) {
1175
485
    uint8_t m = 0;
1176
4.36k
    for (uint8_t i = 0; i < REF_FRAMES; ++i) {
1177
3.88k
        if (ctx->pic_id_per_dpb_slot[i] != 0) {
1178
0
            m |= (uint8_t)(1u << i);
1179
0
        }
1180
3.88k
    }
1181
485
    return m;
1182
485
}
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
485
static void apply_ref_mgmt_events(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1381
485
    uint8_t    new_store_slot = (uint8_t)REF_FRAMES;
1382
485
    const bool have_event     = pcs->ref_mgmt.store_id != 0 || pcs->ref_mgmt.clear_id != 0 || pcs->ref_mgmt.use_id != 0;
1383
485
    bool       events_ok      = have_event;
1384
1385
485
    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
485
    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
485
    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
485
    {
1445
485
        const uint8_t stored_mask   = ref_mgmt_stored_mask(ctx);
1446
485
        const uint8_t preserve_mask = (new_store_slot < REF_FRAMES)
1447
485
            ? (uint8_t)(stored_mask & ~(uint8_t)(1u << new_store_slot))
1448
485
            : stored_mask;
1449
485
        const uint8_t orig          = pcs->av1_ref_signal.refresh_frame_mask;
1450
485
        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
485
        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
485
    }
1465
1466
    // Phase 4: USE — override refs, then recovery-point refresh.
1467
485
    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
485
}
1481
1482
485
static void set_key_frame_rps(PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
1483
485
    FrameHeader* frm_hdr = &pcs->frm_hdr;
1484
485
    pd_ctx->lay0_toggle  = 0;
1485
485
    pd_ctx->lay1_toggle  = 0;
1486
    // KF refreshes all 8 DPB slots, so all previously-STOREd refs are invalidated.
1487
485
    ref_mgmt_reset_state(pd_ctx);
1488
1489
485
    frm_hdr->show_frame    = true;
1490
485
    pcs->has_show_existing = false;
1491
485
    return;
1492
485
}
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
970
                                uint32_t referencing_scheme, bool is_overlay) {
1774
970
    if (is_overlay) {
1775
0
        return false;
1776
0
    }
1777
1778
    // Frames below top layer are always used as ref
1779
970
    if (temporal_layer < hierarchical_levels) {
1780
0
        return true;
1781
0
    }
1782
1783
970
    switch (hierarchical_levels) {
1784
0
    case 0:
1785
0
        return true;
1786
0
    case 1:
1787
0
        return referencing_scheme == 0 ? false : true;
1788
970
    case 2:
1789
970
        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
970
    }
1802
1803
0
    return true;
1804
970
}
1805
1806
485
static void set_ref_list_counts(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
1807
485
    if (pcs->slice_type == I_SLICE) {
1808
485
        pcs->ref_list0_count = 0;
1809
485
        pcs->ref_list1_count = 0;
1810
485
        return;
1811
485
    }
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
485
                                  uint32_t pic_idx, uint32_t mg_idx) {
1915
485
    Av1RpsNode*         av1_rps             = &pcs->av1_ref_signal;
1916
485
    FrameHeader*        frm_hdr             = &pcs->frm_hdr;
1917
485
    SequenceControlSet* scs                 = pcs->scs;
1918
485
    const uint8_t       hierarchical_levels = pcs->hierarchical_levels;
1919
485
    const uint8_t       temporal_layer      = pcs->temporal_layer_index;
1920
485
#if CONFIG_ENABLE_RANDOM_ACCESS
1921
485
    const uint8_t more_5L_refs = pcs->scs->mrp_ctrls.more_5L_refs;
1922
485
#endif
1923
1924
485
    if (scs->allintra) {
1925
485
        pcs->is_ref = false;
1926
485
    } 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
485
    if (pcs->slice_type == I_SLICE) {
1933
485
        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
485
        if (frm_hdr->frame_type == KEY_FRAME) {
1938
485
            set_key_frame_rps(pcs, ctx);
1939
485
            set_ref_list_counts(pcs, ctx);
1940
485
            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
485
            apply_ref_mgmt_events(pcs, ctx);
1946
485
            return;
1947
485
        }
1948
485
    } 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.42k
bool svt_aom_is_delayed_intra(PictureParentControlSet* pcs) {
3631
2.42k
    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.42k
    } else {
3642
2.42k
        return 0;
3643
2.42k
    }
3644
2.42k
}
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
485
static void mctf_frame(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* pd_ctx) {
4209
485
#if CONFIG_ENABLE_TEMPORAL_FILTERING
4210
485
    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
485
    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
485
    } else {
4255
485
        pcs->do_tf = false; // set temporal filtering flag OFF for current picture
4256
485
    }
4257
#else
4258
    (void)scs;
4259
    pcs->do_tf = false; // temporal filtering compiled out
4260
#endif
4261
4262
485
    pcs->is_noise_level = (pd_ctx->last_i_noise_levels_log1p_fp16[0] >= VQ_NOISE_LVL_TH);
4263
4264
485
#if CONFIG_ENABLE_TEMPORAL_FILTERING
4265
485
    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
485
#endif
4270
485
}
4271
4272
485
bool get_similar_ref_brightness(PictureParentControlSet* pcs) {
4273
485
    bool similar_brightness_refs = false;
4274
485
    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
485
    return similar_brightness_refs;
4287
485
}
4288
4289
485
static void send_picture_out(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4290
485
    EbObjectWrapper* me_wrapper;
4291
485
    EbObjectWrapper* out_results_wrapper;
4292
4293
    //every picture enherits latest motion direction from TF
4294
485
    pcs->tf_motion_direction = ctx->tf_motion_direction;
4295
485
    MrpCtrls* mrp_ctrl       = &(scs->mrp_ctrls);
4296
4297
485
    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
485
    pcs->similar_brightness_refs = get_similar_ref_brightness(pcs);
4327
485
    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
485
    if (pcs->me_data_wrapper == NULL) {
4337
485
        svt_get_empty_object(ctx->me_fifo_ptr, &me_wrapper);
4338
485
        pcs->me_data_wrapper = me_wrapper;
4339
485
        pcs->pa_me_data      = (MotionEstimationData*)me_wrapper->object_ptr;
4340
485
        me_update_param(pcs->pa_me_data, scs);
4341
485
    }
4342
4343
485
    uint8_t ref_count_used_list0 = MAX(mrp_ctrl->base_ref_list0_count, mrp_ctrl->non_base_ref_list0_count);
4344
485
    uint8_t ref_count_used_list1 = MAX(mrp_ctrl->base_ref_list1_count, mrp_ctrl->non_base_ref_list1_count);
4345
4346
485
    uint8_t max_ref_to_alloc, max_cand_to_alloc;
4347
4348
485
    svt_aom_get_max_allocated_me_refs(
4349
485
        ref_count_used_list0, ref_count_used_list1, &max_ref_to_alloc, &max_cand_to_alloc);
4350
4351
485
    pcs->pa_me_data->max_cand = max_cand_to_alloc;
4352
485
    pcs->pa_me_data->max_refs = max_ref_to_alloc;
4353
485
    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
485
    if (scs->static_config.pass == ENC_SINGLE_PASS) {
4363
485
        if (scs->static_config.resize_mode > RESIZE_NONE || scs->static_config.superres_mode == SUPERRES_FIXED ||
4364
485
            scs->static_config.superres_mode == SUPERRES_RANDOM) {
4365
0
            svt_aom_init_resize_picture(scs, pcs);
4366
0
        }
4367
485
    }
4368
485
    bool super_res_off = pcs->frame_superres_enabled == false && scs->static_config.resize_mode == RESIZE_NONE;
4369
485
    svt_aom_set_gm_controls(pcs, svt_aom_derive_gm_level(pcs, super_res_off));
4370
485
    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
485
    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
970
    for (uint32_t segment_index = 0; segment_index < pcs->me_segments_total_count; ++segment_index) {
4384
        // Get Empty Results Object
4385
485
        svt_get_empty_object(ctx->picture_decision_results_output_fifo_ptr, &out_results_wrapper);
4386
4387
485
        PictureDecisionResults* out_results = (PictureDecisionResults*)out_results_wrapper->object_ptr;
4388
485
        out_results->pcs_wrapper            = pcs->p_pcs_wrapper_ptr;
4389
485
        out_results->segment_index          = segment_index;
4390
485
        out_results->task_type              = TASK_PAME;
4391
        //Post the Full Results Object
4392
485
        svt_post_full_object(out_results_wrapper);
4393
485
    }
4394
485
}
4395
4396
/***************************************************************************************************
4397
* Store the pcs pointers in the gf group, set the gf_interval and gf_update_due
4398
***************************************************************************************************/
4399
485
void store_gf_group(PictureParentControlSet* pcs, PictureDecisionContext* ctx, uint32_t mg_size) {
4400
485
    if (pcs->slice_type == I_SLICE || (!svt_aom_is_delayed_intra(pcs) && pcs->temporal_layer_index == 0) ||
4401
485
        svt_aom_is_incomp_mg_frame(pcs)) {
4402
485
        if (svt_aom_is_delayed_intra(pcs)) {
4403
0
            pcs->gf_group[0] = pcs;
4404
0
            svt_memcpy(&pcs->gf_group[1], ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
4405
0
            pcs->gf_interval = 1 + mg_size;
4406
485
        } else {
4407
485
            if (svt_aom_is_incomp_mg_frame(pcs) && mg_size > 0 && ctx->mg_pictures_array[mg_size - 1]->idr_flag) {
4408
0
                mg_size = MAX(0, (int)mg_size - 1);
4409
0
            }
4410
485
            svt_memcpy(&pcs->gf_group[0], ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
4411
485
            pcs->gf_interval = mg_size;
4412
485
        }
4413
4414
485
        if (pcs->slice_type == I_SLICE && pcs->end_of_sequence_flag) {
4415
0
            pcs->gf_interval = 1;
4416
0
            pcs->gf_group[0] = pcs;
4417
0
        }
4418
4419
970
        for (int pic_i = 0; pic_i < pcs->gf_interval; ++pic_i) {
4420
485
            if (pcs->gf_group[pic_i]->slice_type == I_SLICE ||
4421
0
                (!svt_aom_is_delayed_intra(pcs) && pcs->gf_group[pic_i]->temporal_layer_index == 0) ||
4422
485
                svt_aom_is_incomp_mg_frame(pcs->gf_group[pic_i])) {
4423
485
                pcs->gf_group[pic_i]->gf_update_due = 1;
4424
485
            } else {
4425
0
                pcs->gf_group[pic_i]->gf_update_due = 0;
4426
0
            }
4427
4428
            // For P picture that come after I, we need to set the gf_group pictures. It is used later in RC
4429
485
            if (pcs->slice_type == I_SLICE && svt_aom_is_incomp_mg_frame(pcs->gf_group[pic_i]) &&
4430
0
                pcs->picture_number < pcs->gf_group[pic_i]->picture_number) {
4431
0
                pcs->gf_group[pic_i]->gf_interval = pcs->gf_interval - 1;
4432
0
                svt_memcpy(&pcs->gf_group[pic_i]->gf_group[0],
4433
0
                           &ctx->mg_pictures_array[1],
4434
0
                           pcs->gf_group[pic_i]->gf_interval * sizeof(PictureParentControlSet*));
4435
0
                pcs->gf_group[pic_i]->gf_update_due = 0;
4436
0
            }
4437
485
        }
4438
485
    }
4439
485
}
4440
4441
#if LAD_MG_PRINT
4442
/* prints content of pre-assignment buffer */
4443
void print_pre_ass_buffer(EncodeContext* ctx, PictureParentControlSet* pcs, uint8_t log) {
4444
    if (log) {
4445
        if (ctx->pre_assignment_buffer_intra_count > 0) {
4446
            SVT_LOG(
4447
                "PRE-ASSIGN INTRA   (%i pictures)  POC:%lld \n", ctx->pre_assignment_buffer_count, pcs->picture_number);
4448
        }
4449
        if (ctx->pre_assignment_buffer_count == (uint32_t)(1 << pcs->scs->static_config.hierarchical_levels)) {
4450
            SVT_LOG("PRE-ASSIGN COMPLETE   (%i pictures)  POC:%lld \n",
4451
                    ctx->pre_assignment_buffer_count,
4452
                    pcs->picture_number);
4453
        }
4454
        if (ctx->pre_assignment_buffer_eos_flag == 1) {
4455
            SVT_LOG(
4456
                "PRE-ASSIGN EOS   (%i pictures)  POC:%lld \n", ctx->pre_assignment_buffer_count, pcs->picture_number);
4457
        }
4458
        if (pcs->pred_structure == LOW_DELAY) {
4459
            SVT_LOG(
4460
                "PRE-ASSIGN LD   (%i pictures)  POC:%lld \n", ctx->pre_assignment_buffer_count, pcs->picture_number);
4461
        }
4462
4463
        SVT_LOG("\n Pre-Assign(%i):  ", ctx->pre_assignment_buffer_count);
4464
        for (uint32_t pic = 0; pic < ctx->pre_assignment_buffer_count; pic++) {
4465
            PictureParentControlSet* pcs = (PictureParentControlSet*)ctx->pre_assignment_buffer[pic]->object_ptr;
4466
            SVT_LOG("%ld ", pcs->picture_number);
4467
        }
4468
        SVT_LOG("\n");
4469
    }
4470
}
4471
#endif
4472
4473
0
static PaReferenceEntry* search_ref_in_ref_queue_pa(EncodeContext* enc_ctx, uint64_t ref_poc) {
4474
0
    PaReferenceEntry* ref_entry_ptr = NULL;
4475
0
    for (uint8_t i = 0; i < REF_FRAMES; i++) {
4476
0
        ref_entry_ptr = enc_ctx->pd_dpb[i];
4477
4478
0
        if (ref_entry_ptr && ref_entry_ptr->picture_number == ref_poc) {
4479
0
            return ref_entry_ptr;
4480
0
        }
4481
0
    }
4482
4483
0
    return NULL;
4484
0
}
4485
4486
/*
4487
 * Copy TF params: scs -> pcs
4488
 */
4489
485
static void copy_tf_params(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4490
    // Map TF settings scs -> pcs
4491
485
    if (scs->static_config.pred_structure == LOW_DELAY) {
4492
0
        if (pcs->slice_type != I_SLICE && pcs->temporal_layer_index == 0) {
4493
0
            pcs->tf_ctrls = scs->tf_params_per_type[1];
4494
0
        } else {
4495
0
            pcs->tf_ctrls.enabled = 0;
4496
0
        }
4497
        // When the hierarchical level reaches zero during flexible S-Frame insertion, tf_pic_arr_cnt is reset to zero upon mini-GOP closure.
4498
        // Add additional protection for TF handling.
4499
0
        if (IS_SFRAME_FLEXIBLE_INSERT(scs->static_config.sframe_mode) && pcs->tf_ctrls.enabled &&
4500
0
            ctx->tf_pic_arr_cnt == 0) {
4501
0
            pcs->tf_ctrls.enabled = 0;
4502
0
        }
4503
4504
0
        return;
4505
0
    }
4506
    // Don't perform TF for overlay pics or pics in the highest layer (relevant for 2L)
4507
485
    if ((pcs->frm_hdr.frame_type == KEY_FRAME && !scs->static_config.enable_tf_key) || pcs->is_overlay ||
4508
485
        pcs->temporal_layer_index == pcs->hierarchical_levels) {
4509
0
        pcs->tf_ctrls.enabled = 0;
4510
485
    } else if (svt_aom_is_delayed_intra(pcs)) {
4511
0
        pcs->tf_ctrls = scs->tf_params_per_type[0];
4512
485
    } else if (pcs->temporal_layer_index == 0) { // BASE
4513
485
        pcs->tf_ctrls = scs->tf_params_per_type[1];
4514
485
    } else if (pcs->temporal_layer_index == 1) { // L1
4515
0
        pcs->tf_ctrls = scs->tf_params_per_type[2];
4516
0
    } else {
4517
0
        pcs->tf_ctrls.enabled = 0;
4518
0
    }
4519
485
}
4520
4521
void svt_aom_is_screen_content(PictureParentControlSet* pcs);
4522
void svt_aom_is_screen_content_antialiasing_aware(PictureParentControlSet* pcs);
4523
bool svt_aom_is_input_luma_dominant(const EbPictureBufferDesc* input_pic);
4524
4525
/*
4526
* Update the list0 count try and the list1 count try based on the Enc-Mode, whether BASE or not, whether SC or not
4527
*/
4528
485
void update_count_try(SequenceControlSet* scs, PictureParentControlSet* pcs) {
4529
485
    MrpCtrls* mrp_ctrl = &scs->mrp_ctrls;
4530
485
    if (frame_is_boosted(pcs)) {
4531
485
        pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->base_ref_list0_count);
4532
485
        pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->base_ref_list1_count);
4533
485
    } else {
4534
0
        pcs->ref_list0_count_try = MIN(pcs->ref_list0_count, mrp_ctrl->non_base_ref_list0_count);
4535
0
        pcs->ref_list1_count_try = MIN(pcs->ref_list1_count, mrp_ctrl->non_base_ref_list1_count);
4536
0
    }
4537
485
}
4538
4539
/*
4540
* 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.
4541
*/
4542
0
static void update_sframe_ref_order_hint(PictureParentControlSet* ppcs, PictureDecisionContext* pd_ctx) {
4543
0
    assert(sizeof(ppcs->dpb_order_hint) == sizeof(pd_ctx->ref_order_hint));
4544
0
    if (ppcs->pred_structure == LOW_DELAY) {
4545
0
        for (int32_t i = 0; i < REF_FRAMES; i++) {
4546
            // dpd_order_hint should be updated with relative position of key frame
4547
0
            ppcs->dpb_order_hint[i] = (uint32_t)(pd_ctx->ref_order_hint[i] - pd_ctx->key_poc);
4548
0
        }
4549
0
    } else {
4550
0
        memcpy(ppcs->dpb_order_hint, pd_ctx->ref_order_hint, sizeof(ppcs->dpb_order_hint));
4551
0
    }
4552
0
    if (ppcs->av1_ref_signal.refresh_frame_mask != 0) {
4553
0
        const uint32_t cur_order_hint = ppcs->picture_number %
4554
0
            ((uint64_t)1 << (ppcs->scs->seq_header.order_hint_info.order_hint_bits));
4555
0
        for (int32_t i = 0; i < REF_FRAMES; i++) {
4556
0
            if ((ppcs->av1_ref_signal.refresh_frame_mask >> i) & 1) {
4557
0
                pd_ctx->ref_order_hint[i] = cur_order_hint;
4558
0
            }
4559
0
        }
4560
0
    }
4561
0
}
4562
4563
/*****************************************************************
4564
* Update the RC param queue
4565
* Set the size of the previous Gop/param, Check if all the frames in gop are processed, if yes reset
4566
* Increament the head index to assign a new spot in the queue for the new gop
4567
*****************************************************************/
4568
485
static void update_rc_param_queue(PictureParentControlSet* ppcs, EncodeContext* enc_cxt) {
4569
485
    if (ppcs->idr_flag == true && ppcs->picture_number > 0) {
4570
0
        svt_block_on_mutex(enc_cxt->rc_param_queue_mutex);
4571
        // Set the size of the previous Gop/param
4572
0
        enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size =
4573
0
            (int32_t)(ppcs->picture_number - enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->first_poc);
4574
        // Check if all the frames in gop are processed, if yes reset
4575
0
        if (enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size ==
4576
0
            enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->processed_frame_number) {
4577
0
            enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size                   = -1;
4578
0
            enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->processed_frame_number = 0;
4579
0
        }
4580
        // Increament the head index to assign a new spot in the queue for the new gop
4581
0
        enc_cxt->rc_param_queue_head_index = (enc_cxt->rc_param_queue_head_index == PARALLEL_GOP_MAX_NUMBER - 1)
4582
0
            ? 0
4583
0
            : enc_cxt->rc_param_queue_head_index + 1;
4584
0
        svt_aom_assert_err(enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->size == -1,
4585
0
                           "The head in rc paramqueue is not empty");
4586
0
        enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index]->first_poc = ppcs->picture_number;
4587
0
        svt_release_mutex(enc_cxt->rc_param_queue_mutex);
4588
0
    }
4589
    // Store the pointer to the right spot in the RC param queue under PCS
4590
485
    ppcs->rate_control_param_ptr = enc_cxt->rc_param_queue[enc_cxt->rc_param_queue_head_index];
4591
485
}
4592
4593
/****************************************************************************************
4594
* set_layer_depth()
4595
* Set the layer depth per frame based on frame type, temporal layer
4596
****************************************************************************************/
4597
485
static void set_layer_depth(PictureParentControlSet* ppcs) {
4598
    // SequenceControlSet *scs = ppcs->scs;
4599
485
    if (ppcs->frm_hdr.frame_type == KEY_FRAME) {
4600
485
        ppcs->layer_depth = 0;
4601
485
    } else {
4602
0
        ppcs->layer_depth = ppcs->temporal_layer_index + 1;
4603
0
    }
4604
485
}
4605
4606
/****************************************************************************************
4607
* set_frame_update_type()
4608
* Set the update type per frame based on frame type, temporal layer and prediction structure
4609
* For Low delay, there is a special case where all non key frames are treated as LF_UPDATE.
4610
* Every MAX_GF_INTERVAL frames, update type is set to GF_UPDATE
4611
****************************************************************************************/
4612
485
static void set_frame_update_type(PictureParentControlSet* ppcs) {
4613
485
    if (ppcs->frm_hdr.frame_type == KEY_FRAME) {
4614
485
        ppcs->update_type = SVT_AV1_KF_UPDATE;
4615
485
    } else if (ppcs->hierarchical_levels > 0) {
4616
0
        if (ppcs->temporal_layer_index == 0) {
4617
0
            ppcs->update_type = SVT_AV1_ARF_UPDATE;
4618
0
        } else if (ppcs->temporal_layer_index == ppcs->hierarchical_levels) {
4619
0
            ppcs->update_type = SVT_AV1_LF_UPDATE;
4620
0
        } else {
4621
0
            ppcs->update_type = SVT_AV1_INTNL_ARF_UPDATE;
4622
0
        }
4623
0
    } else if ((ppcs->frame_offset % MAX(4, 1 << ppcs->hierarchical_levels)) == 0) {
4624
0
        ppcs->update_type = SVT_AV1_GF_UPDATE;
4625
0
    } else if (ppcs->frame_offset & 0x1) {
4626
        // frames with odd offset correspond to leaf layer pics in RA structures
4627
0
        ppcs->update_type = SVT_AV1_LF_UPDATE;
4628
0
    } else {
4629
0
        ppcs->update_type = SVT_AV1_INTNL_ARF_UPDATE;
4630
0
    }
4631
485
}
4632
4633
485
static void set_gf_group_param(PictureParentControlSet* ppcs) {
4634
485
    set_frame_update_type(ppcs);
4635
485
    set_layer_depth(ppcs);
4636
485
}
4637
4638
0
static void process_first_pass(SequenceControlSet* scs, EncodeContext* enc_ctx) {
4639
0
    for (unsigned int window_index = 0; window_index < scs->scd_delay + 1; window_index++) {
4640
0
        unsigned int entry_index = QUEUE_GET_NEXT_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4641
0
                                                       window_index,
4642
0
                                                       enc_ctx->picture_decision_reorder_queue_size);
4643
0
        PictureDecisionReorderEntry* first_pass_queue_entry = enc_ctx->picture_decision_reorder_queue[entry_index];
4644
0
        if (first_pass_queue_entry->ppcs_wrapper == NULL) {
4645
0
            break;
4646
0
        }
4647
4648
0
        PictureParentControlSet* first_pass_pcs = (PictureParentControlSet*)
4649
0
                                                      first_pass_queue_entry->ppcs_wrapper->object_ptr;
4650
0
        if (!first_pass_pcs->first_pass_done) {
4651
0
            first_pass_frame_end_one_pass(first_pass_pcs);
4652
0
            first_pass_pcs->first_pass_done = 1;
4653
0
        }
4654
0
    }
4655
0
}
4656
4657
// Check if have enough frames to do scene change detection or if the EOS has been reached
4658
static void check_window_availability(SequenceControlSet* scs, EncodeContext* enc_ctx, PictureParentControlSet* pcs,
4659
485
                                      PictureDecisionReorderEntry* queue_entry, bool* window_avail, bool* eos_reached) {
4660
485
    *eos_reached  = ((PictureParentControlSet*)(queue_entry->ppcs_wrapper->object_ptr))->end_of_sequence_flag == true;
4661
485
    *window_avail = true;
4662
4663
485
    unsigned int previous_entry_index = QUEUE_GET_PREVIOUS_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4664
485
                                                                enc_ctx->picture_decision_reorder_queue_size);
4665
485
    memset(pcs->pd_window, 0, (2 + scs->scd_delay) * sizeof(PictureParentControlSet*));
4666
    //for poc 0, ignore previous frame check
4667
485
    if (queue_entry->picture_number > 0 &&
4668
0
        enc_ctx->picture_decision_reorder_queue[previous_entry_index]->ppcs_wrapper == NULL) {
4669
0
        *window_avail = false;
4670
485
    } else {
4671
        //TODO: risk of a race condition accessing prev(pcs0 is released, and pcs1 still doing sc).
4672
        //Actually we don't need to keep prev, just keep previous copy of histograms.
4673
485
        pcs->pd_window[0] = queue_entry->picture_number > 0
4674
485
            ? (PictureParentControlSet*)enc_ctx->picture_decision_reorder_queue[previous_entry_index]
4675
0
                  ->ppcs_wrapper->object_ptr
4676
485
            : NULL;
4677
485
        pcs->pd_window[1] = (PictureParentControlSet*)enc_ctx
4678
485
                                ->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index]
4679
485
                                ->ppcs_wrapper->object_ptr;
4680
485
        for (unsigned int window_index = 0; window_index < scs->scd_delay; window_index++) {
4681
0
            unsigned int entry_index = QUEUE_GET_NEXT_SPOT(enc_ctx->picture_decision_reorder_queue_head_index,
4682
0
                                                           window_index + 1,
4683
0
                                                           enc_ctx->picture_decision_reorder_queue_size);
4684
0
            if (enc_ctx->picture_decision_reorder_queue[entry_index]->ppcs_wrapper == NULL) {
4685
0
                *window_avail = false;
4686
0
                break;
4687
0
            } else if (((PictureParentControlSet*)(enc_ctx->picture_decision_reorder_queue[entry_index]
4688
0
                                                       ->ppcs_wrapper->object_ptr))
4689
0
                           ->end_of_sequence_flag == true) {
4690
0
                *window_avail = false;
4691
0
                *eos_reached  = true;
4692
0
                break;
4693
0
            } else {
4694
0
                pcs->pd_window[2 + window_index] = (PictureParentControlSet*)enc_ctx
4695
0
                                                       ->picture_decision_reorder_queue[entry_index]
4696
0
                                                       ->ppcs_wrapper->object_ptr;
4697
0
            }
4698
0
        }
4699
485
    }
4700
485
}
4701
4702
// Perform scene change detection and update relevant signals
4703
static void perform_scene_change_detection(SequenceControlSet* scs, PictureParentControlSet* pcs,
4704
0
                                           PictureDecisionContext* ctx) {
4705
0
    if (scs->static_config.scene_change_detection) {
4706
0
        pcs->scene_change_flag = scene_transition_detector(ctx, scs, (PictureParentControlSet**)pcs->pd_window);
4707
4708
0
    } else {
4709
0
        pcs->scene_change_flag = false;
4710
4711
0
        if (scs->vq_ctrls.sharpness_ctrls.scene_transition &&
4712
0
            (ctx->transition_detected == -1 || ctx->transition_detected == 0)) {
4713
0
            ctx->transition_detected = scene_transition_detector(ctx, scs, (PictureParentControlSet**)pcs->pd_window);
4714
0
        }
4715
0
    }
4716
4717
0
    pcs->cra_flag = (pcs->scene_change_flag == true) ? true : pcs->cra_flag;
4718
4719
    // Store scene change in context
4720
0
    ctx->is_scene_change_detected = pcs->scene_change_flag;
4721
0
}
4722
4723
// Copy current pic's histogram to temporary buffer to be used by next input pic (N + 1) for scene change detection
4724
0
static void copy_histograms(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4725
0
    for (unsigned int region_in_picture_width_index = 0; region_in_picture_width_index < MAX_NUMBER_OF_REGIONS_IN_WIDTH;
4726
0
         region_in_picture_width_index++) {
4727
0
        for (unsigned int region_in_picture_height_index = 0;
4728
0
             region_in_picture_height_index < MAX_NUMBER_OF_REGIONS_IN_HEIGHT;
4729
0
             region_in_picture_height_index++) {
4730
0
            svt_memcpy(&(ctx->prev_picture_histogram[region_in_picture_width_index][region_in_picture_height_index][0]),
4731
0
                       &(pcs->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][0]),
4732
0
                       HISTOGRAM_NUMBER_OF_BINS * sizeof(uint32_t));
4733
4734
0
            ctx->prev_average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index] =
4735
0
                pcs->average_intensity_per_region[region_in_picture_width_index][region_in_picture_height_index];
4736
0
        }
4737
0
    }
4738
0
}
4739
4740
// Decide what mini-gop sizes to use and init the relevant fields
4741
static void set_mini_gop_structure(SequenceControlSet* scs, EncodeContext* enc_ctx, PictureParentControlSet* pcs,
4742
485
                                   PictureDecisionContext* ctx) {
4743
485
    uint32_t next_mg_hierarchical_levels = scs->static_config.hierarchical_levels;
4744
    // Overwrite next_mg_hierarchical_levels when an S-Frame needs to modify the mini-GOP size.
4745
485
    if (ctx->sframe_hier_lvls != (int32_t)scs->static_config.hierarchical_levels) {
4746
0
        next_mg_hierarchical_levels = ctx->sframe_hier_lvls;
4747
0
    }
4748
485
    if (ctx->enable_startup_mg) {
4749
0
        next_mg_hierarchical_levels = scs->static_config.startup_mg_size;
4750
0
    }
4751
    // For RTC mode (implies LOW_DELAY + CBR), support on-the-fly hierarchical_levels changes.
4752
    // pcs->hierarchical_levels holds the value requested by resource_coordination for this picture.
4753
485
    if (scs->static_config.pred_structure == LOW_DELAY && scs->static_config.rtc &&
4754
0
        scs->static_config.rate_control_mode == SVT_AV1_RC_MODE_CBR) {
4755
        // If incoming pic signals change in GOP structure, update the active GOP structure immediately
4756
0
        next_mg_hierarchical_levels = pcs->hierarchical_levels;
4757
0
    }
4758
    // Initialize Picture Block Params
4759
485
    ctx->mini_gop_start_index[0] = 0;
4760
485
    ctx->mini_gop_end_index[0]   = enc_ctx->pre_assignment_buffer_count - 1;
4761
485
    ctx->mini_gop_length[0]      = enc_ctx->pre_assignment_buffer_count;
4762
4763
485
    ctx->mini_gop_hierarchical_levels[0]           = next_mg_hierarchical_levels;
4764
485
    ctx->mini_gop_intra_count[0]                   = enc_ctx->pre_assignment_buffer_intra_count;
4765
485
    ctx->mini_gop_idr_count[0]                     = enc_ctx->pre_assignment_buffer_idr_count;
4766
485
    ctx->total_number_of_mini_gops                 = 1;
4767
485
    enc_ctx->previous_mini_gop_hierarchical_levels = (pcs->picture_number == 0)
4768
485
        ? next_mg_hierarchical_levels
4769
485
        : enc_ctx->previous_mini_gop_hierarchical_levels;
4770
485
    enc_ctx->mini_gop_cnt_per_gop = (enc_ctx->pre_assignment_buffer_idr_count) ? 0 : enc_ctx->mini_gop_cnt_per_gop + 1;
4771
485
    assert(IMPLIES(enc_ctx->pre_assignment_buffer_intra_count == enc_ctx->pre_assignment_buffer_count,
4772
485
                   enc_ctx->pre_assignment_buffer_count == 1));
4773
    // In RA, if the only picture is an I_SLICE, use default settings (set above). If treat the solo I_SLICE
4774
    // as a regular MG, you will change the hierarchical_levels to the minimum.
4775
    // For low-delay pred strucutres, pre_assignment_buffer_count will be 1, but no need to change the default
4776
    // hierarchical levels.
4777
485
    if (enc_ctx->pre_assignment_buffer_count > 1 ||
4778
485
        (!enc_ctx->pre_assignment_buffer_intra_count && scs->static_config.pred_structure == RANDOM_ACCESS)) {
4779
0
        initialize_mini_gop_activity_array(scs, pcs, enc_ctx, ctx);
4780
4781
0
        generate_picture_window_split(ctx, enc_ctx);
4782
4783
0
        handle_incomplete_picture_window_map(next_mg_hierarchical_levels, ctx, enc_ctx);
4784
0
    }
4785
4786
485
    get_pred_struct_for_all_frames(ctx, enc_ctx);
4787
485
}
4788
4789
// Set whether the picture is to be considered as SC; for single-threaded mode we perform SC detection here
4790
485
static void perform_sc_detection(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4791
485
    if (pcs->slice_type == I_SLICE) {
4792
        // If running multi-threaded mode, perform SC detection in svt_aom_picture_analysis_kernel, else in svt_aom_picture_decision_kernel
4793
485
        if (scs->static_config.level_of_parallelism == 1) {
4794
0
            switch (scs->static_config.screen_content_mode) {
4795
0
            case 0:
4796
0
                pcs->sc_class0 = pcs->sc_class1 = pcs->sc_class2 = pcs->sc_class3 = pcs->sc_class4 = pcs->sc_class5 = 0;
4797
0
                break;
4798
0
            case 1:
4799
0
                pcs->sc_class0 = pcs->sc_class1 = pcs->sc_class2 = pcs->sc_class3 = pcs->sc_class4 = pcs->sc_class5 = 1;
4800
0
                break;
4801
0
            case 2:
4802
                // SC Detection is OFF for 4K and higher
4803
0
                if (scs->input_resolution <= INPUT_SIZE_1080p_RANGE) {
4804
0
                    svt_aom_is_screen_content(pcs);
4805
0
                }
4806
0
                break;
4807
0
            case 3:
4808
0
                svt_aom_is_screen_content_antialiasing_aware(pcs);
4809
0
                break;
4810
0
            }
4811
            // Luma-dominant detection in ST mode
4812
0
            if (scs->detect_luma_dominant_input) {
4813
0
                pcs->is_luma_dominant_input = svt_aom_is_input_luma_dominant(pcs->chroma_downsampled_pic);
4814
0
            }
4815
0
        }
4816
485
        ctx->last_i_picture_sc_class0      = pcs->sc_class0;
4817
485
        ctx->last_i_picture_sc_class1      = pcs->sc_class1;
4818
485
        ctx->last_i_picture_sc_class2      = pcs->sc_class2;
4819
485
        ctx->last_i_picture_sc_class3      = pcs->sc_class3;
4820
485
        ctx->last_i_picture_sc_class4      = pcs->sc_class4;
4821
485
        ctx->last_i_picture_sc_class5      = pcs->sc_class5;
4822
485
        ctx->last_i_is_luma_dominant_input = pcs->is_luma_dominant_input;
4823
485
    } else {
4824
0
        pcs->sc_class0              = ctx->last_i_picture_sc_class0;
4825
0
        pcs->sc_class1              = ctx->last_i_picture_sc_class1;
4826
0
        pcs->sc_class2              = ctx->last_i_picture_sc_class2;
4827
0
        pcs->sc_class3              = ctx->last_i_picture_sc_class3;
4828
0
        pcs->sc_class4              = ctx->last_i_picture_sc_class4;
4829
0
        pcs->sc_class5              = ctx->last_i_picture_sc_class5;
4830
0
        pcs->is_luma_dominant_input = ctx->last_i_is_luma_dominant_input;
4831
0
    }
4832
485
}
4833
4834
// Update pred struct info and pic type for non-overlay pictures
4835
static void update_pred_struct_and_pic_type(SequenceControlSet* scs, EncodeContext* enc_ctx,
4836
                                            PictureParentControlSet* pcs, PictureDecisionContext* ctx,
4837
                                            unsigned int mini_gop_index, bool pre_assignment_buffer_first_pass_flag,
4838
485
                                            SliceType* picture_type, PredictionStructureEntry** pred_position_ptr) {
4839
485
    (void)scs;
4840
    // Keep track of the mini GOP size to which the input picture belongs - needed @ PictureManagerProcess()
4841
485
    pcs->pre_assignment_buffer_count = ctx->mini_gop_length[mini_gop_index];
4842
4843
    // Update the Pred Structure if cutting short a Random Access period
4844
485
    if (is_pic_cutting_short_ra_mg(ctx, pcs, mini_gop_index)) {
4845
        // Correct the Pred Index before switching structures
4846
0
        if (pre_assignment_buffer_first_pass_flag == true) {
4847
0
            enc_ctx->pred_struct_position -= pcs->pred_struct_ptr->init_pic_index;
4848
0
        }
4849
0
        pcs->pred_struct_ptr = svt_aom_get_prediction_structure(
4850
0
            enc_ctx->prediction_structure_group_ptr, LOW_DELAY, pcs->hierarchical_levels);
4851
0
        *picture_type        = B_SLICE;
4852
0
        ctx->cut_short_ra_mg = 1;
4853
485
    } else {
4854
        // Set the Picture Type
4855
485
        *picture_type = (pcs->idr_flag || pcs->cra_flag) ? I_SLICE : B_SLICE;
4856
485
    }
4857
    // If mini GOP switch, reset position
4858
485
    if (pcs->init_pred_struct_position_flag) {
4859
0
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
4860
0
    }
4861
4862
    // If Intra, reset position
4863
485
    if (pcs->idr_flag == true) {
4864
485
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
4865
485
    } else if (pcs->cra_flag == true &&
4866
0
               ctx->mini_gop_length[mini_gop_index] < pcs->pred_struct_ptr->pred_struct_entry_count) {
4867
0
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index;
4868
0
    } else if (enc_ctx->elapsed_non_cra_count == 0) {
4869
        // If we are the picture directly after a CRA, we have to not use references that violate the CRA
4870
0
        enc_ctx->pred_struct_position = pcs->pred_struct_ptr->init_pic_index + 1;
4871
0
    }
4872
    // Else, Increment the position normally
4873
0
    else {
4874
0
        ++enc_ctx->pred_struct_position;
4875
0
    }
4876
    // 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.
4877
    // The last_idr_picture is used in reseting the poc (in entropy coding) whenever IDR is encountered.
4878
    // 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.
4879
    // Note: When leading P pictures are implemented, this logic has to change..
4880
485
    if (pcs->idr_flag == true) {
4881
485
        enc_ctx->last_idr_picture = pcs->picture_number;
4882
485
    } else {
4883
0
        pcs->last_idr_picture = enc_ctx->last_idr_picture;
4884
0
    }
4885
    // Cycle the PredStructPosition if its overflowed
4886
485
    enc_ctx->pred_struct_position = (enc_ctx->pred_struct_position == pcs->pred_struct_ptr->pred_struct_entry_count)
4887
485
        ? enc_ctx->pred_struct_position - pcs->pred_struct_ptr->pred_struct_entry_count
4888
485
        : enc_ctx->pred_struct_position;
4889
4890
485
    *pred_position_ptr = pcs->pred_struct_ptr->pred_struct_entry_ptr_array[enc_ctx->pred_struct_position];
4891
485
}
4892
4893
static uint32_t get_pic_idx_in_mg(SequenceControlSet* scs, EncodeContext* enc_ctx, PictureParentControlSet* pcs,
4894
485
                                  PictureDecisionContext* ctx, uint32_t pic_idx, uint32_t mini_gop_index) {
4895
485
    uint32_t pic_idx_in_mg = 0;
4896
485
    if (scs->static_config.pred_structure == RANDOM_ACCESS) {
4897
0
        pic_idx_in_mg = pic_idx - ctx->mini_gop_start_index[mini_gop_index];
4898
485
    } else if (scs->static_config.pred_structure == LOW_DELAY) {
4899
0
        uint64_t mg_pos = enc_ctx->pred_struct_position;
4900
0
        pic_idx_in_mg   = (mg_pos == 0) ? 0 : (uint32_t)((mg_pos - 1) % pcs->pred_struct_ptr->pred_struct_entry_count);
4901
0
        uint64_t distance_to_last_idr = pcs->picture_number - scs->enc_ctx->last_idr_picture;
4902
        // In S-Frame flexible insertion mode, hierarchical levels are adjusted based on the S-Frame position.
4903
        // Picture indices in the low-delay mini-GOP are calculated from the last saved ARF.
4904
0
        if (IS_SFRAME_FLEXIBLE_INSERT(scs->static_config.sframe_mode)) {
4905
0
            pic_idx_in_mg = distance_to_last_idr > ctx->sframe_last_arf
4906
0
                ? (uint32_t)(distance_to_last_idr - ctx->sframe_last_arf - 1)
4907
0
                : 0;
4908
0
        }
4909
0
        pcs->frame_offset = distance_to_last_idr;
4910
0
    }
4911
4912
485
    return pic_idx_in_mg;
4913
485
}
4914
4915
485
static void set_ref_frame_sign_bias(SequenceControlSet* scs, PictureParentControlSet* pcs) {
4916
485
    memset(pcs->av1_cm->ref_frame_sign_bias, 0, 8 * sizeof(int32_t));
4917
4918
485
    if (scs->seq_header.order_hint_info.enable_order_hint) {
4919
3.88k
        for (MvReferenceFrame ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
4920
3.39k
            pcs->av1_cm->ref_frame_sign_bias[ref_frame] = (get_relative_dist(&scs->seq_header.order_hint_info,
4921
3.39k
                                                                             pcs->ref_order_hint[ref_frame - 1],
4922
3.39k
                                                                             (int)pcs->cur_order_hint) <= 0)
4923
3.39k
                ? 0
4924
3.39k
                : 1;
4925
3.39k
        }
4926
485
    }
4927
485
}
4928
4929
// Derive settings used to encode the picture
4930
// Both normative (e.g. frame header info) and non-normative (e.g. feature levels) are set here
4931
485
static void init_pic_settings(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
4932
485
    FrameHeader* frm_hdr        = &pcs->frm_hdr;
4933
485
    pcs->allow_comp_inter_inter = pcs->slice_type != I_SLICE;
4934
485
    frm_hdr->reference_mode     = pcs->slice_type == I_SLICE ? (ReferenceMode)0xFF
4935
485
            : svt_aom_is_incomp_mg_frame(pcs)                ? SINGLE_REFERENCE
4936
0
                                                             : REFERENCE_MODE_SELECT;
4937
4938
485
    pcs->av1_cm->mi_cols = pcs->aligned_width >> MI_SIZE_LOG2;
4939
485
    pcs->av1_cm->mi_rows = pcs->aligned_height >> MI_SIZE_LOG2;
4940
4941
    // Initialize the order hints
4942
485
    const OrderHintInfo* const order_hint_info = &pcs->scs->seq_header.order_hint_info;
4943
485
    uint32_t*                  ref_order_hint  = pcs->ref_order_hint;
4944
3.88k
    for (uint8_t i = 0; i < INTER_REFS_PER_FRAME; ++i) {
4945
3.39k
        ref_order_hint[i] = pcs->av1_ref_signal.ref_poc_array[i] % (uint64_t)(1 << (order_hint_info->order_hint_bits));
4946
3.39k
    }
4947
485
    pcs->cur_order_hint = pcs->picture_number % (uint64_t)(1 << (order_hint_info->order_hint_bits));
4948
4949
485
    set_ref_frame_sign_bias(scs, pcs);
4950
4951
    // TODO: put this in EbMotionEstimationProcess?
4952
485
    copy_tf_params(scs, pcs, ctx);
4953
    // TODO: put this in EbMotionEstimationProcess?
4954
    // ME Kernel Multi-Processes Signal(s) derivation
4955
485
    const bool rtc_tune = SVT_RTC_TUNE(scs);
4956
485
    const bool allintra = SVT_ALLINTRA(scs);
4957
485
    allintra       ? svt_aom_sig_deriv_multi_processes_allintra(scs, pcs)
4958
485
        : rtc_tune ? svt_aom_sig_deriv_multi_processes_rtc(scs, pcs)
4959
0
                   : svt_aom_sig_deriv_multi_processes_default(scs, pcs);
4960
4961
485
    update_count_try(scs, pcs);
4962
4963
485
    if (ctx->transition_detected == 1) {
4964
0
        if (pcs->temporal_layer_index == 0) {
4965
0
            pcs->transition_present  = 1;
4966
0
            ctx->transition_detected = 0;
4967
0
        }
4968
0
    }
4969
4970
485
    if (ctx->list0_only && pcs->slice_type == B_SLICE && pcs->temporal_layer_index == 0) {
4971
0
        pcs->ref_list1_count_try = 0;
4972
0
    }
4973
485
    assert(pcs->ref_list0_count_try <= pcs->ref_list0_count);
4974
485
    assert(pcs->ref_list1_count_try <= pcs->ref_list1_count);
4975
4976
    // Setup the skip mode syntax, see: spec 5.9.22 - Skip mode params syntax
4977
485
    svt_av1_setup_skip_mode_allowed(pcs);
4978
485
    frm_hdr->skip_mode_params.skip_mode_flag = frm_hdr->skip_mode_params.skip_mode_allowed;
4979
4980
    //set the ref frame types used for this picture,
4981
485
    set_all_ref_frame_type(ctx, pcs, pcs->ref_frame_type_arr, &pcs->tot_ref_frame_types);
4982
485
}
4983
4984
// Create MG arrays with pics in decode order (ctx->mg_pictures_array) and dispaly order (ctx->mg_pictures_array_disp_order)
4985
// Input is ctx->mg_pictures_array with all pics in the MG sorted by display order
4986
485
static void store_mg_picture_arrays(PictureDecisionContext* ctx) {
4987
485
    const unsigned int mg_size = ctx->mg_size;
4988
4989
    // mg_pictures_array arrives in display order, so copy into display order array
4990
485
    svt_memcpy(ctx->mg_pictures_array_disp_order, ctx->mg_pictures_array, mg_size * sizeof(PictureParentControlSet*));
4991
4992
    // Sort MG pics into decode order
4993
485
    PictureParentControlSet** mg_pics = &ctx->mg_pictures_array[0];
4994
485
    for (unsigned int i = 0; i < mg_size - 1; ++i) {
4995
0
        for (unsigned int j = i + 1; j < mg_size; ++j) {
4996
0
            if (mg_pics[j]->decode_order < mg_pics[i]->decode_order) {
4997
0
                PictureParentControlSet* temp = mg_pics[i];
4998
0
                mg_pics[i]                    = ctx->mg_pictures_array[j];
4999
0
                mg_pics[j]                    = temp;
5000
0
            }
5001
0
        }
5002
0
    }
5003
485
}
5004
5005
// return true if the frame is part of an incomplete MG (at the end of a GOP)
5006
1.45k
bool svt_aom_is_incomp_mg_frame(PictureParentControlSet* pcs) {
5007
1.45k
    return (pcs->pred_struct_ptr->pred_type == LOW_DELAY && pcs->scs->static_config.pred_structure == RANDOM_ACCESS);
5008
1.45k
}
5009
5010
static void assign_and_release_pa_refs(EncodeContext* enc_ctx, PictureParentControlSet* pcs,
5011
485
                                       PictureDecisionContext* ctx) {
5012
485
    const unsigned int mg_size = ctx->mg_size;
5013
970
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5014
485
        pcs = ctx->mg_pictures_array[pic_i];
5015
485
        if (pcs->slice_type == B_SLICE) {
5016
0
            for (REF_FRAME_MINUS1 ref = LAST; ref < ALT + 1; ref++) {
5017
                // hardcode the reference for the overlay frame
5018
0
                uint64_t ref_poc = pcs->is_overlay ? pcs->picture_number : pcs->av1_ref_signal.ref_poc_array[ref];
5019
5020
0
                uint8_t list_idx = get_list_idx(ref + 1);
5021
0
                uint8_t ref_idx  = get_ref_frame_idx(ref + 1);
5022
0
                svt_block_on_mutex(enc_ctx->pd_dpb_mutex);
5023
0
                PaReferenceEntry* pa_ref_entry = search_ref_in_ref_queue_pa(enc_ctx, ref_poc);
5024
0
                assert(pa_ref_entry != NULL);
5025
                // Set the Reference Object
5026
0
                pcs->ref_pa_pic_ptr_array[list_idx][ref_idx] = pa_ref_entry->input_object_ptr;
5027
0
                pcs->ref_pic_poc_array[list_idx][ref_idx]    = ref_poc;
5028
                // Increment the PA Reference's liveCount by the number of tiles in the input picture
5029
0
                svt_object_inc_live_count(pa_ref_entry->input_object_ptr, 1);
5030
5031
0
                pcs->ref_y8b_array[list_idx][ref_idx] = pa_ref_entry->y8b_wrapper;
5032
5033
0
                if (pa_ref_entry->y8b_wrapper) {
5034
                    //y8b follows longest life cycle of pa ref and input. so it needs to build on top of live count of pa ref
5035
0
                    svt_object_inc_live_count(pa_ref_entry->y8b_wrapper, 1);
5036
0
                }
5037
0
                svt_release_mutex(enc_ctx->pd_dpb_mutex);
5038
0
            }
5039
0
        }
5040
5041
485
        uint8_t released_pics_idx = 0;
5042
5043
        // If the pic is added to DPB, add to ref list until all frames that use it have had a chance to reference it
5044
485
        if (pcs->av1_ref_signal.refresh_frame_mask) {
5045
            //assert(!pcs->is_overlay); // is this true?
5046
            //Update the DPB
5047
4.36k
            for (uint8_t i = 0; i < REF_FRAMES; i++) {
5048
3.88k
                if ((pcs->av1_ref_signal.refresh_frame_mask >> i) & 1) {
5049
3.88k
                    svt_block_on_mutex(enc_ctx->pd_dpb_mutex);
5050
                    // Get the current entry at that spot in the DPB
5051
3.88k
                    PaReferenceEntry* input_entry = enc_ctx->pd_dpb[i];
5052
5053
                    // If DPB entry is occupied, release the current entry
5054
3.88k
                    if (input_entry->is_valid) {
5055
0
                        bool still_in_dpb = 0;
5056
0
                        for (uint8_t j = 0; j < REF_FRAMES; j++) {
5057
0
                            if (j == i) {
5058
0
                                continue;
5059
0
                            }
5060
0
                            if (enc_ctx->pd_dpb[j]->is_valid &&
5061
0
                                enc_ctx->pd_dpb[j]->picture_number == input_entry->picture_number) {
5062
0
                                still_in_dpb = 1;
5063
0
                            }
5064
0
                        }
5065
0
                        if (!still_in_dpb) {
5066
0
                            pcs->released_pics[released_pics_idx++] = input_entry->decode_order;
5067
0
                        }
5068
5069
                        // Release the entry at that DPB spot
5070
                        // Release the nominal live_count value
5071
0
                        svt_release_object(input_entry->input_object_ptr);
5072
5073
0
                        if (input_entry->y8b_wrapper) {
5074
                            //y8b needs to get decremented at the same time of pa ref
5075
0
                            svt_release_object(input_entry->y8b_wrapper);
5076
0
                        }
5077
5078
0
                        input_entry->input_object_ptr = (EbObjectWrapper*)NULL;
5079
0
                    }
5080
5081
                    // Update the list entry with the info of the new pic that is replacing the old pic in the DPB
5082
                    // Place Picture in Picture Decision PA Reference Queue
5083
3.88k
                    input_entry->input_object_ptr = pcs->pa_ref_pic_wrapper;
5084
3.88k
                    input_entry->picture_number   = pcs->picture_number;
5085
3.88k
                    input_entry->is_valid         = true;
5086
3.88k
                    input_entry->decode_order     = pcs->decode_order;
5087
3.88k
                    input_entry->is_alt_ref       = pcs->is_alt_ref;
5088
3.88k
                    input_entry->y8b_wrapper      = pcs->y8b_wrapper;
5089
5090
3.88k
                    svt_object_inc_live_count(input_entry->input_object_ptr, 1);
5091
5092
3.88k
                    if (input_entry->y8b_wrapper) {
5093
                        //y8b follows longest life cycle of pa ref and input. so it needs to build on top of live count of pa ref
5094
3.88k
                        svt_object_inc_live_count(input_entry->y8b_wrapper, 1);
5095
3.88k
                    }
5096
3.88k
                    svt_release_mutex(enc_ctx->pd_dpb_mutex);
5097
3.88k
                }
5098
3.88k
            }
5099
485
        } else {
5100
0
            assert(!pcs->is_ref);
5101
0
        }
5102
485
        pcs->released_pics_count = released_pics_idx;
5103
485
    }
5104
485
}
5105
5106
// Send pictures to TF and ME
5107
485
static void process_pics(SequenceControlSet* scs, PictureDecisionContext* ctx) {
5108
485
    PictureParentControlSet* pcs     = NULL; // init'd to quiet build warnings
5109
485
    const unsigned int       mg_size = ctx->mg_size;
5110
    // Process previous delayed Intra if we have one
5111
485
    if (ctx->prev_delayed_intra) {
5112
0
        pcs = ctx->prev_delayed_intra;
5113
0
        store_gf_group(pcs, ctx, mg_size);
5114
485
    } else {
5115
970
        for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5116
485
            pcs = ctx->mg_pictures_array_disp_order[pic_i];
5117
485
            if (svt_aom_is_delayed_intra(pcs) == false) {
5118
485
                store_gf_group(pcs, ctx, mg_size);
5119
485
            }
5120
485
        }
5121
485
    }
5122
    //Process previous delayed Intra if we have one
5123
485
    if (ctx->prev_delayed_intra) {
5124
0
        pcs                      = ctx->prev_delayed_intra;
5125
0
        ctx->base_counter        = 0;
5126
0
        ctx->gm_pp_last_detected = 0;
5127
0
        pcs->filt_to_unfilt_diff = ctx->filt_to_unfilt_diff = (uint32_t)~0;
5128
0
        mctf_frame(scs, pcs, ctx);
5129
0
        ctx->filt_to_unfilt_diff = pcs->slice_type == I_SLICE ? pcs->filt_to_unfilt_diff : ctx->filt_to_unfilt_diff;
5130
0
    }
5131
5132
    //Do TF loop in display order
5133
970
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5134
485
        pcs = ctx->mg_pictures_array_disp_order[pic_i];
5135
5136
485
        if (svt_aom_is_delayed_intra(pcs) == false) {
5137
485
            if (pcs->slice_type == B_SLICE && pcs->temporal_layer_index == 0) {
5138
0
                pcs->gm_pp_enabled = ctx->base_counter == 0 ? 1 : 0;
5139
0
                ctx->base_counter  = 1 - ctx->base_counter;
5140
0
            }
5141
5142
485
            pcs->filt_to_unfilt_diff = ctx->filt_to_unfilt_diff;
5143
485
            mctf_frame(scs, pcs, ctx);
5144
485
            ctx->filt_to_unfilt_diff = pcs->slice_type == I_SLICE ? pcs->filt_to_unfilt_diff : ctx->filt_to_unfilt_diff;
5145
485
            ctx->gm_pp_last_detected = pcs->gm_pp_enabled ? pcs->gm_pp_detected : ctx->gm_pp_last_detected;
5146
485
        }
5147
485
    }
5148
5149
485
    if (ctx->prev_delayed_intra) {
5150
0
        pcs                     = ctx->prev_delayed_intra;
5151
0
        ctx->prev_delayed_intra = NULL;
5152
0
        send_picture_out(scs, pcs, ctx);
5153
0
    }
5154
5155
    //split MG into two for these two special cases
5156
485
    uint8_t ldp_delayi_mg = 0;
5157
485
    uint8_t ldp_i_eos_mg  = 0;
5158
5159
    // Special considerations for I_SLICE after incomplete MG pic
5160
485
    if (ctx->mg_pictures_array[mg_size - 1]->slice_type == I_SLICE &&
5161
485
        svt_aom_is_incomp_mg_frame(ctx->mg_pictures_array[0])) {
5162
0
        if (svt_aom_is_delayed_intra(ctx->mg_pictures_array[mg_size - 1])) {
5163
0
            ldp_delayi_mg = 1;
5164
0
        } else if (ctx->mg_pictures_array[mg_size - 1]->slice_type == I_SLICE &&
5165
0
                   ctx->mg_pictures_array[mg_size - 1]->end_of_sequence_flag) {
5166
0
            ldp_i_eos_mg = 1;
5167
0
        }
5168
0
    }
5169
5170
970
    for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5171
485
        pcs = ctx->mg_pictures_array[pic_i];
5172
485
        if (svt_aom_is_delayed_intra(pcs)) {
5173
0
            ctx->prev_delayed_intra = pcs;
5174
5175
0
            if (ldp_delayi_mg) {
5176
0
                ctx->mg_progress_id++;
5177
0
            }
5178
5179
0
            pcs->ext_mg_id   = ctx->mg_progress_id;
5180
0
            pcs->ext_mg_size = 1;
5181
485
        } else {
5182
485
            pcs->ext_mg_id   = ctx->mg_progress_id;
5183
485
            pcs->ext_mg_size = ldp_delayi_mg || ldp_i_eos_mg ? mg_size - 1 : mg_size;
5184
5185
485
            if (ldp_i_eos_mg && pcs->slice_type == I_SLICE) {
5186
0
                ctx->mg_progress_id++;
5187
0
                pcs->ext_mg_id   = ctx->mg_progress_id;
5188
0
                pcs->ext_mg_size = 1;
5189
0
            }
5190
485
            pcs->gm_pp_detected = ctx->gm_pp_last_detected;
5191
485
            send_picture_out(scs, pcs, ctx);
5192
485
        }
5193
485
    }
5194
5195
485
    ctx->mg_progress_id++;
5196
485
}
5197
5198
// update the DPB stored in the PD context
5199
485
static void update_dpb(PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
5200
485
    Av1RpsNode* av1_rps = &pcs->av1_ref_signal;
5201
485
    if (av1_rps->refresh_frame_mask) {
5202
4.36k
        for (int i = 0; i < REF_FRAMES; i++) {
5203
3.88k
            if ((av1_rps->refresh_frame_mask >> i) & 1) {
5204
3.88k
                ctx->dpb[i].picture_number       = pcs->picture_number;
5205
3.88k
                ctx->dpb[i].decode_order         = pcs->decode_order;
5206
3.88k
                ctx->dpb[i].temporal_layer_index = pcs->temporal_layer_index;
5207
3.88k
            }
5208
3.88k
        }
5209
485
    }
5210
485
}
5211
5212
0
static uint32_t calc_ahd_pd(SequenceControlSet* scs, PictureParentControlSet* pcs, PictureDecisionContext* ctx) {
5213
    // accumulative histogram (absolute) differences between the past and current frame
5214
0
    uint32_t ahd = 0;
5215
0
    uint32_t region_in_picture_width_index;
5216
0
    uint32_t region_in_picture_height_index;
5217
    // Loop over regions inside the picture
5218
0
    for (region_in_picture_width_index = 0;
5219
0
         region_in_picture_width_index < scs->picture_analysis_number_of_regions_per_width;
5220
0
         region_in_picture_width_index++) { // loop over horizontal regions
5221
0
        for (region_in_picture_height_index = 0;
5222
0
             region_in_picture_height_index < scs->picture_analysis_number_of_regions_per_height;
5223
0
             region_in_picture_height_index++) { // loop over vertical regions
5224
5225
0
            for (int bin = 0; bin < HISTOGRAM_NUMBER_OF_BINS; ++bin) {
5226
0
                ahd += ABS(
5227
0
                    (int32_t)
5228
0
                        pcs->picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin] -
5229
0
                    (int32_t)ctx
5230
0
                        ->prev_picture_histogram[region_in_picture_width_index][region_in_picture_height_index][bin]);
5231
0
            }
5232
0
        }
5233
0
    }
5234
0
    return (ahd);
5235
0
}
5236
5237
/* Picture Decision Kernel */
5238
5239
/***************************************************************************************************
5240
*
5241
* @brief
5242
*  The Picture Decision process performs multi-picture level decisions, including setting of the prediction structure,
5243
*  setting the picture type and performing scene change detection.
5244
*
5245
* @par Description:
5246
*  Since the prior Picture Analysis process stage is multithreaded, inputs to the Picture Decision Process can arrive
5247
*  out-of-display-order, so a reordering queue is used to enforce processing of pictures in display order. The algorithms
5248
*  employed in the Picture Decision process are dependent on prior pictures’ statistics, so the order in which pictures are
5249
*  processed must be strictly enforced. Additionally, the Picture Decision process uses the reorder queue to hold input pictures
5250
*  until they can be started into the Motion Estimation process while following the proper prediction structure.
5251
*
5252
* @param[in] Pictures
5253
*  The Picture Decision Process takes images spontaneously as they arive and perform multi-picture level decisions,
5254
*  including setting of the picture structure, setting the picture type and scene change detection.
5255
*
5256
* @param[out] Picture Control Set
5257
*  Picture Control Set with fully available Picture Analysis Reference List
5258
*
5259
* @remarks
5260
*  For Low Delay Sequences, pictures are started into the encoder pipeline immediately.
5261
*
5262
*  For Random Access Sequences, pictures are held for up to a PredictionStructurePeriod
5263
*    in order to determine if a Scene Change or Intra Frame is forthcoming. Either of
5264
*    those events (and additionally a End of Sequence Flag) will change the expected
5265
*    prediction structure.
5266
*
5267
*  Below is an example worksheet for how Intra Flags and Scene Change Flags interact
5268
*    together to affect the prediction structure.
5269
*
5270
*  The base prediction structure for this example is a 3-Level Hierarchical Random Access,
5271
*    Single Reference Prediction Structure:
5272
*
5273
*        b   b
5274
*       / \ / \
5275
*      /   b   \
5276
*     /   / \   \
5277
*    I-----------b
5278
*
5279
*  From this base structure, the following RPS positions are derived:
5280
*
5281
*    p   p       b   b       p   p
5282
*     \   \     / \ / \     /   /
5283
*      P   \   /   b   \   /   P
5284
*       \   \ /   / \   \ /   /
5285
*        ----I-----------b----
5286
*
5287
*    L L L   I  [ Normal ]   T T T
5288
*    2 1 0   n               0 1 2
5289
*            t
5290
*            r
5291
*            a
5292
*
5293
*  The RPS is composed of Leading Picture [L2-L0], Intra (CRA), Base/Normal Pictures,
5294
*    and Trailing Pictures [T0-t2]. Generally speaking, Leading Pictures are useful
5295
*    for handling scene changes without adding extraneous I-pictures and the Trailing
5296
*    pictures are useful for terminating GOPs.
5297
*
5298
*  Here is a table of possible combinations of pictures needed to handle intra and
5299
*    scene changes happening in quick succession.
5300
*
5301
*        Distance to scene change ------------>
5302
*
5303
*                  0              1                 2                3+
5304
*   I
5305
*   n
5306
*   t   0        I   I           n/a               n/a              n/a
5307
*   r
5308
*   a              p              p
5309
*                   \            /
5310
*   P   1        I   I          I   I              n/a              n/a
5311
*   e
5312
*   r               p                               p
5313
*   i                \                             /
5314
*   o            p    \         p   p             /   p
5315
*   d             \    \       /     \           /   /
5316
*       2     I    -----I     I       I         I----    I          n/a
5317
*   |
5318
*   |            p   p           p   p            p   p            p   p
5319
*   |             \   \         /     \          /     \          /   /
5320
*   |              P   \       /   p   \        /   p   \        /   P
5321
*   |               \   \     /     \   \      /   /     \      /   /
5322
*   V   3+   I       ----I   I       ----I    I----       I    I----       I
5323
*
5324
*   The table is interpreted as follows:
5325
*
5326
*   If there are no SCs or Intras encountered for a PredPeriod, then the normal
5327
*     prediction structure is applied.
5328
*
5329
*   If there is an intra in the PredPeriod, then one of the above combinations of
5330
*     Leading and Trailing pictures is used.  If there is no scene change, the last
5331
*     valid column consisting of Trailing Pictures only is used.  However, if there
5332
*     is an upcoming scene change before the next intra, then one of the above patterns
5333
*     is used. In the case of End of Sequence flags, only the last valid column of Trailing
5334
*     Pictures is used. The intention here is that any combination of Intra Flag and Scene
5335
*     Change flag can be coded.
5336
***************************************************************************************************/
5337
970
EbErrorType svt_aom_picture_decision_kernel_iter(void* context) {
5338
970
    PictureDecisionContext* ctx = (PictureDecisionContext*)context;
5339
5340
970
    PictureParentControlSet* pcs;
5341
5342
970
    EncodeContext*          enc_ctx;
5343
970
    SequenceControlSet*     scs;
5344
970
    EbObjectWrapper*        in_results_wrapper_ptr;
5345
970
    PictureAnalysisResults* in_results_ptr;
5346
5347
970
    PredictionStructureEntry* pred_position_ptr;
5348
5349
970
    PictureDecisionReorderEntry* queue_entry_ptr;
5350
5351
970
    unsigned int pic_idx;
5352
5353
    // Get Input Full Object
5354
970
    EB_GET_FULL_OBJECT(ctx->picture_analysis_results_input_fifo_ptr, &in_results_wrapper_ptr);
5355
5356
485
    in_results_ptr      = (PictureAnalysisResults*)in_results_wrapper_ptr->object_ptr;
5357
485
    pcs                 = (PictureParentControlSet*)in_results_ptr->pcs_wrapper->object_ptr;
5358
485
    scs                 = pcs->scs;
5359
485
    enc_ctx             = scs->enc_ctx;
5360
485
    const bool allintra = scs->allintra;
5361
    // Input Picture Analysis Results into the Picture Decision Reordering Queue
5362
    // Since the prior Picture Analysis processes stage is multithreaded, inputs to the Picture Decision Process
5363
    // can arrive out-of-display-order, so a the Picture Decision Reordering Queue is used to enforce processing of
5364
    // pictures in display order
5365
485
    if (!pcs->is_overlay) {
5366
485
        int queue_entry_index =
5367
485
            (int)(pcs->picture_number -
5368
485
                  enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index]
5369
485
                      ->picture_number);
5370
485
        queue_entry_index += enc_ctx->picture_decision_reorder_queue_head_index;
5371
485
        queue_entry_index = (queue_entry_index > (int)(enc_ctx->picture_decision_reorder_queue_size - 1))
5372
485
            ? queue_entry_index - (int)enc_ctx->picture_decision_reorder_queue_size
5373
485
            : queue_entry_index;
5374
485
        queue_entry_ptr   = enc_ctx->picture_decision_reorder_queue[queue_entry_index];
5375
485
        if (queue_entry_ptr->ppcs_wrapper != NULL) {
5376
0
            CHECK_REPORT_ERROR_NC(enc_ctx->app_callback_ptr, EB_ENC_PD_ERROR8);
5377
485
        } else {
5378
485
            queue_entry_ptr->ppcs_wrapper   = in_results_ptr->pcs_wrapper;
5379
485
            queue_entry_ptr->picture_number = pcs->picture_number;
5380
485
        }
5381
5382
485
        pcs->pic_decision_reorder_queue_idx = queue_entry_index;
5383
485
        pcs->first_pass_done                = 0;
5384
485
    }
5385
    // Process the head of the Picture Decision Reordering Queue (Entry N)
5386
    // The Picture Decision Reordering Queue should be parsed in the display order to be able to construct a pred structure
5387
485
    queue_entry_ptr = enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index];
5388
5389
970
    while (queue_entry_ptr->ppcs_wrapper != NULL) {
5390
485
        if (scs->lap_rc) {
5391
0
            process_first_pass(scs, enc_ctx);
5392
0
        }
5393
5394
485
        pcs = (PictureParentControlSet*)queue_entry_ptr->ppcs_wrapper->object_ptr;
5395
485
        bool window_avail, eos_reached;
5396
485
        check_window_availability(scs, enc_ctx, pcs, queue_entry_ptr, &window_avail, &eos_reached);
5397
5398
485
        if (!allintra) {
5399
0
            pcs->ahd_error = (uint32_t)~0;
5400
0
            if (window_avail == true && queue_entry_ptr->picture_number > 0 && scs->calc_hist) {
5401
0
                pcs->ahd_error = calc_ahd_pd(scs, pcs, ctx);
5402
0
            }
5403
            // If the relevant frames are available, perform scene change detection
5404
0
            if (window_avail == true && queue_entry_ptr->picture_number > 0) {
5405
0
                perform_scene_change_detection(scs, pcs, ctx);
5406
0
            }
5407
0
        }
5408
5409
        // If the required lookahead frames aren't available, and we haven't reached EOS, must wait for more frames before continuing
5410
485
        if (!window_avail && !eos_reached) {
5411
0
            break;
5412
0
        }
5413
5414
        // Place the PCS into the Pre-Assignment Buffer
5415
        // The Pre-Assignment Buffer is used to store a whole pre-structure
5416
485
        enc_ctx->pre_assignment_buffer[enc_ctx->pre_assignment_buffer_count] = queue_entry_ptr->ppcs_wrapper;
5417
5418
        // Set the POC Number
5419
485
        pcs->picture_number                 = ++ctx->current_input_poc;
5420
485
        pcs->pred_structure                 = scs->static_config.pred_structure;
5421
485
        pcs->hierarchical_layers_diff       = 0;
5422
485
        pcs->init_pred_struct_position_flag = false;
5423
485
        pcs->tpl_group_size                 = 0;
5424
485
        if (pcs->picture_number == 0) {
5425
485
            ctx->prev_delayed_intra = NULL;
5426
485
        }
5427
485
        if (pcs->picture_number == 0) {
5428
485
            ctx->sframe_hier_lvls = scs->static_config.hierarchical_levels;
5429
485
        }
5430
5431
485
        release_prev_picture_from_reorder_queue(enc_ctx);
5432
5433
        // If the Intra period length is 0, then introduce an intra for every picture
5434
485
        if (allintra) {
5435
485
            pcs->idr_flag = true;
5436
485
            pcs->cra_flag = false;
5437
485
        }
5438
        // If an #IntraPeriodLength has passed since the last Intra, then introduce a CRA or IDR based on Intra Refresh type
5439
0
        else if (scs->static_config.intra_period_length != -1) {
5440
0
            pcs->cra_flag = (scs->static_config.intra_refresh_type != SVT_AV1_FWDKF_REFRESH) ? pcs->cra_flag
5441
0
                : ((enc_ctx->intra_period_position == (uint32_t)scs->static_config.intra_period_length) ||
5442
0
                   (pcs->scene_change_flag == true))
5443
0
                ? true
5444
0
                : pcs->cra_flag;
5445
5446
0
            pcs->idr_flag = (scs->static_config.intra_refresh_type != SVT_AV1_KF_REFRESH)            ? pcs->idr_flag
5447
0
                : enc_ctx->intra_period_position == (uint32_t)scs->static_config.intra_period_length ?
5448
5449
0
                                                                                                     true
5450
0
                                                                                                     : pcs->idr_flag;
5451
0
        }
5452
485
        pcs->idr_flag = (scs->static_config.intra_refresh_type != SVT_AV1_KF_REFRESH)            ? pcs->idr_flag
5453
485
            : (pcs->scene_change_flag == true || pcs->input_ptr->pic_type == EB_AV1_KEY_PICTURE) ? true
5454
485
                                                                                                 : pcs->idr_flag;
5455
485
        if (!allintra && pcs->picture_number > 0 && scs->static_config.sframe_posi.sframe_posis &&
5456
0
            (pcs->cra_flag || pcs->idr_flag)) {
5457
            // if this key frame position is set to an S-frame by sframe-posi, replace this I frame with B frame,
5458
            // and then the S_FRAME will be set in set_sframe_type()
5459
0
            int32_t dist_next_s = 0;
5460
0
            if (get_dist_to_s(&scs->static_config.sframe_posi, pcs->picture_number, &dist_next_s) == 0) {
5461
0
                pcs->cra_flag = false;
5462
0
                pcs->idr_flag = false;
5463
0
            }
5464
0
        }
5465
485
        enc_ctx->pre_assignment_buffer_eos_flag = (pcs->end_of_sequence_flag) ? (uint32_t)true
5466
485
                                                                              : enc_ctx->pre_assignment_buffer_eos_flag;
5467
5468
        // Histogram data to be used at the next input (N + 1)
5469
        // TODO: can this be moved to the end of perform_scene_change_detection? Histograms aren't needed if at EOS
5470
485
        if (scs->calc_hist) {
5471
0
            copy_histograms(pcs, ctx);
5472
0
        }
5473
5474
        // Increment the Pre-Assignment Buffer Intra Count
5475
485
        enc_ctx->pre_assignment_buffer_intra_count += (pcs->idr_flag || pcs->cra_flag);
5476
485
        enc_ctx->pre_assignment_buffer_idr_count += pcs->idr_flag;
5477
485
        enc_ctx->pre_assignment_buffer_count += 1;
5478
5479
        // Increment the Intra Period Position
5480
485
        enc_ctx->intra_period_position = ((enc_ctx->intra_period_position ==
5481
485
                                           (uint32_t)scs->static_config.intra_period_length) ||
5482
0
                                          (pcs->scene_change_flag == true) ||
5483
0
                                          pcs->input_ptr->pic_type == EB_AV1_KEY_PICTURE)
5484
485
            ? 0
5485
485
            : enc_ctx->intra_period_position + 1;
5486
5487
#if LAD_MG_PRINT
5488
        print_pre_ass_buffer(enc_ctx, pcs, 1);
5489
#endif
5490
5491
485
        uint32_t next_mg_hierarchical_levels = scs->static_config.hierarchical_levels;
5492
        // Overwrite next_mg_hierarchical_levels when an S-Frame needs to modify the mini-GOP size.
5493
485
        if (ctx->sframe_hier_lvls != (int32_t)scs->static_config.hierarchical_levels) {
5494
0
            next_mg_hierarchical_levels = ctx->sframe_hier_lvls;
5495
0
        }
5496
485
        if (ctx->enable_startup_mg) {
5497
0
            next_mg_hierarchical_levels = scs->static_config.startup_mg_size;
5498
0
        }
5499
        // Determine if Pictures can be released from the Pre-Assignment Buffer
5500
485
        if ((enc_ctx->pre_assignment_buffer_intra_count > 0) ||
5501
0
            (enc_ctx->pre_assignment_buffer_count == (uint32_t)(1 << next_mg_hierarchical_levels)) ||
5502
0
            (enc_ctx->pre_assignment_buffer_eos_flag == true) ||
5503
485
            (pcs->pred_structure == LOW_DELAY || pcs->pred_structure == ALL_INTRA)) {
5504
#if LAD_MG_PRINT
5505
            print_pre_ass_buffer(enc_ctx, pcs, 0);
5506
#endif
5507
            // Once there are enough frames in the pre-assignement buffer, we can setup the mini-gops
5508
485
            set_mini_gop_structure(scs, enc_ctx, pcs, ctx);
5509
5510
            // Loop over Mini GOPs
5511
970
            for (unsigned int mini_gop_index = 0; mini_gop_index < ctx->total_number_of_mini_gops; ++mini_gop_index) {
5512
485
                bool pre_assignment_buffer_first_pass_flag = true;
5513
5514
                // Get the 1st PCS in the mini-GOP
5515
485
                pcs = (PictureParentControlSet*)enc_ctx
5516
485
                          ->pre_assignment_buffer[ctx->mini_gop_start_index[mini_gop_index]]
5517
485
                          ->object_ptr;
5518
5519
                // Derive the temporal layer difference between the current mini GOP and the previous mini GOP
5520
485
                pcs->hierarchical_layers_diff = (int32_t)enc_ctx->previous_mini_gop_hierarchical_levels -
5521
485
                    (int32_t)pcs->hierarchical_levels;
5522
5523
                // Set init_pred_struct_position_flag to true if mini-GOP switch
5524
485
                pcs->init_pred_struct_position_flag = enc_ctx->is_mini_gop_changed = (pcs->hierarchical_layers_diff !=
5525
485
                                                                                      0);
5526
5527
                // Keep track of the number of hierarchical levels of the latest implemented mini GOP
5528
485
                enc_ctx->previous_mini_gop_hierarchical_levels = ctx->mini_gop_hierarchical_levels[mini_gop_index];
5529
485
                ctx->cut_short_ra_mg                           = 0;
5530
                // 1st Loop over Pictures in the Pre-Assignment Buffer
5531
                // Setup the pred strucutre and picture types for all frames in the mini-GOP (including overlay pics)
5532
485
                for (pic_idx = ctx->mini_gop_start_index[mini_gop_index];
5533
970
                     pic_idx <= ctx->mini_gop_end_index[mini_gop_index];
5534
485
                     ++pic_idx) {
5535
485
                    pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
5536
485
                    scs = pcs->scs;
5537
5538
485
                    update_pred_struct_and_pic_type(scs,
5539
485
                                                    enc_ctx,
5540
485
                                                    pcs,
5541
485
                                                    ctx,
5542
485
                                                    mini_gop_index,
5543
485
                                                    pre_assignment_buffer_first_pass_flag,
5544
485
                                                    &pcs->slice_type,
5545
485
                                                    &pred_position_ptr);
5546
5547
485
                    if (scs->static_config.enable_overlays == true) {
5548
                        // At this stage we know the prediction structure and the location of ALT_REF pictures.
5549
                        // For every ALTREF picture, there is an overlay picture. They extra pictures are released
5550
                        // is_alt_ref flag is set for non-slice base layer pictures
5551
0
                        if (pred_position_ptr->temporal_layer_index == 0 && pcs->slice_type != I_SLICE) {
5552
0
                            pcs->is_alt_ref         = 1;
5553
0
                            pcs->frm_hdr.show_frame = 0;
5554
0
                        }
5555
                        // release the overlay PCS for non alt ref pictures. First picture does not have overlay PCS
5556
0
                        else if (pcs->picture_number) {
5557
0
                            svt_release_object(pcs->overlay_ppcs_ptr->input_pic_wrapper);
5558
                            // release the pa_reference_picture
5559
0
                            svt_release_object(pcs->overlay_ppcs_ptr->pa_ref_pic_wrapper);
5560
0
                            svt_release_object(pcs->overlay_ppcs_ptr->scs_wrapper);
5561
                            // release the parent pcs
5562
                            // Note: this release will recycle ppcs to empty fifo if not live_count+1 in ResourceCoordination.
5563
0
                            svt_release_object(pcs->overlay_ppcs_ptr->p_pcs_wrapper_ptr);
5564
0
                            pcs->overlay_ppcs_ptr = NULL;
5565
0
                        }
5566
0
                    }
5567
5568
485
                    pcs->pic_idx_in_mg = get_pic_idx_in_mg(scs, enc_ctx, pcs, ctx, pic_idx, mini_gop_index);
5569
5570
970
                    for (uint8_t loop_index = 0; loop_index <= pcs->is_alt_ref; loop_index++) {
5571
                        // Init pred strucutre info - different for overlay/non-overlay
5572
485
                        if (loop_index == 1) {
5573
0
                            pcs = pcs->overlay_ppcs_ptr;
5574
0
                            initialize_overlay_frame(pcs);
5575
485
                        } else {
5576
485
                            assert(!pcs->is_overlay);
5577
485
                            pcs->pred_struct_index    = (uint8_t)enc_ctx->pred_struct_position;
5578
485
                            pcs->temporal_layer_index = (uint8_t)pred_position_ptr->temporal_layer_index;
5579
                            // For flat, set is_highest_layer to false to avoid using aggressive settings for all pictures
5580
485
                            pcs->is_highest_layer = (pcs->temporal_layer_index == pcs->hierarchical_levels) &&
5581
0
                                pcs->hierarchical_levels != 0;
5582
485
                            switch (pcs->slice_type) {
5583
485
                            case I_SLICE:
5584
5585
                                // Reset Prediction Structure Position & Reference Struct Position
5586
485
                                if (pcs->picture_number == 0) {
5587
485
                                    enc_ctx->intra_period_position = 0;
5588
485
                                }
5589
485
                                enc_ctx->elapsed_non_cra_count = 0;
5590
5591
                                // I_SLICE cannot be CRA and IDR
5592
485
                                pcs->cra_flag = !pcs->idr_flag;
5593
5594
485
                                if (pcs->idr_flag) {
5595
485
                                    enc_ctx->elapsed_non_idr_count = 0; // Reset the pictures since last IDR counter
5596
485
                                    ctx->key_poc                   = pcs->picture_number; // log latest key frame poc
5597
485
                                }
5598
485
                                break;
5599
0
                            case B_SLICE:
5600
                                // Reset CRA and IDR Flag
5601
0
                                pcs->cra_flag = false;
5602
0
                                pcs->idr_flag = false;
5603
5604
                                // Increment & Clip the elapsed Non-IDR Counter. This is clipped rather than allowed to free-run
5605
                                // inorder to avoid rollover issues.  This assumes that any the GOP period is less than MAX_ELAPSED_IDR_COUNT
5606
0
                                enc_ctx->elapsed_non_idr_count = MIN(enc_ctx->elapsed_non_idr_count + 1,
5607
0
                                                                     MAX_ELAPSED_IDR_COUNT);
5608
0
                                enc_ctx->elapsed_non_cra_count = MIN(enc_ctx->elapsed_non_cra_count + 1,
5609
0
                                                                     MAX_ELAPSED_IDR_COUNT);
5610
5611
0
                                CHECK_REPORT_ERROR(
5612
0
                                    (pcs->pred_struct_ptr->pred_struct_entry_count < MAX_ELAPSED_IDR_COUNT),
5613
0
                                    enc_ctx->app_callback_ptr,
5614
0
                                    EB_ENC_PD_ERROR1);
5615
5616
0
                                break;
5617
0
                            default:
5618
0
                                CHECK_REPORT_ERROR_NC(enc_ctx->app_callback_ptr, EB_ENC_PD_ERROR2);
5619
0
                                break;
5620
485
                            }
5621
485
                        }
5622
5623
485
                        CHECK_REPORT_ERROR((pcs->pred_struct_ptr->pred_struct_entry_count * REF_LIST_MAX_DEPTH <
5624
485
                                            MAX_ELAPSED_IDR_COUNT),
5625
485
                                           enc_ctx->app_callback_ptr,
5626
485
                                           EB_ENC_PD_ERROR5);
5627
485
                    }
5628
485
                    pre_assignment_buffer_first_pass_flag = false;
5629
485
                }
5630
5631
                // 2nd Loop over Pictures in the Pre-Assignment Buffer
5632
                // Init picture settings
5633
                // 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
5634
485
                const uint32_t has_overlay = ((PictureParentControlSet*)enc_ctx
5635
485
                                                  ->pre_assignment_buffer[ctx->mini_gop_end_index[mini_gop_index]]
5636
485
                                                  ->object_ptr)
5637
485
                                                 ->is_alt_ref
5638
485
                    ? 1
5639
485
                    : 0;
5640
485
                for (pic_idx = ctx->mini_gop_start_index[mini_gop_index];
5641
970
                     pic_idx <= ctx->mini_gop_end_index[mini_gop_index] + has_overlay;
5642
485
                     ++pic_idx) {
5643
                    // 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
5644
485
                    if (has_overlay && pic_idx == ctx->mini_gop_end_index[mini_gop_index] + has_overlay) {
5645
0
                        pcs = ((PictureParentControlSet*)enc_ctx
5646
0
                                   ->pre_assignment_buffer[ctx->mini_gop_end_index[mini_gop_index]]
5647
0
                                   ->object_ptr)
5648
0
                                  ->overlay_ppcs_ptr;
5649
485
                    } else {
5650
485
                        pcs = (PictureParentControlSet*)enc_ctx->pre_assignment_buffer[pic_idx]->object_ptr;
5651
485
                    }
5652
5653
485
                    pcs->picture_number_alt = enc_ctx->picture_number_alt++;
5654
5655
                    // Set the Decode Order
5656
485
                    if ((ctx->mini_gop_idr_count[mini_gop_index] == 0) &&
5657
0
                        (ctx->mini_gop_length[mini_gop_index] == pcs->pred_struct_ptr->pred_struct_entry_count) &&
5658
0
                        (scs->static_config.pred_structure == RANDOM_ACCESS) && !pcs->is_overlay) {
5659
0
                        pcs->decode_order = enc_ctx->decode_base_number +
5660
0
                            pcs->pred_struct_ptr->pred_struct_entry_ptr_array[pcs->pred_struct_index]->decode_order;
5661
485
                    } else {
5662
485
                        pcs->decode_order = pcs->picture_number_alt;
5663
485
                    }
5664
5665
485
                    perform_sc_detection(scs, pcs, ctx);
5666
                    // Update the RC param queue
5667
485
                    update_rc_param_queue(pcs, enc_ctx);
5668
                    // Reset the PA Reference Lists
5669
485
                    EB_MEMSET(pcs->ref_pa_pic_ptr_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5670
485
                    EB_MEMSET(pcs->ref_pa_pic_ptr_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5671
485
                    EB_MEMSET(pcs->ref_y8b_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5672
485
                    EB_MEMSET(pcs->ref_y8b_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(EbObjectWrapper*));
5673
485
                    EB_MEMSET(pcs->ref_pic_poc_array[REF_LIST_0], 0, REF_LIST_MAX_DEPTH * sizeof(uint64_t));
5674
485
                    EB_MEMSET(pcs->ref_pic_poc_array[REF_LIST_1], 0, REF_LIST_MAX_DEPTH * sizeof(uint64_t));
5675
5676
485
                    uint32_t pic_it                = pic_idx - ctx->mini_gop_start_index[mini_gop_index];
5677
485
                    ctx->mg_pictures_array[pic_it] = pcs;
5678
485
                    if (pic_idx == ctx->mini_gop_end_index[mini_gop_index] + has_overlay) {
5679
                        // Increment the Decode Base Number
5680
485
                        enc_ctx->decode_base_number += ctx->mini_gop_length[mini_gop_index] + has_overlay;
5681
485
                    }
5682
485
                }
5683
5684
485
                ctx->mg_size = ctx->mini_gop_end_index[mini_gop_index] + has_overlay -
5685
485
                    ctx->mini_gop_start_index[mini_gop_index] + 1;
5686
5687
                // Store pics in ctx->mg_pictures_array in decode order
5688
                // and pics in ctx->mg_pictures_array_disp_order in display order
5689
485
                store_mg_picture_arrays(ctx);
5690
5691
485
                const unsigned int mg_size = ctx->mg_size;
5692
970
                for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5693
                    // Loop over pics in decode order
5694
485
                    pcs = ctx->mg_pictures_array[pic_i];
5695
485
                    if (pcs->slice_type == I_SLICE) {
5696
485
                        pcs->frm_hdr.frame_type = pcs->idr_flag ? KEY_FRAME : INTRA_ONLY_FRAME;
5697
485
                    } else {
5698
0
                        pcs->frm_hdr.frame_type = INTER_FRAME;
5699
0
                    }
5700
485
                    set_gf_group_param(pcs);
5701
485
                    av1_generate_rps_info(pcs, enc_ctx, ctx, pcs->pic_idx_in_mg, mini_gop_index);
5702
5703
485
                    if (scs->static_config.sframe_dist != 0 || !pcs->is_not_scaled ||
5704
485
                        scs->static_config.sframe_posi.sframe_posis) {
5705
0
                        update_sframe_ref_order_hint(pcs, ctx);
5706
0
                    }
5707
5708
485
                    update_dpb(pcs, ctx);
5709
5710
                    // Set picture settings, incl. normative frame header fields and feature levels in signal_derivation function
5711
485
                    init_pic_settings(scs, pcs, ctx);
5712
485
                }
5713
5714
970
                for (uint32_t pic_i = 0; pic_i < mg_size; ++pic_i) {
5715
485
                    PictureParentControlSet* pcs_1 = ctx->mg_pictures_array_disp_order[pic_i];
5716
485
                    pcs_1->first_frame_in_minigop  = !pic_i;
5717
485
                    if (pcs_1->is_alt_ref) {
5718
0
                        ctx->mg_pictures_array_disp_order[pic_i - 1]->has_show_existing = false;
5719
0
                    }
5720
485
                }
5721
5722
                // Loop over pics in MG and assign their PA reference buffers; release buffers when no longer needed
5723
485
                assign_and_release_pa_refs(enc_ctx, pcs, ctx);
5724
5725
                // Send the pictures in the MG to TF and ME
5726
485
                process_pics(scs, ctx);
5727
485
            } // End MINI GOPs loop
5728
            // Reset the Pre-Assignment Buffer
5729
485
            enc_ctx->pre_assignment_buffer_count       = 0;
5730
485
            enc_ctx->pre_assignment_buffer_idr_count   = 0;
5731
485
            enc_ctx->pre_assignment_buffer_intra_count = 0;
5732
485
            enc_ctx->pre_assignment_buffer_eos_flag    = false;
5733
485
        }
5734
        // Increment the Picture Decision Reordering Queue Head Ptr
5735
485
        enc_ctx->picture_decision_reorder_queue_head_index = (enc_ctx->picture_decision_reorder_queue_head_index ==
5736
485
                                                              enc_ctx->picture_decision_reorder_queue_size - 1)
5737
485
            ? 0
5738
485
            : enc_ctx->picture_decision_reorder_queue_head_index + 1;
5739
5740
        // Get the next entry from the Picture Decision Reordering Queue (Entry N+1)
5741
485
        queue_entry_ptr = enc_ctx->picture_decision_reorder_queue[enc_ctx->picture_decision_reorder_queue_head_index];
5742
485
    }
5743
5744
485
    if (scs->static_config.enable_overlays == true) {
5745
0
        svt_release_object(((PictureParentControlSet*)in_results_ptr->pcs_wrapper->object_ptr)->scs_wrapper);
5746
        // release ppcs, since live_count + 1 before post in ResourceCoordination
5747
0
        svt_release_object(in_results_ptr->pcs_wrapper);
5748
0
    }
5749
5750
    // Release the Input Results
5751
485
    svt_release_object(in_results_wrapper_ptr);
5752
485
    return EB_ErrorNone;
5753
485
}
5754
5755
485
void* svt_aom_picture_decision_kernel(void* input_ptr) {
5756
485
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
5757
970
    for (;;) {
5758
970
        EbErrorType err = svt_aom_picture_decision_kernel_iter(thread_ctx->priv);
5759
970
        if (err == EB_NoErrorFifoShutdown) {
5760
485
            return NULL;
5761
485
        }
5762
970
    }
5763
0
    return NULL;
5764
485
}