int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t height) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.g_w == width && cfg.g_h == height) return 0; if (width * height > cs->max_width * cs->max_height) { vpx_codec_ctx_t v_encoder = cs->v_encoder; if (init_video_encoder(cs, width, height, cs->video_bitrate) == -1) { cs->v_encoder = v_encoder; return cs_ErrorSettingVideoResolution; } vpx_codec_destroy(&v_encoder); return 0; } LOGGER_DEBUG("New video resolution: %u %u", width, height); cfg.g_w = width; cfg.g_h = height; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return cs_ErrorSettingVideoResolution; } return 0; }
int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height, int16_t kf_max_dist) { if (!vc) { return -1; } vpx_codec_enc_cfg_t cfg2 = *vc->encoder->config.enc; vpx_codec_err_t rc; if (cfg2.rc_target_bitrate == bit_rate && cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) { return 0; /* Nothing changed */ } if (cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) { /* Only bit rate changed */ LOGGER_INFO(vc->log, "bitrate change from: %u to: %u", (uint32_t)cfg2.rc_target_bitrate, (uint32_t)bit_rate); cfg2.rc_target_bitrate = bit_rate; rc = vpx_codec_enc_config_set(vc->encoder, &cfg2); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } } else { /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support * reconfiguring encoder to use resolutions greater than initially set. */ LOGGER_DEBUG(vc->log, "Have to reinitialize vpx encoder on session %p", (void *)vc); vpx_codec_ctx_t new_c; vpx_codec_enc_cfg_t cfg; vc_init_encoder_cfg(vc->log, &cfg, kf_max_dist); cfg.rc_target_bitrate = bit_rate; cfg.g_w = width; cfg.g_h = height; LOGGER_DEBUG(vc->log, "Using VP8 codec for encoder"); rc = vpx_codec_enc_init(&new_c, video_codec_encoder_interface(), &cfg, VPX_CODEC_USE_FRAME_THREADING); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } int cpu_used_value = VP8E_SET_CPUUSED_VALUE; rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, cpu_used_value); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); vpx_codec_destroy(&new_c); return -1; } vpx_codec_destroy(vc->encoder); memcpy(vc->encoder, &new_c, sizeof(new_c)); } return 0; }
void krad_vpx_encoder_config_set (krad_vpx_encoder_t *vpx, vpx_codec_enc_cfg_t *cfg) { int ret; ret = vpx_codec_enc_config_set (&vpx->encoder, cfg); if (ret != VPX_CODEC_OK) { printke ("VPX Config problem: %s\n", vpx_codec_err_to_string (ret)); } }
/* * Method: codec_enc_config_set */ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1config_1set (JNIEnv *env, jclass clazz, jlong context, jlong cfg) { return (jint) vpx_codec_enc_config_set( (vpx_codec_ctx_t *) (intptr_t) context, (vpx_codec_enc_cfg_t *) (intptr_t) context); }
int reconfigure_video_encoder_bitrate(CodecState *cs, uint32_t video_bitrate) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.rc_target_bitrate == video_bitrate) return 0; LOGGER_DEBUG("New video bitrate: %u", video_bitrate); cfg.rc_target_bitrate = video_bitrate; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } return 0; }
int reconfigure_video_encoder_resolution(CodecState *cs, uint16_t width, uint16_t height) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.g_w == width && cfg.g_h == height) return 0; if (width * height > cs->max_width * cs->max_height) return -1; LOGGER_DEBUG("New video resolution: %u %u", width, height); cfg.g_w = width; cfg.g_h = height; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } return 0; }
static switch_status_t init_encoder(switch_codec_t *codec) { vpx_context_t *context = (vpx_context_t *)codec->private_info; vpx_codec_enc_cfg_t *config = &context->config; int token_parts = 1; int cpus = switch_core_cpu_count(); if (!context->codec_settings.video.width) { context->codec_settings.video.width = 1280; } if (!context->codec_settings.video.height) { context->codec_settings.video.height = 720; } if (context->codec_settings.video.bandwidth == -1) { context->codec_settings.video.bandwidth = 0; } if (context->codec_settings.video.bandwidth) { context->bandwidth = context->codec_settings.video.bandwidth; } else { context->bandwidth = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 0, 0); } if (context->bandwidth > 40960) { context->bandwidth = 40960; } context->pkt = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_DEBUG1, "VPX reset encoder picture from %dx%d to %dx%d %u BW\n", config->g_w, config->g_h, context->codec_settings.video.width, context->codec_settings.video.height, context->bandwidth); context->start_time = switch_micro_time_now(); config->g_timebase.num = 1; config->g_timebase.den = 1000; config->g_pass = VPX_RC_ONE_PASS; config->g_w = context->codec_settings.video.width; config->g_h = context->codec_settings.video.height; config->rc_target_bitrate = context->bandwidth; config->g_lag_in_frames = 0; config->kf_max_dist = 2000; config->g_threads = (cpus > 1) ? 2 : 1; if (context->is_vp9) { //config->rc_dropframe_thresh = 2; token_parts = (cpus > 1) ? 3 : 0; if (context->lossless) { config->rc_min_quantizer = 0; config->rc_max_quantizer = 0; } else { config->rc_min_quantizer = 0; config->rc_max_quantizer = 63; } } else { // settings config->g_profile = 2; config->g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS; token_parts = (cpus > 1) ? 3 : 0; // rate control settings config->rc_dropframe_thresh = 0; config->rc_end_usage = VPX_CBR; //config->g_pass = VPX_RC_ONE_PASS; config->kf_mode = VPX_KF_AUTO; config->kf_max_dist = 1000; //config->kf_mode = VPX_KF_DISABLED; config->rc_resize_allowed = 1; //config->rc_min_quantizer = 0; //config->rc_max_quantizer = 63; config->rc_min_quantizer = 0; config->rc_max_quantizer = 63; //Rate control adaptation undershoot control. // This value, expressed as a percentage of the target bitrate, // controls the maximum allowed adaptation speed of the codec. // This factor controls the maximum amount of bits that can be // subtracted from the target bitrate in order to compensate for // prior overshoot. // Valid values in the range 0-1000. config->rc_undershoot_pct = 100; //Rate control adaptation overshoot control. // This value, expressed as a percentage of the target bitrate, // controls the maximum allowed adaptation speed of the codec. // This factor controls the maximum amount of bits that can be // added to the target bitrate in order to compensate for prior // undershoot. // Valid values in the range 0-1000. config->rc_overshoot_pct = 15; //Decoder Buffer Size. // This value indicates the amount of data that may be buffered // by the decoding application. Note that this value is expressed // in units of time (milliseconds). For example, a value of 5000 // indicates that the client will buffer (at least) 5000ms worth // of encoded data. Use the target bitrate (rc_target_bitrate) to // convert to bits/bytes, if necessary. config->rc_buf_sz = 5000; //Decoder Buffer Initial Size. // This value indicates the amount of data that will be buffered // by the decoding application prior to beginning playback. // This value is expressed in units of time (milliseconds). // Use the target bitrate (rc_target_bitrate) to convert to // bits/bytes, if necessary. config->rc_buf_initial_sz = 1000; //Decoder Buffer Optimal Size. // This value indicates the amount of data that the encoder should // try to maintain in the decoder's buffer. This value is expressed // in units of time (milliseconds). // Use the target bitrate (rc_target_bitrate) to convert to // bits/bytes, if necessary. config->rc_buf_optimal_sz = 1000; } if (context->encoder_init) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "VPX ENCODER RESET\n"); if (vpx_codec_enc_config_set(&context->encoder, config) != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec init error: [%d:%s]\n", context->encoder.err, context->encoder.err_detail); } } else if (context->flags & SWITCH_CODEC_FLAG_ENCODE) { if (vpx_codec_enc_init(&context->encoder, context->encoder_interface, config, 0 & VPX_CODEC_USE_OUTPUT_PARTITION) != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec init error: [%d:%s]\n", context->encoder.err, context->encoder.err_detail); return SWITCH_STATUS_FALSE; } context->encoder_init = 1; if (context->is_vp9) { if (context->lossless) { vpx_codec_control(&context->encoder, VP9E_SET_LOSSLESS, 1); vpx_codec_control(&context->encoder, VP8E_SET_CPUUSED, -6); } else { vpx_codec_control(&context->encoder, VP8E_SET_CPUUSED, -8); } vpx_codec_control(&context->encoder, VP8E_SET_STATIC_THRESHOLD, 100); vpx_codec_control(&context->encoder, VP8E_SET_TOKEN_PARTITIONS, token_parts); vpx_codec_control(&context->encoder, VP9E_SET_TUNE_CONTENT, VP9E_CONTENT_SCREEN); } else { // The static threshold imposes a change threshold on blocks below which they will be skipped by the encoder. vpx_codec_control(&context->encoder, VP8E_SET_STATIC_THRESHOLD, 100); //Set cpu usage, a bit lower than normal (-6) but higher than android (-12) vpx_codec_control(&context->encoder, VP8E_SET_CPUUSED, -6); vpx_codec_control(&context->encoder, VP8E_SET_TOKEN_PARTITIONS, token_parts); // Enable noise reduction vpx_codec_control(&context->encoder, VP8E_SET_NOISE_SENSITIVITY, 1); //Set max data rate for Intra frames. // This value controls additional clamping on the maximum size of a keyframe. // It is expressed as a percentage of the average per-frame bitrate, with the // special (and default) value 0 meaning unlimited, or no additional clamping // beyond the codec's built-in algorithm. // For example, to allocate no more than 4.5 frames worth of bitrate to a keyframe, set this to 450. //vpx_codec_control(&context->encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT, 0); } } return SWITCH_STATUS_SUCCESS; }