refactor WebRTCWrapper to allow for track adds
This commit is contained in:
parent
8fb2c11771
commit
27d8da2ab4
|
@ -3,7 +3,6 @@ package eu.siacs.conversations.xmpp.jingle;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
@ -127,7 +126,7 @@ class VideoSourceWrapper {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<VideoSourceWrapper> create() {
|
public VideoSourceWrapper create() {
|
||||||
final CameraEnumerator enumerator = new Camera2Enumerator(context);
|
final CameraEnumerator enumerator = new Camera2Enumerator(context);
|
||||||
final Set<String> deviceNames = ImmutableSet.copyOf(enumerator.getDeviceNames());
|
final Set<String> deviceNames = ImmutableSet.copyOf(enumerator.getDeviceNames());
|
||||||
for (final String deviceName : deviceNames) {
|
for (final String deviceName : deviceNames) {
|
||||||
|
@ -135,17 +134,16 @@ class VideoSourceWrapper {
|
||||||
final VideoSourceWrapper videoSourceWrapper =
|
final VideoSourceWrapper videoSourceWrapper =
|
||||||
of(enumerator, deviceName, deviceNames);
|
of(enumerator, deviceName, deviceNames);
|
||||||
if (videoSourceWrapper == null) {
|
if (videoSourceWrapper == null) {
|
||||||
return Optional.absent();
|
return null;
|
||||||
}
|
}
|
||||||
videoSourceWrapper.isFrontCamera = true;
|
videoSourceWrapper.isFrontCamera = true;
|
||||||
return Optional.of(videoSourceWrapper);
|
return videoSourceWrapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deviceNames.size() == 0) {
|
if (deviceNames.size() == 0) {
|
||||||
return Optional.absent();
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return Optional.fromNullable(
|
return of(enumerator, Iterables.get(deviceNames, 0), deviceNames);
|
||||||
of(enumerator, Iterables.get(deviceNames, 0), deviceNames));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ public class WebRTCWrapper {
|
||||||
+ ")");
|
+ ")");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@Nullable private PeerConnectionFactory peerConnectionFactory = null;
|
||||||
@Nullable private PeerConnection peerConnection = null;
|
@Nullable private PeerConnection peerConnection = null;
|
||||||
private AppRTCAudioManager appRTCAudioManager = null;
|
private AppRTCAudioManager appRTCAudioManager = null;
|
||||||
private ToneManager toneManager = null;
|
private ToneManager toneManager = null;
|
||||||
|
@ -260,7 +261,7 @@ public class WebRTCWrapper {
|
||||||
String.format(
|
String.format(
|
||||||
"setUseHardwareAcousticEchoCanceler(%s) model=%s",
|
"setUseHardwareAcousticEchoCanceler(%s) model=%s",
|
||||||
setUseHardwareAcousticEchoCanceler, Build.MODEL));
|
setUseHardwareAcousticEchoCanceler, Build.MODEL));
|
||||||
PeerConnectionFactory peerConnectionFactory =
|
this.peerConnectionFactory =
|
||||||
PeerConnectionFactory.builder()
|
PeerConnectionFactory.builder()
|
||||||
.setVideoDecoderFactory(
|
.setVideoDecoderFactory(
|
||||||
new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
|
new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
|
||||||
|
@ -268,7 +269,7 @@ public class WebRTCWrapper {
|
||||||
new DefaultVideoEncoderFactory(
|
new DefaultVideoEncoderFactory(
|
||||||
eglBase.getEglBaseContext(), true, true))
|
eglBase.getEglBaseContext(), true, true))
|
||||||
.setAudioDeviceModule(
|
.setAudioDeviceModule(
|
||||||
JavaAudioDeviceModule.builder(context)
|
JavaAudioDeviceModule.builder(requireContext())
|
||||||
.setUseHardwareAcousticEchoCanceler(
|
.setUseHardwareAcousticEchoCanceler(
|
||||||
setUseHardwareAcousticEchoCanceler)
|
setUseHardwareAcousticEchoCanceler)
|
||||||
.createAudioDeviceModule())
|
.createAudioDeviceModule())
|
||||||
|
@ -276,36 +277,18 @@ public class WebRTCWrapper {
|
||||||
|
|
||||||
final PeerConnection.RTCConfiguration rtcConfig = buildConfiguration(iceServers);
|
final PeerConnection.RTCConfiguration rtcConfig = buildConfiguration(iceServers);
|
||||||
final PeerConnection peerConnection =
|
final PeerConnection peerConnection =
|
||||||
peerConnectionFactory.createPeerConnection(rtcConfig, peerConnectionObserver);
|
requirePeerConnectionFactory()
|
||||||
|
.createPeerConnection(rtcConfig, peerConnectionObserver);
|
||||||
if (peerConnection == null) {
|
if (peerConnection == null) {
|
||||||
throw new InitializationException("Unable to create PeerConnection");
|
throw new InitializationException("Unable to create PeerConnection");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Optional<VideoSourceWrapper> optionalVideoSourceWrapper =
|
if (media.contains(Media.VIDEO)) {
|
||||||
media.contains(Media.VIDEO)
|
addVideoTrack(peerConnection);
|
||||||
? 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.AUDIO)) {
|
if (media.contains(Media.AUDIO)) {
|
||||||
// set up audio track
|
addAudioTrack(peerConnection);
|
||||||
final AudioSource audioSource =
|
|
||||||
peerConnectionFactory.createAudioSource(new MediaConstraints());
|
|
||||||
final AudioTrack audioTrack =
|
|
||||||
peerConnectionFactory.createAudioTrack("my-audio-track", audioSource);
|
|
||||||
this.localAudioTrack = TrackWrapper.addTrack(peerConnection, audioTrack);
|
|
||||||
}
|
}
|
||||||
peerConnection.setAudioPlayout(true);
|
peerConnection.setAudioPlayout(true);
|
||||||
peerConnection.setAudioRecording(true);
|
peerConnection.setAudioRecording(true);
|
||||||
|
@ -313,6 +296,58 @@ public class WebRTCWrapper {
|
||||||
this.peerConnection = peerConnection;
|
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(
|
private static PeerConnection.RTCConfiguration buildConfiguration(
|
||||||
final List<PeerConnection.IceServer> iceServers) {
|
final List<PeerConnection.IceServer> iceServers) {
|
||||||
final PeerConnection.RTCConfiguration rtcConfig =
|
final PeerConnection.RTCConfiguration rtcConfig =
|
||||||
|
@ -344,6 +379,7 @@ public class WebRTCWrapper {
|
||||||
|
|
||||||
synchronized void close() {
|
synchronized void close() {
|
||||||
final PeerConnection peerConnection = this.peerConnection;
|
final PeerConnection peerConnection = this.peerConnection;
|
||||||
|
final PeerConnectionFactory peerConnectionFactory = this.peerConnectionFactory;
|
||||||
final VideoSourceWrapper videoSourceWrapper = this.videoSourceWrapper;
|
final VideoSourceWrapper videoSourceWrapper = this.videoSourceWrapper;
|
||||||
final AppRTCAudioManager audioManager = this.appRTCAudioManager;
|
final AppRTCAudioManager audioManager = this.appRTCAudioManager;
|
||||||
final EglBase eglBase = this.eglBase;
|
final EglBase eglBase = this.eglBase;
|
||||||
|
@ -363,12 +399,15 @@ public class WebRTCWrapper {
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
Log.e(Config.LOGTAG, "unable to stop capturing");
|
Log.e(Config.LOGTAG, "unable to stop capturing");
|
||||||
}
|
}
|
||||||
// TODO call dispose
|
videoSourceWrapper.dispose();
|
||||||
}
|
}
|
||||||
if (eglBase != null) {
|
if (eglBase != null) {
|
||||||
eglBase.release();
|
eglBase.release();
|
||||||
this.eglBase = null;
|
this.eglBase = null;
|
||||||
}
|
}
|
||||||
|
if (peerConnectionFactory != null) {
|
||||||
|
peerConnectionFactory.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void verifyClosed() {
|
synchronized void verifyClosed() {
|
||||||
|
@ -530,6 +569,7 @@ public class WebRTCWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
private PeerConnection requirePeerConnection() {
|
private PeerConnection requirePeerConnection() {
|
||||||
final PeerConnection peerConnection = this.peerConnection;
|
final PeerConnection peerConnection = this.peerConnection;
|
||||||
if (peerConnection == null) {
|
if (peerConnection == null) {
|
||||||
|
@ -538,6 +578,15 @@ public class WebRTCWrapper {
|
||||||
return peerConnection;
|
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) {
|
void addIceCandidate(IceCandidate iceCandidate) {
|
||||||
requirePeerConnection().addIceCandidate(iceCandidate);
|
requirePeerConnection().addIceCandidate(iceCandidate);
|
||||||
}
|
}
|
||||||
|
@ -626,5 +675,4 @@ public class WebRTCWrapper {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue