*/
#include <mod_conference.h>
-static struct conference_fps FPS_VALS[] = {
- {1.0f, 1000, 90},
- {5.0f, 200, 450},
- {10.0f, 100, 900},
- {15.0f, 66, 1364},
- {16.60f, 60, 1500},
- {20.0f, 50, 4500},
- {25.0f, 40, 2250},
- {30.0f, 33, 2700},
- {33.0f, 30, 2790},
- {66.60f, 15, 6000},
- {100.0f, 10, 9000},
- {0,0,0}
-};
-
-
int conference_video_set_fps(conference_obj_t *conference, float fps)
{
- uint32_t i = 0, j = 0;
-
- for (i = 0; FPS_VALS[i].ms; i++) {
- if (FPS_VALS[i].fps == fps) {
+ uint32_t j = 0;
- conference->video_fps = FPS_VALS[i];
+ if (fps > 100) {
+ return 0;
+ }
- for (j = 0; j <= conference->canvas_count; j++) {
- if (conference->canvases[j]) {
- conference->canvases[j]->video_timer_reset = 1;
- }
- }
+ conference->video_fps.fps = fps;
+ conference->video_fps.ms = (int) 1000 / fps;
+ conference->video_fps.samples = (int) 90000 / conference->video_fps.ms;
- return 1;
+ for (j = 0; j <= conference->canvas_count; j++) {
+ if (conference->canvases[j]) {
+ conference->canvases[j]->video_timer_reset = 1;
}
}
- return 0;
+ return 1;
}
}
if (frame->timestamp) {
- switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME);
+ switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME|SFF_USE_VIDEO_TIMESTAMP);
}
frame->packetlen = frame->datalen + 12;
switch_core_session_request_video_refresh(imember->session);
}
- if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
+ if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY ||
+ switch_channel_test_flag(imember->channel, CF_VIDEO_WRITING) ||
+ switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_core_session_rwunlock(imember->session);
continue;
}
if (!imember->rec &&
(!imember->session || !switch_channel_test_flag(imember->channel, CF_VIDEO_READY) || !imember->canvas ||
+ switch_channel_test_flag(imember->channel, CF_VIDEO_WRITING) ||
switch_core_session_read_lock(imember->session) != SWITCH_STATUS_SUCCESS)) {
continue;
}
switch_core_session_request_video_refresh(imember->session);
}
- if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
+ if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY ||
+ switch_channel_test_flag(imember->channel, CF_VIDEO_WRITING) ||
+ switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_core_session_rwunlock(imember->session);
continue;
}
switch_core_media_gen_key_frame(imember->session);
}
- switch_set_flag(&write_frame, SFF_RAW_RTP);
+ switch_set_flag(&write_frame, SFF_RAW_RTP|SFF_USE_VIDEO_TIMESTAMP|SFF_RAW_RTP_PARSE_FRAME);
write_frame.img = write_img;
write_frame.packet = packet;
write_frame.data = ((uint8_t *)packet) + 12;
write_frame.datalen = 0;
write_frame.buflen = SWITCH_RTP_MAX_BUF_LEN - 12;
write_frame.packetlen = 0;
+ write_frame.timestamp = timestamp;
//switch_core_session_write_video_frame(imember->session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
switch_core_session_request_video_refresh(imember->session);
}
- if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
+ if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY ||
+ switch_channel_test_flag(imember->channel, CF_VIDEO_WRITING) ||
+ switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_core_session_rwunlock(imember->session);
continue;
}
typedef enum {
SMF_INIT = (1 << 0),
SMF_READY = (1 << 1),
- SMF_JB_PAUSED = (1 << 2)
+ SMF_JB_PAUSED = (1 << 2),
+ SMF_VB_PAUSED = (1 << 3)
} smh_flag_t;
switch_media_flow_t rmode;
switch_media_flow_t smode;
switch_thread_id_t thread_id;
+ switch_thread_id_t thread_write_lock;
uint8_t new_ice;
uint8_t new_dtls;
uint32_t sdp_bw;
engine = &smh->engines[type];
+ if (type == SWITCH_MEDIA_TYPE_VIDEO) {
+ if (engine->thread_write_lock && engine->thread_write_lock != switch_thread_self()) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+ }
if (switch_channel_test_flag(session->channel, CF_VIDEO_ONLY) && type == SWITCH_MEDIA_TYPE_AUDIO) {
return SWITCH_STATUS_SUCCESS;
return fh;
}
-static void switch_core_session_write_blank_video(switch_core_session_t *session, uint32_t ms)
+SWITCH_DECLARE(void) switch_core_session_write_blank_video(switch_core_session_t *session, uint32_t ms)
{
switch_frame_t fr = { 0 };
int i = 0;
}
+typedef struct core_fps_s {
+ float fps;
+ int ms;
+ int samples;
+} core_fps_t;
+
+static int video_get_fps(core_fps_t *fpsP, float fps)
+{
+ fpsP->fps = fps;
+ fpsP->ms = (int) 1000 / fps;
+ fpsP->samples = (int) 90000 / fpsP->ms;
+
+ return 0;
+}
static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void *obj)
{
int buflen = SWITCH_RTP_MAX_BUF_LEN;
switch_timer_t timer = { 0 };
int fps;
- switch_video_read_flag_t read_flags = SVR_FLUSH|SVR_BLOCK;
+ switch_video_read_flag_t read_flags = SVR_FLUSH;
switch_core_session_t *b_session = NULL;
-
+ core_fps_t fps_data = { 0 };
+ switch_image_t *last_frame = NULL;
+
if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
return NULL;
}
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+ switch_mutex_lock(smh->write_mutex[SWITCH_MEDIA_TYPE_VIDEO]);
+ v_engine->thread_write_lock = switch_thread_self();
+
buf = switch_core_session_alloc(session, buflen);
fr.packet = buf;
fr.packetlen = buflen;
}
- switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , 1, switch_core_session_get_pool(session));
+ video_get_fps(&fps_data, fps);
+ switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , fps_data.samples, switch_core_session_get_pool(session));
while (smh->video_write_thread_running > 0 &&
switch_channel_up_nosig(session->channel) && smh->video_write_fh && switch_test_flag(smh->video_write_fh, SWITCH_FILE_OPEN)) {
if (smh->video_write_fh && smh->video_write_fh->mm.source_fps && smh->video_write_fh->mm.source_fps != fps) {
switch_core_timer_destroy(&timer);
- switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , 1, switch_core_session_get_pool(session));
+ video_get_fps(&fps_data, fps);
+ switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , fps_data.samples, switch_core_session_get_pool(session));
}
if (smh->video_write_fh && !switch_test_flag(smh->video_write_fh, SWITCH_FILE_FLAG_VIDEO_EOF)) {
wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, read_flags);
if (wstatus == SWITCH_STATUS_SUCCESS) {
- switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_FORCE, SVR_FLUSH);
- switch_img_free(&fr.img);
+ fr.timestamp = timer.samplecount;
+ fr.flags = SFF_USE_VIDEO_TIMESTAMP|SFF_RAW_RTP|SFF_RAW_RTP_PARSE_FRAME;
+
+ if (smh->vid_params.d_width && smh->vid_params.d_height) {
+ switch_img_fit(&fr.img, smh->vid_params.d_width, smh->vid_params.d_height, SWITCH_FIT_SIZE);
+ }
+
+ switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_FORCE, 0);
+
+ switch_img_free(&last_frame);
+ last_frame = fr.img;
+ fr.img = NULL;
+
} else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
switch_set_flag_locked(smh->video_write_fh, SWITCH_FILE_FLAG_VIDEO_EOF);
}
switch_mutex_unlock(v_engine->mh.file_write_mutex);
}
+ if (last_frame) {
+ int x = 0;
+ switch_rgb_color_t bgcolor;
+ switch_color_set_rgb(&bgcolor, "#000000");
+ switch_img_fill(last_frame, 0, 0, last_frame->d_w, last_frame->d_h, &bgcolor);
+ fr.img = last_frame;
+
+ for (x = 0; x < fps / 2; x++) {
+ switch_core_timer_next(&timer);
+ fr.timestamp = timer.samplecount;
+ fr.flags = SFF_USE_VIDEO_TIMESTAMP|SFF_RAW_RTP|SFF_RAW_RTP_PARSE_FRAME;
+ switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_FORCE, 0);
+ }
+ switch_core_media_gen_key_frame(session);
+ switch_core_session_request_video_refresh(session);
+ switch_img_free(&last_frame);
+ }
+
+
switch_core_timer_destroy(&timer);
switch_core_session_rwunlock(session);
switch_core_session_rwunlock(b_session);
}
+
+ v_engine->thread_write_lock = 0;
+ switch_mutex_unlock(smh->write_mutex[SWITCH_MEDIA_TYPE_VIDEO]);
+
switch_channel_clear_flag(session->channel, CF_VIDEO_WRITING);
smh->video_write_thread_running = 0;
if (fh) {
switch_threadattr_t *thd_attr = NULL;
- switch_core_session_write_blank_video(session, 500);
+ //switch_core_session_write_blank_video(session, 500);
switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
smh->video_write_thread_running = 1;
switch_thread_join(&st, smh->video_write_thread);
switch_mutex_lock(v_engine->mh.file_write_mutex);
smh->video_write_thread = NULL;
- switch_core_session_write_blank_video(session, 500);
+ //switch_core_session_write_blank_video(session, 500);
}
smh->video_write_fh = fh;
}
- if ((val = switch_channel_get_variable(session->channel, "rtp_gen_ts_delta_audio")) && switch_true(val)) {
- flags[SWITCH_RTP_FLAG_GEN_TS_MANUAL] = 1;
- flags[SWITCH_RTP_FLAG_GEN_TS_DELTA] = 1;
- }
-
if (switch_channel_up(session->channel)) {
switch_channel_set_variable(session->channel, "rtp_use_timer_name", timer_name);
flags[SWITCH_RTP_FLAG_AUTOADJ]++;
}
- if ((val = switch_channel_get_variable(session->channel, "rtp_gen_ts_delta_video")) && switch_true(val)) {
- flags[SWITCH_RTP_FLAG_GEN_TS_MANUAL] = 1;
- flags[SWITCH_RTP_FLAG_GEN_TS_DELTA] = 1;
- }
-
if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
}
const char *val;
int ok = 0;
- if (!switch_channel_test_flag(session->channel, CF_VIDEO) &&
- (!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
+ if ((!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
if (switch_channel_test_flag(session->channel, CF_JITTERBUFFER) && switch_channel_test_cap_partner(session->channel, CC_FS_RTP)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s PAUSE Jitterbuffer\n", switch_channel_get_name(session->channel));
}
goto end;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
+
+#if 0
+ if (switch_rtp_ready(v_engine->rtp_session)) {
+
+ if (switch_test_flag(smh, SMF_VB_PAUSED)) {
+ switch_clear_flag(smh, SMF_VB_PAUSED);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "%s RESUME Video Jitterbuffer\n", switch_channel_get_name(session->channel));
+ switch_rtp_pause_jitter_buffer(v_engine->rtp_session, SWITCH_FALSE);
+
+ }
+ }
+#endif
+
if (switch_rtp_ready(a_engine->rtp_session)) {
if (switch_test_flag(smh, SMF_JB_PAUSED)) {
switch_image_t *dup_img = NULL, *img = frame->img;
switch_status_t encode_status;
switch_frame_t write_frame = {0};
- switch_rtp_engine_t *v_engine;
-
+ switch_rtp_engine_t *v_engine = NULL;
switch_assert(session);
if (!(smh = session->media_handle)) {
return SWITCH_STATUS_FALSE;
}
- if (switch_channel_test_flag(session->channel, CF_VIDEO_WRITING) && !(flags & SWITCH_IO_FLAG_FORCE)) {
- return SWITCH_STATUS_SUCCESS;
- }
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
return SWITCH_STATUS_INUSE;
}
+ v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+ if (v_engine->thread_write_lock && v_engine->thread_write_lock != switch_thread_self()) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
if (!smh->video_init && smh->mparams->video_key_first && (now - smh->video_last_key_time) > smh->mparams->video_key_first) {
switch_core_media_gen_key_frame(session);
if (!img) {
switch_status_t vstatus;
-
- if (!switch_rtp_test_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_GEN_TS_MANUAL)) {
- switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_GEN_TS_DELTA);
- }
vstatus = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
switch_goto_status(vstatus, done);
- } else {
- if (!switch_rtp_test_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_GEN_TS_MANUAL)) {
- switch_rtp_clear_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_GEN_TS_DELTA);
- }
}
img = dup_img;
}
+
+ if (!switch_channel_test_flag(session->channel, CF_VIDEO_WRITING)) {
+ smh->vid_params.d_width = img->d_w;
+ smh->vid_params.d_height = img->d_h;
+ }
if (session->bugs) {
switch_media_bug_t *bp;
}
+SWITCH_DECLARE(switch_bool_t) switch_core_session_transcoding(switch_core_session_t *session_a, switch_core_session_t *session_b, switch_media_type_t type)
+{
+ switch_bool_t transcoding = SWITCH_FALSE;
+
+ switch(type) {
+ case SWITCH_MEDIA_TYPE_AUDIO:
+ transcoding = (session_a->read_codec->implementation->impl_id != session_b->read_codec->implementation->impl_id || session_a->read_impl.decoded_bytes_per_packet != session_b->read_impl.decoded_bytes_per_packet);
+ break;
+ case SWITCH_MEDIA_TYPE_VIDEO:
+ transcoding = (switch_channel_test_flag(session_a->channel, CF_VIDEO_DECODED_READ) ||
+ switch_channel_test_flag(session_b->channel, CF_VIDEO_DECODED_READ));
+ break;
+ default:
+ break;
+ }
+
+ return transcoding;
+
+}
+
+SWITCH_DECLARE(void) switch_core_session_passthru(switch_core_session_t *session, switch_media_type_t type, switch_bool_t on)
+{
+ switch_rtp_engine_t *engine;
+
+ if (!session->media_handle) return;
+
+ engine = &session->media_handle->engines[type];
+
+
+ if (switch_rtp_ready(engine->rtp_session)) {
+ if (on) {
+ switch_rtp_set_flag(engine->rtp_session, SWITCH_RTP_FLAG_PASSTHRU);
+ } else {
+ switch_rtp_clear_flag(engine->rtp_session, SWITCH_RTP_FLAG_PASSTHRU);
+ }
+
+ if (type == SWITCH_MEDIA_TYPE_VIDEO) {
+ switch_core_session_request_video_refresh(session);
+ if (!on) {
+ switch_core_media_gen_key_frame(session);
+ }
+ }
+
+ }
+
+}
+
SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
int stream_id)
{