Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/av1/encoder/svc_layercontext.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2019, Alliance for Open Media. All rights reserved.
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
11
12
#include <assert.h>
13
#include <math.h>
14
15
#include "av1/encoder/encoder.h"
16
#include "av1/encoder/encoder_alloc.h"
17
18
0
static void swap_ptr(void *a, void *b) {
19
0
  void **a_p = (void **)a;
20
0
  void **b_p = (void **)b;
21
0
  void *c = *a_p;
22
0
  *a_p = *b_p;
23
0
  *b_p = c;
24
0
}
25
26
0
void av1_init_layer_context(AV1_COMP *const cpi) {
27
0
  AV1_COMMON *const cm = &cpi->common;
28
0
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
29
0
  SVC *const svc = &cpi->svc;
30
0
  int mi_rows = cpi->common.mi_params.mi_rows;
31
0
  int mi_cols = cpi->common.mi_params.mi_cols;
32
0
  svc->base_framerate = 30.0;
33
0
  svc->current_superframe = 0;
34
0
  svc->force_zero_mode_spatial_ref = 1;
35
0
  svc->num_encoded_top_layer = 0;
36
0
  svc->use_flexible_mode = 0;
37
0
  svc->has_lower_quality_layer = 0;
38
39
0
  for (int sl = 0; sl < svc->number_spatial_layers; ++sl) {
40
0
    for (int tl = 0; tl < svc->number_temporal_layers; ++tl) {
41
0
      int layer = LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
42
0
      LAYER_CONTEXT *const lc = &svc->layer_context[layer];
43
0
      RATE_CONTROL *const lrc = &lc->rc;
44
0
      PRIMARY_RATE_CONTROL *const lp_rc = &lc->p_rc;
45
0
      lrc->ni_av_qi = oxcf->rc_cfg.worst_allowed_q;
46
0
      lp_rc->total_actual_bits = 0;
47
0
      lrc->ni_tot_qi = 0;
48
0
      lp_rc->tot_q = 0.0;
49
0
      lp_rc->avg_q = 0.0;
50
0
      lp_rc->ni_frames = 0;
51
0
      lrc->decimation_count = 0;
52
0
      lrc->decimation_factor = 0;
53
0
      lrc->worst_quality = av1_quantizer_to_qindex(lc->max_q);
54
0
      lrc->best_quality = av1_quantizer_to_qindex(lc->min_q);
55
0
      lrc->rtc_external_ratectrl = 0;
56
0
      for (int i = 0; i < RATE_FACTOR_LEVELS; ++i) {
57
0
        lp_rc->rate_correction_factors[i] = 1.0;
58
0
      }
59
0
      lc->target_bandwidth = lc->layer_target_bitrate;
60
0
      lp_rc->last_q[INTER_FRAME] = lrc->worst_quality;
61
0
      lp_rc->avg_frame_qindex[INTER_FRAME] = lrc->worst_quality;
62
0
      lp_rc->avg_frame_qindex[KEY_FRAME] = lrc->worst_quality;
63
0
      if (oxcf->rc_cfg.mode == AOM_VBR) {
64
        // Initialize avg_frame_qindex to the midpoint of worst and best
65
        // quality for VBR mode, matching av1_primary_rc_init().
66
0
        lp_rc->avg_frame_qindex[INTER_FRAME] =
67
0
            (lrc->worst_quality + lrc->best_quality) / 2;
68
0
        lp_rc->avg_frame_qindex[KEY_FRAME] =
69
0
            (lrc->worst_quality + lrc->best_quality) / 2;
70
0
      }
71
0
      lp_rc->buffer_level =
72
0
          oxcf->rc_cfg.starting_buffer_level_ms * lc->target_bandwidth / 1000;
73
0
      lp_rc->bits_off_target = lp_rc->buffer_level;
74
      // Initialize the cyclic refresh parameters. If spatial layers are used
75
      // (i.e., ss_number_layers > 1), these need to be updated per spatial
76
      // layer. Cyclic refresh is only applied on base temporal layer.
77
0
      if (svc->number_spatial_layers > 1 && tl == 0 &&
78
0
          cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
79
0
        lc->sb_index = 0;
80
0
        lc->actual_num_seg1_blocks = 0;
81
0
        lc->actual_num_seg2_blocks = 0;
82
0
        lc->counter_encode_maxq_scene_change = 0;
83
0
        aom_free(lc->map);
84
0
        CHECK_MEM_ERROR(cm, lc->map,
85
0
                        aom_calloc(mi_rows * mi_cols, sizeof(*lc->map)));
86
0
      }
87
0
    }
88
0
    svc->downsample_filter_type[sl] = BILINEAR;
89
0
    svc->downsample_filter_phase[sl] = 8;
90
0
    svc->last_layer_dropped[sl] = false;
91
0
    svc->drop_spatial_layer[sl] = false;
92
0
  }
93
0
  if (svc->number_spatial_layers == 3) {
94
0
    svc->downsample_filter_type[0] = EIGHTTAP_SMOOTH;
95
0
  }
96
0
}
97
98
0
bool av1_alloc_layer_context(AV1_COMP *cpi, int num_layers) {
99
0
  SVC *const svc = &cpi->svc;
100
0
  if (svc->layer_context == NULL || svc->num_allocated_layers < num_layers) {
101
0
    av1_free_svc_cyclic_refresh(cpi);
102
0
    assert(num_layers > 1);
103
0
    aom_free(svc->layer_context);
104
0
    svc->num_allocated_layers = 0;
105
0
    svc->layer_context =
106
0
        (LAYER_CONTEXT *)aom_calloc(num_layers, sizeof(*svc->layer_context));
107
0
    if (svc->layer_context == NULL) return false;
108
0
    svc->num_allocated_layers = num_layers;
109
0
  }
110
0
  return true;
111
0
}
112
113
// Update the layer context from a change_config() call.
114
void av1_update_layer_context_change_config(AV1_COMP *const cpi,
115
0
                                            const int64_t target_bandwidth) {
116
0
  const RATE_CONTROL *const rc = &cpi->rc;
117
0
  const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
118
0
  AV1_COMMON *const cm = &cpi->common;
119
0
  SVC *const svc = &cpi->svc;
120
0
  int layer = 0;
121
0
  int64_t spatial_layer_target = 0;
122
0
  float bitrate_alloc = 1.0;
123
0
  const int mi_rows = cm->mi_params.mi_rows;
124
0
  const int mi_cols = cm->mi_params.mi_cols;
125
0
  for (int sl = 0; sl < svc->number_spatial_layers; ++sl) {
126
0
    for (int tl = 0; tl < svc->number_temporal_layers; ++tl) {
127
0
      layer = LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
128
0
      LAYER_CONTEXT *const lc = &svc->layer_context[layer];
129
0
      svc->layer_context[layer].target_bandwidth = lc->layer_target_bitrate;
130
0
    }
131
0
    spatial_layer_target = svc->layer_context[layer].target_bandwidth;
132
0
    for (int tl = 0; tl < svc->number_temporal_layers; ++tl) {
133
0
      LAYER_CONTEXT *const lc =
134
0
          &svc->layer_context[sl * svc->number_temporal_layers + tl];
135
0
      RATE_CONTROL *const lrc = &lc->rc;
136
0
      PRIMARY_RATE_CONTROL *const lp_rc = &lc->p_rc;
137
0
      lc->spatial_layer_target_bandwidth = spatial_layer_target;
138
0
      if (target_bandwidth != 0) {
139
0
        bitrate_alloc = (float)lc->target_bandwidth / target_bandwidth;
140
0
      }
141
0
      lp_rc->starting_buffer_level =
142
0
          (int64_t)(p_rc->starting_buffer_level * bitrate_alloc);
143
0
      lp_rc->optimal_buffer_level =
144
0
          (int64_t)(p_rc->optimal_buffer_level * bitrate_alloc);
145
0
      lp_rc->maximum_buffer_size =
146
0
          (int64_t)(p_rc->maximum_buffer_size * bitrate_alloc);
147
0
      lp_rc->bits_off_target =
148
0
          AOMMIN(lp_rc->bits_off_target, lp_rc->maximum_buffer_size);
149
0
      lp_rc->buffer_level =
150
0
          AOMMIN(lp_rc->buffer_level, lp_rc->maximum_buffer_size);
151
0
      lc->framerate = cpi->framerate / lc->framerate_factor;
152
0
      lrc->avg_frame_bandwidth = saturate_cast_double_to_int(
153
0
          round(lc->target_bandwidth / lc->framerate));
154
0
      lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
155
0
      lrc->rtc_external_ratectrl = rc->rtc_external_ratectrl;
156
0
      lrc->worst_quality = av1_quantizer_to_qindex(lc->max_q);
157
0
      lrc->best_quality = av1_quantizer_to_qindex(lc->min_q);
158
0
      if (rc->use_external_qp_one_pass) {
159
0
        lrc->worst_quality = rc->worst_quality;
160
0
        lrc->best_quality = rc->best_quality;
161
0
      }
162
      // Reset the cyclic refresh parameters, if needed (map is NULL),
163
      // or number of spatial layers has changed.
164
      // Cyclic refresh is only applied on base temporal layer.
165
0
      if (svc->number_spatial_layers > 1 && tl == 0 &&
166
0
          cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
167
0
          (lc->map == NULL ||
168
0
           svc->prev_number_spatial_layers != svc->number_spatial_layers)) {
169
0
        lc->sb_index = 0;
170
0
        lc->actual_num_seg1_blocks = 0;
171
0
        lc->actual_num_seg2_blocks = 0;
172
0
        lc->counter_encode_maxq_scene_change = 0;
173
0
        aom_free(lc->map);
174
0
        CHECK_MEM_ERROR(cm, lc->map,
175
0
                        aom_calloc(mi_rows * mi_cols, sizeof(*lc->map)));
176
0
      }
177
0
    }
178
0
  }
179
0
}
180
181
/*!\brief Return layer context for current layer.
182
 *
183
 * \ingroup rate_control
184
 * \param[in]       cpi   Top level encoder structure
185
 *
186
 * \return LAYER_CONTEXT for current layer.
187
 */
188
0
static LAYER_CONTEXT *get_layer_context(AV1_COMP *const cpi) {
189
0
  return &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
190
0
                                     cpi->svc.number_temporal_layers +
191
0
                                 cpi->svc.temporal_layer_id];
192
0
}
193
194
0
void av1_update_temporal_layer_framerate(AV1_COMP *const cpi) {
195
0
  SVC *const svc = &cpi->svc;
196
0
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
197
0
  RATE_CONTROL *const lrc = &lc->rc;
198
0
  const int tl = svc->temporal_layer_id;
199
0
  lc->framerate = cpi->framerate / lc->framerate_factor;
200
0
  lrc->avg_frame_bandwidth =
201
0
      saturate_cast_double_to_int(round(lc->target_bandwidth / lc->framerate));
202
0
  lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
203
  // Update the average layer frame size (non-cumulative per-frame-bw).
204
0
  if (tl == 0) {
205
0
    lc->avg_frame_size = lrc->avg_frame_bandwidth;
206
0
  } else {
207
0
    int prev_layer = svc->spatial_layer_id * svc->number_temporal_layers +
208
0
                     svc->temporal_layer_id - 1;
209
0
    LAYER_CONTEXT *const lcprev = &svc->layer_context[prev_layer];
210
0
    const double prev_layer_framerate =
211
0
        cpi->framerate / lcprev->framerate_factor;
212
0
    const int64_t prev_layer_target_bandwidth = lcprev->layer_target_bitrate;
213
0
    if (lc->framerate > prev_layer_framerate) {
214
0
      lc->avg_frame_size = saturate_cast_double_to_int(
215
0
          round((lc->target_bandwidth - prev_layer_target_bandwidth) /
216
0
                (lc->framerate - prev_layer_framerate)));
217
0
    } else {
218
0
      lc->avg_frame_size = saturate_cast_double_to_int(
219
0
          round(lc->target_bandwidth / lc->framerate));
220
0
    }
221
0
  }
222
0
}
223
224
bool av1_check_ref_is_low_spatial_res_super_frame(AV1_COMP *const cpi,
225
0
                                                  int ref_frame) {
226
0
  SVC *svc = &cpi->svc;
227
0
  RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
228
0
  int ref_frame_idx = rtc_ref->ref_idx[ref_frame - 1];
229
0
  return rtc_ref->buffer_time_index[ref_frame_idx] == svc->current_superframe &&
230
0
         rtc_ref->buffer_spatial_layer[ref_frame_idx] <=
231
0
             svc->spatial_layer_id - 1;
232
0
}
233
234
0
void av1_restore_layer_context(AV1_COMP *const cpi) {
235
0
  SVC *const svc = &cpi->svc;
236
0
  RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
237
0
  const AV1_COMMON *const cm = &cpi->common;
238
0
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
239
0
  const int old_frame_since_key = cpi->rc.frames_since_key;
240
0
  const int old_frame_to_key = cpi->rc.frames_to_key;
241
0
  const int frames_since_scene_change = cpi->rc.frames_since_scene_change;
242
0
  const int last_encoded_size_keyframe = cpi->rc.last_encoded_size_keyframe;
243
0
  const int last_target_size_keyframe = cpi->rc.last_target_size_keyframe;
244
0
  const int max_consec_drop = cpi->rc.max_consec_drop;
245
0
  const int postencode_drop = cpi->rc.postencode_drop;
246
0
  const int static_since_last_scene_change =
247
0
      cpi->rc.static_since_last_scene_change;
248
0
  const int percent_blocks_inactive = cpi->rc.percent_blocks_inactive;
249
  // Restore layer rate control.
250
0
  cpi->rc = lc->rc;
251
0
  cpi->ppi->p_rc = lc->p_rc;
252
0
  cpi->oxcf.rc_cfg.target_bandwidth = lc->target_bandwidth;
253
0
  cpi->gf_frame_index = 0;
254
0
  cpi->mv_search_params.max_mv_magnitude = lc->max_mv_magnitude;
255
0
  if (cpi->mv_search_params.max_mv_magnitude == 0)
256
0
    cpi->mv_search_params.max_mv_magnitude = AOMMAX(cm->width, cm->height);
257
  // Reset the following parameters to their values before
258
  // the layer restore. Keep these defined for the stream (not layer).
259
0
  cpi->rc.frames_since_key = old_frame_since_key;
260
0
  cpi->rc.frames_to_key = old_frame_to_key;
261
0
  cpi->rc.frames_since_scene_change = frames_since_scene_change;
262
0
  cpi->rc.last_encoded_size_keyframe = last_encoded_size_keyframe;
263
0
  cpi->rc.last_target_size_keyframe = last_target_size_keyframe;
264
0
  cpi->rc.max_consec_drop = max_consec_drop;
265
0
  cpi->rc.postencode_drop = postencode_drop;
266
0
  cpi->rc.static_since_last_scene_change = static_since_last_scene_change;
267
  // The active map is set for the full resolution frame, so keep it only
268
  // without spatial layers.
269
0
  if (svc->number_spatial_layers == 1)
270
0
    cpi->rc.percent_blocks_inactive = percent_blocks_inactive;
271
  // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
272
  // for the base temporal layer.
273
0
  if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
274
0
      svc->number_spatial_layers > 1 && svc->temporal_layer_id == 0) {
275
0
    CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
276
0
    swap_ptr(&cr->map, &lc->map);
277
0
    cr->sb_index = lc->sb_index;
278
0
    cr->actual_num_seg1_blocks = lc->actual_num_seg1_blocks;
279
0
    cr->actual_num_seg2_blocks = lc->actual_num_seg2_blocks;
280
0
    cr->counter_encode_maxq_scene_change = lc->counter_encode_maxq_scene_change;
281
0
  }
282
0
  svc->skip_mvsearch_last = 0;
283
0
  svc->skip_mvsearch_gf = 0;
284
0
  svc->skip_mvsearch_altref = 0;
285
  // For each reference (LAST/GOLDEN) set the skip_mvsearch_last/gf frame flags.
286
  // This is to skip searching mv for that reference if it was last
287
  // refreshed (i.e., buffer slot holding that reference was refreshed) on the
288
  // previous spatial layer(s) at the same time (current_superframe).
289
0
  if (rtc_ref->set_ref_frame_config && svc->force_zero_mode_spatial_ref &&
290
0
      cpi->sf.rt_sf.use_nonrd_pick_mode) {
291
0
    if (av1_check_ref_is_low_spatial_res_super_frame(cpi, LAST_FRAME)) {
292
0
      svc->skip_mvsearch_last = 1;
293
0
    }
294
0
    if (av1_check_ref_is_low_spatial_res_super_frame(cpi, GOLDEN_FRAME)) {
295
0
      svc->skip_mvsearch_gf = 1;
296
0
    }
297
0
    if (av1_check_ref_is_low_spatial_res_super_frame(cpi, ALTREF_FRAME)) {
298
0
      svc->skip_mvsearch_altref = 1;
299
0
    }
300
0
  }
301
0
}
302
303
0
void av1_svc_update_buffer_slot_refreshed(AV1_COMP *const cpi) {
304
0
  SVC *const svc = &cpi->svc;
305
0
  RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
306
0
  const unsigned int current_frame =
307
0
      cpi->ppi->use_svc ? svc->current_superframe
308
0
                        : cpi->common.current_frame.frame_number;
309
  // For any buffer slot that is refreshed, update it with
310
  // the spatial_layer_id and the current_superframe.
311
0
  if (cpi->common.current_frame.frame_type == KEY_FRAME) {
312
    // All slots are refreshed on KEY.
313
0
    for (unsigned int i = 0; i < REF_FRAMES; i++) {
314
0
      rtc_ref->buffer_time_index[i] = current_frame;
315
0
      rtc_ref->buffer_spatial_layer[i] = svc->spatial_layer_id;
316
0
    }
317
0
  } else if (rtc_ref->set_ref_frame_config) {
318
0
    for (unsigned int i = 0; i < REF_FRAMES; i++) {
319
0
      if (rtc_ref->refresh[i]) {
320
0
        rtc_ref->buffer_time_index[i] = current_frame;
321
0
        rtc_ref->buffer_spatial_layer[i] = svc->spatial_layer_id;
322
0
      }
323
0
    }
324
0
  }
325
0
}
326
327
0
void av1_save_layer_context(AV1_COMP *const cpi) {
328
0
  SVC *const svc = &cpi->svc;
329
0
  const AV1_COMMON *const cm = &cpi->common;
330
0
  LAYER_CONTEXT *lc = get_layer_context(cpi);
331
0
  lc->rc = cpi->rc;
332
0
  lc->p_rc = cpi->ppi->p_rc;
333
0
  lc->target_bandwidth = (int)cpi->oxcf.rc_cfg.target_bandwidth;
334
0
  lc->group_index = cpi->gf_frame_index;
335
0
  lc->max_mv_magnitude = cpi->mv_search_params.max_mv_magnitude;
336
0
  if (svc->spatial_layer_id == 0) svc->base_framerate = cpi->framerate;
337
  // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
338
  // for the base temporal layer.
339
0
  if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
340
0
      cpi->svc.number_spatial_layers > 1 && svc->temporal_layer_id == 0) {
341
0
    CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
342
0
    signed char *temp = lc->map;
343
0
    lc->map = cr->map;
344
0
    cr->map = temp;
345
0
    lc->sb_index = cr->sb_index;
346
0
    lc->actual_num_seg1_blocks = cr->actual_num_seg1_blocks;
347
0
    lc->actual_num_seg2_blocks = cr->actual_num_seg2_blocks;
348
0
    lc->counter_encode_maxq_scene_change = cr->counter_encode_maxq_scene_change;
349
0
  }
350
0
  if (!cpi->is_dropped_frame) {
351
0
    av1_svc_update_buffer_slot_refreshed(cpi);
352
0
    for (unsigned int i = 0; i < REF_FRAMES; i++) {
353
0
      if (frame_is_intra_only(cm) ||
354
0
          cm->current_frame.refresh_frame_flags & (1 << i)) {
355
0
        svc->spatial_layer_fb[i] = svc->spatial_layer_id;
356
0
        svc->temporal_layer_fb[i] = svc->temporal_layer_id;
357
0
      }
358
0
    }
359
0
  }
360
0
  if (svc->spatial_layer_id == svc->number_spatial_layers - 1) {
361
0
    svc->current_superframe++;
362
    // Reset drop flag to false for next superframe.
363
0
    for (int sl = 0; sl < svc->number_spatial_layers; sl++)
364
0
      svc->drop_spatial_layer[sl] = false;
365
0
  }
366
0
}
367
368
0
int av1_svc_primary_ref_frame(const AV1_COMP *const cpi) {
369
0
  const SVC *const svc = &cpi->svc;
370
0
  const AV1_COMMON *const cm = &cpi->common;
371
0
  int fb_idx = -1;
372
0
  int primary_ref_frame = PRIMARY_REF_NONE;
373
0
  if (cpi->svc.number_spatial_layers > 1 ||
374
0
      cpi->svc.number_temporal_layers > 1) {
375
    // Set the primary_ref_frame to LAST_FRAME if that buffer slot for LAST
376
    // was last updated on a lower temporal layer (or base TL0) and for the
377
    // same spatial layer. For RTC patterns this allows for continued decoding
378
    // when set of enhancement layers are dropped (continued decoding starting
379
    // at next base TL0), so error_resilience can be off/0 for all layers.
380
0
    fb_idx = get_ref_frame_map_idx(cm, LAST_FRAME);
381
0
    if (cpi->ppi->rtc_ref.reference[0] == 1 &&
382
0
        svc->spatial_layer_fb[fb_idx] == svc->spatial_layer_id &&
383
0
        (svc->temporal_layer_fb[fb_idx] < svc->temporal_layer_id ||
384
0
         svc->temporal_layer_fb[fb_idx] == 0)) {
385
0
      primary_ref_frame = 0;  // LAST_FRAME: ref_frame - LAST_FRAME
386
0
    }
387
0
  } else if (cpi->ppi->rtc_ref.set_ref_frame_config) {
388
0
    const ExternalFlags *const ext_flags = &cpi->ext_flags;
389
0
    int flags = ext_flags->ref_frame_flags;
390
0
    if (flags & AOM_LAST_FLAG) {
391
0
      primary_ref_frame = 0;  // LAST_FRAME: ref_frame - LAST_FRAME
392
0
    } else if (flags & AOM_GOLD_FLAG) {
393
0
      primary_ref_frame = GOLDEN_FRAME - LAST_FRAME;
394
0
    } else if (flags & AOM_ALT_FLAG) {
395
0
      primary_ref_frame = ALTREF_FRAME - LAST_FRAME;
396
0
    }
397
0
  }
398
0
  return primary_ref_frame;
399
0
}
400
401
0
void av1_free_svc_cyclic_refresh(AV1_COMP *const cpi) {
402
0
  SVC *const svc = &cpi->svc;
403
0
  if (svc->layer_context == NULL) return;
404
0
  for (int i = 0; i < svc->num_allocated_layers; ++i) {
405
0
    LAYER_CONTEXT *const lc = &svc->layer_context[i];
406
0
    if (lc->map) {
407
0
      aom_free(lc->map);
408
0
      lc->map = NULL;
409
0
    }
410
0
  }
411
0
}
412
413
0
void av1_svc_reset_temporal_layers(AV1_COMP *const cpi, int is_key) {
414
0
  SVC *const svc = &cpi->svc;
415
0
  LAYER_CONTEXT *lc = NULL;
416
0
  for (int sl = 0; sl < svc->number_spatial_layers; ++sl) {
417
0
    for (int tl = 0; tl < svc->number_temporal_layers; ++tl) {
418
0
      lc = &cpi->svc.layer_context[sl * svc->number_temporal_layers + tl];
419
0
      if (is_key) lc->frames_from_key_frame = 0;
420
0
    }
421
0
  }
422
0
  av1_update_temporal_layer_framerate(cpi);
423
0
  av1_restore_layer_context(cpi);
424
0
}
425
426
void av1_get_layer_resolution(const int width_org, const int height_org,
427
                              const int num, const int den, int *width_out,
428
0
                              int *height_out) {
429
0
  int w, h;
430
0
  if (width_out == NULL || height_out == NULL || den == 0) return;
431
0
  if (den == 1 && num == 1) {
432
0
    *width_out = width_org;
433
0
    *height_out = height_org;
434
0
    return;
435
0
  }
436
0
  w = width_org * num / den;
437
0
  h = height_org * num / den;
438
  // Make height and width even.
439
0
  w += w % 2;
440
0
  h += h % 2;
441
0
  *width_out = w;
442
0
  *height_out = h;
443
0
}
444
445
0
void av1_one_pass_cbr_svc_start_layer(AV1_COMP *const cpi) {
446
0
  SVC *const svc = &cpi->svc;
447
0
  AV1_COMMON *const cm = &cpi->common;
448
0
  LAYER_CONTEXT *lc = NULL;
449
0
  int width = 0, height = 0;
450
0
  lc = &svc->layer_context[svc->spatial_layer_id * svc->number_temporal_layers +
451
0
                           svc->temporal_layer_id];
452
  // Set the lower quality layer flag.
453
0
  svc->has_lower_quality_layer = 0;
454
0
  if (cpi->svc.spatial_layer_id > 0) {
455
0
    const LAYER_CONTEXT *lc_prev =
456
0
        &svc->layer_context[(svc->spatial_layer_id - 1) *
457
0
                                svc->number_temporal_layers +
458
0
                            svc->temporal_layer_id];
459
0
    if (lc_prev->scaling_factor_den == 1 && lc_prev->scaling_factor_num == 1)
460
0
      svc->has_lower_quality_layer = 1;
461
0
  }
462
0
  av1_get_layer_resolution(cpi->oxcf.frm_dim_cfg.width,
463
0
                           cpi->oxcf.frm_dim_cfg.height, lc->scaling_factor_num,
464
0
                           lc->scaling_factor_den, &width, &height);
465
  // Use Eightap_smooth for low resolutions.
466
0
  if (width * height <= 320 * 240)
467
0
    svc->downsample_filter_type[svc->spatial_layer_id] = EIGHTTAP_SMOOTH;
468
469
0
  cm->width = width;
470
0
  cm->height = height;
471
0
  alloc_mb_mode_info_buffers(cpi);
472
0
  av1_update_frame_size(cpi);
473
0
}
474
475
enum {
476
  SVC_LAST_FRAME = 0,
477
  SVC_LAST2_FRAME,
478
  SVC_LAST3_FRAME,
479
  SVC_GOLDEN_FRAME,
480
  SVC_BWDREF_FRAME,
481
  SVC_ALTREF2_FRAME,
482
  SVC_ALTREF_FRAME
483
};
484
485
// For fixed svc mode: fixed pattern is set based on the number of
486
// spatial and temporal layers, and the ksvc_fixed_mode.
487
0
void av1_set_svc_fixed_mode(AV1_COMP *const cpi) {
488
0
  SVC *const svc = &cpi->svc;
489
0
  RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
490
0
  int i;
491
0
  assert(svc->use_flexible_mode == 0);
492
0
  assert(svc->number_spatial_layers >= 1 && svc->number_temporal_layers >= 1);
493
  // Fixed SVC mode only supports at most 3 spatial or temporal layers.
494
0
  if (svc->number_spatial_layers > 3 || svc->number_temporal_layers > 3) {
495
0
    aom_internal_error(&cpi->ppi->error, AOM_CODEC_INVALID_PARAM,
496
0
                       "Invalid number of spatial/temporal layers for fixed "
497
0
                       "SVC mode (max: 3)");
498
0
  }
499
0
  rtc_ref->set_ref_frame_config = 1;
500
0
  int superframe_cnt = svc->current_superframe;
501
  // Set the reference map buffer idx for the 7 references:
502
  // LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3),
503
  // BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
504
0
  for (i = 0; i < INTER_REFS_PER_FRAME; i++) {
505
0
    rtc_ref->reference[i] = 0;
506
0
    rtc_ref->ref_idx[i] = i;
507
0
  }
508
0
  for (i = 0; i < REF_FRAMES; i++) rtc_ref->refresh[i] = 0;
509
  // Always reference LAST, and reference GOLDEN on SL > 0.
510
  // For KSVC: GOLDEN reference will be removed on INTER_FRAMES later
511
  // when frame_type is set.
512
0
  rtc_ref->reference[SVC_LAST_FRAME] = 1;
513
0
  if (svc->spatial_layer_id > 0) rtc_ref->reference[SVC_GOLDEN_FRAME] = 1;
514
0
  if (svc->temporal_layer_id == 0) {
515
    // Base temporal layer.
516
0
    if (svc->spatial_layer_id == 0) {
517
      // Set all buffer_idx to 0. Update slot 0 (LAST).
518
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
519
0
      rtc_ref->refresh[0] = 1;
520
0
    } else if (svc->spatial_layer_id == 1) {
521
      // Set buffer_idx for LAST to slot 1, GOLDEN (and all other refs) to
522
      // slot 0. Update slot 1 (LAST).
523
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
524
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 1;
525
0
      rtc_ref->refresh[1] = 1;
526
0
    } else if (svc->spatial_layer_id == 2) {
527
      // Set buffer_idx for LAST to slot 2, GOLDEN (and all other refs) to
528
      // slot 1. Update slot 2 (LAST).
529
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 1;
530
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 2;
531
0
      rtc_ref->refresh[2] = 1;
532
0
    }
533
0
  } else if (svc->temporal_layer_id == 2 && (superframe_cnt - 1) % 4 == 0) {
534
    // First top temporal enhancement layer.
535
0
    if (svc->spatial_layer_id == 0) {
536
      // Reference LAST (slot 0).
537
      // Set GOLDEN to slot 3 and update slot 3.
538
      // Set all other buffer_idx to slot 0.
539
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
540
0
      if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
541
0
        rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 3;
542
0
        rtc_ref->refresh[3] = 1;
543
0
      }
544
0
    } else if (svc->spatial_layer_id == 1) {
545
      // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
546
      // GOLDEN (and all other refs) to slot 3.
547
      // Set LAST2 to slot 4 and Update slot 4.
548
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 3;
549
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 1;
550
0
      if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
551
0
        rtc_ref->ref_idx[SVC_LAST2_FRAME] = 4;
552
0
        rtc_ref->refresh[4] = 1;
553
0
      }
554
0
    } else if (svc->spatial_layer_id == 2) {
555
      // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2,
556
      // GOLDEN (and all other refs) to slot 4.
557
      // No update.
558
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 4;
559
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 2;
560
0
    }
561
0
  } else if (svc->temporal_layer_id == 1) {
562
    // Middle temporal enhancement layer.
563
0
    if (svc->spatial_layer_id == 0) {
564
      // Reference LAST.
565
      // Set all buffer_idx to 0.
566
      // Set GOLDEN to slot 5 and update slot 5.
567
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
568
0
      if (svc->temporal_layer_id < svc->number_temporal_layers - 1 ||
569
0
          svc->spatial_layer_id < svc->number_spatial_layers - 1) {
570
0
        rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 5;
571
0
        rtc_ref->refresh[5] = 1;
572
0
      }
573
0
    } else if (svc->spatial_layer_id == 1) {
574
      // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
575
      // GOLDEN (and all other refs) to slot 5.
576
      // Set LAST3 to slot 6 and update slot 6.
577
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 5;
578
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 1;
579
0
      if (svc->temporal_layer_id < svc->number_temporal_layers - 1 ||
580
0
          svc->spatial_layer_id < svc->number_spatial_layers - 1) {
581
0
        rtc_ref->ref_idx[SVC_LAST3_FRAME] = 6;
582
0
        rtc_ref->refresh[6] = 1;
583
0
      }
584
0
    } else if (svc->spatial_layer_id == 2) {
585
      // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2,
586
      // GOLDEN (and all other refs) to slot 6.
587
      // Set LAST3 to slot 7 and update slot 7.
588
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 6;
589
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 2;
590
0
      if (svc->temporal_layer_id < svc->number_temporal_layers - 1) {
591
0
        rtc_ref->ref_idx[SVC_LAST3_FRAME] = 7;
592
0
        rtc_ref->refresh[7] = 1;
593
0
      }
594
0
    }
595
0
  } else if (svc->temporal_layer_id == 2 && (superframe_cnt - 3) % 4 == 0) {
596
    // Second top temporal enhancement layer.
597
0
    if (svc->spatial_layer_id == 0) {
598
      // Set LAST to slot 5 and reference LAST.
599
      // Set GOLDEN to slot 3 and update slot 3.
600
      // Set all other buffer_idx to 0.
601
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
602
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 5;
603
0
      if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
604
0
        rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 3;
605
0
        rtc_ref->refresh[3] = 1;
606
0
      }
607
0
    } else if (svc->spatial_layer_id == 1) {
608
      // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 6,
609
      // GOLDEN to slot 3. Set LAST2 to slot 4 and update slot 4.
610
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
611
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 6;
612
0
      rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 3;
613
0
      if (svc->spatial_layer_id < svc->number_spatial_layers - 1) {
614
0
        rtc_ref->ref_idx[SVC_LAST2_FRAME] = 4;
615
0
        rtc_ref->refresh[4] = 1;
616
0
      }
617
0
    } else if (svc->spatial_layer_id == 2) {
618
      // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 7,
619
      // GOLDEN to slot 4. No update.
620
0
      for (i = 0; i < INTER_REFS_PER_FRAME; i++) rtc_ref->ref_idx[i] = 0;
621
0
      rtc_ref->ref_idx[SVC_LAST_FRAME] = 7;
622
0
      rtc_ref->ref_idx[SVC_GOLDEN_FRAME] = 4;
623
0
    }
624
0
  }
625
0
}
626
627
0
void av1_svc_check_reset_layer_rc_flag(AV1_COMP *const cpi) {
628
0
  SVC *const svc = &cpi->svc;
629
0
  for (int sl = 0; sl < svc->number_spatial_layers; ++sl) {
630
    // Check for reset based on avg_frame_bandwidth for spatial layer sl.
631
    // If avg_frame_bandwidth for top temporal layer is not set
632
    // (because enhancement layer was inactive), use the base TL0
633
0
    int layer = LAYER_IDS_TO_IDX(sl, svc->number_temporal_layers - 1,
634
0
                                 svc->number_temporal_layers);
635
0
    LAYER_CONTEXT *lc = &svc->layer_context[layer];
636
0
    RATE_CONTROL *lrc = &lc->rc;
637
0
    int avg_frame_bandwidth = lrc->avg_frame_bandwidth;
638
0
    int prev_avg_frame_bandwidth = lrc->prev_avg_frame_bandwidth;
639
0
    if (avg_frame_bandwidth == 0 || prev_avg_frame_bandwidth == 0) {
640
      // Use base TL0.
641
0
      layer = LAYER_IDS_TO_IDX(sl, 0, svc->number_temporal_layers);
642
0
      lc = &svc->layer_context[layer];
643
0
      lrc = &lc->rc;
644
0
      avg_frame_bandwidth = lrc->avg_frame_bandwidth;
645
0
      prev_avg_frame_bandwidth = lrc->prev_avg_frame_bandwidth;
646
0
    }
647
0
    if (avg_frame_bandwidth / 3 > (prev_avg_frame_bandwidth >> 1) ||
648
0
        avg_frame_bandwidth < (prev_avg_frame_bandwidth >> 1)) {
649
      // Reset for all temporal layers with spatial layer sl.
650
0
      for (int tl = 0; tl < svc->number_temporal_layers; ++tl) {
651
0
        int layer2 = LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
652
0
        LAYER_CONTEXT *lc2 = &svc->layer_context[layer2];
653
0
        RATE_CONTROL *lrc2 = &lc2->rc;
654
0
        PRIMARY_RATE_CONTROL *lp_rc2 = &lc2->p_rc;
655
0
        PRIMARY_RATE_CONTROL *const lp_rc = &lc2->p_rc;
656
0
        lrc2->rc_1_frame = 0;
657
0
        lrc2->rc_2_frame = 0;
658
0
        lp_rc2->bits_off_target = lp_rc->optimal_buffer_level;
659
0
        lp_rc2->buffer_level = lp_rc->optimal_buffer_level;
660
0
      }
661
0
    }
662
0
  }
663
0
}
664
665
void av1_svc_set_last_source(AV1_COMP *const cpi, EncodeFrameInput *frame_input,
666
0
                             YV12_BUFFER_CONFIG *prev_source) {
667
0
  frame_input->last_source = prev_source != NULL ? prev_source : NULL;
668
0
  if (cpi->svc.source_last_TL0.buffer_alloc_sz == 0) return;
669
0
  if (!cpi->ppi->use_svc && cpi->rc.prev_frame_is_dropped &&
670
0
      cpi->rc.frame_number_encoded > 0) {
671
0
    frame_input->last_source = &cpi->svc.source_last_TL0;
672
0
  } else {
673
0
    RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
674
0
    if (cpi->svc.spatial_layer_id == 0) {
675
      // For base spatial layer: if the LAST reference (index 0) is not
676
      // the previous (super)frame set the last_source to the source
677
      // corresponding to the last TL0, otherwise keep it at prev_source.
678
      // Always use source_last_TL0 if previous base TL0 was dropped.
679
0
      if (cpi->svc.current_superframe > 0) {
680
0
        const int buffslot_last = rtc_ref->ref_idx[0];
681
        // Check if previous frame was dropped on base TL0 layer.
682
0
        const int layer =
683
0
            LAYER_IDS_TO_IDX(0, 0, cpi->svc.number_temporal_layers);
684
0
        LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
685
0
        RATE_CONTROL *lrc = &lc->rc;
686
0
        if (lrc->prev_frame_is_dropped ||
687
0
            rtc_ref->buffer_time_index[buffslot_last] <
688
0
                cpi->svc.current_superframe - 1) {
689
0
          frame_input->last_source = &cpi->svc.source_last_TL0;
690
0
        }
691
0
      }
692
0
    } else if (cpi->svc.spatial_layer_id > 0) {
693
      // For spatial enhancement layers: the previous source (prev_source)
694
      // corresponds to the lower spatial layer (which is the same source so
695
      // we can't use that), so always set the last_source to the source of the
696
      // last TL0.
697
0
      if (cpi->svc.current_superframe > 0)
698
0
        frame_input->last_source = &cpi->svc.source_last_TL0;
699
0
      else
700
0
        frame_input->last_source = NULL;
701
0
    }
702
0
  }
703
0
}
704
705
0
int av1_svc_get_min_ref_dist(const AV1_COMP *cpi) {
706
0
  RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
707
0
  int min_dist = INT_MAX;
708
0
  const unsigned int current_frame_num =
709
0
      cpi->ppi->use_svc ? cpi->svc.current_superframe
710
0
                        : cpi->common.current_frame.frame_number;
711
0
  for (unsigned int i = 0; i < INTER_REFS_PER_FRAME; i++) {
712
0
    if (rtc_ref->reference[i]) {
713
0
      const int ref_frame_map_idx = rtc_ref->ref_idx[i];
714
0
      const int dist = (1 + current_frame_num) -
715
0
                       rtc_ref->buffer_time_index[ref_frame_map_idx];
716
0
      if (dist < min_dist) min_dist = dist;
717
0
    }
718
0
  }
719
0
  return min_dist;
720
0
}
721
722
0
void av1_svc_set_reference_was_previous(AV1_COMP *cpi) {
723
0
  RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
724
  // Check if the encoded frame had some reference that was the
725
  // previous frame.
726
0
  const unsigned int current_frame =
727
0
      cpi->ppi->use_svc ? cpi->svc.current_superframe
728
0
                        : cpi->common.current_frame.frame_number;
729
0
  rtc_ref->reference_was_previous_frame = true;
730
0
  if (current_frame > 0) {
731
0
    rtc_ref->reference_was_previous_frame = false;
732
0
    for (unsigned int i = 0; i < INTER_REFS_PER_FRAME; i++) {
733
0
      if (rtc_ref->reference[i]) {
734
0
        const int ref_frame_map_idx = rtc_ref->ref_idx[i];
735
0
        if (rtc_ref->buffer_time_index[ref_frame_map_idx] == current_frame - 1)
736
0
          rtc_ref->reference_was_previous_frame = true;
737
0
      }
738
0
    }
739
0
  }
740
0
}