Skip to content

Instantly share code, notes, and snippets.

@lyokato
Created July 2, 2018 03:20
Show Gist options
  • Save lyokato/6cb6a6c23eeeb16f49e90ec1b2326439 to your computer and use it in GitHub Desktop.
Save lyokato/6cb6a6c23eeeb16f49e90ec1b2326439 to your computer and use it in GitHub Desktop.
package com.github.lyokato.rtc360;
import android.content.Context;
import android.util.Log;
import android.view.Surface;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.UVCCamera;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.ThreadUtils;
import org.webrtc.VideoCapturer;
import java.util.List;
public class UVCCameraCapturer implements VideoCapturer,
SurfaceTextureHelper.OnTextureFrameAvailableListener {
private static final String TAG = UVCCameraCapturer.class.getSimpleName();
private SurfaceTextureHelper surfaceTextureHelper;
private VideoCapturer.CapturerObserver capturerObserver;
private boolean isDisposed;
private int width;
private int height;
private UVCCamera camera;
public UVCCameraCapturer(UVCCamera camera) {
this.camera = camera;
this.isDisposed = false;
}
private void checkNotDisposed() {
if (isDisposed) {
throw new RuntimeException("capturer is disposed.");
}
}
@Override
public void onTextureFrameAvailable(int oesTextureId,
float[] transformMatrix,
long timestampNs) {
capturerObserver.onTextureFrameCaptured(
width, height, oesTextureId, transformMatrix, 0 /* rotation */, timestampNs);
}
@Override
public void initialize(final SurfaceTextureHelper surfaceTextureHelper,
final Context context,
final VideoCapturer.CapturerObserver capturerObserver) {
Log.d(TAG, "initialize");
checkNotDisposed();
if (surfaceTextureHelper == null) {
throw new RuntimeException("surfaceTextureHelper not set.");
}
this.surfaceTextureHelper = surfaceTextureHelper;
if (capturerObserver == null) {
throw new RuntimeException("capturerObserver not set.");
}
this.capturerObserver = capturerObserver;
}
@Override
public void startCapture(final int width,
final int height,
final int ignoredFrameRate) {
Log.d(TAG, "startCapture");
checkNotDisposed();
if (setupCameraTexture(width, height)) {
capturerObserver.onCapturerStarted(true);
surfaceTextureHelper.startListening(UVCCameraCapturer.this);
}
}
private Size getNearestSize(List<Size> sizeList, int preferredWidth, int preferredHeight) {
Size selected = null;
int lastDiff = 10000;
for (Size s : sizeList) {
Log.d(TAG, "SIZE: " + String.valueOf(s.width) + ":" + String.valueOf(s.height));
int diff = Math.abs(s.width - preferredWidth);
if (diff < lastDiff) {
selected = s;
}
}
return selected;
}
private boolean setupCameraTexture(final int width, final int height) {
Log.d(TAG, "setupCameraTexture");
List<Size> sizeList = camera.getSupportedSizeList();
if (sizeList.size() == 0) {
Log.d(TAG, "failed to obtain supported size list");
camera.destroy();
return false;
}
Size size = getNearestSize(sizeList, width, height);
this.width = size.width;
this.height = size.height;
try {
camera.setPreviewSize(this.width, this.height, UVCCamera.FRAME_FORMAT_MJPEG);
} catch (IllegalArgumentException e1) {
Log.d(TAG, "failed to set preview size: " + e1.getStackTrace().toString());
try {
camera.setPreviewSize(this.width, this.height, UVCCamera.DEFAULT_PREVIEW_MODE);
} catch (IllegalArgumentException e2) {
Log.d(TAG, "failed to set preview size YUV: " + e2.getStackTrace().toString());
camera.destroy();
return false;
}
}
surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(this.width, this.height);
Surface surface = new Surface(surfaceTextureHelper.getSurfaceTexture());
camera.setPreviewDisplay(surface);
camera.startPreview();
return true;
}
@Override
public void stopCapture() throws InterruptedException {
Log.d(TAG, "stopCapture");
checkNotDisposed();
ThreadUtils.invokeAtFrontUninterruptibly(surfaceTextureHelper.getHandler(), new Runnable() {
@Override
public void run() {
camera.stopPreview();
surfaceTextureHelper.stopListening();
capturerObserver.onCapturerStopped();
}
});
}
@Override
public void changeCaptureFormat(final int width,
final int height,
final int ignoredFrameRate) {
Log.d(TAG, "changeCaptureFormat");
checkNotDisposed();
ThreadUtils.invokeAtFrontUninterruptibly(surfaceTextureHelper.getHandler(), new Runnable() {
@Override
public void run() {
camera.stopPreview();
setupCameraTexture(width, height);
surfaceTextureHelper.stopListening();
capturerObserver.onCapturerStopped();
}
});
}
@Override
public void dispose() {
Log.d(TAG, "dispose");
isDisposed = true;
if (camera != null) {
camera.destroy();
camera = null;
}
}
@Override
public boolean isScreencast() {
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment