Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c	(revision 3420)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c	(revision 3431)
@@ -19,4 +19,5 @@
 #include <pjmedia/videoport.h>
 #include <pjmedia/clock.h>
+#include <pjmedia/vid_codec.h>
 #include <pj/log.h>
 #include <pj/pool.h>
@@ -64,4 +65,6 @@
     pjmedia_frame	*enc_frm_buf,
 		        *dec_frm_buf;
+    pj_size_t            enc_frm_buf_size,
+                         dec_frm_buf_size;
 
     pj_mutex_t		*enc_frm_mutex,
@@ -183,7 +186,9 @@
 
 	if (vp->dir & PJMEDIA_DIR_ENCODING) {
-	    status = pjmedia_clock_create2(pool,
-                                           PJMEDIA_PTIME(&vfd->fps),
-					   prm->vidparam.clock_rate,
+            pjmedia_clock_param param;
+            
+            param.usec_interval = PJMEDIA_PTIME(&vfd->fps);
+            param.clock_rate = prm->vidparam.clock_rate;
+	    status = pjmedia_clock_create2(pool, &param,
 					   PJMEDIA_CLOCK_NO_HIGHEST_PRIO,
 					   &enc_clock_cb, vp, &vp->enc_clock);
@@ -193,7 +198,9 @@
 
 	if (vp->dir & PJMEDIA_DIR_DECODING) {
-	    status = pjmedia_clock_create2(pool,
-                                           PJMEDIA_PTIME(&vfd->fps),
-					   prm->vidparam.clock_rate,
+            pjmedia_clock_param param;
+            
+            param.usec_interval = PJMEDIA_PTIME(&vfd->fps);
+            param.clock_rate = prm->vidparam.clock_rate;
+	    status = pjmedia_clock_create2(pool, &param,
 					   PJMEDIA_CLOCK_NO_HIGHEST_PRIO,
 					   &dec_clock_cb, vp, &vp->dec_clock);
@@ -237,4 +244,5 @@
 	if (vp->dir & PJMEDIA_DIR_ENCODING) {
 	    vp->enc_frm_buf = PJ_POOL_ZALLOC_T(pool, pjmedia_frame);
+            vp->enc_frm_buf_size = vafp.framebytes;
 	    vp->enc_frm_buf->buf = pj_pool_alloc(pool, vafp.framebytes);
 	    vp->enc_frm_buf->size = vafp.framebytes;
@@ -249,4 +257,5 @@
 	if (vp->dir & PJMEDIA_DIR_DECODING) {
 	    vp->dec_frm_buf = PJ_POOL_ZALLOC_T(pool, pjmedia_frame);
+            vp->dec_frm_buf_size = vafp.framebytes;
 	    vp->dec_frm_buf->buf = pj_pool_alloc(pool, vafp.framebytes);
 	    vp->dec_frm_buf->size = vafp.framebytes;
@@ -463,4 +472,60 @@
 */
 
+static pj_status_t detect_fmt_change(pjmedia_vid_port *vp,
+                                     pjmedia_frame *frame)
+{
+    if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) {
+        const pjmedia_video_format_detail *vfd;
+        pjmedia_vid_event pevent;
+        pj_status_t status;
+
+        /* Retrieve the video format detail */
+        vfd = pjmedia_format_get_video_format_detail(
+                  &vp->client_port->info.fmt, PJ_TRUE);
+        if (!vfd)
+            return PJMEDIA_EVID_BADFORMAT;
+        pj_assert(vfd->fps.num);
+
+        status = pjmedia_vid_dev_stream_set_cap(
+                     vp->strm,
+                     PJMEDIA_VID_DEV_CAP_FORMAT,
+                     &vp->client_port->info.fmt);
+        if (status != PJ_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "failure in changing the format of the "
+                                  "video device"));
+            PJ_LOG(3, (THIS_FILE, "reverting to its original format: %s",
+                                  status != PJMEDIA_EVID_ERR ? "success" :
+                                  "failure"));
+            pjmedia_vid_port_stop(vp);
+            return status;
+        }
+
+        if (vp->stream_role == ROLE_PASSIVE) {
+            pjmedia_vid_param vid_param;
+            pjmedia_clock_param clock_param;
+
+            /**
+             * Initially, dec_frm_buf was allocated the biggest
+             * supported size, so we do not need to re-allocate
+             * the buffer here.
+             */
+            /* Adjust the clock */
+            pjmedia_vid_dev_stream_get_param(vp->strm, &vid_param);
+            clock_param.usec_interval = PJMEDIA_PTIME(&vfd->fps);
+            clock_param.clock_rate = vid_param.clock_rate;
+            pjmedia_clock_modify(vp->dec_clock, &clock_param);
+        }
+
+        /* Notify application of the format change. */
+        pevent.event_type = PJMEDIA_EVENT_FMT_CHANGED;
+        pj_memcpy(&pevent.event_desc.fmt_change.new_format,
+                  &vp->client_port->info.fmt, sizeof(pjmedia_format));
+        if (vp->strm_cb.on_event_cb)
+            (*vp->strm_cb.on_event_cb)(vp->strm, vp->strm_cb_data, &pevent);
+    }
+
+    return PJ_SUCCESS;
+}
+
 static void enc_clock_cb(const pj_timestamp *ts, void *user_data)
 {
@@ -478,4 +543,5 @@
 	return;
 
+    vp->enc_frm_buf->size = vp->enc_frm_buf_size;
     status = pjmedia_vid_dev_stream_get_frame(vp->strm, vp->enc_frm_buf);
     if (status != PJ_SUCCESS)
@@ -583,4 +649,5 @@
 
                 for (i = 0; i < ndrop; i++) {
+                    vp->dec_frm_buf->size = vp->dec_frm_buf_size;
                     status = pjmedia_port_get_frame(vp->client_port,
                                                     vp->dec_frm_buf);
@@ -589,4 +656,9 @@
                         return;
                     }
+
+                    status = detect_fmt_change(vp, vp->dec_frm_buf);
+                    if (status != PJ_SUCCESS)
+                        return;
+
                     pj_add_timestamp32(&vp->rend_clocksrc.timestamp,
                                        frame_ts);
@@ -596,4 +668,5 @@
     }
 
+    vp->dec_frm_buf->size = vp->dec_frm_buf_size;
     status = pjmedia_port_get_frame(vp->client_port, vp->dec_frm_buf);
     if (status != PJ_SUCCESS) {
@@ -604,4 +677,8 @@
     pjmedia_clock_src_update(&vp->rend_clocksrc, NULL);
 
+    status = detect_fmt_change(vp, vp->dec_frm_buf);
+    if (status != PJ_SUCCESS)
+        return;
+
     status = pjmedia_vid_dev_stream_put_frame(vp->strm, vp->dec_frm_buf);
 }
@@ -623,5 +700,5 @@
 
     if (vp->role==ROLE_ACTIVE) {
-	if (vp->client_port)
+        if (vp->client_port)
 	    return pjmedia_port_put_frame(vp->client_port, frame);
     } else {
@@ -642,6 +719,13 @@
 
     if (vp->role==ROLE_ACTIVE) {
-	if (vp->client_port)
-	    return pjmedia_port_get_frame(vp->client_port, frame);
+        if (vp->client_port) {
+            pj_status_t status;
+
+	    status = pjmedia_port_get_frame(vp->client_port, frame);
+            if (status != PJ_SUCCESS)
+                return status;
+
+            return detect_fmt_change(vp, frame);
+        }
     } else {
 	pj_mutex_lock(vp->dec_frm_mutex);
