#include <libavutil/channel_layout.h>
// #include <libavutil/timestamp.h>
#include <libavresample/avresample.h>
+#define DFT_RECORD_OFFSET 350
SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load);
SWITCH_MODULE_DEFINITION(mod_avformat, mod_avformat_load, NULL, NULL);
char buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
switch_size_t datalen = codec.implementation->decoded_bytes_per_packet;
switch_size_t samples = datalen / 2 / codec.implementation->number_of_channels;
- int offset = 1200;
+ int offset = DFT_RECORD_OFFSET;
int fps = codec.implementation->actual_samples_per_second / samples;
int lead_frames = (offset * fps) / 1000;
memset(context, 0, sizeof(av_file_context_t));
- context->offset = 1200;
+ context->offset = DFT_RECORD_OFFSET;
if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
context->offset = atoi(tmp);
}
switch_vid_params_t vid_params;
switch_file_handle_t *video_read_fh;
switch_file_handle_t *video_write_fh;
+
+ uint64_t vid_frames;
+ time_t vid_started;
};
}
}
+static uint32_t round_to_step(uint32_t num, uint32_t step)
+{
+ uint32_t r;
+ uint32_t x;
+
+ if (!num) return 0;
+
+ r = (num % step);
+ x = num - r;
+
+ if (r > step / 2) {
+ x += step;
+ }
+
+ return x;
+}
+SWITCH_DECLARE(uint32_t) switch_core_media_get_video_fps(switch_core_session_t *session)
+{
+ switch_media_handle_t *smh;
+ time_t now;
+
+ switch_assert(session);
+
+ if (!(smh = session->media_handle)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
+ return 0;
+ }
+
+ now = switch_epoch_time_now(NULL);
+
+ if (!(smh->vid_started && smh->vid_frames && smh->vid_started < now)) {
+ return 0;
+ }
+
+ return round_to_step(smh->vid_frames / (now - smh->vid_started), 5);
+}
+
SWITCH_DECLARE(void) switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session)
{
_switch_core_media_pass_zrtp_hash2(aleg_session, bleg_session, SWITCH_MEDIA_TYPE_AUDIO);
}
-static void check_jb(switch_core_session_t *session, const char *input)
+
+static void check_jb(switch_core_session_t *session, const char *input, int32_t jb_msec, int32_t maxlen)
{
const char *val;
switch_media_handle_t *smh;
}
- if ((val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) {
- int jb_msec = atoi(val);
- int maxlen = 0, max_drift = 0;
+ if (jb_msec || (val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) {
+ int max_drift = 0;
char *p, *q;
+ if (!jb_msec) {
+ jb_msec = atoi(val);
- if ((p = strchr(val, ':'))) {
- p++;
- maxlen = atoi(p);
- if ((q = strchr(p, ':'))) {
- q++;
- max_drift = abs(atoi(q));
+ if ((p = strchr(val, ':'))) {
+ p++;
+ maxlen = atoi(p);
+ if ((q = strchr(p, ':'))) {
+ q++;
+ max_drift = abs(atoi(q));
+ }
}
}
}
+static void check_jb_sync(switch_core_session_t *session)
+{
+ int32_t jb_sync_msec = 200;
+ uint32_t fps, frames = 0;
+ switch_media_handle_t *smh;
+ switch_rtp_engine_t *v_engine = NULL;
+ const char *var;
+
+ switch_assert(session);
+
+ if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
+ return;
+ }
+
+ if (!(smh = session->media_handle)) {
+ return;
+ }
+
+ v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+
+ if ((var = switch_channel_get_variable(session->channel, "jb_sync_msec"))) {
+ int tmp;
+
+ if (!strcasecmp(var, "disabled")) {
+ return;
+ }
+
+ tmp = atol(var);
+
+ if (tmp > -50 && tmp < 10000) {
+ jb_sync_msec = tmp;
+ }
+ }
+
+ fps = switch_core_media_get_video_fps(session);
+
+ if (!fps) return;
+
+ if (jb_sync_msec < 0) {
+ frames = abs(jb_sync_msec);
+ jb_sync_msec = 1000 / (fps / frames);
+ } else {
+ frames = fps / (1000 / jb_sync_msec);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
+ SWITCH_LOG_DEBUG, "%s Sync Audio and Video Jitterbuffer to %dms %u Video Frames FPS %u\n",
+ switch_channel_get_name(session->channel),
+ jb_sync_msec, frames, fps);
+
+ switch_rtp_set_video_buffer_size(v_engine->rtp_session, frames);
+ check_jb(session, NULL, jb_sync_msec, jb_sync_msec);
+}
+
+
//?
SWITCH_DECLARE(switch_status_t) switch_core_media_read_lock_unlock(switch_core_session_t *session, switch_media_type_t type, switch_bool_t lock)
{
goto end;
}
+ if (type == SWITCH_MEDIA_TYPE_VIDEO && engine->read_frame.m) {
+ if (!smh->vid_started) {
+ smh->vid_started = switch_epoch_time_now(NULL);
+ }
+ smh->vid_frames++;
+
+ if (smh->vid_frames == 45) {
+ check_jb_sync(session);
+ }
+ }
+
+
/* re-set codec if necessary */
if (engine->reset_codec > 0) {
const char *val;
}
}
- check_jb(session, NULL);
+ check_jb(session, NULL, 0, 0);
engine->check_frames = 0;
engine->last_ts = 0;
}
- check_jb(session, NULL);
+ check_jb(session, NULL, 0, 0);
if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
int v = atoi(val);
case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER:
{
if (switch_rtp_ready(a_engine->rtp_session)) {
- check_jb(session, msg->string_arg);
+ check_jb(session, msg->string_arg, 0, 0);
}
}
break;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Starting video timer.\n");
}
- switch_vb_create(&rtp_session->vb, 5, 30, rtp_session->pool);
+ //switch_vb_create(&rtp_session->vb, 5, 30, rtp_session->pool);
//switch_vb_debug_level(rtp_session->vb, 10);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Starting video buffer.\n");
+
+
+
+
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Not using a timer\n");
va_end(ap);
}
+SWITCH_DECLARE(switch_status_t) switch_rtp_set_video_buffer_size(switch_rtp_t *rtp_session, uint32_t frames)
+{
+ if (!switch_rtp_ready(rtp_session)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!rtp_session->vb) {
+ switch_vb_create(&rtp_session->vb, frames, frames * 3, rtp_session->pool);
+ } else {
+ switch_vb_set_frames(rtp_session->vb, frames, frames * 3);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Setting video buffer %u Frames.\n", frames);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
{