diff --git a/src/mod/codecs/mod_avcodec/mod_avcodec.c b/src/mod/codecs/mod_avcodec/mod_avcodec.c
index 9496e5f9ad..45c8d00da8 100644
--- a/src/mod/codecs/mod_avcodec/mod_avcodec.c
+++ b/src/mod/codecs/mod_avcodec/mod_avcodec.c
@@ -36,7 +36,7 @@
 #include <libavutil/imgutils.h>
 
 /* use libx264 by default, comment out to use the ffmpeg/avcodec wrapper */
-#define H264_CODEC_USE_LIBX264
+// #define H264_CODEC_USE_LIBX264
 
 #define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE
 
@@ -146,7 +146,6 @@ typedef struct h264_codec_context_s {
 	x264_nal_t *x264_nals;
 	int x264_nal_count;
 	int cur_nalu_index;
-
 #endif
 
 } h264_codec_context_t;
@@ -269,7 +268,7 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, switch_frame_t
 
 	switch_assert(nalu_len > 0);
 
-	// if ((*buffer & 0x1f) == 7) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Got SPS\n");
+	// if ((*buffer & 0x1f) == 7) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Got SPS | %02x %02x %02x\n", *(buffer+1), *(buffer+2), *(buffer+3));
 
 	memcpy(frame->data, buffer, nalu_len);
 	frame->datalen = nalu_len;
@@ -365,11 +364,11 @@ static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_
 
 	if (!nalu->start) {
 		frame->datalen = 0;
-		frame->m = 1;
+		frame->m = 0;
 		if (context->encoder_avpacket.size > 0) av_free_packet(&context->encoder_avpacket);
 		if (context->encoder_avframe->data) av_freep(&context->encoder_avframe->data[0]);
 		context->nalu_current_index = 0;
-		return SWITCH_STATUS_SUCCESS;
+		return SWITCH_STATUS_NOTFOUND;
 	}
 
 	assert(nalu->len);
@@ -395,7 +394,7 @@ static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_
 		int left = nalu->len - (nalu->eat - nalu->start);
 		uint8_t *p = frame->data;
 
-		if (left <= (1400 - 2)) {
+		if (left <= (SLICE_SIZE - 2)) {
 			p[0] = nri | 28; // FU-A
 			p[1] = 0x40 | nalu_type;
 			memcpy(p+2, nalu->eat, left);
@@ -410,9 +409,9 @@ static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_
 			p[0] = nri | 28; // FU-A
 			p[1] = start | nalu_type;
 			if (start) nalu->eat++;
-			memcpy(p+2, nalu->eat, 1400 - 2);
-			nalu->eat += (1400 - 2);
-			frame->datalen = 1400;
+			memcpy(p+2, nalu->eat, SLICE_SIZE - 2);
+			nalu->eat += (SLICE_SIZE - 2);
+			frame->datalen = SLICE_SIZE;
 			return SWITCH_STATUS_MORE_DATA;
 		}
 	}
@@ -428,26 +427,60 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
 		return SWITCH_STATUS_FALSE;
 	}
 
-	if (!context->encoder_ctx) context->encoder_ctx = avcodec_alloc_context3(context->encoder);
+	if (context->encoder_ctx) {
+		if (avcodec_is_open(context->encoder_ctx)) {
+			avcodec_close(context->encoder_ctx);
+		}
+		av_free(context->encoder_ctx);
+		context->encoder_ctx = NULL;
+	}
+
+	context->encoder_ctx = avcodec_alloc_context3(context->encoder);
 
 	if (!context->encoder_ctx) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate video encoder context\n");
 		return SWITCH_STATUS_FALSE;
 	}
 
-	context->encoder_ctx->bit_rate = 400000;
+	if (width && height) {
+		context->codec_settings.video.width = width;
+		context->codec_settings.video.height = height;
+	}
+
+	if (!context->codec_settings.video.width) {
+		context->codec_settings.video.width = 1280;
+	}
+
+	if (!context->codec_settings.video.height) {
+		context->codec_settings.video.height = 720;
+	}
+
+	if (context->codec_settings.video.bandwidth) {
+		context->bandwidth = context->codec_settings.video.bandwidth;
+	} else {
+		context->bandwidth = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 0, 0);
+	}
+
+	if (context->bandwidth > 5120) {
+		context->bandwidth = 5120;
+	}
+
+	context->encoder_ctx->bit_rate = context->bandwidth * 1024;
 	context->encoder_ctx->width = width;
 	context->encoder_ctx->height = height;
 	/* frames per second */
-	context->encoder_ctx->time_base = (AVRational){1, 90000};
+	context->encoder_ctx->time_base = (AVRational){1, FPS};
 	context->encoder_ctx->gop_size = FPS * 3; /* emit one intra frame every 3 seconds */
 	context->encoder_ctx->max_b_frames = 0;
 	context->encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
 	context->encoder_ctx->thread_count = 1; // switch_core_cpu_count();
 	context->encoder_ctx->rtp_payload_size = SLICE_SIZE;
-	av_opt_set(context->encoder_ctx->priv_data, "preset", "fast", 0);
-
-	if (avcodec_is_open(context->encoder_ctx)) avcodec_close(context->encoder_ctx);
+	context->encoder_ctx->profile = 66;
+	context->encoder_ctx->level = 31;
+	av_opt_set(context->encoder_ctx->priv_data, "preset", "veryfast", 0);
+	av_opt_set(context->encoder_ctx->priv_data, "tune", "animation+zerolatency", 0);
+	av_opt_set(context->encoder_ctx->priv_data, "profile", "baseline", 0);
+	// av_opt_set_int(context->encoder_ctx->priv_data, "slice-max-size", SLICE_SIZE, 0);
 
 	if (avcodec_open2(context->encoder_ctx, context->encoder, NULL) < 0) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open codec\n");
@@ -481,7 +514,6 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
 			context->codec_settings = *codec_settings;
 		}
 
-
 		if (decoding) {
 			context->decoder = avcodec_find_decoder(AV_CODEC_ID_H264);
 
@@ -543,7 +575,7 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
 	AVCodecContext *avctx = context->encoder_ctx;
 	int ret;
 	int *got_output = &context->got_encoded_output;
-	AVFrame *avframe;
+	AVFrame *avframe = NULL;
 	AVPacket *pkt = &context->encoder_avpacket;
 	uint32_t width = 0;
 	uint32_t height = 0;
@@ -576,31 +608,51 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
 		if (open_encoder(context, width, height) != SWITCH_STATUS_SUCCESS) {
 			goto error;
 		}
+		avctx = context->encoder_ctx;
+	}
+
+	if (context->change_bandwidth) {
+		context->codec_settings.video.bandwidth = context->change_bandwidth;
+		context->change_bandwidth = 0;
+		if (open_encoder(context, width, height) != SWITCH_STATUS_SUCCESS) {
+			goto error;
+		}
+		avctx = context->encoder_ctx;
+		switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
 	}
 
 	av_init_packet(pkt);
 	pkt->data = NULL;      // packet data will be allocated by the encoder
 	pkt->size = 0;
 
-	if (!context->encoder_avframe) context->encoder_avframe = av_frame_alloc();//avcodec_alloc_frame();
-
 	avframe = context->encoder_avframe;
 
-	if (!avframe) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocate frame!\n");
-		goto error;
+	if (avframe) {
+		if (avframe->width != width || avframe->height != height) {
+			av_frame_free(&avframe);
+		}
 	}
 
-	avframe->format = avctx->pix_fmt;
-	avframe->width  = avctx->width;
-	avframe->height = avctx->height;
+	if (!avframe) {
+		avframe = av_frame_alloc();
+		context->encoder_avframe = avframe;
 
-	/* the image can be allocated by any means and av_image_alloc() is
-	 * just the most convenient way if av_malloc() is to be used */
-	ret = av_image_alloc(avframe->data, avframe->linesize, avctx->width, avctx->height, avctx->pix_fmt, 32);
-	if (ret < 0) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate raw picture buffer\n");
-		goto error;
+		if (!avframe) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocate frame!\n");
+			goto error;
+		}
+
+		avframe->format = avctx->pix_fmt;
+		avframe->width  = avctx->width;
+		avframe->height = avctx->height;
+
+		ret = av_frame_get_buffer(avframe, 32);
+
+		if (ret < 0) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate raw picture buffer\n");
+			av_frame_free(&context->encoder_avframe);
+			goto error;
+		}
 	}
 
 	if (*got_output) { // Could be more delayed frames
@@ -611,7 +663,7 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
 		}
 
 		if (*got_output) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Encoded frame %lu (size=%5d) nalu_type=0x%x %d\n", context->pts, pkt->size, *((uint8_t *)pkt->data +4), *got_output);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Encoded frame %" SWITCH_INT64_T_FMT " (size=%5d) nalu_type=0x%x %d\n", context->pts, pkt->size, *((uint8_t *)pkt->data +4), *got_output);
 			goto process;
 		}
 	}
@@ -620,6 +672,12 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
 
 	avframe->pts = context->pts++;
 
+	if (context->need_key_frame) {
+		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NEED Refresh\n");
+		// av_opt_set_int(context->encoder_ctx->priv_data, "intra-refresh", 1, 0);
+		avframe->pict_type = AV_PICTURE_TYPE_I;
+	}
+
 	/* encode the image */
 	ret = avcodec_encode_video2(avctx, pkt, avframe, got_output);
 
@@ -628,13 +686,18 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
 		goto error;
 	}
 
+	if (context->need_key_frame) {
+		avframe->pict_type = 0;
+		context->need_key_frame = 0;
+	}
+
 process:
 
 	if (*got_output) {
 		const uint8_t *p = pkt->data;
 		int i = 0;
 
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Encoded frame %lu (size=%5d) nalu_type=0x%x %d\n", context->pts, pkt->size, *((uint8_t *)pkt->data +4), *got_output);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Encoded frame %" SWITCH_INT64_T_FMT " (size=%5d) nalu_type=0x%x %d\n", context->pts, pkt->size, *((uint8_t *)pkt->data +4), *got_output);
 
 		/* split into nalus */
 		memset(context->nalus, 0, sizeof(context->nalus));
@@ -659,11 +722,6 @@ process:
 		return consume_nalu(context, frame);
 	}
 
-	if (context->encoder_avframe) { //quick code to avoice internal refs
-		av_frame_free(&context->encoder_avframe);
-		context->encoder_avframe = NULL;
-	}
-
 error:
 	frame->datalen = 0;
 	return SWITCH_STATUS_FALSE;