Index: /pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/jbuf.h
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/jbuf.h	(revision 3434)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/jbuf.h	(revision 3435)
@@ -327,4 +327,20 @@
 
 
+/**
+ * Get a frame from the jitter buffer. The jitter buffer will return the
+ * oldest frame from it's buffer, when it is available.
+ *
+ * @param jb		The jitter buffer.
+ * @param frame		Buffer to receive the payload from the jitter buffer.
+ *			@see pjmedia_jbuf_get_frame().    
+ * @param size		Pointer to receive frame size.
+ * @param p_frm_type	Pointer to receive frame type.
+ *			@see pjmedia_jbuf_get_frame().    
+ * @param bit_info	Bit precise info of the frame, e.g: a frame may not 
+ *			exactly start and end at the octet boundary, so this
+ *			field may be used for specifying start & end bit offset.
+ * @param ts		Frame timestamp.
+ * @param seq		Frame sequence number.
+ */
 PJ_DECL(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb, 
 				      void *frame, 
@@ -332,14 +348,43 @@
 				      char *p_frm_type,
 				      pj_uint32_t *bit_info,
-				      pj_uint32_t *ts);
-
+				      pj_uint32_t *ts,
+				      int *seq);
+
+
+/**
+ * Peek a frame from the jitter buffer. The jitter buffer state will not be
+ * modified.
+ *
+ * @param jb		The jitter buffer.
+ * @param offset	Offset from the oldest frame to be peeked.
+ * @param frame		Buffer to receive the payload from the jitter buffer.
+ *			@see pjmedia_jbuf_get_frame().    
+ * @param size		Pointer to receive frame size.
+ * @param p_frm_type	Pointer to receive frame type.
+ *			@see pjmedia_jbuf_get_frame().    
+ * @param bit_info	Bit precise info of the frame, e.g: a frame may not 
+ *			exactly start and end at the octet boundary, so this
+ *			field may be used for specifying start & end bit offset.
+ * @param ts		Frame timestamp.
+ * @param seq		Frame sequence number.
+ */
 PJ_DECL(void) pjmedia_jbuf_peek_frame(pjmedia_jbuf *jb,
-				      unsigned idx,
+				      unsigned offset,
 				      const void **frame, 
 				      pj_size_t *size, 
 				      char *p_frm_type,
 				      pj_uint32_t *bit_info,
-				      pj_uint32_t *ts);
-
+				      pj_uint32_t *ts,
+				      int *seq);
+
+
+/**
+ * Remove frames from the jitter buffer.
+ *
+ * @param jb		The jitter buffer.
+ * @param frame_cnt	Number of frames to be removed.
+ *
+ * @return		The number of frame successfully removed.
+ */
 PJ_DECL(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb, 
 					    unsigned frame_cnt);
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 3434)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-codec/ffmpeg_codecs.c	(revision 3435)
@@ -182,7 +182,4 @@
 						/**< expected output format of 
 						     ffmpeg decoder	    */
-    struct SwsContext		    *sws_ctx;   /**< the format converter for 
-						     post decoding	    */
-
 } ffmpeg_private;
 
@@ -207,4 +204,6 @@
     pjmedia_vid_codec_info       info;
     pjmedia_format_id		 base_fmt_id;
+    pj_uint32_t			 avg_bps;
+    pj_uint32_t			 max_bps;
     func_packetize		 packetize;
     func_unpacketize		 unpacketize;
@@ -248,5 +247,5 @@
     {
 	{PJMEDIA_FORMAT_H263P,	{"H263-1998",9},    PJMEDIA_RTP_PT_H263},
-	PJMEDIA_FORMAT_H263,
+	PJMEDIA_FORMAT_H263,	1000000,    2000000,
 	&h263_packetize, &h263_unpacketize, &h263_parse_fmtp,
 	{2, { {{"CIF",3}, {"2",1}}, {{"QCIF",4}, {"1",1}}, } },
@@ -254,5 +253,5 @@
     {
 	{PJMEDIA_FORMAT_H263,	{"H263",4},	    PJMEDIA_RTP_PT_H263},
-	0,
+	0,			1000000,    2000000,
 	&h263_packetize, &h263_unpacketize, &h263_parse_fmtp,
 	{2, { {{"CIF",3}, {"2",1}}, {{"QCIF",4}, {"1",1}}, } },
@@ -802,4 +801,8 @@
     attr->dec_fmtp = desc->dec_fmtp;
 
+    /* Bitrate */
+    attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
+    attr->enc_fmt.det.vid.max_bps = desc->max_bps;
+
     return PJ_SUCCESS;
 }
@@ -989,8 +992,9 @@
             ctx->time_base.num = vfd->fps.denum;
             ctx->time_base.den = vfd->fps.num;
-            if (vfd->avg_bps)
+	    if (vfd->avg_bps) {
                 ctx->bit_rate = vfd->avg_bps;
-            if (vfd->max_bps)
-                ctx->rc_max_rate = vfd->max_bps;
+		if (vfd->max_bps)
+		    ctx->bit_rate_tolerance = vfd->max_bps - vfd->avg_bps;
+	    }
 
 	    /* For encoder, should be better to be strict to the standards */
@@ -1124,10 +1128,6 @@
         av_free(ff->dec_ctx);
     }
-    if (ff->sws_ctx) {
-	sws_freeContext(ff->sws_ctx);
-    }
     ff->enc_ctx = NULL;
     ff->dec_ctx = NULL;
-    ff->sws_ctx = NULL;
     pj_mutex_unlock(ff_mutex);
 
@@ -1409,5 +1409,4 @@
 #ifdef _MSC_VER
 #   pragma comment( lib, "avcodec.lib")
-#   pragma comment( lib, "swscale.lib")
 #endif
 
Index: /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c	(revision 3434)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c	(revision 3435)
@@ -447,4 +447,7 @@
                     if (strm->overlay)
                         SDL_FreeYUVOverlay(strm->overlay);
+
+		    /* Update SDL info for the new format */
+		    sdl_info = get_sdl_format_info(fmt->id);
 
                     if (vfi->color_model == PJMEDIA_COLOR_MODEL_RGB) {
Index: /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/jbuf.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/jbuf.c	(revision 3434)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/jbuf.c	(revision 3435)
@@ -264,5 +264,6 @@
 				  pjmedia_jb_frame_type *p_type,
 				  pj_uint32_t *bit_info,
-				  pj_uint32_t *ts) 
+				  pj_uint32_t *ts,
+				  int *seq) 
 {
     if (framelist->size) {
@@ -289,4 +290,6 @@
 	    if (ts)
 		*ts = framelist->ts[framelist->head];
+	    if (seq)
+		*seq = framelist->origin;
 
 	    //pj_bzero(framelist->content + 
@@ -314,17 +317,19 @@
 
 static pj_bool_t jb_framelist_peek(jb_framelist_t *framelist,
-				   unsigned idx,
+				   unsigned offset,
 				   const void **frame,
 				   pj_size_t *size,
 				   pjmedia_jb_frame_type *type,
 				   pj_uint32_t *bit_info,
-				   pj_uint32_t *ts) 
-{
-    unsigned pos;
-
-    if (idx >= jb_framelist_eff_size(framelist))
+				   pj_uint32_t *ts,
+				   int *seq) 
+{
+    unsigned pos, idx;
+
+    if (offset >= jb_framelist_eff_size(framelist))
 	return PJ_FALSE;
 
     pos = framelist->head;
+    idx = offset;
 
     /* Find actual peek position, note there may be discarded frames */
@@ -351,4 +356,6 @@
     if (ts)
 	*ts = framelist->ts[pos];
+    if (seq)
+	*seq = framelist->origin + offset;
 
     return PJ_TRUE;
@@ -932,5 +939,6 @@
 				     char *p_frame_type)
 {
-    pjmedia_jbuf_get_frame3(jb, frame, NULL, p_frame_type, NULL, NULL);
+    pjmedia_jbuf_get_frame3(jb, frame, NULL, p_frame_type, NULL,
+			    NULL, NULL);
 }
 
@@ -944,5 +952,6 @@
 				     pj_uint32_t *bit_info)
 {
-    pjmedia_jbuf_get_frame3(jb, frame, size, p_frame_type, bit_info, NULL);
+    pjmedia_jbuf_get_frame3(jb, frame, size, p_frame_type, bit_info,
+			    NULL, NULL);
 }
 
@@ -955,5 +964,6 @@
 				     char *p_frame_type,
 				     pj_uint32_t *bit_info,
-				     pj_uint32_t *ts)
+				     pj_uint32_t *ts,
+				     int *seq)
 {
     if (jb->jb_status == JB_STATUS_PREFETCHING) {
@@ -980,5 +990,5 @@
 	/* Try to retrieve a frame from frame list */
 	res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype, 
-			       bit_info, ts);
+			       bit_info, ts, seq);
 	if (res) {
 	    /* We've successfully retrieved a frame from the frame list, but
@@ -1050,15 +1060,17 @@
 
 PJ_DEF(void) pjmedia_jbuf_peek_frame( pjmedia_jbuf *jb,
-				      unsigned idx,
+				      unsigned offset,
 				      const void **frame, 
 				      pj_size_t *size, 
 				      char *p_frm_type,
 				      pj_uint32_t *bit_info,
-				      pj_uint32_t *ts)
+				      pj_uint32_t *ts,
+				      int *seq)
 {
     pjmedia_jb_frame_type ftype;
     pj_bool_t res;
 
-    res = jb_framelist_peek(&jb->jb_framelist, idx, frame, size, &ftype, bit_info, ts);
+    res = jb_framelist_peek(&jb->jb_framelist, offset, frame, size, &ftype,
+			    bit_info, ts, seq);
     if (!res)
 	*p_frm_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
Index: /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/stream.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/stream.c	(revision 3434)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/stream.c	(revision 3435)
@@ -2742,6 +2742,4 @@
 
 static const pj_str_t ID_AUDIO = { "audio", 5};
-static const pj_str_t ID_VIDEO = { "video", 5};
-static const pj_str_t ID_APPLICATION = { "application", 11};
 static const pj_str_t ID_IN = { "IN", 2 };
 static const pj_str_t ID_IP4 = { "IP4", 3};
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 3434)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/vid_stream.c	(revision 3435)
@@ -69,5 +69,5 @@
     void		   *buf;	    /**< Output buffer.		    */
     unsigned		    buf_size;	    /**< Size of output buffer.	    */
-    unsigned                buf_len;    /**< Length of data in buffer.  */
+    unsigned                buf_len;	    /**< Length of data in buffer.  */
     pjmedia_rtp_session	    rtp;	    /**< RTP session.		    */
 } pjmedia_vid_channel;
@@ -135,4 +135,6 @@
 
     pjmedia_vid_codec	    *codec;	    /**< Codec instance being used. */
+    pj_uint32_t		     last_dec_ts;    /**< Last decoded timestamp.   */
+    int			     last_dec_seq;   /**< Last decoded sequence.    */
 };
 
@@ -841,4 +843,6 @@
     pjmedia_vid_channel *channel = stream->dec;
     pjmedia_frame frame_in;
+    pj_bool_t fps_changed = PJ_FALSE;
+    pjmedia_ratio new_fps = {0};
     pj_status_t status;
 
@@ -857,5 +861,6 @@
 	pj_size_t psize, data_len;
 	pj_uint32_t ts, last_ts;
-	pj_bool_t got_frame;
+	int seq;
+	pj_bool_t got_frame, check_fps;
 	unsigned i;
 
@@ -863,4 +868,5 @@
 	last_ts = 0;
 	got_frame = PJ_FALSE;
+	check_fps = PJ_FALSE;
 
 	/* Lock jitter buffer mutex first */
@@ -870,8 +876,12 @@
 	    /* Get frame from jitter buffer. */
 	    pjmedia_jbuf_peek_frame(stream->jb, i, &p, &psize, &ptype,
-				    NULL, &ts);
+				    NULL, &ts, &seq);
 	    if (ptype == PJMEDIA_JB_NORMAL_FRAME) {
-		if (last_ts == 0)
+		if (last_ts == 0) {
 		    last_ts = ts;
+		    check_fps = stream->last_dec_ts &&
+				(seq - stream->last_dec_seq == 1) &&
+				(last_ts > stream->last_dec_ts);
+		}
 
 		if (ts != last_ts) {
@@ -880,5 +890,5 @@
 		    break;
 		}
-		
+
 		data = (pj_uint8_t*)channel->buf + channel->buf_len;
 		data_len = channel->buf_size - channel->buf_len;
@@ -901,4 +911,26 @@
 	    return PJ_SUCCESS;
 	}
+
+	/* Learn remote frame rate */
+	if (check_fps) {
+	    pj_uint32_t ts_diff;
+	    pjmedia_video_format_detail *vfd;
+
+	    ts_diff = last_ts - stream->last_dec_ts;
+	    vfd = pjmedia_format_get_video_format_detail(
+				    &channel->port.info.fmt, PJ_TRUE);
+	    if (ts_diff * vfd->fps.num !=
+		stream->info.codec_info.clock_rate * vfd->fps.denum)
+	    {
+		/* Frame rate changed */
+		fps_changed = PJ_TRUE;
+		new_fps.num = stream->info.codec_info.clock_rate;
+		new_fps.denum = ts_diff;
+	    }
+	}
+
+	/* Update last frame seq and timestamp */
+	stream->last_dec_seq = seq - 1;
+	stream->last_dec_ts = last_ts;
     }
 
@@ -924,8 +956,28 @@
 
 	/* Update decoding channel port info */
-	pjmedia_format_copy(&stream->dec->port.info.fmt,
+	pjmedia_format_copy(&channel->port.info.fmt,
 			    &stream->info.codec_param->dec_fmt);
     }
-    
+
+    if (fps_changed) {
+	pjmedia_video_format_detail *vfd;
+
+	/* Update decoding channel port info */
+	vfd = pjmedia_format_get_video_format_detail(
+				&channel->port.info.fmt, PJ_TRUE);
+	vfd->fps = new_fps;
+
+	/* Update stream info */
+	vfd = pjmedia_format_get_video_format_detail(
+				&stream->info.codec_param->dec_fmt, PJ_TRUE);
+	vfd->fps = new_fps;
+
+	/* Set bit_info */
+	frame->bit_info |= PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED;
+
+	PJ_LOG(4, (channel->port.info.name.ptr, "Frame rate changed to %.2ffps",
+		   (1.0 * new_fps.num / new_fps.denum)));
+    }
+
     return PJ_SUCCESS;
 }
@@ -1134,6 +1186,9 @@
 	return status;
 
-    /* Get the frame size */
-    stream->frame_size = vfd_enc->max_bps * vfd_enc->fps.denum /
+    /* Estimate the maximum frame size */
+    stream->frame_size = vfd_enc->size.w * vfd_enc->size.h * 4;
+
+#if 0
+    stream->frame_size = vfd_enc->max_bps/8 * vfd_enc->fps.denum /
 			 vfd_enc->fps.num;
     
@@ -1142,5 +1197,6 @@
      * frame size value for safety.
      */
-    stream->frame_size <<= 2;
+    stream->frame_size <<= 4;
+#endif
 
     /* Validate the frame size */
@@ -1562,7 +1618,5 @@
 
 
-static const pj_str_t ID_AUDIO = { "audio", 5};
 static const pj_str_t ID_VIDEO = { "video", 5};
-static const pj_str_t ID_APPLICATION = { "application", 11};
 static const pj_str_t ID_IN = { "IN", 2 };
 static const pj_str_t ID_IP4 = { "IP4", 3};
@@ -1572,5 +1626,4 @@
 //static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };
 static const pj_str_t ID_RTPMAP = { "rtpmap", 6 };
-static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 };
 
 static const pj_str_t STR_INACTIVE = { "inactive", 8 };
Index: /pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/simpleua.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/simpleua.c	(revision 3434)
+++ /pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/simpleua.c	(revision 3435)
@@ -548,4 +548,40 @@
     dump_pool_usage(THIS_FILE, &cp);
 
+    /* Destroy stream */
+    if (g_med_stream)
+	pjmedia_stream_destroy(g_med_stream);
+    if (g_med_vstream)
+	pjmedia_vid_stream_destroy(g_med_vstream);
+
+    /* Destroy audio ports */
+    if (g_snd_player)
+	pjmedia_snd_port_destroy(g_snd_player);
+    if (g_snd_rec)
+	pjmedia_snd_port_destroy(g_snd_rec);
+
+    /* Destroy video ports */
+    if (g_vid_capturer)
+	pjmedia_vid_port_destroy(g_vid_capturer);
+    if (g_vid_renderer)
+	pjmedia_vid_port_destroy(g_vid_renderer);
+
+    /* Destroy media transports */
+    for (i = 0; i < MAX_MEDIA_CNT; ++i) {
+	if (g_med_transport[i])
+	    pjmedia_transport_close(g_med_transport[i]);
+    }
+
+    /* Deinit ffmpeg codec */
+    pjmedia_codec_ffmpeg_deinit();
+
+    /* Deinit pjmedia endpoint */
+    if (g_med_endpt)
+	pjmedia_endpt_destroy(g_med_endpt);
+
+    /* Deinit pjsip endpoint */
+    if (g_endpt)
+	pjsip_endpt_destroy(g_endpt);
+
+    /* Release pool */
     pj_pool_release(pool);
 
Index: /pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/vid_streamutil.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/vid_streamutil.c	(revision 3434)
+++ /pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/vid_streamutil.c	(revision 3435)
@@ -126,4 +126,14 @@
 }
 
+/* 
+ * Register all codecs. 
+ */
+static void deinit_codecs()
+{
+#if defined(PJMEDIA_HAS_FFMPEG_CODEC) && PJMEDIA_HAS_FFMPEG_CODEC != 0
+    pjmedia_codec_ffmpeg_deinit();
+#endif
+}
+
 static pj_status_t create_file_player( pj_pool_t *pool,
 				       const char *file_name,
@@ -616,5 +626,5 @@
 	file_vfd = pjmedia_format_get_video_format_detail(&play_port->info.fmt,
 							  PJ_TRUE);
-	PJ_LOG(2, (THIS_FILE, "Reading video stream %dx%d %c%c%c%c @%.2dfps",
+	PJ_LOG(2, (THIS_FILE, "Reading video stream %dx%d %c%c%c%c @%.2ffps",
 		   file_vfd->size.w, file_vfd->size.h,
 		   ((play_port->info.fmt.id & 0x000000FF) >> 0),
@@ -622,5 +632,5 @@
 		   ((play_port->info.fmt.id & 0x00FF0000) >> 16),
 		   ((play_port->info.fmt.id & 0xFF000000) >> 24),
-		   file_vfd->fps.num/file_vfd->fps.denum));
+		   (1.0*file_vfd->fps.num/file_vfd->fps.denum)));
 
 	/* Allocate file read buffer */
@@ -658,4 +668,5 @@
 		goto on_exit;
 
+	    codec_param2.dir = PJMEDIA_DIR_DECODING;
 	    status = play_decoder->op->open(play_decoder, &codec_param2);
 	    if (status != PJ_SUCCESS)
@@ -706,5 +717,6 @@
 	        goto on_exit;
 
-            pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.dec_fmt);
+            pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.enc_fmt);
+	    vpp.vidparam.fmt.id = codec_param.dec_fmt.id;
             vpp.vidparam.dir = PJMEDIA_DIR_CAPTURE;
             
@@ -836,11 +848,11 @@
 
     if (dir & PJMEDIA_DIR_ENCODING)
-	PJ_LOG(2, (THIS_FILE, "Sending %dx%d %.*s @%.2dfps",
+	PJ_LOG(2, (THIS_FILE, "Sending %dx%d %.*s @%.2ffps",
 		   codec_param.enc_fmt.det.vid.size.w,
 		   codec_param.enc_fmt.det.vid.size.h,
 		   codec_info->encoding_name.slen,
 		   codec_info->encoding_name.ptr,
-		   codec_param.enc_fmt.det.vid.fps.num/
-		   codec_param.enc_fmt.det.vid.fps.denum));
+		   (1.0*codec_param.enc_fmt.det.vid.fps.num/
+		    codec_param.enc_fmt.det.vid.fps.denum)));
 
     for (;;) {
@@ -880,6 +892,8 @@
 
     /* Destroy file decoder */
-    if (play_decoder)
+    if (play_decoder) {
 	play_decoder->op->close(play_decoder);
+	pjmedia_vid_codec_mgr_dealloc_codec(NULL, play_decoder);
+    }
 
     /* Destroy video devices */
@@ -899,4 +913,7 @@
     }
 
+    /* Deinit codecs */
+    deinit_codecs();
+
     /* Shutdown video subsystem */
     pjmedia_vid_subsys_shutdown();
