1package eu.siacs.conversations.xmpp.jingle;
2
3import android.util.Log;
4
5import com.google.common.base.CaseFormat;
6import com.google.common.base.Optional;
7import com.google.common.base.Preconditions;
8
9import eu.siacs.conversations.Config;
10
11import org.webrtc.MediaStreamTrack;
12import org.webrtc.PeerConnection;
13import org.webrtc.RtpSender;
14import org.webrtc.RtpTransceiver;
15
16import java.util.UUID;
17
18import javax.annotation.Nonnull;
19import javax.annotation.Nullable;
20
21class TrackWrapper<T extends MediaStreamTrack> {
22 public final T track;
23 public final RtpSender rtpSender;
24
25 private TrackWrapper(final T track, final RtpSender rtpSender) {
26 Preconditions.checkNotNull(track);
27 Preconditions.checkNotNull(rtpSender);
28 this.track = track;
29 this.rtpSender = rtpSender;
30 }
31
32 public static <T extends MediaStreamTrack> TrackWrapper<T> addTrack(
33 final PeerConnection peerConnection, final T mediaStreamTrack) {
34 final RtpSender rtpSender = peerConnection.addTrack(mediaStreamTrack);
35 return new TrackWrapper<>(mediaStreamTrack, rtpSender);
36 }
37
38 public static <T extends MediaStreamTrack> Optional<T> get(
39 @Nullable final PeerConnection peerConnection, final TrackWrapper<T> trackWrapper) {
40 if (trackWrapper == null) {
41 return Optional.absent();
42 }
43 final RtpTransceiver transceiver =
44 peerConnection == null ? null : getTransceiver(peerConnection, trackWrapper);
45 if (transceiver == null) {
46 final String id;
47 try {
48 id = trackWrapper.rtpSender.id();
49 } catch (final IllegalStateException e) {
50 return Optional.absent();
51 }
52 Log.w(Config.LOGTAG, "unable to detect transceiver for " + id);
53 return Optional.of(trackWrapper.track);
54 }
55 final RtpTransceiver.RtpTransceiverDirection direction = transceiver.getDirection();
56 if (direction == RtpTransceiver.RtpTransceiverDirection.SEND_ONLY
57 || direction == RtpTransceiver.RtpTransceiverDirection.SEND_RECV) {
58 return Optional.of(trackWrapper.track);
59 } else {
60 Log.d(Config.LOGTAG, "withholding track because transceiver is " + direction);
61 return Optional.absent();
62 }
63 }
64
65 public static <T extends MediaStreamTrack> RtpTransceiver getTransceiver(
66 @Nonnull final PeerConnection peerConnection, final TrackWrapper<T> trackWrapper) {
67 final RtpSender rtpSender = trackWrapper.rtpSender;
68 for (final RtpTransceiver transceiver : peerConnection.getTransceivers()) {
69 if (transceiver.getSender().id().equals(rtpSender.id())) {
70 return transceiver;
71 }
72 }
73 return null;
74 }
75
76 public static String id(final Class<? extends MediaStreamTrack> clazz) {
77 return String.format(
78 "%s-%s",
79 CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, clazz.getSimpleName()),
80 UUID.randomUUID().toString());
81 }
82}