Index: pjproject/trunk/pjmedia/include/pjmedia-codec/config.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/config.h	(revision 3808)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec/config.h	(revision 3819)
@@ -355,4 +355,22 @@
 
 /**
+ * Enable FFMPEG H263+/H263-1998 codec.
+ *
+ * Default: 1
+ */
+#ifndef PJMEDIA_HAS_FFMPEG_CODEC_H263P
+#   define PJMEDIA_HAS_FFMPEG_CODEC_H263P	1
+#endif
+
+/**
+ * Enable FFMPEG H264 codec (requires libx264).
+ *
+ * Default: 0
+ */
+#ifndef PJMEDIA_HAS_FFMPEG_CODEC_H264
+#   define PJMEDIA_HAS_FFMPEG_CODEC_H264	0
+#endif
+
+/**
  * @}
  */
Index: pjproject/trunk/pjmedia/include/pjmedia/format.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/format.h	(revision 3808)
+++ pjproject/trunk/pjmedia/include/pjmedia/format.h	(revision 3819)
@@ -110,4 +110,12 @@
      */
     PJMEDIA_FORMAT_DIB      = PJMEDIA_FORMAT_PACK('D', 'I', 'B', ' '),
+
+    /**
+     * This is planar 4:4:4/24bpp RGB format, the data can be treated as
+     * three planes of color components, where the first plane contains
+     * only the G samples, the second plane contains only the B samples,
+     * and the third plane contains only the R samples.
+     */
+    PJMEDIA_FORMAT_GBRP    = PJMEDIA_FORMAT_PACK('G', 'B', 'R', 'P'),
 
     /**
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c	(revision 3808)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c	(revision 3819)
@@ -43,6 +43,6 @@
 #include <libavcodec/avcodec.h>
 #include <libavformat/avformat.h>
-
-#define ENABLE_H264	0
+#include <libavutil/opt.h>
+
 
 /* Prototypes for FFMPEG codecs factory */
@@ -220,5 +220,9 @@
 
 
-#if ENABLE_H264
+#if PJMEDIA_HAS_FFMPEG_CODEC_H264 && \
+    (LIBAVCODEC_VERSION_MAJOR < 53 || LIBAVCODEC_VERSION_MINOR < 20)
+#   error "Must use libavcodec version 53.20 or later to enable FFMPEG H264"
+#endif
+
 /* H264 constants */
 #define PROFILE_H264_BASELINE		66
@@ -230,5 +234,4 @@
 static FUNC_PACKETIZE(h264_packetize);
 static FUNC_UNPACKETIZE(h264_unpacketize);
-#endif	/* ENABLE_H264 */
 
 static pj_status_t h263_preopen(ffmpeg_private *ff);
@@ -240,5 +243,5 @@
 static ffmpeg_codec_desc codec_desc[] =
 {
-#if ENABLE_H264
+#if PJMEDIA_HAS_FFMPEG_CODEC_H264
     {
 	{PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264, {"H264",4},
@@ -251,14 +254,7 @@
 	      {{" packetization-mode",19},  {"1",1}}, } },
     },
-    {
-	{PJMEDIA_FORMAT_H264, PJMEDIA_RTP_PT_H264_RSV1, {"H264",4},
-	 {"Baseline (level=30, pack=1)", 27}},
-	PJMEDIA_FORMAT_H264,	128000,    1000000,
-	&h264_packetize, &h264_unpacketize, &h264_preopen, &h264_postopen,
-	&pjmedia_vid_codec_h264_match_sdp,
-	{2, { {{"profile-level-id",16},    {"42001e",6}}, 
-	      {{" packetization-mode",19},  {"1",1}}, } },
-    },
 #endif
+
+#if PJMEDIA_HAS_FFMPEG_CODEC_H263P
     {
 	{PJMEDIA_FORMAT_H263P, PJMEDIA_RTP_PT_H263P, {"H263-1998",9}},
@@ -268,18 +264,9 @@
 	      {{"QCIF",4},  {"1",1}}, } },
     },
-#if 0
-    /* Force plain H263 to use H263-1998 RTP packetization */
-    {
-	{PJMEDIA_FORMAT_H263, PJMEDIA_RTP_PT_H263, {"H263",4}},
-	PJMEDIA_FORMAT_H263,	1000000,    2000000,
-	&h263_packetize, &h263_unpacketize, &h263_preopen, NULL, NULL,
-	{2, { {{"CIF",3},   {"1",1}}, 
-	      {{"QCIF",4},  {"1",1}}, } },
-    },
-#else
+#endif
+
     {
 	{PJMEDIA_FORMAT_H263,	PJMEDIA_RTP_PT_H263,	{"H263",4}},
     },
-#endif
     {
 	{PJMEDIA_FORMAT_H261,	PJMEDIA_RTP_PT_H261,	{"H261",4}},
@@ -297,5 +284,6 @@
 };
 
-#if ENABLE_H264
+#if PJMEDIA_HAS_FFMPEG_CODEC_H264
+
 typedef struct h264_data
 {
@@ -354,24 +342,25 @@
     if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
 	AVCodecContext *ctx = ff->enc_ctx;
-
-	/* Apply profile. Note that, for x264 backend, ffmpeg doesn't seem to
-	 * use this profile param field, so let's try to apply it "manually".
-	 */
+	const char *profile = NULL;
+
+	/* Apply profile. */
 	ctx->profile  = data->fmtp.profile_idc;
-	if (ctx->profile == PROFILE_H264_BASELINE) {
-	    /* Baseline profile settings (the most used profile in
-	     * conversational/real-time communications).
-	     */
-	    ctx->coder_type = FF_CODER_TYPE_VLC;
-	    ctx->max_b_frames = 0;
-	    ctx->flags2 &= ~(CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT);
-	    ctx->weighted_p_pred = 0;
-	} else if (ctx->profile == PROFILE_H264_MAIN) {
-	    ctx->flags2 &= ~CODEC_FLAG2_8X8DCT;
+	switch (ctx->profile) {
+	case PROFILE_H264_BASELINE:
+	    profile = "baseline";
+	    break;
+	case PROFILE_H264_MAIN:
+	    profile = "main";
+	    break;
+	default:
+	    break;
+	}
+	if (profile &&
+	    av_set_string3(ctx->priv_data, "profile", profile, 0, NULL))
+	{
+	    PJ_LOG(3, (THIS_FILE, "Failed to set H264 profile"));
 	}
 
 	/* Apply profile constraint bits. */
-	// The x264 doesn't seem to support non-constrained (baseline) profile
-	// so this shouldn't be a problem (for now).
 	//PJ_TODO(set_h264_constraint_bits_properly_in_ffmpeg);
 	if (data->fmtp.profile_iop) {
@@ -384,12 +373,29 @@
 	ctx->level    = data->fmtp.level;
 
-	/* Libx264 rejects the "broken" ffmpeg defaults, so just change some */
-	ctx->me_range = 16;
-	ctx->max_qdiff = 4;
-	ctx->qmin = 20;
-	ctx->qmax = 32;
-	ctx->qcompress = 0.6f;
-
-	ctx->rtp_payload_size = ff->param.enc_mtu;
+	/* Limit NAL unit size as we prefer single NAL unit packetization */
+	if (!av_set_int(ctx->priv_data, "slice-max-size", ff->param.enc_mtu))
+	{
+	    PJ_LOG(3, (THIS_FILE, "Failed to set H264 max NAL size to %d",
+		       ff->param.enc_mtu));
+	}
+
+	/* Apply intra-refresh */
+	if (!av_set_int(ctx->priv_data, "intra-refresh", 1))
+	{
+	    PJ_LOG(3, (THIS_FILE, "Failed to set x264 intra-refresh"));
+	}
+
+	/* Misc x264 settings (performance, quality, latency, etc).
+	 * Let's just use the x264 predefined preset & tune.
+	 */
+	if (av_set_string3(ctx->priv_data, "preset", "veryslow", 0, NULL))
+	{
+	    PJ_LOG(3, (THIS_FILE, "Failed to set x264 preset 'veryfast'"));
+	}
+	if (av_set_string3(ctx->priv_data, "tune", "animation+zerolatency",
+			   0, NULL))
+	{
+	    PJ_LOG(3, (THIS_FILE, "Failed to set x264 tune 'zerolatency'"));
+	}
     }
 
@@ -416,5 +422,4 @@
 }
 
-
 static FUNC_PACKETIZE(h264_packetize)
 {
@@ -430,5 +435,9 @@
 				    bits, bits_len, bits_pos);
 }
-#endif	/* ENABLE_H264 */
+
+#endif /* PJMEDIA_HAS_FFMPEG_CODEC_H264 */
+
+
+#if PJMEDIA_HAS_FFMPEG_CODEC_H263P
 
 typedef struct h263_data
@@ -475,4 +484,6 @@
 				    bits, bits_len, bits_pos);
 }
+
+#endif /* PJMEDIA_HAS_FFMPEG_CODEC_H263P */
 
 
@@ -990,21 +1001,4 @@
 }
 
-static enum PixelFormat dec_get_format(struct AVCodecContext *s, 
-                                       const enum PixelFormat * fmt)
-{
-    ffmpeg_private *ff = (ffmpeg_private*)s->opaque;
-    enum PixelFormat def_fmt = *fmt;
-
-    while (*fmt != -1) {
-	if (*fmt == ff->expected_dec_fmt)
-	    return *fmt;
-	++fmt;
-    }
-
-    pj_assert(!"Inconsistency in supported formats");
-    return def_fmt;
-}
-
-
 static pj_status_t open_ffmpeg_codec(ffmpeg_private *ff,
                                      pj_mutex_t *ff_mutex)
@@ -1028,26 +1022,18 @@
     /* Allocate ffmpeg codec context */
     if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
-	ff->enc_ctx = avcodec_alloc_context();
+	ff->enc_ctx = avcodec_alloc_context3(ff->enc);
 	if (ff->enc_ctx == NULL)
 	    goto on_error;
     }
     if (ff->param.dir & PJMEDIA_DIR_DECODING) {
-	ff->dec_ctx = avcodec_alloc_context();
+	ff->dec_ctx = avcodec_alloc_context3(ff->dec);
 	if (ff->dec_ctx == NULL)
 	    goto on_error;
     }
 
-    /* Let the codec apply specific settings before the codec opened */
-    if (ff->desc->preopen) {
-	status = (*ff->desc->preopen)(ff);
-	if (status != PJ_SUCCESS)
-	    goto on_error;
-    }
-
+    /* Init generic encoder params */
     if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
         AVCodecContext *ctx = ff->enc_ctx;
-        int err;
-
-	/* Init common settings */
+
         ctx->pix_fmt = pix_fmt;
 	ctx->width = vfd->size.w;
@@ -1071,8 +1057,33 @@
 	ctx->rc_lookahead = 0;
 #endif
-
-	/* Open ffmpeg codec */
-        pj_mutex_lock(ff_mutex);
-        err = avcodec_open(ctx, ff->enc);
+    }
+
+    /* Init generic decoder params */
+    if (ff->param.dir & PJMEDIA_DIR_DECODING) {
+	AVCodecContext *ctx = ff->dec_ctx;
+
+	/* Width/height may be overriden by ffmpeg after first decoding. */
+	ctx->width  = ctx->coded_width  = ff->param.dec_fmt.det.vid.size.w;
+	ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h;
+	ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+        ctx->workaround_bugs = FF_BUG_AUTODETECT;
+        ctx->opaque = ff;
+    }
+
+    /* Init codec override generic params or apply specific params before
+     * the codec opened.
+     */
+    if (ff->desc->preopen) {
+	status = (*ff->desc->preopen)(ff);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+    }
+
+    /* Open encoder */
+    if (ff->param.dir & PJMEDIA_DIR_ENCODING) {
+	int err;
+
+	pj_mutex_lock(ff_mutex);
+	err = avcodec_open(ff->enc_ctx, ff->enc);
         pj_mutex_unlock(ff_mutex);
         if (err < 0) {
@@ -1084,20 +1095,10 @@
     }
 
+    /* Open decoder */
     if (ff->param.dir & PJMEDIA_DIR_DECODING) {
-	AVCodecContext *ctx = ff->dec_ctx;
 	int err;
 
-	/* Init common settings */
-	/* Width/height may be overriden by ffmpeg after first decoding. */
-	ctx->width  = ctx->coded_width  = ff->param.dec_fmt.det.vid.size.w;
-	ctx->height = ctx->coded_height = ff->param.dec_fmt.det.vid.size.h;
-	ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
-        ctx->workaround_bugs = FF_BUG_AUTODETECT;
-        ctx->opaque = ff;
-	ctx->get_format = &dec_get_format;
-
-	/* Open ffmpeg codec */
-        pj_mutex_lock(ff_mutex);
-        err = avcodec_open(ctx, ff->dec);
+	pj_mutex_lock(ff_mutex);
+	err = avcodec_open(ff->dec_ctx, ff->dec);
         pj_mutex_unlock(ff_mutex);
         if (err < 0) {
@@ -1109,5 +1110,5 @@
     }
 
-    /* Let the codec apply specific settings after the codec opened */
+    /* Let the codec apply specific params after the codec opened */
     if (ff->desc->postopen) {
 	status = (*ff->desc->postopen)(ff);
@@ -1528,4 +1529,5 @@
 	    ff->param.dec_fmt.det.vid.size.w = ff->dec_ctx->width;
 	    ff->param.dec_fmt.det.vid.size.h = ff->dec_ctx->height;
+	    ff->expected_dec_fmt = ff->dec_ctx->pix_fmt;
 
 	    /* Re-init format info and apply-param of decoder */
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/h264_packetizer.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/h264_packetizer.c	(revision 3808)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/h264_packetizer.c	(revision 3819)
@@ -320,6 +320,4 @@
 
     /* Single NAL unit packet */
-    pj_assert(nal_octet);
-
     *payload = nal_start;
     *payload_len = nal_end - nal_start;
Index: pjproject/trunk/pjmedia/src/pjmedia/ffmpeg_util.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/ffmpeg_util.c	(revision 3808)
+++ pjproject/trunk/pjmedia/src/pjmedia/ffmpeg_util.c	(revision 3819)
@@ -33,6 +33,7 @@
 {
     { PJMEDIA_FORMAT_RGBA, PIX_FMT_RGBA},
-    { PJMEDIA_FORMAT_RGB24,PIX_FMT_RGB24},
+    { PJMEDIA_FORMAT_RGB24,PIX_FMT_BGR24},
     { PJMEDIA_FORMAT_BGRA, PIX_FMT_BGRA},
+    { PJMEDIA_FORMAT_GBRP, PIX_FMT_GBR24P},
 
     { PJMEDIA_FORMAT_AYUV, PIX_FMT_NONE},
Index: pjproject/trunk/pjmedia/src/pjmedia/format.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/format.c	(revision 3808)
+++ pjproject/trunk/pjmedia/src/pjmedia/format.c	(revision 3819)
@@ -79,4 +79,7 @@
 	                            pjmedia_video_apply_fmt_param *aparam);
 
+static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi,
+	                            pjmedia_video_apply_fmt_param *aparam);
+
 struct pjmedia_video_format_mgr
 {
@@ -93,4 +96,5 @@
     {PJMEDIA_FORMAT_BGRA,  "BGRA", PJMEDIA_COLOR_MODEL_RGB, 32, 1, &apply_packed_fmt},
     {PJMEDIA_FORMAT_DIB ,  "DIB ", PJMEDIA_COLOR_MODEL_RGB, 24, 1, &apply_packed_fmt},
+    {PJMEDIA_FORMAT_GBRP,  "GBRP", PJMEDIA_COLOR_MODEL_RGB, 24, 3, &apply_planar_444},
     {PJMEDIA_FORMAT_AYUV,  "AYUV", PJMEDIA_COLOR_MODEL_YUV, 32, 1, &apply_packed_fmt},
     {PJMEDIA_FORMAT_YUY2,  "YUY2", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt},
@@ -241,4 +245,37 @@
 }
 
+static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi,
+	                            pjmedia_video_apply_fmt_param *aparam)
+{
+    unsigned i;
+    pj_size_t Y_bytes;
+
+    PJ_UNUSED_ARG(fi);
+
+    /* Calculate memsize */
+    Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h);
+    aparam->framebytes = (Y_bytes * 3);
+
+    /* Planar formats use 3 plane */
+    aparam->strides[0] = aparam->strides[1] = 
+			 aparam->strides[2] = aparam->size.w;
+
+    aparam->planes[0] = aparam->buffer;
+    aparam->planes[1] = aparam->planes[0] + Y_bytes;
+    aparam->planes[2] = aparam->planes[1] + Y_bytes;
+
+    aparam->plane_bytes[0] = aparam->plane_bytes[1] =
+			     aparam->plane_bytes[2] = Y_bytes;
+
+    /* Zero unused planes */
+    for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) {
+	aparam->strides[i] = 0;
+	aparam->planes[i] = NULL;
+        aparam->plane_bytes[i] = 0;
+    }
+
+    return PJ_SUCCESS;
+}
+
 PJ_DEF(pj_status_t)
 pjmedia_video_format_mgr_create(pj_pool_t *pool,
Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3808)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3819)
@@ -3195,8 +3195,24 @@
 {
     char event_name[5];
-    PJ_UNUSED_ARG(call_id);
-    PJ_UNUSED_ARG(med_idx);
-    PJ_LOG(4,(THIS_FILE, "Event %s",
+
+    PJ_LOG(5,(THIS_FILE, "Event %s",
 	      pjmedia_fourcc_name(event->type, event_name)));
+
+    if (event->type == PJMEDIA_EVENT_FMT_CHANGED) {
+	/* Adjust renderer window size to original video size */
+	pjsua_call_info ci;
+	pjsua_vid_win_id wid;
+	pjmedia_rect_size size;
+
+	pjsua_call_get_info(call_id, &ci);
+
+	if ((ci.media[med_idx].type == PJMEDIA_TYPE_VIDEO) &&
+	    (ci.media[med_idx].dir & PJMEDIA_DIR_DECODING))
+	{
+	    wid = ci.media[med_idx].stream.vid.win_in;
+	    size = event->data.fmt_changed.new_fmt.det.vid.size;
+	    pjsua_vid_win_set_size(wid, &size);
+	}
+    }
 }
 
