Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update video recording to be controlled through the CoroutineJob #34

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

yasith
Copy link
Member

@yasith yasith commented Aug 26, 2023

This is a clean up PR, to clean up the video recording code. Video start/stop is now controlled through the coroutine job spawned from viewModel scope

}
recordingJob = cameraUseCase.startVideoRecording(viewModelScope)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider keeping the stopVideoRecording function and just having the use case manage the job rather than exposing it to the view model?
From an interface / api pov I would expect a start and stop
If the use case manages the job then it could also include logic of asserting that a call to start doesn't have an active job (or cancel the job first and then start again) and similarly for stop
I'm also not sure if the job should be managed by the use case or maybe it's better suited for the view model

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some API feedback we received on the initial VideoCapture use case was that we should avoid including API that can be called from an invalid state. This exact scenario was discussed: you shouldn't be able to call a "stop" method if there isn't already a recording in progress. This is considered an API design problem with the existingMediaRecorder API. The way we implemented this in "VideoCapture" was to have a chain of methods that returned more "scoped" APIs:

  1. Recorder.prepareRecording() --> class PendingRecording
  2. PendingRecording.start() --> class Recording : AutoCloseable
  3. Recording.stop()/close().

We possibly could have taken this even further. For instance, we don't have anything like a PausedRecording when you call Recording.pause().

Kotlin and coroutines make this kind of API decomposition even easier. Instead of dealing with the clunky Java AutoCloseable, we now have coroutine scopes to handle that.

I do think we should avoid returning the Job as it's a pretty low-level detail that can probably be managed internally by the use case. We also don't need an explicit CoroutineScope argument if we keep startVideoRecording as a suspend function. We could do something like this:

suspend fun startVideoRecording(session: suspend (recording: Recording) -> RecordingCompletionStatus): RecordingCompletionStatus = coroutineScope {
  // Check if an existing job exists and throw an error if so, otherwise store `coroutineContext.job` as the active job.
  ...
  try {
    return@coroutineScope session(Recording(mediaStoreOutput))
  } finally {
    ...
  }
}

This allows us to use it something like:

viewModelScope.launch {
  val completionStatus = cameraUseCase.startVideoRecording { recording ->
    // Set up a listener that triggers from a "stop" button being pressed.
    stopSignal.addListener { recording.stop() }

    // These could potentially be broken down further into their own `coroutineScope`
    pauseSignal.addListener { recording.pause() }
    resumeSignal.addListener { recording.resume() }

    // Add listeners for recording duration, etc
    recording.addDurationListener { ... }

    // Suspend until completion
    return recording.awaitCompletion()
  }

  // Do something with the completion status
 ...
}

Copy link
Collaborator

@jsaund jsaund left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall lgtm
just curious about whether we should keep the stop function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants