Index: pjproject/trunk/pjsip-apps/src/swig/java/android/res/layout/activity_call.xml
===================================================================
--- pjproject/trunk/pjsip-apps/src/swig/java/android/res/layout/activity_call.xml	(revision 5101)
+++ pjproject/trunk/pjsip-apps/src/swig/java/android/res/layout/activity_call.xml	(revision 5102)
@@ -24,23 +24,50 @@
         android:gravity="center"
         android:text="Call state" />
-
-    <Button
-        android:id="@+id/buttonAccept"
+    
+	<LinearLayout 
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:onClick="acceptCall"
-        android:text="Accept" />
-
-    <Button
-        android:id="@+id/buttonHangup"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:onClick="hangupCall"
-        android:text="Reject" />
-
+        android:orientation="horizontal">    
+        
+        <LinearLayout 
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_weight=".50">    
+	    	    
+            <Button
+                android:id="@+id/buttonAccept"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:onClick="acceptCall"
+                android:text="Accept" />
+		
+            <Button
+                android:id="@+id/buttonHangup"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:onClick="hangupCall"
+                android:text="Reject" />
+		    
+            <Button
+                android:id="@+id/buttonShowPreview"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"		        
+                android:onClick="showPreview"
+                android:text="@+string/show_preview" />
+	    
+        </LinearLayout>
+        <SurfaceView
+            android:id="@+id/surfacePreviewCapture"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight=".50" />			    
+	    
+    </LinearLayout>
+   
     <SurfaceView
-        android:id="@+id/surfaceIncomingVideo"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
+       	android:id="@+id/surfaceIncomingVideo"
+       	android:layout_width="match_parent"
+       	android:layout_height="match_parent" />
+	
 </LinearLayout>
Index: pjproject/trunk/pjsip-apps/src/swig/java/android/res/values/strings.xml
===================================================================
--- pjproject/trunk/pjsip-apps/src/swig/java/android/res/values/strings.xml	(revision 5101)
+++ pjproject/trunk/pjsip-apps/src/swig/java/android/res/values/strings.xml	(revision 5102)
@@ -6,4 +6,5 @@
     <string name="title_activity_call">Call</string>
     <string name="hello_world">Hello world!</string>
-
+    <string name="show_preview">Show Preview</string>
+    <string name="hide_preview">Hide Preview</string>
 </resources>
Index: pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java
===================================================================
--- pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java	(revision 5101)
+++ pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java	(revision 5102)
@@ -31,4 +31,57 @@
 import org.pjsip.pjsua2.*;
 
+class VideoPreviewHandler implements SurfaceHolder.Callback
+{   
+    public boolean videoPreviewActive = false;
+        
+    public void updateVideoPreview(SurfaceHolder holder) 
+    {
+	if (MainActivity.currentCall != null &&
+	    MainActivity.currentCall.vidWin != null &&
+	    MainActivity.currentCall.vidPrev != null)
+	{	
+	    if (videoPreviewActive) {
+		VideoWindowHandle vidWH = new VideoWindowHandle();
+		vidWH.getHandle().setWindow(holder.getSurface());
+		VideoPreviewOpParam vidPrevParam = new VideoPreviewOpParam();
+		vidPrevParam.setWindow(vidWH);		
+		try {
+		    MainActivity.currentCall.vidPrev.start(vidPrevParam);
+		} catch (Exception e) {
+		    System.out.println(e);
+		}
+	    } else {
+		try {
+		    MainActivity.currentCall.vidPrev.stop();
+		} catch (Exception e) {
+		    System.out.println(e);
+		}	
+	    }
+	}
+    }    
+    
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
+    {
+	updateVideoPreview(holder);
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) 
+    {
+	
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) 
+    {
+	try {
+	    MainActivity.currentCall.vidPrev.stop();
+	} catch (Exception e) {
+	    System.out.println(e);
+	}
+    }    
+}
+
 public class CallActivity extends Activity
 			  implements Handler.Callback, SurfaceHolder.Callback
@@ -36,4 +89,6 @@
 
     public static Handler handler_;
+    private static VideoPreviewHandler previewHandler = 
+	    					      new VideoPreviewHandler();
 
     private final Handler handler = new Handler(this);
@@ -46,12 +101,20 @@
 	setContentView(R.layout.activity_call);
 
-	SurfaceView surfaceView = (SurfaceView)
+	SurfaceView surfaceInVideo = (SurfaceView)
 				  findViewById(R.id.surfaceIncomingVideo);
+	SurfaceView surfacePreview = (SurfaceView)
+		  		  findViewById(R.id.surfacePreviewCapture);	
+	Button buttonShowPreview = (Button) 
+		  		  findViewById(R.id.buttonShowPreview);	
+	
 	if (MainActivity.currentCall == null ||
 	    MainActivity.currentCall.vidWin == null)
 	{
-	    surfaceView.setVisibility(View.GONE);
-	}
-	surfaceView.getHolder().addCallback(this);
+	    surfaceInVideo.setVisibility(View.GONE);	    
+	    buttonShowPreview.setVisibility(View.GONE);
+	}
+	setupVideoPreview(surfacePreview, buttonShowPreview);
+	surfaceInVideo.getHolder().addCallback(this);
+	surfacePreview.getHolder().addCallback(previewHandler);
 
 	handler_ = handler;
@@ -74,24 +137,32 @@
 	handler_ = null;
     }
-
-    private void updateVideoWindow(SurfaceHolder holder)
-    {
+    
+    private void updateVideoWindow(boolean show)
+    { 
 	if (MainActivity.currentCall != null &&
-	    MainActivity.currentCall.vidWin != null)
+	    MainActivity.currentCall.vidWin != null &&
+	    MainActivity.currentCall.vidPrev != null)
 	{
-	    VideoWindowHandle vidWH = new VideoWindowHandle();
-	    if (holder == null)
+	    SurfaceView surfaceInVideo = (SurfaceView) 
+		       		  findViewById(R.id.surfaceIncomingVideo);
+	    
+	    VideoWindowHandle vidWH = new VideoWindowHandle();	    
+	    if (show) {
+		vidWH.getHandle().setWindow(
+				       surfaceInVideo.getHolder().getSurface());
+	    } else {
 		vidWH.getHandle().setWindow(null);
-	    else
-		vidWH.getHandle().setWindow(holder.getSurface());
+	    }
 	    try {
 		MainActivity.currentCall.vidWin.setWindow(vidWH);
-	    } catch (Exception e) {}
-	}
-    }
-
+	    } catch (Exception e) {
+		System.out.println(e);
+	    }	    
+	}
+    }
+     
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
     {
-	updateVideoWindow(holder);
+	updateVideoWindow(true);
     }
 
@@ -102,5 +173,5 @@
     public void surfaceDestroyed(SurfaceHolder holder)
     {
-	updateVideoWindow(null);
+	updateVideoWindow(false);
     }
 
@@ -133,11 +204,43 @@
 	}
     }
+    
+    public void setupVideoPreview(SurfaceView surfacePreview, 
+	    			  Button buttonShowPreview)
+    {
+	surfacePreview.setVisibility(previewHandler.videoPreviewActive?
+		     		     View.VISIBLE:View.GONE);
+	
+	buttonShowPreview.setText(previewHandler.videoPreviewActive?
+		  		  getString(R.string.hide_preview):
+		  		  getString(R.string.show_preview));		
+    }
+    
+    public void showPreview(View view)
+    {
+	SurfaceView surfacePreview = (SurfaceView)
+		  	          findViewById(R.id.surfacePreviewCapture);	
+
+	Button buttonShowPreview = (Button) 
+		  		  findViewById(R.id.buttonShowPreview);
+	
+	
+	previewHandler.videoPreviewActive = !previewHandler.videoPreviewActive;
+	
+	setupVideoPreview(surfacePreview, buttonShowPreview);
+	
+	previewHandler.updateVideoPreview(surfacePreview.getHolder());
+    }
 
     private void setupVideoSurface()
     {
-	SurfaceView surfaceView = (SurfaceView)
+	SurfaceView surfaceInVideo = (SurfaceView)
 				  findViewById(R.id.surfaceIncomingVideo);
-	surfaceView.setVisibility(View.VISIBLE);
-	updateVideoWindow(surfaceView.getHolder());
+	SurfaceView surfacePreview = (SurfaceView)
+		  		  findViewById(R.id.surfacePreviewCapture);
+	Button buttonShowPreview = (Button)
+		  		  findViewById(R.id.buttonShowPreview);	
+	surfaceInVideo.setVisibility(View.VISIBLE);
+	buttonShowPreview.setVisibility(View.VISIBLE);
+	surfacePreview.setVisibility(View.GONE);	
     }
 
Index: pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MyApp.java
===================================================================
--- pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MyApp.java	(revision 5101)
+++ pjproject/trunk/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MyApp.java	(revision 5102)
@@ -50,4 +50,5 @@
 {
     public VideoWindow vidWin;
+    public VideoPreview vidPrev;
 
     MyCall(MyAccount acc, int call_id)
@@ -113,4 +114,5 @@
 	    {
 		vidWin = new VideoWindow(cmi.getVideoIncomingWindowId());
+		vidPrev = new VideoPreview(cmi.getVideoCapDev());
 	    }
 	}
Index: pjproject/trunk/pjsip/include/pjsua2/media.hpp
===================================================================
--- pjproject/trunk/pjsip/include/pjsua2/media.hpp	(revision 5101)
+++ pjproject/trunk/pjsip/include/pjsua2/media.hpp	(revision 5102)
@@ -1489,4 +1489,103 @@
 };
 
+/**
+ * This structure contains parameters for VideoPreview::start()
+ */
+struct VideoPreviewOpParam {
+    /**
+     * Device ID for the video renderer to be used for rendering the
+     * capture stream for preview. This parameter is ignored if native
+     * preview is being used.
+     *
+     * Default: PJMEDIA_VID_DEFAULT_RENDER_DEV
+     */
+    pjmedia_vid_dev_index   rendId;
+
+    /**
+     * Show window initially.
+     *
+     * Default: PJ_TRUE.
+     */
+    bool		    show;
+
+    /**
+     * Window flags.  The value is a bitmask combination of
+     * \a pjmedia_vid_dev_wnd_flag.
+     *
+     * Default: 0.
+     */
+    unsigned		    windowFlags;
+
+    /**
+     * Media format. If left unitialized, this parameter will not be used.
+     */
+    MediaFormat		    format;
+
+    /**
+     * Optional output window to be used to display the video preview.
+     * This parameter will only be used if the video device supports
+     * PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW capability and the capability
+     * is not read-only.
+     */
+    VideoWindowHandle	    window;
+
+public:
+    /**
+     * Default constructor initializes with default values.
+     */
+    VideoPreviewOpParam();
+
+    /** 
+     * Convert from pjsip
+     */
+    void fromPj(const pjsua_vid_preview_param &prm);
+
+    /**
+     * Convert to pjsip
+     */
+    pjsua_vid_preview_param toPj() const;
+};
+
+/**
+ * Video Preview
+ */
+class VideoPreview {
+public:
+    /**
+     * Constructor
+     */
+    VideoPreview(int dev_id);
+
+    /**
+     * Determine if the specified video input device has built-in native
+     * preview capability. This is a convenience function that is equal to
+     * querying device's capability for PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW
+     * capability.
+     *
+     * @return		true if it has.
+     */
+    bool hasNative();
+
+    /**
+     * Start video preview window for the specified capture device.
+     *
+     * @param p		Video preview parameters. 
+     */
+    void start(const VideoPreviewOpParam &param) throw(Error);
+
+    /**
+     * Stop video preview.
+     */
+    void stop() throw(Error);
+
+    /*
+     * Get the preview window handle associated with the capture device,if any.
+     */
+    VideoWindow getVideoWindow();
+
+private:
+    pjmedia_vid_dev_index devId;
+};
+
 /*************************************************************************
 * Codec management
Index: pjproject/trunk/pjsip/src/pjsua2/media.cpp
===================================================================
--- pjproject/trunk/pjsip/src/pjsua2/media.cpp	(revision 5101)
+++ pjproject/trunk/pjsip/src/pjsua2/media.cpp	(revision 5102)
@@ -1094,4 +1094,86 @@
 #endif
 }
+///////////////////////////////////////////////////////////////////////////////
+
+VideoPreviewOpParam::VideoPreviewOpParam()
+{
+#if PJSUA_HAS_VIDEO
+    pjsua_vid_preview_param vid_prev_param;
+
+    pjsua_vid_preview_param_default(&vid_prev_param);
+    fromPj(vid_prev_param);
+#endif
+}
+
+void VideoPreviewOpParam::fromPj(const pjsua_vid_preview_param &prm)
+{
+#if PJSUA_HAS_VIDEO
+    this->rendId		    = prm.rend_id;
+    this->show			    = PJ2BOOL(prm.show);
+    this->windowFlags		    = prm.wnd_flags;
+    this->format.id		    = prm.format.id;
+    this->format.type		    = prm.format.type;
+    this->window.type		    = prm.wnd.type;
+    this->window.handle.window	    = prm.wnd.info.window;
+#else
+    PJ_UNUSED_ARG(prm);
+#endif
+}
+
+pjsua_vid_preview_param VideoPreviewOpParam::toPj() const
+{
+    pjsua_vid_preview_param param;
+#if PJSUA_HAS_VIDEO
+    param.rend_id	    = this->rendId;
+    param.show		    = this->show;
+    param.wnd_flags	    = this->windowFlags;
+    param.format.id	    = this->format.id;
+    param.format.type	    = this->format.type;
+    param.wnd.type	    = this->window.type;
+    param.wnd.info.window   = this->window.handle.window;
+#endif
+    return param;
+}
+
+VideoPreview::VideoPreview(int dev_id) 
+: devId(dev_id)
+{
+
+}
+
+bool VideoPreview::hasNative()
+{
+#if PJSUA_HAS_VIDEO
+    return(PJ2BOOL(pjsua_vid_preview_has_native(devId)));
+#else
+    return false;
+#endif
+}
+
+void VideoPreview::start(const VideoPreviewOpParam &param) throw(Error)
+{
+#if PJSUA_HAS_VIDEO
+    pjsua_vid_preview_param prm = param.toPj();
+    PJSUA2_CHECK_EXPR(pjsua_vid_preview_start(devId, &prm));
+#else
+    PJ_UNUSED_ARG(param);
+#endif
+}
+
+void VideoPreview::stop() throw(Error)
+{
+#if PJSUA_HAS_VIDEO
+    pjsua_vid_preview_stop(devId);
+#endif
+}
+
+VideoWindow VideoPreview::getVideoWindow()
+{
+#if PJSUA_HAS_VIDEO
+    return (VideoWindow(pjsua_vid_preview_get_win(devId)));
+#else
+    return (VideoWindow(PJSUA_INVALID_ID));
+#endif
+}
 
 ///////////////////////////////////////////////////////////////////////////////
