]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7513: add configurable FPS for conf and default to 15
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 13 Feb 2015 20:10:42 +0000 (14:10 -0600)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:02 +0000 (12:47 -0500)
conf/vanilla/autoload_configs/conference.conf.xml
src/include/switch_types.h
src/mod/applications/mod_conference/mod_conference.c
src/mod/codecs/mod_vpx/mod_vpx.c
src/switch_rtp.c

index 3b3342b1e66a6dbc92e8bcbee37c2fb335202f2b..0f90510736ecd7bea6eda1247b733b11876bbdd9 100644 (file)
       <!-- <param name="video-canvas-bgcolor" value="#333333"/> -->
       <!-- <param name="video-layout-bgcolor" value="#000000"/> -->
       <!-- <param name="video-codec-bandwidth" value="2mb"/> -->
+      <!-- <param name="video-fps" value="15"/> -->
 
 
       <!--<param name="tts-engine" value="flite"/>-->
index 068e5d0849bd18326d422595eab8abfe40ffcd99..4520ca23c6668fce7046afcc2aaac6e00cc37c88 100644 (file)
@@ -2193,7 +2193,8 @@ typedef switch_status_t (*switch_core_codec_video_decode_func_t) (switch_codec_t
 
 typedef enum {
        SCC_VIDEO_REFRESH = 0,
-       SCC_VIDEO_BANDWIDTH
+       SCC_VIDEO_BANDWIDTH,
+       SCC_VIDEO_RESET
 } switch_codec_control_command_t;
 
 typedef enum {
index 9533025d58e8709626def4c6b28ee2e1457dac09..8f014358272989f5e7c66367784397ada38bda0e 100644 (file)
@@ -55,6 +55,27 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown);
 SWITCH_MODULE_DEFINITION(mod_conference, mod_conference_load, mod_conference_shutdown, NULL);
 
+struct conf_fps {
+       float fps;
+       int ms;
+       int samples;
+};
+
+static struct conf_fps FPS_VALS[] = { 
+       {1.0f, 1000, 90},
+       {5.0f, 200, 450},
+       {10.0f, 100, 900},
+       {15.0f, 66, 1364},
+       {16.60f, 60, 1500},
+       {25.0f, 40, 2250},
+       {30.0f, 33, 2700},
+       {33.0f, 30, 2790},
+       {66.60f, 15, 6000},
+       {100.0f, 10, 9000},
+       {0,0,0}
+};
+
+
 typedef enum {
        CONF_SILENT_REQ = (1 << 0),
        CONF_SILENT_DONE = (1 << 1)
@@ -380,6 +401,7 @@ typedef struct mcu_canvas_s {
        int layout_floor_id;
        switch_rgb_color_t bgcolor;
        switch_mutex_t *mutex;
+       switch_timer_t timer;
        switch_memory_pool_t *pool;
 } mcu_canvas_t;
 
@@ -430,6 +452,7 @@ typedef struct conference_obj {
        char *video_layout_group;
        char *video_canvas_bgcolor;
        char *video_layout_bgcolor;
+       int video_timer_reset;
        int32_t video_write_bandwidth;
        switch_codec_settings_t video_codec_settings;
        uint32_t canvas_width;
@@ -518,6 +541,7 @@ typedef struct conference_obj {
        mcu_canvas_t *canvas;
        switch_hash_t *layout_hash;
        switch_hash_t *layout_group_hash;
+       struct conf_fps video_fps;
 } conference_obj_t;
 
 /* Relationship with another member */
@@ -640,6 +664,22 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
 
 SWITCH_STANDARD_API(conf_api_main);
 
+
+static int conference_set_fps(conference_obj_t *conference, float fps)
+{
+       int i = 0;
+
+       for (i = 0; FPS_VALS[i].ms; i++) {
+               if (FPS_VALS[i].fps == fps) {
+                       conference->video_fps = FPS_VALS[i];
+                       conference->video_timer_reset = 1;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 static switch_status_t conference_outcall(conference_obj_t *conference,
                                                                                  char *conference_name,
                                                                                  switch_core_session_t *session,
@@ -1303,7 +1343,8 @@ typedef struct codec_set_s {
 } codec_set_t;
 
 static void write_canvas_image_to_codec_group(conference_obj_t *conference, codec_set_t *codec_set,
-                                                                                         int codec_index, uint32_t timestamp, switch_bool_t need_refresh, switch_bool_t need_keyframe)
+                                                                                         int codec_index, uint32_t timestamp, switch_bool_t need_refresh, 
+                                                                                         switch_bool_t need_keyframe, switch_bool_t need_reset)
 
 {
        conference_member_t *imember;
@@ -1319,6 +1360,12 @@ static void write_canvas_image_to_codec_group(conference_obj_t *conference, code
        frame->m = 0;
        frame->timestamp = timestamp;
 
+       if (need_reset) {
+               int type = 1; // sum flags: 1 encoder; 2; decoder
+               switch_core_codec_control(&codec_set->codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, NULL, NULL);
+               need_refresh = SWITCH_TRUE;
+       }
+
        if (need_refresh || need_keyframe) {
                switch_core_codec_control(&codec_set->codec, SCC_VIDEO_REFRESH, SCCT_NONE, NULL, NULL, NULL);
        }
@@ -1388,7 +1435,6 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
        switch_codec_t *check_codec = NULL;
        codec_set_t *write_codecs[MAX_MUX_CODECS] = { 0 };
        int buflen = SWITCH_RECOMMENDED_BUFFER_SIZE * 2;
-       switch_timer_t timer = { 0 };
        int i = 0;
        int used = 0;
        uint32_t video_key_freq = 30000000;
@@ -1419,17 +1465,23 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
 
        init_canvas(conference, vlayout);
 
-       switch_core_timer_init(&timer, "soft", 33, 3000, conference->pool);
-
+       conference->video_timer_reset = 1;
+       
        if (!switch_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) {
                packet = switch_core_alloc(conference->pool, SWITCH_RECOMMENDED_BUFFER_SIZE);
        }
 
        while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT) && switch_test_flag(conference, CFLAG_VIDEO_MUXING)) {
-               switch_bool_t need_refresh = SWITCH_FALSE, need_keyframe = SWITCH_FALSE;
+               switch_bool_t need_refresh = SWITCH_FALSE, need_keyframe = SWITCH_FALSE, need_reset = SWITCH_FALSE;
                switch_time_t now;
-                       
-               switch_core_timer_next(&timer);
+
+               if (conference->video_timer_reset) {
+                       conference->video_timer_reset = 0;
+                       switch_core_timer_init(&conference->canvas->timer, "soft", conference->video_fps.ms, conference->video_fps.samples, NULL);
+                       need_reset = SWITCH_TRUE;
+               }
+               
+               switch_core_timer_next(&conference->canvas->timer);
 
                now = switch_micro_time_now();
 
@@ -1600,7 +1652,8 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
                if (switch_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) {
                        for (i = 0; write_codecs[i] && switch_core_codec_ready(&write_codecs[i]->codec) && i < MAX_MUX_CODECS; i++) {
                                write_codecs[i]->frame.img = conference->canvas->img;
-                               write_canvas_image_to_codec_group(conference, write_codecs[i], i, timer.samplecount, need_refresh, need_keyframe);
+                               write_canvas_image_to_codec_group(conference, write_codecs[i], i, 
+                                                                                                 conference->canvas->timer.samplecount, need_refresh, need_keyframe, need_reset);
 
                                if (conference->video_write_bandwidth) {
                                        switch_core_codec_control(&write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, SCCT_INT, &conference->video_write_bandwidth, NULL, NULL);
@@ -1658,7 +1711,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
                }
        }
 
-       switch_core_timer_destroy(&timer);
+       switch_core_timer_destroy(&conference->canvas->timer);
 
        destroy_canvas(&conference->canvas);
 
@@ -7761,6 +7814,32 @@ static switch_status_t conf_api_sub_vid_bandwidth(conference_obj_t *conference,
        return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t conf_api_sub_vid_fps(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
+{
+       float fps = 0;
+
+       if (!argv[2]) {
+               stream->write_function(stream, "Invalid input\n");
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (!conference->canvas) {
+               stream->write_function(stream, "Conference is not in mixing mode\n");
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       fps = atof(argv[2]);
+
+       if (conference_set_fps(conference, fps)) {
+               stream->write_function(stream, "FPS set to [%s]\n", argv[2]);
+       } else {
+               stream->write_function(stream, "Invalid FPS [%s]\n", argv[2]);
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+       
+}
+
 static switch_status_t conf_api_sub_vid_layout(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
 {
        video_layout_t *vlayout = NULL;
@@ -9468,6 +9547,7 @@ static api_command_t conf_api_sub_commands[] = {
        {"vid-banner", (void_fn_t) & conf_api_sub_vid_banner, CONF_API_SUB_MEMBER_TARGET, "vid-banner", "<member_id|last> <text>"},
        {"clear-vid-floor", (void_fn_t) & conf_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""},
        {"vid-layout", (void_fn_t) & conf_api_sub_vid_layout, CONF_API_SUB_ARGS_SPLIT, "vid-layout", "<layout name>"},
+       {"vid-fps", (void_fn_t) & conf_api_sub_vid_fps, CONF_API_SUB_ARGS_SPLIT, "vid-fps", "<fps>"},
        {"vid-bandwidth", (void_fn_t) & conf_api_sub_vid_bandwidth, CONF_API_SUB_ARGS_SPLIT, "vid-bandwidth", "<BW>"}
 };
 
@@ -11212,6 +11292,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
        char *video_canvas_bgcolor = NULL;
        char *video_layout_bgcolor = NULL;
        char *video_codec_bandwidth = NULL;
+       float fps = 15.0f;
        uint32_t max_members = 0;
        uint32_t announce_count = 0;
        char *maxmember_sound = NULL;
@@ -11367,6 +11448,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
                                video_layout_bgcolor= val;
                        } else if (!strcasecmp(var, "video-canvas-size") && !zstr(val)) {
                                video_canvas_size = val;
+                       } else if (!strcasecmp(var, "video-fps") && !zstr(val)) {
+                               fps = atof(val);
                        } else if (!strcasecmp(var, "video-codec-bandwidth") && !zstr(val)) {
                                video_codec_bandwidth = val;
                        } else if (!strcasecmp(var, "exit-sound") && !zstr(val)) {
@@ -11580,6 +11663,14 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
 
        conference->video_canvas_bgcolor = switch_core_strdup(conference->pool, video_canvas_bgcolor);
        conference->video_layout_bgcolor = switch_core_strdup(conference->pool, video_layout_bgcolor);
+
+       if (fps) {
+               conference_set_fps(conference, fps);
+       }
+
+       if (!conference->video_fps.ms) {
+               conference_set_fps(conference, 30);
+       }
        
        if (video_canvas_size && video_layout_name) {
                int w = 0, h = 0;
index d1cbbe47609a4d2482b5d2a04a4e9395c7deb0ca..67730514d08f7b55d9e0069fe5391d55de29ea9c 100644 (file)
@@ -76,6 +76,8 @@ struct vpx_context {
        switch_size_t last_received_timestamp;
        switch_bool_t last_received_complete_picture;
        int need_key_frame;
+       int need_encoder_reset;
+       int need_decoder_reset;
        int32_t change_bandwidth;
        uint64_t framecount;
        uint64_t framesum;
@@ -387,6 +389,15 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *
                return consume_partition(context, frame);
        }
 
+       if (context->need_encoder_reset != 0) {
+               vpx_codec_destroy(&context->encoder);
+               context->framesum = 0;
+               context->framecount = 0;
+               context->encoder_init = 0;
+               init_codec(codec);
+               context->need_encoder_reset = 0;
+       }
+
        //d_w and d_h are messed up
        //printf("WTF %d %d\n", frame->img->d_w, frame->img->d_h);
 
@@ -420,7 +431,6 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *
                init_codec(codec);
        }
 
-
        if (context->need_key_frame != 0) {
                // force generate a key frame
                switch_time_t now = switch_micro_time_now();
@@ -535,6 +545,15 @@ static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *
        vpx_codec_ctx_t *decoder = NULL;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
        int is_keyframe = ((*(unsigned char *)frame->data) & 0x01) ? 0 : 1;
+
+
+
+       if (context->need_decoder_reset != 0) {
+               vpx_codec_destroy(&context->decoder);
+               context->decoder_init = 0;
+               init_codec(codec);
+               context->need_decoder_reset = 0;
+       }
        
        if (!context->decoder_init) {
                init_codec(codec);
@@ -586,6 +605,7 @@ static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *
 
                //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffered: %" SWITCH_SIZE_T_FMT ", key: %d\n", len, keyframe);
 
+
                err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0);
 
                if (err != VPX_CODEC_OK) {
@@ -643,6 +663,17 @@ static switch_status_t switch_vpx_control(switch_codec_t *codec,
        vpx_context_t *context = (vpx_context_t *)codec->private_info;
 
        switch(cmd) {
+       case SCC_VIDEO_RESET:
+               {
+                       int mask = *((int *) cmd_data);
+                       if (mask & 1) {
+                               context->need_encoder_reset = 1;
+                       }
+                       if (mask & 2) {
+                               context->need_decoder_reset = 1;
+                       }
+               }
+               break;
        case SCC_VIDEO_REFRESH:
                context->need_key_frame = 1;            
                break;
index 2da7671b4a15db8a10e966983fcad1adbfa3e1a0..2e5661cb7788e183d7d6cd9ff34b2dafb3b7271e 100644 (file)
@@ -6747,6 +6747,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 
                if (ntohl(send_msg->header.ts) != rtp_session->ts_norm.last_frame) {
                        rtp_session->ts_norm.delta = ntohl(send_msg->header.ts) - rtp_session->ts_norm.last_frame;
+                       //printf("WTF %d\n", rtp_session->ts_norm.delta);
                        rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
                        //switch_core_timer_sync(&rtp_session->timer);
                        //printf("W00t %d\n", rtp_session->timer.samplecount);