]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7500: codec tweaks
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 29 Jan 2015 22:37:29 +0000 (16:37 -0600)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:46:56 +0000 (12:46 -0500)
src/mod/codecs/mod_openh264/mod_openh264.cpp
src/mod/codecs/mod_vpx/mod_vpx.c
src/switch_core_media.c

index fa918565fc8e5b08a9ef33e2673cc547e04e1b72..0074e6146edb855d9fd8c38bcc71395f96be3fd6 100644 (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;
        }
 
index 01fe627b4ea8d3e443f773c5f5bdc9054db69458..3bfa7ba59cd8533a67e6d9d0694544fb9cd478be 100644 (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);
        }
 
index 1098c75c5261912d17cdf10f760ae0c2683610ad..3ef020dbd29a3b6a6409b677fb9d218a737c7469 100644 (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;
                        }