FS-10126: [freeswitch-core] General Video Improvements #resolve

This commit is contained in:
Anthony Minessale 2017-03-10 21:14:17 -06:00
parent 589023b52c
commit f4ad4ed6c4
12 changed files with 596 additions and 158 deletions

View File

@ -1307,6 +1307,9 @@ SWITCH_DECLARE(uint32_t) switch_core_session_flush_private_events(switch_core_se
SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
int stream_id);
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_DECLARE(void) switch_core_session_passthru(switch_core_session_t *session, switch_media_type_t type, switch_bool_t on);
/*!
\brief Read a video frame from a session
\param session the session to read from

View File

@ -215,6 +215,7 @@ struct switch_timer {
unsigned int samples;
/*! current sample count based on samples parameter */
uint32_t samplecount;
uint32_t last_samplecount;
/*! the timer interface provided from a loadable module */
switch_timer_interface_t *timer_interface;
/*! the timer's memory pool */

View File

@ -774,11 +774,10 @@ typedef enum {
SWITCH_RTP_FLAG_MUTE,
SWITCH_RTP_FLAG_NACK,
SWITCH_RTP_FLAG_TMMBR,
SWITCH_RTP_FLAG_GEN_TS_DELTA,
SWITCH_RTP_FLAG_GEN_TS_MANUAL,
SWITCH_RTP_FLAG_DETECT_SSRC,
SWITCH_RTP_FLAG_TEXT,
SWITCH_RTP_FLAG_OLD_FIR,
SWITCH_RTP_FLAG_PASSTHRU,
SWITCH_RTP_FLAG_INVALID
} switch_rtp_flag_t;
@ -909,7 +908,6 @@ typedef enum {
*/
} switch_rtp_bug_flag_t;
#ifdef _MSC_VER
@ -1558,6 +1556,8 @@ typedef struct switch_vid_params_s {
uint32_t width;
uint32_t height;
uint32_t fps;
uint32_t d_width;
uint32_t d_height;
} switch_vid_params_t;
@ -1608,7 +1608,8 @@ typedef enum {
SFF_USE_VIDEO_TIMESTAMP = (1 << 16),
SFF_ENCODED = (1 << 17),
SFF_TEXT_LINE_BREAK = (1 << 18),
SFF_IS_KEYFRAME = (1 << 19)
SFF_IS_KEYFRAME = (1 << 19),
SFF_EXTERNAL = (1 << 20)
} switch_frame_flag_enum_t;
typedef uint32_t switch_frame_flag_t;

View File

@ -95,7 +95,6 @@ switch_status_t conference_file_close(conference_obj_t *conference, conference_f
if (conference->canvases[node->canvas_id]->timer.timer_interface) {
conference->canvases[node->canvas_id]->timer.interval = conference->video_fps.ms;
conference->canvases[node->canvas_id]->timer.samples = conference->video_fps.samples;
switch_core_timer_sync(&conference->canvases[node->canvas_id]->timer);
conference->canvases[node->canvas_id]->send_keyframe = 1;
}
conference->playing_video_file = 0;

View File

@ -1723,7 +1723,7 @@ void conference_video_write_canvas_image_to_codec_group(conference_obj_t *confer
}
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;
@ -1753,7 +1753,9 @@ void conference_video_write_canvas_image_to_codec_group(conference_obj_t *confer
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;
}
@ -3476,6 +3478,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
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;
}
@ -3680,7 +3683,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
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;
}
@ -3695,13 +3700,14 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
conference_video_set_canvas_fgimg(canvas, NULL);
}
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);
@ -4034,7 +4040,9 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_
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;
}

View File

@ -5754,6 +5754,50 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_vid_params_t_fps_get(void * j
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_vid_params_t_d_width_set(void * jarg1, unsigned long jarg2) {
switch_vid_params_s *arg1 = (switch_vid_params_s *) 0 ;
uint32_t arg2 ;
arg1 = (switch_vid_params_s *)jarg1;
arg2 = (uint32_t)jarg2;
if (arg1) (arg1)->d_width = arg2;
}
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_vid_params_t_d_width_get(void * jarg1) {
unsigned long jresult ;
switch_vid_params_s *arg1 = (switch_vid_params_s *) 0 ;
uint32_t result;
arg1 = (switch_vid_params_s *)jarg1;
result = (uint32_t) ((arg1)->d_width);
jresult = (unsigned long)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_vid_params_t_d_height_set(void * jarg1, unsigned long jarg2) {
switch_vid_params_s *arg1 = (switch_vid_params_s *) 0 ;
uint32_t arg2 ;
arg1 = (switch_vid_params_s *)jarg1;
arg2 = (uint32_t)jarg2;
if (arg1) (arg1)->d_height = arg2;
}
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_vid_params_t_d_height_get(void * jarg1) {
unsigned long jresult ;
switch_vid_params_s *arg1 = (switch_vid_params_s *) 0 ;
uint32_t result;
arg1 = (switch_vid_params_s *)jarg1;
result = (uint32_t) ((arg1)->d_height);
jresult = (unsigned long)result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_vid_params_t() {
void * jresult ;
switch_vid_params_s *result = 0 ;
@ -12952,6 +12996,34 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_read_frame(void * jarg1, v
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_transcoding(void * jarg1, void * jarg2, int jarg3) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
switch_core_session_t *arg2 = (switch_core_session_t *) 0 ;
switch_media_type_t arg3 ;
switch_bool_t result;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (switch_core_session_t *)jarg2;
arg3 = (switch_media_type_t)jarg3;
result = (switch_bool_t)switch_core_session_transcoding(arg1,arg2,arg3);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_passthru(void * jarg1, int jarg2, int jarg3) {
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
switch_media_type_t arg2 ;
switch_bool_t arg3 ;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (switch_media_type_t)jarg2;
arg3 = (switch_bool_t)jarg3;
switch_core_session_passthru(arg1,arg2,arg3);
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_read_video_frame(void * jarg1, void * jarg2, unsigned long jarg3, int jarg4) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
@ -24674,6 +24746,28 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_timer_samplecount_get(void *
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_timer_last_samplecount_set(void * jarg1, unsigned long jarg2) {
switch_timer *arg1 = (switch_timer *) 0 ;
uint32_t arg2 ;
arg1 = (switch_timer *)jarg1;
arg2 = (uint32_t)jarg2;
if (arg1) (arg1)->last_samplecount = arg2;
}
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_timer_last_samplecount_get(void * jarg1) {
unsigned long jresult ;
switch_timer *arg1 = (switch_timer *) 0 ;
uint32_t result;
arg1 = (switch_timer *)jarg1;
result = (uint32_t) ((arg1)->last_samplecount);
jresult = (unsigned long)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_timer_timer_interface_set(void * jarg1, void * jarg2) {
switch_timer *arg1 = (switch_timer *) 0 ;
switch_timer_interface_t *arg2 = (switch_timer_interface_t *) 0 ;

View File

@ -2122,6 +2122,15 @@ else
return ret;
}
public static switch_bool_t switch_core_session_transcoding(SWIGTYPE_p_switch_core_session session_a, SWIGTYPE_p_switch_core_session session_b, switch_media_type_t type) {
switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_core_session_transcoding(SWIGTYPE_p_switch_core_session.getCPtr(session_a), SWIGTYPE_p_switch_core_session.getCPtr(session_b), (int)type);
return ret;
}
public static void switch_core_session_passthru(SWIGTYPE_p_switch_core_session session, switch_media_type_t type, switch_bool_t on) {
freeswitchPINVOKE.switch_core_session_passthru(SWIGTYPE_p_switch_core_session.getCPtr(session), (int)type, (int)on);
}
public static switch_status_t switch_core_session_read_video_frame(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_frame frame, uint flags, int stream_id) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_read_video_frame(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_frame.getCPtr(frame), flags, stream_id);
return ret;
@ -9559,6 +9568,18 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_vid_params_t_fps_get")]
public static extern uint switch_vid_params_t_fps_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_vid_params_t_d_width_set")]
public static extern void switch_vid_params_t_d_width_set(HandleRef jarg1, uint jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_vid_params_t_d_width_get")]
public static extern uint switch_vid_params_t_d_width_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_vid_params_t_d_height_set")]
public static extern void switch_vid_params_t_d_height_set(HandleRef jarg1, uint jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_vid_params_t_d_height_get")]
public static extern uint switch_vid_params_t_d_height_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_new_switch_vid_params_t")]
public static extern IntPtr new_switch_vid_params_t();
@ -11338,6 +11359,12 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_read_frame")]
public static extern int switch_core_session_read_frame(HandleRef jarg1, HandleRef jarg2, uint jarg3, int jarg4);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_transcoding")]
public static extern int switch_core_session_transcoding(HandleRef jarg1, HandleRef jarg2, int jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_passthru")]
public static extern void switch_core_session_passthru(HandleRef jarg1, int jarg2, int jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_read_video_frame")]
public static extern int switch_core_session_read_video_frame(HandleRef jarg1, HandleRef jarg2, uint jarg3, int jarg4);
@ -14065,6 +14092,12 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_timer_samplecount_get")]
public static extern uint switch_timer_samplecount_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_timer_last_samplecount_set")]
public static extern void switch_timer_last_samplecount_set(HandleRef jarg1, uint jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_timer_last_samplecount_get")]
public static extern uint switch_timer_last_samplecount_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_timer_timer_interface_set")]
public static extern void switch_timer_timer_interface_set(HandleRef jarg1, HandleRef jarg2);
@ -35952,7 +35985,8 @@ namespace FreeSWITCH.Native {
SFF_USE_VIDEO_TIMESTAMP = (1 << 16),
SFF_ENCODED = (1 << 17),
SFF_TEXT_LINE_BREAK = (1 << 18),
SFF_IS_KEYFRAME = (1 << 19)
SFF_IS_KEYFRAME = (1 << 19),
SFF_EXTERNAL = (1 << 20)
}
}
@ -40382,11 +40416,10 @@ public enum switch_rtp_flag_t {
SWITCH_RTP_FLAG_MUTE,
SWITCH_RTP_FLAG_NACK,
SWITCH_RTP_FLAG_TMMBR,
SWITCH_RTP_FLAG_GEN_TS_DELTA,
SWITCH_RTP_FLAG_GEN_TS_MANUAL,
SWITCH_RTP_FLAG_DETECT_SSRC,
SWITCH_RTP_FLAG_TEXT,
SWITCH_RTP_FLAG_OLD_FIR,
SWITCH_RTP_FLAG_PASSTHRU,
SWITCH_RTP_FLAG_INVALID
}
@ -43410,6 +43443,16 @@ public class switch_timer : IDisposable {
}
}
public uint last_samplecount {
set {
freeswitchPINVOKE.switch_timer_last_samplecount_set(swigCPtr, value);
}
get {
uint ret = freeswitchPINVOKE.switch_timer_last_samplecount_get(swigCPtr);
return ret;
}
}
public switch_timer_interface timer_interface {
set {
freeswitchPINVOKE.switch_timer_timer_interface_set(swigCPtr, switch_timer_interface.getCPtr(value));
@ -44192,6 +44235,26 @@ public class switch_vid_params_t : IDisposable {
}
}
public uint d_width {
set {
freeswitchPINVOKE.switch_vid_params_t_d_width_set(swigCPtr, value);
}
get {
uint ret = freeswitchPINVOKE.switch_vid_params_t_d_width_get(swigCPtr);
return ret;
}
}
public uint d_height {
set {
freeswitchPINVOKE.switch_vid_params_t_d_height_set(swigCPtr, value);
}
get {
uint ret = freeswitchPINVOKE.switch_vid_params_t_d_height_get(swigCPtr);
return ret;
}
}
public switch_vid_params_t() : this(freeswitchPINVOKE.new_switch_vid_params_t(), true) {
}

View File

@ -60,7 +60,8 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co
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;
@ -198,6 +199,7 @@ typedef struct switch_rtp_engine_s {
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;
@ -3017,6 +3019,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_sessio
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;
@ -6188,7 +6195,7 @@ SWITCH_DECLARE(switch_file_handle_t *) switch_core_media_get_video_file(switch_c
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;
@ -6244,6 +6251,41 @@ static void switch_core_session_write_blank_video(switch_core_session_t *session
}
typedef struct core_fps_s {
float fps;
int ms;
int samples;
} core_fps_t;
static struct core_fps_s 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}
};
static int video_get_fps(core_fps_t *fpsP, float fps)
{
uint32_t i = 0;
for (i = 0; FPS_VALS[i].ms; i++) {
if (FPS_VALS[i].fps == fps) {
*fpsP = FPS_VALS[i];
return 1;
}
}
return 0;
}
static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void *obj)
{
@ -6255,9 +6297,11 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
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;
}
@ -6276,7 +6320,10 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
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;
@ -6296,7 +6343,8 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
}
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)) {
@ -6307,15 +6355,27 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
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);
}
@ -6323,6 +6383,25 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
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);
@ -6332,6 +6411,10 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
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;
@ -6473,7 +6556,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_ses
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;
@ -6490,7 +6573,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_ses
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;
@ -8159,11 +8242,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
}
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);
@ -8872,11 +8950,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
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]++;
}
@ -12101,12 +12174,26 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
case SWITCH_MESSAGE_INDICATE_BRIDGE:
{
#if 0
if (switch_rtp_ready(v_engine->rtp_session)) {
const char *val;
if ((!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
if (switch_rtp_get_jitter_buffer(v_engine->rtp_session) && 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));
switch_rtp_pause_jitter_buffer(v_engine->rtp_session, SWITCH_TRUE);
switch_set_flag(smh, SMF_VB_PAUSED);
}
}
}
#endif
if (switch_rtp_ready(a_engine->rtp_session)) {
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));
@ -12160,6 +12247,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
}
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)) {
@ -13811,8 +13912,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
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)) {
@ -13828,9 +13928,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
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");
@ -13845,7 +13942,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
return SWITCH_STATUS_SUCCESS;
}
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
if (smh->write_mutex[SWITCH_MEDIA_TYPE_VIDEO] && switch_mutex_trylock(smh->write_mutex[SWITCH_MEDIA_TYPE_VIDEO]) != SWITCH_STATUS_SUCCESS) {
/* return CNG, another thread is already writing */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being written to for %s\n",
@ -13853,6 +13949,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
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);
@ -13871,16 +13972,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
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);
}
}
@ -13894,6 +13987,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
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;
int prune = 0;
@ -14066,6 +14164,53 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_wait_for_video_input_params(
}
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)
{

View File

@ -155,6 +155,7 @@ static void video_bridge_thread(switch_core_session_t *session, void *obj)
switch_frame_t *read_frame = 0;
int set_decoded_read = 0, refresh_timer = 0;
int refresh_cnt = 300;
int pass_val = 0, last_pass_val = 0;
vh->up = 1;
@ -178,8 +179,18 @@ static void video_bridge_thread(switch_core_session_t *session, void *obj)
if (switch_channel_media_up(channel)) {
switch_codec_t *a_codec = switch_core_session_get_video_read_codec(vh->session_a);
switch_codec_t *b_codec = switch_core_session_get_video_write_codec(vh->session_b);
if (switch_core_session_transcoding(vh->session_a, vh->session_b, SWITCH_MEDIA_TYPE_VIDEO)) {
pass_val = 1;
} else {
pass_val = 2;
}
if (pass_val != last_pass_val) {
switch_core_session_passthru(session, SWITCH_MEDIA_TYPE_VIDEO, pass_val == 2 ? SWITCH_TRUE : SWITCH_FALSE);
last_pass_val = pass_val;
}
if (switch_channel_test_flag(channel, CF_VIDEO_REFRESH_REQ)) {
switch_channel_clear_flag(channel, CF_VIDEO_REFRESH_REQ);
refresh_timer = refresh_cnt;
@ -246,6 +257,8 @@ static void video_bridge_thread(switch_core_session_t *session, void *obj)
switch_core_session_request_video_refresh(vh->session_a);
switch_core_session_request_video_refresh(vh->session_b);
switch_core_session_passthru(vh->session_a, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_FALSE);
switch_core_session_rwunlock(vh->session_a);
switch_core_session_rwunlock(vh->session_b);
@ -370,6 +383,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
struct vid_helper th = { 0 };
const char *banner_file = NULL;
int played_banner = 0, banner_counter = 0;
int pass_val = 0, last_pass_val = 0;
#ifdef SWITCH_VIDEO_IN_THREADS
struct vid_helper vh = { 0 };
@ -501,6 +515,17 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
switch_status_t status;
switch_event_t *event;
if (switch_core_session_transcoding(session_a, session_b, SWITCH_MEDIA_TYPE_AUDIO)) {
pass_val = 1;
} else {
pass_val = 2;
}
if (pass_val != last_pass_val) {
switch_core_session_passthru(session_a, SWITCH_MEDIA_TYPE_AUDIO, pass_val == 2 ? SWITCH_TRUE : SWITCH_FALSE);
last_pass_val = pass_val;
}
if (switch_channel_test_flag(chan_a, CF_TRANSFER)) {
data->clean_exit = 1;
}
@ -810,6 +835,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
end_of_bridge_loop:
switch_core_session_passthru(session_a, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_FALSE);
#ifdef SWITCH_VIDEO_IN_THREADS
if (vh.up > 0) {

View File

@ -58,9 +58,10 @@ struct switch_jb_s {
struct switch_jb_node_s *node_list;
uint32_t last_target_seq;
uint32_t highest_read_ts;
uint32_t highest_dropped_ts;
uint32_t highest_read_seq;
uint32_t highest_wrote_ts;
uint32_t highest_wrote_seq;
uint16_t highest_wrote_seq;
uint16_t target_seq;
uint32_t target_ts;
uint32_t last_target_ts;
@ -104,6 +105,8 @@ struct switch_jb_s {
switch_channel_t *channel;
uint32_t buffer_lag;
uint32_t flush;
uint32_t packet_count;
uint32_t max_packet_len;
};
@ -211,6 +214,22 @@ static inline switch_jb_node_t *new_node(switch_jb_t *jb)
}
if (!np) {
int mult = 25;
if (jb->type != SJB_VIDEO) {
mult = 2;
} else {
if (jb->max_packet_len > mult) {
mult = jb->max_packet_len;
}
}
if (jb->allocated_nodes > jb->max_frame_len * mult) {
jb_debug(jb, 2, "ALLOCATED FRAMES TOO HIGH! %d\n", jb->allocated_nodes);
switch_jb_reset(jb);
switch_mutex_unlock(jb->list_mutex);
return NULL;
}
np = switch_core_alloc(jb->pool, sizeof(*np));
jb->allocated_nodes++;
@ -279,7 +298,7 @@ static inline void hide_node(switch_jb_node_t *node, switch_bool_t pop)
}
if (switch_core_inthash_delete(jb->node_hash, node->packet.header.seq)) {
if (node->packet.header.m && jb->type == SJB_VIDEO) {
if (node->packet.header.version == 1 && jb->type == SJB_VIDEO) {
jb->complete_frames--;
}
}
@ -573,20 +592,45 @@ static inline void drop_second_newest_frame(switch_jb_t *jb)
}
#endif
static inline int check_seq(uint16_t a, uint16_t b)
{
a = ntohs(a);
b = ntohs(b);
if (a >= b || (b > a && b > USHRT_MAX / 2 && a < USHRT_MAX / 2)) {
return 1;
}
return 0;
}
static inline int check_ts(uint32_t a, uint32_t b)
{
a = ntohl(a);
b = ntohl(b);
if (a > b || (b > a && b > UINT_MAX / 2 && a < UINT_MAX / 2)) {
return 1;
}
return 0;
}
static inline void add_node(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t len)
{
switch_jb_node_t *node = new_node(jb);
if (!node) {
return;
}
node->packet = *packet;
node->len = len;
memcpy(node->packet.body, packet->body, len);
switch_core_inthash_insert(jb->node_hash, node->packet.header.seq, node);
if (packet->header.m && jb->type == SJB_VIDEO) {
jb->complete_frames++;
}
if (jb->node_hash_ts) {
switch_core_inthash_insert(jb->node_hash_ts, node->packet.header.ts, node);
}
@ -621,11 +665,23 @@ static inline void add_node(switch_jb_t *jb, switch_rtp_packet_t *packet, switch
}
if (jb->type == SJB_VIDEO) {
if (jb->write_init && ((htons(packet->header.seq) >= htons(jb->highest_wrote_seq) && (ntohl(node->packet.header.ts) > ntohl(jb->highest_wrote_ts))) ||
(ntohl(jb->highest_wrote_ts) > (UINT_MAX - 1000) && ntohl(node->packet.header.ts) < 1000))) {
if (!switch_test_flag(jb, SJB_QUEUE_ONLY)) {
jb->packet_count++;
}
if (jb->write_init && check_seq(packet->header.seq, jb->highest_wrote_seq) && check_ts(node->packet.header.ts, jb->highest_wrote_ts)) {
jb_debug(jb, 2, "WRITE frame ts: %u complete=%u/%u n:%u\n", ntohl(node->packet.header.ts), jb->complete_frames , jb->frame_len, jb->visible_nodes);
jb->highest_wrote_ts = packet->header.ts;
//verify_oldest_frame(jb);
jb->complete_frames++;
if (!switch_test_flag(jb, SJB_QUEUE_ONLY)) {
if (jb->packet_count > jb->max_packet_len) {
jb->max_packet_len = jb->packet_count;
}
jb->packet_count = 0;
}
node->packet.header.version = 1;
} else if (!jb->write_init) {
jb->highest_wrote_ts = packet->header.ts;
}
@ -716,9 +772,9 @@ static inline switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_n
jb_frame_inc(jb, 1);
}
//if (jb->session) {
// switch_core_session_request_video_refresh(jb->session);
//}
if (jb->session) {
switch_core_session_request_video_refresh(jb->session);
}
for (x = 0; x < 10; x++) {
increment_seq(jb);
@ -729,6 +785,7 @@ static inline switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_n
jb_debug(jb, 2, "%s", "SAME FRAME DROPPING\n");
jb->dropped++;
drop_ts(jb, node->packet.header.ts);
jb->highest_dropped_ts = ntohl(node->packet.header.ts);
node = NULL;
goto top;
}
@ -737,6 +794,7 @@ static inline switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_n
jb_debug(jb, 2, "MISSING incremental seq: %u\n", ntohs(jb->target_seq));
}
}
} else {
increment_seq(jb);
}
@ -816,10 +874,11 @@ SWITCH_DECLARE(void) switch_jb_set_session(switch_jb_t *jb, switch_core_session_
jb->session = session;
jb->channel = switch_core_session_get_channel(session);
if (jb->type == SJB_VIDEO && (var = switch_channel_get_variable_dup(jb->channel, "jb_video_low_bitrate", SWITCH_FALSE, -1))) {
if (jb->type == SJB_VIDEO && !switch_test_flag(jb, SJB_QUEUE_ONLY) &&
(var = switch_channel_get_variable_dup(jb->channel, "jb_video_low_bitrate", SWITCH_FALSE, -1))) {
int tmp = atoi(var);
if (tmp > 128 && tmp < 10240) {
if (tmp >= 128 && tmp <= 10240) {
jb->video_low_bitrate = (uint32_t)tmp;
}
}
@ -1133,6 +1192,16 @@ SWITCH_DECLARE(switch_status_t) switch_jb_put_packet(switch_jb_t *jb, switch_rtp
switch_mutex_lock(jb->mutex);
if (jb->highest_dropped_ts) {
if (ntohl(packet->header.ts) < jb->highest_dropped_ts) {
jb_debug(jb, 2, "%s", "TS ALREADY DROPPED, DROPPING PACKET\n");
switch_mutex_unlock(jb->mutex);
return SWITCH_STATUS_SUCCESS;
}
jb->highest_dropped_ts = 0;
}
if (!want) want = got;
if (switch_test_flag(jb, SJB_QUEUE_ONLY) || jb->type == SJB_AUDIO || jb->type == SJB_TEXT) {
@ -1197,6 +1266,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet_by_seq(switch_jb_t *jb, uin
*packet = node->packet;
*len = node->len;
memcpy(packet->body, node->packet.body, node->len);
packet->header.version = 2;
status = SWITCH_STATUS_SUCCESS;
} else {
jb_debug(jb, 2, "Missing buffered seq: %u\n", ntohs(seq));
@ -1211,7 +1281,6 @@ SWITCH_DECLARE(switch_size_t) switch_jb_get_last_read_len(switch_jb_t *jb)
return jb->last_len;
}
SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp_packet_t *packet, switch_size_t *len)
{
switch_jb_node_t *node = NULL;
@ -1261,16 +1330,17 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
if (jb->session) {
switch_core_session_request_video_refresh(jb->session);
}
} else if (!switch_channel_test_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE) && jb->frame_len > jb->min_frame_len * 2) {
} else if (!switch_channel_test_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE) && jb->frame_len > jb->max_frame_len / 2) {
switch_core_session_message_t msg = { 0 };
jb->bitrate_control = jb->video_low_bitrate;
msg.message_id = SWITCH_MESSAGE_INDICATE_BITRATE_REQ;
msg.numeric_arg = jb->bitrate_control * 1024;
msg.from = __FILE__;
jb_debug(jb, 2, "Force BITRATE to %d\n", jb->bitrate_control);
switch_core_session_receive_message(jb->session, &msg);
switch_channel_set_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE);
if (jb->session) {
@ -1291,15 +1361,14 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
if ((status = jb_next_packet(jb, &node)) == SWITCH_STATUS_SUCCESS) {
jb_debug(jb, 2, "Found next frame cur ts: %u seq: %u\n", htonl(node->packet.header.ts), htons(node->packet.header.seq));
if (!jb->read_init || ntohs(node->packet.header.seq) > ntohs(jb->highest_read_seq) ||
(ntohs(jb->highest_read_seq) > USHRT_MAX - 10 && ntohs(node->packet.header.seq) <= 10) ) {
if (!jb->read_init || check_seq(node->packet.header.seq, jb->highest_read_seq)) {
jb->highest_read_seq = node->packet.header.seq;
}
if (jb->type == SJB_TEXT || jb->type == SJB_AUDIO ||
(jb->read_init && htons(node->packet.header.seq) >= htons(jb->highest_read_seq) && (ntohl(node->packet.header.ts) > ntohl(jb->highest_read_ts)))) {
if (jb->type != SJB_VIDEO ||
(jb->read_init && check_seq(node->packet.header.seq, jb->highest_read_seq) && check_ts(node->packet.header.ts, jb->highest_read_ts))) {
if (jb->type == SJB_TEXT || jb->type == SJB_AUDIO) {
if (jb->type != SJB_VIDEO) {
jb->complete_frames--;
}
jb_debug(jb, 2, "READ frame ts: %u complete=%u/%u n:%u\n", ntohl(node->packet.header.ts), jb->complete_frames , jb->frame_len, jb->visible_nodes);
@ -1351,6 +1420,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
*len = node->len;
jb->last_len = *len;
memcpy(packet->body, node->packet.body, node->len);
packet->header.version = 2;
hide_node(node, SWITCH_TRUE);
jb_debug(jb, 1, "GET packet ts:%u seq:%u %s\n", ntohl(packet->header.ts), ntohs(packet->header.seq), packet->header.m ? " <MARK>" : "");

View File

@ -302,8 +302,8 @@ typedef struct ts_normalize_s {
uint32_t last_frame;
uint32_t ts;
uint32_t delta;
uint32_t delta_ct;
uint32_t delta_ttl;
int last_external;
} ts_normalize_t;
struct switch_rtp {
@ -453,6 +453,7 @@ struct switch_rtp {
switch_byte_t rtcp_auto_adj_used;
uint8_t pause_jb;
uint16_t last_seq;
uint16_t last_write_seq;
switch_time_t last_read_time;
switch_size_t last_flush_packet_count;
uint32_t interdigit_delay;
@ -1656,6 +1657,10 @@ static void check_jitter(switch_rtp_t *rtp_session)
(rtp_session->stats.inbound.last_processed_seq + 1), lost);
rtp_session->stats.inbound.last_loss++;
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
switch_core_session_request_video_refresh(rtp_session->session);
}
if (rtp_session->stats.inbound.last_loss > 0 && rtp_session->stats.inbound.last_loss < LOST_BURST_CAPTURE) {
rtp_session->stats.inbound.loss[rtp_session->stats.inbound.last_loss] += lost;
}
@ -4119,21 +4124,27 @@ SWITCH_DECLARE(switch_jb_t *) switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_ses
SWITCH_DECLARE(switch_status_t) switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause)
{
if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) {
return SWITCH_STATUS_FALSE;
}
if (!!pause == !!rtp_session->pause_jb) {
return SWITCH_STATUS_FALSE;
}
int new_val;
if (rtp_session->pause_jb && !pause) {
switch_jb_reset(rtp_session->jb);
if (rtp_session->jb) {
switch_jb_reset(rtp_session->jb);
}
if (rtp_session->vb) {
switch_jb_reset(rtp_session->vb);
}
}
rtp_session->pause_jb = pause ? 1 : 0;
new_val = pause ? 1 : -1;
if (rtp_session->pause_jb + new_val > -1) {
rtp_session->pause_jb += new_val;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1,
"Jitterbuffer %s is %s\n", rtp_type(rtp_session), rtp_session->pause_jb ? "paused" : "enabled");
return SWITCH_STATUS_SUCCESS;
}
@ -4730,37 +4741,7 @@ SWITCH_DECLARE(void) switch_rtp_set_flags(switch_rtp_t *rtp_session, switch_rtp_
for(i = 0; i < SWITCH_RTP_FLAG_INVALID; i++) {
if (flags[i]) {
rtp_session->flags[i] = flags[i];
if (i == SWITCH_RTP_FLAG_AUTOADJ) {
rtp_session->autoadj_window = 20;
rtp_session->autoadj_threshold = 10;
rtp_session->autoadj_tally = 0;
if (rtp_session->session) {
switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
const char *x = switch_channel_get_variable(channel, "rtp_auto_adjust_threshold");
if (x && *x) {
int xn = atoi(x);
if (xn > 0 && xn <= 65535) {
rtp_session->autoadj_window = xn*2;
rtp_session->autoadj_threshold = xn;
}
}
}
rtp_session->flags[SWITCH_RTP_FLAG_RTCP_AUTOADJ] = 1;
rtp_session->rtcp_autoadj_window = 20;
rtp_session->rtcp_autoadj_threshold = 1;
rtp_session->rtcp_autoadj_tally = 0;
rtp_flush_read_buffer(rtp_session, SWITCH_RTP_FLUSH_ONCE);
} else if (i == SWITCH_RTP_FLAG_NOBLOCK && rtp_session->sock_input) {
switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE);
}
switch_rtp_set_flag(rtp_session, i);
}
}
}
@ -4771,19 +4752,24 @@ SWITCH_DECLARE(void) switch_rtp_clear_flags(switch_rtp_t *rtp_session, switch_rt
for(i = 0; i < SWITCH_RTP_FLAG_INVALID; i++) {
if (flags[i]) {
rtp_session->flags[i] = 0;
switch_rtp_clear_flag(rtp_session, i);
}
}
}
SWITCH_DECLARE(void) switch_rtp_set_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flag)
{
int old_flag = rtp_session->flags[flag];
switch_mutex_lock(rtp_session->flag_mutex);
rtp_session->flags[flag] = 1;
switch_mutex_unlock(rtp_session->flag_mutex);
if (flag == SWITCH_RTP_FLAG_DTMF_ON) {
if (flag == SWITCH_RTP_FLAG_PASSTHRU) {
if (!old_flag) {
switch_rtp_pause_jitter_buffer(rtp_session, SWITCH_TRUE);
}
} else if (flag == SWITCH_RTP_FLAG_DTMF_ON) {
rtp_session->stats.inbound.last_processed_seq = 0;
} else if (flag == SWITCH_RTP_FLAG_FLUSH) {
reset_jitter_seq(rtp_session);
@ -4832,12 +4818,17 @@ SWITCH_DECLARE(uint32_t) switch_rtp_test_flag(switch_rtp_t *rtp_session, switch_
SWITCH_DECLARE(void) switch_rtp_clear_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flag)
{
int old_flag = rtp_session->flags[flag];
switch_mutex_lock(rtp_session->flag_mutex);
rtp_session->flags[flag] = 0;
switch_mutex_unlock(rtp_session->flag_mutex);
if (flag == SWITCH_RTP_FLAG_DTMF_ON) {
if (flag == SWITCH_RTP_FLAG_PASSTHRU) {
if (old_flag) {
switch_rtp_pause_jitter_buffer(rtp_session, SWITCH_FALSE);
}
} else if (flag == SWITCH_RTP_FLAG_DTMF_ON) {
rtp_session->stats.inbound.last_processed_seq = 0;
} else if (flag == SWITCH_RTP_FLAG_PAUSE) {
reset_jitter_seq(rtp_session);
@ -5803,7 +5794,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
return SWITCH_STATUS_SUCCESS;
}
if (rtp_session->vb && jb_valid(rtp_session)) {
if (rtp_session->vb && !rtp_session->pause_jb && jb_valid(rtp_session)) {
status = switch_jb_put_packet(rtp_session->vb, (switch_rtp_packet_t *) &rtp_session->recv_msg, *bytes);
if (status == SWITCH_STATUS_TOO_LATE) {
@ -5900,7 +5891,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
}
}
if (rtp_session->vb && jb_valid(rtp_session)) {
if (rtp_session->vb && !rtp_session->pause_jb && jb_valid(rtp_session)) {
switch_status_t vstatus = switch_jb_get_packet(rtp_session->vb, (switch_rtp_packet_t *) &rtp_session->recv_msg, bytes);
status = vstatus;
@ -6700,7 +6691,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
pt = 100000;
}
if (rtp_session->vb) {
if (rtp_session->vb && !rtp_session->pause_jb) {
if (switch_jb_poll(rtp_session->vb)) {
pt = 1000;
}
@ -6726,7 +6717,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
got_jb = (rtp_session->vb && switch_jb_poll(rtp_session->vb));
got_jb = (rtp_session->vb && !rtp_session->pause_jb && switch_jb_poll(rtp_session->vb));
} else {
got_jb = SWITCH_TRUE;
}
@ -6922,7 +6913,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
process_rtcp_packet(rtp_session, &rtcp_bytes);
ret = 1;
if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && rtp_session->timer.interval) {
if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && rtp_session->timer.interval && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
switch_core_timer_sync(&rtp_session->timer);
reset_jitter_seq(rtp_session);
}
@ -7422,6 +7413,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
frame->source = __FILE__;
switch_set_flag(frame, SFF_RAW_RTP);
switch_set_flag(frame, SFF_EXTERNAL);
if (frame->payload == rtp_session->recv_te) {
switch_set_flag(frame, SFF_RFC2833);
}
@ -7649,59 +7641,65 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
}
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_GEN_TS_DELTA) || switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
int external = (*flags & SFF_EXTERNAL);
/* Normalize the timestamps to our own base by generating a made up starting point then adding the measured deltas to that base
so if the timestamps and ssrc of the source change, it will not break the other end's jitter bufffer / decoder etc *cough* CHROME *cough*
*/
if (!rtp_session->ts_norm.ts) {
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_GEN_TS_DELTA)) {
rtp_session->ts_norm.ts = (uint32_t) rand() % 1000000 + 1;
} else {
switch_core_timer_sync(&rtp_session->timer);
rtp_session->ts_norm.ts = rtp_session->timer.samplecount;
}
rtp_session->ts_norm.ts = (uint32_t) rand() % 1000000 + 1;
}
if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc) {
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_GEN_TS_DELTA)) {
if (rtp_session->ts_norm.last_ssrc) {
rtp_session->ts_norm.delta_ct = 1;
rtp_session->ts_norm.delta_ttl = 0;
if (rtp_session->ts_norm.delta) {
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
}
}
if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc || rtp_session->ts_norm.last_external != external) {
switch_core_session_t *other_session;
switch_core_session_request_video_refresh(rtp_session->session);
switch_core_media_gen_key_frame(rtp_session->session);
if (switch_core_session_get_partner(rtp_session->session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_core_session_request_video_refresh(other_session);
switch_core_media_gen_key_frame(other_session);
switch_core_session_rwunlock(other_session);
}
if (rtp_session->ts_norm.last_ssrc) {
rtp_session->ts_norm.delta_ttl = 0;
rtp_session->ts_norm.ts++;
}
rtp_session->ts_norm.last_ssrc = send_msg->header.ssrc;
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
}
rtp_session->ts_norm.last_external = external;
if (ntohl(send_msg->header.ts) != rtp_session->ts_norm.last_frame) {
int32_t delta = (int32_t) (ntohl(send_msg->header.ts) - rtp_session->ts_norm.last_frame);
int32_t delta;
int64_t x, y;
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && delta > 0 && delta < 90000) {
x = rtp_session->ts_norm.last_frame;
y = ntohl(send_msg->header.ts);
if (x > UINT32_MAX / 2 && y < UINT32_MAX / 2) {
x -= (int64_t)UINT32_MAX+1;
}
delta = (int32_t)y-x;
if (delta < 0 || delta > 90000) {
switch_core_media_gen_key_frame(rtp_session->session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1,
"Timestamp shift detected last: %d this: %d delta: %d stick with prev delta: %d\n",
rtp_session->ts_norm.last_frame, ntohl(send_msg->header.ts), delta, rtp_session->ts_norm.delta);
} else {
rtp_session->ts_norm.delta = delta;
}
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_GEN_TS_DELTA)) {
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
} else {
switch_core_timer_sync(&rtp_session->timer);
if (rtp_session->ts_norm.ts == rtp_session->timer.samplecount) {
rtp_session->ts_norm.ts = rtp_session->timer.samplecount + 1;
} else {
rtp_session->ts_norm.ts = rtp_session->timer.samplecount;
}
if (send_msg->header.m) {
rtp_session->ts_norm.last_frame++;
}
}
}
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
}
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
send_msg->header.ts = htonl(rtp_session->ts_norm.ts);
}
@ -7844,8 +7842,27 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
if (send) {
send_msg->header.seq = htons(++rtp_session->seq);
int delta = 1;
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && (*flags & SFF_EXTERNAL) && rtp_session->stats.outbound.packet_count && rtp_session->flags[SWITCH_RTP_FLAG_PASSTHRU]) {
int32_t x;
int32_t y;
x = rtp_session->last_write_seq;
y = ntohs(send_msg->header.seq);
if (x > UINT16_MAX / 2 && y < UINT16_MAX / 2) {
x -= (int32_t)UINT16_MAX+1;
}
delta = y-x;
}
rtp_session->seq += delta;
send_msg->header.seq = htons(rtp_session->seq);
rtp_session->last_write_seq = rtp_session->seq;
if (rtp_session->flags[SWITCH_RTP_FLAG_BYTESWAP] && send_msg->header.pt == rtp_session->payload) {
switch_swap_linear((int16_t *)send_msg->body, (int) datalen);
}
@ -7993,7 +8010,8 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
// //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SEND %u\n", ntohs(send_msg->header.seq));
//}
if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
rtp_session->seq--;
rtp_session->seq -= delta;
ret = -1;
goto end;
}
@ -8239,7 +8257,7 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
fwd = (rtp_session->flags[SWITCH_RTP_FLAG_RAW_WRITE] &&
(switch_test_flag(frame, SFF_RAW_RTP) || switch_test_flag(frame, SFF_RAW_RTP_PARSE_FRAME))) ? 1 : 0;
if (!fwd && !rtp_session->sending_dtmf && !rtp_session->queue_delay &&
if (!fwd && !rtp_session->sending_dtmf && !rtp_session->queue_delay && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] &&
rtp_session->flags[SWITCH_RTP_FLAG_RAW_WRITE] && (rtp_session->rtp_bugs & RTP_BUG_GEN_ONE_GEN_ALL)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "Generating RTP locally but timestamp passthru is configured, disabling....\n");
@ -8308,6 +8326,7 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
if (switch_test_flag(frame, SFF_RAW_RTP_PARSE_FRAME)) {
send_msg->header.version = 2;
send_msg->header.m = frame->m;
send_msg->header.ts = htonl(frame->timestamp);
if (frame->ssrc) {
send_msg->header.ssrc = htonl(frame->ssrc);

View File

@ -386,6 +386,14 @@ static switch_status_t timer_generic_sync(switch_timer_t *timer)
timer->tick = (elapsed / timer->interval) / 1000;
timer->samplecount = (uint32_t)(timer->tick * timer->samples);
if (timer->interval == 1 && timer->samplecount == timer->last_samplecount) {
timer->samplecount++;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Timer sync too often\n");
}
timer->last_samplecount = timer->samplecount;
return SWITCH_STATUS_SUCCESS;
}