Coverage Report

Created: 2026-07-16 06:32

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