OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.media; | 5 package org.chromium.media; |
6 | 6 |
7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.graphics.ImageFormat; | 9 import android.graphics.ImageFormat; |
10 import android.graphics.Rect; | 10 import android.graphics.Rect; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 | 120 |
121 if (reader.getWidth() != image.getWidth() | 121 if (reader.getWidth() != image.getWidth() |
122 || reader.getHeight() != image.getHeight()) { | 122 || reader.getHeight() != image.getHeight()) { |
123 nativeOnError(mNativeVideoCaptureDeviceAndroid, "ImageReader
size (" | 123 nativeOnError(mNativeVideoCaptureDeviceAndroid, "ImageReader
size (" |
124 + reader.getWidth() + "x" + reader.getHeight() | 124 + reader.getWidth() + "x" + reader.getHeight() |
125 + ") did not match Image size (" + image.getWidth()
+ "x" | 125 + ") did not match Image size (" + image.getWidth()
+ "x" |
126 + image.getHeight() + ")"); | 126 + image.getHeight() + ")"); |
127 throw new IllegalStateException(); | 127 throw new IllegalStateException(); |
128 } | 128 } |
129 | 129 |
130 readImageIntoBuffer(image, mCapturedData); | 130 nativeOnI420FrameAvailable(mNativeVideoCaptureDeviceAndroid, |
131 nativeOnFrameAvailable(mNativeVideoCaptureDeviceAndroid, mCaptur
edData, | 131 image.getPlanes()[0].getBuffer(), image.getPlanes()[0].g
etRowStride(), |
132 mCapturedData.length, getCameraRotation()); | 132 image.getPlanes()[1].getBuffer(), image.getPlanes()[2].g
etBuffer(), |
| 133 image.getPlanes()[1].getRowStride(), image.getPlanes()[1
].getPixelStride(), |
| 134 image.getWidth(), image.getHeight(), getCameraRotation()
); |
133 } catch (IllegalStateException ex) { | 135 } catch (IllegalStateException ex) { |
134 Log.e(TAG, "acquireLatestImage():", ex); | 136 Log.e(TAG, "acquireLatestImage():", ex); |
135 } | 137 } |
136 } | 138 } |
137 }; | 139 }; |
138 | 140 |
139 // Inner class to extend a Photo Session state change listener. | 141 // Inner class to extend a Photo Session state change listener. |
140 // Error paths must signal notifyTakePhotoError(). | 142 // Error paths must signal notifyTakePhotoError(). |
141 private class CrPhotoSessionListener extends CameraCaptureSession.StateCallb
ack { | 143 private class CrPhotoSessionListener extends CameraCaptureSession.StateCallb
ack { |
142 private final CaptureRequest mPhotoRequest; | 144 private final CaptureRequest mPhotoRequest; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 220 } |
219 }; | 221 }; |
220 | 222 |
221 private static final double kNanoSecondsToFps = 1.0E-9; | 223 private static final double kNanoSecondsToFps = 1.0E-9; |
222 private static final String TAG = "VideoCapture"; | 224 private static final String TAG = "VideoCapture"; |
223 | 225 |
224 private static enum CameraState { OPENING, CONFIGURING, STARTED, STOPPED } | 226 private static enum CameraState { OPENING, CONFIGURING, STARTED, STOPPED } |
225 | 227 |
226 private final Object mCameraStateLock = new Object(); | 228 private final Object mCameraStateLock = new Object(); |
227 | 229 |
228 private byte[] mCapturedData; | |
229 | |
230 private CameraDevice mCameraDevice; | 230 private CameraDevice mCameraDevice; |
231 private CameraCaptureSession mPreviewSession; | 231 private CameraCaptureSession mPreviewSession; |
232 private CaptureRequest mPreviewRequest; | 232 private CaptureRequest mPreviewRequest; |
233 | 233 |
234 private CameraState mCameraState = CameraState.STOPPED; | 234 private CameraState mCameraState = CameraState.STOPPED; |
235 private final float mMaxZoom; | 235 private final float mMaxZoom; |
236 private Rect mCropRect = new Rect(); | 236 private Rect mCropRect = new Rect(); |
237 | 237 |
238 // Service function to grab CameraCharacteristics and handle exceptions. | 238 // Service function to grab CameraCharacteristics and handle exceptions. |
239 private static CameraCharacteristics getCameraCharacteristics(Context appCon
text, int id) { | 239 private static CameraCharacteristics getCameraCharacteristics(Context appCon
text, int id) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 try { | 305 try { |
306 mCameraDevice.createCaptureSession(surfaceList, captureSessionListen
er, null); | 306 mCameraDevice.createCaptureSession(surfaceList, captureSessionListen
er, null); |
307 } catch (CameraAccessException | IllegalArgumentException | SecurityExce
ption ex) { | 307 } catch (CameraAccessException | IllegalArgumentException | SecurityExce
ption ex) { |
308 Log.e(TAG, "createCaptureSession: ", ex); | 308 Log.e(TAG, "createCaptureSession: ", ex); |
309 return false; | 309 return false; |
310 } | 310 } |
311 // Wait for trigger on CrPreviewSessionListener.onConfigured(); | 311 // Wait for trigger on CrPreviewSessionListener.onConfigured(); |
312 return true; | 312 return true; |
313 } | 313 } |
314 | 314 |
315 private static void readImageIntoBuffer(Image image, byte[] data) { | |
316 final int imageWidth = image.getWidth(); | |
317 final int imageHeight = image.getHeight(); | |
318 final Image.Plane[] planes = image.getPlanes(); | |
319 | |
320 int offset = 0; | |
321 for (int plane = 0; plane < planes.length; ++plane) { | |
322 final ByteBuffer buffer = planes[plane].getBuffer(); | |
323 final int rowStride = planes[plane].getRowStride(); | |
324 // Experimentally, U and V planes have |pixelStride| = 2, which | |
325 // essentially means they are packed. That's silly, because we are | |
326 // forced to unpack here. | |
327 final int pixelStride = planes[plane].getPixelStride(); | |
328 final int planeWidth = (plane == 0) ? imageWidth : imageWidth / 2; | |
329 final int planeHeight = (plane == 0) ? imageHeight : imageHeight / 2
; | |
330 | |
331 if (pixelStride == 1 && rowStride == planeWidth) { | |
332 // Copy whole plane from buffer into |data| at once. | |
333 buffer.get(data, offset, planeWidth * planeHeight); | |
334 offset += planeWidth * planeHeight; | |
335 } else { | |
336 // Copy pixels one by one respecting pixelStride and rowStride. | |
337 byte[] rowData = new byte[rowStride]; | |
338 for (int row = 0; row < planeHeight - 1; ++row) { | |
339 buffer.get(rowData, 0, rowStride); | |
340 for (int col = 0; col < planeWidth; ++col) { | |
341 data[offset++] = rowData[col * pixelStride]; | |
342 } | |
343 } | |
344 | |
345 // Last row is special in some devices and may not contain the f
ull | |
346 // |rowStride| bytes of data. See http://crbug.com/458701 and | |
347 // http://developer.android.com/reference/android/media/Image.Pl
ane.html#getBuffer() | |
348 buffer.get(rowData, 0, Math.min(rowStride, buffer.remaining())); | |
349 for (int col = 0; col < planeWidth; ++col) { | |
350 data[offset++] = rowData[col * pixelStride]; | |
351 } | |
352 } | |
353 } | |
354 } | |
355 | |
356 private void changeCameraStateAndNotify(CameraState state) { | 315 private void changeCameraStateAndNotify(CameraState state) { |
357 synchronized (mCameraStateLock) { | 316 synchronized (mCameraStateLock) { |
358 mCameraState = state; | 317 mCameraState = state; |
359 mCameraStateLock.notifyAll(); | 318 mCameraStateLock.notifyAll(); |
360 } | 319 } |
361 } | 320 } |
362 | 321 |
363 static boolean isLegacyDevice(Context appContext, int id) { | 322 static boolean isLegacyDevice(Context appContext, int id) { |
364 final CameraCharacteristics cameraCharacteristics = | 323 final CameraCharacteristics cameraCharacteristics = |
365 getCameraCharacteristics(appContext, id); | 324 getCameraCharacteristics(appContext, id); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 if (minDiff == Integer.MAX_VALUE) { | 449 if (minDiff == Integer.MAX_VALUE) { |
491 Log.e(TAG, "No supported resolutions."); | 450 Log.e(TAG, "No supported resolutions."); |
492 return false; | 451 return false; |
493 } | 452 } |
494 Log.d(TAG, "allocate: matched (%d x %d)", closestSupportedSize.getWidth(
), | 453 Log.d(TAG, "allocate: matched (%d x %d)", closestSupportedSize.getWidth(
), |
495 closestSupportedSize.getHeight()); | 454 closestSupportedSize.getHeight()); |
496 | 455 |
497 // |mCaptureFormat| is also used to configure the ImageReader. | 456 // |mCaptureFormat| is also used to configure the ImageReader. |
498 mCaptureFormat = new VideoCaptureFormat(closestSupportedSize.getWidth(), | 457 mCaptureFormat = new VideoCaptureFormat(closestSupportedSize.getWidth(), |
499 closestSupportedSize.getHeight(), frameRate, ImageFormat.YUV_420
_888); | 458 closestSupportedSize.getHeight(), frameRate, ImageFormat.YUV_420
_888); |
500 int expectedFrameSize = mCaptureFormat.mWidth * mCaptureFormat.mHeight | |
501 * ImageFormat.getBitsPerPixel(mCaptureFormat.mPixelFormat) / 8; | |
502 mCapturedData = new byte[expectedFrameSize]; | |
503 mCameraNativeOrientation = | 459 mCameraNativeOrientation = |
504 cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATI
ON); | 460 cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATI
ON); |
505 // TODO(mcasas): The following line is correct for N5 with prerelease Bu
ild, | 461 // TODO(mcasas): The following line is correct for N5 with prerelease Bu
ild, |
506 // but NOT for N7 with a dev Build. Figure out which one to support. | 462 // but NOT for N7 with a dev Build. Figure out which one to support. |
507 mInvertDeviceOrientationReadings = | 463 mInvertDeviceOrientationReadings = |
508 cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) | 464 cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) |
509 == CameraCharacteristics.LENS_FACING_BACK; | 465 == CameraCharacteristics.LENS_FACING_BACK; |
510 return true; | 466 return true; |
511 } | 467 } |
512 | 468 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 return false; | 607 return false; |
652 } | 608 } |
653 return true; | 609 return true; |
654 } | 610 } |
655 | 611 |
656 @Override | 612 @Override |
657 public void deallocate() { | 613 public void deallocate() { |
658 Log.d(TAG, "deallocate"); | 614 Log.d(TAG, "deallocate"); |
659 } | 615 } |
660 } | 616 } |
OLD | NEW |