From f4acf46c863f2d516b09b00b39608de7e506ac65 Mon Sep 17 00:00:00 2001 From: Per Date: Fri, 10 Apr 2015 16:45:22 +0200 Subject: [PATCH] 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} --- talk/app/webrtc/androidvideocapturer.cc | 19 +++++++++++----- .../src/org/webrtc/VideoCapturerAndroid.java | 22 +++++++++++-------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/talk/app/webrtc/androidvideocapturer.cc b/talk/app/webrtc/androidvideocapturer.cc index 6711b6ed0..8763f619b 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 @@ class AndroidVideoCapturer::FrameFactory : public cricket::VideoFrameFactory { if (!apply_rotation_ || captured_frame->rotation == kVideoRotation_0) { DCHECK(captured_frame->fourcc == cricket::FOURCC_YV12); const uint8_t* y_plane = static_cast(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 e65077063..e2f67c551 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 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba List 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 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba 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.