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 3534)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c	(revision 3535)
@@ -378,50 +378,44 @@
 }
 
-#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
-@implementation SDLDelegate
-- (int)sdl_thread
-{
-#else
-static int sdlthread(void * data)
-{
-    struct sdl_stream *strm = (struct sdl_stream*)data;
-#endif
-    sdl_fmt_info *sdl_info = get_sdl_format_info(strm->param.fmt.id);
+static void destroy_sdl(struct sdl_stream *strm)
+{
+    if (strm->surf) {
+	SDL_FreeSurface(strm->surf);
+	strm->surf = NULL;
+    }
+    if (strm->overlay) {
+	SDL_FreeYUVOverlay(strm->overlay);
+	strm->overlay = NULL;
+    }
+#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
+    if (strm->texture) {
+	glDeleteTextures(1, &strm->texture);
+	strm->texture = 0;
+    }
+#endif
+}
+
+static pj_status_t init_sdl(struct sdl_stream *strm, pjmedia_format *fmt)
+{
+    sdl_fmt_info *sdl_info = get_sdl_format_info(fmt->id);
     const pjmedia_video_format_info *vfi;
     pjmedia_video_format_detail *vfd;
 
     vfi = pjmedia_get_video_format_info(pjmedia_video_format_mgr_instance(),
-                                        strm->param.fmt.id);
-    if (!vfi || !sdl_info) {
-        strm->status = PJMEDIA_EVID_BADFORMAT;
-        goto on_return;
-    }
-
-    strm->vafp.size = strm->param.fmt.det.vid.size;
+                                        fmt->id);
+    if (!vfi || !sdl_info)
+        return PJMEDIA_EVID_BADFORMAT;
+
+    strm->vafp.size = fmt->det.vid.size;
     strm->vafp.buffer = NULL;
-    if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS) {
-        strm->status = PJMEDIA_EVID_BADFORMAT;
-        goto on_return;
-    }
-
-    /* Initialize the SDL library */
-    if (SDL_Init(SDL_INIT_VIDEO)) {
-        PJ_LOG(4, (THIS_FILE, "Cannot initialize SDL"));
-        strm->status = PJMEDIA_EVID_INIT;
-        goto on_return;
-    }
-
-    vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, PJ_TRUE);
+    if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS)
+        return PJMEDIA_EVID_BADFORMAT;
+
+    vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE);
     strm->rect.x = strm->rect.y = 0;
     strm->rect.w = (Uint16)vfd->size.w;
     strm->rect.h = (Uint16)vfd->size.h;
 
-#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
-    if (strm->param.rend_id == OPENGL_DEV_IDX) {
-	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
-    }
-#endif
-
-    /* Initialize the display, requesting a software surface */
+    /* Initialize the display */
     strm->screen = SDL_SetVideoMode(strm->rect.w, strm->rect.h, 0, (
 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
@@ -430,16 +424,19 @@
 #endif
 				    SDL_RESIZABLE | SDL_SWSURFACE));
-    if (strm->screen == NULL) {
-        strm->status = PJMEDIA_EVID_SYSERR;
-        goto on_return;
-    }
+    if (strm->screen == NULL)
+        return PJMEDIA_EVID_SYSERR;
+
     SDL_WM_SetCaption("pjmedia-SDL video", NULL);
 
+    destroy_sdl(strm);
+
 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
     if (strm->param.rend_id == OPENGL_DEV_IDX) {
+	/* Init some OpenGL settings */
 	glDisable(GL_DEPTH_TEST);
 	glDisable(GL_CULL_FACE);
 	glEnable(GL_TEXTURE_2D);
 	
+	/* Init the viewport */
 	glViewport(0, 0, strm->rect.w, strm->rect.h);
 	glMatrixMode(GL_PROJECTION);
@@ -452,8 +449,14 @@
 	glLoadIdentity();
 	
+	/* Create a texture */
 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 	glGenTextures(1, &strm->texture);
 
 #if defined(PJ_WIN32) && PJ_WIN32 != 0
+	/**
+	 * On Win32 platform, the OpenGL drawing must be in the same
+	 * thread that calls SDL_SetVideoMode(), hence we need a buffer
+	 * for the frame from sdl_stream_put_frame()
+	 */
 	if (strm->vafp.framebytes > strm->tex_buf_size) {
 	    strm->tex_buf_size = strm->vafp.framebytes;
@@ -471,37 +474,48 @@
 					  sdl_info->Bmask,
 					  sdl_info->Amask);
-        if (strm->surf == NULL) {
-            strm->status = PJMEDIA_EVID_SYSERR;
-            goto on_return;
-        }
+        if (strm->surf == NULL)
+            return PJMEDIA_EVID_SYSERR;
     } else if (vfi->color_model == PJMEDIA_COLOR_MODEL_YUV) {
         strm->overlay = SDL_CreateYUVOverlay(strm->rect.w, strm->rect.h,
 					     sdl_info->sdl_format,
 					     strm->screen);
-        if (strm->overlay == NULL) {
-            strm->status = PJMEDIA_EVID_SYSERR;
-            goto on_return;
-        }
-    }
+        if (strm->overlay == NULL)
+            return PJMEDIA_EVID_SYSERR;
+    }
+
+    return PJ_SUCCESS;
+}
+
+#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
+@implementation SDLDelegate
+- (int)sdl_thread
+{
+#else
+static int sdlthread(void * data)
+{
+    struct sdl_stream *strm = (struct sdl_stream*)data;
+#endif
+
+    /* Initialize the SDL library */
+    if (SDL_Init(SDL_INIT_VIDEO)) {
+        PJ_LOG(4, (THIS_FILE, "Cannot initialize SDL"));
+        strm->status = PJMEDIA_EVID_INIT;
+        goto on_return;
+    }
+
+#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
+    if (strm->param.rend_id == OPENGL_DEV_IDX) {
+	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
+    }
+#endif
+
+    strm->status = init_sdl(strm, &strm->param.fmt);
+    if (strm->status != PJ_SUCCESS)
+	goto on_return;
 
 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
 on_return:
     if (strm->status != PJ_SUCCESS) {
-	if (strm->surf) {
-	    SDL_FreeSurface(strm->surf);
-	    strm->surf = NULL;
-	}
-	
-	if (strm->overlay) {
-	    SDL_FreeYUVOverlay(strm->overlay);
-	    strm->overlay = NULL;
-	}
-    #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
-	if (strm->texture) {
-	    glDeleteTextures(1, &strm->texture);
-	    strm->texture = 0;
-	}
-    #endif
-	
+	destory_sdl(strm);	
 	SDL_Quit();
 	strm->screen = NULL;
@@ -554,75 +568,18 @@
                     pj_assert(sevent.user.code == PJMEDIA_VID_DEV_CAP_FORMAT);
 
-                    PJ_TODO(FIX_THIS_FOR_OPENGL);
 		    fmt = (pjmedia_format *)sevent.user.data1;
-                    vfi = pjmedia_get_video_format_info(
-			      pjmedia_video_format_mgr_instance(),
-			      fmt->id);
-                    if (!vfi || !sdl_info) {
-                        strm->status = PJMEDIA_EVID_BADFORMAT;
-                        break;
-                    }
-
-                    vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE);
-                    strm->vafp.size = vfd->size;
-                    strm->vafp.buffer = NULL;
-                    if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS) {
-                        strm->status = PJMEDIA_EVID_BADFORMAT;
-                        break;
-                    }
-
-                    strm->rect.w = (Uint16)vfd->size.w;
-                    strm->rect.h = (Uint16)vfd->size.h;
-
-                    /* Stop the stream */
+
+		    /* Stop the stream */
                     sdl_stream_stop((pjmedia_vid_dev_stream *)strm);
 
-                    /* Initialize the display, requesting a software surface */
-                    strm->screen = SDL_SetVideoMode(strm->rect.w,
-                                                    strm->rect.h, 0,
-                                                    SDL_RESIZABLE |
-                                                    SDL_SWSURFACE);
-                    if (strm->screen == NULL) {
-                        strm->status = PJMEDIA_EVID_SYSERR;
-                        break;
-                    }
-
-                    if (strm->surf)
-                        SDL_FreeSurface(strm->surf);
-                    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) {
-                        strm->surf = SDL_CreateRGBSurface(SDL_SWSURFACE,
-                                                          strm->rect.w,
-                                                          strm->rect.h,
-                                                          vfi->bpp,
-                                                          sdl_info->Rmask,
-                                                          sdl_info->Gmask,
-                                                          sdl_info->Bmask,
-                                                          sdl_info->Amask);
-                        if (strm->surf == NULL) {
-                            strm->status = PJMEDIA_EVID_SYSERR;
-                            break;
-                        }
-                    } else if (vfi->color_model == PJMEDIA_COLOR_MODEL_YUV) {
-                        strm->overlay = SDL_CreateYUVOverlay(
-					    strm->rect.w,
-					    strm->rect.h,
-					    sdl_info->sdl_format,
-					    strm->screen);
-                        if (strm->overlay == NULL) {
-                            strm->status = PJMEDIA_EVID_SYSERR;
-                            break;
-                        }
-                    }
-
-                    /* Restart the stream */
-                    sdl_stream_start((pjmedia_vid_dev_stream *)strm);
-
-                    strm->status = PJ_SUCCESS;
+		    /* Re-initialize SDL */
+		    strm->status = init_sdl(strm, fmt);
+
+		    if (strm->status == PJ_SUCCESS) {
+			pjmedia_format_copy(&strm->param.fmt, fmt); 
+			/* Restart the stream */
+			sdl_stream_start((pjmedia_vid_dev_stream *)strm);
+		    }
+
                     break;
                 }
@@ -714,20 +671,5 @@
 #endif
 on_return:
-    if (strm->surf) {
-	SDL_FreeSurface(strm->surf);
-	strm->surf = NULL;
-    }
-
-    if (strm->overlay) {
-	SDL_FreeYUVOverlay(strm->overlay);
-	strm->overlay = NULL;
-    }
-#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL
-    if (strm->texture) {
-	glDeleteTextures(1, &strm->texture);
-	strm->texture = 0;
-    }
-#endif
-
+    destroy_sdl(strm);
     SDL_Quit();
     strm->screen = NULL;
@@ -818,6 +760,5 @@
     else if (stream->param.rend_id == OPENGL_DEV_IDX) {
 #if defined(PJ_WIN32) && PJ_WIN32 != 0
-	pj_assert(frame->size == stream->vafp.framebytes);
-	pj_memcpy(stream->tex_buf, frame->buf, frame->size);
+	pj_memcpy(stream->tex_buf, frame->buf, stream->vafp.framebytes);
 #else
 	draw_gl(stream, frame->buf);
@@ -892,4 +833,5 @@
 	strm->delegate = [[SDLDelegate alloc]init];
 	strm->delegate->strm = strm;
+	/* On Mac OS X, we need to call SDL functions in the main thread */
 	[strm->delegate performSelectorOnMainThread:@selector(sdl_thread)
 			withObject:nil waitUntilDone:YES];
@@ -1032,6 +974,4 @@
 	    
 	    strm->status = status;
-	} else if (strm->status == PJ_SUCCESS) {
-	    pj_memcpy(&strm->param.fmt, pval, sizeof(strm->param.fmt));
 	}
 	
Index: /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c
===================================================================
--- /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c	(revision 3534)
+++ /pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c	(revision 3535)
@@ -38,4 +38,5 @@
 struct pjmedia_vid_port
 {
+    pj_pool_t		*pool;
     pj_str_t		 dev_name;
     pjmedia_dir		 dir;
@@ -50,7 +51,8 @@
     pj_bool_t		 destroy_client_port;
 
-    pjmedia_converter	*cap_conv;
-    void		*cap_conv_buf;
-    pj_size_t		 cap_conv_buf_size;
+    pjmedia_converter	    *cap_conv;
+    void		    *cap_conv_buf;
+    pj_size_t		     cap_conv_buf_size;
+    pjmedia_conversion_param cap_conv_param;
 
     pjmedia_clock	*enc_clock,
@@ -136,5 +138,4 @@
     unsigned ptime_usec;
     pjmedia_vid_param vparam;
-    pjmedia_conversion_param conv_param;
 
     PJ_ASSERT_RETURN(pool && prm && p_vid_port, PJ_EINVAL);
@@ -152,4 +153,5 @@
     /* Allocate videoport */
     vp = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_port);
+    vp->pool = pool;
     vp->role = prm->active ? ROLE_ACTIVE : ROLE_PASSIVE;
     vp->dir = prm->vidparam.dir;
@@ -257,4 +259,12 @@
 	      vparam.fmt.det.vid.fps.num, vparam.fmt.det.vid.fps.denum));
 
+    if (vp->dir & PJMEDIA_DIR_CAPTURE) {
+	pjmedia_format_copy(&vp->cap_conv_param.src, &vparam.fmt);
+	pjmedia_format_copy(&vp->cap_conv_param.dst, &prm->vidparam.fmt);
+    } else {
+	pjmedia_format_copy(&vp->cap_conv_param.src, &prm->vidparam.fmt);
+	pjmedia_format_copy(&vp->cap_conv_param.dst, &vparam.fmt);
+    }
+
     /* Instantiate converter if necessary */
     if (vparam.fmt.id != prm->vidparam.fmt.id ||
@@ -268,18 +278,6 @@
 	pjmedia_video_apply_fmt_param vafp;
 
-	if (vp->dir & PJMEDIA_DIR_CAPTURE) {
-	    pjmedia_format_copy(&conv_param.src, &vparam.fmt);
-	    pjmedia_format_copy(&conv_param.dst, &prm->vidparam.fmt);
-
-	    status = pjmedia_converter_create(NULL, pool, &conv_param,
-					      &vp->cap_conv);
-	} else {
-	    pjmedia_format_copy(&conv_param.src, &prm->vidparam.fmt);
-	    pjmedia_format_copy(&conv_param.dst, &vparam.fmt);
-
-	    status = pjmedia_converter_create(NULL, pool, &conv_param,
-					      &vp->cap_conv);
-	}
-
+	status = pjmedia_converter_create(NULL, pool, &vp->cap_conv_param,
+					  &vp->cap_conv);
 	if (status != PJ_SUCCESS) {
 	    PJ_PERROR(4,(THIS_FILE, status, "Error creating converter"));
@@ -288,10 +286,10 @@
 
 	/* Allocate buffer for conversion */
-	vfi = pjmedia_get_video_format_info(NULL, conv_param.dst.id);
+	vfi = pjmedia_get_video_format_info(NULL, vp->cap_conv_param.dst.id);
 	if (!vfi)
 	    return PJMEDIA_EBADFMT;
 
 	pj_bzero(&vafp, sizeof(vafp));
-	vafp.size = conv_param.dst.det.vid.size;
+	vafp.size = vp->cap_conv_param.dst.det.vid.size;
 	status = vfi->apply_fmt(vfi, &vafp);
 	if (status != PJ_SUCCESS)
@@ -354,5 +352,5 @@
 
 	vfi = pjmedia_get_video_format_info(NULL, vp->cap_conv?
-					    conv_param.src.id:
+					    vp->cap_conv_param.src.id:
 					    vparam.fmt.id);
 	if (!vfi) {
@@ -362,5 +360,5 @@
 
 	pj_bzero(&vafp, sizeof(vafp));
-	vafp.size = (vp->cap_conv? conv_param.src.det.vid.size:
+	vafp.size = (vp->cap_conv? vp->cap_conv_param.src.det.vid.size:
 		     vparam.fmt.det.vid.size);
 	status = vfi->apply_fmt(vfi, &vafp);
@@ -611,4 +609,6 @@
         pj_status_t status;
 
+	pjmedia_vid_port_stop(vp);
+
         /* Retrieve the video format detail */
         vfd = pjmedia_format_get_video_format_detail(
@@ -617,4 +617,23 @@
             return PJMEDIA_EVID_BADFORMAT;
         pj_assert(vfd->fps.num);
+
+	if (vp->cap_conv) {
+	    /* Change the destination format to the new format */
+	    pjmedia_format_copy(&vp->cap_conv_param.src,
+				&vp->client_port->info.fmt);
+	    /* Only copy the size here */
+	    vp->cap_conv_param.dst.det.vid.size =
+		vp->client_port->info.fmt.det.vid.size,
+
+	    /* Recreate converter */
+	    pjmedia_converter_destroy(vp->cap_conv);
+	    status = pjmedia_converter_create(NULL, vp->pool,
+					      &vp->cap_conv_param,
+					      &vp->cap_conv);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(4,(THIS_FILE, status, "Error recreating converter"));
+		return status;
+	    }
+	}
 
         status = pjmedia_vid_dev_stream_set_cap(
@@ -628,5 +647,4 @@
                                   status != PJMEDIA_EVID_ERR ? "success" :
                                   "failure"));
-            pjmedia_vid_port_stop(vp);
             return status;
         }
@@ -650,8 +668,10 @@
         /* 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));
+	pjmedia_format_copy(&pevent.event_desc.fmt_change.new_format,
+			    &vp->client_port->info.fmt);
         if (vp->strm_cb.on_event_cb)
             (*vp->strm_cb.on_event_cb)(vp->strm, vp->strm_cb_data, &pevent);
+
+	pjmedia_vid_port_start(vp);
     }
 
