uint32_t dropped;
uint32_t samples_per_frame;
uint32_t samples_per_second;
+ uint32_t bitrate_control;
uint8_t write_init;
uint8_t read_init;
uint8_t debug_level;
return lowest ? lowest->packet.header.ts : 0;
}
+
+static inline switch_jb_node_t *jb_find_highest_node(switch_jb_t *jb)
+{
+ switch_jb_node_t *np, *highest = NULL;
+
+ switch_mutex_lock(jb->list_mutex);
+ for (np = jb->node_list; np; np = np->next) {
+ if (!np->visible) continue;
+
+ if (!highest || ntohl(highest->packet.header.ts) < ntohl(np->packet.header.ts)) {
+ highest = np;
+ }
+ }
+ switch_mutex_unlock(jb->list_mutex);
+
+ return highest ? highest : NULL;
+}
+
+static inline uint32_t jb_find_highest_ts(switch_jb_t *jb)
+{
+ switch_jb_node_t *highest = jb_find_highest_node(jb);
+
+ return highest ? highest->packet.header.ts : 0;
+}
+
static inline void jb_hit(switch_jb_t *jb)
{
jb->period_good_count++;
jb->consec_miss_count = 0;
}
-static void jb_frame_inc(switch_jb_t *jb, int i)
+static void jb_frame_inc_line(switch_jb_t *jb, int i, int line)
{
uint32_t old_frame_len = jb->frame_len;
jb->highest_frame_len = jb->frame_len;
}
- if (jb->type == SJB_VIDEO && (jb->frame_len > jb->min_frame_len || jb->frame_len == jb->min_frame_len)) {
- if (jb->channel) {
- if (jb->frame_len == jb->min_frame_len) {
- jb_debug(jb, 2, "%s", "Allow BITRATE changes\n");
- switch_channel_clear_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE);
- } else {
- switch_core_session_message_t msg = { 0 };
- int new_bitrate = 512;
-
- msg.message_id = SWITCH_MESSAGE_INDICATE_BITRATE_REQ;
- msg.numeric_arg = new_bitrate * 1024;
- msg.from = __FILE__;
-
- jb_debug(jb, 2, "Force BITRATE to %d\n", new_bitrate);
- switch_core_session_receive_message(jb->session, &msg);
-
- switch_channel_set_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE);
+ if (jb->type == SJB_VIDEO && jb->channel) {
+ int ok = (jb->frame_len <= jb->min_frame_len + 1);
+
+ if (switch_channel_test_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE) && ok) {
+ jb_debug(jb, 2, "%s", "Allow BITRATE changes\n");
+ switch_channel_clear_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE);
+ jb->bitrate_control = 0;
+ } else if (!ok) {
+ switch_core_session_message_t msg = { 0 };
+ jb->bitrate_control = 512;
+
+ 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 (old_frame_len != jb->frame_len) {
- jb_debug(jb, 2, "Change framelen from %u to %u\n", old_frame_len, jb->frame_len);
+ jb_debug(jb, 2, "%d Change framelen from %u to %u\n", line, old_frame_len, jb->frame_len);
}
}
+#define jb_frame_inc(_jb, _i) jb_frame_inc_line(_jb, _i, __LINE__)
+
+
static inline void jb_miss(switch_jb_t *jb)
{
jb->period_miss_count++;
jb_debug(jb, 1, "Dropping oldest frame ts:%u\n", ntohl(ts));
}
+static inline void drop_newest_frame(switch_jb_t *jb)
+{
+ uint32_t ts = jb_find_highest_ts(jb);
+
+ drop_ts(jb, ts);
+ jb_debug(jb, 1, "Dropping highest frame ts:%u\n", ntohl(ts));
+}
+
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);
jb_debug(jb, (packet->header.m ? 1 : 2), "PUT packet last_ts:%u ts:%u seq:%u%s\n",
ntohl(jb->highest_wrote_ts), ntohl(node->packet.header.ts), ntohs(node->packet.header.seq), packet->header.m ? " <MARK>" : "");
-
-
-
-
- if (jb->write_init && ((abs(((int)ntohs(packet->header.seq) - ntohs(jb->highest_wrote_seq))) >= jb->max_frame_len) ||
- (abs((int)((int64_t)ntohl(node->packet.header.ts) - (int64_t)ntohl(jb->highest_wrote_ts))) > (900000 * 5)))) {
- jb_debug(jb, 2, "%s", "CHANGE DETECTED, PUNT\n");
- switch_jb_reset(jb);
- }
+ //if (jb->write_init && ((abs(((int)ntohs(packet->header.seq) - ntohs(jb->highest_wrote_seq))) >= jb->max_frame_len) ||
+ //(abs((int)((int64_t)ntohl(node->packet.header.ts) - (int64_t)ntohl(jb->highest_wrote_ts))) > (900000 * 5)))) {
+ //jb_debug(jb, 2, "%s", "CHANGE DETECTED, PUNT\n");
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s Jitter Buffer anomoly, max size may be too small...\n",
+ //jb->type == SJB_AUDIO ? "Audio" : "Video");
+ //switch_jb_reset(jb);
+
+ //}
-
-
-
if (!jb->write_init || ntohs(packet->header.seq) > ntohs(jb->highest_wrote_seq) ||
(ntohs(jb->highest_wrote_seq) > USHRT_MAX - 10 && ntohs(packet->header.seq) <= 10) ) {
jb->highest_wrote_seq = packet->header.seq;
}
if (!jb->write_init) jb->write_init = 1;
-
- if (jb->complete_frames > jb->max_frame_len + MAX_FRAME_PADDING) {
- drop_oldest_frame(jb);
- }
}
static inline void increment_ts(switch_jb_t *jb)
SWITCH_DECLARE(switch_status_t) switch_jb_set_frames(switch_jb_t *jb, uint32_t min_frame_len, uint32_t max_frame_len)
{
+ int lowest = 0;
+
switch_mutex_lock(jb->mutex);
+
+ if (jb->frame_len == jb->min_frame_len) lowest = 1;
+
jb->min_frame_len = min_frame_len;
jb->max_frame_len = max_frame_len;
jb->highest_frame_len = jb->frame_len;
}
+ if (lowest) {
+ jb->frame_len = jb->min_frame_len;
+ }
+
switch_mutex_unlock(jb->mutex);
return SWITCH_STATUS_SUCCESS;
switch_status_t status;
switch_mutex_lock(jb->mutex);
- jb_debug(jb, 2, "GET PACKET %u/%u n:%d\n", jb->complete_frames , jb->frame_len, jb->visible_nodes);
if (jb->complete_frames < jb->frame_len) {
jb_debug(jb, 2, "BUFFERING %u/%u\n", jb->complete_frames , jb->frame_len);
switch_goto_status(SWITCH_STATUS_MORE_DATA, end);
}
+ jb_debug(jb, 2, "GET PACKET %u/%u n:%d\n", jb->complete_frames , jb->frame_len, jb->visible_nodes);
+
if (++jb->period_count >= PERIOD_LEN) {
if (jb->consec_good_count >= (PERIOD_LEN - 5)) {
switch_mutex_unlock(jb->mutex);
+ if (status == SWITCH_STATUS_SUCCESS) {
+ if (jb->complete_frames > jb->max_frame_len) {
+ drop_oldest_frame(jb);
+ }
+ }
+
return status;
}
switch_jb_put_packet(rtp_session->vb, (switch_rtp_packet_t *) &rtp_session->recv_msg, *bytes);
status = SWITCH_STATUS_FALSE;
*bytes = 0;
+
+ if (!return_jb_packet) {
+ return status;
+ }
}
if (rtp_session->jb && jb_valid(rtp_session)) {
uint32_t read_ssrc = ntohl(rtp_session->last_rtp_hdr.ssrc);
+
if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && !(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) {
switch_jb_reset(rtp_session->jb);
} else if (rtp_session->last_jb_read_ssrc && rtp_session->last_jb_read_ssrc != read_ssrc) {
switch_jb_reset(rtp_session->jb);
}
+
rtp_session->last_jb_read_ssrc = read_ssrc;
if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && rtp_session->timer.interval) {
if (rtp_session->jb && !rtp_session->pause_jb && jb_valid(rtp_session)) {
switch_status_t jstatus = switch_jb_get_packet(rtp_session->jb, (switch_rtp_packet_t *) &rtp_session->recv_msg, bytes);
- if (jstatus == SWITCH_STATUS_NOTFOUND) {
- (*flags) |= SFF_PLC;
- status = SWITCH_STATUS_SUCCESS;
- rtp_session->recv_msg.header = rtp_session->last_rtp_hdr;
- *bytes = switch_jb_get_last_read_len(rtp_session->jb);
- } else if (jstatus == SWITCH_STATUS_SUCCESS) {
- rtp_session->stats.inbound.jb_packet_count++;
- status = SWITCH_STATUS_SUCCESS;
- rtp_session->last_rtp_hdr = rtp_session->recv_msg.header;
+ status = jstatus;
- if (!xcheck_jitter) {
- check_jitter(rtp_session);
- xcheck_jitter = *bytes;
+ switch(jstatus) {
+ case SWITCH_STATUS_MORE_DATA:
+ status = SWITCH_STATUS_BREAK;
+ break;
+ case SWITCH_STATUS_NOTFOUND:
+ {
+ (*flags) |= SFF_PLC;
+ status = SWITCH_STATUS_SUCCESS;
+ rtp_session->recv_msg.header = rtp_session->last_rtp_hdr;
+ *bytes = switch_jb_get_last_read_len(rtp_session->jb);
}
+ break;
+ case SWITCH_STATUS_SUCCESS:
+ default:
+ {
+ rtp_session->stats.inbound.jb_packet_count++;
+ status = SWITCH_STATUS_SUCCESS;
+ rtp_session->last_rtp_hdr = rtp_session->recv_msg.header;
+
+ if (!xcheck_jitter) {
+ check_jitter(rtp_session);
+ xcheck_jitter = *bytes;
+ }
+ }
+ break;
}
}
-
+
if (rtp_session->vb && 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;
read_pretriggered = 0;
goto rtcp;
}
-
- if (status != SWITCH_STATUS_FALSE) {
- read_pretriggered = 1;
- break;
- }
+
+ //if (status != SWITCH_STATUS_FALSE) {
+ // read_pretriggered = 1;
+ // break;
+ //}
}
} else if ((rtp_session->flags[SWITCH_RTP_FLAG_AUTOFLUSH] || rtp_session->flags[SWITCH_RTP_FLAG_STICKY_FLUSH])) {