Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: media/base/android/java/src/org/chromium/media/VideoCaptureCamera.java

Issue 1705333003: Move VideoCapture* files from media/base/android/... to media/capture/video/android/java/... (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: reuploaded w --similarity=75 Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.media;
6
7 import android.annotation.TargetApi;
8 import android.content.Context;
9 import android.graphics.SurfaceTexture;
10 import android.opengl.GLES20;
11 import android.os.Build;
12
13 import org.chromium.base.Log;
14 import org.chromium.base.annotations.JNINamespace;
15
16 import java.io.IOException;
17 import java.util.List;
18 import java.util.concurrent.locks.ReentrantLock;
19
20 /**
21 * Video Capture Device extension of VideoCapture to provide common functionalit y
22 * for capture using android.hardware.Camera API (deprecated in API 21). Normal
23 * Android and Tango devices are extensions of this class.
24 **/
25 @JNINamespace("media")
26 @SuppressWarnings("deprecation")
27 //TODO: is this class only used on ICS MR1 (or some later version) and above?
28 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
29 public abstract class VideoCaptureCamera extends VideoCapture
30 implements android.hardware.Camera.PreviewCallback {
31
32 protected android.hardware.Camera mCamera;
33 // Lock to mutually exclude execution of OnPreviewFrame() and {start/stop}Ca pture().
34 protected ReentrantLock mPreviewBufferLock = new ReentrantLock();
35 // True when native code has started capture.
36 protected boolean mIsRunning = false;
37
38 protected int[] mGlTextures = null;
39 protected SurfaceTexture mSurfaceTexture = null;
40 protected static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
41
42 private static final String TAG = "cr.media";
43
44 protected static android.hardware.Camera.CameraInfo getCameraInfo(int id) {
45 android.hardware.Camera.CameraInfo cameraInfo =
46 new android.hardware.Camera.CameraInfo();
47 try {
48 android.hardware.Camera.getCameraInfo(id, cameraInfo);
49 } catch (RuntimeException ex) {
50 Log.e(TAG, "getCameraInfo: Camera.getCameraInfo: " + ex);
51 return null;
52 }
53 return cameraInfo;
54 }
55
56 protected static android.hardware.Camera.Parameters getCameraParameters(
57 android.hardware.Camera camera) {
58 android.hardware.Camera.Parameters parameters;
59 try {
60 parameters = camera.getParameters();
61 } catch (RuntimeException ex) {
62 Log.e(TAG, "getCameraParameters: android.hardware.Camera.getParamete rs: " + ex);
63 if (camera != null) camera.release();
64 return null;
65 }
66 return parameters;
67 }
68
69 VideoCaptureCamera(Context context,
70 int id,
71 long nativeVideoCaptureDeviceAndroid) {
72 super(context, id, nativeVideoCaptureDeviceAndroid);
73 }
74
75 @Override
76 public boolean allocate(int width, int height, int frameRate) {
77 Log.d(TAG, "allocate: requested (%d x %d) @%dfps", width, height, frameR ate);
78 try {
79 mCamera = android.hardware.Camera.open(mId);
80 } catch (RuntimeException ex) {
81 Log.e(TAG, "allocate: Camera.open: " + ex);
82 return false;
83 }
84
85 android.hardware.Camera.CameraInfo cameraInfo = VideoCaptureCamera.getCa meraInfo(mId);
86 if (cameraInfo == null) {
87 mCamera.release();
88 mCamera = null;
89 return false;
90 }
91 mCameraNativeOrientation = cameraInfo.orientation;
92 // For Camera API, the readings of back-facing camera need to be inverte d.
93 mInvertDeviceOrientationReadings =
94 (cameraInfo.facing == android.hardware.Camera.CameraInfo.CAMERA_ FACING_BACK);
95 Log.d(TAG, "allocate: Rotation dev=%d, cam=%d, facing back? %s", getDevi ceRotation(),
96 mCameraNativeOrientation, mInvertDeviceOrientationReadings);
97
98 android.hardware.Camera.Parameters parameters = getCameraParameters(mCam era);
99 if (parameters == null) {
100 mCamera = null;
101 return false;
102 }
103
104 // getSupportedPreviewFpsRange() returns a List with at least one
105 // element, but when camera is in bad state, it can return null pointer.
106 List<int[]> listFpsRange = parameters.getSupportedPreviewFpsRange();
107 if (listFpsRange == null || listFpsRange.size() == 0) {
108 Log.e(TAG, "allocate: no fps range found");
109 return false;
110 }
111 // API fps ranges are scaled up x1000 to avoid floating point.
112 int frameRateScaled = frameRate * 1000;
113 // Use the first range as the default chosen range.
114 int[] chosenFpsRange = listFpsRange.get(0);
115 int frameRateNearest = Math.abs(frameRateScaled - chosenFpsRange[0])
116 < Math.abs(frameRateScaled - chosenFpsRange[1])
117 ? chosenFpsRange[0] : chosenFpsRange[1];
118 int chosenFrameRate = (frameRateNearest + 999) / 1000;
119 int fpsRangeSize = Integer.MAX_VALUE;
120 for (int[] fpsRange : listFpsRange) {
121 if (fpsRange[0] <= frameRateScaled && frameRateScaled <= fpsRange[1]
122 && (fpsRange[1] - fpsRange[0]) <= fpsRangeSize) {
123 chosenFpsRange = fpsRange;
124 chosenFrameRate = frameRate;
125 fpsRangeSize = fpsRange[1] - fpsRange[0];
126 }
127 }
128 Log.d(TAG, "allocate: fps set to %d, [%d-%d]", chosenFrameRate,
129 chosenFpsRange[0], chosenFpsRange[1]);
130
131 // Calculate size.
132 List<android.hardware.Camera.Size> listCameraSize =
133 parameters.getSupportedPreviewSizes();
134 int minDiff = Integer.MAX_VALUE;
135 int matchedWidth = width;
136 int matchedHeight = height;
137 for (android.hardware.Camera.Size size : listCameraSize) {
138 int diff = Math.abs(size.width - width)
139 + Math.abs(size.height - height);
140 Log.d(TAG, "allocate: supported (%d, %d), diff=%d", size.width, size .height, diff);
141 // TODO(wjia): Remove this hack (forcing width to be multiple
142 // of 32) by supporting stride in video frame buffer.
143 // Right now, VideoCaptureController requires compact YV12
144 // (i.e., with no padding).
145 if (diff < minDiff && (size.width % 32 == 0)) {
146 minDiff = diff;
147 matchedWidth = size.width;
148 matchedHeight = size.height;
149 }
150 }
151 if (minDiff == Integer.MAX_VALUE) {
152 Log.e(TAG, "allocate: can not find a multiple-of-32 resolution");
153 return false;
154 }
155 Log.d(TAG, "allocate: matched (%d x %d)", matchedWidth, matchedHeight);
156
157 if (parameters.isVideoStabilizationSupported()) {
158 Log.d(TAG, "Image stabilization supported, currently: "
159 + parameters.getVideoStabilization() + ", setting it.");
160 parameters.setVideoStabilization(true);
161 } else {
162 Log.d(TAG, "Image stabilization not supported.");
163 }
164
165 if (parameters.getSupportedFocusModes().contains(
166 android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
167 parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MOD E_CONTINUOUS_VIDEO);
168 } else {
169 Log.d(TAG, "Continuous focus mode not supported.");
170 }
171
172 setCaptureParameters(matchedWidth, matchedHeight, chosenFrameRate, param eters);
173 parameters.setPictureSize(matchedWidth, matchedHeight);
174 parameters.setPreviewSize(matchedWidth, matchedHeight);
175 parameters.setPreviewFpsRange(chosenFpsRange[0], chosenFpsRange[1]);
176 parameters.setPreviewFormat(mCaptureFormat.mPixelFormat);
177 try {
178 mCamera.setParameters(parameters);
179 } catch (RuntimeException ex) {
180 Log.e(TAG, "setParameters: " + ex);
181 return false;
182 }
183
184 // Set SurfaceTexture. Android Capture needs a SurfaceTexture even if
185 // it is not going to be used.
186 mGlTextures = new int[1];
187 // Generate one texture pointer and bind it as an external texture.
188 GLES20.glGenTextures(1, mGlTextures, 0);
189 GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mGlTextures[0]);
190 // No mip-mapping with camera source.
191 GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
192 GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
193 GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
194 GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
195 // Clamp to edge is only option.
196 GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
197 GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
198 GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
199 GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
200
201 mSurfaceTexture = new SurfaceTexture(mGlTextures[0]);
202 mSurfaceTexture.setOnFrameAvailableListener(null);
203 try {
204 mCamera.setPreviewTexture(mSurfaceTexture);
205 } catch (IOException ex) {
206 Log.e(TAG, "allocate: " + ex);
207 return false;
208 }
209
210 allocateBuffers();
211 return true;
212 }
213
214 @Override
215 public boolean startCapture() {
216 if (mCamera == null) {
217 Log.e(TAG, "startCapture: camera is null");
218 return false;
219 }
220
221 mPreviewBufferLock.lock();
222 try {
223 if (mIsRunning) {
224 return true;
225 }
226 mIsRunning = true;
227 } finally {
228 mPreviewBufferLock.unlock();
229 }
230 setPreviewCallback(this);
231 try {
232 mCamera.startPreview();
233 } catch (RuntimeException ex) {
234 Log.e(TAG, "startCapture: Camera.startPreview: " + ex);
235 return false;
236 }
237 return true;
238 }
239
240 @Override
241 public boolean stopCapture() {
242 if (mCamera == null) {
243 Log.e(TAG, "stopCapture: camera is null");
244 return true;
245 }
246
247 mPreviewBufferLock.lock();
248 try {
249 if (!mIsRunning) {
250 return true;
251 }
252 mIsRunning = false;
253 } finally {
254 mPreviewBufferLock.unlock();
255 }
256
257 mCamera.stopPreview();
258 setPreviewCallback(null);
259 return true;
260 }
261
262 @Override
263 public void deallocate() {
264 if (mCamera == null) return;
265
266 stopCapture();
267 try {
268 mCamera.setPreviewTexture(null);
269 if (mGlTextures != null) GLES20.glDeleteTextures(1, mGlTextures, 0);
270 mCaptureFormat = null;
271 mCamera.release();
272 mCamera = null;
273 } catch (IOException ex) {
274 Log.e(TAG, "deallocate: failed to deallocate camera, " + ex);
275 return;
276 }
277 }
278
279 // Local hook to allow derived classes to configure and plug capture
280 // buffers if needed.
281 abstract void allocateBuffers();
282
283 // Local hook to allow derived classes to fill capture format and modify
284 // camera parameters as they see fit.
285 abstract void setCaptureParameters(
286 int width,
287 int height,
288 int frameRate,
289 android.hardware.Camera.Parameters cameraParameters);
290
291 // Local method to be overriden with the particular setPreviewCallback to be
292 // used in the implementations.
293 abstract void setPreviewCallback(android.hardware.Camera.PreviewCallback cb) ;
294 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698