diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c
index 9d25422c2992686cff15e25ac33c108cc2dad029..e60f56a4773082fc3e87e3c274899b166fee6b61 100644
--- a/channels/chan_brcm.c
+++ b/channels/chan_brcm.c
@@ -1109,6 +1109,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 -1:		return "none set"; break;
 			default: 		return "unknown id"; break;
 	}
@@ -1125,6 +1126,7 @@ static int brcm_classify_rtp_packet(int id) {
 		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);
@@ -1185,12 +1187,44 @@ static int brcm_write(struct ast_channel *ast, struct ast_frame *frame)
 	if (sub->channel_state == ONHOLD) {
 		return 0;
 	}
+    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");
+			return -1;
+		}
+
+		ap->line = sub->parent->line_id;
+		ap->cnx_id = sub->parent->line_id;
+		ap->rtp_size = RTP_HEADER_SIZE + 1;
+
+		/* copy frame data to audio packet */
+		/* 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 = 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_VOICE) {
 		packet_size = sizeof(audio_packet_t) - 1 + RTP_HEADER_SIZE + frame->datalen;
 		ap = calloc(1, packet_size);
 		if (!ap) {
-			printf("Out of memory\n");
+			ast_log(LOG_ERROR, "Out of memory\n");
 			return -1;
 		}
 
@@ -2230,8 +2264,12 @@ 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;
 		default:
-			ast_log(LOG_WARNING, "Unknown rtp codec id [%d]\n", p->data[1]);
+			ast_log(LOG_WARNING, "Unknown rtp codec id [%d], %d\n", ap->rtp[1], p->data[1]);
 			return;
 		}
 	} else {
diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h
index bfb7867ce864f96a858dcdd65b3e1822a6824a53..4316f43e2aaef82a4510a3be655ed47065190925 100644
--- a/channels/chan_brcm.h
+++ b/channels/chan_brcm.h
@@ -23,6 +23,7 @@
 #define DTMF_PAYLOAD 101
 #define DTMF 128
 #define RTCP 200
+#define CN 13
 
 #define NOT_INITIALIZED -1
 //#define EPSTATUS_DRIVER_ERROR -1
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index ba8d74e1f9a90dd75edcccc4e1409dd01b3227cd..60db00a5a42521efe64e27543795e8dbb42f6479 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -1017,6 +1017,14 @@ static int chan_pjsip_write_stream(struct ast_channel *ast, int stream_num, stru
 		}
 		break;
 	case AST_FRAME_CNG:
+	    if (!media) {
+			return 0;
+        } else if (media->write_callback) {
+			res = media->write_callback(session, media, frame);
+		} else {
+		    ast_rtp_instance_sendcng(media->rtp, frame->subclass.integer);
+		    return 0;
+		}
 		break;
 	case AST_FRAME_RTCP:
 		/* We only support writing out feedback */
diff --git a/main/channel.c b/main/channel.c
index 42083c3f47d2b409c7c4915e9b83ff05ace87bd2..436a1d736a9855b3e62a419468445870d9f20b7d 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1068,7 +1068,7 @@ static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, in
 
 		AST_LIST_INSERT_TAIL(&frames, f, frame_list);
 		new_frames++;
-		if (f->frametype == AST_FRAME_VOICE) {
+		if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_CNG) {
 			new_voice_frames++;
 		}
 	}
@@ -1076,7 +1076,7 @@ static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, in
 	/* Count how many frames exist on the queue */
 	AST_LIST_TRAVERSE(ast_channel_readq(chan), cur, frame_list) {
 		queued_frames++;
-		if (cur->frametype == AST_FRAME_VOICE) {
+		if (cur->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_CNG) {
 			queued_voice_frames++;
 		}
 	}
@@ -1088,7 +1088,7 @@ static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, in
 			/* Save the most recent frame */
 			if (!AST_LIST_NEXT(cur, frame_list)) {
 				break;
-			} else if (cur->frametype == AST_FRAME_VOICE || cur->frametype == AST_FRAME_VIDEO || cur->frametype == AST_FRAME_NULL) {
+			} else if (cur->frametype == AST_FRAME_VOICE || cur->frametype == AST_FRAME_VIDEO || cur->frametype == AST_FRAME_NULL || cur->frametype == AST_FRAME_CNG) {
 				if (++count > 64) {
 					break;
 				}
@@ -2764,6 +2764,7 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay)
 				case AST_FRAME_HTML:
 				case AST_FRAME_MODEM:
 				case AST_FRAME_RTCP:
+				case AST_FRAME_CNG:
 					done = 1;
 					break;
 				case AST_FRAME_CONTROL:
@@ -2771,7 +2772,6 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay)
 				case AST_FRAME_BRIDGE_ACTION:
 				case AST_FRAME_BRIDGE_ACTION_SYNC:
 				case AST_FRAME_NULL:
-				case AST_FRAME_CNG:
 					break;
 				}
 
@@ -3409,7 +3409,7 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram
 	generator = ast_channel_generator(chan);
 	if (!generator
 		|| !generator->generate
-		|| f->frametype != AST_FRAME_VOICE
+		|| (f->frametype != AST_FRAME_VOICE || f->frametype != AST_FRAME_CNG)
 		|| !ast_channel_generatordata(chan)
 		|| ast_channel_timingfunc(chan)) {
 		return;
@@ -3704,15 +3704,21 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
 			default:
 				break;
 			}
-		} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
+		} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO || f->frametype == AST_FRAME_CNG) {
+		    enum ast_media_type type = AST_MEDIA_TYPE_UNKNOWN;
+		    if (f->frametype == AST_FRAME_CNG) {
+		        type = AST_MEDIA_TYPE_AUDIO;
+		    } else {
+		        type = ast_format_get_type(f->subclass.format);
+		    }
 			if (ast_channel_tech(chan) && ast_channel_tech(chan)->read_stream) {
 				stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), f->stream_num);
-				default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+				default_stream = ast_channel_get_default_stream(chan, type);
 			} else {
 				/* Since this channel driver does not support multistream determine the default stream this frame
 				 * originated from and update the frame to include it.
 				 */
-				stream = default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+				stream = default_stream = ast_channel_get_default_stream(chan, type);
 				/* In order to allow media to be passed up the underlying media type has to have a format negotiated on
 				 * the channel itself. In cases where this hasn't happened the channel driver is incorrectly passing up
 				 * a frame for a format that has not been negotiated. If this occurs just drop the frame as we have no
@@ -3743,9 +3749,13 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
 			 * thing different is that we need to find the default stream so we know whether to invoke the
 			 * default stream logic or not (such as transcoding).
 			 */
-			if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
+			if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO || f->frametype == AST_FRAME_CNG)) {
 				stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), f->stream_num);
-				default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+				if (f->frametype == AST_FRAME_CNG) {
+				    default_stream = ast_channel_get_default_stream(chan, AST_MEDIA_TYPE_AUDIO);
+                } else {
+                    default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+                }
 			}
 		} else if (ast_channel_tech(chan) && ast_channel_tech(chan)->read) {
 			f = ast_channel_tech(chan)->read(chan);
@@ -3753,8 +3763,12 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
 			/* Since this channel driver does not support multistream determine the default stream this frame
 			 * originated from and update the frame to include it.
 			 */
-			if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
-				stream = default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+			if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO || f->frametype == AST_FRAME_CNG)) {
+			    if (f->frametype == AST_FRAME_CNG) {
+			        stream = default_stream = ast_channel_get_default_stream(chan, AST_MEDIA_TYPE_AUDIO);
+			    } else {
+				    stream = default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+				}
 				if (!stream) {
 					ast_frfree(f);
 					f = &ast_null_frame;
@@ -5130,7 +5144,7 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
 		}
 		stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num);
 		default_stream = ast_channel_get_default_stream(chan, ast_stream_get_type(stream));
-	} else if (fr->frametype == AST_FRAME_VOICE || fr->frametype == AST_FRAME_VIDEO || fr->frametype == AST_FRAME_MODEM) {
+	} else if (fr->frametype == AST_FRAME_VOICE || fr->frametype == AST_FRAME_VIDEO || fr->frametype == AST_FRAME_MODEM || fr->frametype == AST_FRAME_CNG) {
 		/* If we haven't been told of a stream then we need to figure out which once we need */
 		enum ast_media_type type = AST_MEDIA_TYPE_UNKNOWN;
 
@@ -5139,6 +5153,8 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
 			type = ast_format_get_type(fr->subclass.format);
 		} else if (fr->frametype == AST_FRAME_MODEM) {
 			type = AST_MEDIA_TYPE_IMAGE;
+		} else if (fr->frametype == AST_FRAME_CNG) {
+			type = AST_MEDIA_TYPE_AUDIO;
 		}
 
 		/* No stream was specified, so use the default one */
@@ -5450,6 +5466,16 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
 		}
 		ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);
 		break;
+    case AST_FRAME_CNG:
+        CHECK_BLOCKING(chan);
+		if (ast_channel_tech(chan)->write_stream && stream) {
+			res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+		} else {
+		    res = ast_channel_tech(chan)->write(chan, fr);
+			res = 0;
+		}
+		ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);
+		break;
 	default:
 		/* At this point, fr is the incoming frame and f is NULL.  Channels do
 		 * not expect to get NULL as a frame pointer and will segfault.  Hence,
diff --git a/main/frame.c b/main/frame.c
index 711f9e15f104d6a71d071f948087335d46546bd9..f5e7ad038ea45bc4ed737c81479f752c3d31dab2 100644
--- a/main/frame.c
+++ b/main/frame.c
@@ -418,6 +418,12 @@ char *ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, c
 			subclass[1] = '\0';
 		}
 		break;
+    case AST_FRAME_CNG:
+		if (slen > 1) {
+			subclass[0] = f->subclass.integer;
+			subclass[1] = '\0';
+		}
+		break;
 	case AST_FRAME_CONTROL:
 		switch (f->subclass.integer) {
 		case AST_CONTROL_HANGUP:
@@ -677,6 +683,9 @@ char *ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len
 	case AST_FRAME_DTMF_END:
 		ast_copy_string(ftype, "DTMF End", len);
 		break;
+    case AST_FRAME_CNG:
+        ast_copy_string(ftype, "Comfort Noise", len);
+		break;
 	case AST_FRAME_CONTROL:
 		ast_copy_string(ftype, "Control", len);
 		break;
@@ -761,6 +770,9 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
 	if (f->frametype == AST_FRAME_RTCP) {
 		return;
 	}
+    if (f->frametype == AST_FRAME_CNG) {
+		return;
+	}
 
 	ast_frame_type2str(f->frametype, ftype, sizeof(ftype));
 	ast_frame_subclass2str(f, subclass, sizeof(subclass), moreinfo, sizeof(moreinfo));
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index fe565f66def7b41cfac562f1371eb47ca936ca55..6b25ec43e43c4a7aacb0a72bfcef99c66f465807 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -94,6 +94,7 @@ static int send_keepalive(const void *data)
 		rtp, (int) interval, send_keepalive ? "S" : "Not s");
 
 	if (send_keepalive) {
+	    ast_verbose("Send ast_rtp_instance_sendcng\n");
 		ast_rtp_instance_sendcng(rtp, 0);
 		return keepalive * 1000;
 	}
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index e5bef24258ba2a6a56681104729c1200f0ed78da..14c2f15e5c148d42712c81e707dad73a15ceba9a 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -5311,6 +5311,11 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
 		}
 		return 0;
 	}
+    if (frame->frametype == AST_FRAME_CNG) {
+        /* send CN packet */
+        ast_rtp_sendcng(instance, frame->subclass.integer);
+        return 0;
+    }
 
 	/* If there is no data length we can't very well send the packet */
 	if (!frame->datalen) {