diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 0872089269..c30cd66a63 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -78,6 +78,8 @@ struct opus_context { uint32_t debug; uint32_t use_jb_lookahead; opus_codec_settings_t codec_settings; + int look_check; + int look_ts; }; struct { @@ -610,6 +612,7 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, if (*flag & SFF_PLC) { switch_core_session_t *session = codec->session; + switch_channel_t *channel = switch_core_session_get_channel(session); switch_jb_t *jb = NULL; int got_frame = 0; @@ -618,20 +621,40 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, encoded_data = NULL; if ((opus_prefs.use_jb_lookahead || context->use_jb_lookahead) && context->codec_settings.useinbandfec && session) { - if (opus_packet_get_bandwidth(codec->cur_frame->data) != OPUS_BANDWIDTH_FULLBAND && - codec->cur_frame && (jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO))) { + if (!context->look_check) { + context->look_ts = switch_true(switch_channel_get_variable_dup(channel, "jb_use_timestamps", SWITCH_FALSE, -1)); + context->look_check = 1; + } + if (codec->cur_frame && (jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO))) { switch_frame_t frame = { 0 }; uint8_t buf[SWITCH_RTP_MAX_BUF_LEN]; + uint32_t ts = 0; + uint16_t seq = 0; + + if (context->look_ts) { + ts = codec->cur_frame->timestamp; + } else { + seq = codec->cur_frame->seq; + } + frame.data = buf; frame.buflen = sizeof(buf); + + if (switch_jb_peek_frame(jb, ts, seq, 1, &frame) == SWITCH_STATUS_SUCCESS) { + if (globals.debug || context->debug) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Lookahead frame found: %u -> %u\n", + codec->cur_frame->timestamp, frame.timestamp); + } - if (switch_jb_peek_frame(jb, codec->cur_frame->timestamp, 0, 1, &frame)) { - got_frame = 1; - fec = 1; encoded_data = frame.data; encoded_data_len = frame.datalen; + + if ((fec = switch_opus_has_fec(frame.data, frame.datalen))) { + got_frame = 1; + } + if (globals.debug || context->debug) { - if (switch_opus_has_fec(frame.data, frame.datalen)) { + if (fec) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FEC info available in packet with SEQ[%d] encoded_data_len: %d\n", codec->cur_frame->seq, encoded_data_len); } else { @@ -639,7 +662,7 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, codec->cur_frame->seq, encoded_data_len ); } } - } + } } } @@ -784,6 +807,13 @@ static switch_status_t opus_load_config(switch_bool_t reload) return status; } + memset(&opus_prefs, 0, sizeof(opus_prefs)); + opus_prefs.use_jb_lookahead = 1; + opus_prefs.keep_fec = 1; + opus_prefs.use_dtx = 1; + opus_prefs.plpct = 20; + opus_prefs.use_vbr = 1; + if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *key = (char *) switch_xml_attr_soft(param, "name"); diff --git a/src/switch_jitterbuffer.c b/src/switch_jitterbuffer.c index cf6bf6dd69..f799b11fdb 100644 --- a/src/switch_jitterbuffer.c +++ b/src/switch_jitterbuffer.c @@ -65,6 +65,7 @@ struct switch_jb_s { uint32_t target_ts; uint32_t last_target_ts; uint16_t psuedo_seq; + uint16_t last_psuedo_seq; uint32_t visible_nodes; uint32_t complete_frames; uint32_t frame_len; @@ -581,6 +582,8 @@ static inline void increment_ts(switch_jb_t *jb) { if (!jb->target_ts) return; + jb->last_psuedo_seq = jb->psuedo_seq; + jb->last_target_ts = jb->target_ts; jb->target_ts = htonl((ntohl(jb->target_ts) + jb->samples_per_frame)); jb->psuedo_seq++; } @@ -589,6 +592,7 @@ static inline void set_read_ts(switch_jb_t *jb, uint32_t ts) { if (!ts) return; + jb->last_psuedo_seq = jb->psuedo_seq; jb->last_target_ts = ts; jb->target_ts = htonl((ntohl(jb->last_target_ts) + jb->samples_per_frame)); jb->psuedo_seq++; @@ -597,6 +601,7 @@ static inline void set_read_ts(switch_jb_t *jb, uint32_t ts) static inline void increment_seq(switch_jb_t *jb) { + jb->last_target_seq = jb->target_seq; jb->target_seq = htons((ntohs(jb->target_seq) + 1)); } @@ -828,13 +833,12 @@ SWITCH_DECLARE(void) switch_jb_reset(switch_jb_t *jb) SWITCH_DECLARE(switch_status_t) switch_jb_peek_frame(switch_jb_t *jb, uint32_t ts, uint16_t seq, int peek, switch_frame_t *frame) { switch_jb_node_t *node = NULL; - if (seq) { uint16_t want_seq = seq + peek; - node = switch_core_inthash_find(jb->node_hash, want_seq); + node = switch_core_inthash_find(jb->node_hash, htons(want_seq)); } else if (ts && jb->samples_per_frame) { uint32_t want_ts = ts + (peek * jb->samples_per_frame); - node = switch_core_inthash_find(jb->node_hash_ts, want_ts); + node = switch_core_inthash_find(jb->node_hash_ts, htonl(want_ts)); } if (node) { @@ -842,6 +846,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_peek_frame(switch_jb_t *jb, uint32_t t frame->timestamp = ntohl(node->packet.header.ts); frame->m = node->packet.header.m; frame->datalen = node->len; + if (frame->data && frame->buflen > node->len) { memcpy(frame->data, node->packet.body, node->len); } @@ -1129,7 +1134,8 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp { switch_jb_node_t *node = NULL; switch_status_t status; - + int plc = 0; + switch_mutex_lock(jb->mutex); if (jb->complete_frames < jb->frame_len) { @@ -1230,6 +1236,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp switch_goto_status(SWITCH_STATUS_RESTART, end); } else { jb_debug(jb, 2, "%s", "Frame not found suggest PLC\n"); + plc = 1; switch_goto_status(SWITCH_STATUS_NOTFOUND, end); } } @@ -1253,6 +1260,22 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp end: + if (plc) { + uint16_t seq; + uint32_t ts; + + if (jb->samples_per_frame) { + seq = htons(jb->last_psuedo_seq); + } else { + seq = jb->last_target_seq; + } + + ts = jb->last_target_ts; + + packet->header.seq = seq; + packet->header.ts = ts + } + switch_mutex_unlock(jb->mutex); if (status == SWITCH_STATUS_SUCCESS && jb->type == SJB_AUDIO) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 7573aa16c6..62e48e7d1c 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -4059,7 +4059,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t * } else { status = switch_jb_create(&rtp_session->jb, SJB_AUDIO, queue_frames, max_queue_frames, rtp_session->pool); switch_jb_set_session(rtp_session->jb, rtp_session->session); - switch_jb_ts_mode(rtp_session->jb, samples_per_packet, samples_per_second); + if (switch_true(switch_channel_get_variable_dup(switch_core_session_get_channel(rtp_session->session), "jb_use_timestamps", SWITCH_FALSE, -1))) { + switch_jb_ts_mode(rtp_session->jb, samples_per_packet, samples_per_second); + } //switch_jb_debug_level(rtp_session->jb, 10); } @@ -5459,8 +5461,8 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t { (*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); + rtp_session->last_rtp_hdr = rtp_session->recv_msg.header; } break; case SWITCH_STATUS_SUCCESS: @@ -6803,10 +6805,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp if (frame->payload == rtp_session->recv_te) { switch_set_flag(frame, SFF_RFC2833); } - frame->timestamp = ntohl(rtp_session->recv_msg.header.ts); - frame->seq = (uint16_t) ntohs((uint16_t) rtp_session->recv_msg.header.seq); + frame->timestamp = ntohl(rtp_session->last_rtp_hdr.ts); + frame->seq = (uint16_t) ntohs((uint16_t) rtp_session->last_rtp_hdr.seq); frame->ssrc = ntohl(rtp_session->last_rtp_hdr.ssrc); - frame->m = rtp_session->recv_msg.header.m ? SWITCH_TRUE : SWITCH_FALSE; + frame->m = rtp_session->last_rtp_hdr.m ? SWITCH_TRUE : SWITCH_FALSE; } #ifdef ENABLE_ZRTP