FS-7513: add configurable FPS for conf and default to 15
This commit is contained in:
parent
889f5265eb
commit
2c1ab14074
|
@ -183,6 +183,7 @@
|
|||
<!-- <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"/>-->
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue