Vidyo patch: Rate control for SVC, 1 pass CBR mode.
-Make Rate control work for SVC 1 pass CBR mode. -Added temporal layering mode. -Fixed bug in non-rd variance partition. -Modified/updated the sample encoders (vp9_spatial_svc_encoder, vpx_temporal_svc_encoder). -Added datarate unittest(s) for 1 pass CBR SVC. Change-Id: Ie94b1b68a56ea1267b5087c625e5df04def2ee48
This commit is contained in:
		@@ -14,11 +14,13 @@
 | 
				
			|||||||
 * that benefit from a scalable bitstream.
 | 
					 * that benefit from a scalable bitstream.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../args.h"
 | 
					#include "../args.h"
 | 
				
			||||||
#include "../tools_common.h"
 | 
					#include "../tools_common.h"
 | 
				
			||||||
#include "../video_writer.h"
 | 
					#include "../video_writer.h"
 | 
				
			||||||
@@ -27,11 +29,18 @@
 | 
				
			|||||||
#include "vpx/vp8cx.h"
 | 
					#include "vpx/vp8cx.h"
 | 
				
			||||||
#include "vpx/vpx_encoder.h"
 | 
					#include "vpx/vpx_encoder.h"
 | 
				
			||||||
#include "../vpxstats.h"
 | 
					#include "../vpxstats.h"
 | 
				
			||||||
 | 
					#define OUTPUT_RC_STATS 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const arg_def_t skip_frames_arg =
 | 
					static const arg_def_t skip_frames_arg =
 | 
				
			||||||
    ARG_DEF("s", "skip-frames", 1, "input frames to skip");
 | 
					    ARG_DEF("s", "skip-frames", 1, "input frames to skip");
 | 
				
			||||||
static const arg_def_t frames_arg =
 | 
					static const arg_def_t frames_arg =
 | 
				
			||||||
    ARG_DEF("f", "frames", 1, "number of frames to encode");
 | 
					    ARG_DEF("f", "frames", 1, "number of frames to encode");
 | 
				
			||||||
 | 
					static const arg_def_t threads_arg =
 | 
				
			||||||
 | 
					    ARG_DEF("th", "threads", 1, "number of threads to use");
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					static const arg_def_t output_rc_stats_arg =
 | 
				
			||||||
 | 
					    ARG_DEF("rcstat", "output_rc_stats", 1, "output rc stats");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width");
 | 
					static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width");
 | 
				
			||||||
static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height");
 | 
					static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height");
 | 
				
			||||||
static const arg_def_t timebase_arg =
 | 
					static const arg_def_t timebase_arg =
 | 
				
			||||||
@@ -42,6 +51,9 @@ static const arg_def_t spatial_layers_arg =
 | 
				
			|||||||
    ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
 | 
					    ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
 | 
				
			||||||
static const arg_def_t temporal_layers_arg =
 | 
					static const arg_def_t temporal_layers_arg =
 | 
				
			||||||
    ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
 | 
					    ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
 | 
				
			||||||
 | 
					static const arg_def_t temporal_layering_mode_arg =
 | 
				
			||||||
 | 
					    ARG_DEF("tlm", "temporal-layering-mode", 1, "temporal layering scheme."
 | 
				
			||||||
 | 
					        "VP9E_TEMPORAL_LAYERING_MODE");
 | 
				
			||||||
static const arg_def_t kf_dist_arg =
 | 
					static const arg_def_t kf_dist_arg =
 | 
				
			||||||
    ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
 | 
					    ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
 | 
				
			||||||
static const arg_def_t scale_factors_arg =
 | 
					static const arg_def_t scale_factors_arg =
 | 
				
			||||||
@@ -65,6 +77,8 @@ static const arg_def_t lag_in_frame_arg =
 | 
				
			|||||||
        "generating any outputs");
 | 
					        "generating any outputs");
 | 
				
			||||||
static const arg_def_t rc_end_usage_arg =
 | 
					static const arg_def_t rc_end_usage_arg =
 | 
				
			||||||
    ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
 | 
					    ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
 | 
				
			||||||
 | 
					static const arg_def_t speed_arg =
 | 
				
			||||||
 | 
					    ARG_DEF("sp", "speed", 1, "speed configuration");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG_VP9_HIGHBITDEPTH
 | 
					#if CONFIG_VP9_HIGHBITDEPTH
 | 
				
			||||||
static const struct arg_enum_list bitdepth_enum[] = {
 | 
					static const struct arg_enum_list bitdepth_enum[] = {
 | 
				
			||||||
@@ -85,10 +99,16 @@ static const arg_def_t *svc_args[] = {
 | 
				
			|||||||
  &timebase_arg,      &bitrate_arg,       &skip_frames_arg, &spatial_layers_arg,
 | 
					  &timebase_arg,      &bitrate_arg,       &skip_frames_arg, &spatial_layers_arg,
 | 
				
			||||||
  &kf_dist_arg,       &scale_factors_arg, &passes_arg,      &pass_arg,
 | 
					  &kf_dist_arg,       &scale_factors_arg, &passes_arg,      &pass_arg,
 | 
				
			||||||
  &fpf_name_arg,      &min_q_arg,         &max_q_arg,       &min_bitrate_arg,
 | 
					  &fpf_name_arg,      &min_q_arg,         &max_q_arg,       &min_bitrate_arg,
 | 
				
			||||||
  &max_bitrate_arg,   &temporal_layers_arg,                 &lag_in_frame_arg,
 | 
					  &max_bitrate_arg,   &temporal_layers_arg, &temporal_layering_mode_arg,
 | 
				
			||||||
 | 
					  &lag_in_frame_arg,  &threads_arg,
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  &output_rc_stats_arg,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG_VP9_HIGHBITDEPTH
 | 
					#if CONFIG_VP9_HIGHBITDEPTH
 | 
				
			||||||
  &bitdepth_arg,
 | 
					  &bitdepth_arg,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					  &speed_arg,
 | 
				
			||||||
  &rc_end_usage_arg,  NULL
 | 
					  &rc_end_usage_arg,  NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,6 +122,10 @@ static const uint32_t default_bitrate = 1000;
 | 
				
			|||||||
static const uint32_t default_spatial_layers = 5;
 | 
					static const uint32_t default_spatial_layers = 5;
 | 
				
			||||||
static const uint32_t default_temporal_layers = 1;
 | 
					static const uint32_t default_temporal_layers = 1;
 | 
				
			||||||
static const uint32_t default_kf_dist = 100;
 | 
					static const uint32_t default_kf_dist = 100;
 | 
				
			||||||
 | 
					static const uint32_t default_temporal_layering_mode = 0;
 | 
				
			||||||
 | 
					static const uint32_t default_output_rc_stats = 0;
 | 
				
			||||||
 | 
					static const int32_t default_speed = -1;  // -1 means use library default.
 | 
				
			||||||
 | 
					static const uint32_t default_threads = 0;  // zero means use library default.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
  const char *input_filename;
 | 
					  const char *input_filename;
 | 
				
			||||||
@@ -143,6 +167,12 @@ static void parse_command_line(int argc, const char **argv_,
 | 
				
			|||||||
  svc_ctx->log_level = SVC_LOG_DEBUG;
 | 
					  svc_ctx->log_level = SVC_LOG_DEBUG;
 | 
				
			||||||
  svc_ctx->spatial_layers = default_spatial_layers;
 | 
					  svc_ctx->spatial_layers = default_spatial_layers;
 | 
				
			||||||
  svc_ctx->temporal_layers = default_temporal_layers;
 | 
					  svc_ctx->temporal_layers = default_temporal_layers;
 | 
				
			||||||
 | 
					  svc_ctx->temporal_layering_mode = default_temporal_layering_mode;
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  svc_ctx->output_rc_stat = default_output_rc_stats;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  svc_ctx->speed = default_speed;
 | 
				
			||||||
 | 
					  svc_ctx->threads = default_threads;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // start with default encoder configuration
 | 
					  // start with default encoder configuration
 | 
				
			||||||
  res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
 | 
					  res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
 | 
				
			||||||
@@ -184,6 +214,20 @@ static void parse_command_line(int argc, const char **argv_,
 | 
				
			|||||||
      svc_ctx->spatial_layers = arg_parse_uint(&arg);
 | 
					      svc_ctx->spatial_layers = arg_parse_uint(&arg);
 | 
				
			||||||
    } else if (arg_match(&arg, &temporal_layers_arg, argi)) {
 | 
					    } else if (arg_match(&arg, &temporal_layers_arg, argi)) {
 | 
				
			||||||
      svc_ctx->temporal_layers = arg_parse_uint(&arg);
 | 
					      svc_ctx->temporal_layers = arg_parse_uint(&arg);
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					    } else if (arg_match(&arg, &output_rc_stats_arg, argi)) {
 | 
				
			||||||
 | 
					      svc_ctx->output_rc_stat = arg_parse_uint(&arg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    } else if (arg_match(&arg, &speed_arg, argi)) {
 | 
				
			||||||
 | 
					      svc_ctx->speed = arg_parse_uint(&arg);
 | 
				
			||||||
 | 
					    } else if (arg_match(&arg, &threads_arg, argi)) {
 | 
				
			||||||
 | 
					      svc_ctx->threads = arg_parse_uint(&arg);
 | 
				
			||||||
 | 
					    } else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
 | 
				
			||||||
 | 
					      svc_ctx->temporal_layering_mode =
 | 
				
			||||||
 | 
					          enc_cfg->temporal_layering_mode = arg_parse_int(&arg);
 | 
				
			||||||
 | 
					      if (svc_ctx->temporal_layering_mode) {
 | 
				
			||||||
 | 
					        enc_cfg->g_error_resilient = 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } else if (arg_match(&arg, &kf_dist_arg, argi)) {
 | 
					    } else if (arg_match(&arg, &kf_dist_arg, argi)) {
 | 
				
			||||||
      enc_cfg->kf_min_dist = arg_parse_uint(&arg);
 | 
					      enc_cfg->kf_min_dist = arg_parse_uint(&arg);
 | 
				
			||||||
      enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
 | 
					      enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
 | 
				
			||||||
@@ -316,6 +360,185 @@ static void parse_command_line(int argc, const char **argv_,
 | 
				
			|||||||
      enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
 | 
					      enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					// For rate control encoding stats.
 | 
				
			||||||
 | 
					struct RateControlStats {
 | 
				
			||||||
 | 
					  // Number of input frames per layer.
 | 
				
			||||||
 | 
					  int layer_input_frames[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Total (cumulative) number of encoded frames per layer.
 | 
				
			||||||
 | 
					  int layer_tot_enc_frames[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Number of encoded non-key frames per layer.
 | 
				
			||||||
 | 
					  int layer_enc_frames[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Framerate per layer (cumulative).
 | 
				
			||||||
 | 
					  double layer_framerate[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Target average frame size per layer (per-frame-bandwidth per layer).
 | 
				
			||||||
 | 
					  double layer_pfb[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Actual average frame size per layer.
 | 
				
			||||||
 | 
					  double layer_avg_frame_size[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Average rate mismatch per layer (|target - actual| / target).
 | 
				
			||||||
 | 
					  double layer_avg_rate_mismatch[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Actual encoding bitrate per layer (cumulative).
 | 
				
			||||||
 | 
					  double layer_encoding_bitrate[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					  // Average of the short-time encoder actual bitrate.
 | 
				
			||||||
 | 
					  // TODO(marpan): Should we add these short-time stats for each layer?
 | 
				
			||||||
 | 
					  double avg_st_encoding_bitrate;
 | 
				
			||||||
 | 
					  // Variance of the short-time encoder actual bitrate.
 | 
				
			||||||
 | 
					  double variance_st_encoding_bitrate;
 | 
				
			||||||
 | 
					  // Window (number of frames) for computing short-time encoding bitrate.
 | 
				
			||||||
 | 
					  int window_size;
 | 
				
			||||||
 | 
					  // Number of window measurements.
 | 
				
			||||||
 | 
					  int window_count;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Note: these rate control stats assume only 1 key frame in the
 | 
				
			||||||
 | 
					// sequence (i.e., first frame only).
 | 
				
			||||||
 | 
					static void set_rate_control_stats(struct RateControlStats *rc,
 | 
				
			||||||
 | 
					                                     vpx_codec_enc_cfg_t *cfg) {
 | 
				
			||||||
 | 
					  unsigned int sl, tl;
 | 
				
			||||||
 | 
					  // Set the layer (cumulative) framerate and the target layer (non-cumulative)
 | 
				
			||||||
 | 
					  // per-frame-bandwidth, for the rate control encoding stats below.
 | 
				
			||||||
 | 
					  const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					    for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					      const int layer = sl * cfg->ts_number_layers + tl;
 | 
				
			||||||
 | 
					      const int tlayer0 = sl * cfg->ts_number_layers;
 | 
				
			||||||
 | 
					      rc->layer_framerate[layer] =
 | 
				
			||||||
 | 
					          framerate / cfg->ts_rate_decimator[tl];
 | 
				
			||||||
 | 
					      if (tl > 0) {
 | 
				
			||||||
 | 
					        rc->layer_pfb[layer] = 1000.0 *
 | 
				
			||||||
 | 
					            (cfg->layer_target_bitrate[layer] -
 | 
				
			||||||
 | 
					                cfg->layer_target_bitrate[layer - 1]) /
 | 
				
			||||||
 | 
					            (rc->layer_framerate[layer] -
 | 
				
			||||||
 | 
					                rc->layer_framerate[layer - 1]);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        rc->layer_pfb[tlayer0] = 1000.0 *
 | 
				
			||||||
 | 
					            cfg->layer_target_bitrate[tlayer0] /
 | 
				
			||||||
 | 
					            rc->layer_framerate[tlayer0];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      rc->layer_input_frames[layer] = 0;
 | 
				
			||||||
 | 
					      rc->layer_enc_frames[layer] = 0;
 | 
				
			||||||
 | 
					      rc->layer_tot_enc_frames[layer] = 0;
 | 
				
			||||||
 | 
					      rc->layer_encoding_bitrate[layer] = 0.0;
 | 
				
			||||||
 | 
					      rc->layer_avg_frame_size[layer] = 0.0;
 | 
				
			||||||
 | 
					      rc->layer_avg_rate_mismatch[layer] = 0.0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  rc->window_count = 0;
 | 
				
			||||||
 | 
					  rc->window_size = 15;
 | 
				
			||||||
 | 
					  rc->avg_st_encoding_bitrate = 0.0;
 | 
				
			||||||
 | 
					  rc->variance_st_encoding_bitrate = 0.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void printout_rate_control_summary(struct RateControlStats *rc,
 | 
				
			||||||
 | 
					                                          vpx_codec_enc_cfg_t *cfg,
 | 
				
			||||||
 | 
					                                          int frame_cnt) {
 | 
				
			||||||
 | 
					  unsigned int sl, tl;
 | 
				
			||||||
 | 
					  int tot_num_frames = 0;
 | 
				
			||||||
 | 
					  double perc_fluctuation = 0.0;
 | 
				
			||||||
 | 
					  printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
 | 
				
			||||||
 | 
					  printf("Rate control layer stats for sl%d tl%d layer(s):\n\n",
 | 
				
			||||||
 | 
					      cfg->ss_number_layers, cfg->ts_number_layers);
 | 
				
			||||||
 | 
					  for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					    for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					      const int layer = sl * cfg->ts_number_layers + tl;
 | 
				
			||||||
 | 
					      const int num_dropped = (tl > 0) ?
 | 
				
			||||||
 | 
					          (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer]) :
 | 
				
			||||||
 | 
					          (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] - 1);
 | 
				
			||||||
 | 
					      if (!sl)
 | 
				
			||||||
 | 
					        tot_num_frames += rc->layer_input_frames[layer];
 | 
				
			||||||
 | 
					      rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] *
 | 
				
			||||||
 | 
					          rc->layer_encoding_bitrate[layer] / tot_num_frames;
 | 
				
			||||||
 | 
					      rc->layer_avg_frame_size[layer] = rc->layer_avg_frame_size[layer] /
 | 
				
			||||||
 | 
					          rc->layer_enc_frames[layer];
 | 
				
			||||||
 | 
					      rc->layer_avg_rate_mismatch[layer] =
 | 
				
			||||||
 | 
					          100.0 * rc->layer_avg_rate_mismatch[layer] /
 | 
				
			||||||
 | 
					          rc->layer_enc_frames[layer];
 | 
				
			||||||
 | 
					      printf("For layer#: sl%d tl%d \n", sl, tl);
 | 
				
			||||||
 | 
					      printf("Bitrate (target vs actual): %d %f.0 kbps\n",
 | 
				
			||||||
 | 
					             cfg->layer_target_bitrate[layer],
 | 
				
			||||||
 | 
					             rc->layer_encoding_bitrate[layer]);
 | 
				
			||||||
 | 
					      printf("Average frame size (target vs actual): %f %f bits\n",
 | 
				
			||||||
 | 
					             rc->layer_pfb[layer], rc->layer_avg_frame_size[layer]);
 | 
				
			||||||
 | 
					      printf("Average rate_mismatch: %f\n",
 | 
				
			||||||
 | 
					             rc->layer_avg_rate_mismatch[layer]);
 | 
				
			||||||
 | 
					      printf("Number of input frames, encoded (non-key) frames, "
 | 
				
			||||||
 | 
					          "and percent dropped frames: %d %d %f.0 \n",
 | 
				
			||||||
 | 
					          rc->layer_input_frames[layer], rc->layer_enc_frames[layer],
 | 
				
			||||||
 | 
					          100.0 * num_dropped / rc->layer_input_frames[layer]);
 | 
				
			||||||
 | 
					      printf("\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
 | 
				
			||||||
 | 
					  rc->variance_st_encoding_bitrate =
 | 
				
			||||||
 | 
					      rc->variance_st_encoding_bitrate / rc->window_count -
 | 
				
			||||||
 | 
					      (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
 | 
				
			||||||
 | 
					  perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
 | 
				
			||||||
 | 
					      rc->avg_st_encoding_bitrate;
 | 
				
			||||||
 | 
					  printf("Short-time stats, for window of %d frames: \n", rc->window_size);
 | 
				
			||||||
 | 
					  printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
 | 
				
			||||||
 | 
					         rc->avg_st_encoding_bitrate,
 | 
				
			||||||
 | 
					         sqrt(rc->variance_st_encoding_bitrate),
 | 
				
			||||||
 | 
					         perc_fluctuation);
 | 
				
			||||||
 | 
					  if (frame_cnt != tot_num_frames)
 | 
				
			||||||
 | 
					    die("Error: Number of input frames not equal to output encoded frames != "
 | 
				
			||||||
 | 
					        "%d tot_num_frames = %d\n", frame_cnt, tot_num_frames);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vpx_codec_err_t parse_superframe_index(const uint8_t *data,
 | 
				
			||||||
 | 
					                                       size_t data_sz,
 | 
				
			||||||
 | 
					                                       uint32_t sizes[8], int *count) {
 | 
				
			||||||
 | 
					  // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
 | 
				
			||||||
 | 
					  // it is a super frame index. If the last byte of real video compression
 | 
				
			||||||
 | 
					  // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
 | 
				
			||||||
 | 
					  // not the associated matching marker byte at the front of the index we have
 | 
				
			||||||
 | 
					  // an invalid bitstream and need to return an error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t marker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  marker = *(data + data_sz - 1);
 | 
				
			||||||
 | 
					  *count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((marker & 0xe0) == 0xc0) {
 | 
				
			||||||
 | 
					    const uint32_t frames = (marker & 0x7) + 1;
 | 
				
			||||||
 | 
					    const uint32_t mag = ((marker >> 3) & 0x3) + 1;
 | 
				
			||||||
 | 
					    const size_t index_sz = 2 + mag * frames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This chunk is marked as having a superframe index but doesn't have
 | 
				
			||||||
 | 
					    // enough data for it, thus it's an invalid superframe index.
 | 
				
			||||||
 | 
					    if (data_sz < index_sz)
 | 
				
			||||||
 | 
					      return VPX_CODEC_CORRUPT_FRAME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      const uint8_t marker2 = *(data + data_sz - index_sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // This chunk is marked as having a superframe index but doesn't have
 | 
				
			||||||
 | 
					      // the matching marker byte at the front of the index therefore it's an
 | 
				
			||||||
 | 
					      // invalid chunk.
 | 
				
			||||||
 | 
					      if (marker != marker2)
 | 
				
			||||||
 | 
					        return VPX_CODEC_CORRUPT_FRAME;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      // Found a valid superframe index.
 | 
				
			||||||
 | 
					      uint32_t i, j;
 | 
				
			||||||
 | 
					      const uint8_t *x = &data[data_sz - index_sz + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (i = 0; i < frames; ++i) {
 | 
				
			||||||
 | 
					        uint32_t this_sz = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (j = 0; j < mag; ++j)
 | 
				
			||||||
 | 
					          this_sz |= (*x++) << (j * 8);
 | 
				
			||||||
 | 
					        sizes[i] = this_sz;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      *count = frames;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return VPX_CODEC_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, const char **argv) {
 | 
					int main(int argc, const char **argv) {
 | 
				
			||||||
  AppInput app_input = {0};
 | 
					  AppInput app_input = {0};
 | 
				
			||||||
  VpxVideoWriter *writer = NULL;
 | 
					  VpxVideoWriter *writer = NULL;
 | 
				
			||||||
@@ -332,7 +555,15 @@ int main(int argc, const char **argv) {
 | 
				
			|||||||
  FILE *infile = NULL;
 | 
					  FILE *infile = NULL;
 | 
				
			||||||
  int end_of_stream = 0;
 | 
					  int end_of_stream = 0;
 | 
				
			||||||
  int frames_received = 0;
 | 
					  int frames_received = 0;
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
 | 
				
			||||||
 | 
					  struct RateControlStats rc;
 | 
				
			||||||
 | 
					  vpx_svc_layer_id_t layer_id;
 | 
				
			||||||
 | 
					  int sl, tl;
 | 
				
			||||||
 | 
					  double sum_bitrate = 0.0;
 | 
				
			||||||
 | 
					  double sum_bitrate2 = 0.0;
 | 
				
			||||||
 | 
					  double framerate  = 30.0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  memset(&svc_ctx, 0, sizeof(svc_ctx));
 | 
					  memset(&svc_ctx, 0, sizeof(svc_ctx));
 | 
				
			||||||
  svc_ctx.log_print = 1;
 | 
					  svc_ctx.log_print = 1;
 | 
				
			||||||
  exec_name = argv[0];
 | 
					  exec_name = argv[0];
 | 
				
			||||||
@@ -359,6 +590,13 @@ int main(int argc, const char **argv) {
 | 
				
			|||||||
      VPX_CODEC_OK)
 | 
					      VPX_CODEC_OK)
 | 
				
			||||||
    die("Failed to initialize encoder\n");
 | 
					    die("Failed to initialize encoder\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  if (svc_ctx.output_rc_stat) {
 | 
				
			||||||
 | 
					    set_rate_control_stats(&rc, &enc_cfg);
 | 
				
			||||||
 | 
					    framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  info.codec_fourcc = VP9_FOURCC;
 | 
					  info.codec_fourcc = VP9_FOURCC;
 | 
				
			||||||
  info.time_base.numerator = enc_cfg.g_timebase.num;
 | 
					  info.time_base.numerator = enc_cfg.g_timebase.num;
 | 
				
			||||||
  info.time_base.denominator = enc_cfg.g_timebase.den;
 | 
					  info.time_base.denominator = enc_cfg.g_timebase.den;
 | 
				
			||||||
@@ -370,11 +608,30 @@ int main(int argc, const char **argv) {
 | 
				
			|||||||
    if (!writer)
 | 
					    if (!writer)
 | 
				
			||||||
      die("Failed to open %s for writing\n", app_input.output_filename);
 | 
					      die("Failed to open %s for writing\n", app_input.output_filename);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  // For now, just write temporal layer streams.
 | 
				
			||||||
 | 
					  // TODO(wonkap): do spatial by re-writing superframe.
 | 
				
			||||||
 | 
					  if (svc_ctx.output_rc_stat) {
 | 
				
			||||||
 | 
					    for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					      char file_name[PATH_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      snprintf(file_name, sizeof(file_name), "%s_t%d.ivf",
 | 
				
			||||||
 | 
					               app_input.output_filename, tl);
 | 
				
			||||||
 | 
					      outfile[tl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
 | 
				
			||||||
 | 
					      if (!outfile[tl])
 | 
				
			||||||
 | 
					        die("Failed to open %s for writing", file_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // skip initial frames
 | 
					  // skip initial frames
 | 
				
			||||||
  for (i = 0; i < app_input.frames_to_skip; ++i)
 | 
					  for (i = 0; i < app_input.frames_to_skip; ++i)
 | 
				
			||||||
    vpx_img_read(&raw, infile);
 | 
					    vpx_img_read(&raw, infile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (svc_ctx.speed != -1)
 | 
				
			||||||
 | 
					    vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
 | 
				
			||||||
 | 
					  vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Encode frames
 | 
					  // Encode frames
 | 
				
			||||||
  while (!end_of_stream) {
 | 
					  while (!end_of_stream) {
 | 
				
			||||||
    vpx_codec_iter_t iter = NULL;
 | 
					    vpx_codec_iter_t iter = NULL;
 | 
				
			||||||
@@ -386,7 +643,9 @@ int main(int argc, const char **argv) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
 | 
					    res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
 | 
				
			||||||
                         pts, frame_duration, VPX_DL_GOOD_QUALITY);
 | 
					                         pts, frame_duration, svc_ctx.speed >= 5 ?
 | 
				
			||||||
 | 
					                         VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("%s", vpx_svc_get_message(&svc_ctx));
 | 
					    printf("%s", vpx_svc_get_message(&svc_ctx));
 | 
				
			||||||
    if (res != VPX_CODEC_OK) {
 | 
					    if (res != VPX_CODEC_OK) {
 | 
				
			||||||
      die_codec(&codec, "Failed to encode frame");
 | 
					      die_codec(&codec, "Failed to encode frame");
 | 
				
			||||||
@@ -395,11 +654,90 @@ int main(int argc, const char **argv) {
 | 
				
			|||||||
    while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
 | 
					    while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
 | 
				
			||||||
      switch (cx_pkt->kind) {
 | 
					      switch (cx_pkt->kind) {
 | 
				
			||||||
        case VPX_CODEC_CX_FRAME_PKT: {
 | 
					        case VPX_CODEC_CX_FRAME_PKT: {
 | 
				
			||||||
          if (cx_pkt->data.frame.sz > 0)
 | 
					          if (cx_pkt->data.frame.sz > 0) {
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					            uint32_t sizes[8];
 | 
				
			||||||
 | 
					            int count = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
            vpx_video_writer_write_frame(writer,
 | 
					            vpx_video_writer_write_frame(writer,
 | 
				
			||||||
                                         cx_pkt->data.frame.buf,
 | 
					                                         cx_pkt->data.frame.buf,
 | 
				
			||||||
                                         cx_pkt->data.frame.sz,
 | 
					                                         cx_pkt->data.frame.sz,
 | 
				
			||||||
                                         cx_pkt->data.frame.pts);
 | 
					                                         cx_pkt->data.frame.pts);
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					            // TODO(marpan/wonkap): Put this (to line728) in separate function.
 | 
				
			||||||
 | 
					            if (svc_ctx.output_rc_stat) {
 | 
				
			||||||
 | 
					              vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id);
 | 
				
			||||||
 | 
					              parse_superframe_index(cx_pkt->data.frame.buf,
 | 
				
			||||||
 | 
					                                     cx_pkt->data.frame.sz, sizes, &count);
 | 
				
			||||||
 | 
					              for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					                ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
 | 
				
			||||||
 | 
					                                        layer_id.temporal_layer_id];
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              for (tl = layer_id.temporal_layer_id;
 | 
				
			||||||
 | 
					                  tl < enc_cfg.ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					                vpx_video_writer_write_frame(outfile[tl],
 | 
				
			||||||
 | 
					                                             cx_pkt->data.frame.buf,
 | 
				
			||||||
 | 
					                                             cx_pkt->data.frame.sz,
 | 
				
			||||||
 | 
					                                             cx_pkt->data.frame.pts);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					                for (tl = layer_id.temporal_layer_id;
 | 
				
			||||||
 | 
					                    tl < enc_cfg.ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					                  const int layer = sl * enc_cfg.ts_number_layers + tl;
 | 
				
			||||||
 | 
					                  ++rc.layer_tot_enc_frames[layer];
 | 
				
			||||||
 | 
					                  rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
 | 
				
			||||||
 | 
					                  // Keep count of rate control stats per layer, for non-key
 | 
				
			||||||
 | 
					                  // frames.
 | 
				
			||||||
 | 
					                  if (tl == layer_id.temporal_layer_id &&
 | 
				
			||||||
 | 
					                      !(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
 | 
				
			||||||
 | 
					                    rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
 | 
				
			||||||
 | 
					                    rc.layer_avg_rate_mismatch[layer] +=
 | 
				
			||||||
 | 
					                        fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) /
 | 
				
			||||||
 | 
					                        rc.layer_pfb[layer];
 | 
				
			||||||
 | 
					                    ++rc.layer_enc_frames[layer];
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Update for short-time encoding bitrate states, for moving
 | 
				
			||||||
 | 
					              // window of size rc->window, shifted by rc->window / 2.
 | 
				
			||||||
 | 
					              // Ignore first window segment, due to key frame.
 | 
				
			||||||
 | 
					              if (frame_cnt > rc.window_size) {
 | 
				
			||||||
 | 
					                tl = layer_id.temporal_layer_id;
 | 
				
			||||||
 | 
					                for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					                  sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (frame_cnt % rc.window_size == 0) {
 | 
				
			||||||
 | 
					                  rc.window_count += 1;
 | 
				
			||||||
 | 
					                  rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
 | 
				
			||||||
 | 
					                  rc.variance_st_encoding_bitrate +=
 | 
				
			||||||
 | 
					                      (sum_bitrate / rc.window_size) *
 | 
				
			||||||
 | 
					                      (sum_bitrate / rc.window_size);
 | 
				
			||||||
 | 
					                  sum_bitrate = 0.0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Second shifted window.
 | 
				
			||||||
 | 
					              if (frame_cnt > rc.window_size + rc.window_size / 2) {
 | 
				
			||||||
 | 
					               tl = layer_id.temporal_layer_id;
 | 
				
			||||||
 | 
					               for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					                 sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					               if (frame_cnt > 2 * rc.window_size &&
 | 
				
			||||||
 | 
					                  frame_cnt % rc.window_size == 0) {
 | 
				
			||||||
 | 
					                 rc.window_count += 1;
 | 
				
			||||||
 | 
					                 rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
 | 
				
			||||||
 | 
					                 rc.variance_st_encoding_bitrate +=
 | 
				
			||||||
 | 
					                    (sum_bitrate2 / rc.window_size) *
 | 
				
			||||||
 | 
					                    (sum_bitrate2 / rc.window_size);
 | 
				
			||||||
 | 
					                 sum_bitrate2 = 0.0;
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
 | 
					          printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
 | 
				
			||||||
                 !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
 | 
					                 !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
 | 
				
			||||||
@@ -424,25 +762,30 @@ int main(int argc, const char **argv) {
 | 
				
			|||||||
      pts += frame_duration;
 | 
					      pts += frame_duration;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  printf("Processed %d frames\n", frame_cnt);
 | 
					  printf("Processed %d frames\n", frame_cnt);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  fclose(infile);
 | 
					  fclose(infile);
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  if (svc_ctx.output_rc_stat) {
 | 
				
			||||||
 | 
					    printout_rate_control_summary(&rc, &enc_cfg, frame_cnt);
 | 
				
			||||||
 | 
					    printf("\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
 | 
					  if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (app_input.passes == 2)
 | 
					  if (app_input.passes == 2)
 | 
				
			||||||
    stats_close(&app_input.rc_stats, 1);
 | 
					    stats_close(&app_input.rc_stats, 1);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (writer) {
 | 
					  if (writer) {
 | 
				
			||||||
    vpx_video_writer_close(writer);
 | 
					    vpx_video_writer_close(writer);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					#if OUTPUT_RC_STATS
 | 
				
			||||||
 | 
					  if (svc_ctx.output_rc_stat) {
 | 
				
			||||||
 | 
					    for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					      vpx_video_writer_close(outfile[tl]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  vpx_img_free(&raw);
 | 
					  vpx_img_free(&raw);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // display average size, psnr
 | 
					  // display average size, psnr
 | 
				
			||||||
  printf("%s", vpx_svc_dump_statistics(&svc_ctx));
 | 
					  printf("%s", vpx_svc_dump_statistics(&svc_ctx));
 | 
				
			||||||
 | 
					 | 
				
			||||||
  vpx_svc_release(&svc_ctx);
 | 
					  vpx_svc_release(&svc_ctx);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return EXIT_SUCCESS;
 | 
					  return EXIT_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,13 +85,13 @@ static void set_rate_control_metrics(struct RateControlMetrics *rc,
 | 
				
			|||||||
  // per-frame-bandwidth, for the rate control encoding stats below.
 | 
					  // per-frame-bandwidth, for the rate control encoding stats below.
 | 
				
			||||||
  const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
 | 
					  const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
 | 
				
			||||||
  rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
 | 
					  rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
 | 
				
			||||||
  rc->layer_pfb[0] = 1000.0 * cfg->ts_target_bitrate[0] /
 | 
					  rc->layer_pfb[0] = 1000.0 * cfg->layer_target_bitrate[0] /
 | 
				
			||||||
      rc->layer_framerate[0];
 | 
					      rc->layer_framerate[0];
 | 
				
			||||||
  for (i = 0; i < cfg->ts_number_layers; ++i) {
 | 
					  for (i = 0; i < cfg->ts_number_layers; ++i) {
 | 
				
			||||||
    if (i > 0) {
 | 
					    if (i > 0) {
 | 
				
			||||||
      rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
 | 
					      rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
 | 
				
			||||||
      rc->layer_pfb[i] = 1000.0 *
 | 
					      rc->layer_pfb[i] = 1000.0 *
 | 
				
			||||||
          (cfg->ts_target_bitrate[i] - cfg->ts_target_bitrate[i - 1]) /
 | 
					          (cfg->layer_target_bitrate[i] - cfg->layer_target_bitrate[i - 1]) /
 | 
				
			||||||
          (rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
 | 
					          (rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rc->layer_input_frames[i] = 0;
 | 
					    rc->layer_input_frames[i] = 0;
 | 
				
			||||||
@@ -128,7 +128,7 @@ static void printout_rate_control_summary(struct RateControlMetrics *rc,
 | 
				
			|||||||
    rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
 | 
					    rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
 | 
				
			||||||
        rc->layer_enc_frames[i];
 | 
					        rc->layer_enc_frames[i];
 | 
				
			||||||
    printf("For layer#: %d \n", i);
 | 
					    printf("For layer#: %d \n", i);
 | 
				
			||||||
    printf("Bitrate (target vs actual): %d %f \n", cfg->ts_target_bitrate[i],
 | 
					    printf("Bitrate (target vs actual): %d %f \n", cfg->layer_target_bitrate[i],
 | 
				
			||||||
           rc->layer_encoding_bitrate[i]);
 | 
					           rc->layer_encoding_bitrate[i]);
 | 
				
			||||||
    printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
 | 
					    printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
 | 
				
			||||||
           rc->layer_avg_frame_size[i]);
 | 
					           rc->layer_avg_frame_size[i]);
 | 
				
			||||||
@@ -597,7 +597,7 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
  for (i = min_args_base;
 | 
					  for (i = min_args_base;
 | 
				
			||||||
       (int)i < min_args_base + mode_to_num_layers[layering_mode];
 | 
					       (int)i < min_args_base + mode_to_num_layers[layering_mode];
 | 
				
			||||||
       ++i) {
 | 
					       ++i) {
 | 
				
			||||||
    cfg.ts_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
 | 
					    cfg.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Real time parameters.
 | 
					  // Real time parameters.
 | 
				
			||||||
@@ -625,6 +625,8 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
  // Disable automatic keyframe placement.
 | 
					  // Disable automatic keyframe placement.
 | 
				
			||||||
  cfg.kf_min_dist = cfg.kf_max_dist = 3000;
 | 
					  cfg.kf_min_dist = cfg.kf_max_dist = 3000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  set_temporal_layer_pattern(layering_mode,
 | 
					  set_temporal_layer_pattern(layering_mode,
 | 
				
			||||||
                             &cfg,
 | 
					                             &cfg,
 | 
				
			||||||
                             layer_flags,
 | 
					                             layer_flags,
 | 
				
			||||||
@@ -633,8 +635,8 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
  set_rate_control_metrics(&rc, &cfg);
 | 
					  set_rate_control_metrics(&rc, &cfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Target bandwidth for the whole stream.
 | 
					  // Target bandwidth for the whole stream.
 | 
				
			||||||
  // Set to ts_target_bitrate for highest layer (total bitrate).
 | 
					  // Set to layer_target_bitrate for highest layer (total bitrate).
 | 
				
			||||||
  cfg.rc_target_bitrate = cfg.ts_target_bitrate[cfg.ts_number_layers - 1];
 | 
					  cfg.rc_target_bitrate = cfg.layer_target_bitrate[cfg.ts_number_layers - 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Open input file.
 | 
					  // Open input file.
 | 
				
			||||||
  if (!(infile = fopen(argv[1], "rb"))) {
 | 
					  if (!(infile = fopen(argv[1], "rb"))) {
 | 
				
			||||||
@@ -677,6 +679,9 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
    vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
 | 
					    vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
 | 
				
			||||||
    vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
 | 
					    vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
 | 
				
			||||||
  } else if (strncmp(encoder->name, "vp9", 3) == 0) {
 | 
					  } else if (strncmp(encoder->name, "vp9", 3) == 0) {
 | 
				
			||||||
 | 
					#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
 | 
				
			||||||
 | 
					    vpx_svc_extra_cfg_t svc_params;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
      vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
 | 
					      vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
 | 
				
			||||||
      vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
 | 
					      vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
 | 
				
			||||||
      vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
 | 
					      vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
 | 
				
			||||||
@@ -685,6 +690,15 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
      vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
 | 
					      vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
 | 
				
			||||||
      if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) {
 | 
					      if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) {
 | 
				
			||||||
        die_codec(&codec, "Failed to set SVC");
 | 
					        die_codec(&codec, "Failed to set SVC");
 | 
				
			||||||
 | 
					#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
 | 
				
			||||||
 | 
					      for (i = 0; i < cfg.ts_number_layers; ++i) {
 | 
				
			||||||
 | 
					        svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
 | 
				
			||||||
 | 
					        svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      svc_params.scaling_factor_num[0] = cfg.g_h;
 | 
				
			||||||
 | 
					      svc_params.scaling_factor_den[0] = cfg.g_h;
 | 
				
			||||||
 | 
					      vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (strncmp(encoder->name, "vp8", 3) == 0) {
 | 
					  if (strncmp(encoder->name, "vp8", 3) == 0) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@
 | 
				
			|||||||
#include "test/i420_video_source.h"
 | 
					#include "test/i420_video_source.h"
 | 
				
			||||||
#include "test/util.h"
 | 
					#include "test/util.h"
 | 
				
			||||||
#include "test/y4m_video_source.h"
 | 
					#include "test/y4m_video_source.h"
 | 
				
			||||||
 | 
					#include "vpx/vpx_codec.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -565,6 +566,8 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
 | 
				
			|||||||
  cfg_.ts_rate_decimator[0] = 2;
 | 
					  cfg_.ts_rate_decimator[0] = 2;
 | 
				
			||||||
  cfg_.ts_rate_decimator[1] = 1;
 | 
					  cfg_.ts_rate_decimator[1] = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (deadline_ == VPX_DL_REALTIME)
 | 
					  if (deadline_ == VPX_DL_REALTIME)
 | 
				
			||||||
    cfg_.g_error_resilient = 1;
 | 
					    cfg_.g_error_resilient = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -574,14 +577,14 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
 | 
				
			|||||||
    cfg_.rc_target_bitrate = i;
 | 
					    cfg_.rc_target_bitrate = i;
 | 
				
			||||||
    ResetModel();
 | 
					    ResetModel();
 | 
				
			||||||
    // 60-40 bitrate allocation for 2 temporal layers.
 | 
					    // 60-40 bitrate allocation for 2 temporal layers.
 | 
				
			||||||
    cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
 | 
					    cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
 | 
				
			||||||
    cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
 | 
					    cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
 | 
				
			||||||
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
					    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
				
			||||||
    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
 | 
					    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
 | 
				
			||||||
      ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.85)
 | 
					      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
 | 
				
			||||||
          << " The datarate for the file is lower than target by too much, "
 | 
					          << " The datarate for the file is lower than target by too much, "
 | 
				
			||||||
              "for layer: " << j;
 | 
					              "for layer: " << j;
 | 
				
			||||||
      ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.15)
 | 
					      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
 | 
				
			||||||
          << " The datarate for the file is greater than target by too much, "
 | 
					          << " The datarate for the file is greater than target by too much, "
 | 
				
			||||||
              "for layer: " << j;
 | 
					              "for layer: " << j;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -606,25 +609,27 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
 | 
				
			|||||||
  cfg_.ts_rate_decimator[1] = 2;
 | 
					  cfg_.ts_rate_decimator[1] = 2;
 | 
				
			||||||
  cfg_.ts_rate_decimator[2] = 1;
 | 
					  cfg_.ts_rate_decimator[2] = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
 | 
					  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
 | 
				
			||||||
                                       30, 1, 0, 200);
 | 
					                                       30, 1, 0, 200);
 | 
				
			||||||
  for (int i = 200; i <= 800; i += 200) {
 | 
					  for (int i = 200; i <= 800; i += 200) {
 | 
				
			||||||
    cfg_.rc_target_bitrate = i;
 | 
					    cfg_.rc_target_bitrate = i;
 | 
				
			||||||
    ResetModel();
 | 
					    ResetModel();
 | 
				
			||||||
    // 40-20-40 bitrate allocation for 3 temporal layers.
 | 
					    // 40-20-40 bitrate allocation for 3 temporal layers.
 | 
				
			||||||
    cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
 | 
					    cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
 | 
				
			||||||
    cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
 | 
					    cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
 | 
				
			||||||
    cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
 | 
					    cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
 | 
				
			||||||
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
					    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
				
			||||||
    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
 | 
					    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
 | 
				
			||||||
      // TODO(yaowu): Work out more stable rc control strategy and
 | 
					      // TODO(yaowu): Work out more stable rc control strategy and
 | 
				
			||||||
      //              Adjust the thresholds to be tighter than .75.
 | 
					      //              Adjust the thresholds to be tighter than .75.
 | 
				
			||||||
      ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
 | 
					      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
 | 
				
			||||||
          << " The datarate for the file is lower than target by too much, "
 | 
					          << " The datarate for the file is lower than target by too much, "
 | 
				
			||||||
              "for layer: " << j;
 | 
					              "for layer: " << j;
 | 
				
			||||||
      // TODO(yaowu): Work out more stable rc control strategy and
 | 
					      // TODO(yaowu): Work out more stable rc control strategy and
 | 
				
			||||||
      //              Adjust the thresholds to be tighter than 1.25.
 | 
					      //              Adjust the thresholds to be tighter than 1.25.
 | 
				
			||||||
      ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
 | 
					      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
 | 
				
			||||||
          << " The datarate for the file is greater than target by too much, "
 | 
					          << " The datarate for the file is greater than target by too much, "
 | 
				
			||||||
              "for layer: " << j;
 | 
					              "for layer: " << j;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -652,20 +657,22 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
 | 
				
			|||||||
  cfg_.ts_rate_decimator[1] = 2;
 | 
					  cfg_.ts_rate_decimator[1] = 2;
 | 
				
			||||||
  cfg_.ts_rate_decimator[2] = 1;
 | 
					  cfg_.ts_rate_decimator[2] = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
 | 
					  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
 | 
				
			||||||
                                       30, 1, 0, 200);
 | 
					                                       30, 1, 0, 200);
 | 
				
			||||||
  cfg_.rc_target_bitrate = 200;
 | 
					  cfg_.rc_target_bitrate = 200;
 | 
				
			||||||
  ResetModel();
 | 
					  ResetModel();
 | 
				
			||||||
  // 40-20-40 bitrate allocation for 3 temporal layers.
 | 
					  // 40-20-40 bitrate allocation for 3 temporal layers.
 | 
				
			||||||
  cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
 | 
					  cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
 | 
				
			||||||
  cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
 | 
					  cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
 | 
				
			||||||
  cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
 | 
					  cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
 | 
				
			||||||
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
					  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
				
			||||||
  for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
 | 
					  for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
 | 
				
			||||||
    ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.85)
 | 
					    ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
 | 
				
			||||||
        << " The datarate for the file is lower than target by too much, "
 | 
					        << " The datarate for the file is lower than target by too much, "
 | 
				
			||||||
            "for layer: " << j;
 | 
					            "for layer: " << j;
 | 
				
			||||||
    ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.15)
 | 
					    ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
 | 
				
			||||||
        << " The datarate for the file is greater than target by too much, "
 | 
					        << " The datarate for the file is greater than target by too much, "
 | 
				
			||||||
            "for layer: " << j;
 | 
					            "for layer: " << j;
 | 
				
			||||||
    // Expect some frame drops in this test: for this 200 frames test,
 | 
					    // Expect some frame drops in this test: for this 200 frames test,
 | 
				
			||||||
@@ -737,9 +744,180 @@ TEST_P(DatarateTestVP9Large, DenoiserOffOn) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif  // CONFIG_VP9_TEMPORAL_DENOISING
 | 
					#endif  // CONFIG_VP9_TEMPORAL_DENOISING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
 | 
				
			||||||
 | 
					    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {}
 | 
				
			||||||
 | 
					  virtual ~DatarateOnePassCbrSvc() {}
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  virtual void SetUp() {
 | 
				
			||||||
 | 
					    InitializeConfig();
 | 
				
			||||||
 | 
					    SetMode(GET_PARAM(1));
 | 
				
			||||||
 | 
					    speed_setting_ = GET_PARAM(2);
 | 
				
			||||||
 | 
					    ResetModel();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  virtual void ResetModel() {
 | 
				
			||||||
 | 
					    last_pts_ = 0;
 | 
				
			||||||
 | 
					    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
 | 
				
			||||||
 | 
					    frame_number_ = 0;
 | 
				
			||||||
 | 
					    first_drop_ = 0;
 | 
				
			||||||
 | 
					    bits_total_ = 0;
 | 
				
			||||||
 | 
					    duration_ = 0.0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  virtual void BeginPassHook(unsigned int /*pass*/) {
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
 | 
				
			||||||
 | 
					                                  ::libvpx_test::Encoder *encoder) {
 | 
				
			||||||
 | 
					    if (video->frame() == 0) {
 | 
				
			||||||
 | 
					      int i;
 | 
				
			||||||
 | 
					      for (i = 0; i < 2; ++i) {
 | 
				
			||||||
 | 
					        svc_params_.max_quantizers[i] = 63;
 | 
				
			||||||
 | 
					        svc_params_.min_quantizers[i] = 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      svc_params_.scaling_factor_num[0] = 144;
 | 
				
			||||||
 | 
					      svc_params_.scaling_factor_den[0] = 288;
 | 
				
			||||||
 | 
					      svc_params_.scaling_factor_num[1] = 288;
 | 
				
			||||||
 | 
					      svc_params_.scaling_factor_den[1] = 288;
 | 
				
			||||||
 | 
					      encoder->Control(VP9E_SET_SVC, 1);
 | 
				
			||||||
 | 
					#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
 | 
				
			||||||
 | 
					      encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
 | 
				
			||||||
 | 
					      encoder->Control(VP9E_SET_TILE_COLUMNS, 0);
 | 
				
			||||||
 | 
					      encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const vpx_rational_t tb = video->timebase();
 | 
				
			||||||
 | 
					    timebase_ = static_cast<double>(tb.num) / tb.den;
 | 
				
			||||||
 | 
					    duration_ = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
 | 
				
			||||||
 | 
					    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
 | 
				
			||||||
 | 
					    if (last_pts_ == 0)
 | 
				
			||||||
 | 
					      duration = 1;
 | 
				
			||||||
 | 
					    bits_in_buffer_model_ += static_cast<int64_t>(
 | 
				
			||||||
 | 
					        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
 | 
				
			||||||
 | 
					    const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
 | 
				
			||||||
 | 
					                         ? true: false;
 | 
				
			||||||
 | 
					    if (!key_frame) {
 | 
				
			||||||
 | 
					      ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
 | 
				
			||||||
 | 
					          << pkt->data.frame.pts;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
 | 
				
			||||||
 | 
					    bits_in_buffer_model_ -= frame_size_in_bits;
 | 
				
			||||||
 | 
					    bits_total_ += frame_size_in_bits;
 | 
				
			||||||
 | 
					    if (!first_drop_ && duration > 1)
 | 
				
			||||||
 | 
					      first_drop_ = last_pts_ + 1;
 | 
				
			||||||
 | 
					    last_pts_ = pkt->data.frame.pts;
 | 
				
			||||||
 | 
					    bits_in_last_frame_ = frame_size_in_bits;
 | 
				
			||||||
 | 
					    ++frame_number_;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  virtual void EndPassHook(void) {
 | 
				
			||||||
 | 
					    if (bits_total_) {
 | 
				
			||||||
 | 
					      const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
 | 
				
			||||||
 | 
					      duration_ = (last_pts_ + 1) * timebase_;
 | 
				
			||||||
 | 
					      effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
 | 
				
			||||||
 | 
					          / (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
 | 
				
			||||||
 | 
					      file_datarate_ = file_size_in_kb / duration_;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  vpx_codec_pts_t last_pts_;
 | 
				
			||||||
 | 
					  int64_t bits_in_buffer_model_;
 | 
				
			||||||
 | 
					  double timebase_;
 | 
				
			||||||
 | 
					  int frame_number_;
 | 
				
			||||||
 | 
					  vpx_codec_pts_t first_drop_;
 | 
				
			||||||
 | 
					  int64_t bits_total_;
 | 
				
			||||||
 | 
					  double duration_;
 | 
				
			||||||
 | 
					  double file_datarate_;
 | 
				
			||||||
 | 
					  double effective_datarate_;
 | 
				
			||||||
 | 
					  size_t bits_in_last_frame_;
 | 
				
			||||||
 | 
					  vpx_svc_extra_cfg_t svc_params_;
 | 
				
			||||||
 | 
					  int speed_setting_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg,
 | 
				
			||||||
 | 
					    const vpx_svc_extra_cfg_t *svc_params,
 | 
				
			||||||
 | 
					    int spatial_layers,
 | 
				
			||||||
 | 
					    int temporal_layers,
 | 
				
			||||||
 | 
					    int temporal_layering_mode,
 | 
				
			||||||
 | 
					    unsigned int total_rate) {
 | 
				
			||||||
 | 
					  int sl, spatial_layer_target;
 | 
				
			||||||
 | 
					  float total = 0;
 | 
				
			||||||
 | 
					  float alloc_ratio[VPX_MAX_LAYERS] = {0};
 | 
				
			||||||
 | 
					  for (sl = 0; sl < spatial_layers; ++sl) {
 | 
				
			||||||
 | 
					    if (svc_params->scaling_factor_den[sl] > 0) {
 | 
				
			||||||
 | 
					      alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] *
 | 
				
			||||||
 | 
					          1.0 / svc_params->scaling_factor_den[sl]);
 | 
				
			||||||
 | 
					      total += alloc_ratio[sl];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  for (sl = 0; sl < spatial_layers; ++sl) {
 | 
				
			||||||
 | 
					    enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
 | 
				
			||||||
 | 
					        (unsigned int)(enc_cfg->rc_target_bitrate *
 | 
				
			||||||
 | 
					            alloc_ratio[sl] / total);
 | 
				
			||||||
 | 
					    const int index = sl * temporal_layers;
 | 
				
			||||||
 | 
					    if (temporal_layering_mode == 3) {
 | 
				
			||||||
 | 
					      enc_cfg->layer_target_bitrate[index] =
 | 
				
			||||||
 | 
					          spatial_layer_target >> 1;
 | 
				
			||||||
 | 
					      enc_cfg->layer_target_bitrate[index + 1] =
 | 
				
			||||||
 | 
					          (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
 | 
				
			||||||
 | 
					      enc_cfg->layer_target_bitrate[index + 2] =
 | 
				
			||||||
 | 
					          spatial_layer_target;
 | 
				
			||||||
 | 
					    } else if (temporal_layering_mode == 2) {
 | 
				
			||||||
 | 
					      enc_cfg->layer_target_bitrate[index] =
 | 
				
			||||||
 | 
					          spatial_layer_target * 2 / 3;
 | 
				
			||||||
 | 
					      enc_cfg->layer_target_bitrate[index + 1] =
 | 
				
			||||||
 | 
					          spatial_layer_target;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
 | 
				
			||||||
 | 
					// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
 | 
				
			||||||
 | 
					// 3 temporal layers.
 | 
				
			||||||
 | 
					TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc) {
 | 
				
			||||||
 | 
					  cfg_.rc_buf_initial_sz = 500;
 | 
				
			||||||
 | 
					  cfg_.rc_buf_optimal_sz = 500;
 | 
				
			||||||
 | 
					  cfg_.rc_buf_sz = 1000;
 | 
				
			||||||
 | 
					  cfg_.rc_min_quantizer = 0;
 | 
				
			||||||
 | 
					  cfg_.rc_max_quantizer = 63;
 | 
				
			||||||
 | 
					  cfg_.rc_end_usage = VPX_CBR;
 | 
				
			||||||
 | 
					  cfg_.g_lag_in_frames = 0;
 | 
				
			||||||
 | 
					  cfg_.ss_number_layers = 2;
 | 
				
			||||||
 | 
					  cfg_.ts_number_layers = 3;
 | 
				
			||||||
 | 
					  cfg_.ts_rate_decimator[0] = 4;
 | 
				
			||||||
 | 
					  cfg_.ts_rate_decimator[1] = 2;
 | 
				
			||||||
 | 
					  cfg_.ts_rate_decimator[2] = 1;
 | 
				
			||||||
 | 
					  cfg_.g_error_resilient = 1;
 | 
				
			||||||
 | 
					  cfg_.temporal_layering_mode = 3;
 | 
				
			||||||
 | 
					  svc_params_.scaling_factor_num[0] = 144;
 | 
				
			||||||
 | 
					  svc_params_.scaling_factor_den[0] = 288;
 | 
				
			||||||
 | 
					  svc_params_.scaling_factor_num[1] = 288;
 | 
				
			||||||
 | 
					  svc_params_.scaling_factor_den[1] = 288;
 | 
				
			||||||
 | 
					  // TODO(wonkap/marpan): No frame drop for now, we need to implement correct
 | 
				
			||||||
 | 
					  // frame dropping for SVC.
 | 
				
			||||||
 | 
					  cfg_.rc_dropframe_thresh = 0;
 | 
				
			||||||
 | 
					  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
 | 
				
			||||||
 | 
					                                       30, 1, 0, 200);
 | 
				
			||||||
 | 
					  // TODO(wonkap/marpan): Check that effective_datarate for each layer hits the
 | 
				
			||||||
 | 
					  // layer target_bitrate. Also check if test can pass at lower bitrate (~200k).
 | 
				
			||||||
 | 
					  for (int i = 400; i <= 800; i += 200) {
 | 
				
			||||||
 | 
					    cfg_.rc_target_bitrate = i;
 | 
				
			||||||
 | 
					    ResetModel();
 | 
				
			||||||
 | 
					    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
 | 
				
			||||||
 | 
					        cfg_.ts_number_layers, cfg_.temporal_layering_mode,
 | 
				
			||||||
 | 
					        cfg_.rc_target_bitrate);
 | 
				
			||||||
 | 
					    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 | 
				
			||||||
 | 
					    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.85)
 | 
				
			||||||
 | 
					            << " The datarate for the file exceeds the target by too much!";
 | 
				
			||||||
 | 
					    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
 | 
				
			||||||
 | 
					        << " The datarate for the file is lower than the target by too much!";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES);
 | 
					VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES);
 | 
				
			||||||
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
 | 
					VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
 | 
				
			||||||
                          ::testing::Values(::libvpx_test::kOnePassGood,
 | 
					                          ::testing::Values(::libvpx_test::kOnePassGood,
 | 
				
			||||||
                                            ::libvpx_test::kRealTime),
 | 
					                                            ::libvpx_test::kRealTime),
 | 
				
			||||||
                          ::testing::Range(2, 7));
 | 
					                          ::testing::Range(2, 7));
 | 
				
			||||||
 | 
					VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
 | 
				
			||||||
 | 
					                          ::testing::Values(::libvpx_test::kRealTime),
 | 
				
			||||||
 | 
					                          ::testing::Range(5, 8));
 | 
				
			||||||
}  // namespace
 | 
					}  // namespace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,6 +133,10 @@ class Encoder {
 | 
				
			|||||||
    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
 | 
					    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
 | 
				
			||||||
 | 
					    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
 | 
				
			||||||
 | 
					    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
 | 
					#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
 | 
				
			||||||
  void Control(int ctrl_id, vpx_active_map_t *arg) {
 | 
					  void Control(int ctrl_id, vpx_active_map_t *arg) {
 | 
				
			||||||
    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
 | 
					    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -453,6 +453,7 @@ TEST_F(SvcTest, OnePassEncodeOneFrame) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST_F(SvcTest, OnePassEncodeThreeFrames) {
 | 
					TEST_F(SvcTest, OnePassEncodeThreeFrames) {
 | 
				
			||||||
  codec_enc_.g_pass = VPX_RC_ONE_PASS;
 | 
					  codec_enc_.g_pass = VPX_RC_ONE_PASS;
 | 
				
			||||||
 | 
					  codec_enc_.g_lag_in_frames = 0;
 | 
				
			||||||
  vpx_fixed_buf outputs[3];
 | 
					  vpx_fixed_buf outputs[3];
 | 
				
			||||||
  memset(&outputs[0], 0, sizeof(outputs));
 | 
					  memset(&outputs[0], 0, sizeof(outputs));
 | 
				
			||||||
  Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
 | 
					  Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -687,17 +687,28 @@ static int choose_partitioning(VP9_COMP *cpi,
 | 
				
			|||||||
  s = x->plane[0].src.buf;
 | 
					  s = x->plane[0].src.buf;
 | 
				
			||||||
  sp = x->plane[0].src.stride;
 | 
					  sp = x->plane[0].src.stride;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!is_key_frame) {
 | 
					  if (!is_key_frame && !(is_one_pass_cbr_svc(cpi) &&
 | 
				
			||||||
 | 
					      cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)) {
 | 
				
			||||||
 | 
					    // In the case of spatial/temporal scalable coding, the assumption here is
 | 
				
			||||||
 | 
					    // that the temporal reference frame will always be of type LAST_FRAME.
 | 
				
			||||||
 | 
					    // TODO(marpan): If that assumption is broken, we need to revisit this code.
 | 
				
			||||||
    MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
 | 
					    MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
 | 
				
			||||||
    unsigned int uv_sad;
 | 
					    unsigned int uv_sad;
 | 
				
			||||||
    const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
 | 
					    const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const YV12_BUFFER_CONFIG *yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
 | 
					    const YV12_BUFFER_CONFIG *yv12_g = NULL;
 | 
				
			||||||
    unsigned int y_sad, y_sad_g;
 | 
					    unsigned int y_sad, y_sad_g;
 | 
				
			||||||
    const BLOCK_SIZE bsize = BLOCK_32X32
 | 
					    const BLOCK_SIZE bsize = BLOCK_32X32
 | 
				
			||||||
        + (mi_col + 4 < cm->mi_cols) * 2 + (mi_row + 4 < cm->mi_rows);
 | 
					        + (mi_col + 4 < cm->mi_cols) * 2 + (mi_row + 4 < cm->mi_rows);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(yv12 != NULL);
 | 
					    assert(yv12 != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!(is_one_pass_cbr_svc(cpi) && cpi->svc.spatial_layer_id)) {
 | 
				
			||||||
 | 
					      // For now, GOLDEN will not be used for non-zero spatial layers, since
 | 
				
			||||||
 | 
					      // it may not be a temporal reference.
 | 
				
			||||||
 | 
					      yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (yv12_g && yv12_g != yv12) {
 | 
					    if (yv12_g && yv12_g != yv12) {
 | 
				
			||||||
      vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
 | 
					      vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
 | 
				
			||||||
                           &cm->frame_refs[GOLDEN_FRAME - 1].sf);
 | 
					                           &cm->frame_refs[GOLDEN_FRAME - 1].sf);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -756,6 +756,8 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
 | 
				
			|||||||
  cm->height = oxcf->height;
 | 
					  cm->height = oxcf->height;
 | 
				
			||||||
  vp9_alloc_compressor_data(cpi);
 | 
					  vp9_alloc_compressor_data(cpi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cpi->svc.temporal_layering_mode = oxcf->temporal_layering_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Single thread case: use counts in common.
 | 
					  // Single thread case: use counts in common.
 | 
				
			||||||
  cpi->td.counts = &cm->counts;
 | 
					  cpi->td.counts = &cm->counts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2265,8 +2267,9 @@ static void generate_psnr_packet(VP9_COMP *cpi) {
 | 
				
			|||||||
    pkt.data.psnr.psnr[i] = psnr.psnr[i];
 | 
					    pkt.data.psnr.psnr[i] = psnr.psnr[i];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  pkt.kind = VPX_CODEC_PSNR_PKT;
 | 
					  pkt.kind = VPX_CODEC_PSNR_PKT;
 | 
				
			||||||
  if (is_two_pass_svc(cpi))
 | 
					  if (cpi->use_svc)
 | 
				
			||||||
    cpi->svc.layer_context[cpi->svc.spatial_layer_id].psnr_pkt = pkt.data.psnr;
 | 
					    cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
 | 
					        cpi->svc.number_temporal_layers].psnr_pkt = pkt.data.psnr;
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
 | 
					    vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -3667,9 +3670,11 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  cm->prev_frame = cm->cur_frame;
 | 
					  cm->prev_frame = cm->cur_frame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (is_two_pass_svc(cpi))
 | 
					  if (cpi->use_svc)
 | 
				
			||||||
    cpi->svc.layer_context[cpi->svc.spatial_layer_id].last_frame_type =
 | 
					    cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
        cm->frame_type;
 | 
					                           cpi->svc.number_temporal_layers +
 | 
				
			||||||
 | 
					                           cpi->svc.temporal_layer_id].last_frame_type =
 | 
				
			||||||
 | 
					                               cm->frame_type;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
 | 
					static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
 | 
				
			||||||
@@ -3930,6 +3935,8 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    if (oxcf->pass == 2)
 | 
					    if (oxcf->pass == 2)
 | 
				
			||||||
      vp9_restore_layer_context(cpi);
 | 
					      vp9_restore_layer_context(cpi);
 | 
				
			||||||
 | 
					  } else if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
 | 
					    vp9_one_pass_cbr_svc_start_layer(cpi);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vpx_usec_timer_start(&cmptimer);
 | 
					  vpx_usec_timer_start(&cmptimer);
 | 
				
			||||||
@@ -3948,9 +3955,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
				
			|||||||
  // Normal defaults
 | 
					  // Normal defaults
 | 
				
			||||||
  cm->reset_frame_context = 0;
 | 
					  cm->reset_frame_context = 0;
 | 
				
			||||||
  cm->refresh_frame_context = 1;
 | 
					  cm->refresh_frame_context = 1;
 | 
				
			||||||
  cpi->refresh_last_frame = 1;
 | 
					  if (!is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
  cpi->refresh_golden_frame = 0;
 | 
					    cpi->refresh_last_frame = 1;
 | 
				
			||||||
  cpi->refresh_alt_ref_frame = 0;
 | 
					    cpi->refresh_golden_frame = 0;
 | 
				
			||||||
 | 
					    cpi->refresh_alt_ref_frame = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Should we encode an arf frame.
 | 
					  // Should we encode an arf frame.
 | 
				
			||||||
  arf_src_index = get_arf_src_index(cpi);
 | 
					  arf_src_index = get_arf_src_index(cpi);
 | 
				
			||||||
@@ -4006,12 +4015,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Read in the source frame.
 | 
					    // Read in the source frame.
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					    if (cpi->use_svc)
 | 
				
			||||||
    if (is_two_pass_svc(cpi))
 | 
					 | 
				
			||||||
      source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
 | 
					      source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      source = vp9_lookahead_pop(cpi->lookahead, flush);
 | 
					      source = vp9_lookahead_pop(cpi->lookahead, flush);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (source != NULL) {
 | 
					    if (source != NULL) {
 | 
				
			||||||
      cm->show_frame = 1;
 | 
					      cm->show_frame = 1;
 | 
				
			||||||
      cm->intra_only = 0;
 | 
					      cm->intra_only = 0;
 | 
				
			||||||
@@ -4060,8 +4068,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
				
			|||||||
    adjust_frame_rate(cpi, source);
 | 
					    adjust_frame_rate(cpi, source);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (cpi->svc.number_temporal_layers > 1 &&
 | 
					  if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
      oxcf->rc_mode == VPX_CBR) {
 | 
					 | 
				
			||||||
    vp9_update_temporal_layer_framerate(cpi);
 | 
					    vp9_update_temporal_layer_framerate(cpi);
 | 
				
			||||||
    vp9_restore_layer_context(cpi);
 | 
					    vp9_restore_layer_context(cpi);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -4143,11 +4150,10 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Save layer specific state.
 | 
					  // Save layer specific state.
 | 
				
			||||||
  if ((cpi->svc.number_temporal_layers > 1 &&
 | 
					  if (is_one_pass_cbr_svc(cpi) ||
 | 
				
			||||||
       oxcf->rc_mode == VPX_CBR) ||
 | 
					        ((cpi->svc.number_temporal_layers > 1 ||
 | 
				
			||||||
      ((cpi->svc.number_temporal_layers > 1 ||
 | 
					          cpi->svc.number_spatial_layers > 1) &&
 | 
				
			||||||
        cpi->svc.number_spatial_layers > 1) &&
 | 
					         oxcf->pass == 2)) {
 | 
				
			||||||
       oxcf->pass == 2)) {
 | 
					 | 
				
			||||||
    vp9_save_layer_context(cpi);
 | 
					    vp9_save_layer_context(cpi);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4343,6 +4349,12 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
 | 
				
			|||||||
      // May need the empty frame after an visible frame.
 | 
					      // May need the empty frame after an visible frame.
 | 
				
			||||||
      cpi->svc.encode_empty_frame_state = NEED_TO_ENCODE;
 | 
					      cpi->svc.encode_empty_frame_state = NEED_TO_ENCODE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  } else if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
 | 
					    if (cm->show_frame) {
 | 
				
			||||||
 | 
					      ++cpi->svc.spatial_layer_to_encode;
 | 
				
			||||||
 | 
					      if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
 | 
				
			||||||
 | 
					        cpi->svc.spatial_layer_to_encode = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,10 +194,10 @@ typedef struct VP9EncoderConfig {
 | 
				
			|||||||
  int ss_number_layers;  // Number of spatial layers.
 | 
					  int ss_number_layers;  // Number of spatial layers.
 | 
				
			||||||
  int ts_number_layers;  // Number of temporal layers.
 | 
					  int ts_number_layers;  // Number of temporal layers.
 | 
				
			||||||
  // Bitrate allocation for spatial layers.
 | 
					  // Bitrate allocation for spatial layers.
 | 
				
			||||||
 | 
					  int layer_target_bitrate[VPX_MAX_LAYERS];
 | 
				
			||||||
  int ss_target_bitrate[VPX_SS_MAX_LAYERS];
 | 
					  int ss_target_bitrate[VPX_SS_MAX_LAYERS];
 | 
				
			||||||
  int ss_enable_auto_arf[VPX_SS_MAX_LAYERS];
 | 
					  int ss_enable_auto_arf[VPX_SS_MAX_LAYERS];
 | 
				
			||||||
  // Bitrate allocation (CBR mode) and framerate factor, for temporal layers.
 | 
					  // Bitrate allocation (CBR mode) and framerate factor, for temporal layers.
 | 
				
			||||||
  int ts_target_bitrate[VPX_TS_MAX_LAYERS];
 | 
					 | 
				
			||||||
  int ts_rate_decimator[VPX_TS_MAX_LAYERS];
 | 
					  int ts_rate_decimator[VPX_TS_MAX_LAYERS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int enable_auto_arf;
 | 
					  int enable_auto_arf;
 | 
				
			||||||
@@ -237,6 +237,7 @@ typedef struct VP9EncoderConfig {
 | 
				
			|||||||
  int use_highbitdepth;
 | 
					  int use_highbitdepth;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  vpx_color_space_t color_space;
 | 
					  vpx_color_space_t color_space;
 | 
				
			||||||
 | 
					  VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
 | 
				
			||||||
} VP9EncoderConfig;
 | 
					} VP9EncoderConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
 | 
					static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
 | 
				
			||||||
@@ -611,9 +612,11 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
 | 
				
			|||||||
void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags);
 | 
					void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static INLINE int is_two_pass_svc(const struct VP9_COMP *const cpi) {
 | 
					static INLINE int is_two_pass_svc(const struct VP9_COMP *const cpi) {
 | 
				
			||||||
  return cpi->use_svc &&
 | 
					  return cpi->use_svc && cpi->oxcf.pass != 0;
 | 
				
			||||||
         ((cpi->svc.number_spatial_layers > 1) ||
 | 
					}
 | 
				
			||||||
         (cpi->svc.number_temporal_layers > 1 && cpi->oxcf.pass != 0));
 | 
					
 | 
				
			||||||
 | 
					static INLINE int is_one_pass_cbr_svc(const struct VP9_COMP *const cpi) {
 | 
				
			||||||
 | 
					  return (cpi->use_svc && cpi->oxcf.pass == 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static INLINE int is_altref_enabled(const VP9_COMP *const cpi) {
 | 
					static INLINE int is_altref_enabled(const VP9_COMP *const cpi) {
 | 
				
			||||||
@@ -642,6 +645,8 @@ static INLINE int *cond_cost_list(const struct VP9_COMP *cpi, int *cost_list) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void vp9_new_framerate(VP9_COMP *cpi, double framerate);
 | 
					void vp9_new_framerate(VP9_COMP *cpi, double framerate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LAYER_IDS_TO_IDX(sl, tl, num_tl) ((sl) * (num_tl) + (tl))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}  // extern "C"
 | 
					}  // extern "C"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -234,13 +234,16 @@ int vp9_rc_clamp_iframe_target_size(const VP9_COMP *const cpi, int target) {
 | 
				
			|||||||
  return target;
 | 
					  return target;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Update the buffer level for higher layers, given the encoded current layer.
 | 
					// Update the buffer level for higher temporal layers, given the encoded current
 | 
				
			||||||
 | 
					// temporal layer.
 | 
				
			||||||
static void update_layer_buffer_level(SVC *svc, int encoded_frame_size) {
 | 
					static void update_layer_buffer_level(SVC *svc, int encoded_frame_size) {
 | 
				
			||||||
  int temporal_layer = 0;
 | 
					  int i = 0;
 | 
				
			||||||
  int current_temporal_layer = svc->temporal_layer_id;
 | 
					  int current_temporal_layer = svc->temporal_layer_id;
 | 
				
			||||||
  for (temporal_layer = current_temporal_layer + 1;
 | 
					  for (i = current_temporal_layer + 1;
 | 
				
			||||||
      temporal_layer < svc->number_temporal_layers; ++temporal_layer) {
 | 
					      i < svc->number_temporal_layers; ++i) {
 | 
				
			||||||
    LAYER_CONTEXT *lc = &svc->layer_context[temporal_layer];
 | 
					    const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id, i,
 | 
				
			||||||
 | 
					                                       svc->number_temporal_layers);
 | 
				
			||||||
 | 
					    LAYER_CONTEXT *lc = &svc->layer_context[layer];
 | 
				
			||||||
    RATE_CONTROL *lrc = &lc->rc;
 | 
					    RATE_CONTROL *lrc = &lc->rc;
 | 
				
			||||||
    int bits_off_for_this_layer = (int)(lc->target_bandwidth / lc->framerate -
 | 
					    int bits_off_for_this_layer = (int)(lc->target_bandwidth / lc->framerate -
 | 
				
			||||||
        encoded_frame_size);
 | 
					        encoded_frame_size);
 | 
				
			||||||
@@ -268,7 +271,7 @@ static void update_buffer_level(VP9_COMP *cpi, int encoded_frame_size) {
 | 
				
			|||||||
  rc->bits_off_target = MIN(rc->bits_off_target, rc->maximum_buffer_size);
 | 
					  rc->bits_off_target = MIN(rc->bits_off_target, rc->maximum_buffer_size);
 | 
				
			||||||
  rc->buffer_level = rc->bits_off_target;
 | 
					  rc->buffer_level = rc->bits_off_target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					  if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
    update_layer_buffer_level(&cpi->svc, encoded_frame_size);
 | 
					    update_layer_buffer_level(&cpi->svc, encoded_frame_size);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1418,13 +1421,14 @@ static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
 | 
				
			|||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    target = rc->avg_frame_bandwidth;
 | 
					    target = rc->avg_frame_bandwidth;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (svc->number_temporal_layers > 1 &&
 | 
					  if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
      oxcf->rc_mode == VPX_CBR) {
 | 
					 | 
				
			||||||
    // Note that for layers, avg_frame_bandwidth is the cumulative
 | 
					    // Note that for layers, avg_frame_bandwidth is the cumulative
 | 
				
			||||||
    // per-frame-bandwidth. For the target size of this frame, use the
 | 
					    // per-frame-bandwidth. For the target size of this frame, use the
 | 
				
			||||||
    // layer average frame size (i.e., non-cumulative per-frame-bw).
 | 
					    // layer average frame size (i.e., non-cumulative per-frame-bw).
 | 
				
			||||||
    int current_temporal_layer = svc->temporal_layer_id;
 | 
					    int layer =
 | 
				
			||||||
    const LAYER_CONTEXT *lc = &svc->layer_context[current_temporal_layer];
 | 
					        LAYER_IDS_TO_IDX(svc->spatial_layer_id,
 | 
				
			||||||
 | 
					            svc->temporal_layer_id, svc->number_temporal_layers);
 | 
				
			||||||
 | 
					    const LAYER_CONTEXT *lc = &svc->layer_context[layer];
 | 
				
			||||||
    target = lc->avg_frame_size;
 | 
					    target = lc->avg_frame_size;
 | 
				
			||||||
    min_frame_target = MAX(lc->avg_frame_size >> 4, FRAME_OVERHEAD_BITS);
 | 
					    min_frame_target = MAX(lc->avg_frame_size >> 4, FRAME_OVERHEAD_BITS);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1459,7 +1463,9 @@ static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
 | 
				
			|||||||
    if (svc->number_temporal_layers > 1 &&
 | 
					    if (svc->number_temporal_layers > 1 &&
 | 
				
			||||||
        oxcf->rc_mode == VPX_CBR) {
 | 
					        oxcf->rc_mode == VPX_CBR) {
 | 
				
			||||||
      // Use the layer framerate for temporal layers CBR mode.
 | 
					      // Use the layer framerate for temporal layers CBR mode.
 | 
				
			||||||
      const LAYER_CONTEXT *lc = &svc->layer_context[svc->temporal_layer_id];
 | 
					      const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id,
 | 
				
			||||||
 | 
					          svc->temporal_layer_id, svc->number_temporal_layers);
 | 
				
			||||||
 | 
					      const LAYER_CONTEXT *lc = &svc->layer_context[layer];
 | 
				
			||||||
      framerate = lc->framerate;
 | 
					      framerate = lc->framerate;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    kf_boost = MAX(kf_boost, (int)(2 * framerate - 16));
 | 
					    kf_boost = MAX(kf_boost, (int)(2 * framerate - 16));
 | 
				
			||||||
@@ -1472,10 +1478,27 @@ static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
 | 
				
			|||||||
  return vp9_rc_clamp_iframe_target_size(cpi, target);
 | 
					  return vp9_rc_clamp_iframe_target_size(cpi, target);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reset information needed to set proper reference frames and buffer updates
 | 
				
			||||||
 | 
					// for temporal layering. This is called when a key frame is encoded.
 | 
				
			||||||
 | 
					static void reset_temporal_layer_to_zero(VP9_COMP *cpi) {
 | 
				
			||||||
 | 
					  int sl;
 | 
				
			||||||
 | 
					  LAYER_CONTEXT *lc = NULL;
 | 
				
			||||||
 | 
					  cpi->svc.temporal_layer_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
 | 
				
			||||||
 | 
					    lc = &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
 | 
				
			||||||
 | 
					    lc->current_video_frame_in_layer = 0;
 | 
				
			||||||
 | 
					    lc->frames_from_key_frame = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vp9_rc_get_svc_params(VP9_COMP *cpi) {
 | 
					void vp9_rc_get_svc_params(VP9_COMP *cpi) {
 | 
				
			||||||
  VP9_COMMON *const cm = &cpi->common;
 | 
					  VP9_COMMON *const cm = &cpi->common;
 | 
				
			||||||
  RATE_CONTROL *const rc = &cpi->rc;
 | 
					  RATE_CONTROL *const rc = &cpi->rc;
 | 
				
			||||||
  int target = rc->avg_frame_bandwidth;
 | 
					  int target = rc->avg_frame_bandwidth;
 | 
				
			||||||
 | 
					  const int layer = LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id,
 | 
				
			||||||
 | 
					      cpi->svc.temporal_layer_id, cpi->svc.number_temporal_layers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ((cm->current_video_frame == 0) ||
 | 
					  if ((cm->current_video_frame == 0) ||
 | 
				
			||||||
      (cpi->frame_flags & FRAMEFLAGS_KEY) ||
 | 
					      (cpi->frame_flags & FRAMEFLAGS_KEY) ||
 | 
				
			||||||
      (cpi->oxcf.auto_key && (rc->frames_since_key %
 | 
					      (cpi->oxcf.auto_key && (rc->frames_since_key %
 | 
				
			||||||
@@ -1484,30 +1507,39 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
 | 
				
			|||||||
    rc->source_alt_ref_active = 0;
 | 
					    rc->source_alt_ref_active = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (is_two_pass_svc(cpi)) {
 | 
					    if (is_two_pass_svc(cpi)) {
 | 
				
			||||||
      cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame = 1;
 | 
					      cpi->svc.layer_context[layer].is_key_frame = 1;
 | 
				
			||||||
      cpi->ref_frame_flags &=
 | 
					      cpi->ref_frame_flags &=
 | 
				
			||||||
          (~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
 | 
					          (~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
 | 
				
			||||||
    }
 | 
					    } else if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
 | 
					      cpi->svc.layer_context[layer].is_key_frame = 1;
 | 
				
			||||||
    if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					      reset_temporal_layer_to_zero(cpi);
 | 
				
			||||||
 | 
					      cpi->ref_frame_flags &=
 | 
				
			||||||
 | 
					                (~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
 | 
				
			||||||
 | 
					      // Assumption here is that LAST_FRAME is being updated for a keyframe.
 | 
				
			||||||
 | 
					      // Thus no change in update flags.
 | 
				
			||||||
      target = calc_iframe_target_size_one_pass_cbr(cpi);
 | 
					      target = calc_iframe_target_size_one_pass_cbr(cpi);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    cm->frame_type = INTER_FRAME;
 | 
					    cm->frame_type = INTER_FRAME;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (is_two_pass_svc(cpi)) {
 | 
					    if (is_two_pass_svc(cpi)) {
 | 
				
			||||||
      LAYER_CONTEXT *lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
 | 
					      LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
 | 
				
			||||||
      if (cpi->svc.spatial_layer_id == 0) {
 | 
					      if (cpi->svc.spatial_layer_id == 0) {
 | 
				
			||||||
        lc->is_key_frame = 0;
 | 
					        lc->is_key_frame = 0;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        lc->is_key_frame = cpi->svc.layer_context[0].is_key_frame;
 | 
					        lc->is_key_frame =
 | 
				
			||||||
 | 
					            cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame;
 | 
				
			||||||
        if (lc->is_key_frame)
 | 
					        if (lc->is_key_frame)
 | 
				
			||||||
          cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
 | 
					          cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      cpi->ref_frame_flags &= (~VP9_ALT_FLAG);
 | 
					      cpi->ref_frame_flags &= (~VP9_ALT_FLAG);
 | 
				
			||||||
    }
 | 
					    } else if (is_one_pass_cbr_svc(cpi)) {
 | 
				
			||||||
 | 
					      LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
 | 
				
			||||||
    if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					      if (cpi->svc.spatial_layer_id == 0) {
 | 
				
			||||||
 | 
					        lc->is_key_frame = 0;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        lc->is_key_frame =
 | 
				
			||||||
 | 
					            cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      target = calc_pframe_target_size_one_pass_cbr(cpi);
 | 
					      target = calc_pframe_target_size_one_pass_cbr(cpi);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,83 +21,79 @@
 | 
				
			|||||||
void vp9_init_layer_context(VP9_COMP *const cpi) {
 | 
					void vp9_init_layer_context(VP9_COMP *const cpi) {
 | 
				
			||||||
  SVC *const svc = &cpi->svc;
 | 
					  SVC *const svc = &cpi->svc;
 | 
				
			||||||
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
 | 
					  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
 | 
				
			||||||
  int layer;
 | 
					  int sl, tl;
 | 
				
			||||||
  int layer_end;
 | 
					 | 
				
			||||||
  int alt_ref_idx = svc->number_spatial_layers;
 | 
					  int alt_ref_idx = svc->number_spatial_layers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  svc->spatial_layer_id = 0;
 | 
					  svc->spatial_layer_id = 0;
 | 
				
			||||||
  svc->temporal_layer_id = 0;
 | 
					  svc->temporal_layer_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					  if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
 | 
				
			||||||
    layer_end = svc->number_temporal_layers;
 | 
					    if (vp9_realloc_frame_buffer(&cpi->svc.empty_frame.img,
 | 
				
			||||||
  } else {
 | 
					                                 SMALL_FRAME_WIDTH, SMALL_FRAME_HEIGHT,
 | 
				
			||||||
    layer_end = svc->number_spatial_layers;
 | 
					                                 cpi->common.subsampling_x,
 | 
				
			||||||
 | 
					                                 cpi->common.subsampling_y,
 | 
				
			||||||
    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,
 | 
					 | 
				
			||||||
#if CONFIG_VP9_HIGHBITDEPTH
 | 
					#if CONFIG_VP9_HIGHBITDEPTH
 | 
				
			||||||
                                 cpi->common.use_highbitdepth,
 | 
					                                 cpi->common.use_highbitdepth,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
                                 VP9_ENC_BORDER_IN_PIXELS,
 | 
					                                 VP9_ENC_BORDER_IN_PIXELS,
 | 
				
			||||||
                                 cpi->common.byte_alignment,
 | 
					                                 cpi->common.byte_alignment,
 | 
				
			||||||
                                 NULL, NULL, NULL))
 | 
					                                 NULL, NULL, NULL))
 | 
				
			||||||
        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
 | 
					      vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
 | 
				
			||||||
                           "Failed to allocate empty frame for multiple frame "
 | 
					                         "Failed to allocate empty frame for multiple frame "
 | 
				
			||||||
                           "contexts");
 | 
					                         "contexts");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80,
 | 
					    memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80,
 | 
				
			||||||
             cpi->svc.empty_frame.img.buffer_alloc_sz);
 | 
					           cpi->svc.empty_frame.img.buffer_alloc_sz);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (layer = 0; layer < layer_end; ++layer) {
 | 
					  for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
 | 
				
			||||||
    LAYER_CONTEXT *const lc = &svc->layer_context[layer];
 | 
					    for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
 | 
				
			||||||
    RATE_CONTROL *const lrc = &lc->rc;
 | 
					      int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
 | 
				
			||||||
    int i;
 | 
					      LAYER_CONTEXT *const lc = &svc->layer_context[layer];
 | 
				
			||||||
    lc->current_video_frame_in_layer = 0;
 | 
					      RATE_CONTROL *const lrc = &lc->rc;
 | 
				
			||||||
    lc->layer_size = 0;
 | 
					      int i;
 | 
				
			||||||
    lc->frames_from_key_frame = 0;
 | 
					      lc->current_video_frame_in_layer = 0;
 | 
				
			||||||
    lc->last_frame_type = FRAME_TYPES;
 | 
					      lc->layer_size = 0;
 | 
				
			||||||
    lrc->ni_av_qi = oxcf->worst_allowed_q;
 | 
					      lc->frames_from_key_frame = 0;
 | 
				
			||||||
    lrc->total_actual_bits = 0;
 | 
					      lc->last_frame_type = FRAME_TYPES;
 | 
				
			||||||
    lrc->total_target_vs_actual = 0;
 | 
					      lrc->ni_av_qi = oxcf->worst_allowed_q;
 | 
				
			||||||
    lrc->ni_tot_qi = 0;
 | 
					      lrc->total_actual_bits = 0;
 | 
				
			||||||
    lrc->tot_q = 0.0;
 | 
					      lrc->total_target_vs_actual = 0;
 | 
				
			||||||
    lrc->avg_q = 0.0;
 | 
					      lrc->ni_tot_qi = 0;
 | 
				
			||||||
    lrc->ni_frames = 0;
 | 
					      lrc->tot_q = 0.0;
 | 
				
			||||||
    lrc->decimation_count = 0;
 | 
					      lrc->avg_q = 0.0;
 | 
				
			||||||
    lrc->decimation_factor = 0;
 | 
					      lrc->ni_frames = 0;
 | 
				
			||||||
 | 
					      lrc->decimation_count = 0;
 | 
				
			||||||
 | 
					      lrc->decimation_factor = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
 | 
					      for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
 | 
				
			||||||
      lrc->rate_correction_factors[i] = 1.0;
 | 
					        lrc->rate_correction_factors[i] = 1.0;
 | 
				
			||||||
    }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					      if (cpi->oxcf.rc_mode == VPX_CBR) {
 | 
				
			||||||
      lc->target_bandwidth = oxcf->ts_target_bitrate[layer];
 | 
					        lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
 | 
				
			||||||
      lrc->last_q[INTER_FRAME] = oxcf->worst_allowed_q;
 | 
					        lrc->last_q[INTER_FRAME] = oxcf->worst_allowed_q;
 | 
				
			||||||
      lrc->avg_frame_qindex[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;
 | 
					        lrc->avg_frame_qindex[KEY_FRAME] = oxcf->worst_allowed_q;
 | 
				
			||||||
    } else {
 | 
					      } else {
 | 
				
			||||||
      lc->target_bandwidth = oxcf->ss_target_bitrate[layer];
 | 
					        lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
 | 
				
			||||||
      lrc->last_q[KEY_FRAME] = oxcf->best_allowed_q;
 | 
					        lrc->last_q[KEY_FRAME] = oxcf->best_allowed_q;
 | 
				
			||||||
      lrc->last_q[INTER_FRAME] = oxcf->best_allowed_q;
 | 
					        lrc->last_q[INTER_FRAME] = oxcf->best_allowed_q;
 | 
				
			||||||
      lrc->avg_frame_qindex[KEY_FRAME] = (oxcf->worst_allowed_q +
 | 
					        lrc->avg_frame_qindex[KEY_FRAME] = (oxcf->worst_allowed_q +
 | 
				
			||||||
                                          oxcf->best_allowed_q) / 2;
 | 
					 | 
				
			||||||
      lrc->avg_frame_qindex[INTER_FRAME] = (oxcf->worst_allowed_q +
 | 
					 | 
				
			||||||
                                            oxcf->best_allowed_q) / 2;
 | 
					                                            oxcf->best_allowed_q) / 2;
 | 
				
			||||||
      if (oxcf->ss_enable_auto_arf[layer])
 | 
					        lrc->avg_frame_qindex[INTER_FRAME] = (oxcf->worst_allowed_q +
 | 
				
			||||||
        lc->alt_ref_idx = alt_ref_idx++;
 | 
					                                              oxcf->best_allowed_q) / 2;
 | 
				
			||||||
      else
 | 
					        if (oxcf->ss_enable_auto_arf[sl])
 | 
				
			||||||
        lc->alt_ref_idx = INVALID_IDX;
 | 
					          lc->alt_ref_idx = alt_ref_idx++;
 | 
				
			||||||
      lc->gold_ref_idx = INVALID_IDX;
 | 
					        else
 | 
				
			||||||
    }
 | 
					          lc->alt_ref_idx = INVALID_IDX;
 | 
				
			||||||
 | 
					        lc->gold_ref_idx = INVALID_IDX;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lrc->buffer_level = oxcf->starting_buffer_level_ms *
 | 
					      lrc->buffer_level = oxcf->starting_buffer_level_ms *
 | 
				
			||||||
                            lc->target_bandwidth / 1000;
 | 
					                              lc->target_bandwidth / 1000;
 | 
				
			||||||
    lrc->bits_off_target = lrc->buffer_level;
 | 
					      lrc->bits_off_target = lrc->buffer_level;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Still have extra buffer for base layer golden frame
 | 
					  // Still have extra buffer for base layer golden frame
 | 
				
			||||||
@@ -112,53 +108,100 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
 | 
				
			|||||||
  SVC *const svc = &cpi->svc;
 | 
					  SVC *const svc = &cpi->svc;
 | 
				
			||||||
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
 | 
					  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
 | 
				
			||||||
  const RATE_CONTROL *const rc = &cpi->rc;
 | 
					  const RATE_CONTROL *const rc = &cpi->rc;
 | 
				
			||||||
  int layer;
 | 
					  int sl, tl, layer = 0, spatial_layer_target;
 | 
				
			||||||
  int layer_end;
 | 
					 | 
				
			||||||
  float bitrate_alloc = 1.0;
 | 
					  float bitrate_alloc = 1.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					  if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING) {
 | 
				
			||||||
    layer_end = svc->number_temporal_layers;
 | 
					    for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
 | 
				
			||||||
 | 
					      spatial_layer_target = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      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];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      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;
 | 
				
			||||||
 | 
					        layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					        lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[layer];
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    layer_end = svc->number_spatial_layers;
 | 
					    int layer_end;
 | 
				
			||||||
  }
 | 
					    float bitrate_alloc = 1.0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (layer = 0; layer < layer_end; ++layer) {
 | 
					 | 
				
			||||||
    LAYER_CONTEXT *const lc = &svc->layer_context[layer];
 | 
					 | 
				
			||||||
    RATE_CONTROL *const lrc = &lc->rc;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					    if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
				
			||||||
      lc->target_bandwidth = oxcf->ts_target_bitrate[layer];
 | 
					      layer_end = svc->number_temporal_layers;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      lc->target_bandwidth = oxcf->ss_target_bitrate[layer];
 | 
					      layer_end = svc->number_spatial_layers;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    bitrate_alloc = (float)lc->target_bandwidth / target_bandwidth;
 | 
					
 | 
				
			||||||
    // Update buffer-related quantities.
 | 
					    for (layer = 0; layer < layer_end; ++layer) {
 | 
				
			||||||
    lrc->starting_buffer_level =
 | 
					      LAYER_CONTEXT *const lc = &svc->layer_context[layer];
 | 
				
			||||||
        (int64_t)(rc->starting_buffer_level * bitrate_alloc);
 | 
					      RATE_CONTROL *const lrc = &lc->rc;
 | 
				
			||||||
    lrc->optimal_buffer_level =
 | 
					
 | 
				
			||||||
        (int64_t)(rc->optimal_buffer_level * bitrate_alloc);
 | 
					      lc->target_bandwidth = oxcf->layer_target_bitrate[layer];
 | 
				
			||||||
    lrc->maximum_buffer_size =
 | 
					
 | 
				
			||||||
        (int64_t)(rc->maximum_buffer_size * bitrate_alloc);
 | 
					      bitrate_alloc = (float)lc->target_bandwidth / target_bandwidth;
 | 
				
			||||||
    lrc->bits_off_target = MIN(lrc->bits_off_target, lrc->maximum_buffer_size);
 | 
					      // Update buffer-related quantities.
 | 
				
			||||||
    lrc->buffer_level = MIN(lrc->buffer_level, lrc->maximum_buffer_size);
 | 
					      lrc->starting_buffer_level =
 | 
				
			||||||
    // Update framerate-related quantities.
 | 
					          (int64_t)(rc->starting_buffer_level * bitrate_alloc);
 | 
				
			||||||
    if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
 | 
					      lrc->optimal_buffer_level =
 | 
				
			||||||
      lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[layer];
 | 
					          (int64_t)(rc->optimal_buffer_level * bitrate_alloc);
 | 
				
			||||||
    } else {
 | 
					      lrc->maximum_buffer_size =
 | 
				
			||||||
      lc->framerate = cpi->framerate;
 | 
					          (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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static LAYER_CONTEXT *get_layer_context(VP9_COMP *const cpi) {
 | 
					static LAYER_CONTEXT *get_layer_context(VP9_COMP *const cpi) {
 | 
				
			||||||
  return (cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ?
 | 
					  if (is_one_pass_cbr_svc(cpi))
 | 
				
			||||||
         &cpi->svc.layer_context[cpi->svc.temporal_layer_id] :
 | 
					    return &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
         &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];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
 | 
					void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
 | 
				
			||||||
@@ -166,18 +209,22 @@ void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
 | 
				
			|||||||
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
 | 
					  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
 | 
				
			||||||
  LAYER_CONTEXT *const lc = get_layer_context(cpi);
 | 
					  LAYER_CONTEXT *const lc = get_layer_context(cpi);
 | 
				
			||||||
  RATE_CONTROL *const lrc = &lc->rc;
 | 
					  RATE_CONTROL *const lrc = &lc->rc;
 | 
				
			||||||
  const int layer = svc->temporal_layer_id;
 | 
					  // 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[layer];
 | 
					  lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[tl];
 | 
				
			||||||
  lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
 | 
					  lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
 | 
				
			||||||
  lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
 | 
					  lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
 | 
				
			||||||
  // Update the average layer frame size (non-cumulative per-frame-bw).
 | 
					  // Update the average layer frame size (non-cumulative per-frame-bw).
 | 
				
			||||||
  if (layer == 0) {
 | 
					  if (tl == 0) {
 | 
				
			||||||
    lc->avg_frame_size = lrc->avg_frame_bandwidth;
 | 
					    lc->avg_frame_size = lrc->avg_frame_bandwidth;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    const double prev_layer_framerate =
 | 
					    const double prev_layer_framerate =
 | 
				
			||||||
        cpi->framerate / oxcf->ts_rate_decimator[layer - 1];
 | 
					        cpi->framerate / oxcf->ts_rate_decimator[tl - 1];
 | 
				
			||||||
    const int prev_layer_target_bandwidth = oxcf->ts_target_bitrate[layer - 1];
 | 
					    const int prev_layer_target_bandwidth =
 | 
				
			||||||
 | 
					        oxcf->layer_target_bitrate[st_idx - 1];
 | 
				
			||||||
    lc->avg_frame_size =
 | 
					    lc->avg_frame_size =
 | 
				
			||||||
        (int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
 | 
					        (int)((lc->target_bandwidth - prev_layer_target_bandwidth) /
 | 
				
			||||||
              (lc->framerate - prev_layer_framerate));
 | 
					              (lc->framerate - prev_layer_framerate));
 | 
				
			||||||
@@ -243,9 +290,8 @@ void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void vp9_inc_frame_in_layer(VP9_COMP *const cpi) {
 | 
					void vp9_inc_frame_in_layer(VP9_COMP *const cpi) {
 | 
				
			||||||
  LAYER_CONTEXT *const lc =
 | 
					  LAYER_CONTEXT *const lc =
 | 
				
			||||||
      (cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ?
 | 
					      &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
      &cpi->svc.layer_context[cpi->svc.temporal_layer_id] :
 | 
					                              cpi->svc.number_temporal_layers];
 | 
				
			||||||
      &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
 | 
					 | 
				
			||||||
  ++lc->current_video_frame_in_layer;
 | 
					  ++lc->current_video_frame_in_layer;
 | 
				
			||||||
  ++lc->frames_from_key_frame;
 | 
					  ++lc->frames_from_key_frame;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -253,10 +299,11 @@ void vp9_inc_frame_in_layer(VP9_COMP *const cpi) {
 | 
				
			|||||||
int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) {
 | 
					int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) {
 | 
				
			||||||
  return is_two_pass_svc(cpi) &&
 | 
					  return is_two_pass_svc(cpi) &&
 | 
				
			||||||
         cpi->svc.spatial_layer_id > 0 &&
 | 
					         cpi->svc.spatial_layer_id > 0 &&
 | 
				
			||||||
         cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame;
 | 
					         cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
 | 
					                                cpi->svc.number_temporal_layers +
 | 
				
			||||||
 | 
					                                cpi->svc.temporal_layer_id].is_key_frame;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					 | 
				
			||||||
static void get_layer_resolution(const int width_org, const int height_org,
 | 
					static void get_layer_resolution(const int width_org, const int height_org,
 | 
				
			||||||
                                 const int num, const int den,
 | 
					                                 const int num, const int den,
 | 
				
			||||||
                                 int *width_out, int *height_out) {
 | 
					                                 int *width_out, int *height_out) {
 | 
				
			||||||
@@ -276,6 +323,201 @@ static void get_layer_resolution(const int width_org, const int height_org,
 | 
				
			|||||||
  *height_out = h;
 | 
					  *height_out = h;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
int vp9_svc_start_frame(VP9_COMP *const cpi) {
 | 
					int vp9_svc_start_frame(VP9_COMP *const cpi) {
 | 
				
			||||||
  int width = 0, height = 0;
 | 
					  int width = 0, height = 0;
 | 
				
			||||||
  LAYER_CONTEXT *lc;
 | 
					  LAYER_CONTEXT *lc;
 | 
				
			||||||
@@ -386,11 +628,12 @@ int vp9_svc_start_frame(VP9_COMP *const cpi) {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
 | 
					struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
 | 
				
			||||||
                                              struct lookahead_ctx *ctx,
 | 
					                                              struct lookahead_ctx *ctx,
 | 
				
			||||||
                                              int drain) {
 | 
					                                              int drain) {
 | 
				
			||||||
  struct lookahead_entry *buf = NULL;
 | 
					  struct lookahead_entry *buf = NULL;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
 | 
					  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
 | 
				
			||||||
    buf = vp9_lookahead_peek(ctx, 0);
 | 
					    buf = vp9_lookahead_peek(ctx, 0);
 | 
				
			||||||
    if (buf != NULL) {
 | 
					    if (buf != NULL) {
 | 
				
			||||||
@@ -400,7 +643,5 @@ struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return buf;
 | 
					  return buf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ extern "C" {
 | 
				
			|||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
  RATE_CONTROL rc;
 | 
					  RATE_CONTROL rc;
 | 
				
			||||||
  int target_bandwidth;
 | 
					  int target_bandwidth;
 | 
				
			||||||
 | 
					  int spatial_layer_target_bandwidth;  // Target for the spatial layer.
 | 
				
			||||||
  double framerate;
 | 
					  double framerate;
 | 
				
			||||||
  int avg_frame_size;
 | 
					  int avg_frame_size;
 | 
				
			||||||
  int max_q;
 | 
					  int max_q;
 | 
				
			||||||
@@ -64,9 +65,11 @@ typedef struct {
 | 
				
			|||||||
  YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
 | 
					  YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Layer context used for rate control in one pass temporal CBR mode or
 | 
					  // Layer context used for rate control in one pass temporal CBR mode or
 | 
				
			||||||
  // two pass spatial mode. Defined for temporal or spatial layers for now.
 | 
					  // two pass spatial mode.
 | 
				
			||||||
  // Does not support temporal combined with spatial RC.
 | 
					  LAYER_CONTEXT layer_context[VPX_MAX_LAYERS];
 | 
				
			||||||
  LAYER_CONTEXT layer_context[MAX(VPX_TS_MAX_LAYERS, VPX_SS_MAX_LAYERS)];
 | 
					  // Indicates what sort of temporal layering is used.
 | 
				
			||||||
 | 
					  // Currently, this only works for CBR mode.
 | 
				
			||||||
 | 
					  VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
 | 
				
			||||||
} SVC;
 | 
					} SVC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct VP9_COMP;
 | 
					struct VP9_COMP;
 | 
				
			||||||
@@ -110,6 +113,8 @@ struct lookahead_entry *vp9_svc_lookahead_pop(struct VP9_COMP *const cpi,
 | 
				
			|||||||
// Start a frame and initialize svc parameters
 | 
					// Start a frame and initialize svc parameters
 | 
				
			||||||
int vp9_svc_start_frame(struct VP9_COMP *const cpi);
 | 
					int vp9_svc_start_frame(struct VP9_COMP *const cpi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int vp9_one_pass_cbr_svc_start_layer(struct VP9_COMP *const cpi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}  // extern "C"
 | 
					}  // extern "C"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -682,7 +682,7 @@ void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
 | 
				
			|||||||
  if (frames_to_blur > 0) {
 | 
					  if (frames_to_blur > 0) {
 | 
				
			||||||
    // Setup scaling factors. Scaling on each of the arnr frames is not
 | 
					    // Setup scaling factors. Scaling on each of the arnr frames is not
 | 
				
			||||||
    // supported.
 | 
					    // supported.
 | 
				
			||||||
    if (is_two_pass_svc(cpi)) {
 | 
					    if (cpi->use_svc) {
 | 
				
			||||||
      // In spatial svc the scaling factors might be less then 1/2.
 | 
					      // In spatial svc the scaling factors might be less then 1/2.
 | 
				
			||||||
      // So we will use non-normative scaling.
 | 
					      // So we will use non-normative scaling.
 | 
				
			||||||
      int frame_used = 0;
 | 
					      int frame_used = 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -176,15 +176,23 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
 | 
				
			|||||||
  RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
 | 
					  RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
 | 
				
			||||||
  RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
 | 
					  RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (cfg->ss_number_layers * cfg->ts_number_layers > VPX_MAX_LAYERS)
 | 
				
			||||||
 | 
					    ERROR("ss_number_layers * ts_number_layers is out of range");
 | 
				
			||||||
  if (cfg->ts_number_layers > 1) {
 | 
					  if (cfg->ts_number_layers > 1) {
 | 
				
			||||||
    unsigned int i;
 | 
					    unsigned int sl, tl;
 | 
				
			||||||
    for (i = 1; i < cfg->ts_number_layers; ++i)
 | 
					    for (sl = 1; sl < cfg->ss_number_layers; ++sl) {
 | 
				
			||||||
      if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i - 1])
 | 
					      for (tl = 1; tl < cfg->ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					        const int layer =
 | 
				
			||||||
 | 
					            LAYER_IDS_TO_IDX(sl, tl, cfg->ts_number_layers);
 | 
				
			||||||
 | 
					        if (cfg->layer_target_bitrate[layer] <
 | 
				
			||||||
 | 
					            cfg->layer_target_bitrate[layer - 1])
 | 
				
			||||||
        ERROR("ts_target_bitrate entries are not increasing");
 | 
					        ERROR("ts_target_bitrate entries are not increasing");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
 | 
					    RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
 | 
				
			||||||
    for (i = cfg->ts_number_layers - 2; i > 0; --i)
 | 
					    for (tl = cfg->ts_number_layers - 2; tl > 0; --tl)
 | 
				
			||||||
      if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i])
 | 
					      if (cfg->ts_rate_decimator[tl - 1] != 2 * cfg->ts_rate_decimator[tl])
 | 
				
			||||||
        ERROR("ts_rate_decimator factors are not powers of 2");
 | 
					        ERROR("ts_rate_decimator factors are not powers of 2");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -360,6 +368,7 @@ static vpx_codec_err_t set_encoder_config(
 | 
				
			|||||||
  const vpx_codec_enc_cfg_t *cfg,
 | 
					  const vpx_codec_enc_cfg_t *cfg,
 | 
				
			||||||
  const struct vp9_extracfg *extra_cfg) {
 | 
					  const struct vp9_extracfg *extra_cfg) {
 | 
				
			||||||
  const int is_vbr = cfg->rc_end_usage == VPX_VBR;
 | 
					  const int is_vbr = cfg->rc_end_usage == VPX_VBR;
 | 
				
			||||||
 | 
					  int sl, tl;
 | 
				
			||||||
  oxcf->profile = cfg->g_profile;
 | 
					  oxcf->profile = cfg->g_profile;
 | 
				
			||||||
  oxcf->max_threads = (int)cfg->g_threads;
 | 
					  oxcf->max_threads = (int)cfg->g_threads;
 | 
				
			||||||
  oxcf->width   = cfg->g_w;
 | 
					  oxcf->width   = cfg->g_w;
 | 
				
			||||||
@@ -460,35 +469,33 @@ static vpx_codec_err_t set_encoder_config(
 | 
				
			|||||||
  oxcf->frame_periodic_boost =  extra_cfg->frame_periodic_boost;
 | 
					  oxcf->frame_periodic_boost =  extra_cfg->frame_periodic_boost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  oxcf->ss_number_layers = cfg->ss_number_layers;
 | 
					  oxcf->ss_number_layers = cfg->ss_number_layers;
 | 
				
			||||||
 | 
					  oxcf->ts_number_layers = cfg->ts_number_layers;
 | 
				
			||||||
 | 
					  oxcf->temporal_layering_mode = (enum vp9e_temporal_layering_mode)
 | 
				
			||||||
 | 
					      cfg->temporal_layering_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (oxcf->ss_number_layers > 1) {
 | 
					  for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
 | 
				
			||||||
    int i;
 | 
					 | 
				
			||||||
    for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
 | 
					 | 
				
			||||||
      oxcf->ss_target_bitrate[i] =  1000 * cfg->ss_target_bitrate[i];
 | 
					 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					#if CONFIG_SPATIAL_SVC
 | 
				
			||||||
      oxcf->ss_enable_auto_arf[i] =  cfg->ss_enable_auto_alt_ref[i];
 | 
					    oxcf->ss_enable_auto_arf[sl] = cfg->ss_enable_auto_alt_ref[sl];
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					    for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
 | 
				
			||||||
 | 
					      oxcf->layer_target_bitrate[sl * oxcf->ts_number_layers + tl] =
 | 
				
			||||||
 | 
					          1000 * cfg->layer_target_bitrate[sl * oxcf->ts_number_layers + tl];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if (oxcf->ss_number_layers == 1) {
 | 
					  }
 | 
				
			||||||
 | 
					  if (oxcf->ss_number_layers == 1 && oxcf->pass != 0) {
 | 
				
			||||||
    oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
 | 
					    oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					#if CONFIG_SPATIAL_SVC
 | 
				
			||||||
    oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
 | 
					    oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  oxcf->ts_number_layers = cfg->ts_number_layers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (oxcf->ts_number_layers > 1) {
 | 
					  if (oxcf->ts_number_layers > 1) {
 | 
				
			||||||
    int i;
 | 
					    for (tl = 0; tl < VPX_TS_MAX_LAYERS; ++tl) {
 | 
				
			||||||
    for (i = 0; i < VPX_TS_MAX_LAYERS; ++i) {
 | 
					      oxcf->ts_rate_decimator[tl] = cfg->ts_rate_decimator[tl] ?
 | 
				
			||||||
      oxcf->ts_target_bitrate[i] = 1000 * cfg->ts_target_bitrate[i];
 | 
					          cfg->ts_rate_decimator[tl] : 1;
 | 
				
			||||||
      oxcf->ts_rate_decimator[i] = cfg->ts_rate_decimator[i];
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if (oxcf->ts_number_layers == 1) {
 | 
					  } else if (oxcf->ts_number_layers == 1) {
 | 
				
			||||||
    oxcf->ts_target_bitrate[0] = (int)oxcf->target_bandwidth;
 | 
					 | 
				
			||||||
    oxcf->ts_rate_decimator[0] = 1;
 | 
					    oxcf->ts_rate_decimator[0] = 1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
  printf("Current VP9 Settings: \n");
 | 
					  printf("Current VP9 Settings: \n");
 | 
				
			||||||
  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
 | 
					  printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
 | 
				
			||||||
@@ -902,11 +909,12 @@ static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi,
 | 
				
			|||||||
                                                   unsigned int lib_flags) {
 | 
					                                                   unsigned int lib_flags) {
 | 
				
			||||||
  vpx_codec_frame_flags_t flags = lib_flags << 16;
 | 
					  vpx_codec_frame_flags_t flags = lib_flags << 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (lib_flags & FRAMEFLAGS_KEY
 | 
					  if (lib_flags & FRAMEFLAGS_KEY ||
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					      (cpi->use_svc &&
 | 
				
			||||||
      || (is_two_pass_svc(cpi) && cpi->svc.layer_context[0].is_key_frame)
 | 
					          cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
#endif
 | 
					              cpi->svc.number_temporal_layers +
 | 
				
			||||||
        )
 | 
					              cpi->svc.temporal_layer_id].is_key_frame)
 | 
				
			||||||
 | 
					     )
 | 
				
			||||||
    flags |= VPX_FRAME_IS_KEY;
 | 
					    flags |= VPX_FRAME_IS_KEY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (cpi->droppable)
 | 
					  if (cpi->droppable)
 | 
				
			||||||
@@ -1022,16 +1030,15 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
				
			|||||||
        vpx_codec_cx_pkt_t pkt;
 | 
					        vpx_codec_cx_pkt_t pkt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					#if CONFIG_SPATIAL_SVC
 | 
				
			||||||
        if (is_two_pass_svc(cpi))
 | 
					        if (cpi->use_svc)
 | 
				
			||||||
          cpi->svc.layer_context[cpi->svc.spatial_layer_id].layer_size += size;
 | 
					          cpi->svc.layer_context[cpi->svc.spatial_layer_id *
 | 
				
			||||||
 | 
					              cpi->svc.number_temporal_layers].layer_size += size;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Pack invisible frames with the next visible frame
 | 
					        // Pack invisible frames with the next visible frame
 | 
				
			||||||
        if (!cpi->common.show_frame
 | 
					        if (!cpi->common.show_frame ||
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					            (cpi->use_svc &&
 | 
				
			||||||
            || (is_two_pass_svc(cpi) &&
 | 
					             cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
 | 
				
			||||||
                cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
            ) {
 | 
					            ) {
 | 
				
			||||||
          if (ctx->pending_cx_data == 0)
 | 
					          if (ctx->pending_cx_data == 0)
 | 
				
			||||||
            ctx->pending_cx_data = cx_data;
 | 
					            ctx->pending_cx_data = cx_data;
 | 
				
			||||||
@@ -1089,24 +1096,26 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
				
			|||||||
        pkt.data.frame.partition_id = -1;
 | 
					        pkt.data.frame.partition_id = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(ctx->output_cx_pkt_cb.output_cx_pkt)
 | 
					        if(ctx->output_cx_pkt_cb.output_cx_pkt)
 | 
				
			||||||
          ctx->output_cx_pkt_cb.output_cx_pkt(&pkt, ctx->output_cx_pkt_cb.user_priv);
 | 
					          ctx->output_cx_pkt_cb.output_cx_pkt(&pkt,
 | 
				
			||||||
 | 
					                                              ctx->output_cx_pkt_cb.user_priv);
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
 | 
					          vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cx_data += size;
 | 
					        cx_data += size;
 | 
				
			||||||
        cx_data_sz -= size;
 | 
					        cx_data_sz -= size;
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					#if CONFIG_SPATIAL_SVC
 | 
				
			||||||
        if (is_two_pass_svc(cpi) && !ctx->output_cx_pkt_cb.output_cx_pkt) {
 | 
					        if (cpi->use_svc && !ctx->output_cx_pkt_cb.output_cx_pkt) {
 | 
				
			||||||
          vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
 | 
					          vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
 | 
				
			||||||
          int i;
 | 
					          int sl;
 | 
				
			||||||
          vp9_zero(pkt_sizes);
 | 
					          vp9_zero(pkt_sizes);
 | 
				
			||||||
          vp9_zero(pkt_psnr);
 | 
					          vp9_zero(pkt_psnr);
 | 
				
			||||||
          pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
 | 
					          pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
 | 
				
			||||||
          pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
 | 
					          pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
 | 
				
			||||||
          for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
 | 
					          for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
 | 
				
			||||||
            LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
 | 
					            LAYER_CONTEXT *lc =
 | 
				
			||||||
            pkt_sizes.data.layer_sizes[i] = lc->layer_size;
 | 
					                &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
 | 
				
			||||||
            pkt_psnr.data.layer_psnr[i] = lc->psnr_pkt;
 | 
					            pkt_sizes.data.layer_sizes[sl] = lc->layer_size;
 | 
				
			||||||
 | 
					            pkt_psnr.data.layer_psnr[sl] = lc->psnr_pkt;
 | 
				
			||||||
            lc->layer_size = 0;
 | 
					            lc->layer_size = 0;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1115,6 +1124,11 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
 | 
				
			|||||||
          vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
 | 
					          vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					        if (is_one_pass_cbr_svc(cpi) &&
 | 
				
			||||||
 | 
					            (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
 | 
				
			||||||
 | 
					          // Encoded all spatial layers; exit loop.
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1292,16 +1306,20 @@ static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
 | 
				
			|||||||
static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
 | 
					static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
 | 
				
			||||||
  int data = va_arg(args, int);
 | 
					  int data = va_arg(args, int);
 | 
				
			||||||
  const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
 | 
					  const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
 | 
				
			||||||
 | 
					  // Both one-pass and two-pass RC are supported now.
 | 
				
			||||||
 | 
					  // User setting this has to make sure of the following.
 | 
				
			||||||
 | 
					  // In two-pass setting: either (but not both)
 | 
				
			||||||
 | 
					  //      cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
 | 
				
			||||||
 | 
					  // In one-pass setting:
 | 
				
			||||||
 | 
					  //      either or both cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vp9_set_svc(ctx->cpi, data);
 | 
					  vp9_set_svc(ctx->cpi, data);
 | 
				
			||||||
  // CBR or two pass mode for SVC with both temporal and spatial layers
 | 
					
 | 
				
			||||||
  // not yet supported.
 | 
					 | 
				
			||||||
  if (data == 1 &&
 | 
					  if (data == 1 &&
 | 
				
			||||||
      (cfg->rc_end_usage == VPX_CBR ||
 | 
					      (cfg->g_pass == VPX_RC_FIRST_PASS ||
 | 
				
			||||||
       cfg->g_pass == VPX_RC_FIRST_PASS ||
 | 
					 | 
				
			||||||
       cfg->g_pass == VPX_RC_LAST_PASS) &&
 | 
					       cfg->g_pass == VPX_RC_LAST_PASS) &&
 | 
				
			||||||
      cfg->ss_number_layers > 1 &&
 | 
					       cfg->ss_number_layers > 1 &&
 | 
				
			||||||
      cfg->ts_number_layers > 1) {
 | 
					       cfg->ts_number_layers > 1) {
 | 
				
			||||||
    return VPX_CODEC_INVALID_PARAM;
 | 
					    return VPX_CODEC_INVALID_PARAM;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return VPX_CODEC_OK;
 | 
					  return VPX_CODEC_OK;
 | 
				
			||||||
@@ -1347,15 +1365,21 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
 | 
				
			|||||||
                                               va_list args) {
 | 
					                                               va_list args) {
 | 
				
			||||||
  VP9_COMP *const cpi = ctx->cpi;
 | 
					  VP9_COMP *const cpi = ctx->cpi;
 | 
				
			||||||
  vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
 | 
					  vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
 | 
				
			||||||
  int i;
 | 
					  int sl, tl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
 | 
					  // Number of temporal layers and number of spatial layers have to be set
 | 
				
			||||||
    LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
 | 
					  // properly before calling this control function.
 | 
				
			||||||
 | 
					  for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
 | 
				
			||||||
    lc->max_q = params->max_quantizers[i];
 | 
					    for (tl = 0; tl < cpi->svc.number_temporal_layers; ++tl) {
 | 
				
			||||||
    lc->min_q = params->min_quantizers[i];
 | 
					      const int layer =
 | 
				
			||||||
    lc->scaling_factor_num = params->scaling_factor_num[i];
 | 
					          LAYER_IDS_TO_IDX(sl, tl, cpi->svc.number_temporal_layers);
 | 
				
			||||||
    lc->scaling_factor_den = params->scaling_factor_den[i];
 | 
					      LAYER_CONTEXT *lc =
 | 
				
			||||||
 | 
					          &cpi->svc.layer_context[layer];
 | 
				
			||||||
 | 
					      lc->max_q = params->max_quantizers[sl];
 | 
				
			||||||
 | 
					      lc->min_q = params->min_quantizers[sl];
 | 
				
			||||||
 | 
					      lc->scaling_factor_num = params->scaling_factor_num[sl];
 | 
				
			||||||
 | 
					      lc->scaling_factor_den = params->scaling_factor_den[sl];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return VPX_CODEC_OK;
 | 
					  return VPX_CODEC_OK;
 | 
				
			||||||
@@ -1495,6 +1519,8 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
 | 
				
			|||||||
      {0},                    // ts_rate_decimator
 | 
					      {0},                    // ts_rate_decimator
 | 
				
			||||||
      0,                      // ts_periodicity
 | 
					      0,                      // ts_periodicity
 | 
				
			||||||
      {0},                    // ts_layer_id
 | 
					      {0},                    // ts_layer_id
 | 
				
			||||||
 | 
					      {0},                  // layer_taget_bitrate
 | 
				
			||||||
 | 
					      0                     // temporal_layering_mode
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -302,31 +302,79 @@ void assign_layer_bitrates(const SvcContext *svc_ctx,
 | 
				
			|||||||
                           vpx_codec_enc_cfg_t *const enc_cfg) {
 | 
					                           vpx_codec_enc_cfg_t *const enc_cfg) {
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
  const SvcInternal_t *const si = get_const_svc_internal(svc_ctx);
 | 
					  const SvcInternal_t *const si = get_const_svc_internal(svc_ctx);
 | 
				
			||||||
 | 
					  int sl, tl, spatial_layer_target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (si->bitrates[0] != 0) {
 | 
					  if (svc_ctx->temporal_layering_mode != 0) {
 | 
				
			||||||
    enc_cfg->rc_target_bitrate = 0;
 | 
					    if (si->bitrates[0] != 0) {
 | 
				
			||||||
    for (i = 0; i < svc_ctx->spatial_layers; ++i) {
 | 
					      enc_cfg->rc_target_bitrate = 0;
 | 
				
			||||||
      enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i];
 | 
					      for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
 | 
				
			||||||
      enc_cfg->rc_target_bitrate += si->bitrates[i];
 | 
					        enc_cfg->ss_target_bitrate[sl*svc_ctx->temporal_layers] = 0;
 | 
				
			||||||
    }
 | 
					        for (tl = 0; tl < svc_ctx->temporal_layers; ++tl) {
 | 
				
			||||||
  } else {
 | 
					          enc_cfg->ss_target_bitrate[sl*svc_ctx->temporal_layers]
 | 
				
			||||||
    float total = 0;
 | 
					              += (unsigned int)si->bitrates[sl * svc_ctx->temporal_layers + tl];
 | 
				
			||||||
    float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
 | 
					          enc_cfg->layer_target_bitrate[sl*svc_ctx->temporal_layers + tl]
 | 
				
			||||||
 | 
					              = si->bitrates[sl * svc_ctx->temporal_layers + tl];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      float total = 0;
 | 
				
			||||||
 | 
					      float alloc_ratio[VPX_MAX_LAYERS] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < svc_ctx->spatial_layers; ++i) {
 | 
					      for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
 | 
				
			||||||
      if (si->svc_params.scaling_factor_den[i] > 0) {
 | 
					        if (si->svc_params.scaling_factor_den[sl] > 0) {
 | 
				
			||||||
        alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 /
 | 
					          alloc_ratio[sl] = (float)(si->svc_params.scaling_factor_num[sl] *
 | 
				
			||||||
                                 si->svc_params.scaling_factor_den[i]);
 | 
					              1.0 / si->svc_params.scaling_factor_den[sl]);
 | 
				
			||||||
 | 
					          total += alloc_ratio[sl];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        alloc_ratio[i] *= alloc_ratio[i];
 | 
					      for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
 | 
				
			||||||
        total += alloc_ratio[i];
 | 
					        enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
 | 
				
			||||||
 | 
					            (unsigned int)(enc_cfg->rc_target_bitrate *
 | 
				
			||||||
 | 
					                alloc_ratio[sl] / total);
 | 
				
			||||||
 | 
					        if (svc_ctx->temporal_layering_mode == 3) {
 | 
				
			||||||
 | 
					          enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] =
 | 
				
			||||||
 | 
					              spatial_layer_target >> 1;
 | 
				
			||||||
 | 
					          enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] =
 | 
				
			||||||
 | 
					              (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
 | 
				
			||||||
 | 
					          enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] =
 | 
				
			||||||
 | 
					              spatial_layer_target;
 | 
				
			||||||
 | 
					        } else if (svc_ctx->temporal_layering_mode == 2) {
 | 
				
			||||||
 | 
					          enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] =
 | 
				
			||||||
 | 
					              spatial_layer_target * 2 / 3;
 | 
				
			||||||
 | 
					          enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] =
 | 
				
			||||||
 | 
					              spatial_layer_target;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          // User should explicitly assign bitrates in this case.
 | 
				
			||||||
 | 
					          assert(0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    if (si->bitrates[0] != 0) {
 | 
				
			||||||
 | 
					      enc_cfg->rc_target_bitrate = 0;
 | 
				
			||||||
 | 
					      for (i = 0; i < svc_ctx->spatial_layers; ++i) {
 | 
				
			||||||
 | 
					        enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i];
 | 
				
			||||||
 | 
					        enc_cfg->rc_target_bitrate += si->bitrates[i];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      float total = 0;
 | 
				
			||||||
 | 
					      float alloc_ratio[VPX_MAX_LAYERS] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
 | 
					      for (i = 0; i < svc_ctx->spatial_layers; ++i) {
 | 
				
			||||||
      if (total > 0) {
 | 
					        if (si->svc_params.scaling_factor_den[i] > 0) {
 | 
				
			||||||
        enc_cfg->ss_target_bitrate[i] = (unsigned int)
 | 
					          alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 /
 | 
				
			||||||
            (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
 | 
					                                   si->svc_params.scaling_factor_den[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          alloc_ratio[i] *= alloc_ratio[i];
 | 
				
			||||||
 | 
					          total += alloc_ratio[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
 | 
				
			||||||
 | 
					        if (total > 0) {
 | 
				
			||||||
 | 
					          enc_cfg->layer_target_bitrate[i] = (unsigned int)
 | 
				
			||||||
 | 
					              (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -365,6 +413,14 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
				
			|||||||
    return VPX_CODEC_INVALID_PARAM;
 | 
					    return VPX_CODEC_INVALID_PARAM;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Note: temporal_layering_mode only applies to one-pass CBR
 | 
				
			||||||
 | 
					  // si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode;
 | 
				
			||||||
 | 
					  if (svc_ctx->temporal_layering_mode == 3) {
 | 
				
			||||||
 | 
					    svc_ctx->temporal_layers = 3;
 | 
				
			||||||
 | 
					  } else if (svc_ctx->temporal_layering_mode == 2) {
 | 
				
			||||||
 | 
					    svc_ctx->temporal_layers = 2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
 | 
					  for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
 | 
				
			||||||
    si->svc_params.max_quantizers[i] = MAX_QUANTIZER;
 | 
					    si->svc_params.max_quantizers[i] = MAX_QUANTIZER;
 | 
				
			||||||
    si->svc_params.min_quantizers[i] = 0;
 | 
					    si->svc_params.min_quantizers[i] = 0;
 | 
				
			||||||
@@ -387,6 +443,14 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
				
			|||||||
  if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS)
 | 
					  if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS)
 | 
				
			||||||
    svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS;
 | 
					    svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (svc_ctx->temporal_layers * svc_ctx->spatial_layers > VPX_MAX_LAYERS) {
 | 
				
			||||||
 | 
					      svc_log(svc_ctx, SVC_LOG_ERROR,
 | 
				
			||||||
 | 
					          "spatial layers * temporal layers exceeds the maximum number of "
 | 
				
			||||||
 | 
					          "allowed layers of %d\n",
 | 
				
			||||||
 | 
					          svc_ctx->spatial_layers * svc_ctx->temporal_layers,
 | 
				
			||||||
 | 
					          (int) VPX_MAX_LAYERS);
 | 
				
			||||||
 | 
					      return VPX_CODEC_INVALID_PARAM;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  assign_layer_bitrates(svc_ctx, enc_cfg);
 | 
					  assign_layer_bitrates(svc_ctx, enc_cfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG_SPATIAL_SVC
 | 
					#if CONFIG_SPATIAL_SVC
 | 
				
			||||||
@@ -403,10 +467,24 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // modify encoder configuration
 | 
					  if (svc_ctx->threads)
 | 
				
			||||||
 | 
					    enc_cfg->g_threads = svc_ctx->threads;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Modify encoder configuration
 | 
				
			||||||
  enc_cfg->ss_number_layers = svc_ctx->spatial_layers;
 | 
					  enc_cfg->ss_number_layers = svc_ctx->spatial_layers;
 | 
				
			||||||
  enc_cfg->ts_number_layers = svc_ctx->temporal_layers;
 | 
					  enc_cfg->ts_number_layers = svc_ctx->temporal_layers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (enc_cfg->rc_end_usage == VPX_CBR) {
 | 
				
			||||||
 | 
					    enc_cfg->rc_resize_allowed = 0;
 | 
				
			||||||
 | 
					    enc_cfg->rc_min_quantizer = 2;
 | 
				
			||||||
 | 
					    enc_cfg->rc_max_quantizer = 63;
 | 
				
			||||||
 | 
					    enc_cfg->rc_undershoot_pct = 50;
 | 
				
			||||||
 | 
					    enc_cfg->rc_overshoot_pct = 50;
 | 
				
			||||||
 | 
					    enc_cfg->rc_buf_initial_sz = 20;
 | 
				
			||||||
 | 
					    enc_cfg->rc_buf_optimal_sz = 600;
 | 
				
			||||||
 | 
					    enc_cfg->rc_buf_sz = 1000;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0)
 | 
					  if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0)
 | 
				
			||||||
    enc_cfg->g_error_resilient = 1;
 | 
					    enc_cfg->g_error_resilient = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -554,7 +632,7 @@ const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
 | 
				
			|||||||
            mse[1], mse[2], mse[3]);
 | 
					            mse[1], mse[2], mse[3]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bytes_total += si->bytes_sum[i];
 | 
					    bytes_total += si->bytes_sum[i];
 | 
				
			||||||
    // clear sums for next time
 | 
					    // Clear sums for next time.
 | 
				
			||||||
    si->bytes_sum[i] = 0;
 | 
					    si->bytes_sum[i] = 0;
 | 
				
			||||||
    for (j = 0; j < COMPONENTS; ++j) {
 | 
					    for (j = 0; j < COMPONENTS; ++j) {
 | 
				
			||||||
      si->psnr_sum[i][j] = 0;
 | 
					      si->psnr_sum[i][j] = 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,10 +33,13 @@ typedef struct {
 | 
				
			|||||||
  // public interface to svc_command options
 | 
					  // public interface to svc_command options
 | 
				
			||||||
  int spatial_layers;               // number of spatial layers
 | 
					  int spatial_layers;               // number of spatial layers
 | 
				
			||||||
  int temporal_layers;               // number of temporal layers
 | 
					  int temporal_layers;               // number of temporal layers
 | 
				
			||||||
 | 
					  int temporal_layering_mode;
 | 
				
			||||||
  SVC_LOG_LEVEL log_level;  // amount of information to display
 | 
					  SVC_LOG_LEVEL log_level;  // amount of information to display
 | 
				
			||||||
  int log_print;  // when set, printf log messages instead of returning the
 | 
					  int log_print;  // when set, printf log messages instead of returning the
 | 
				
			||||||
                  // message with svc_get_message
 | 
					                  // message with svc_get_message
 | 
				
			||||||
 | 
					  int output_rc_stat;  // for outputting rc stats
 | 
				
			||||||
 | 
					  int speed;  // speed setting for codec
 | 
				
			||||||
 | 
					  int threads;
 | 
				
			||||||
  // private storage for vpx_svc_encode
 | 
					  // private storage for vpx_svc_encode
 | 
				
			||||||
  void *internal;
 | 
					  void *internal;
 | 
				
			||||||
} SvcContext;
 | 
					} SvcContext;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								vpx/vp8cx.h
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								vpx/vp8cx.h
									
									
									
									
									
								
							@@ -511,6 +511,17 @@ enum vp8e_enc_control_id {
 | 
				
			|||||||
   */
 | 
					   */
 | 
				
			||||||
  VP9E_SET_COLOR_SPACE,
 | 
					  VP9E_SET_COLOR_SPACE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*!\brief Codec control function to set temporal layering mode.
 | 
				
			||||||
 | 
					   * \note Valid ranges: 0..3, default is "0" (VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING).
 | 
				
			||||||
 | 
					   *                     0 = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING
 | 
				
			||||||
 | 
					   *                     1 = VP9E_TEMPORAL_LAYERING_MODE_BYPASS
 | 
				
			||||||
 | 
					   *                     2 = VP9E_TEMPORAL_LAYERING_MODE_0101
 | 
				
			||||||
 | 
					   *                     3 = VP9E_TEMPORAL_LAYERING_MODE_0212
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Supported in codecs: VP9
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  VP9E_SET_TEMPORAL_LAYERING_MODE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*!\brief Codec control function to get an Active map back from the encoder.
 | 
					  /*!\brief Codec control function to get an Active map back from the encoder.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * Supported in codecs: VP9
 | 
					   * Supported in codecs: VP9
 | 
				
			||||||
@@ -529,6 +540,32 @@ typedef enum vpx_scaling_mode_1d {
 | 
				
			|||||||
  VP8E_ONETWO      = 3
 | 
					  VP8E_ONETWO      = 3
 | 
				
			||||||
} VPX_SCALING_MODE;
 | 
					} VPX_SCALING_MODE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!\brief Temporal layering mode enum for VP9 SVC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This set of macros define the different temporal layering modes.
 | 
				
			||||||
 | 
					 * Supported codecs: VP9 (in SVC mode)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef enum vp9e_temporal_layering_mode {
 | 
				
			||||||
 | 
					  /*!\brief No temporal layering.
 | 
				
			||||||
 | 
					   * Used when only spatial layering is used.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING   = 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*!\brief Bypass mode.
 | 
				
			||||||
 | 
					   * Used when application needs to control temporal layering.
 | 
				
			||||||
 | 
					   * This will only work when the number of spatial layers equals 1.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  VP9E_TEMPORAL_LAYERING_MODE_BYPASS       = 1,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*!\brief 0-1-0-1... temporal layering scheme with two temporal layers.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  VP9E_TEMPORAL_LAYERING_MODE_0101         = 2,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*!\brief 0-2-1-2... temporal layering scheme with three temporal layers.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  VP9E_TEMPORAL_LAYERING_MODE_0212         = 3
 | 
				
			||||||
 | 
					} VP9E_TEMPORAL_LAYERING_MODE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*!\brief  vpx region of interest map
 | 
					/*!\brief  vpx region of interest map
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,8 +42,11 @@ extern "C" {
 | 
				
			|||||||
  /*!\deprecated Use #VPX_TS_MAX_PERIODICITY instead. */
 | 
					  /*!\deprecated Use #VPX_TS_MAX_PERIODICITY instead. */
 | 
				
			||||||
#define MAX_PERIODICITY VPX_TS_MAX_PERIODICITY
 | 
					#define MAX_PERIODICITY VPX_TS_MAX_PERIODICITY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*!\deprecated Use #VPX_TS_MAX_LAYERS instead. */
 | 
					/*! Temporal+Spatial Scalability: Maximum number of coding layers */
 | 
				
			||||||
#define MAX_LAYERS      VPX_TS_MAX_LAYERS
 | 
					#define VPX_MAX_LAYERS  12  // 3 temporal + 4 spatial layers are allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!\deprecated Use #VPX_MAX_LAYERS instead. */
 | 
				
			||||||
 | 
					#define MAX_LAYERS    VPX_MAX_LAYERS  // 3 temporal + 4 spatial layers allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! Spatial Scalability: Maximum number of coding layers */
 | 
					/*! Spatial Scalability: Maximum number of coding layers */
 | 
				
			||||||
#define VPX_SS_MAX_LAYERS       5
 | 
					#define VPX_SS_MAX_LAYERS       5
 | 
				
			||||||
@@ -729,6 +732,22 @@ extern "C" {
 | 
				
			|||||||
     * ts_periodicity=8, then ts_layer_id = (0,1,0,1,0,1,0,1).
 | 
					     * ts_periodicity=8, then ts_layer_id = (0,1,0,1,0,1,0,1).
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    unsigned int           ts_layer_id[VPX_TS_MAX_PERIODICITY];
 | 
					    unsigned int           ts_layer_id[VPX_TS_MAX_PERIODICITY];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*!\brief Target bitrate for each spatial/temporal layer.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * These values specify the target coding bitrate to be used for each
 | 
				
			||||||
 | 
					     * spatial/temporal layer.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    unsigned int           layer_target_bitrate[VPX_MAX_LAYERS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*!\brief Temporal layering mode indicating which temporal layering scheme to use.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The value (refer to VP9E_TEMPORAL_LAYERING_MODE) specifies the
 | 
				
			||||||
 | 
					     * temporal layering mode to use.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    int                    temporal_layering_mode;
 | 
				
			||||||
  } vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
 | 
					  } vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*!\brief  vp9 svc extra configure parameters
 | 
					  /*!\brief  vp9 svc extra configure parameters
 | 
				
			||||||
@@ -737,10 +756,11 @@ extern "C" {
 | 
				
			|||||||
   *
 | 
					   *
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  typedef struct vpx_svc_parameters {
 | 
					  typedef struct vpx_svc_parameters {
 | 
				
			||||||
    int max_quantizers[VPX_SS_MAX_LAYERS]; /**< Max Q for each layer */
 | 
					    int max_quantizers[VPX_MAX_LAYERS]; /**< Max Q for each layer */
 | 
				
			||||||
    int min_quantizers[VPX_SS_MAX_LAYERS]; /**< Min Q for each layer */
 | 
					    int min_quantizers[VPX_MAX_LAYERS]; /**< Min Q for each layer */
 | 
				
			||||||
    int scaling_factor_num[VPX_SS_MAX_LAYERS]; /**< Scaling factor-numerator*/
 | 
					    int scaling_factor_num[VPX_MAX_LAYERS]; /**< Scaling factor-numerator */
 | 
				
			||||||
    int scaling_factor_den[VPX_SS_MAX_LAYERS]; /**< Scaling factor-denominator*/
 | 
					    int scaling_factor_den[VPX_MAX_LAYERS]; /**< Scaling factor-denominator */
 | 
				
			||||||
 | 
					    int temporal_layering_mode; /**< Temporal layering mode */
 | 
				
			||||||
  } vpx_svc_extra_cfg_t;
 | 
					  } vpx_svc_extra_cfg_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user