Coverage Report

Created: 2026-10-17 06:56

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