Index: pjproject/trunk/pjmedia/src/pjmedia-videodev/android_dev.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-videodev/android_dev.c	(revision 5003)
+++ pjproject/trunk/pjmedia/src/pjmedia-videodev/android_dev.c	(revision 5138)
@@ -17,4 +17,5 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include "util.h"
 #include <pjmedia-videodev/videodev_imp.h>
 #include <pj/assert.h>
@@ -39,4 +40,8 @@
 #define ALIGN16(x)		((((x)+15) >> 4) << 4)
 
+/* Define whether we should maintain the aspect ratio when rotating the image.
+ * For more details, please refer to util.h.
+ */
+#define MAINTAIN_ASPECT_RATIO 	PJ_TRUE
 
 /* Format map info */
@@ -119,4 +124,8 @@
     /** NV21/YV12 -> I420 Conversion buffer  */
     pj_uint8_t		   *convert_buf;
+    pjmedia_rect_size	    cam_size;
+    
+    /** Converter to rotate frame  */
+    pjmedia_vid_dev_conv    conv;
     
     /** Frame format param for NV21/YV12 -> I420 conversion */
@@ -512,5 +521,6 @@
 	vdi->dir = PJMEDIA_DIR_CAPTURE;
 	vdi->has_callback = PJ_TRUE;
-	vdi->caps = PJMEDIA_VID_DEV_CAP_SWITCH;
+	vdi->caps = PJMEDIA_VID_DEV_CAP_SWITCH |
+		    PJMEDIA_VID_DEV_CAP_ORIENTATION;
 
 	/* Set driver & name info */
@@ -579,10 +589,17 @@
 
 		for (k = 0; k < adi->sup_size_cnt &&
-			    vdi->fmt_cnt < max_fmt_cnt; k++)
+			    vdi->fmt_cnt < max_fmt_cnt-1; k++)
 		{
+		    /* Landscape video */
 		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
 					      fmt,
 					      adi->sup_size[k].w,
 					      adi->sup_size[k].h,
+					      DEFAULT_FPS, 1);
+		    /* Portrait video */
+		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
+					      fmt,
+					      adi->sup_size[k].h,
+					      adi->sup_size[k].w,
 					      DEFAULT_FPS, 1);
 		}
@@ -599,5 +616,5 @@
 		adi->forced_i420 = PJ_TRUE;
 		for (k = 0; k < adi->sup_size_cnt &&
-			    vdi->fmt_cnt < max_fmt_cnt; k++)
+			    vdi->fmt_cnt < max_fmt_cnt-1; k++)
 		{
 		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
@@ -605,4 +622,9 @@
 					      adi->sup_size[k].w,
 					      adi->sup_size[k].h,
+					      DEFAULT_FPS, 1);
+		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
+					      PJMEDIA_FORMAT_I420,
+					      adi->sup_size[k].h,
+					      adi->sup_size[k].w,
 					      DEFAULT_FPS, 1);
 		}
@@ -637,5 +659,5 @@
     for (i = 0; i < f->dev_count; i++) {
 	and_dev_info *adi = &f->dev_info[i];
-	char tmp_str[1024], *p;
+	char tmp_str[2048], *p;
 	int j, plen, slen;
 	PJ_LOG(4, (THIS_FILE, "%2d: %s", i, f->dev_info[i].info.name));
@@ -793,8 +815,10 @@
 
     /* Instantiate PjCamera */
+    strm->cam_size.w = (vfd->size.w > vfd->size.h? vfd->size.w: vfd->size.h);
+    strm->cam_size.h = (vfd->size.w > vfd->size.h? vfd->size.h: vfd->size.w);
     jcam = (*jni_env)->NewObject(jni_env, jobjs.cam.cls, jobjs.cam.m_init,
 				 adi->dev_idx,		/* idx */
-				 vfd->size.w,		/* w */
-				 vfd->size.h,		/* h */
+				 strm->cam_size.w,	/* w */
+				 strm->cam_size.h,	/* h */
 				 and_fmt,		/* fmt */
 				 vfd->fps.num*1000/
@@ -814,4 +838,17 @@
         status = PJMEDIA_EVID_SYSERR;
 	goto on_return;
+    }
+    
+    /* Video orientation.
+     * If we send in portrait, we need to set up orientation converter
+     * as well.
+     */
+    if ((param->flags & PJMEDIA_VID_DEV_CAP_ORIENTATION) ||
+        (vfd->size.h > vfd->size.w))
+    {
+        if (param->orient == PJMEDIA_ORIENT_UNKNOWN)
+    	    param->orient = PJMEDIA_ORIENT_NATURAL;
+        and_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_ORIENTATION,
+    		           &param->orient);
     }
 
@@ -922,4 +959,38 @@
 	}
 
+        case PJMEDIA_VID_DEV_CAP_ORIENTATION:
+        {
+            pjmedia_orient orient = *(pjmedia_orient *)pval;
+
+	    pj_assert(orient >= PJMEDIA_ORIENT_UNKNOWN &&
+	              orient <= PJMEDIA_ORIENT_ROTATE_270DEG);
+
+            if (orient == PJMEDIA_ORIENT_UNKNOWN)
+                return PJ_EINVAL;
+
+            pj_memcpy(&strm->param.orient, pval,
+                      sizeof(strm->param.orient));
+
+	    if (!strm->conv.conv) {
+	        status = pjmedia_vid_dev_conv_create_converter(
+	        				 &strm->conv, strm->pool,
+	        		        	 &strm->param.fmt,
+	        		        	 strm->cam_size,
+	        		        	 strm->param.fmt.det.vid.size,
+	        		        	 PJ_TRUE,
+	        		        	 MAINTAIN_ASPECT_RATIO);
+	    	
+	    	if (status != PJ_SUCCESS)
+	    	    return status;
+	    }
+	    
+	    pjmedia_vid_dev_conv_set_rotation(&strm->conv, strm->param.orient);
+	    
+	    PJ_LOG(4, (THIS_FILE, "Video capture orientation set to %d",
+	    			  strm->param.orient));
+
+            break;
+        }
+
 	default:
 	    status = PJMEDIA_EVID_INVCAP;
@@ -1006,4 +1077,6 @@
     jni_detach_env(with_attach);
     
+    pjmedia_vid_dev_conv_destroy_converter(&strm->conv);
+    
     if (strm->pool)
 	pj_pool_release(strm->pool);
@@ -1021,4 +1094,6 @@
     pjmedia_frame f;
     pj_uint8_t *Y, *U, *V;
+    pj_status_t status; 
+    void *frame_buf, *data_buf;     
 
     strm->frame_ts.u64 += strm->ts_inc;
@@ -1040,5 +1115,5 @@
     f.size = length;
     f.timestamp.u64 = strm->frame_ts.u64;
-    f.buf = (*env)->GetByteArrayElements(env, data, 0);
+    f.buf = data_buf = (*env)->GetByteArrayElements(env, data, 0);
 
     Y = (pj_uint8_t*)f.buf;
@@ -1116,7 +1191,14 @@
 	}
     }
+    
+    status = pjmedia_vid_dev_conv_resize_and_rotate(&strm->conv, 
+    						    f.buf,
+    				       		    &frame_buf);
+    if (status == PJ_SUCCESS) {
+        f.buf = frame_buf;
+    }
 
     (*strm->vid_cb.capture_cb)(&strm->base, strm->user_data, &f);
-    (*env)->ReleaseByteArrayElements(env, data, f.buf, JNI_ABORT);
+    (*env)->ReleaseByteArrayElements(env, data, data_buf, JNI_ABORT);
 }
 
