diff options
Diffstat (limited to 'source/libvpx/vpx')
-rw-r--r-- | source/libvpx/vpx/exports_enc | 2 | ||||
-rw-r--r-- | source/libvpx/vpx/src/svc_encodeframe.c | 143 | ||||
-rw-r--r-- | source/libvpx/vpx/src/vpx_encoder.c | 2 | ||||
-rw-r--r-- | source/libvpx/vpx/svc_context.h | 11 | ||||
-rw-r--r-- | source/libvpx/vpx/vp8cx.h | 3 | ||||
-rw-r--r-- | source/libvpx/vpx/vpx_encoder.h | 2 |
6 files changed, 120 insertions, 43 deletions
diff --git a/source/libvpx/vpx/exports_enc b/source/libvpx/vpx/exports_enc index 99b1bfa..155faf6 100644 --- a/source/libvpx/vpx/exports_enc +++ b/source/libvpx/vpx/exports_enc @@ -21,3 +21,5 @@ text vpx_svc_set_options text vpx_svc_set_quantizers text vpx_svc_set_scale_factors text vpx_svc_get_layer_resolution +text vpx_svc_get_rc_stats_buffer_size +text vpx_svc_get_rc_stats_buffer
\ No newline at end of file diff --git a/source/libvpx/vpx/src/svc_encodeframe.c b/source/libvpx/vpx/src/svc_encodeframe.c index c783724..76aacd2 100644 --- a/source/libvpx/vpx/src/svc_encodeframe.c +++ b/source/libvpx/vpx/src/svc_encodeframe.c @@ -13,6 +13,7 @@ * VP9 SVC encoding support via libvpx */ +#include <assert.h> #include <math.h> #include <stdarg.h> #include <stdio.h> @@ -81,6 +82,10 @@ typedef struct SvcInternal { size_t buffer_size; void *buffer; + char *rc_stats_buf; + size_t rc_stats_buf_size; + size_t rc_stats_buf_used; + char message_buffer[2048]; vpx_codec_ctx_t *codec_ctx; } SvcInternal; @@ -519,9 +524,6 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, svc_ctx->spatial_layers); return VPX_CODEC_INVALID_PARAM; } - // use SvcInternal value for number of layers to enable forcing single layer - // for first frame - si->layers = svc_ctx->spatial_layers; res = parse_quantizer_values(svc_ctx, si->quantizers, 0); if (res != VPX_CODEC_OK) return res; @@ -533,10 +535,13 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, res = parse_scale_factors(svc_ctx, si->scale_factors); if (res != VPX_CODEC_OK) return res; - // parse aggregate command line options + // Parse aggregate command line options. Options must start with + // "layers=xx" then followed by other options res = parse_options(svc_ctx, si->options); if (res != VPX_CODEC_OK) return res; + si->layers = svc_ctx->spatial_layers; + // Assign target bitrate for each layer. We calculate the ratio // from the resolution for now. // TODO(Minghai): Optimize the mechanism of allocating bits after @@ -546,6 +551,7 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, float total = 0; float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; + assert(si->layers <= VPX_SS_MAX_LAYERS); for (i = 0; i < si->layers; ++i) { int pos = i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers; if (pos < VPX_SS_MAX_LAYERS && si->scaling_factor_den[pos] > 0) { @@ -569,7 +575,6 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, enc_cfg->ss_number_layers = si->layers; enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder. enc_cfg->kf_mode = VPX_KF_DISABLED; - enc_cfg->g_pass = VPX_RC_ONE_PASS; // Lag in frames not currently supported enc_cfg->g_lag_in_frames = 0; @@ -578,8 +583,12 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, enc_cfg->rc_dropframe_thresh = 0; enc_cfg->rc_end_usage = VPX_CBR; enc_cfg->rc_resize_allowed = 0; - enc_cfg->rc_min_quantizer = 33; - enc_cfg->rc_max_quantizer = 33; + + if (enc_cfg->g_pass == VPX_RC_ONE_PASS) { + enc_cfg->rc_min_quantizer = 33; + enc_cfg->rc_max_quantizer = 33; + } + enc_cfg->rc_undershoot_pct = 100; enc_cfg->rc_overshoot_pct = 15; enc_cfg->rc_buf_initial_sz = 500; @@ -779,12 +788,17 @@ static void set_svc_parameters(SvcContext *svc_ctx, } layer_index = layer + VPX_SS_MAX_LAYERS - si->layers; - if (vpx_svc_is_keyframe(svc_ctx)) { - svc_params.min_quantizer = si->quantizer_keyframe[layer_index]; - svc_params.max_quantizer = si->quantizer_keyframe[layer_index]; + if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) { + if (vpx_svc_is_keyframe(svc_ctx)) { + svc_params.min_quantizer = si->quantizer_keyframe[layer_index]; + svc_params.max_quantizer = si->quantizer_keyframe[layer_index]; + } else { + svc_params.min_quantizer = si->quantizer[layer_index]; + svc_params.max_quantizer = si->quantizer[layer_index]; + } } else { - svc_params.min_quantizer = si->quantizer[layer_index]; - svc_params.max_quantizer = si->quantizer[layer_index]; + svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer; + svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer; } svc_params.distance_from_i_frame = si->frame_within_gop; @@ -845,12 +859,13 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, struct LayerData *layer_data; struct Superframe superframe; SvcInternal *const si = get_svc_internal(svc_ctx); - if (svc_ctx == NULL || codec_ctx == NULL || rawimg == NULL || si == NULL) { + if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { return VPX_CODEC_INVALID_PARAM; } memset(&superframe, 0, sizeof(superframe)); svc_log_reset(svc_ctx); + si->rc_stats_buf_used = 0; si->layers = svc_ctx->spatial_layers; if (si->frame_within_gop >= si->kf_dist || @@ -860,9 +875,12 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, si->is_keyframe = (si->frame_within_gop == 0); si->frame_size = 0; - svc_log(svc_ctx, SVC_LOG_DEBUG, - "vpx_svc_encode layers: %d, frame_count: %d, frame_within_gop: %d\n", - si->layers, si->encode_frame_count, si->frame_within_gop); + if (rawimg != NULL) { + svc_log(svc_ctx, SVC_LOG_DEBUG, + "vpx_svc_encode layers: %d, frame_count: %d, " + "frame_within_gop: %d\n", si->layers, si->encode_frame_count, + si->frame_within_gop); + } // encode each layer for (si->layer = 0; si->layer < si->layers; ++si->layer) { @@ -871,9 +889,11 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer); continue; } - calculate_enc_frame_flags(svc_ctx); - set_svc_parameters(svc_ctx, codec_ctx); + if (rawimg != NULL) { + calculate_enc_frame_flags(svc_ctx); + set_svc_parameters(svc_ctx, codec_ctx); + } res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, si->enc_frame_flags, deadline); @@ -923,39 +943,63 @@ vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, } break; } + case VPX_CODEC_STATS_PKT: { + size_t new_size = si->rc_stats_buf_used + + cx_pkt->data.twopass_stats.sz; + + if (new_size > si->rc_stats_buf_size) { + char *p = (char*)realloc(si->rc_stats_buf, new_size); + if (p == NULL) { + svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n"); + break; + } + si->rc_stats_buf = p; + si->rc_stats_buf_size = new_size; + } + + memcpy(si->rc_stats_buf + si->rc_stats_buf_used, + cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz); + si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz; + break; + } default: { break; } } } + if (rawimg == NULL) { + break; + } } - // add superframe index to layer data list - sf_create_index(&superframe); - layer_data = ld_create(superframe.buffer, superframe.index_size); - ld_list_add(&cx_layer_list, layer_data); - - // get accumulated size of layer data - si->frame_size = ld_list_get_buffer_size(cx_layer_list); - if (si->frame_size == 0) return VPX_CODEC_ERROR; + if (codec_ctx->config.enc->g_pass != VPX_RC_FIRST_PASS) { + // add superframe index to layer data list + sf_create_index(&superframe); + layer_data = ld_create(superframe.buffer, superframe.index_size); + ld_list_add(&cx_layer_list, layer_data); + + // get accumulated size of layer data + si->frame_size = ld_list_get_buffer_size(cx_layer_list); + if (si->frame_size > 0) { + // all layers encoded, create single buffer with concatenated layers + if (si->frame_size > si->buffer_size) { + free(si->buffer); + si->buffer = malloc(si->frame_size); + if (si->buffer == NULL) { + ld_list_free(cx_layer_list); + return VPX_CODEC_MEM_ERROR; + } + si->buffer_size = si->frame_size; + } + // copy layer data into packet + ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer); - // all layers encoded, create single buffer with concatenated layers - if (si->frame_size > si->buffer_size) { - free(si->buffer); - si->buffer = malloc(si->frame_size); - if (si->buffer == NULL) { ld_list_free(cx_layer_list); - return VPX_CODEC_MEM_ERROR; + + svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, " + "pts: %d\n", si->encode_frame_count, si->is_keyframe, + (int)si->frame_size, (int)pts); } - si->buffer_size = si->frame_size; } - // copy layer data into packet - ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer); - - ld_list_free(cx_layer_list); - - svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, pts: %d\n", - si->encode_frame_count, si->is_keyframe, (int)si->frame_size, - (int)pts); ++si->frame_within_gop; ++si->encode_frame_count; @@ -1077,7 +1121,24 @@ void vpx_svc_release(SvcContext *svc_ctx) { si = (SvcInternal *)svc_ctx->internal; if (si != NULL) { free(si->buffer); + if (si->rc_stats_buf) { + free(si->rc_stats_buf); + } free(si); svc_ctx->internal = NULL; } } + +size_t vpx_svc_get_rc_stats_buffer_size(const SvcContext *svc_ctx) { + const SvcInternal *const si = get_const_svc_internal(svc_ctx); + if (svc_ctx == NULL || si == NULL) return 0; + return si->rc_stats_buf_used; +} + +char *vpx_svc_get_rc_stats_buffer(const SvcContext *svc_ctx) { + const SvcInternal *const si = get_const_svc_internal(svc_ctx); + if (svc_ctx == NULL || si == NULL) return NULL; + return si->rc_stats_buf; +} + + diff --git a/source/libvpx/vpx/src/vpx_encoder.c b/source/libvpx/vpx/src/vpx_encoder.c index e69d96e..ece2d0b 100644 --- a/source/libvpx/vpx/src/vpx_encoder.c +++ b/source/libvpx/vpx/src/vpx_encoder.c @@ -394,7 +394,7 @@ const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list *iter = list->pkts; } - pkt = (const void *) * iter; + pkt = (const vpx_codec_cx_pkt_t *)*iter; if ((size_t)(pkt - list->pkts) < list->cnt) *iter = pkt + 1; diff --git a/source/libvpx/vpx/svc_context.h b/source/libvpx/vpx/svc_context.h index 98474ca..5d0fbbd 100644 --- a/source/libvpx/vpx/svc_context.h +++ b/source/libvpx/vpx/svc_context.h @@ -114,6 +114,17 @@ size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx); void *vpx_svc_get_buffer(const SvcContext *svc_ctx); /** + * return size of two pass rate control stats data to be returned by + * vpx_svc_get_rc_stats_buffer + */ +size_t vpx_svc_get_rc_stats_buffer_size(const SvcContext *svc_ctx); + +/** + * return buffer two pass of rate control stats data + */ +char *vpx_svc_get_rc_stats_buffer(const SvcContext *svc_ctx); + +/** * return spatial resolution of the specified layer */ vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx, diff --git a/source/libvpx/vpx/vp8cx.h b/source/libvpx/vpx/vp8cx.h index 0b637d4..8944a26 100644 --- a/source/libvpx/vpx/vp8cx.h +++ b/source/libvpx/vpx/vp8cx.h @@ -192,6 +192,7 @@ enum vp8e_enc_control_id { VP9E_SET_TILE_ROWS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE, + VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_SVC, VP9E_SET_SVC_PARAMETERS, @@ -364,6 +365,8 @@ VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int) VPX_CTRL_USE_TYPE(VP9E_SET_AQ_MODE, unsigned int) +VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PERIODIC_BOOST, unsigned int) + /*! @} - end defgroup vp8_encoder */ #ifdef __cplusplus } // extern "C" diff --git a/source/libvpx/vpx/vpx_encoder.h b/source/libvpx/vpx/vpx_encoder.h index 851ff1a..2c882c1 100644 --- a/source/libvpx/vpx/vpx_encoder.h +++ b/source/libvpx/vpx/vpx_encoder.h @@ -49,7 +49,7 @@ extern "C" { #define VPX_SS_MAX_LAYERS 5 /*! Spatial Scalability: Default number of coding layers */ -#define VPX_SS_DEFAULT_LAYERS 3 +#define VPX_SS_DEFAULT_LAYERS 1 /*!\brief Current ABI version number * |