Coverage Report

Created: 2026-05-16 06:41

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