vp9_svc_layercontext.c 24 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*
 *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <math.h>

Dmitry Kovalev's avatar
Dmitry Kovalev committed
13
#include "vp9/encoder/vp9_encoder.h"
14
#include "vp9/encoder/vp9_svc_layercontext.h"
15
#include "vp9/encoder/vp9_extend.h"
16

17
#define SMALL_FRAME_FB_IDX 7
18
19
#define SMALL_FRAME_WIDTH  16
#define SMALL_FRAME_HEIGHT 16
20

21
void vp9_init_layer_context(VP9_COMP *const cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
22
  SVC *const svc = &cpi->svc;
23
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
24
  int sl, tl;
25
  int alt_ref_idx = svc->number_spatial_layers;
26

Dmitry Kovalev's avatar
Dmitry Kovalev committed
27
28
  svc->spatial_layer_id = 0;
  svc->temporal_layer_id = 0;
29

30
31
32
33
34
  if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
    if (vp9_realloc_frame_buffer(&cpi->svc.empty_frame.img,
                                 SMALL_FRAME_WIDTH, SMALL_FRAME_HEIGHT,
                                 cpi->common.subsampling_x,
                                 cpi->common.subsampling_y,
35
36
37
#if CONFIG_VP9_HIGHBITDEPTH
                                 cpi->common.use_highbitdepth,
#endif
38
39
40
                                 VP9_ENC_BORDER_IN_PIXELS,
                                 cpi->common.byte_alignment,
                                 NULL, NULL, NULL))
41
42
43
      vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                         "Failed to allocate empty frame for multiple frame "
                         "contexts");
44

45
46
    memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80,
           cpi->svc.empty_frame.img.buffer_alloc_sz);
47
48
  }

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
    for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
      int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
      LAYER_CONTEXT *const lc = &svc->layer_context[layer];
      RATE_CONTROL *const lrc = &lc->rc;
      int i;
      lc->current_video_frame_in_layer = 0;
      lc->layer_size = 0;
      lc->frames_from_key_frame = 0;
      lc->last_frame_type = FRAME_TYPES;
      lrc->ni_av_qi = oxcf->worst_allowed_q;
      lrc->total_actual_bits = 0;
      lrc->total_target_vs_actual = 0;
      lrc->ni_tot_qi = 0;
      lrc->tot_q = 0.0;
      lrc->avg_q = 0.0;
      lrc->ni_frames = 0;
      lrc->decimation_count = 0;
      lrc->decimation_factor = 0;

      for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
        lrc->rate_correction_factors[i] = 1.0;
      }
72

73
74
75
76
77
78
79
80
81
82
      if (cpi->oxcf.rc_mode == VPX_CBR) {
        lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
        lrc->last_q[INTER_FRAME] = oxcf->worst_allowed_q;
        lrc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q;
        lrc->avg_frame_qindex[KEY_FRAME] = oxcf->worst_allowed_q;
      } else {
        lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
        lrc->last_q[KEY_FRAME] = oxcf->best_allowed_q;
        lrc->last_q[INTER_FRAME] = oxcf->best_allowed_q;
        lrc->avg_frame_qindex[KEY_FRAME] = (oxcf->worst_allowed_q +
83
                                            oxcf->best_allowed_q) / 2;
84
85
86
87
88
89
90
91
        lrc->avg_frame_qindex[INTER_FRAME] = (oxcf->worst_allowed_q +
                                              oxcf->best_allowed_q) / 2;
        if (oxcf->ss_enable_auto_arf[sl])
          lc->alt_ref_idx = alt_ref_idx++;
        else
          lc->alt_ref_idx = INVALID_IDX;
        lc->gold_ref_idx = INVALID_IDX;
      }
92

93
94
95
96
      lrc->buffer_level = oxcf->starting_buffer_level_ms *
                              lc->target_bandwidth / 1000;
      lrc->bits_off_target = lrc->buffer_level;
    }
97
  }
98
99

  // Still have extra buffer for base layer golden frame
100
101
  if (!(svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR)
      && alt_ref_idx < REF_FRAMES)
102
    svc->layer_context[0].gold_ref_idx = alt_ref_idx;
103
104
105
106
107
}

// Update the layer context from a change_config() call.
void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
                                            const int target_bandwidth) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
108
  SVC *const svc = &cpi->svc;
109
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
110
  const RATE_CONTROL *const rc = &cpi->rc;
111
  int sl, tl, layer = 0, spatial_layer_target;
112
  float bitrate_alloc = 1.0;
113

114
115
116
  if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
    for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
      spatial_layer_target = 0;
117

118
119
120
121
122
      for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
        layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
        svc->layer_context[layer].target_bandwidth =
            oxcf->layer_target_bitrate[layer];
      }
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
      layer = LAYER_IDS_TO_IDX(sl, ((oxcf->ts_number_layers - 1) < 0 ?
          0 : (oxcf->ts_number_layers - 1)), oxcf->ts_number_layers);
      spatial_layer_target =
          svc->layer_context[layer].target_bandwidth =
              oxcf->layer_target_bitrate[layer];

      for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
        LAYER_CONTEXT *const lc =
            &svc->layer_context[sl * oxcf->ts_number_layers + tl];
        RATE_CONTROL *const lrc = &lc->rc;

        lc->spatial_layer_target_bandwidth = spatial_layer_target;
        bitrate_alloc = (float)lc->target_bandwidth / spatial_layer_target;
        lrc->starting_buffer_level =
            (int64_t)(rc->starting_buffer_level * bitrate_alloc);
        lrc->optimal_buffer_level =
            (int64_t)(rc->optimal_buffer_level * bitrate_alloc);
        lrc->maximum_buffer_size =
            (int64_t)(rc->maximum_buffer_size * bitrate_alloc);
        lrc->bits_off_target =
            MIN(lrc->bits_off_target, lrc->maximum_buffer_size);
        lrc->buffer_level = MIN(lrc->buffer_level, lrc->maximum_buffer_size);
Marco's avatar
Marco committed
146
        lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
147
148
149
150
151
        lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
        lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
        lrc->worst_quality = rc->worst_quality;
        lrc->best_quality = rc->best_quality;
      }
152
    }
153
154
155
  } else {
    int layer_end;

156
    if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
157
      layer_end = svc->number_temporal_layers;
158
    } else {
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
      layer_end = svc->number_spatial_layers;
    }

    for (layer = 0; layer < layer_end; ++layer) {
      LAYER_CONTEXT *const lc = &svc->layer_context[layer];
      RATE_CONTROL *const lrc = &lc->rc;

      lc->target_bandwidth = oxcf->layer_target_bitrate[layer];

      bitrate_alloc = (float)lc->target_bandwidth / target_bandwidth;
      // Update buffer-related quantities.
      lrc->starting_buffer_level =
          (int64_t)(rc->starting_buffer_level * bitrate_alloc);
      lrc->optimal_buffer_level =
          (int64_t)(rc->optimal_buffer_level * bitrate_alloc);
      lrc->maximum_buffer_size =
          (int64_t)(rc->maximum_buffer_size * bitrate_alloc);
      lrc->bits_off_target = MIN(lrc->bits_off_target,
                                 lrc->maximum_buffer_size);
      lrc->buffer_level = MIN(lrc->buffer_level, lrc->maximum_buffer_size);
      // Update framerate-related quantities.
      if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
        lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[layer];
      } else {
        lc->framerate = cpi->framerate;
      }
      lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
      lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
      // Update qp-related quantities.
      lrc->worst_quality = rc->worst_quality;
      lrc->best_quality = rc->best_quality;
190
    }
191
192
193
  }
}

194
static LAYER_CONTEXT *get_layer_context(VP9_COMP *const cpi) {
195
196
197
198
199
200
201
202
  if (is_one_pass_cbr_svc(cpi))
    return &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
        cpi->svc.number_temporal_layers + cpi->svc.temporal_layer_id];
  else
    return (cpi->svc.number_temporal_layers > 1 &&
            cpi->oxcf.rc_mode == VPX_CBR) ?
             &cpi->svc.layer_context[cpi->svc.temporal_layer_id] :
             &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
203
204
}

205
void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
206
  SVC *const svc = &cpi->svc;
207
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
208
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
209
  RATE_CONTROL *const lrc = &lc->rc;
210
211
212
213
  // Index into spatial+temporal arrays.
  const int st_idx = svc->spatial_layer_id * svc->number_temporal_layers +
      svc->temporal_layer_id;
  const int tl = svc->temporal_layer_id;
214

215
  lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
216
  lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
217
218
  lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
  // Update the average layer frame size (non-cumulative per-frame-bw).
219
  if (tl == 0) {
220
    lc->avg_frame_size = lrc->avg_frame_bandwidth;
221
  } else {
222
    const double prev_layer_framerate =
223
224
225
        cpi->framerate / oxcf->ts_rate_decimator[tl - 1];
    const int prev_layer_target_bandwidth =
        oxcf->layer_target_bitrate[st_idx - 1];
226
227
228
229
230
231
    lc->avg_frame_size =
        (int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
              (lc->framerate - prev_layer_framerate));
  }
}

232
void vp9_update_spatial_layer_framerate(VP9_COMP *const cpi, double framerate) {
233
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
234
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
235
236
237
  RATE_CONTROL *const lrc = &lc->rc;

  lc->framerate = framerate;
238
239
  lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
  lrc->min_frame_bandwidth = (int)(lrc->avg_frame_bandwidth *
240
                                   oxcf->two_pass_vbrmin_section / 100);
241
  lrc->max_frame_bandwidth = (int)(((int64_t)lrc->avg_frame_bandwidth *
242
                                   oxcf->two_pass_vbrmax_section) / 100);
paulwilkins's avatar
paulwilkins committed
243
  vp9_rc_set_gf_interval_range(cpi, lrc);
244
245
}

246
void vp9_restore_layer_context(VP9_COMP *const cpi) {
247
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
248
249
250
  const int old_frame_since_key = cpi->rc.frames_since_key;
  const int old_frame_to_key = cpi->rc.frames_to_key;

251
  cpi->rc = lc->rc;
252
  cpi->twopass = lc->twopass;
253
  cpi->oxcf.target_bandwidth = lc->target_bandwidth;
254
  cpi->alt_ref_source = lc->alt_ref_source;
255
256
  // Reset the frames_since_key and frames_to_key counters to their values
  // before the layer restore. Keep these defined for the stream (not layer).
257
258
259
260
  if (cpi->svc.number_temporal_layers > 1) {
    cpi->rc.frames_since_key = old_frame_since_key;
    cpi->rc.frames_to_key = old_frame_to_key;
  }
261
262
263
}

void vp9_save_layer_context(VP9_COMP *const cpi) {
264
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
265
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
266

267
  lc->rc = cpi->rc;
268
  lc->twopass = cpi->twopass;
269
  lc->target_bandwidth = (int)oxcf->target_bandwidth;
270
  lc->alt_ref_source = cpi->alt_ref_source;
271
}
272
273

void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
274
  SVC *const svc = &cpi->svc;
275
276
  int i;

Dmitry Kovalev's avatar
Dmitry Kovalev committed
277
  for (i = 0; i < svc->number_spatial_layers; ++i) {
Paul Wilkins's avatar
Paul Wilkins committed
278
    TWO_PASS *const twopass = &svc->layer_context[i].twopass;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
279
280

    svc->spatial_layer_id = i;
281
282
283
284
285
    vp9_init_second_pass(cpi);

    twopass->total_stats.spatial_layer_id = i;
    twopass->total_left_stats.spatial_layer_id = i;
  }
Dmitry Kovalev's avatar
Dmitry Kovalev committed
286
  svc->spatial_layer_id = 0;
287
}
288

289
290
void vp9_inc_frame_in_layer(VP9_COMP *const cpi) {
  LAYER_CONTEXT *const lc =
291
292
      &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
                              cpi->svc.number_temporal_layers];
293
  ++lc->current_video_frame_in_layer;
294
  ++lc->frames_from_key_frame;
295
}
296

297
int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) {
298
  return is_two_pass_svc(cpi) &&
299
         cpi->svc.spatial_layer_id > 0 &&
300
301
302
         cpi->svc.layer_context[cpi->svc.spatial_layer_id *
                                cpi->svc.number_temporal_layers +
                                cpi->svc.temporal_layer_id].is_key_frame;
303
}
304

305
306
307
308
static void get_layer_resolution(const int width_org, const int height_org,
                                 const int num, const int den,
                                 int *width_out, int *height_out) {
  int w, h;
309

310
311
  if (width_out == NULL || height_out == NULL || den == 0)
    return;
312

313
314
  w = width_org * num / den;
  h = height_org * num / den;
315

316
317
318
  // make height and width even to make chrome player happy
  w += w % 2;
  h += h % 2;
319

320
321
  *width_out = w;
  *height_out = h;
322
323
}

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
// The function sets proper ref_frame_flags, buffer indices, and buffer update
// variables for temporal layering mode 3 - that does 0-2-1-2 temporal layering
// scheme.
static void set_flags_and_fb_idx_for_temporal_mode3(VP9_COMP *const cpi) {
  int frame_num_within_temporal_struct = 0;
  int spatial_id, temporal_id;
  spatial_id = cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
  frame_num_within_temporal_struct =
      cpi->svc.layer_context[cpi->svc.spatial_layer_id *
      cpi->svc.number_temporal_layers].current_video_frame_in_layer % 4;
  temporal_id = cpi->svc.temporal_layer_id =
      (frame_num_within_temporal_struct & 1) ? 2 :
      (frame_num_within_temporal_struct >> 1);
  cpi->ext_refresh_last_frame = cpi->ext_refresh_golden_frame =
      cpi->ext_refresh_alt_ref_frame = 0;
  if (!temporal_id) {
    cpi->ext_refresh_frame_flags_pending = 1;
    cpi->ext_refresh_last_frame = 1;
    if (!spatial_id) {
      cpi->ref_frame_flags = VP9_LAST_FLAG;
    } else if (cpi->svc.layer_context[temporal_id].is_key_frame) {
      // base layer is a key frame.
      cpi->ref_frame_flags = VP9_GOLD_FLAG;
    } else {
      cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
    }
  } else if (temporal_id == 1) {
    cpi->ext_refresh_frame_flags_pending = 1;
    cpi->ext_refresh_alt_ref_frame = 1;
    if (!spatial_id) {
      cpi->ref_frame_flags = VP9_LAST_FLAG;
    } else {
      cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
    }
  } else {
    if (frame_num_within_temporal_struct == 1) {
      // the first tl2 picture
      if (!spatial_id) {
        cpi->ext_refresh_frame_flags_pending = 1;
        cpi->ext_refresh_alt_ref_frame = 1;
        cpi->ref_frame_flags = VP9_LAST_FLAG;
      } else if (spatial_id < cpi->svc.number_spatial_layers - 1) {
        cpi->ext_refresh_frame_flags_pending = 1;
        cpi->ext_refresh_alt_ref_frame = 1;
        cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
      } else {  // Top layer
        cpi->ext_refresh_frame_flags_pending = 0;
        cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
      }
    } else {
      //  The second tl2 picture
      if (!spatial_id) {
        cpi->ext_refresh_frame_flags_pending = 1;
        cpi->ref_frame_flags = VP9_LAST_FLAG;
        cpi->ext_refresh_last_frame = 1;
      } else if (spatial_id < cpi->svc.number_spatial_layers - 1) {
        cpi->ext_refresh_frame_flags_pending = 1;
        cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
        cpi->ext_refresh_last_frame = 1;
      } else {  // top layer
        cpi->ext_refresh_frame_flags_pending = 0;
        cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
      }
    }
  }
  if (temporal_id == 0) {
    cpi->lst_fb_idx = spatial_id;
    if (spatial_id)
      cpi->gld_fb_idx = spatial_id - 1;
    else
      cpi->gld_fb_idx = 0;
    cpi->alt_fb_idx = 0;
  } else if (temporal_id == 1) {
    cpi->lst_fb_idx = spatial_id;
    cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
    cpi->alt_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
  } else if (frame_num_within_temporal_struct == 1) {
    cpi->lst_fb_idx = spatial_id;
    cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
    cpi->alt_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
  } else {
    cpi->lst_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
    cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
    cpi->alt_fb_idx = 0;
  }
}

// The function sets proper ref_frame_flags, buffer indices, and buffer update
// variables for temporal layering mode 2 - that does 0-1-0-1 temporal layering
// scheme.
static void set_flags_and_fb_idx_for_temporal_mode2(VP9_COMP *const cpi) {
  int spatial_id, temporal_id;
  spatial_id = cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
  temporal_id = cpi->svc.temporal_layer_id =
      cpi->svc.layer_context[cpi->svc.spatial_layer_id *
      cpi->svc.number_temporal_layers].current_video_frame_in_layer & 1;
  cpi->ext_refresh_last_frame = cpi->ext_refresh_golden_frame =
                                cpi->ext_refresh_alt_ref_frame = 0;
  if (!temporal_id) {
    cpi->ext_refresh_frame_flags_pending = 1;
    cpi->ext_refresh_last_frame = 1;
    if (!spatial_id) {
      cpi->ref_frame_flags = VP9_LAST_FLAG;
    } else if (cpi->svc.layer_context[temporal_id].is_key_frame) {
      // base layer is a key frame.
      cpi->ref_frame_flags = VP9_GOLD_FLAG;
    } else {
      cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
    }
  } else if (temporal_id == 1) {
    cpi->ext_refresh_frame_flags_pending = 1;
    cpi->ext_refresh_alt_ref_frame = 1;
    if (!spatial_id) {
      cpi->ref_frame_flags = VP9_LAST_FLAG;
    } else {
      cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
    }
  }

  if (temporal_id == 0) {
    cpi->lst_fb_idx = spatial_id;
    if (spatial_id)
      cpi->gld_fb_idx = spatial_id - 1;
    else
      cpi->gld_fb_idx = 0;
    cpi->alt_fb_idx = 0;
  } else if (temporal_id == 1) {
    cpi->lst_fb_idx = spatial_id;
    cpi->gld_fb_idx = cpi->svc.number_spatial_layers + spatial_id - 1;
    cpi->alt_fb_idx = cpi->svc.number_spatial_layers + spatial_id;
  }
}

// The function sets proper ref_frame_flags, buffer indices, and buffer update
// variables for temporal layering mode 0 - that has no temporal layering.
static void set_flags_and_fb_idx_for_temporal_mode_noLayering(
    VP9_COMP *const cpi) {
  int spatial_id;
  spatial_id = cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
  cpi->ext_refresh_last_frame =
      cpi->ext_refresh_golden_frame = cpi->ext_refresh_alt_ref_frame = 0;
  cpi->ext_refresh_frame_flags_pending = 1;
  cpi->ext_refresh_last_frame = 1;
  if (!spatial_id) {
    cpi->ref_frame_flags = VP9_LAST_FLAG;
  } else if (cpi->svc.layer_context[0].is_key_frame) {
    cpi->ref_frame_flags = VP9_GOLD_FLAG;
  } else {
    cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
  }
  cpi->lst_fb_idx = spatial_id;
  if (spatial_id)
    cpi->gld_fb_idx = spatial_id - 1;
  else
    cpi->gld_fb_idx = 0;
}

int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
  int width = 0, height = 0;
  LAYER_CONTEXT *lc = NULL;

  if (cpi->svc.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_0212) {
    set_flags_and_fb_idx_for_temporal_mode3(cpi);
  } else if (cpi->svc.temporal_layering_mode ==
           VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
    set_flags_and_fb_idx_for_temporal_mode_noLayering(cpi);
  } else if (cpi->svc.temporal_layering_mode ==
           VP9E_TEMPORAL_LAYERING_MODE_0101) {
    set_flags_and_fb_idx_for_temporal_mode2(cpi);
  } else if (cpi->svc.temporal_layering_mode ==
      VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
    // VP9E_TEMPORAL_LAYERING_MODE_BYPASS :
    // if the code goes here, it means the encoder will be relying on the
    // flags from outside for layering.
    // However, since when spatial+temporal layering is used, the buffer indices
    // cannot be derived automatically, the bypass mode will only work when the
    // number of spatial layers equals 1.
    assert(cpi->svc.number_spatial_layers == 1);
  }

  lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
                               cpi->svc.number_temporal_layers +
                               cpi->svc.temporal_layer_id];

  get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
                       lc->scaling_factor_num, lc->scaling_factor_den,
                       &width, &height);

  if (vp9_set_size_literal(cpi, width, height) != 0)
    return VPX_CODEC_INVALID_PARAM;

  return 0;
}

#if CONFIG_SPATIAL_SVC
519
520
int vp9_svc_start_frame(VP9_COMP *const cpi) {
  int width = 0, height = 0;
521
  LAYER_CONTEXT *lc;
522
  struct lookahead_entry *buf;
523
  int count = 1 << (cpi->svc.number_temporal_layers - 1);
524

525
  cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
526
  lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
527

528
529
530
531
532
533
  cpi->svc.temporal_layer_id = 0;
  while ((lc->current_video_frame_in_layer % count) != 0) {
    ++cpi->svc.temporal_layer_id;
    count >>= 1;
  }

534
535
  cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;

536
537
538
539
540
541
542
  cpi->lst_fb_idx = cpi->svc.spatial_layer_id;

  if (cpi->svc.spatial_layer_id == 0)
    cpi->gld_fb_idx = (lc->gold_ref_idx >= 0) ?
                      lc->gold_ref_idx : cpi->lst_fb_idx;
  else
    cpi->gld_fb_idx = cpi->svc.spatial_layer_id - 1;
543
544

  if (lc->current_video_frame_in_layer == 0) {
545
    if (cpi->svc.spatial_layer_id >= 2) {
546
      cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2;
547
    } else {
548
      cpi->alt_fb_idx = cpi->lst_fb_idx;
549
550
      cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_ALT_FLAG);
    }
551
  } else {
552
    if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id]) {
553
554
555
556
557
558
559
560
561
562
563
      cpi->alt_fb_idx = lc->alt_ref_idx;
      if (!lc->has_alt_frame)
        cpi->ref_frame_flags &= (~VP9_ALT_FLAG);
    } else {
      // Find a proper alt_fb_idx for layers that don't have alt ref frame
      if (cpi->svc.spatial_layer_id == 0) {
        cpi->alt_fb_idx = cpi->lst_fb_idx;
      } else {
        LAYER_CONTEXT *lc_lower =
            &cpi->svc.layer_context[cpi->svc.spatial_layer_id - 1];

564
        if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id - 1] &&
565
566
567
            lc_lower->alt_ref_source != NULL)
          cpi->alt_fb_idx = lc_lower->alt_ref_idx;
        else if (cpi->svc.spatial_layer_id >= 2)
568
          cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2;
569
570
571
572
573
        else
          cpi->alt_fb_idx = cpi->lst_fb_idx;
      }
    }
  }
574

575
576
577
  get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
                       lc->scaling_factor_num, lc->scaling_factor_den,
                       &width, &height);
578
579
580
581
582

  // Workaround for multiple frame contexts. In some frames we can't use prev_mi
  // since its previous frame could be changed during decoding time. The idea is
  // we put a empty invisible frame in front of them, then we will not use
  // prev_mi when encoding these frames.
583
584

  buf = vp9_lookahead_peek(cpi->lookahead, 0);
585
  if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 &&
586
      cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE &&
587
588
      lc->rc.frames_to_key != 0 &&
      !(buf != NULL && (buf->flags & VPX_EFLAG_FORCE_KF))) {
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
    if ((cpi->svc.number_temporal_layers > 1 &&
         cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1) ||
        (cpi->svc.number_spatial_layers > 1 &&
         cpi->svc.spatial_layer_id == 0)) {
      struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead, 0);

      if (buf != NULL) {
        cpi->svc.empty_frame.ts_start = buf->ts_start;
        cpi->svc.empty_frame.ts_end = buf->ts_end;
        cpi->svc.encode_empty_frame_state = ENCODING;
        cpi->common.show_frame = 0;
        cpi->ref_frame_flags = 0;
        cpi->common.frame_type = INTER_FRAME;
        cpi->lst_fb_idx =
            cpi->gld_fb_idx = cpi->alt_fb_idx = SMALL_FRAME_FB_IDX;

605
606
        if (cpi->svc.encode_intra_empty_frame != 0)
          cpi->common.intra_only = 1;
607

608
609
        width = SMALL_FRAME_WIDTH;
        height = SMALL_FRAME_HEIGHT;
610
611
612
613
      }
    }
  }

614
615
  cpi->oxcf.worst_allowed_q = vp9_quantizer_to_qindex(lc->max_q);
  cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q);
616
617

  vp9_change_config(cpi, &cpi->oxcf);
618
619
620
621

  if (vp9_set_size_literal(cpi, width, height) != 0)
    return VPX_CODEC_INVALID_PARAM;

622
623
  vp9_set_high_precision_mv(cpi, 1);

624
  cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source;
625
626
627
628

  return 0;
}

629
630
#endif

631
632
633
634
635
struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
                                              struct lookahead_ctx *ctx,
                                              int drain) {
  struct lookahead_entry *buf = NULL;
  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
636
    buf = vp9_lookahead_peek(ctx, 0);
637
    if (buf != NULL) {
638
      // Only remove the buffer when pop the highest layer.
639
640
641
642
643
644
645
      if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
        vp9_lookahead_pop(ctx, drain);
      }
    }
  }
  return buf;
}