Index: pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/event.h
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/event.h	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/event.h	(revision 3622)
@@ -103,7 +103,8 @@
 typedef struct pjmedia_event_fmt_changed_data
 {
-    /**
-     * The new media format.
-     */
+    /** The media flow direction */
+    pjmedia_dir		dir;
+
+    /** The new media format. */
     pjmedia_format	new_fmt;
 } pjmedia_event_fmt_changed_data;
@@ -337,4 +338,14 @@
 PJ_DECL(pj_status_t) pjmedia_event_unsubscribe(pjmedia_event_publisher *epub,
                                                pjmedia_event_subscription *esub);
+
+/**
+ * Check if the specified publisher has subscribers.
+ *
+ * @param epub		The event publisher.
+ *
+ * @return		PJ_TRUE if the publisher has at least one subscriber.
+ */
+PJ_DECL(pj_bool_t)
+pjmedia_event_publisher_has_sub(pjmedia_event_publisher *epub);
 
 /**
Index: pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/port.h
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/port.h	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/port.h	(revision 3622)
@@ -26,4 +26,5 @@
  */
 #include <pjmedia/clock.h>
+#include <pjmedia/event.h>
 #include <pjmedia/format.h>
 #include <pjmedia/frame.h>
@@ -399,4 +400,9 @@
     pj_status_t (*on_destroy)(struct pjmedia_port *this_port);
 
+    /**
+     * Get event publisher for this media port, if any.
+     */
+    pjmedia_event_publisher *(*get_event_pub)(struct pjmedia_port *this_port);
+
 } pjmedia_port;
 
@@ -478,4 +484,14 @@
 					     pjmedia_frame *frame );
 
+/**
+ * Get the event publisher for the media port, if any.
+ *
+ * @param port	    The media port.
+ *
+ * @return	    The event publisher, or NULL if the port does not publish
+ * 		    events.
+ */
+PJ_DECL(pjmedia_event_publisher*)
+pjmedia_port_get_event_publisher(pjmedia_port *port);
 
 /**
Index: pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/vid_codec.h
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/vid_codec.h	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/vid_codec.h	(revision 3622)
@@ -28,4 +28,5 @@
 
 #include <pjmedia/codec.h>
+#include <pjmedia/event.h>
 #include <pjmedia/format.h>
 #include <pjmedia/types.h>
@@ -99,21 +100,4 @@
 
 /**
- * Enumeration of video codec events.
- */
-typedef enum pjmedia_vid_codec_event
-{
-    /**
-     * Format changed event. The decoder output format is not really
-     * configurable, so that the output format setting configured in the
-     * initialization may be changed. Application can catch this event
-     * by checking the bit_info field of the pjmedia_frame of the decoder
-     * output frame.
-     */
-    PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED = 1,
-
-} pjmedia_vid_codec_event;
-
-
-/**
  * Forward declaration for video codec.
  */
@@ -269,6 +253,6 @@
      * format may different to the current setting, e.g: the format specified
      * in the #pjmedia_vid_codec_param when opening the codec, in this case the
-     * PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED flag will be set in the bit_info
-     * field of the output frame and application can query the new format
+     * PJMEDIA_EVENT_FMT_CHANGED event will be emitted by the codec. The codec
+     * parameter will also be updated, and application can query the format by
      * using #get_param().
      *
@@ -310,5 +294,7 @@
 
 /**
- * This structure describes a video codec instance. 
+ * This structure describes a video codec instance. Codec implementers
+ * should use #pjmedia_vid_codec_init() to initialize this structure with
+ * default values.
  */
 struct pjmedia_vid_codec
@@ -325,4 +311,7 @@
     /** Operations to codec. */
     pjmedia_vid_codec_op	*op;
+
+    /** Event publisher object */
+    pjmedia_event_publisher	 epub;
 };
 
@@ -438,4 +427,10 @@
 
 
+/**
+ * Initialize pjmedia_vid_codec structure with default values.
+ *
+ * @param codec	    The codec to be initialized.
+ */
+PJ_DECL(void) pjmedia_vid_codec_init(pjmedia_vid_codec *codec);
 
 /**
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c	(revision 3622)
@@ -879,9 +879,10 @@
     /* Create pool for codec instance */
     pool = pj_pool_create(ffmpeg_factory.pf, "ffmpeg codec", 512, 512, NULL);
-    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec);
+    codec = PJ_POOL_ALLOC_T(pool, pjmedia_vid_codec);
     if (!codec) {
         status = PJ_ENOMEM;
         goto on_error;
     }
+    pjmedia_vid_codec_init(codec);
     codec->op = &ffmpeg_op;
     codec->factory = factory;
@@ -1404,6 +1405,15 @@
 		return status;
 
-	    /* Notify application via the bit_info field of pjmedia_frame */
-	    output->bit_info = PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED;
+	    /* Broadcast event */
+	    if (pjmedia_event_publisher_has_sub(&codec->epub)) {
+		pjmedia_event event;
+
+		pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED,
+				   &input->timestamp, &codec->epub);
+		event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING;
+		pj_memcpy(&event.data.fmt_changed.new_fmt, &ff->param.dec_fmt,
+			  sizeof(ff->param.dec_fmt));
+		pjmedia_event_publish(&codec->epub, &event);
+	    }
 	}
 
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/event.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/event.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/event.c	(revision 3622)
@@ -58,4 +58,12 @@
 }
 
+PJ_DEF(pj_bool_t)
+pjmedia_event_publisher_has_sub(pjmedia_event_publisher *epub)
+{
+    PJ_ASSERT_RETURN(epub, PJ_FALSE);
+    return epub->subscription_list.next &&
+	    (!pj_list_empty(&epub->subscription_list));
+}
+
 PJ_DEF(pj_status_t) pjmedia_event_subscribe( pjmedia_event_publisher *epub,
                                              pjmedia_event_subscription *esub)
@@ -88,4 +96,7 @@
 
     esub = epub->subscription_list.next;
+    if (!esub)
+	return err;
+
     while (esub != &epub->subscription_list) {
 	pjmedia_event_subscription *next;
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/port.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/port.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/port.c	(revision 3622)
@@ -118,4 +118,17 @@
 }
 
+/*
+ * Get event publisher
+ */
+PJ_DEF(pjmedia_event_publisher*)
+pjmedia_port_get_event_publisher(pjmedia_port *port)
+{
+    PJ_ASSERT_RETURN(port, NULL);
+
+    if (port->get_event_pub)
+	return (*port->get_event_pub)(port);
+
+    return NULL;
+}
 
 /**
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_codec.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_codec.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_codec.c	(revision 3622)
@@ -67,4 +67,12 @@
 static void sort_codecs(pjmedia_vid_codec_mgr *mgr);
 
+/*
+ * Initialize pjmedia_vid_codec structure with default values.
+ */
+PJ_DEF(void) pjmedia_vid_codec_init(pjmedia_vid_codec *codec)
+{
+    pj_bzero(codec, sizeof(*codec));
+    pj_list_init(&codec->epub);
+}
 
 /*
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_port.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_port.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_port.c	(revision 3622)
@@ -57,6 +57,7 @@
     pjmedia_conversion_param conv_param;
 
-    pjmedia_event_publisher  epub;
+    pjmedia_event_publisher    epub;
     pjmedia_event_subscription esub_dev;
+    pjmedia_event_subscription esub_client_port;
 
     pjmedia_clock           *clock;
@@ -91,4 +92,6 @@
 static pj_status_t vidstream_event_cb(pjmedia_event_subscription *esub,
 			              pjmedia_event *event);
+static pj_status_t client_port_event_cb(pjmedia_event_subscription *esub,
+                                        pjmedia_event *event);
 
 static void enc_clock_cb(const pj_timestamp *ts, void *user_data);
@@ -398,7 +401,18 @@
 					      pj_bool_t destroy)
 {
+    pjmedia_event_publisher *epub;
+
     PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL);
     vp->destroy_client_port = destroy;
     vp->client_port = port;
+
+    /* Subscribe to client port's events */
+    epub = pjmedia_port_get_event_publisher(port);
+    if (epub) {
+	pjmedia_event_subscription_init(&vp->esub_client_port,
+	                                &client_port_event_cb,
+	                                vp);
+	pjmedia_event_subscribe(epub, &vp->esub_client_port);
+    }
     return PJ_SUCCESS;
 }
@@ -408,5 +422,16 @@
 {
     PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL);
-    vp->client_port = NULL;
+
+    if (vp->client_port) {
+	pjmedia_event_publisher *epub;
+
+	/* Unsubscribe event */
+	epub = pjmedia_port_get_event_publisher(vp->client_port);
+	if (epub && vp->esub_client_port.user_data) {
+	    pjmedia_event_unsubscribe(epub, &vp->esub_client_port);
+	    pj_bzero(&vp->esub_client_port, sizeof(vp->esub_client_port));
+	}
+	vp->client_port = NULL;
+    }
     return PJ_SUCCESS;
 }
@@ -513,4 +538,5 @@
 */
 
+/* Handle event from vidstream */
 static pj_status_t vidstream_event_cb(pjmedia_event_subscription *esub,
 				      pjmedia_event *event)
@@ -538,11 +564,14 @@
 }
 
-static pj_status_t detect_fmt_change(pjmedia_vid_port *vp,
-                                     pjmedia_frame *frame)
-{
-    if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) {
+static pj_status_t client_port_event_cb(pjmedia_event_subscription *esub,
+                                        pjmedia_event *event)
+{
+    pjmedia_vid_port *vp = (pjmedia_vid_port*)esub->user_data;
+
+    if (event->type == PJMEDIA_EVENT_FMT_CHANGED) {
         const pjmedia_video_format_detail *vfd;
-        pjmedia_event pevent;
         pj_status_t status;
+
+        ++event->proc_cnt;
 
 	pjmedia_vid_port_stop(vp);
@@ -605,14 +634,9 @@
         }
 
-        /* Notify application of the format change. */
-        pjmedia_event_init(&pevent, PJMEDIA_EVENT_FMT_CHANGED, NULL, &vp->epub);
-	pjmedia_format_copy(&pevent.data.fmt_changed.new_fmt,
-			    &vp->client_port->info.fmt);
-	pjmedia_event_publish(&vp->epub, &pevent);
-
 	pjmedia_vid_port_start(vp);
     }
 
-    return PJ_SUCCESS;
+    /* Republish the event */
+    return pjmedia_event_publish(&vp->epub, event);
 }
 
@@ -752,8 +776,4 @@
                     }
 
-                    status = detect_fmt_change(vp, vp->frm_buf);
-                    if (status != PJ_SUCCESS)
-                        return;
-
                     pj_add_timestamp32(&vp->clocksrc.timestamp,
                                        frame_ts);
@@ -771,8 +791,4 @@
     pj_add_timestamp32(&vp->clocksrc.timestamp, frame_ts);
     pjmedia_clock_src_update(&vp->clocksrc, NULL);
-
-    status = detect_fmt_change(vp, vp->frm_buf);
-    if (status != PJ_SUCCESS)
-        return;
 
     if (convert_frame(vp, vp->frm_buf, &frame) != PJ_SUCCESS)
@@ -821,11 +837,5 @@
     if (vp->role==ROLE_ACTIVE) {
         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);
+	    return pjmedia_port_get_frame(vp->client_port, frame);
         }
     } else {
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_stream.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_stream.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_stream.c	(revision 3622)
@@ -19,4 +19,5 @@
 #include <pjmedia/vid_stream.h>
 #include <pjmedia/errno.h>
+#include <pjmedia/event.h>
 #include <pjmedia/rtp.h>
 #include <pjmedia/rtcp.h>
@@ -135,4 +136,7 @@
     pj_uint32_t		     last_dec_ts;    /**< Last decoded timestamp.   */
     int			     last_dec_seq;   /**< Last decoded sequence.    */
+
+    pjmedia_event_subscription esub_codec;   /**< To subscribe codec events */
+    pjmedia_event_publisher    epub;	     /**< To publish events	    */
 };
 
@@ -301,4 +305,62 @@
 #endif /* TRACE_JB */
 
+static void dump_port_info(const pjmedia_vid_channel *chan,
+                           const char *event_name)
+{
+    const pjmedia_port_info *pi = &chan->port.info;
+
+    PJ_LOG(5, (pi->name.ptr,
+	       " %s format %s: %dx%d %c%c%c%c%s %d/%d(~%d)fps",
+	       (chan->dir==PJMEDIA_DIR_DECODING? "Decoding":"Encoding"),
+	       event_name,
+	       pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
+	       ((pi->fmt.id & 0x000000FF) >> 0),
+	       ((pi->fmt.id & 0x0000FF00) >> 8),
+	       ((pi->fmt.id & 0x00FF0000) >> 16),
+	       ((pi->fmt.id & 0xFF000000) >> 24),
+	       (chan->dir==PJMEDIA_DIR_ENCODING?"->":"<-"),
+	       pi->fmt.det.vid.fps.num, pi->fmt.det.vid.fps.denum,
+	       pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum));
+}
+
+/*
+ * Handle events from stream components.
+ */
+static pj_status_t stream_event_cb(pjmedia_event_subscription *esub,
+                                   pjmedia_event *event)
+{
+    pjmedia_vid_stream *stream = (pjmedia_vid_stream*)esub->user_data;
+
+    if (esub == &stream->esub_codec) {
+	/* This is codec event */
+	switch (event->type) {
+	case PJMEDIA_EVENT_FMT_CHANGED:
+	    /* Update param from codec */
+	    stream->codec->op->get_param(stream->codec, stream->info.codec_param);
+
+	    /* Update decoding channel port info */
+	    pjmedia_format_copy(&stream->dec->port.info.fmt,
+				&stream->info.codec_param->dec_fmt);
+
+	    /* we process the event */
+	    ++event->proc_cnt;
+
+	    dump_port_info(event->data.fmt_changed.dir==PJMEDIA_DIR_DECODING ?
+			    stream->dec : stream->enc,
+			  "changed");
+	    break;
+	default:
+	    break;
+	}
+    }
+
+    return pjmedia_event_publish(&stream->epub, event);
+}
+
+static pjmedia_event_publisher *port_get_epub(pjmedia_port *port)
+{
+    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata;
+    return &stream->epub;
+}
 
 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
@@ -795,5 +857,4 @@
     return PJ_SUCCESS;
 }
-
 
 static pj_status_t get_frame(pjmedia_port *port,
@@ -915,14 +976,4 @@
     }
 
-    /* Check if the decoder format is changed */
-    if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) {
-	/* Update param from codec */
-	stream->codec->op->get_param(stream->codec, stream->info.codec_param);
-
-	/* Update decoding channel port info */
-	pjmedia_format_copy(&channel->port.info.fmt,
-			    &stream->info.codec_param->dec_fmt);
-    }
-
     /* Learn remote frame rate after successful decoding */
     if (0 && frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size)
@@ -950,9 +1001,23 @@
 		stream->info.codec_param->dec_fmt.det.vid.fps = vfd->fps;
 
-		/* Set bit_info */
-		frame->bit_info |= PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED;
-
-		PJ_LOG(5, (channel->port.info.name.ptr, "Frame rate changed to %.2ffps",
-			   (1.0 * vfd->fps.num / vfd->fps.denum)));
+		PJ_LOG(5, (channel->port.info.name.ptr,
+			   "Frame rate changed to %d/%d(~%d)fps",
+			   vfd->fps.num, vfd->fps.denum,
+			   vfd->fps.num / vfd->fps.denum));
+
+		/* Publish PJMEDIA_EVENT_FMT_CHANGED event */
+		if (pjmedia_event_publisher_has_sub(&stream->epub)) {
+		    pjmedia_event event;
+
+		    dump_port_info(stream->dec, "changed");
+
+		    pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED,
+		                       &frame_in.timestamp, &stream->epub);
+		    event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING;
+		    pj_memcpy(&event.data.fmt_changed.new_fmt,
+		              &stream->info.codec_param->dec_fmt,
+		              sizeof(pjmedia_format));
+		    pjmedia_event_publish(&stream->epub, &event);
+		}
 	    }
 	}
@@ -962,19 +1027,4 @@
 	stream->last_dec_ts = last_ts;
     }
-
-#if PJ_LOG_MAX_LEVEL >= 5
-    if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) {
-	pjmedia_port_info *pi = &channel->port.info;
-
-	PJ_LOG(5, (channel->port.info.name.ptr,
-		   "Decoding format changed to %dx%d %c%c%c%c %.2ffps",
-		   pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
-		   ((pi->fmt.id & 0x000000FF) >> 0),
-		   ((pi->fmt.id & 0x0000FF00) >> 8),
-		   ((pi->fmt.id & 0x00FF0000) >> 16),
-		   ((pi->fmt.id & 0xFF000000) >> 24),
-		   (1.0*pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum)));
-    }
-#endif
 
     return PJ_SUCCESS;
@@ -1070,6 +1120,8 @@
     /* Init port. */
     channel->port.port_data.pdata = stream;
-
-    PJ_LOG(5, (name.ptr, "%s channel created %dx%d %c%c%c%c%s%.*s %.2ffps",
+    channel->port.get_event_pub = &port_get_epub;
+
+    PJ_LOG(5, (name.ptr,
+	       "%s channel created %dx%d %c%c%c%c%s%.*s %d/%d(~%d)fps",
 	       (dir==PJMEDIA_DIR_ENCODING?"Encoding":"Decoding"),
 	       pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
@@ -1081,5 +1133,6 @@
 	       info->codec_info.encoding_name.slen,
 	       info->codec_info.encoding_name.ptr,
-	       (1.0*pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum)));
+	       pi->fmt.det.vid.fps.num, pi->fmt.det.vid.fps.denum,
+	       pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum));
 
     /* Done. */
@@ -1198,4 +1251,10 @@
     if (status != PJ_SUCCESS)
 	return status;
+
+    /* Init event publisher and subscribe to codec events */
+    pjmedia_event_publisher_init(&stream->epub);
+    pjmedia_event_subscription_init(&stream->esub_codec, &stream_event_cb,
+                                    stream);
+    pjmedia_event_subscribe(&stream->codec->epub, &stream->esub_codec);
 
     /* Estimate the maximum frame size */
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_codec_test.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_codec_test.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_codec_test.c	(revision 3622)
@@ -29,4 +29,31 @@
 } codec_port_data_t;
 
+static pj_status_t codec_on_event(pjmedia_event_subscription *esub,
+                                  pjmedia_event *event)
+{
+    codec_port_data_t *port_data = (codec_port_data_t*)esub->user_data;
+
+    if (event->type == PJMEDIA_EVENT_FMT_CHANGED) {
+	pjmedia_vid_codec *codec = port_data->codec;
+	pjmedia_vid_codec_param codec_param;
+	pj_status_t status;
+
+	++event->proc_cnt;
+
+	status = codec->op->get_param(codec, &codec_param);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	status = pjmedia_vid_dev_stream_set_cap(
+			pjmedia_vid_port_get_stream(port_data->rdr_port),
+			PJMEDIA_VID_DEV_CAP_FORMAT,
+			&codec_param.dec_fmt);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
 static pj_status_t codec_put_frame(pjmedia_port *port,
 			           pjmedia_frame *frame)
@@ -48,5 +75,5 @@
 #if !BYPASS_PACKETIZER
 	if (enc_frame.size) {
-	    unsigned pos = 0, i = 0;
+	    unsigned pos = 0;
 	    pj_bool_t packetized = PJ_FALSE;
 	    unsigned unpack_pos = 0;
@@ -59,5 +86,6 @@
 					      (pj_uint8_t*)enc_frame.buf,
 					      enc_frame.size, &pos,
-					      &payload, &payload_len);
+					      (const pj_uint8_t**)&payload,
+					      &payload_len);
 		if (status == PJ_ENOTSUP)
 		    break;
@@ -87,18 +115,4 @@
 	status = codec->op->decode(codec, &enc_frame, frame->size, frame);
 	if (status != PJ_SUCCESS) goto on_error;
-
-	/* Detect format change */
-	if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) {
-	    pjmedia_vid_codec_param codec_param;
-
-	    status = codec->op->get_param(codec, &codec_param);
-	    if (status != PJ_SUCCESS) goto on_error;
-
-	    status = pjmedia_vid_dev_stream_set_cap(
-			    pjmedia_vid_port_get_stream(port_data->rdr_port),
-			    PJMEDIA_VID_DEV_CAP_FORMAT,
-			    &codec_param.dec_fmt);
-	    if (status != PJ_SUCCESS) goto on_error;
-	}
     }
 #endif
@@ -170,4 +184,5 @@
     pjmedia_vid_port_param vport_param;
     pjmedia_video_format_detail *vfd;
+    pjmedia_event_subscription esub;
     pj_status_t status;
     int rc = 0;
@@ -277,7 +292,10 @@
 	codec_param.dec_fmt.det = codec_param.enc_fmt.det;
 
+	/* Subscribe to codec events */
+	pjmedia_event_subscription_init(&esub, &codec_on_event,
+	                                &codec_port_data);
+	pjmedia_event_subscribe(&codec->epub, &esub);
 #endif /* !BYPASS_CODEC */
     }
-
 
     pjmedia_vid_port_param_default(&vport_param);
Index: pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_dev_test.c
===================================================================
--- pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_dev_test.c	(revision 3621)
+++ pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_dev_test.c	(revision 3622)
@@ -90,5 +90,4 @@
     pjmedia_vid_port_param param;
     pjmedia_video_format_detail *vfd;
-    pjmedia_vid_cb cb;
     pjmedia_event_subscription esub;
     pj_status_t status;
