Created
April 8, 2020 13:58
-
-
Save k-konovalov/a8e834465fc26e7fd67c96d6b3af1513 to your computer and use it in GitHub Desktop.
USBCameraToWebRTC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package android.konovalovk.webrtc.core | |
import android.content.Context | |
import android.hardware.usb.UsbDevice | |
import android.util.Log | |
import com.serenegiant.usb.IFrameCallback | |
import com.serenegiant.usb.USBMonitor | |
import com.serenegiant.usb.UVCCamera | |
import java.util.concurrent.Executors | |
import android.graphics.Bitmap | |
import android.widget.ImageView | |
import com.serenegiant.usb.Size | |
import kotlinx.coroutines.* | |
import org.webrtc.* | |
import java.lang.Exception | |
import java.lang.ref.WeakReference | |
import java.nio.ByteBuffer | |
private const val TAG = "CustomVideoCapturer" | |
class CustomVideoCapturer( | |
private val camera: UVCCamera, | |
private var width: Int, | |
private var height: Int | |
) : VideoCapturer { | |
//Coroutines | |
private var job = Job() | |
private val defScope = CoroutineScope(Dispatchers.Default + job) | |
//USBCamera | |
private val executor = Executors.newSingleThreadExecutor() | |
//for WebRTC | |
private lateinit var surfaceTextureHelper: SurfaceTextureHelper | |
private lateinit var capturerObserver: CapturerObserver | |
private var videoFrame: VideoFrame? = null | |
var start = 0L | |
var isExternalCameraRunning = false | |
//--------------------implement VideoCapturer | |
override fun changeCaptureFormat(i: Int, i1: Int, i2: Int) { | |
Log.i(TAG, "changeCaptureFormat right fired!") | |
} | |
override fun isScreencast(): Boolean { | |
return false | |
} | |
override fun initialize( | |
surfaceTextureHelper: SurfaceTextureHelper, | |
context: Context, | |
capturerObserver: CapturerObserver | |
) { | |
this.surfaceTextureHelper = surfaceTextureHelper | |
this.capturerObserver = capturerObserver | |
Log.i(TAG, "USB init") | |
} | |
/** | |
* Notify if the camera have been started successfully or not. | |
* Called on a Java thread owned by VideoCapturer. CapturerThread | |
* */ | |
override fun startCapture(i: Int, i1: Int, i2: Int) { | |
Log.i(TAG, "USB start Capture") | |
if (!isExternalCameraRunning) executor.execute { | |
start = System.nanoTime() | |
Log.i(TAG, "USB Camera" + camera.device.toString()) | |
Log.i(TAG, "USB Camera" + camera.deviceName) | |
logSupportedSizes() | |
val check = | |
camera.supportedSizeList!! | |
.filter { (it.width in (width-1)..(width+1)) && (it.height in (height-1)..(height+1))} | |
.also { | |
it.forEach { | |
Log.d(TAG, "${it.width} x ${it.height}") | |
} | |
} | |
//Use default if not supported cutom res | |
if (check.isEmpty()) { | |
width = UVCCamera.DEFAULT_PREVIEW_WIDTH | |
height = UVCCamera.DEFAULT_PREVIEW_HEIGHT | |
} | |
Log.e(TAG, "Selected resolution $width x $height") | |
camera.apply { | |
autoFocus = false | |
setPreviewSize( | |
width, | |
height, | |
UVCCamera.FRAME_FORMAT_MJPEG //Work: MJPEG | |
) | |
//setPreviewDisplay(svVideoRender.holder) | |
setFrameCallback(myFrameCallBack, UVCCamera.PIXEL_FORMAT_NV21) | |
startPreview() | |
} | |
capturerObserver.onCapturerStarted(true) | |
} | |
isExternalCameraRunning = true | |
} | |
override fun stopCapture() { | |
Log.i(TAG, "USB stop capture") | |
camera.stopPreview() | |
isExternalCameraRunning = false | |
surfaceTextureHelper.handler.removeCallbacksAndMessages(null) | |
} | |
override fun dispose() { | |
Log.i(TAG, "USB disposed") | |
surfaceTextureHelper.handler?.removeCallbacksAndMessages(null) | |
defScope.cancel() | |
} | |
//--------------------IFrameCallback are most important thing there | |
private val myFrameCallBack: IFrameCallback = IFrameCallback { frame -> | |
videoFrame = VideoFrame( | |
NV12Buffer( | |
width, | |
height, | |
width, | |
height, | |
frame, | |
{ JniCommon.nativeFreeByteBuffer(frame) }), 0, System.nanoTime() - start | |
) | |
capturerObserver.onFrameCaptured(videoFrame) | |
} | |
private fun logSupportedSizes() { | |
val sizeList = camera.supportedSizeList //List<Size> | |
sizeList?.apply { | |
var supportedSizes = "" | |
forEach { | |
supportedSizes += "${it.width}x${it.height} " | |
} | |
Log.i(TAG, "Support resolution's: $supportedSizes") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment