ref: 37e1295c61f6b0c6d7ef3b97d7eec8fdd3bdb67c
parent: 2221ec88d54c307d5f7496d1ff5cf6fd029e0b1f
author: Jerome Jiang <jianj@google.com>
date: Fri Feb 8 10:44:46 EST 2019
refactor vp9 svc example encoder. Put rc stats related code into a separate function. Change-Id: I11808bb947079b5fd9e53dfa5894bf227ed0c4c6
--- a/examples/vp9_spatial_svc_encoder.c
+++ b/examples/vp9_spatial_svc_encoder.c
@@ -749,6 +749,96 @@
}
}
+#if OUTPUT_RC_STATS
+static void svc_output_rc_stats(
+ vpx_codec_ctx_t *codec, vpx_codec_enc_cfg_t *enc_cfg,
+ vpx_svc_layer_id_t *layer_id, const vpx_codec_cx_pkt_t *cx_pkt,
+ struct RateControlStats *rc, VpxVideoWriter **outfile,
+ const uint32_t frame_cnt, const double framerate) {
+ int num_layers_encoded = 0;
+ unsigned int sl, tl;
+ uint64_t sizes[8];
+ uint64_t sizes_parsed[8];
+ int count = 0;
+ double sum_bitrate = 0.0;
+ double sum_bitrate2 = 0.0;
+ vp9_zero(sizes);
+ vp9_zero(sizes_parsed);
+ 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_parsed, &count);
+ if (enc_cfg->ss_number_layers == 1) sizes[0] = cx_pkt->data.frame.sz;
+ for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
+ sizes[sl] = 0;
+ if (cx_pkt->data.frame.spatial_layer_encoded[sl]) {
+ sizes[sl] = sizes_parsed[num_layers_encoded];
+ num_layers_encoded++;
+ }
+ }
+ for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
+ unsigned int sl2;
+ uint64_t tot_size = 0;
+ for (sl2 = 0; sl2 <= sl; ++sl2) {
+ if (cx_pkt->data.frame.spatial_layer_encoded[sl2]) tot_size += sizes[sl2];
+ }
+ if (tot_size > 0)
+ vpx_video_writer_write_frame(outfile[sl], cx_pkt->data.frame.buf,
+ (size_t)(tot_size), cx_pkt->data.frame.pts);
+ }
+ for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
+ if (cx_pkt->data.frame.spatial_layer_encoded[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 == (unsigned int)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 > (unsigned int)rc->window_size) {
+ for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
+ if (cx_pkt->data.frame.spatial_layer_encoded[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);
+ }
+ }
+
+ // Second shifted window.
+ if (frame_cnt > (unsigned int)(rc->window_size + rc->window_size / 2)) {
+ for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
+ sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
+ }
+
+ if (frame_cnt > (unsigned int)(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);
+ }
+ }
+}
+#endif
+
int main(int argc, const char **argv) {
AppInput app_input;
VpxVideoWriter *writer = NULL;
@@ -770,9 +860,7 @@
struct RateControlStats rc;
vpx_svc_layer_id_t layer_id;
vpx_svc_ref_frame_config_t ref_frame_config;
- unsigned int sl, tl;
- double sum_bitrate = 0.0;
- double sum_bitrate2 = 0.0;
+ unsigned int sl;
double framerate = 30.0;
#endif
struct vpx_usec_timer timer;
@@ -988,101 +1076,13 @@
case VPX_CODEC_CX_FRAME_PKT: {
SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
if (cx_pkt->data.frame.sz > 0) {
-#if OUTPUT_RC_STATS
- uint64_t sizes[8];
- uint64_t sizes_parsed[8];
- int count = 0;
- vp9_zero(sizes);
- vp9_zero(sizes_parsed);
-#endif
vpx_video_writer_write_frame(writer, cx_pkt->data.frame.buf,
cx_pkt->data.frame.sz,
cx_pkt->data.frame.pts);
#if OUTPUT_RC_STATS
- // TODO(marpan): Put this (to line728) in separate function.
if (svc_ctx.output_rc_stat) {
- int num_layers_encoded = 0;
- 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_parsed,
- &count);
- if (enc_cfg.ss_number_layers == 1)
- sizes[0] = cx_pkt->data.frame.sz;
- for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
- sizes[sl] = 0;
- if (cx_pkt->data.frame.spatial_layer_encoded[sl]) {
- sizes[sl] = sizes_parsed[num_layers_encoded];
- num_layers_encoded++;
- }
- }
- for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
- unsigned int sl2;
- uint64_t tot_size = 0;
- for (sl2 = 0; sl2 <= sl; ++sl2) {
- if (cx_pkt->data.frame.spatial_layer_encoded[sl2])
- tot_size += sizes[sl2];
- }
- if (tot_size > 0)
- vpx_video_writer_write_frame(
- outfile[sl], cx_pkt->data.frame.buf, (size_t)(tot_size),
- cx_pkt->data.frame.pts);
- }
- for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
- if (cx_pkt->data.frame.spatial_layer_encoded[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 == (unsigned int)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 > (unsigned int)rc.window_size) {
- for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
- if (cx_pkt->data.frame.spatial_layer_encoded[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 >
- (unsigned int)(rc.window_size + rc.window_size / 2)) {
- for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
- sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
- }
-
- if (frame_cnt > (unsigned int)(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;
- }
- }
+ svc_output_rc_stats(&codec, &enc_cfg, &layer_id, cx_pkt, &rc,
+ outfile, frame_cnt, framerate);
}
#endif
}