diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c
index 890cad713975086637f79f94b1f861684f225a0b..eaa896dd0176ec4e4840e0885cb13903146e1ecf 100644
--- a/src/channels/chan_voicemngr.c
+++ b/src/channels/chan_voicemngr.c
@@ -79,7 +79,8 @@ static int cwtimeout_cb(const void *data);
 static int cwbeep_cb(const void *data);
 static int r4hanguptimeout_cb(const void *data);
 static void chan_voicemngr_generate_rtp_packet(struct chan_voicemngr_subchannel *p, uint8_t *packet_buf, int type, int seqno, unsigned int rtp_timestamp);
-static void chan_voicemngr_process_rtcp_packet(struct chan_voicemngr_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size);
+static void chan_voicemngr_process_incoming_rtcp_packet(struct chan_voicemngr_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size);
+static void chan_voicemngr_process_outgoing_rtcp_packet(struct chan_voicemngr_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size);
 static int chan_voicemngr_mute_connection(struct chan_voicemngr_subchannel *p);
 static int chan_voicemngr_unmute_connection(struct chan_voicemngr_subchannel *p);
 static int chan_voicemngr_close_connection(struct chan_voicemngr_subchannel *p);
@@ -1796,7 +1797,7 @@ static int chan_voicemngr_write(struct ast_channel *ast, struct ast_frame *frame
 		/* copy frame data to audio packet */
 		memcpy(ap->rtp, frame->data.ptr, frame->datalen);
 
-		chan_voicemngr_process_rtcp_packet(sub, ap->rtp, ap->rtp_size);
+		chan_voicemngr_process_incoming_rtcp_packet(sub, ap->rtp, ap->rtp_size);
 
 		pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size);
 		free(ap);
@@ -3108,6 +3109,7 @@ static void audio_packet_handler(pe_packet_t *p) {
 		frame.data.ptr = ap->rtp;
 		frame.datalen = ap->rtp_size;
 		frame.subclass.integer = (packet_type == CHAN_VOICEMNGR_RTCP_SR ? RTCP_SR : RTCP_RR);
+		chan_voicemngr_process_outgoing_rtcp_packet(sub, ap->rtp, ap->rtp_size);
 	} else {
 		//ast_debug(5, "Dropping RTP frame of type %d.\n", packet_type);
 		drop_frame=1;
@@ -3648,8 +3650,12 @@ static struct chan_voicemngr_pvt *chan_voicemngr_allocate_pvt(void)
 				sub->period = default_ptime;												// 20 ms
 				sub->conference_initiator = 0;
 				tmp->sub[i] = sub;
-				sub->jitter_count = 0;
-				sub->farEndInterrivalJitter = 0;
+				sub->remote_jitter_count = 0;
+				sub->local_jitter_count = 0;
+				sub->farEndInterarrivalJitter = 0;
+				sub->receiveInterarrivalJitter = 0;
+				sub->totalFarEndInterarrivalJitter = 0;
+				sub->totalReceiveInterarrivalJitter = 0;
 				sub->blind_xfer_target[0] = '\0';
 				ast_debug(2, "subchannel created\n");
 			} else {
@@ -4522,7 +4528,8 @@ enum {
 	RTP_STATS_TX_PKTS,
 	RTP_STATS_JB_AVG,
 	RTP_STATS_JITTER,
-	RTP_STATS_LOSS_RATE,
+	RTP_STATS_LOCAL_LOSS_RATE,
+	RTP_STATS_REMOTE_LOSS_RATE,
 	RTP_STATS_MAX_JITTER,
 	RTP_STATS_AVERAGE_ROUND_TRIP_DELAY,
 	RTP_STATS_OVERRUNS,
@@ -4554,7 +4561,8 @@ static const struct blobmsg_policy endpt_rtp_stats_policy[__MAX_RTP_STATS] = {
 	[RTP_STATS_TX_PKTS] = { .name = "txpkts", .type = BLOBMSG_TYPE_INT32 },
 	[RTP_STATS_JB_AVG] = { .name = "jbAvg", .type = BLOBMSG_TYPE_INT16 },
 	[RTP_STATS_JITTER] = { .name = "jitter", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_LOSS_RATE] = { .name = "uLossRate", .type = BLOBMSG_TYPE_INT16 },
+	[RTP_STATS_LOCAL_LOSS_RATE] = { .name = "localLossRate", .type = BLOBMSG_TYPE_INT16 },
+	[RTP_STATS_REMOTE_LOSS_RATE] = { .name = "remoteLossRate", .type = BLOBMSG_TYPE_INT16 },
 	[RTP_STATS_MAX_JITTER] = { .name = "maxJitter", .type = BLOBMSG_TYPE_INT32 },
 	[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY] = { .name = "averageRoundTripDelay", .type = BLOBMSG_TYPE_INT32 },
 	[RTP_STATS_OVERRUNS] = { .name = "overruns", .type = BLOBMSG_TYPE_INT16 },
@@ -4701,8 +4709,10 @@ static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struc
 		sub->rtp_stats.jbAvg = blobmsg_get_u16(tb[RTP_STATS_JB_AVG]);
 	if (tb[RTP_STATS_JITTER])
 		sub->rtp_stats.jitter = blobmsg_get_u32(tb[RTP_STATS_JITTER]);
-	if (tb[RTP_STATS_LOSS_RATE])
-		sub->rtp_stats.uLossRate = blobmsg_get_u16(tb[RTP_STATS_LOSS_RATE]);
+	if (tb[RTP_STATS_LOCAL_LOSS_RATE])
+		sub->rtp_stats.localLossRate = blobmsg_get_u16(tb[RTP_STATS_LOCAL_LOSS_RATE]);
+	if (tb[RTP_STATS_REMOTE_LOSS_RATE])
+		sub->rtp_stats.remoteLossRate = blobmsg_get_u16(tb[RTP_STATS_REMOTE_LOSS_RATE]);
 	if (tb[RTP_STATS_MAX_JITTER])
 		sub->rtp_stats.maxJitter = blobmsg_get_u32(tb[RTP_STATS_MAX_JITTER]);
 	if (tb[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY])
@@ -4721,7 +4731,10 @@ static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struc
 			line_stats[sip_client_id].total_underruns += underruns;
 		}
 	}
-	sub->rtp_stats.averageFarEndInterarrivalJitter = sub->jitter_count ? (sub->farEndInterrivalJitter / sub->jitter_count) : 0;
+	sub->rtp_stats.farEndInterarrivalJitter = sub->farEndInterarrivalJitter;
+	sub->rtp_stats.receiveInterarrivalJitter = sub->receiveInterarrivalJitter;
+	sub->rtp_stats.averageFarEndInterarrivalJitter = sub->remote_jitter_count ? (sub->totalFarEndInterarrivalJitter / sub->remote_jitter_count) : 0;
+	sub->rtp_stats.averageReceiveInterarrivalJitter = sub->local_jitter_count ? (sub->totalReceiveInterarrivalJitter / sub->local_jitter_count) : 0;
 
 	ast_log(LOG_DEBUG, "RTP stats received:\nlocalBurstDensity: %d, remoteBurstDensity: %d, "
 			"localBurstDuration: %d, remoteBurstDuration: %d, localGapDensity: %d, "
@@ -4729,16 +4742,18 @@ static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struc
 			"localJbRate: %d, remoteJbRate: %d, localJbMax: %d, remoteJbMax: %d, "
 			"localJbNominal: %d remoteJbNominal: %d, localJbAbsMax: %d, "
 			"remoteJbAbsMax: %d, discarded: %d, lost: %d, rxpkts: %d, txpkts: %d, "
-			"jbAvg: %d, jitter: %d, uLossRate: %d, maxJitter: %d, averageRoundTripDelay: %d, "
-			"averageFarEndInterarrivalJitter: %d, overruns: %d, underruns: %d\n",
+			"jbAvg: %d, jitter: %d, localLossRate: %d, remoteLossRate: %d, maxJitter: %d, averageRoundTripDelay: %d, "
+			"farEndInterarrivalJitter: %d, averageFarEndInterarrivalJitter: %d, receiveInterarrivalJitter: %d, averageReceiveInterarrivalJitter: %d, "
+			"overruns: %d, underruns: %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, overruns, underruns);
+			sub->rtp_stats.localLossRate, sub->rtp_stats.remoteLossRate, sub->rtp_stats.maxJitter, sub->rtp_stats.averageRoundTripDelay,
+			sub->rtp_stats.farEndInterarrivalJitter, sub->rtp_stats.averageFarEndInterarrivalJitter, sub->rtp_stats.receiveInterarrivalJitter, sub->rtp_stats.averageReceiveInterarrivalJitter,
+			overruns, underruns);
 }
 
 static int endpt_get_rtp_stats(int line) {
@@ -5245,8 +5260,12 @@ static int chan_voicemngr_create_connection(struct chan_voicemngr_subchannel *su
 
 		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;
+		sub->remote_jitter_count = 0;
+		sub->local_jitter_count = 0;
+		sub->farEndInterarrivalJitter = 0;
+		sub->receiveInterarrivalJitter = 0;
+		sub->totalFarEndInterarrivalJitter = 0;
+		sub->totalReceiveInterarrivalJitter = 0;
 
 		if (sub->owner) {
 			sub->call_id = ast_channel_callid(sub->owner);
@@ -5516,10 +5535,10 @@ static void chan_voicemngr_generate_rtp_packet(struct chan_voicemngr_subchannel
  * This function does the followings.
  * - Replace SSRC with the value from the sub-channel, which is also used by the corresponding RTP packets within
  *   the same session. Both RTP and RTCP packets in the same session must have the same SSRC value.
- * - Accumulate "Interarrival jitter" for farEndInterrivalJitter and jitter_count which are used to calculate
+ * - Accumulate "Interarrival jitter" for farEndInterarrivalJitter and remote_jitter_count which are used to calculate
  *   averageFarEndInterarrivalJitter.
  */
-static void chan_voicemngr_process_rtcp_packet(struct chan_voicemngr_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size)
+static void chan_voicemngr_process_incoming_rtcp_packet(struct chan_voicemngr_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size)
 {
 	struct rtcp_header_t *rtcp_hdr = (struct rtcp_header_t *)rtcp_frame;
 	uint8_t *packet_end = rtcp_frame + rtcp_size;
@@ -5530,19 +5549,50 @@ static void chan_voicemngr_process_rtcp_packet(struct chan_voicemngr_subchannel
 			RTCP_PKT_END(rtcp_hdr) <= packet_end) {       // Packet length validation
 		switch (rtcp_hdr->pt) {
 			case RTCP_SR:
-				p->jitter_count++;
-				p->farEndInterrivalJitter += RTCP_SR_GET_INTERARRIVAL_JITTER(rtcp_hdr);
+				p->remote_jitter_count++;
+				p->farEndInterarrivalJitter = RTCP_SR_GET_INTERARRIVAL_JITTER(rtcp_hdr);
+				p->totalFarEndInterarrivalJitter += p->farEndInterarrivalJitter;
 				packet_buf32[7] = p->dsp_ssrc;	// replace Source Identifier with dsp's SSRC
 				/* Intentional fall through */
 			case RTCP_RR:
 			case RTCP_SDES:
 			case RTCP_XR:
+			case RTCP_BYE:
 				// Replace SSRC with far end  SSRC for all types of RTCP packets above
 				rtcp_hdr->ssrc = p->far_end_ssrc;
 				break;
 
 			default:
-				ast_log(LOG_ERROR, "Unknown RTCP packet type:%hhu\n", rtcp_hdr->pt);
+				ast_log(LOG_ERROR, "Unknown incoming RTCP packet type:%hhu\n", rtcp_hdr->pt);
+				break;
+		}
+		// Move to the next RTCP header for a compound RTCP packet which contains more than one packet types
+		rtcp_hdr = (struct rtcp_header_t *)RTCP_PKT_END(rtcp_hdr);
+	}
+}
+
+static void chan_voicemngr_process_outgoing_rtcp_packet(struct chan_voicemngr_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size)
+{
+	struct rtcp_header_t *rtcp_hdr = (struct rtcp_header_t *)rtcp_frame;
+	uint8_t *packet_end = rtcp_frame + rtcp_size;
+
+	while ((uint8_t *)rtcp_hdr + sizeof(struct rtcp_header_t) <= packet_end && // Minimum RTCP packet size validation
+			RTCP_GET_VERSION(rtcp_hdr) == RTP_VERSION &&  // RTP version validation
+			RTCP_PKT_END(rtcp_hdr) <= packet_end) {       // Packet length validation
+		switch (rtcp_hdr->pt) {
+			case RTCP_SR:
+				p->local_jitter_count++;
+				p->receiveInterarrivalJitter = RTCP_SR_GET_INTERARRIVAL_JITTER(rtcp_hdr);
+				p->totalReceiveInterarrivalJitter += p->receiveInterarrivalJitter;
+				break;
+			case RTCP_RR:
+			case RTCP_SDES:
+			case RTCP_XR:
+			case RTCP_BYE:
+				break;
+
+			default:
+				ast_log(LOG_ERROR, "Unknown outgoing RTCP packet type:%hhu\n", rtcp_hdr->pt);
 				break;
 		}
 		// Move to the next RTCP header for a compound RTCP packet which contains more than one packet types
diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h
index f876e38d39ff763f23a6ecd14e13ee062e45964d..dd5d985f2113934cd4e6ecb0d3db47ffc64bedea 100644
--- a/src/channels/chan_voicemngr.h
+++ b/src/channels/chan_voicemngr.h
@@ -131,6 +131,7 @@ struct line_stats_t {
 #define RTCP_SR      200
 #define RTCP_RR      201
 #define RTCP_SDES    202
+#define RTCP_BYE     203
 #define RTCP_XR      207
 struct __attribute__((packed)) rtcp_header_t {
 	uint8_t  v_p_rc; // Version, padding and reception report count
@@ -169,8 +170,12 @@ struct chan_voicemngr_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;
+	unsigned int remote_jitter_count;
+	unsigned int local_jitter_count;
+	unsigned int farEndInterarrivalJitter;
+	unsigned int receiveInterarrivalJitter;
+	unsigned long int totalFarEndInterarrivalJitter;
+	unsigned long int totalReceiveInterarrivalJitter;
 	char blind_xfer_target[32];	/* Transfer target for unattended call transfer */
 	int updated_codec;
 	int sip_client_id;	/* The SIP client used for the current call */