#define switch_core_media_gen_key_frame(_session) switch_core_media_codec_control(_session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_IO_WRITE, \
SCC_VIDEO_REFRESH, SCCT_NONE, NULL, NULL, NULL) \
+#define switch_core_media_write_bandwidth(_session, _val) switch_core_media_codec_control(_session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_IO_WRITE, \
+ SCC_VIDEO_BANDWIDTH, SCCT_STRING, _val, NULL, NULL) \
+
SWITCH_DECLARE(switch_timer_t *) switch_core_media_get_timer(switch_core_session_t *session, switch_media_type_t mtype);
SWITCH_DECLARE(void) switch_core_media_start_video_function(switch_core_session_t *session, switch_video_function_t video_function, void *user_data);
typedef switch_status_t (*switch_core_codec_video_decode_func_t) (switch_codec_t *codec, switch_frame_t *frame);
typedef enum {
- SCC_VIDEO_REFRESH = 0
+ SCC_VIDEO_REFRESH = 0,
+ SCC_VIDEO_BANDWIDTH
} switch_codec_control_command_t;
typedef enum {
- SCCT_NONE = 0
+ SCCT_NONE = 0,
+ SCCT_STRING,
+ SCCT_INT,
} switch_codec_control_type_t;
typedef enum {
if (bwv && (bw = (int32_t) atol(bwv))) {
if (bw < 0) return 0;
- if (switch_stristr("KB", bwv)) {
+ if (!strcasecmp(bwv, "auto")) {
+ return -1;
+ } else if (switch_stristr("KB", bwv)) {
bw *= 8;
} else if (switch_stristr("mb", bwv)) {
bw *= 1024;
char *video_layout_name;
char *video_layout_group;
char *video_canvas_bgcolor;
- uint32_t video_codec_bandwidth;
+ int32_t video_write_bandwidth;
+ switch_codec_settings_t video_codec_settings;
uint32_t canvas_width;
uint32_t canvas_height;
uint32_t terminate_on_silence;
if (imember->video_codec_index < 0) {
write_codecs[i] = switch_core_alloc(conference->pool, sizeof(codec_set_t));
- if (switch_core_codec_copy(check_codec, &write_codecs[i]->codec, conference->pool) == SWITCH_STATUS_SUCCESS) {
+ if (switch_core_codec_copy(check_codec, &write_codecs[i]->codec,
+ &conference->video_codec_settings, conference->pool) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Setting up video write codec %s at slot %d\n", write_codecs[i]->codec.implementation->iananame, i);
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);
+
+ if (conference->video_write_bandwidth) {
+ switch_core_codec_control(&write_codecs[i]->codec, SCC_VIDEO_BANDWIDTH, SCCT_INT, &conference->video_write_bandwidth, NULL, NULL);
+ conference->video_write_bandwidth = 0;
+ }
+
}
} else {
switch_mutex_lock(conference->member_mutex);
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t conf_api_sub_vid_bandwidth(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
+{
+ if (!switch_test_flag(conference, CFLAG_MINIMIZE_VIDEO_ENCODING)) {
+ stream->write_function(stream, "Bandwidth control not available.\n");
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!argv[2]) {
+ stream->write_function(stream, "Invalid input\n");
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ conference->video_write_bandwidth = switch_parse_bandwidth_string(argv[2]);
+ stream->write_function(stream, "Set Bandwidth %d\n", conference->video_write_bandwidth);
+
+ 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;
{"floor", (void_fn_t) & conf_api_sub_floor, CONF_API_SUB_MEMBER_TARGET, "floor", "<member_id|last>"},
{"vid-floor", (void_fn_t) & conf_api_sub_vid_floor, CONF_API_SUB_MEMBER_TARGET, "vid-floor", "<member_id|last> [force]"},
{"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-layout", (void_fn_t) & conf_api_sub_vid_layout, CONF_API_SUB_ARGS_SPLIT, "vid-layout", "<layout name>"},
+ {"vid-bandwidth", (void_fn_t) & conf_api_sub_vid_bandwidth, CONF_API_SUB_ARGS_SPLIT, "vid-bandwidth", "<BW>"}
};
#define CONFFUNCAPISIZE (sizeof(conf_api_sub_commands)/sizeof(conf_api_sub_commands[0]))
conference_parse_layouts(conference);
if (video_codec_bandwidth) {
- conference->video_codec_bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth);
+ conference->video_codec_settings.video.bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth);
}
if (video_layout_name) {
int last_nalu_data_pos;
int nalu_eat;
int nalu_28_start;
+ int change_bandwidth;
SSourcePicture pic;
ISVCDecoder *decoder;
{
int i;
- context->encoder_params.iPicWidth = width;
- context->encoder_params.iPicHeight = height;
+ if (width) context->encoder_params.iPicWidth = width;
+ if (height) context->encoder_params.iPicHeight = height;
//context->encoder_params.iTargetBitrate = width * height * 8;
for (int i=0; i<context->encoder_params.iSpatialLayerNum; i++) {
context->encoder_params.sSpatialLayers[i].iVideoWidth = width;
context->encoder_params.sSpatialLayers[i].iVideoHeight = height;
}
+ FillSpecificParameters(context);
/* just do it, the encoder will Uninitialize first by itself if already initialized */
if (cmResultSuccess != context->encoder->InitializeExt(&context->encoder_params)) {
return SWITCH_STATUS_FALSE;
}
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Codec ready; picture size %dx%d Bandwidth: %d\n",
+ context->encoder_params.iPicWidth, context->encoder_params.iPicHeight, context->codec_settings.video.bandwidth);
+
+
context->encoder_initialized = SWITCH_TRUE;
return SWITCH_STATUS_SUCCESS;
}
init_encoder(context, width, height);
}
+
+ if (context->change_bandwidth) {
+ context->codec_settings.video.bandwidth = context->change_bandwidth;
+ context->change_bandwidth = 0;
+ init_encoder(context, 0, 0);
+ }
+
if (width != context->encoder_params.iPicWidth || height != context->encoder_params.iPicHeight ) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "picture size changed from %dx%d to %dx%d, reinitializing encoder",
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "picture size changed from %dx%d to %dx%d, reinitializing encoder\n",
context->encoder_params.iPicWidth, context->encoder_params.iPicHeight, width, height);
+
init_encoder(context, width, height);
}
case SCC_VIDEO_REFRESH:
context->need_key_frame = 1;
break;
+ case SCC_VIDEO_BANDWIDTH:
+ {
+ switch(ctype) {
+ case SCCT_INT:
+ context->change_bandwidth = *((int *) cmd_data);
+ break;
+ case SCCT_STRING:
+ {
+ char *bwv = (char *) cmd_data;
+ context->change_bandwidth = switch_parse_bandwidth_string(bwv);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
default:
break;
}
switch_size_t last_received_timestamp;
switch_bool_t last_received_complete_picture;
int need_key_frame;
+ int32_t change_bandwidth;
uint64_t framecount;
uint64_t framesum;
};
context->codec_settings.video.height = 720;
}
+ if (context->codec_settings.video.bandwidth == -1) {
+ context->codec_settings.video.bandwidth = 0;
+ }
+
if (context->codec_settings.video.bandwidth) {
context->bandwidth = context->codec_settings.video.bandwidth;
} else {
init_codec(codec);
}
+ if (context->change_bandwidth) {
+ context->codec_settings.video.bandwidth = context->change_bandwidth;
+ context->change_bandwidth = 0;
+ init_codec(codec);
+ }
+
+
if (context->need_key_frame != 0) {
// force generate a key frame
switch_time_t now = switch_micro_time_now();
case SCC_VIDEO_REFRESH:
context->need_key_frame = 1;
break;
+ case SCC_VIDEO_BANDWIDTH:
+ {
+ switch(ctype) {
+ case SCCT_INT:
+ context->change_bandwidth = *((int *) cmd_data);
+ break;
+ case SCCT_STRING:
+ {
+ char *bwv = (char *) cmd_data;
+ context->change_bandwidth = switch_parse_bandwidth_string(bwv);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
default:
break;
}
}
smh->last_codec_refresh = now;
+ switch_channel_set_flag(session->channel, CF_VIDEO_REFRESH_REQ);
}
- switch_channel_set_flag(session->channel, CF_VIDEO_REFRESH_REQ);
return switch_core_codec_control(codec, cmd, ctype, cmd_data, rtype, ret_data);
}