vp9_svc_layercontext.c 27.7 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>

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

19
#define SMALL_FRAME_FB_IDX 7
20
#define SMALL_FRAME_WIDTH  32
21
#define SMALL_FRAME_HEIGHT 16
22

23
void vp9_init_layer_context(VP9_COMP *const cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
24
  SVC *const svc = &cpi->svc;
25
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
26
27
  int mi_rows = cpi->common.mi_rows;
  int mi_cols = cpi->common.mi_cols;
28
  int sl, tl;
29
  int alt_ref_idx = svc->number_spatial_layers;
30

Dmitry Kovalev's avatar
Dmitry Kovalev committed
31
32
  svc->spatial_layer_id = 0;
  svc->temporal_layer_id = 0;
33
  svc->first_spatial_layer_to_encode = 0;
34

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

50
51
    memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80,
           cpi->svc.empty_frame.img.buffer_alloc_sz);
52
53
  }

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  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;
      }
77

78
79
80
81
82
83
84
85
86
87
      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 +
88
                                            oxcf->best_allowed_q) / 2;
89
90
91
92
93
94
95
96
        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;
      }
97

98
99
100
      lrc->buffer_level = oxcf->starting_buffer_level_ms *
                              lc->target_bandwidth / 1000;
      lrc->bits_off_target = lrc->buffer_level;
101
102
103
104
105
106
107

      // Initialize the cyclic refresh parameters. If spatial layers are used
      // (i.e., ss_number_layers > 1), these need to be updated per spatial
      // layer.
      // Cyclic refresh is only applied on base temporal layer.
      if (oxcf->ss_number_layers > 1 &&
          tl == 0) {
108
109
        size_t last_coded_q_map_size;
        size_t consec_zero_mv_size;
110
111
112
        lc->sb_index = 0;
        lc->map = vpx_malloc(mi_rows * mi_cols * sizeof(signed char));
        memset(lc->map, 0, mi_rows * mi_cols);
113
        last_coded_q_map_size = mi_rows * mi_cols * sizeof(uint8_t);
114
115
116
        lc->last_coded_q_map = vpx_malloc(last_coded_q_map_size);
        assert(MAXQ <= 255);
        memset(lc->last_coded_q_map, MAXQ, last_coded_q_map_size);
117
118
119
        consec_zero_mv_size = mi_rows * mi_cols * sizeof(uint8_t);
        lc->consec_zero_mv = vpx_malloc(consec_zero_mv_size);
        memset(lc->consec_zero_mv, 0, consec_zero_mv_size);
120
       }
121
    }
122
  }
123
124

  // Still have extra buffer for base layer golden frame
125
126
  if (!(svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR)
      && alt_ref_idx < REF_FRAMES)
127
    svc->layer_context[0].gold_ref_idx = alt_ref_idx;
128
129
130
131
132
}

// 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
133
  SVC *const svc = &cpi->svc;
134
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
135
  const RATE_CONTROL *const rc = &cpi->rc;
136
  int sl, tl, layer = 0, spatial_layer_target;
137
  float bitrate_alloc = 1.0;
138

139
140
141
142
143
144
145
  if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
    for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
      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];
      }
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
      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 =
167
168
            VPXMIN(lrc->bits_off_target, lrc->maximum_buffer_size);
        lrc->buffer_level = VPXMIN(lrc->buffer_level, lrc->maximum_buffer_size);
Marco's avatar
Marco committed
169
        lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
170
171
172
173
174
        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;
      }
175
    }
176
177
178
  } else {
    int layer_end;

179
    if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
180
      layer_end = svc->number_temporal_layers;
181
    } else {
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
      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);
199
200
201
      lrc->bits_off_target = VPXMIN(lrc->bits_off_target,
                                    lrc->maximum_buffer_size);
      lrc->buffer_level = VPXMIN(lrc->buffer_level, lrc->maximum_buffer_size);
202
203
204
205
206
207
208
209
210
211
212
      // 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;
213
    }
214
215
216
  }
}

217
static LAYER_CONTEXT *get_layer_context(VP9_COMP *const cpi) {
218
219
220
221
222
223
224
225
  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];
226
227
}

228
void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
229
  SVC *const svc = &cpi->svc;
230
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
231
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
232
  RATE_CONTROL *const lrc = &lc->rc;
233
234
235
236
  // 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;
237

238
  lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
239
  lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
240
241
  lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
  // Update the average layer frame size (non-cumulative per-frame-bw).
242
  if (tl == 0) {
243
    lc->avg_frame_size = lrc->avg_frame_bandwidth;
244
  } else {
245
    const double prev_layer_framerate =
246
247
248
        cpi->framerate / oxcf->ts_rate_decimator[tl - 1];
    const int prev_layer_target_bandwidth =
        oxcf->layer_target_bitrate[st_idx - 1];
249
250
251
252
253
254
    lc->avg_frame_size =
        (int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
              (lc->framerate - prev_layer_framerate));
  }
}

255
void vp9_update_spatial_layer_framerate(VP9_COMP *const cpi, double framerate) {
256
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
257
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
258
259
260
  RATE_CONTROL *const lrc = &lc->rc;

  lc->framerate = framerate;
261
262
  lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
  lrc->min_frame_bandwidth = (int)(lrc->avg_frame_bandwidth *
263
                                   oxcf->two_pass_vbrmin_section / 100);
264
  lrc->max_frame_bandwidth = (int)(((int64_t)lrc->avg_frame_bandwidth *
265
                                   oxcf->two_pass_vbrmax_section) / 100);
paulwilkins's avatar
paulwilkins committed
266
  vp9_rc_set_gf_interval_range(cpi, lrc);
267
268
}

269
void vp9_restore_layer_context(VP9_COMP *const cpi) {
270
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
271
272
273
  const int old_frame_since_key = cpi->rc.frames_since_key;
  const int old_frame_to_key = cpi->rc.frames_to_key;

274
  cpi->rc = lc->rc;
275
  cpi->twopass = lc->twopass;
276
  cpi->oxcf.target_bandwidth = lc->target_bandwidth;
277
  cpi->alt_ref_source = lc->alt_ref_source;
278
279
  // 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).
280
281
282
283
  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;
  }
284
285
286
287
288
289
290
291
292

  // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
  // for the base temporal layer.
  if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
      cpi->svc.number_spatial_layers > 1 &&
      cpi->svc.temporal_layer_id == 0) {
    CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
    signed char *temp = cr->map;
    uint8_t *temp2 = cr->last_coded_q_map;
293
    uint8_t *temp3 = cr->consec_zero_mv;
294
295
296
297
    cr->map = lc->map;
    lc->map = temp;
    cr->last_coded_q_map = lc->last_coded_q_map;
    lc->last_coded_q_map = temp2;
298
299
    cr->consec_zero_mv = lc->consec_zero_mv;
    lc->consec_zero_mv = temp3;
300
301
    cr->sb_index = lc->sb_index;
  }
302
303
304
}

void vp9_save_layer_context(VP9_COMP *const cpi) {
305
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
306
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
307

308
  lc->rc = cpi->rc;
309
  lc->twopass = cpi->twopass;
310
  lc->target_bandwidth = (int)oxcf->target_bandwidth;
311
  lc->alt_ref_source = cpi->alt_ref_source;
312
313
314
315
316
317
318
319
320

  // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
  // for the base temporal layer.
  if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
      cpi->svc.number_spatial_layers > 1 &&
      cpi->svc.temporal_layer_id == 0) {
    CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
    signed char *temp = lc->map;
    uint8_t *temp2 = lc->last_coded_q_map;
321
    uint8_t *temp3 = lc->consec_zero_mv;
322
323
324
325
    lc->map = cr->map;
    cr->map = temp;
    lc->last_coded_q_map = cr->last_coded_q_map;
    cr->last_coded_q_map = temp2;
326
327
    lc->consec_zero_mv = cr->consec_zero_mv;
    cr->consec_zero_mv = temp3;
328
329
    lc->sb_index = cr->sb_index;
  }
330
}
331
332

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

Dmitry Kovalev's avatar
Dmitry Kovalev committed
336
  for (i = 0; i < svc->number_spatial_layers; ++i) {
Paul Wilkins's avatar
Paul Wilkins committed
337
    TWO_PASS *const twopass = &svc->layer_context[i].twopass;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
338
339

    svc->spatial_layer_id = i;
340
341
342
343
344
    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
345
  svc->spatial_layer_id = 0;
346
}
347

348
349
void vp9_inc_frame_in_layer(VP9_COMP *const cpi) {
  LAYER_CONTEXT *const lc =
350
351
      &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
                              cpi->svc.number_temporal_layers];
352
  ++lc->current_video_frame_in_layer;
353
  ++lc->frames_from_key_frame;
354
}
355

356
int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) {
357
  return is_two_pass_svc(cpi) &&
358
         cpi->svc.spatial_layer_id > 0 &&
359
360
361
         cpi->svc.layer_context[cpi->svc.spatial_layer_id *
                                cpi->svc.number_temporal_layers +
                                cpi->svc.temporal_layer_id].is_key_frame;
362
}
363

364
365
366
367
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;
368

369
370
  if (width_out == NULL || height_out == NULL || den == 0)
    return;
371

372
373
  w = width_org * num / den;
  h = height_org * num / den;
374

375
376
377
  // make height and width even to make chrome player happy
  w += w % 2;
  h += h % 2;
378

379
380
  *width_out = w;
  *height_out = h;
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
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
// 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) {
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
    // In the BYPASS/flexible mode, the encoder is relying on the application
    // to specify, for each spatial layer, the flags and buffer indices for the
    // layering.
    // Note that the check (cpi->ext_refresh_frame_flags_pending == 0) is
    // needed to support the case where the frame flags may be passed in via
    // vpx_codec_encode(), which can be used for the temporal-only svc case.
    if (cpi->ext_refresh_frame_flags_pending == 0) {
      int sl;
      cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
      sl = cpi->svc.spatial_layer_id;
      vp9_apply_encoding_flags(cpi, cpi->svc.ext_frame_flags[sl]);
      cpi->lst_fb_idx = cpi->svc.ext_lst_fb_idx[sl];
      cpi->gld_fb_idx = cpi->svc.ext_gld_fb_idx[sl];
      cpi->alt_fb_idx = cpi->svc.ext_alt_fb_idx[sl];
    }
569
570
571
572
573
574
  }

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

575
576
577
578
579
580
581
582
  // Setting the worst/best_quality via the encoder control: SET_SVC_PARAMETERS,
  // only for non-BYPASS mode for now.
  if (cpi->svc.temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
    RATE_CONTROL *const lrc = &lc->rc;
    lrc->worst_quality = vp9_quantizer_to_qindex(lc->max_q);
    lrc->best_quality =  vp9_quantizer_to_qindex(lc->min_q);
  }

583
584
585
586
587
588
589
590
591
592
593
  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
594
595
int vp9_svc_start_frame(VP9_COMP *const cpi) {
  int width = 0, height = 0;
596
  LAYER_CONTEXT *lc;
597
  struct lookahead_entry *buf;
598
  int count = 1 << (cpi->svc.number_temporal_layers - 1);
599

600
  cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
601
  lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
602

603
604
605
606
607
608
  cpi->svc.temporal_layer_id = 0;
  while ((lc->current_video_frame_in_layer % count) != 0) {
    ++cpi->svc.temporal_layer_id;
    count >>= 1;
  }

609
610
  cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;

611
612
613
614
615
616
617
  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;
618
619

  if (lc->current_video_frame_in_layer == 0) {
620
    if (cpi->svc.spatial_layer_id >= 2) {
621
      cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2;
622
    } else {
623
      cpi->alt_fb_idx = cpi->lst_fb_idx;
624
625
      cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_ALT_FLAG);
    }
626
  } else {
627
    if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id]) {
628
629
630
631
632
633
634
635
636
637
638
      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];

639
        if (cpi->oxcf.ss_enable_auto_arf[cpi->svc.spatial_layer_id - 1] &&
640
641
642
            lc_lower->alt_ref_source != NULL)
          cpi->alt_fb_idx = lc_lower->alt_ref_idx;
        else if (cpi->svc.spatial_layer_id >= 2)
643
          cpi->alt_fb_idx = cpi->svc.spatial_layer_id - 2;
644
645
646
647
648
        else
          cpi->alt_fb_idx = cpi->lst_fb_idx;
      }
    }
  }
649

650
651
652
  get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
                       lc->scaling_factor_num, lc->scaling_factor_den,
                       &width, &height);
653
654
655
656
657

  // 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.
658
659

  buf = vp9_lookahead_peek(cpi->lookahead, 0);
660
  if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 &&
661
      cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE &&
662
663
      lc->rc.frames_to_key != 0 &&
      !(buf != NULL && (buf->flags & VPX_EFLAG_FORCE_KF))) {
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
    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;

680
681
        if (cpi->svc.encode_intra_empty_frame != 0)
          cpi->common.intra_only = 1;
682

683
684
        width = SMALL_FRAME_WIDTH;
        height = SMALL_FRAME_HEIGHT;
685
686
687
688
      }
    }
  }

689
690
  cpi->oxcf.worst_allowed_q = vp9_quantizer_to_qindex(lc->max_q);
  cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q);
691
692

  vp9_change_config(cpi, &cpi->oxcf);
693
694
695
696

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

697
698
  vp9_set_high_precision_mv(cpi, 1);

699
  cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source;
700
701
702
703

  return 0;
}

704
705
#endif

706
707
708
709
710
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)) {
711
    buf = vp9_lookahead_peek(ctx, 0);
712
    if (buf != NULL) {
713
      // Only remove the buffer when pop the highest layer.
714
715
716
717
718
719
720
      if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
        vp9_lookahead_pop(ctx, drain);
      }
    }
  }
  return buf;
}
721
722
723
724
725
726
727
728
729
730
731
732
733

void vp9_free_svc_cyclic_refresh(VP9_COMP *const cpi) {
  int sl, tl;
  SVC *const svc = &cpi->svc;
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
  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];
        if (lc->map)
          vpx_free(lc->map);
        if (lc->last_coded_q_map)
          vpx_free(lc->last_coded_q_map);
734
735
        if (lc->consec_zero_mv)
          vpx_free(lc->consec_zero_mv);
736
737
738
    }
  }
}