-
Hey Pedro, The main screen of the application should be divided in two halves. I do this using a CamaraPreview Composable: @Composable
fun CameraPreview(cameraProviderFuture: ListenableFuture<ProcessCameraProvider>) {
val lifecycleOwner = LocalLifecycleOwner.current
AndroidView(
factory = { context ->
PreviewView(context).apply {
setBackgroundColor(Color.GREEN)
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
scaleType = PreviewView.ScaleType.FILL_START
implementationMode = PreviewView.ImplementationMode.COMPATIBLE
post {
cameraProviderFuture.addListener(Runnable {
val cameraProvider = cameraProviderFuture.get()
bindPreview(
cameraProvider,
lifecycleOwner,
this,
)
}, ContextCompat.getMainExecutor(context))
}
}
}
)
}
fun bindPreview(
cameraProvider: ProcessCameraProvider,
lifecycleOwner: LifecycleOwner,
previewView: PreviewView,
) {
val preview: Preview = Preview.Builder()
.build()
val cameraSelector: CameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
preview.setSurfaceProvider(previewView.surfaceProvider)
var camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)
} This CameraPreview Composable is integrated into a HomeScreen Composable: @OptIn(ExperimentalPermissionsApi::class)
@Composable
fun HomeScreen(
modifier: Modifier = Modifier
){
val currentContext = LocalContext.current
val connectChecker = AppConnectChecker(currentContext)
val multiplePermissionsState = rememberMultiplePermissionsState(
listOf(
android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.CAMERA,
)
)
val rtmpCamera2 = RtmpCamera2(currentContext, false, connectChecker)
rtmpCamera2.streamClient.setReTries(10)
var streamButtonLabel by remember { mutableIntStateOf(R.string.start_button) }
var streamingTarget by remember { mutableStateOf("rtmp://somelink") }
val cameraProviderFuture : ListenableFuture<ProcessCameraProvider> = ProcessCameraProvider.getInstance(currentContext)
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(
dimensionResource(id = R.dimen.padding_medium)
)
) {
DefaultButton(
labelResourceId = streamButtonLabel,
onClick = { onStreamClicked(currentContext, rtmpCamera2, multiplePermissionsState, streamingTarget, changeButtonLabel = { streamButtonLabel = it }) }
)
DefaultButton(
labelResourceId = R.string.switch_camera_button,
onClick = { onSwitchCameraClicked(currentContext, rtmpCamera2) }
)
EditStreamingTargetField(streamingTarget, onTargetChange = { streamingTarget = it })
CameraPreview(cameraProviderFuture = cameraProviderFuture)
}
} Im still in the phase of trying around so many things are not really best practise. I somehow tried to find out how to tell the Preview to use the already instantiated stuff from Camera2, but I did not get behind it. Do you know a way on how to reach the desired state? If you miss some more background information I will provide further files and so on of course... |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
Hello,
This is because RtmpCamera2 already contain a camera instance and you can't use 2 cameras instances at the same time. class MainActivity : ComponentActivity(), ConnectChecker {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val rtmpCamera2 = RtmpCamera2(LocalContext.current, true, this)
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
AndroidView(factory = {
OpenGlView(it).apply {
val view = this
view.setAspectRatioMode(AspectRatioMode.Adjust)
view.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(p0: SurfaceHolder) {
}
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
rtmpCamera2.replaceView(view) //attach preview to camera
rtmpCamera2.startPreview() //open camera
}
override fun surfaceDestroyed(p0: SurfaceHolder) {
rtmpCamera2.stopPreview() //close camera
}
})
}
}, modifier = Modifier.fillMaxSize())
}
}
}
}
.... //ConnectChecker implementation
} |
Beta Was this translation helpful? Give feedback.
-
Hello, First a tip. Surface of the component can be removed if you want. I used it because it is wrote when you create a new jetpack compose project. About the packets send. Check that you correctly stop the stream. You have an example code here: if (rtmpCamera1.isRecording()) {
rtmpCamera1.stopRecord();
}
if (rtmpCamera1.isStreaming()) {
rtmpCamera1.stopStream();
}
rtmpCamera1.stopPreview(); //remove this line if you don't want stop preview The preview should be alive if you call only stopStream or stopRecord. The preview stop when you call stopPreview or your preview view (OpenGlView) is destroyed (surfaceDestroyed callback is called). You can check it in my app examples. I recommend you use breakpoints or logs to make sure that your preview is not destroyed or stopPreview is not called. |
Beta Was this translation helpful? Give feedback.
-
Closing then. |
Beta Was this translation helpful? Give feedback.
Hello,
This is because RtmpCamera2 already contain a camera instance and you can't use 2 cameras instances at the same time.
You need to use camera from RtmpCamera2 instead of CameraPreview with ProcessCameraProvider.
For example: