Support none multiple of 16 pixels width on android.

BUG=4522
R=magjed@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/44129004

Cr-Commit-Position: refs/heads/master@{#8977}
diff --git a/talk/app/webrtc/androidvideocapturer.cc b/talk/app/webrtc/androidvideocapturer.cc
index 6711b6e..8763f61 100644
--- a/talk/app/webrtc/androidvideocapturer.cc
+++ b/talk/app/webrtc/androidvideocapturer.cc
@@ -34,6 +34,11 @@
 #include "webrtc/base/timeutils.h"
 #include "webrtc/base/thread.h"
 
+static int RoundUp(int value, int alignment) {
+  DCHECK(value  > 0 && alignment > 0);
+  return ((value + (alignment - 1)) & ~(alignment - 1));
+}
+
 namespace webrtc {
 
 using cricket::WebRtcVideoFrame;
@@ -93,12 +98,14 @@
     if (!apply_rotation_ || captured_frame->rotation == kVideoRotation_0) {
       DCHECK(captured_frame->fourcc == cricket::FOURCC_YV12);
       const uint8_t* y_plane = static_cast<uint8_t*>(captured_frame_.data);
-      const int y_stride = captured_frame->width;
-      const uint8_t* v_plane = y_plane +
-          captured_frame->width * captured_frame->height;
-      const int uv_stride = (captured_frame->width + 1) / 2;
-      const int uv_height = (captured_frame->height + 1) / 2;
-      const uint8_t* u_plane = v_plane + uv_stride * uv_height;
+
+      // Android guarantee that the stride is a multiple of 16.
+      // http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29
+      const int y_stride = RoundUp(captured_frame->width, 16);
+      const int uv_stride = RoundUp(y_stride / 2, 16);
+      const uint8_t* v_plane = y_plane + y_stride * captured_frame->height;
+      const uint8_t* u_plane =
+          v_plane + uv_stride * captured_frame->height / 2;
 
       // Create a WrappedI420Buffer and bind the |no_longer_used| callback
       // to the static method ReturnFrame. The |delegate_| is bound as an
diff --git a/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java b/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java
index e650770..e2f67c5 100644
--- a/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java
+++ b/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java
@@ -28,6 +28,7 @@
 package org.webrtc;
 
 import static java.lang.Math.abs;
+import static java.lang.Math.ceil;
 
 import android.content.Context;
 import android.graphics.ImageFormat;
@@ -303,13 +304,6 @@
 
       List<Camera.Size> supportedSizes = parameters.getSupportedPreviewSizes();
       for (Camera.Size size : supportedSizes) {
-        if (size.width % 16 != 0) {
-          // If the width is not a multiple of 16, the frames received from the
-          // camera will have a stride != width when YV12 is used. Since we
-          // currently only support tightly packed images, we simply ignore
-          // those resolutions.
-          continue;
-        }
         formatList.add(new CaptureFormat(size.width, size.height,
             range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
             range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]));
@@ -660,8 +654,18 @@
         throw new RuntimeException("camera already set.");
 
       this.camera = camera;
-      int newframeSize =
-          width * height * ImageFormat.getBitsPerPixel(format) / 8;
+      int newframeSize = 0;
+      if (format == ImageFormat.YV12) {
+        int yStride   = (int) ceil(width / 16.0) * 16;
+        int uvStride  = (int) ceil( (yStride / 2) / 16.0) * 16;
+        int ySize     = yStride * height;
+        int uvSize    = uvStride * height / 2;
+        newframeSize  = ySize + uvSize * 2;
+      } else {
+        newframeSize  =
+            width * height * ImageFormat.getBitsPerPixel(format) / 8;
+      }
+
       int numberOfEnquedCameraBuffers = 0;
       if (newframeSize != frameSize) {
         // Create new frames and add to the camera.