TrackWrapper.java

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