|
|
|
|
@ -44,7 +44,7 @@ class StreamCaptureEngine(
|
|
|
|
|
private var activeConfig: StreamCaptureConfig? = null |
|
|
|
|
private var previewTarget: StreamPreviewTarget? = null |
|
|
|
|
private var sessionGeneration = 0L |
|
|
|
|
private var cameraSessions = 0 |
|
|
|
|
private val cameraSessions = mutableMapOf<Long, Pair<CameraDevice, (String) -> Unit>>() |
|
|
|
|
private var record: AudioRecord? = null |
|
|
|
|
private var audioThread: Thread? = null |
|
|
|
|
@Volatile private var audioRunning = false |
|
|
|
|
@ -85,6 +85,7 @@ class StreamCaptureEngine(
|
|
|
|
|
preview.bind { target -> |
|
|
|
|
if (!handler.post { |
|
|
|
|
if (stopping || stopped || terminalFailure) { target?.release(); return@post } |
|
|
|
|
if (target === previewTarget) { target?.release(); return@post } |
|
|
|
|
val previous = previewTarget; previewTarget = target; previous?.release() |
|
|
|
|
val config = activeConfig; val device = camera |
|
|
|
|
LogManager.addLog("DEBUG", "video", "preview output change id=$id target=${target?.let(System::identityHashCode)} " + |
|
|
|
|
@ -215,6 +216,9 @@ class StreamCaptureEngine(
|
|
|
|
|
} |
|
|
|
|
override fun onClosed(device: CameraDevice) { |
|
|
|
|
if (camera === device) camera = null |
|
|
|
|
val pending = cameraSessions.values.filter { it.first === device }.map { it.second } |
|
|
|
|
LogManager.addLog("DEBUG", "video", "camera closed id=$id revision=$token retiringSessions=${pending.size}") |
|
|
|
|
pending.forEach { it("cameraClosed") } |
|
|
|
|
if (releaseDone != null && camera == null && !opening) finishRelease(true) |
|
|
|
|
maybeQuit() |
|
|
|
|
} |
|
|
|
|
@ -241,11 +245,13 @@ class StreamCaptureEngine(
|
|
|
|
|
val output = if (withPreview) previewTarget?.retain() else null |
|
|
|
|
var format: StreamPreviewFormat? = null |
|
|
|
|
var completed = false |
|
|
|
|
cameraSessions++ |
|
|
|
|
fun complete() { |
|
|
|
|
fun complete(reason: String) { |
|
|
|
|
if (completed) return |
|
|
|
|
completed = true; output?.release(); cameraSessions--; maybeQuit() |
|
|
|
|
completed = true; cameraSessions.remove(serial); output?.release() |
|
|
|
|
LogManager.addLog("DEBUG", "video", "camera session output released id=$id session=$serial reason=$reason remaining=${cameraSessions.size}") |
|
|
|
|
maybeQuit() |
|
|
|
|
} |
|
|
|
|
cameraSessions[serial] = device to ::complete |
|
|
|
|
fun valid() = current(token) && serial == sessionGeneration |
|
|
|
|
fun rejected(detail: String) { |
|
|
|
|
if (!valid()) { LogManager.addLog("DEBUG", "video", "stale camera session failure id=$id session=$serial: $detail"); return } |
|
|
|
|
@ -312,21 +318,25 @@ class StreamCaptureEngine(
|
|
|
|
|
} catch (e: Exception) { configured.close(); rejected("camera request: ${e.message}") } |
|
|
|
|
} |
|
|
|
|
override fun onConfigureFailed(session: CameraCaptureSession) { |
|
|
|
|
complete(); rejected("camera session configuration") |
|
|
|
|
complete("configureFailed"); rejected("camera session configuration") |
|
|
|
|
} |
|
|
|
|
override fun onClosed(closed: CameraCaptureSession) { |
|
|
|
|
if (session === closed) session = null |
|
|
|
|
complete() |
|
|
|
|
LogManager.addLog("DEBUG", "video", "camera session closed id=$id session=$serial remaining=$cameraSessions") |
|
|
|
|
complete("sessionClosed") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
LogManager.addLog("DEBUG", "video", "camera session configuring id=$id revision=$token session=$serial outputs=${targets.size}") |
|
|
|
|
if (mode.highSpeed) device.createConstrainedHighSpeedCaptureSession(targets, callback, handler) |
|
|
|
|
else device.createCaptureSession(targets, callback, handler) |
|
|
|
|
} catch (e: Exception) { complete(); rejected("camera session: ${e.message}") } |
|
|
|
|
} catch (e: Exception) { complete("exception"); rejected("camera session: ${e.message}") } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun maybeQuit() { if (stopped && camera == null && !opening && cameraSessions == 0) thread.quitSafely() } |
|
|
|
|
private fun maybeQuit() { |
|
|
|
|
if (stopped && camera == null && !opening && cameraSessions.isEmpty()) { |
|
|
|
|
LogManager.addLog("INFO", "video", "capture handler released id=$id pendingSessions=0") |
|
|
|
|
thread.quitSafely() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun captureError(token: Long, detail: String) { |
|
|
|
|
if (!current(token)) { LogManager.addLog("DEBUG", "video", "stale capture error revision=$token: $detail"); return } |
|
|
|
|
|