Last active
February 23, 2020 13:33
-
-
Save apkelly/f1cd7df5bb9ae131ed66acf2ab212dc9 to your computer and use it in GitHub Desktop.
CameraSourcePreview.kt
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
class CameraSourcePreview(private val mContext: Context, attrs: AttributeSet) : ViewGroup(mContext, attrs) { | |
companion object { | |
private const val TAG = "CameraSourcePreview" | |
} | |
private val mSurfaceView: SurfaceView | |
private var mStartRequested: Boolean = false | |
private var mSurfaceAvailable: Boolean = false | |
private var mCameraSource: ICameraSource? = null | |
private var mOverlay: GraphicOverlay? = null | |
private val isPortraitMode: Boolean | |
get() { | |
val orientation = mContext.resources.configuration.orientation | |
if (orientation == Configuration.ORIENTATION_LANDSCAPE) { | |
return false | |
} | |
if (orientation == Configuration.ORIENTATION_PORTRAIT) { | |
return true | |
} | |
Log.d(TAG, "isPortraitMode returning false by default") | |
return false | |
} | |
init { | |
mStartRequested = false | |
mSurfaceAvailable = false | |
mSurfaceView = SurfaceView(mContext) | |
mSurfaceView.holder.addCallback(SurfaceCallback()) | |
addView(mSurfaceView) | |
} | |
@Throws(IOException::class) | |
fun start(cameraSource: ICameraSource?) { | |
if (cameraSource == null) { | |
stop() | |
} | |
mCameraSource = cameraSource | |
if (mCameraSource != null) { | |
mStartRequested = true | |
startIfReady() | |
} | |
} | |
@Throws(IOException::class) | |
fun start(cameraSource: ICameraSource, overlay: GraphicOverlay) { | |
mOverlay = overlay | |
start(cameraSource) | |
} | |
fun stop() { | |
if (mCameraSource != null) { | |
mCameraSource!!.stop() | |
} | |
} | |
fun release() { | |
if (mCameraSource != null) { | |
mCameraSource!!.release() | |
mCameraSource = null | |
} | |
} | |
@Throws(IOException::class) | |
private fun startIfReady() { | |
if (mStartRequested && mSurfaceAvailable) { | |
mCameraSource!!.start(mSurfaceView.holder) | |
if (mOverlay != null) { | |
val size = mCameraSource!!.previewSize() | |
size?.let { | |
val min = Math.min(it.width, it.height) | |
val max = Math.max(it.width, it.height) | |
if (isPortraitMode) { | |
// Swap width and height sizes when in portrait, since it will be rotated by | |
// 90 degrees | |
mOverlay!!.setCameraInfo(min, max, mCameraSource!!.cameraFacing()) | |
} else { | |
mOverlay!!.setCameraInfo(max, min, mCameraSource!!.cameraFacing()) | |
} | |
mOverlay!!.clear() | |
} | |
} | |
mStartRequested = false | |
} | |
} | |
private inner class SurfaceCallback : SurfaceHolder.Callback { | |
override fun surfaceCreated(surface: SurfaceHolder) { | |
mSurfaceAvailable = true | |
try { | |
startIfReady() | |
} catch (e: IOException) { | |
Log.e(TAG, "Could not start camera source.", e) | |
} | |
} | |
override fun surfaceDestroyed(surface: SurfaceHolder) { | |
mSurfaceAvailable = false | |
} | |
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {} | |
} | |
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { | |
var width = 640 | |
var height = 480 | |
if (mCameraSource != null) { | |
val size = mCameraSource!!.previewSize() | |
if (size != null) { | |
width = size.width | |
height = size.height | |
} | |
} | |
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees | |
if (isPortraitMode) { | |
val tmp = width | |
width = height | |
height = tmp | |
} | |
val layoutWidth = right - left | |
val layoutHeight = bottom - top | |
// Computes height and width for potentially doing fit width. | |
var childWidth = layoutWidth | |
var childHeight = (layoutWidth.toFloat() / width.toFloat() * height).toInt() | |
// If height is too tall using fit width, does fit height instead. | |
if (childHeight > layoutHeight) { | |
childHeight = layoutHeight | |
childWidth = (layoutHeight.toFloat() / height.toFloat() * width).toInt() | |
} | |
for (i in 0 until childCount) { | |
getChildAt(i).layout(0, 0, childWidth, childHeight) | |
} | |
try { | |
startIfReady() | |
} catch (e: IOException) { | |
Log.e(TAG, "Could not start camera source.", e) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment