summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
authorMinghai Shang <minghai@google.com>2014-03-27 13:43:20 -0700
committerMinghai Shang <minghai@google.com>2014-03-27 13:43:20 -0700
commit6b2e4061235f39978ec186afad0534330e049858 (patch)
tree1ba96f34c4889667b09f1bb293d74c917b82cac4 /vp9
parent143b09558c0152c6f65be26fa114dc6f160fff21 (diff)
downloadlibvpx-6b2e4061235f39978ec186afad0534330e049858.tar
libvpx-6b2e4061235f39978ec186afad0534330e049858.tar.gz
libvpx-6b2e4061235f39978ec186afad0534330e049858.tar.bz2
libvpx-6b2e4061235f39978ec186afad0534330e049858.zip
[svc] Verify and store input two pass stats data in 2nd pass rc
Change-Id: Ib09eedc17ea0ea2eec75d78112e4786d98f382aa
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_onyx_if.c52
-rw-r--r--vp9/encoder/vp9_svc_layercontext.h1
-rw-r--r--vp9/vp9_cx_iface.c48
3 files changed, 90 insertions, 11 deletions
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 444720915..e30f5346a 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -177,6 +177,7 @@ void vp9_initialize_enc() {
static void dealloc_compressor_data(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
+ int i;
// Delete sementation map
vpx_free(cpi->segmentation_map);
@@ -210,6 +211,13 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
cpi->mb_activity_map = 0;
vpx_free(cpi->mb_norm_activity_map);
cpi->mb_norm_activity_map = 0;
+
+ for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
+ LAYER_CONTEXT *const lc = &cpi->svc.layer_context[i];
+ vpx_free(lc->rc_twopass_stats_in.buf);
+ lc->rc_twopass_stats_in.buf = NULL;
+ lc->rc_twopass_stats_in.sz = 0;
+ }
}
// Computes a q delta (in "q index" terms) to get from a starting q value
@@ -1750,9 +1758,47 @@ VP9_COMP *vp9_create_compressor(VP9_CONFIG *oxcf) {
const size_t packet_sz = sizeof(FIRSTPASS_STATS);
const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
- cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
- cpi->twopass.stats_in = cpi->twopass.stats_in_start;
- cpi->twopass.stats_in_end = &cpi->twopass.stats_in[packets - 1];
+ if (cpi->svc.number_spatial_layers > 1
+ && cpi->svc.number_temporal_layers == 1) {
+ FIRSTPASS_STATS *const stats = oxcf->two_pass_stats_in.buf;
+ FIRSTPASS_STATS *stats_copy[VPX_SS_MAX_LAYERS] = {0};
+ int i;
+
+ for (i = 0; i < oxcf->ss_number_layers; ++i) {
+ FIRSTPASS_STATS *const last_packet_for_layer =
+ &stats[packets - oxcf->ss_number_layers + i];
+ const int layer_id = last_packet_for_layer->spatial_layer_id;
+ const int packets_in_layer = (int)last_packet_for_layer->count + 1;
+ if (layer_id >= 0 && layer_id < oxcf->ss_number_layers) {
+ LAYER_CONTEXT *const lc = &cpi->svc.layer_context[layer_id];
+
+ vpx_free(lc->rc_twopass_stats_in.buf);
+
+ lc->rc_twopass_stats_in.sz = packets_in_layer * packet_sz;
+ CHECK_MEM_ERROR(cm, lc->rc_twopass_stats_in.buf,
+ vpx_malloc(lc->rc_twopass_stats_in.sz));
+ lc->twopass.stats_in_start = lc->rc_twopass_stats_in.buf;
+ lc->twopass.stats_in = lc->twopass.stats_in_start;
+ lc->twopass.stats_in_end = lc->twopass.stats_in_start
+ + packets_in_layer - 1;
+ stats_copy[layer_id] = lc->rc_twopass_stats_in.buf;
+ }
+ }
+
+ for (i = 0; i < packets; ++i) {
+ const int layer_id = stats[i].spatial_layer_id;
+ if (layer_id >= 0 && layer_id < oxcf->ss_number_layers
+ && stats_copy[layer_id] != NULL) {
+ *stats_copy[layer_id] = stats[i];
+ ++stats_copy[layer_id];
+ }
+ }
+ } else {
+ cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
+ cpi->twopass.stats_in = cpi->twopass.stats_in_start;
+ cpi->twopass.stats_in_end = &cpi->twopass.stats_in[packets - 1];
+ }
+
vp9_init_second_pass(cpi);
}
diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h
index e81b0b7c8..afbbdf086 100644
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -28,6 +28,7 @@ typedef struct {
double framerate;
int avg_frame_size;
struct twopass_rc twopass;
+ struct vpx_fixed_buf rc_twopass_stats_in;
} LAYER_CONTEXT;
typedef struct {
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 30c2c49e6..84b61eba4 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -221,14 +221,43 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
if (cfg->rc_twopass_stats_in.sz % packet_sz)
ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
- if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
- ERROR("rc_twopass_stats_in requires at least two packets.");
+ if (cfg->ss_number_layers > 1) {
+ int i;
+ unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = {0};
+
+ stats = cfg->rc_twopass_stats_in.buf;
+ for (i = 0; i < n_packets; ++i) {
+ const int layer_id = stats[i].spatial_layer_id;
+ if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
+ ++n_packets_per_layer[layer_id];
+ }
+ }
+
+ for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
+ unsigned int layer_id;
+ if (n_packets_per_layer[i] < 2) {
+ ERROR("rc_twopass_stats_in requires at least two packets for each "
+ "layer.");
+ }
- stats =
- (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
+ stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
+ n_packets - cfg->ss_number_layers + i;
+ layer_id = stats->spatial_layer_id;
- if ((int)(stats->count + 0.5) != n_packets - 1)
- ERROR("rc_twopass_stats_in missing EOS stats packet");
+ if (layer_id >= cfg->ss_number_layers
+ ||(int)(stats->count + 0.5) != n_packets_per_layer[layer_id] - 1)
+ ERROR("rc_twopass_stats_in missing EOS stats packet");
+ }
+ } else {
+ if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
+ ERROR("rc_twopass_stats_in requires at least two packets.");
+
+ stats =
+ (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
+
+ if ((int)(stats->count + 0.5) != n_packets - 1)
+ ERROR("rc_twopass_stats_in missing EOS stats packet");
+ }
}
return VPX_CODEC_OK;
@@ -990,9 +1019,12 @@ static vpx_codec_err_t vp9e_set_svc(vpx_codec_alg_priv_t *ctx, int ctr_id,
va_list args) {
int data = va_arg(args, int);
vp9_set_svc(ctx->cpi, data);
- // CBR mode for SVC with both temporal and spatial layers not yet supported.
+ // CBR or two pass mode for SVC with both temporal and spatial layers
+ // not yet supported.
if (data == 1 &&
- ctx->cfg.rc_end_usage == VPX_CBR &&
+ (ctx->cfg.rc_end_usage == VPX_CBR ||
+ ctx->cfg.g_pass == VPX_RC_FIRST_PASS ||
+ ctx->cfg.g_pass == VPX_RC_LAST_PASS) &&
ctx->cfg.ss_number_layers > 1 &&
ctx->cfg.ts_number_layers > 1) {
return VPX_CODEC_INVALID_PARAM;