refactor WebRTCWrapper to allow for track adds

This commit is contained in:
Daniel Gultsch 2022-11-19 13:03:34 +01:00
parent 8fb2c11771
commit 27d8da2ab4
2 changed files with 80 additions and 34 deletions

View file

@ -3,7 +3,6 @@ package eu.siacs.conversations.xmpp.jingle;
import android.content.Context;
import android.util.Log;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
@ -127,7 +126,7 @@ class VideoSourceWrapper {
this.context = context;
}
public Optional<VideoSourceWrapper> create() {
public VideoSourceWrapper create() {
final CameraEnumerator enumerator = new Camera2Enumerator(context);
final Set<String> deviceNames = ImmutableSet.copyOf(enumerator.getDeviceNames());
for (final String deviceName : deviceNames) {
@ -135,17 +134,16 @@ class VideoSourceWrapper {
final VideoSourceWrapper videoSourceWrapper =
of(enumerator, deviceName, deviceNames);
if (videoSourceWrapper == null) {
return Optional.absent();
return null;
}
videoSourceWrapper.isFrontCamera = true;
return Optional.of(videoSourceWrapper);
return videoSourceWrapper;
}
}
if (deviceNames.size() == 0) {
return Optional.absent();
return null;
} else {
return Optional.fromNullable(
of(enumerator, Iterables.get(deviceNames, 0), deviceNames));
return of(enumerator, Iterables.get(deviceNames, 0), deviceNames);
}
}

View file

@ -196,6 +196,7 @@ public class WebRTCWrapper {
+ ")");
}
};
@Nullable private PeerConnectionFactory peerConnectionFactory = null;
@Nullable private PeerConnection peerConnection = null;
private AppRTCAudioManager appRTCAudioManager = null;
private ToneManager toneManager = null;
@ -260,7 +261,7 @@ public class WebRTCWrapper {
String.format(
"setUseHardwareAcousticEchoCanceler(%s) model=%s",
setUseHardwareAcousticEchoCanceler, Build.MODEL));
PeerConnectionFactory peerConnectionFactory =
this.peerConnectionFactory =
PeerConnectionFactory.builder()
.setVideoDecoderFactory(
new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
@ -268,7 +269,7 @@ public class WebRTCWrapper {
new DefaultVideoEncoderFactory(
eglBase.getEglBaseContext(), true, true))
.setAudioDeviceModule(
JavaAudioDeviceModule.builder(context)
JavaAudioDeviceModule.builder(requireContext())
.setUseHardwareAcousticEchoCanceler(
setUseHardwareAcousticEchoCanceler)
.createAudioDeviceModule())
@ -276,36 +277,18 @@ public class WebRTCWrapper {
final PeerConnection.RTCConfiguration rtcConfig = buildConfiguration(iceServers);
final PeerConnection peerConnection =
peerConnectionFactory.createPeerConnection(rtcConfig, peerConnectionObserver);
requirePeerConnectionFactory()
.createPeerConnection(rtcConfig, peerConnectionObserver);
if (peerConnection == null) {
throw new InitializationException("Unable to create PeerConnection");
}
final Optional<VideoSourceWrapper> optionalVideoSourceWrapper =
media.contains(Media.VIDEO)
? new VideoSourceWrapper.Factory(requireContext()).create()
: Optional.absent();
if (optionalVideoSourceWrapper.isPresent()) {
this.videoSourceWrapper = optionalVideoSourceWrapper.get();
this.videoSourceWrapper.initialize(
peerConnectionFactory, context, eglBase.getEglBaseContext());
this.videoSourceWrapper.startCapture();
final VideoTrack videoTrack =
peerConnectionFactory.createVideoTrack(
"my-video-track", this.videoSourceWrapper.getVideoSource());
this.localVideoTrack = TrackWrapper.addTrack(peerConnection, videoTrack);
if (media.contains(Media.VIDEO)) {
addVideoTrack(peerConnection);
}
if (media.contains(Media.AUDIO)) {
// set up audio track
final AudioSource audioSource =
peerConnectionFactory.createAudioSource(new MediaConstraints());
final AudioTrack audioTrack =
peerConnectionFactory.createAudioTrack("my-audio-track", audioSource);
this.localAudioTrack = TrackWrapper.addTrack(peerConnection, audioTrack);
addAudioTrack(peerConnection);
}
peerConnection.setAudioPlayout(true);
peerConnection.setAudioRecording(true);
@ -313,6 +296,58 @@ public class WebRTCWrapper {
this.peerConnection = peerConnection;
}
private VideoSourceWrapper initializeVideoSourceWrapper() {
final VideoSourceWrapper existingVideoSourceWrapper = this.videoSourceWrapper;
if (existingVideoSourceWrapper != null) {
existingVideoSourceWrapper.startCapture();
return existingVideoSourceWrapper;
}
final VideoSourceWrapper videoSourceWrapper =
new VideoSourceWrapper.Factory(requireContext()).create();
if (videoSourceWrapper == null) {
throw new IllegalStateException("Could not instantiate VideoSourceWrapper");
}
videoSourceWrapper.initialize(
requirePeerConnectionFactory(), requireContext(), eglBase.getEglBaseContext());
videoSourceWrapper.startCapture();
return videoSourceWrapper;
}
public synchronized boolean addTrack(final Media media) {
if (media == Media.VIDEO) {
return addVideoTrack(requirePeerConnection());
} else if (media == Media.AUDIO) {
return addAudioTrack(requirePeerConnection());
}
throw new IllegalStateException(String.format("Could not add track for %s", media));
}
private boolean addAudioTrack(final PeerConnection peerConnection) {
final AudioSource audioSource =
requirePeerConnectionFactory().createAudioSource(new MediaConstraints());
final AudioTrack audioTrack =
requirePeerConnectionFactory().createAudioTrack("my-audio-track", audioSource);
this.localAudioTrack = TrackWrapper.addTrack(peerConnection, audioTrack);
return true;
}
private boolean addVideoTrack(final PeerConnection peerConnection) {
Preconditions.checkState(
this.localVideoTrack == null, "A local video track already exists");
final VideoSourceWrapper videoSourceWrapper;
try {
videoSourceWrapper = initializeVideoSourceWrapper();
} catch (final IllegalStateException e) {
Log.d(Config.LOGTAG, "could not add video track", e);
return false;
}
final VideoTrack videoTrack =
requirePeerConnectionFactory()
.createVideoTrack("my-video-track", videoSourceWrapper.getVideoSource());
this.localVideoTrack = TrackWrapper.addTrack(peerConnection, videoTrack);
return true;
}
private static PeerConnection.RTCConfiguration buildConfiguration(
final List<PeerConnection.IceServer> iceServers) {
final PeerConnection.RTCConfiguration rtcConfig =
@ -344,6 +379,7 @@ public class WebRTCWrapper {
synchronized void close() {
final PeerConnection peerConnection = this.peerConnection;
final PeerConnectionFactory peerConnectionFactory = this.peerConnectionFactory;
final VideoSourceWrapper videoSourceWrapper = this.videoSourceWrapper;
final AppRTCAudioManager audioManager = this.appRTCAudioManager;
final EglBase eglBase = this.eglBase;
@ -363,12 +399,15 @@ public class WebRTCWrapper {
} catch (final InterruptedException e) {
Log.e(Config.LOGTAG, "unable to stop capturing");
}
// TODO call dispose
videoSourceWrapper.dispose();
}
if (eglBase != null) {
eglBase.release();
this.eglBase = null;
}
if (peerConnectionFactory != null) {
peerConnectionFactory.dispose();
}
}
synchronized void verifyClosed() {
@ -530,6 +569,7 @@ public class WebRTCWrapper {
}
}
@Nonnull
private PeerConnection requirePeerConnection() {
final PeerConnection peerConnection = this.peerConnection;
if (peerConnection == null) {
@ -538,6 +578,15 @@ public class WebRTCWrapper {
return peerConnection;
}
@Nonnull
private PeerConnectionFactory requirePeerConnectionFactory() {
final PeerConnectionFactory peerConnectionFactory = this.peerConnectionFactory;
if (peerConnectionFactory == null) {
throw new IllegalStateException("Make sure PeerConnectionFactory is initialized");
}
return peerConnectionFactory;
}
void addIceCandidate(IceCandidate iceCandidate) {
requirePeerConnection().addIceCandidate(iceCandidate);
}
@ -626,5 +675,4 @@ public class WebRTCWrapper {
super(message);
}
}
}