diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c index 4f710d60f29395d22643fc11b4611daaccc3ebdf..ca1c19287bdad4d391812a76dbed3ae493cffc0a 100644 --- a/channels/chan_brcm.c +++ b/channels/chan_brcm.c @@ -76,6 +76,7 @@ static int brcm_signal_dialtone(struct brcm_pvt *p); static int brcm_in_conference(const struct brcm_pvt *p); static int cwtimeout_cb(const void *data); static int r4hanguptimeout_cb(const void *data); +static void brcm_generate_rtp_packet(struct brcm_subchannel *p, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp); static int brcm_mute_connection(struct brcm_subchannel *p); static int brcm_unmute_connection(struct brcm_subchannel *p); static int brcm_close_connection(struct brcm_subchannel *p); @@ -1190,7 +1191,7 @@ static char* brcm_get_codec_string(int id) { case G726: return "g726"; break; case G729: return "g729"; break; case G722: return "g722"; break; - case CN: return "cn"; break; + case CN: return "cn"; break; case -1: return "none set"; break; default: return "unknown id"; break; } @@ -1201,15 +1202,14 @@ static int brcm_classify_rtp_packet(int id) { //ast_debug(5, "RTP Packet ID = %d\n", id); switch (id) { - case PCMU: return BRCM_AUDIO; - case G726: return BRCM_AUDIO; - case G723: return BRCM_AUDIO; - case PCMA: return BRCM_AUDIO; - case G729: return BRCM_AUDIO; - case G722: return BRCM_AUDIO; - case CN: return BRCM_AUDIO; - case RTCP_SR: return BRCM_RTCP_SR; - case RTCP_RR: return BRCM_RTCP_RR; + case PCMU: return BRCM_AUDIO; + case G726: return BRCM_AUDIO; + case G723: return BRCM_AUDIO; + case PCMA: return BRCM_AUDIO; + case G729: return BRCM_AUDIO; + case G722: return BRCM_AUDIO; + case CN: return BRCM_AUDIO; + case RTCP: return BRCM_UNKNOWN; // Ignored packet. default: ast_verbose("Unknown rtp packet id %d\n", id); return BRCM_UNKNOWN; @@ -1269,9 +1269,10 @@ static int brcm_write(struct ast_channel *ast, struct ast_frame *frame) if (sub->channel_state == ONHOLD) { return 0; } - - if(frame->frametype == AST_FRAME_VOICE || frame->frametype == AST_FRAME_CNG) { - packet_size = sizeof(audio_packet_t) - 1 + frame->datalen; + if (frame->frametype == AST_FRAME_CNG) { + /*packet_size = sizeof(audio_packet_t) - 1 + RTP_HEADER_SIZE + frame->datalen; + CNG paket has only 1 data for the noise lvl, datalen=1*/ + packet_size = sizeof(audio_packet_t) + RTP_HEADER_SIZE ; ap = calloc(1, packet_size); if (!ap) { ast_log(LOG_ERROR, "Out of memory\n"); @@ -1280,26 +1281,29 @@ static int brcm_write(struct ast_channel *ast, struct ast_frame *frame) ap->line = sub->parent->line_id; ap->cnx_id = sub->parent->line_id; - ap->rtp_size = frame->datalen; + ap->rtp_size = RTP_HEADER_SIZE + 1; /* copy frame data to audio packet */ - memcpy(ap->rtp, frame->data.ptr, frame->datalen); + /* level = 127 - (level & 0x7f); */ + ap->rtp[12]=127 - (frame->subclass.integer & 0x7f); //ast_mutex_lock(&sub->parent->lock); pvt_lock(sub->parent, "TELCHAN write frame"); + /* generate the rtp header */ + brcm_generate_rtp_packet(sub, ap->rtp, CN, 0, 0); + /* set rtp id sent to endpoint */ - sub->codec = frame->frametype == AST_FRAME_CNG ? CN : map_ast_codec_id_to_rtp(frame->subclass.format); + sub->codec = CN; //ast_mutex_unlock(&sub->parent->lock); pvt_unlock(sub->parent); - pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size); free(ap); - } + } - if(frame->frametype == AST_FRAME_RTCP) { - packet_size = sizeof(audio_packet_t) - 1 + frame->datalen; + if(frame->frametype == AST_FRAME_VOICE) { + packet_size = sizeof(audio_packet_t) - 1 + RTP_HEADER_SIZE + frame->datalen; ap = calloc(1, packet_size); if (!ap) { ast_log(LOG_ERROR, "Out of memory\n"); @@ -1308,15 +1312,22 @@ static int brcm_write(struct ast_channel *ast, struct ast_frame *frame) ap->line = sub->parent->line_id; ap->cnx_id = sub->parent->line_id; - ap->rtp_size = frame->datalen; + ap->rtp_size = RTP_HEADER_SIZE + frame->datalen; /* copy frame data to audio packet */ - memcpy(ap->rtp, frame->data.ptr, frame->datalen); + memcpy(ap->rtp + RTP_HEADER_SIZE, frame->data.ptr, frame->datalen); - if (frame->subclass.integer == RTCP_SR && frame->datalen >= 44) { - sub->jitter_count++; - sub->farEndInterrivalJitter += ((ap->rtp[40] << 24) | (ap->rtp[41] << 16) | (ap->rtp[42] << 8) | (ap->rtp[43])); - } + //ast_mutex_lock(&sub->parent->lock); + pvt_lock(sub->parent, "TELCHAN write frame"); + + /* generate the rtp header */ + brcm_generate_rtp_packet(sub, ap->rtp, map_ast_codec_id_to_rtp(frame->subclass.format), 0, 0); + + /* set rtp id sent to endpoint */ + sub->codec = map_ast_codec_id_to_rtp(frame->subclass.format); + + //ast_mutex_unlock(&sub->parent->lock); + pvt_unlock(sub->parent); pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size); free(ap); @@ -2308,8 +2319,8 @@ static void audio_packet_handler(pe_packet_t *p) { (ap->rtp[0] & 0x80) && ap->rtp_size) { fr.frametype = AST_FRAME_VOICE; fr.offset = 0; - fr.data.ptr = ap->rtp; - fr.datalen = ap->rtp_size; + fr.data.ptr = ap->rtp + 12; + fr.datalen = ap->rtp_size - 12; switch (ap->rtp[1]) { case PCMU: @@ -2336,21 +2347,16 @@ static void audio_packet_handler(pe_packet_t *p) { fr.subclass.format = ast_format_g722; fr.samples = 160; break; - case CN: - fr.frametype = AST_FRAME_CNG; - fr.subclass.integer = ap->rtp[12]; - break; + case CN: + fr.frametype = AST_FRAME_CNG; + fr.subclass.integer = ap->rtp[12]; + break; default: ast_log(LOG_WARNING, "Unknown rtp codec id [%d], %d\n", ap->rtp[1], p->data[1]); return; } - } else if (rtp_packet_type == BRCM_RTCP_SR || rtp_packet_type == BRCM_RTCP_RR) { - fr.frametype = AST_FRAME_RTCP; - fr.data.ptr = ap->rtp; - fr.datalen = ap->rtp_size; - fr.subclass.integer = (rtp_packet_type == BRCM_RTCP_SR ? RTCP_SR : RTCP_RR); } else { - ast_debug(5, "Dropping RTP frame of type %d.\n", rtp_packet_type); + //ast_debug(5, "Dropping RTP frame of type %d.\n", rtp_packet_type); drop_frame=1; //pvt_unlock(sub->parent); } @@ -2790,6 +2796,9 @@ static struct brcm_pvt *brcm_allocate_pvt(void) sub->connection_id = -1; sub->connection_init = 0; sub->channel_state = ONHOOK; + sub->time_stamp = 0; + sub->sequence_number = 0; + sub->ssrc = 0; sub->codec = -1; sub->parent = tmp; sub->cw_timer_id = -1; @@ -2799,8 +2808,6 @@ static struct brcm_pvt *brcm_allocate_pvt(void) sub->period = 20; // 20 ms sub->conference_initiator = 0; tmp->sub[i] = sub; - sub->jitter_count = 0; - sub->farEndInterrivalJitter = 0; ast_debug(2, "subchannel created\n"); } else { ast_log(LOG_ERROR, "no subchannel created\n"); @@ -3044,6 +3051,9 @@ static void brcm_show_subchannels(struct ast_cli_args *a, struct brcm_pvt *p) ast_cli(a->fd, " Channel state : %s\n", state2str(sub->channel_state)); ast_cli(a->fd, " Connection init : %d\n", sub->connection_init); ast_cli(a->fd, " Codec used : %s\n", brcm_get_codec_string(sub->codec)); + ast_cli(a->fd, " RTP sequence number : %d\n", sub->sequence_number); + ast_cli(a->fd, " RTP SSRC : %d\n", sub->ssrc); + ast_cli(a->fd, " RTP timestamp : %d\n", sub->time_stamp); ast_cli(a->fd, " CW Timer id : %d\n", sub->cw_timer_id); ast_cli(a->fd, " CW Rejected : %d\n", sub->cw_rejected); ast_cli(a->fd, " R4 Hangup Timer id : %d\n", sub->r4_hangup_timer_id); @@ -3816,23 +3826,20 @@ static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struc if (tb[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY]) sub->rtp_stats.averageRoundTripDelay = blobmsg_get_u32(tb[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY]); - sub->rtp_stats.averageFarEndInterarrivalJitter = sub->jitter_count ? (sub->farEndInterrivalJitter / sub->jitter_count) : 0; - ast_log(LOG_DEBUG, "RTP stats received:\nlocalBurstDensity: %d\nremoteBurstDensity: %d\n" "localBurstDuration: %d\nremoteBurstDuration: %d\nlocalGapDensity: %d\n" "remoteGapDensity: %d\nlocalGapDuration: %d\nremoteGapDuration: %d\n" "localJbRate: %d\nremoteJbRate: %d\nlocalJbMax: %d\nremoteJbMax: %d\n" "localJbNominal: %d\nremoteJbNominal: %d\nlocalJbAbsMax: %d\n" "remoteJbAbsMax: %d\ndiscarded: %d\nlost: %d\nrxpkts: %d\ntxpkts: %d\n" - "jbAvg: %d\njitter: %d\nuLossRate: %d\nmaxJitter: %d\naverageRoundTripDelay: %d\n" - "averageFarEndInterarrivalJitter: %d\n", + "jbAvg: %d\njitter: %d\nuLossRate: %d\nmaxJitter: %d\naverageRoundTripDelay: %d\n", sub->rtp_stats.localBurstDensity, sub->rtp_stats.remoteBurstDensity, sub->rtp_stats.localBurstDuration, sub->rtp_stats.remoteBurstDuration, sub->rtp_stats.localGapDensity, sub->rtp_stats.remoteGapDensity, sub->rtp_stats.localGapDuration, sub->rtp_stats.remoteGapDuration, sub->rtp_stats.localJbRate, sub->rtp_stats.remoteJbRate, sub->rtp_stats.localJbMax, sub->rtp_stats.remoteJbMax, sub->rtp_stats.localJbNominal, sub->rtp_stats.remoteJbNominal, sub->rtp_stats.localJbAbsMax, sub->rtp_stats.remoteJbAbsMax, sub->rtp_stats.discarded, sub->rtp_stats.lost, sub->rtp_stats.rxpkts, sub->rtp_stats.txpkts, sub->rtp_stats.jbAvg, sub->rtp_stats.jitter, - sub->rtp_stats.uLossRate, sub->rtp_stats.maxJitter, sub->rtp_stats.averageRoundTripDelay, sub->rtp_stats.averageFarEndInterarrivalJitter); + sub->rtp_stats.uLossRate, sub->rtp_stats.maxJitter, sub->rtp_stats.averageRoundTripDelay); } static int endpt_get_rtp_stats(int line) { @@ -4312,10 +4319,11 @@ static int brcm_signal_callerid(struct ast_channel *chan, struct brcm_subchannel static int brcm_create_connection(struct brcm_subchannel *sub) { if (!sub->connection_init) { + /* generate random nr for rtp header */ + sub->ssrc = rand(); + ast_debug(1, "Creating virtual Asterisk connection for pvt line_id=%i connection_id=%d\n", sub->parent->line_id, sub->connection_id); sub->connection_init = 1; - sub->jitter_count = 0; - sub->farEndInterrivalJitter = 0; if(!brcm_in_onhold(sub->parent) && !brcm_in_call(sub->parent)) { // Is there another connection already? ast_debug(1, "Creating real endpoint connection for pvt line_id=%i\n", sub->parent->line_id); endpt_connection(sub->parent->line_id, sub->connection_id, "create"); @@ -4442,6 +4450,27 @@ static int brcm_close_connection(struct brcm_subchannel *sub) return 0; } + +/* Generate rtp payload, 12 bytes of header and 160 bytes of ulaw payload */ +static void brcm_generate_rtp_packet(struct brcm_subchannel *sub, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp) { + unsigned short* packet_buf16 = (unsigned short*)packet_buf; + unsigned int* packet_buf32 = (unsigned int*)packet_buf; + + //Generate the rtp header, packet is zero from the start, that fact is used + packet_buf[0] |= 0x80; //Set version 2 of header + //Padding 0 + //Extension 0 + //CSRC count 0 + packet_buf[1] = type; + packet_buf[1] |= marker?0x80:0x00; + packet_buf16[1] = htons(sub->sequence_number++); //Add sequence number + if (sub->sequence_number > 0xFFFF) sub->sequence_number=0; + packet_buf32[1] = htonl(sub->time_stamp); //Add timestamp + sub->time_stamp += sub->period*8; + packet_buf32[2] = sub->ssrc; //Random SSRC +} + + static void brcm_dialtone_set(struct brcm_pvt *p, dialtone_state state) { ast_debug(3, "Old dialtone: %s, new dialtone: %s\n", diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h index 58d2b95777519c47e2180b190706b8f221f8f65c..8bce65d5dfe69e0d688fd614c72a4645e10d52f4 100644 --- a/channels/chan_brcm.h +++ b/channels/chan_brcm.h @@ -22,8 +22,7 @@ #define G722 9 #define DTMF_PAYLOAD 101 #define DTMF 128 -#define RTCP_SR 200 -#define RTCP_RR 201 +#define RTCP 200 #define CN 13 #define NOT_INITIALIZED -1 @@ -102,7 +101,10 @@ struct brcm_subchannel { enum brcm_channel_state channel_state; /* Channel states */ unsigned int connection_init; /* State for endpoint id connection initialization */ struct ast_frame fr; /* Frame */ + unsigned int sequence_number; /* Endpoint RTP sequence number state */ + unsigned int time_stamp; /* Endpoint RTP time stamp state */ unsigned int period; /* Endpoint RTP period */ + unsigned int ssrc; /* Endpoint RTP synchronization source */ int codec; /* Used codec */ struct brcm_pvt *parent; /* brcm_line owning this subchannel */ int cw_timer_id; /* Current call waiting timer id, -1 if no active timer */ @@ -113,8 +115,6 @@ struct brcm_subchannel { char *conference_id; /* uuid of the conference initiated by this subchannel */ int conf_timer_id; /* Current conference call timer id, -1 if no active timer */ rtp_statistics rtp_stats; /* RTP statistics for currently hanging up channel */ - unsigned int jitter_count; - unsigned long int farEndInterrivalJitter; }; @@ -163,8 +163,6 @@ struct brcm_pvt { enum rtp_type { BRCM_UNKNOWN, BRCM_AUDIO, - BRCM_RTCP_SR, - BRCM_RTCP_RR };