FS-7500: codec tweaks

This commit is contained in:
Anthony Minessale 2015-01-29 16:37:29 -06:00 committed by Michael Jerris
parent 13c3f053ab
commit ac140fb6dd
3 changed files with 110 additions and 65 deletions

View File

@ -39,7 +39,7 @@
#include "codec_api.h"
//#include "inc/logging.h" // for debug
#define FPS 30.0f // frame rate
#define FPS 15.0f // frame rate
#define H264_NALU_BUFFER_SIZE 65536
#define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE //NALU Slice Size
@ -70,66 +70,90 @@ typedef struct h264_codec_context_s {
int need_key_frame;
switch_size_t last_received_timestamp;
switch_bool_t last_received_complete_picture;
switch_codec_settings_t codec_settings;
unsigned int bandwidth;
} h264_codec_context_t;
int FillSpecificParameters(SEncParamExt& param) {
int FillSpecificParameters(h264_codec_context_t *context) {
SEncParamExt *param;
param = &context->encoder_params;
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) {
context->bandwidth = context->codec_settings.video.bandwidth;
} else {
context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height / 1024;
}
if (context->bandwidth > 5120) {
context->bandwidth = 5120;
}
/* Test for temporal, spatial, SNR scalability */
param.iPicWidth = 1280; // width of picture in samples
param.iPicHeight = 720; // height of picture in samples
param.iTargetBitrate = 1250000;//1280 * 720 * 8; // target bitrate desired
param.iRCMode = RC_QUALITY_MODE; // rc mode control
param.iTemporalLayerNum = 1; // layer number at temporal level
param.iSpatialLayerNum = 1; // layer number at spatial level
param.bEnableDenoise = 0; // denoise control
param.bEnableBackgroundDetection = 1; // background detection control
param.bEnableSceneChangeDetect= 1;
//param.bEnableFrameSkip = 1;
param.iMultipleThreadIdc= 1;
param.bEnableAdaptiveQuant = 1; // adaptive quantization control
param.bEnableLongTermReference = 0; // long term reference control
param.iLtrMarkPeriod = 30;
param.iLoopFilterAlphaC0Offset= 0;
param.iLoopFilterBetaOffset= 0;
param.iComplexityMode = MEDIUM_COMPLEXITY;
param.uiIntraPeriod = FPS * 3; // period of Intra frame
param->iPicWidth = 1280; // width of picture in samples
param->iPicHeight = 720; // height of picture in samples
param->iTargetBitrate = context->bandwidth;
param->iRCMode = RC_QUALITY_MODE; // rc mode control
param->iTemporalLayerNum = 1; // layer number at temporal level
param->iSpatialLayerNum = 1; // layer number at spatial level
param->bEnableDenoise = 0; // denoise control
param->bEnableBackgroundDetection = 1; // background detection control
param->bEnableSceneChangeDetect= 1;
//param->bEnableFrameSkip = 1;
param->iMultipleThreadIdc= 1;
param->bEnableAdaptiveQuant = 1; // adaptive quantization control
param->bEnableLongTermReference = 0; // long term reference control
param->iLtrMarkPeriod = 30;
param->iLoopFilterAlphaC0Offset= 0;
param->iLoopFilterBetaOffset= 0;
param->iComplexityMode = MEDIUM_COMPLEXITY;
param->uiIntraPeriod = FPS * 3; // period of Intra frame
#ifdef MT_ENABLED
param.bEnableSpsPpsIdAddition = 1;
param->bEnableSpsPpsIdAddition = 1;
#else
param.bEnableSpsPpsIdAddition = 0;
param->bEnableSpsPpsIdAddition = 0;
#endif
param.bPrefixNalAddingCtrl = 0;
param->bPrefixNalAddingCtrl = 0;
int iIndexLayer = 0;
param.sSpatialLayers[iIndexLayer].iVideoWidth = 1280;
param.sSpatialLayers[iIndexLayer].iVideoHeight = 720;
param.sSpatialLayers[iIndexLayer].fFrameRate = (double) (FPS * 1.0f);
// param.sSpatialLayers[iIndexLayer].iQualityLayerNum = 1;
param.sSpatialLayers[iIndexLayer].iSpatialBitrate = param.iTargetBitrate;
//param.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = param.iTargetBitrate;
//param.sSpatialLayers[iIndexLayer].uiLevelIdc = LEVEL_1_3;
param.sSpatialLayers[iIndexLayer].uiProfileIdc = PRO_BASELINE;
param->sSpatialLayers[iIndexLayer].iVideoWidth = 1280;
param->sSpatialLayers[iIndexLayer].iVideoHeight = 720;
param->sSpatialLayers[iIndexLayer].fFrameRate = (double) (FPS * 1.0f);
// param->sSpatialLayers[iIndexLayer].iQualityLayerNum = 1;
param->sSpatialLayers[iIndexLayer].iSpatialBitrate = param->iTargetBitrate;
//param->sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = param->iTargetBitrate;
//param->sSpatialLayers[iIndexLayer].uiLevelIdc = LEVEL_1_3;
param->sSpatialLayers[iIndexLayer].uiProfileIdc = PRO_BASELINE;
param.iUsageType = CAMERA_VIDEO_REAL_TIME;
param.bEnableFrameCroppingFlag = 1;
//param.iMaxBitrate = 1250000;
//param.iTargetBitrate = 1250000;
param->iUsageType = CAMERA_VIDEO_REAL_TIME;
param->bEnableFrameCroppingFlag = 1;
//param->iMaxBitrate = 1250000;
//param->iTargetBitrate = 1250000;
#ifdef MT_ENABLED
param.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_DYN_SLICE;
param.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = SLICE_SIZE;
param.uiMaxNalSize = SLICE_SIZE;
param->sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_DYN_SLICE;
param->sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = SLICE_SIZE;
param->uiMaxNalSize = SLICE_SIZE;
#else
param.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
param->sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
#endif
float fMaxFr = param.sSpatialLayers[param.iSpatialLayerNum - 1].fFrameRate;
for (int32_t i = param.iSpatialLayerNum - 2; i >= 0; --i) {
if (param.sSpatialLayers[i].fFrameRate > fMaxFr + EPSN) {
fMaxFr = param.sSpatialLayers[i].fFrameRate;
float fMaxFr = param->sSpatialLayers[param->iSpatialLayerNum - 1].fFrameRate;
for (int32_t i = param->iSpatialLayerNum - 2; i >= 0; --i) {
if (param->sSpatialLayers[i].fFrameRate > fMaxFr + EPSN) {
fMaxFr = param->sSpatialLayers[i].fFrameRate;
}
}
param.fMaxFrameRate = fMaxFr;
param->fMaxFrameRate = fMaxFr;
return 0;
}
@ -376,6 +400,10 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
context = (h264_codec_context_t*)switch_core_alloc(codec->memory_pool, sizeof(h264_codec_context_t));
memset(context, 0, sizeof(*context));
if (codec_settings) {
context->codec_settings = *codec_settings;
}
if (decoding) {
WelsCreateDecoder(&context->decoder);
@ -407,7 +435,7 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
goto error;
}
FillSpecificParameters(context->encoder_params);
FillSpecificParameters(context);
}
//if (encoding | decoding) WelsStderrSetTraceLevel(10);
@ -627,9 +655,9 @@ end:
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
}
if (frame->img) {
switch_set_flag(frame, SFF_USE_VIDEO_TIMESTAMP);
} else {
if (!frame->img) {
//switch_set_flag(frame, SFF_USE_VIDEO_TIMESTAMP);
//} else {
status = SWITCH_STATUS_MORE_DATA;
}

View File

@ -38,7 +38,6 @@
#include <vpx/vp8dx.h>
#include <vpx/vp8.h>
#define FPS 15
#define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE
#define KEY_FRAME_MIN_FREQ 1000000
@ -64,12 +63,12 @@ struct vpx_context {
int fps;
int format;
int intra_period;
int pts;
int num;
int partition_index;
const vpx_codec_cx_pkt_t *pkt;
int pkt_pos;
vpx_codec_iter_t iter;
uint32_t last_ts;
vpx_codec_ctx_t decoder;
uint8_t decoder_init;
switch_buffer_t *vpx_packet_buffer;
@ -99,15 +98,13 @@ static switch_status_t init_codec(switch_codec_t *codec)
if (context->codec_settings.video.bandwidth) {
context->bandwidth = context->codec_settings.video.bandwidth;
} else {
int x = (context->codec_settings.video.width / 100) + 1;
context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height * x;
context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height / 1024;
}
if (context->bandwidth > 1250000) {
context->bandwidth = 1250000;
if (context->bandwidth > 5120) {
context->bandwidth = 5120;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_NOTICE,
"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);
@ -119,7 +116,7 @@ static switch_status_t init_codec(switch_codec_t *codec)
config->g_h = context->codec_settings.video.height;
config->rc_target_bitrate = context->bandwidth;
config->g_timebase.num = 1;
config->g_timebase.den = 1000;
config->g_timebase.den = 90000;
config->g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS;
config->g_lag_in_frames = 0; // 0- no frame lagging
@ -374,11 +371,10 @@ static switch_status_t consume_partition(vpx_context_t *context, switch_frame_t
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *frame)
{
vpx_context_t *context = (vpx_context_t *)codec->private_info;
uint32_t duration = 90000 / FPS;
int width = 0;
int height = 0;
vpx_enc_frame_flags_t vpx_flags = 0;
int32_t dur = 0;
if (frame->flags & SFF_SAME_IMAGE) {
return consume_partition(context, frame);
@ -423,7 +419,20 @@ 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) {
if (context->last_ts) {
dur = frame->timestamp - context->last_ts;
if (dur < 0 || dur > 90000) {
dur = 0;
}
}
if (!dur) {
dur = 1;
}
if (vpx_codec_encode(&context->encoder, (vpx_image_t *) frame->img, frame->timestamp, dur, 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);
@ -431,8 +440,8 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *
return SWITCH_STATUS_FALSE;
}
context->pts += duration;
context->iter = NULL;
context->last_ts = frame->timestamp;
return consume_partition(context, frame);
}
@ -521,6 +530,7 @@ static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *
// possible packet loss
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Reset\n");
context->need_key_frame = 1;
context->last_ts = 0;
switch_goto_status(SWITCH_STATUS_RESTART, end);
}

View File

@ -1515,7 +1515,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
session->media_handle->mparams = params;
if (!session->media_handle->mparams->video_key_freq) {
session->media_handle->mparams->video_key_freq = 5000000;
session->media_handle->mparams->video_key_freq = 30000000;
}
if (!session->media_handle->mparams->video_key_first) {
@ -2366,14 +2366,21 @@ static void switch_core_session_parse_codec_settings(switch_core_session_t *sess
break;
case SWITCH_MEDIA_TYPE_VIDEO:
{
const char *bwv = switch_channel_get_variable(session->channel, "video_codec_bandwidth");
const char *bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth");
uint32_t bw = 0;
if (!bwv) {
bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth_out");
}
if (bwv && (bw = (uint32_t) atol(bwv))) {
if (switch_stristr("kb", bwv)) {
bw *= 125;
if (switch_stristr("KB", bwv)) {
bw *= 8;
} else if (switch_stristr("mb", bwv)) {
bw *= 125000;
bw *= 1024;
} else if (switch_stristr("MB", bwv)) {
bw *= 8192;
}
engine->codec_settings.video.bandwidth = bw;
}