opentok / opentok-android-sdk-samples

Sample applications illustrating best practices using OpenTok Android SDK.
https://tokbox.com/developer/sdks/android/
MIT License
210 stars 170 forks source link

Stream freezes when `cycleCamera` is called without delay multiple times #504

Closed Doctoror closed 2 months ago

Doctoror commented 3 months ago

Describe the bug Stream freezes when cycleCamera is called without delay multiple times

To Reproduce Steps to reproduce the behavior:

  1. Call cycleCamera twice in a row

Minimal reproducible example:

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import com.opentok.android.Publisher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class CycleCameraProblem : ComponentActivity() {

    private val requestPermissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
            if (isGranted) {
                onCameraPermissionGranted()
            } else {
                Toast.makeText(this, "Cannot run without permission", Toast.LENGTH_LONG).show()
            }
        }

    private lateinit var publisher: Publisher
    private lateinit var container: ViewGroup

    private var job: Job? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        container = findViewById(android.R.id.content)
    }

    override fun onResume() {
        super.onResume()
        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            onCameraPermissionGranted()
        } else {
            requestPermissionLauncher.launch(Manifest.permission.CAMERA)
        }
    }

    override fun onPause() {
        super.onPause()
        job?.cancel()
        job = null
    }

    private fun onCameraPermissionGranted() {
        if (!::publisher.isInitialized) {

            publisher = Publisher.Builder(this).build()
            publisher.publishVideo = true

            container.addView(publisher.view)
        }

        runJob()
    }

    private fun runJob() {
        job = GlobalScope.launch(Dispatchers.Main) {
            delay(2000)

            publisher.cycleCamera()
            publisher.cycleCamera()
        }
    }
}

Expected behavior Camera cycles multiple times

Screenshots Video attached: CycleCamera.webm

Device (please compete the following information):

Additional context cycleCamera should either be synchronous, or a Future, so that the API users know when the process of switching camera is finished and is ready to be switched again. Note that Publisher.CameraListener.onCameraChanged is firing before cycleCamera is complete. It cannot be used as a reliable source of information about when cycleCamera is ready to be called again.

v-kpheng commented 2 months ago

@Doctoror, I'm going to close this since you're already working with Support: https://jira.vonage.com/browse/VIDCS-2099.