OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
ck { | 72 public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
ck { |
73 private final static String TAG = "VideoCapturerAndroid"; | 73 private final static String TAG = "VideoCapturerAndroid"; |
74 private final static int CAMERA_OBSERVER_PERIOD_MS = 5000; | 74 private final static int CAMERA_OBSERVER_PERIOD_MS = 5000; |
75 | 75 |
76 private Camera camera; // Only non-null while capturing. | 76 private Camera camera; // Only non-null while capturing. |
77 private CameraThread cameraThread; | 77 private CameraThread cameraThread; |
78 private Handler cameraThreadHandler; | 78 private Handler cameraThreadHandler; |
79 private Context applicationContext; | 79 private Context applicationContext; |
80 private int id; | 80 private int id; |
81 private Camera.CameraInfo info; | 81 private Camera.CameraInfo info; |
82 private SurfaceTexture cameraSurfaceTexture; | |
83 private int cameraGlTexture = 0; | 82 private int cameraGlTexture = 0; |
84 private final FramePool videoBuffers = new FramePool(); | 83 private final FramePool videoBuffers = new FramePool(); |
85 // Remember the requested format in case we want to switch cameras. | 84 // Remember the requested format in case we want to switch cameras. |
86 private int requestedWidth; | 85 private int requestedWidth; |
87 private int requestedHeight; | 86 private int requestedHeight; |
88 private int requestedFramerate; | 87 private int requestedFramerate; |
89 // The capture format will be the closest supported format to the requested fo
rmat. | 88 // The capture format will be the closest supported format to the requested fo
rmat. |
90 private CaptureFormat captureFormat; | 89 private CaptureFormat captureFormat; |
91 private int cameraFramesCount; | 90 private int cameraFramesCount; |
92 private int captureBuffersCount; | 91 private int captureBuffersCount; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 @Override public void run() { | 268 @Override public void run() { |
270 Looper.prepare(); | 269 Looper.prepare(); |
271 exchange(handlerExchanger, new Handler()); | 270 exchange(handlerExchanger, new Handler()); |
272 Looper.loop(); | 271 Looper.loop(); |
273 } | 272 } |
274 } | 273 } |
275 | 274 |
276 // Called by native code. Returns true if capturer is started. | 275 // Called by native code. Returns true if capturer is started. |
277 // | 276 // |
278 // Note that this actually opens the camera, and Camera callbacks run on the | 277 // Note that this actually opens the camera, and Camera callbacks run on the |
279 // thread that calls open(), so this is done on the CameraThread. Since the | 278 // thread that calls open(), so this is done on the CameraThread. |
280 // API needs a synchronous success return value we wait for the result. | |
281 synchronized void startCapture( | 279 synchronized void startCapture( |
282 final int width, final int height, final int framerate, | 280 final int width, final int height, final int framerate, |
283 final Context applicationContext, final CapturerObserver frameObserver) { | 281 final Context applicationContext, final CapturerObserver frameObserver) { |
284 Logging.d(TAG, "startCapture requested: " + width + "x" + height | 282 Logging.d(TAG, "startCapture requested: " + width + "x" + height |
285 + "@" + framerate); | 283 + "@" + framerate); |
286 if (applicationContext == null) { | 284 if (applicationContext == null) { |
287 throw new RuntimeException("applicationContext not set."); | 285 throw new RuntimeException("applicationContext not set."); |
288 } | 286 } |
289 if (frameObserver == null) { | 287 if (frameObserver == null) { |
290 throw new RuntimeException("frameObserver not set."); | 288 throw new RuntimeException("frameObserver not set."); |
(...skipping 25 matching lines...) Expand all Loading... |
316 camera = Camera.open(id); | 314 camera = Camera.open(id); |
317 info = new Camera.CameraInfo(); | 315 info = new Camera.CameraInfo(); |
318 Camera.getCameraInfo(id, info); | 316 Camera.getCameraInfo(id, info); |
319 // No local renderer (we only care about onPreviewFrame() buffers, not a | 317 // No local renderer (we only care about onPreviewFrame() buffers, not a |
320 // directly-displayed UI element). Camera won't capture without | 318 // directly-displayed UI element). Camera won't capture without |
321 // setPreview{Texture,Display}, so we create a SurfaceTexture and hand | 319 // setPreview{Texture,Display}, so we create a SurfaceTexture and hand |
322 // it over to Camera, but never listen for frame-ready callbacks, | 320 // it over to Camera, but never listen for frame-ready callbacks, |
323 // and never call updateTexImage on it. | 321 // and never call updateTexImage on it. |
324 try { | 322 try { |
325 cameraGlTexture = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_O
ES); | 323 cameraGlTexture = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_O
ES); |
326 cameraSurfaceTexture = new SurfaceTexture(cameraGlTexture); | 324 SurfaceTexture cameraSurfaceTexture = new SurfaceTexture(cameraGlTexture
); |
327 cameraSurfaceTexture.setOnFrameAvailableListener(null); | 325 cameraSurfaceTexture.setOnFrameAvailableListener(null); |
328 | 326 |
329 camera.setPreviewTexture(cameraSurfaceTexture); | 327 camera.setPreviewTexture(cameraSurfaceTexture); |
330 } catch (IOException e) { | 328 } catch (IOException e) { |
331 Logging.e(TAG, "setPreviewTexture failed", error); | 329 Logging.e(TAG, "setPreviewTexture failed", error); |
332 throw new RuntimeException(e); | 330 throw new RuntimeException(e); |
333 } | 331 } |
334 | 332 |
335 Logging.d(TAG, "Camera orientation: " + info.orientation + | 333 Logging.d(TAG, "Camera orientation: " + info.orientation + |
336 " .Device orientation: " + getDeviceOrientation()); | 334 " .Device orientation: " + getDeviceOrientation()); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 doStopCaptureOnCameraThread(); | 439 doStopCaptureOnCameraThread(); |
442 Looper.myLooper().quit(); | 440 Looper.myLooper().quit(); |
443 return; | 441 return; |
444 } | 442 } |
445 | 443 |
446 private void doStopCaptureOnCameraThread() { | 444 private void doStopCaptureOnCameraThread() { |
447 Logging.d(TAG, "stopCaptureOnCameraThread"); | 445 Logging.d(TAG, "stopCaptureOnCameraThread"); |
448 if (camera == null) { | 446 if (camera == null) { |
449 return; | 447 return; |
450 } | 448 } |
451 try { | |
452 cameraThreadHandler.removeCallbacks(cameraObserver); | |
453 Logging.d(TAG, "Stop preview."); | |
454 camera.stopPreview(); | |
455 camera.setPreviewCallbackWithBuffer(null); | |
456 videoBuffers.stopReturnBuffersToCamera(); | |
457 captureFormat = null; | |
458 | 449 |
459 camera.setPreviewTexture(null); | 450 cameraThreadHandler.removeCallbacks(cameraObserver); |
460 cameraSurfaceTexture = null; | 451 Logging.d(TAG, "Stop preview."); |
461 if (cameraGlTexture != 0) { | 452 camera.stopPreview(); |
462 GLES20.glDeleteTextures(1, new int[] {cameraGlTexture}, 0); | 453 camera.setPreviewCallbackWithBuffer(null); |
463 cameraGlTexture = 0; | 454 videoBuffers.stopReturnBuffersToCamera(); |
464 } | 455 captureFormat = null; |
465 Logging.d(TAG, "Release camera."); | 456 |
466 camera.release(); | 457 if (cameraGlTexture != 0) { |
467 camera = null; | 458 GLES20.glDeleteTextures(1, new int[] {cameraGlTexture}, 0); |
468 } catch (IOException e) { | 459 cameraGlTexture = 0; |
469 Logging.e(TAG, "Failed to stop camera", e); | |
470 } | 460 } |
| 461 Logging.d(TAG, "Release camera."); |
| 462 camera.release(); |
| 463 camera = null; |
471 } | 464 } |
472 | 465 |
473 private void switchCameraOnCameraThread(Runnable switchDoneEvent) { | 466 private void switchCameraOnCameraThread(Runnable switchDoneEvent) { |
474 Logging.d(TAG, "switchCameraOnCameraThread"); | 467 Logging.d(TAG, "switchCameraOnCameraThread"); |
475 | 468 |
476 doStopCaptureOnCameraThread(); | 469 doStopCaptureOnCameraThread(); |
477 startCaptureOnCameraThread(requestedWidth, requestedHeight, requestedFramera
te, frameObserver, | 470 startCaptureOnCameraThread(requestedWidth, requestedHeight, requestedFramera
te, frameObserver, |
478 applicationContext); | 471 applicationContext); |
479 pendingCameraSwitch = false; | 472 pendingCameraSwitch = false; |
480 Logging.d(TAG, "switchCameraOnCameraThread done"); | 473 Logging.d(TAG, "switchCameraOnCameraThread done"); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 } | 727 } |
735 | 728 |
736 private native void nativeCapturerStarted(long nativeCapturer, | 729 private native void nativeCapturerStarted(long nativeCapturer, |
737 boolean success); | 730 boolean success); |
738 private native void nativeOnFrameCaptured(long nativeCapturer, | 731 private native void nativeOnFrameCaptured(long nativeCapturer, |
739 byte[] data, int length, int width, int height, int rotation, long timeS
tamp); | 732 byte[] data, int length, int width, int height, int rotation, long timeS
tamp); |
740 private native void nativeOnOutputFormatRequest(long nativeCapturer, | 733 private native void nativeOnOutputFormatRequest(long nativeCapturer, |
741 int width, int height, int fps); | 734 int width, int height, int fps); |
742 } | 735 } |
743 } | 736 } |
OLD | NEW |