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.content.Context; | 7 import android.content.Context; |
8 import android.graphics.ImageFormat; | 8 import android.graphics.ImageFormat; |
9 | 9 |
10 import org.chromium.base.Log; | 10 import org.chromium.base.Log; |
11 | 11 |
12 import java.util.ArrayList; | 12 import java.util.ArrayList; |
13 import java.util.List; | 13 import java.util.List; |
14 | 14 |
15 /** | 15 /** |
16 * This class extends the VideoCaptureCamera base class for manipulating normal | 16 * This class extends the VideoCaptureCamera base class for manipulating normal |
17 * video capture devices in Android, including receiving copies of preview | 17 * video capture devices in Android, including receiving copies of preview |
18 * frames via Java-allocated buffers. It also includes class BuggyDeviceHack to | 18 * frames via Java-allocated buffers. It also includes class BuggyDeviceHack to |
19 * deal with troublesome devices. | 19 * deal with troublesome devices. |
20 **/ | 20 **/ |
21 @SuppressWarnings("deprecation") | 21 @SuppressWarnings("deprecation") |
22 public class VideoCaptureAndroid extends VideoCaptureCamera { | 22 public class VideoCaptureAndroid extends VideoCaptureCamera { |
23 | |
24 // Some devices don't support YV12 format correctly, even with JELLY_BEAN or | 23 // Some devices don't support YV12 format correctly, even with JELLY_BEAN or |
25 // newer OS. To work around the issues on those devices, we have to request | 24 // newer OS. To work around the issues on those devices, we have to request |
26 // NV21. This is supposed to be a temporary hack. | 25 // NV21. This is supposed to be a temporary hack. |
27 private static class BuggyDeviceHack { | 26 private static class BuggyDeviceHack { |
28 private static final String[] COLORSPACE_BUGGY_DEVICE_LIST = { | 27 private static final String[] COLORSPACE_BUGGY_DEVICE_LIST = { |
29 "SAMSUNG-SGH-I747", | 28 "SAMSUNG-SGH-I747", "ODROID-U2", |
30 "ODROID-U2", | 29 // See https://crbug.com/577435 for more info. |
31 // See https://crbug.com/577435 for more info. | 30 "XT1092", "XT1095", "XT1096", |
32 "XT1092", | |
33 "XT1095", | |
34 "XT1096", | |
35 }; | 31 }; |
36 | 32 |
37 static int getImageFormat() { | 33 static int getImageFormat() { |
38 for (String buggyDevice : COLORSPACE_BUGGY_DEVICE_LIST) { | 34 for (String buggyDevice : COLORSPACE_BUGGY_DEVICE_LIST) { |
39 if (buggyDevice.contentEquals(android.os.Build.MODEL)) { | 35 if (buggyDevice.contentEquals(android.os.Build.MODEL)) { |
40 return ImageFormat.NV21; | 36 return ImageFormat.NV21; |
41 } | 37 } |
42 } | 38 } |
43 return ImageFormat.YV12; | 39 return ImageFormat.YV12; |
44 } | 40 } |
(...skipping 11 matching lines...) Expand all Loading... |
56 if (VideoCaptureCamera.getCameraInfo(id) == null) { | 52 if (VideoCaptureCamera.getCameraInfo(id) == null) { |
57 return CaptureApiType.API_TYPE_UNKNOWN; | 53 return CaptureApiType.API_TYPE_UNKNOWN; |
58 } | 54 } |
59 return CaptureApiType.API1; | 55 return CaptureApiType.API1; |
60 } | 56 } |
61 | 57 |
62 static String getName(int id) { | 58 static String getName(int id) { |
63 android.hardware.Camera.CameraInfo cameraInfo = VideoCaptureCamera.getCa
meraInfo(id); | 59 android.hardware.Camera.CameraInfo cameraInfo = VideoCaptureCamera.getCa
meraInfo(id); |
64 if (cameraInfo == null) return null; | 60 if (cameraInfo == null) return null; |
65 | 61 |
66 return "camera " + id + ", facing " + (cameraInfo.facing | 62 return "camera " + id + ", facing " |
67 == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? "fro
nt" : "back"); | 63 + (cameraInfo.facing == android.hardware.Camera.CameraInfo.CAMER
A_FACING_FRONT |
| 64 ? "front" |
| 65 : "back"); |
68 } | 66 } |
69 | 67 |
70 static VideoCaptureFormat[] getDeviceSupportedFormats(int id) { | 68 static VideoCaptureFormat[] getDeviceSupportedFormats(int id) { |
71 android.hardware.Camera camera; | 69 android.hardware.Camera camera; |
72 try { | 70 try { |
73 camera = android.hardware.Camera.open(id); | 71 camera = android.hardware.Camera.open(id); |
74 } catch (RuntimeException ex) { | 72 } catch (RuntimeException ex) { |
75 Log.e(TAG, "Camera.open: ", ex); | 73 Log.e(TAG, "Camera.open: ", ex); |
76 return null; | 74 return null; |
77 } | 75 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 for (int[] fpsRange : listFpsRange) { | 108 for (int[] fpsRange : listFpsRange) { |
111 List<android.hardware.Camera.Size> supportedSizes = | 109 List<android.hardware.Camera.Size> supportedSizes = |
112 parameters.getSupportedPreviewSizes(); | 110 parameters.getSupportedPreviewSizes(); |
113 if (supportedSizes == null) { | 111 if (supportedSizes == null) { |
114 supportedSizes = new ArrayList<android.hardware.Camera.Size>
(); | 112 supportedSizes = new ArrayList<android.hardware.Camera.Size>
(); |
115 } | 113 } |
116 if (supportedSizes.size() == 0) { | 114 if (supportedSizes.size() == 0) { |
117 supportedSizes.add(camera.new Size(0, 0)); | 115 supportedSizes.add(camera.new Size(0, 0)); |
118 } | 116 } |
119 for (android.hardware.Camera.Size size : supportedSizes) { | 117 for (android.hardware.Camera.Size size : supportedSizes) { |
120 formatList.add(new VideoCaptureFormat(size.width, | 118 formatList.add(new VideoCaptureFormat( |
121 size.height, | 119 size.width, size.height, (fpsRange[1] + 999) / 1000,
pixelFormat)); |
122 (fpsRange[1] + 999) / 1000, | |
123 pixelFormat)); | |
124 } | 120 } |
125 } | 121 } |
126 } | 122 } |
127 camera.release(); | 123 camera.release(); |
128 return formatList.toArray(new VideoCaptureFormat[formatList.size()]); | 124 return formatList.toArray(new VideoCaptureFormat[formatList.size()]); |
129 } | 125 } |
130 | 126 |
131 VideoCaptureAndroid(Context context, | 127 VideoCaptureAndroid(Context context, int id, long nativeVideoCaptureDeviceAn
droid) { |
132 int id, | |
133 long nativeVideoCaptureDeviceAndroid) { | |
134 super(context, id, nativeVideoCaptureDeviceAndroid); | 128 super(context, id, nativeVideoCaptureDeviceAndroid); |
135 } | 129 } |
136 | 130 |
137 @Override | 131 @Override |
138 protected void setCaptureParameters( | 132 protected void setCaptureParameters(int width, int height, int frameRate, |
139 int width, | |
140 int height, | |
141 int frameRate, | |
142 android.hardware.Camera.Parameters cameraParameters) { | 133 android.hardware.Camera.Parameters cameraParameters) { |
143 mCaptureFormat = new VideoCaptureFormat( | 134 mCaptureFormat = |
144 width, height, frameRate, BuggyDeviceHack.getImageFormat()); | 135 new VideoCaptureFormat(width, height, frameRate, BuggyDeviceHack
.getImageFormat()); |
145 } | 136 } |
146 | 137 |
147 @Override | 138 @Override |
148 protected void allocateBuffers() { | 139 protected void allocateBuffers() { |
149 mExpectedFrameSize = mCaptureFormat.mWidth * mCaptureFormat.mHeight | 140 mExpectedFrameSize = mCaptureFormat.mWidth * mCaptureFormat.mHeight |
150 * ImageFormat.getBitsPerPixel(mCaptureFormat.mPixelFormat) / 8; | 141 * ImageFormat.getBitsPerPixel(mCaptureFormat.mPixelFormat) / 8; |
151 for (int i = 0; i < NUM_CAPTURE_BUFFERS; i++) { | 142 for (int i = 0; i < NUM_CAPTURE_BUFFERS; i++) { |
152 byte[] buffer = new byte[mExpectedFrameSize]; | 143 byte[] buffer = new byte[mExpectedFrameSize]; |
153 mCamera.addCallbackBuffer(buffer); | 144 mCamera.addCallbackBuffer(buffer); |
154 } | 145 } |
155 } | 146 } |
156 | 147 |
157 @Override | 148 @Override |
158 protected void setPreviewCallback(android.hardware.Camera.PreviewCallback cb
) { | 149 protected void setPreviewCallback(android.hardware.Camera.PreviewCallback cb
) { |
159 mCamera.setPreviewCallbackWithBuffer(cb); | 150 mCamera.setPreviewCallbackWithBuffer(cb); |
160 } | 151 } |
161 | 152 |
162 @Override | 153 @Override |
163 public void onPreviewFrame(byte[] data, android.hardware.Camera camera) { | 154 public void onPreviewFrame(byte[] data, android.hardware.Camera camera) { |
164 mPreviewBufferLock.lock(); | 155 mPreviewBufferLock.lock(); |
165 try { | 156 try { |
166 if (!mIsRunning) { | 157 if (!mIsRunning) { |
167 return; | 158 return; |
168 } | 159 } |
169 if (data.length == mExpectedFrameSize) { | 160 if (data.length == mExpectedFrameSize) { |
170 nativeOnFrameAvailable(mNativeVideoCaptureDeviceAndroid, | 161 nativeOnFrameAvailable(mNativeVideoCaptureDeviceAndroid, data, m
ExpectedFrameSize, |
171 data, mExpectedFrameSize, getCameraRotation()); | 162 getCameraRotation()); |
172 } | 163 } |
173 } finally { | 164 } finally { |
174 mPreviewBufferLock.unlock(); | 165 mPreviewBufferLock.unlock(); |
175 if (camera != null) { | 166 if (camera != null) { |
176 camera.addCallbackBuffer(data); | 167 camera.addCallbackBuffer(data); |
177 } | 168 } |
178 } | 169 } |
179 } | 170 } |
180 | 171 |
181 // TODO(wjia): investigate whether reading from texture could give better | 172 // TODO(wjia): investigate whether reading from texture could give better |
182 // performance and frame rate, using onFrameAvailable(). | 173 // performance and frame rate, using onFrameAvailable(). |
183 } | 174 } |
OLD | NEW |