feat: Wait for camera to finish completely

This commit is contained in:
Myzel394 2023-12-01 00:04:14 +01:00
parent 3cee858b56
commit 569794d437
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
6 changed files with 22 additions and 14 deletions

View File

@ -176,7 +176,7 @@ class AudioRecorderService :
resetRecorder() resetRecorder()
} }
override fun stop() { override suspend fun stop() {
super.stop() super.stop()
resetRecorder() resetRecorder()

View File

@ -55,7 +55,7 @@ abstract class IntervalRecorderService<S : IntervalRecorderService.Settings, I>
createTimer() createTimer()
} }
override fun stop() { override suspend fun stop() {
cycleTimer.shutdown() cycleTimer.shutdown()
} }

View File

@ -44,7 +44,7 @@ abstract class RecorderService : LifecycleService() {
protected abstract fun start() protected abstract fun start()
protected abstract fun pause() protected abstract fun pause()
protected abstract fun resume() protected abstract fun resume()
protected abstract fun stop() protected abstract suspend fun stop()
override fun onBind(intent: Intent): IBinder? { override fun onBind(intent: Intent): IBinder? {
super.onBind(intent) super.onBind(intent)
@ -162,7 +162,7 @@ abstract class RecorderService : LifecycleService() {
changeState(RecorderState.RECORDING) changeState(RecorderState.RECORDING)
} }
fun stopRecording() { suspend fun stopRecording() {
changeState(RecorderState.IDLE) changeState(RecorderState.IDLE)
stop() stop()
} }

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.util.Range import android.util.Range
import androidx.camera.core.Camera import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector import androidx.camera.core.CameraSelector
import androidx.camera.core.impl.CameraConfig
import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.video.FileOutputOptions import androidx.camera.video.FileOutputOptions
import androidx.camera.video.Quality import androidx.camera.video.Quality
@ -11,6 +12,7 @@ import androidx.camera.video.QualitySelector
import androidx.camera.video.Recorder import androidx.camera.video.Recorder
import androidx.camera.video.Recording import androidx.camera.video.Recording
import androidx.camera.video.VideoCapture import androidx.camera.video.VideoCapture
import androidx.camera.video.VideoRecordEvent
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.db.RecordingInformation import app.myzel394.alibi.db.RecordingInformation
@ -38,11 +40,12 @@ class VideoRecorderService :
// Used to listen and check if the camera is available // Used to listen and check if the camera is available
private var _cameraAvailableListener = CompletableDeferred<Unit>() private var _cameraAvailableListener = CompletableDeferred<Unit>()
private var _cameraClosedListener = CompletableDeferred<Unit>()
private var selectedCamera: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA private var selectedCamera: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// Runs a function in the main thread // Runs a function in the main thread
private fun runInMain(callback: () -> Unit) { private fun runOnMain(callback: () -> Unit) {
val mainHandler = ContextCompat.getMainExecutor(this) val mainHandler = ContextCompat.getMainExecutor(this)
mainHandler.execute(callback) mainHandler.execute(callback)
@ -76,7 +79,7 @@ class VideoRecorderService :
val recorder = buildRecorder() val recorder = buildRecorder()
videoCapture = buildVideoCapture(recorder) videoCapture = buildVideoCapture(recorder)
runInMain { runOnMain {
camera = cameraProvider!!.bindToLifecycle( camera = cameraProvider!!.bindToLifecycle(
this, this,
selectedCamera, selectedCamera,
@ -91,11 +94,11 @@ class VideoRecorderService :
// Used to close it finally, shouldn't be called when pausing / resuming. // Used to close it finally, shouldn't be called when pausing / resuming.
// This should only be called after recording has finished. // This should only be called after recording has finished.
private fun closeCamera() { private fun closeCamera() {
stopActiveRecording()
runCatching { runCatching {
runOnMain {
cameraProvider?.unbindAll() cameraProvider?.unbindAll()
} }
}
cameraProvider = null cameraProvider = null
videoCapture = null videoCapture = null
@ -110,9 +113,12 @@ class VideoRecorderService :
} }
} }
override fun stop() { override suspend fun stop() {
super.stop() super.stop()
stopActiveRecording()
_cameraClosedListener.await()
// Camera can only be closed after the recording has been finalized
closeCamera() closeCamera()
} }
@ -134,7 +140,12 @@ class VideoRecorderService :
activeRecording?.stop() activeRecording?.stop()
val newRecording = prepareVideoRecording() val newRecording = prepareVideoRecording()
activeRecording = newRecording.start(ContextCompat.getMainExecutor(this), {}) activeRecording = newRecording.start(ContextCompat.getMainExecutor(this)) { event ->
// TODO: Add timeout to completer
if (event is VideoRecordEvent.Finalize) {
_cameraClosedListener.complete(Unit)
}
}
} }
if (_cameraAvailableListener.isCompleted) { if (_cameraAvailableListener.isCompleted) {

View File

@ -128,7 +128,6 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
suspend fun stopRecording(context: Context) { suspend fun stopRecording(context: Context) {
recorderService!!.stopRecording() recorderService!!.stopRecording()
} }
fun pauseRecording() { fun pauseRecording() {

View File

@ -48,8 +48,6 @@ fun POCVideo(
val batchesFolder = videoRecorder.batchesFolder!! val batchesFolder = videoRecorder.batchesFolder!!
videoRecorder.stopRecording(context) videoRecorder.stopRecording(context)
delay(5000)
batchesFolder.concatenate( batchesFolder.concatenate(
recordingStart = information.recordingStart, recordingStart = information.recordingStart,
extension = information.fileExtension, extension = information.fileExtension,