diff --git a/src/mod/codecs/mod_vpx/mod_vpx.c b/src/mod/codecs/mod_vpx/mod_vpx.c index ee7f7f63f7..979357ecd5 100644 --- a/src/mod/codecs/mod_vpx/mod_vpx.c +++ b/src/mod/codecs/mod_vpx/mod_vpx.c @@ -83,6 +83,8 @@ static switch_status_t init_codec(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 = 0; + int cpus = switch_core_cpu_count(); if (!context->codec_settings.video.width) { context->codec_settings.video.width = 1280; @@ -95,7 +97,8 @@ static switch_status_t init_codec(switch_codec_t *codec) if (context->codec_settings.video.bandwidth) { context->bandwidth = context->codec_settings.video.bandwidth; } else { - context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height * 8; + int x = (context->codec_settings.video.width / 1000) + 1; + context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height * x; } if (context->bandwidth > 1250000) { @@ -103,7 +106,7 @@ static switch_status_t init_codec(switch_codec_t *codec) } // settings - config->g_profile = 1; + config->g_profile = 0; config->g_w = context->codec_settings.video.width; config->g_h = context->codec_settings.video.height; config->rc_target_bitrate = context->bandwidth; @@ -111,19 +114,22 @@ static switch_status_t init_codec(switch_codec_t *codec) config->g_timebase.den = 1000; config->g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS; config->g_lag_in_frames = 0; // 0- no frame lagging - config->g_threads = (switch_core_cpu_count() > 1) ? 2 : 1; + + + + config->g_threads = (cpus > 1) ? 2 : 1; + 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_DISABLED; - //config->kf_mode = VPX_KF_AUTO; - //config->kf_min_dist = FPS;// Intra Period 3 seconds; - //config->kf_max_dist = FPS; + 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 = 2; - config->rc_max_quantizer = 56; + 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. @@ -181,8 +187,8 @@ static switch_status_t init_codec(switch_codec_t *codec) 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); - // Only one partition - // vpx_codec_control(&context->encoder, VP8E_SET_TOKEN_PARTITIONS, VP8_ONE_TOKENPARTITION); + 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. @@ -191,7 +197,7 @@ static switch_status_t init_codec(switch_codec_t *codec) // 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); + //vpx_codec_control(&context->encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT, 0); } if (context->flags & SWITCH_CODEC_FLAG_DECODE) { @@ -299,8 +305,6 @@ static switch_status_t consume_partition(vpx_context_t *context, switch_frame_t { if (!context->pkt) context->pkt = vpx_codec_get_cx_data(&context->encoder, &context->iter); - frame->m = 0; - if (context->pkt) { // if (context->pkt->kind == VPX_CODEC_CX_FRAME_PKT && (context->pkt->data.frame.flags & VPX_FRAME_IS_KEY) && context->pkt_pos == 0) { // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "============================Got a VP8 Key Frame size:[%d]===================================\n", (int)context->pkt->data.frame.sz); @@ -407,7 +411,7 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t * if (vpx_codec_encode(&context->encoder, (vpx_image_t *) frame->img, context->pts, duration, vpx_flags, VPX_DL_REALTIME) != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VP8 encode error %d:%s\n", context->encoder.err, context->encoder.err_detail); - + frame->datalen = 0; return SWITCH_STATUS_FALSE; } diff --git a/src/switch_core_codec.c b/src/switch_core_codec.c index 480a5a046f..c8f175709c 100644 --- a/src/switch_core_codec.c +++ b/src/switch_core_codec.c @@ -809,12 +809,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *c if (codec->implementation->encode_video) { status = codec->implementation->encode_video(codec, frame); - if (frame->datalen) { - frame->packetlen = frame->datalen + 12; + if (status == SWITCH_STATUS_MORE_DATA) { frame->flags |= SFF_SAME_IMAGE; } else { frame->flags &= ~SFF_SAME_IMAGE; } + + frame->packetlen = frame->datalen + 12; } if (codec->mutex) switch_mutex_unlock(codec->mutex); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 0a3866f580..03e83b5c43 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -9553,6 +9553,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor switch_timer_t *timer; switch_media_handle_t *smh; switch_image_t *img = frame->img; + switch_status_t encode_status; switch_assert(session); @@ -9602,26 +9603,32 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor } switch_clear_flag(frame, SFF_SAME_IMAGE); + frame->m = 0; do { frame->datalen = SWITCH_DEFAULT_VIDEO_SIZE; - switch_core_codec_encode_video(codec, frame); - - if (frame->flags & SFF_PICTURE_RESET) { - smh->video_init = 0; - smh->video_last_key_time = 0; - frame->flags &= ~SFF_PICTURE_RESET; - } + encode_status = switch_core_codec_encode_video(codec, frame); - switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME); - - status = raw_write_video(session, frame, flags, stream_id); + if (encode_status == SWITCH_STATUS_SUCCESS || encode_status == SWITCH_STATUS_MORE_DATA) { - if (status == SWITCH_STATUS_SUCCESS && session->image_write_callback) { - session->image_write_callback(session, frame, img, session->image_write_callback_user_data); + switch_assert((encode_status == SWITCH_STATUS_SUCCESS && frame->m) || !frame->m); + + if (frame->flags & SFF_PICTURE_RESET) { + smh->video_init = 0; + smh->video_last_key_time = 0; + frame->flags &= ~SFF_PICTURE_RESET; + } + + switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME); + + status = raw_write_video(session, frame, flags, stream_id); + + if (status == SWITCH_STATUS_SUCCESS && session->image_write_callback) { + session->image_write_callback(session, frame, img, session->image_write_callback_user_data); + } } - } while(frame->datalen); + } while(status == SWITCH_STATUS_SUCCESS && encode_status == SWITCH_STATUS_MORE_DATA); return status;