diff --git a/sdk/android/api/org/webrtc/AudioSource.java b/sdk/android/api/org/webrtc/AudioSource.java index 99fcad1cf8..f8104e5904 100644 --- a/sdk/android/api/org/webrtc/AudioSource.java +++ b/sdk/android/api/org/webrtc/AudioSource.java @@ -18,4 +18,9 @@ public class AudioSource extends MediaSource { public AudioSource(long nativeSource) { super(nativeSource); } + + /** Returns a pointer to webrtc::AudioSourceInterface. */ + long getNativeAudioSource() { + return getNativeMediaSource(); + } } diff --git a/sdk/android/api/org/webrtc/AudioTrack.java b/sdk/android/api/org/webrtc/AudioTrack.java index 828e89c5e5..ca745db634 100644 --- a/sdk/android/api/org/webrtc/AudioTrack.java +++ b/sdk/android/api/org/webrtc/AudioTrack.java @@ -20,7 +20,12 @@ public class AudioTrack extends MediaStreamTrack { * 0 to 10. */ public void setVolume(double volume) { - nativeSetVolume(super.nativeTrack, volume); + nativeSetVolume(getNativeAudioTrack(), volume); + } + + /** Returns a pointer to webrtc::AudioTrackInterface. */ + long getNativeAudioTrack() { + return getNativeMediaStreamTrack(); } private static native void nativeSetVolume(long track, double volume); diff --git a/sdk/android/api/org/webrtc/DataChannel.java b/sdk/android/api/org/webrtc/DataChannel.java index 53ea0d8280..f51dab97af 100644 --- a/sdk/android/api/org/webrtc/DataChannel.java +++ b/sdk/android/api/org/webrtc/DataChannel.java @@ -102,7 +102,7 @@ public class DataChannel { } } - private final long nativeDataChannel; + private long nativeDataChannel; private long nativeObserver; @CalledByNative @@ -112,6 +112,7 @@ public class DataChannel { /** Register |observer|, replacing any previously-registered observer. */ public void registerObserver(Observer observer) { + checkDataChannelExists(); if (nativeObserver != 0) { nativeUnregisterObserver(nativeObserver); } @@ -120,18 +121,22 @@ public class DataChannel { /** Unregister the (only) observer. */ public void unregisterObserver() { + checkDataChannelExists(); nativeUnregisterObserver(nativeObserver); } public String label() { + checkDataChannelExists(); return nativeLabel(); } public int id() { + checkDataChannelExists(); return nativeId(); } public State state() { + checkDataChannelExists(); return nativeState(); } @@ -141,16 +146,19 @@ public class DataChannel { * to the network. */ public long bufferedAmount() { + checkDataChannelExists(); return nativeBufferedAmount(); } /** Close the channel. */ public void close() { + checkDataChannelExists(); nativeClose(); } /** Send |data| to the remote peer; return success. */ public boolean send(Buffer buffer) { + checkDataChannelExists(); // TODO(fischman): this could be cleverer about avoiding copies if the // ByteBuffer is direct and/or is backed by an array. byte[] data = new byte[buffer.data.remaining()]; @@ -160,7 +168,9 @@ public class DataChannel { /** Dispose of native resources attached to this channel. */ public void dispose() { + checkDataChannelExists(); JniCommon.nativeReleaseRef(nativeDataChannel); + nativeDataChannel = 0; } @CalledByNative @@ -168,6 +178,12 @@ public class DataChannel { return nativeDataChannel; } + private void checkDataChannelExists() { + if (nativeDataChannel == 0) { + throw new IllegalStateException("DataChannel has been disposed."); + } + } + private native long nativeRegisterObserver(Observer observer); private native void nativeUnregisterObserver(long observer); private native String nativeLabel(); diff --git a/sdk/android/api/org/webrtc/DtmfSender.java b/sdk/android/api/org/webrtc/DtmfSender.java index 9f203f390e..6549823089 100644 --- a/sdk/android/api/org/webrtc/DtmfSender.java +++ b/sdk/android/api/org/webrtc/DtmfSender.java @@ -12,7 +12,7 @@ package org.webrtc; /** Java wrapper for a C++ DtmfSenderInterface. */ public class DtmfSender { - final long nativeDtmfSender; + private long nativeDtmfSender; public DtmfSender(long nativeDtmfSender) { this.nativeDtmfSender = nativeDtmfSender; @@ -22,6 +22,7 @@ public class DtmfSender { * @return true if this DtmfSender is capable of sending DTMF. Otherwise false. */ public boolean canInsertDtmf() { + checkDtmfSenderExists(); return nativeCanInsertDtmf(nativeDtmfSender); } @@ -43,6 +44,7 @@ public class DtmfSender { * @return true on success and false on failure. */ public boolean insertDtmf(String tones, int duration, int interToneGap) { + checkDtmfSenderExists(); return nativeInsertDtmf(nativeDtmfSender, tones, duration, interToneGap); } @@ -50,6 +52,7 @@ public class DtmfSender { * @return The tones remaining to be played out */ public String tones() { + checkDtmfSenderExists(); return nativeTones(nativeDtmfSender); } @@ -58,6 +61,7 @@ public class DtmfSender { * insertDtmf() method, or the default value of 100 ms if insertDtmf() was never called. */ public int duration() { + checkDtmfSenderExists(); return nativeDuration(nativeDtmfSender); } @@ -67,11 +71,20 @@ public class DtmfSender { * called. */ public int interToneGap() { + checkDtmfSenderExists(); return nativeInterToneGap(nativeDtmfSender); } public void dispose() { + checkDtmfSenderExists(); JniCommon.nativeReleaseRef(nativeDtmfSender); + nativeDtmfSender = 0; + } + + private void checkDtmfSenderExists() { + if (nativeDtmfSender == 0) { + throw new IllegalStateException("DtmfSender has been disposed."); + } } private static native boolean nativeCanInsertDtmf(long dtmfSender); diff --git a/sdk/android/api/org/webrtc/MediaSource.java b/sdk/android/api/org/webrtc/MediaSource.java index 3f20dd7353..0b19e1a775 100644 --- a/sdk/android/api/org/webrtc/MediaSource.java +++ b/sdk/android/api/org/webrtc/MediaSource.java @@ -25,18 +25,33 @@ public class MediaSource { } } - final long nativeSource; // Package-protected for PeerConnectionFactory. + private long nativeSource; public MediaSource(long nativeSource) { this.nativeSource = nativeSource; } public State state() { + checkMediaSourceExists(); return nativeGetState(nativeSource); } public void dispose() { + checkMediaSourceExists(); JniCommon.nativeReleaseRef(nativeSource); + nativeSource = 0; + } + + /** Returns a pointer to webrtc::MediaSourceInterface. */ + protected long getNativeMediaSource() { + checkMediaSourceExists(); + return nativeSource; + } + + private void checkMediaSourceExists() { + if (nativeSource == 0) { + throw new IllegalStateException("MediaSource has been disposed."); + } } private static native State nativeGetState(long pointer); diff --git a/sdk/android/api/org/webrtc/MediaStream.java b/sdk/android/api/org/webrtc/MediaStream.java index 7f4a43402d..e530fe5f7f 100644 --- a/sdk/android/api/org/webrtc/MediaStream.java +++ b/sdk/android/api/org/webrtc/MediaStream.java @@ -11,8 +11,8 @@ package org.webrtc; import java.util.ArrayList; -import java.util.List; import java.util.Iterator; +import java.util.List; /** Java wrapper for a C++ MediaStreamInterface. */ public class MediaStream { @@ -21,8 +21,7 @@ public class MediaStream { public final List audioTracks = new ArrayList<>(); public final List videoTracks = new ArrayList<>(); public final List preservedVideoTracks = new ArrayList<>(); - // Package-protected for PeerConnection. - final long nativeStream; + private long nativeStream; @CalledByNative public MediaStream(long nativeStream) { @@ -30,7 +29,8 @@ public class MediaStream { } public boolean addTrack(AudioTrack track) { - if (nativeAddAudioTrackToNativeStream(nativeStream, track.nativeTrack)) { + checkMediaStreamExists(); + if (nativeAddAudioTrackToNativeStream(nativeStream, track.getNativeAudioTrack())) { audioTracks.add(track); return true; } @@ -38,7 +38,8 @@ public class MediaStream { } public boolean addTrack(VideoTrack track) { - if (nativeAddVideoTrackToNativeStream(nativeStream, track.nativeTrack)) { + checkMediaStreamExists(); + if (nativeAddVideoTrackToNativeStream(nativeStream, track.getNativeVideoTrack())) { videoTracks.add(track); return true; } @@ -49,7 +50,8 @@ public class MediaStream { // is called. If video track need to be preserved after MediaStream is destroyed it // should be added to MediaStream using addPreservedTrack() call. public boolean addPreservedTrack(VideoTrack track) { - if (nativeAddVideoTrackToNativeStream(nativeStream, track.nativeTrack)) { + checkMediaStreamExists(); + if (nativeAddVideoTrackToNativeStream(nativeStream, track.getNativeVideoTrack())) { preservedVideoTracks.add(track); return true; } @@ -57,18 +59,21 @@ public class MediaStream { } public boolean removeTrack(AudioTrack track) { + checkMediaStreamExists(); audioTracks.remove(track); - return nativeRemoveAudioTrack(nativeStream, track.nativeTrack); + return nativeRemoveAudioTrack(nativeStream, track.getNativeAudioTrack()); } public boolean removeTrack(VideoTrack track) { + checkMediaStreamExists(); videoTracks.remove(track); preservedVideoTracks.remove(track); - return nativeRemoveVideoTrack(nativeStream, track.nativeTrack); + return nativeRemoveVideoTrack(nativeStream, track.getNativeVideoTrack()); } @CalledByNative public void dispose() { + checkMediaStreamExists(); // Remove and release previously added audio and video tracks. while (!audioTracks.isEmpty()) { AudioTrack track = audioTracks.get(0 /* index */); @@ -85,9 +90,11 @@ public class MediaStream { removeTrack(preservedVideoTracks.get(0 /* index */)); } JniCommon.nativeReleaseRef(nativeStream); + nativeStream = 0; } public String getId() { + checkMediaStreamExists(); return nativeGetId(nativeStream); } @@ -116,12 +123,24 @@ public class MediaStream { removeMediaStreamTrack(videoTracks, nativeTrack); } + /** Returns a pointer to webrtc::MediaStreamInterface. */ + long getNativeMediaStream() { + checkMediaStreamExists(); + return nativeStream; + } + + private void checkMediaStreamExists() { + if (nativeStream == 0) { + throw new IllegalStateException("MediaStream has been disposed."); + } + } + private static void removeMediaStreamTrack( List tracks, long nativeTrack) { final Iterator it = tracks.iterator(); while (it.hasNext()) { MediaStreamTrack track = it.next(); - if (track.nativeTrack == nativeTrack) { + if (track.getNativeMediaStreamTrack() == nativeTrack) { track.dispose(); it.remove(); return; diff --git a/sdk/android/api/org/webrtc/MediaStreamTrack.java b/sdk/android/api/org/webrtc/MediaStreamTrack.java index 198da1e3e8..944c7ef1b2 100644 --- a/sdk/android/api/org/webrtc/MediaStreamTrack.java +++ b/sdk/android/api/org/webrtc/MediaStreamTrack.java @@ -70,34 +70,52 @@ public class MediaStreamTrack { } } - final long nativeTrack; + private long nativeTrack; public MediaStreamTrack(long nativeTrack) { this.nativeTrack = nativeTrack; } public String id() { + checkMediaStreamTrackExists(); return nativeGetId(nativeTrack); } public String kind() { + checkMediaStreamTrackExists(); return nativeGetKind(nativeTrack); } public boolean enabled() { + checkMediaStreamTrackExists(); return nativeGetEnabled(nativeTrack); } public boolean setEnabled(boolean enable) { + checkMediaStreamTrackExists(); return nativeSetEnabled(nativeTrack, enable); } public State state() { + checkMediaStreamTrackExists(); return nativeGetState(nativeTrack); } public void dispose() { + checkMediaStreamTrackExists(); JniCommon.nativeReleaseRef(nativeTrack); + nativeTrack = 0; + } + + long getNativeMediaStreamTrack() { + checkMediaStreamTrackExists(); + return nativeTrack; + } + + private void checkMediaStreamTrackExists() { + if (nativeTrack == 0) { + throw new IllegalStateException("MediaStreamTrack has been disposed."); + } } private static native String nativeGetId(long track); diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index 2f9adcf962..84d49ebb8a 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java @@ -781,7 +781,7 @@ public class PeerConnection { * use addTrack instead. */ public boolean addStream(MediaStream stream) { - boolean ret = nativeAddLocalStream(stream.nativeStream); + boolean ret = nativeAddLocalStream(stream.getNativeMediaStream()); if (!ret) { return false; } @@ -795,7 +795,7 @@ public class PeerConnection { * removeTrack instead. */ public void removeStream(MediaStream stream) { - nativeRemoveLocalStream(stream.nativeStream); + nativeRemoveLocalStream(stream.getNativeMediaStream()); localStreams.remove(stream); } @@ -905,7 +905,7 @@ public class PeerConnection { if (track == null || streamIds == null) { throw new NullPointerException("No MediaStreamTrack specified in addTrack."); } - RtpSender newSender = nativeAddTrack(track.nativeTrack, streamIds); + RtpSender newSender = nativeAddTrack(track.getNativeMediaStreamTrack(), streamIds); if (newSender == null) { throw new IllegalStateException("C++ addTrack failed."); } @@ -922,7 +922,7 @@ public class PeerConnection { if (sender == null) { throw new NullPointerException("No RtpSender specified for removeTrack."); } - return nativeRemoveTrack(sender.nativeRtpSender); + return nativeRemoveTrack(sender.getNativeRtpSender()); } /** @@ -962,7 +962,8 @@ public class PeerConnection { if (init == null) { init = new RtpTransceiver.RtpTransceiverInit(); } - RtpTransceiver newTransceiver = nativeAddTransceiverWithTrack(track.nativeTrack, init); + RtpTransceiver newTransceiver = + nativeAddTransceiverWithTrack(track.getNativeMediaStreamTrack(), init); if (newTransceiver == null) { throw new IllegalStateException("C++ addTransceiver failed."); } @@ -993,7 +994,7 @@ public class PeerConnection { // Older, non-standard implementation of getStats. @Deprecated public boolean getStats(StatsObserver observer, @Nullable MediaStreamTrack track) { - return nativeOldGetStats(observer, (track == null) ? 0 : track.nativeTrack); + return nativeOldGetStats(observer, (track == null) ? 0 : track.getNativeMediaStreamTrack()); } /** @@ -1070,7 +1071,7 @@ public class PeerConnection { public void dispose() { close(); for (MediaStream stream : localStreams) { - nativeRemoveLocalStream(stream.nativeStream); + nativeRemoveLocalStream(stream.getNativeMediaStream()); stream.dispose(); } localStreams.clear(); diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java index 672bd0e726..eb98e923f6 100644 --- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java +++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java @@ -28,7 +28,7 @@ public class PeerConnectionFactory { private static final String TAG = "PeerConnectionFactory"; private static final String VIDEO_CAPTURER_THREAD_NAME = "VideoCapturerThread"; - private final long nativeFactory; + private long nativeFactory; private static volatile boolean internalTracerInitialized; @Nullable private static Thread networkThread; @Nullable private static Thread workerThread; @@ -307,6 +307,7 @@ public class PeerConnectionFactory { PeerConnection createPeerConnectionInternal(PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, PeerConnection.Observer observer, SSLCertificateVerifier sslCertificateVerifier) { + checkPeerConnectionFactoryExists(); long nativeObserver = PeerConnection.createNativePeerConnectionObserver(observer); if (nativeObserver == 0) { return null; @@ -364,61 +365,80 @@ public class PeerConnectionFactory { } public MediaStream createLocalMediaStream(String label) { + checkPeerConnectionFactoryExists(); return new MediaStream(nativeCreateLocalMediaStream(nativeFactory, label)); } public VideoSource createVideoSource(boolean isScreencast) { + checkPeerConnectionFactoryExists(); return new VideoSource(nativeCreateVideoSource(nativeFactory, isScreencast)); } public VideoTrack createVideoTrack(String id, VideoSource source) { - return new VideoTrack(nativeCreateVideoTrack(nativeFactory, id, source.nativeSource)); + checkPeerConnectionFactoryExists(); + return new VideoTrack( + nativeCreateVideoTrack(nativeFactory, id, source.getNativeVideoTrackSource())); } public AudioSource createAudioSource(MediaConstraints constraints) { + checkPeerConnectionFactoryExists(); return new AudioSource(nativeCreateAudioSource(nativeFactory, constraints)); } public AudioTrack createAudioTrack(String id, AudioSource source) { - return new AudioTrack(nativeCreateAudioTrack(nativeFactory, id, source.nativeSource)); + checkPeerConnectionFactoryExists(); + return new AudioTrack(nativeCreateAudioTrack(nativeFactory, id, source.getNativeAudioSource())); } // Starts recording an AEC dump. Ownership of the file is transfered to the // native code. If an AEC dump is already in progress, it will be stopped and // a new one will start using the provided file. public boolean startAecDump(int file_descriptor, int filesize_limit_bytes) { + checkPeerConnectionFactoryExists(); return nativeStartAecDump(nativeFactory, file_descriptor, filesize_limit_bytes); } // Stops recording an AEC dump. If no AEC dump is currently being recorded, // this call will have no effect. public void stopAecDump() { + checkPeerConnectionFactoryExists(); nativeStopAecDump(nativeFactory); } public void dispose() { + checkPeerConnectionFactoryExists(); nativeFreeFactory(nativeFactory); networkThread = null; workerThread = null; signalingThread = null; MediaCodecVideoEncoder.disposeEglContext(); MediaCodecVideoDecoder.disposeEglContext(); + nativeFactory = 0; } public void threadsCallbacks() { + checkPeerConnectionFactoryExists(); nativeInvokeThreadsCallbacks(nativeFactory); } /** Returns a pointer to the native webrtc::PeerConnectionFactoryInterface. */ public long getNativePeerConnectionFactory() { + checkPeerConnectionFactoryExists(); return nativeGetNativePeerConnectionFactory(nativeFactory); } /** Returns a pointer to the native OwnedFactoryAndThreads object */ public long getNativeOwnedFactoryAndThreads() { + checkPeerConnectionFactoryExists(); return nativeFactory; } + private void checkPeerConnectionFactoryExists() { + if (nativeFactory == 0) { + throw new IllegalStateException("PeerConnectionFactory has been disposed."); + } + } + private static void printStackTrace(@Nullable Thread thread, String threadName) { if (thread != null) { StackTraceElement[] stackTraces = thread.getStackTrace(); diff --git a/sdk/android/api/org/webrtc/RtpReceiver.java b/sdk/android/api/org/webrtc/RtpReceiver.java index 4da7537855..8be494f196 100644 --- a/sdk/android/api/org/webrtc/RtpReceiver.java +++ b/sdk/android/api/org/webrtc/RtpReceiver.java @@ -22,7 +22,7 @@ public class RtpReceiver { public void onFirstPacketReceived(MediaStreamTrack.MediaType media_type); } - final long nativeRtpReceiver; + private long nativeRtpReceiver; private long nativeObserver; @Nullable private MediaStreamTrack cachedTrack; @@ -40,28 +40,34 @@ public class RtpReceiver { } public boolean setParameters(@Nullable RtpParameters parameters) { + checkRtpReceiverExists(); return parameters == null ? false : nativeSetParameters(nativeRtpReceiver, parameters); } public RtpParameters getParameters() { + checkRtpReceiverExists(); return nativeGetParameters(nativeRtpReceiver); } public String id() { + checkRtpReceiverExists(); return nativeGetId(nativeRtpReceiver); } @CalledByNative public void dispose() { + checkRtpReceiverExists(); cachedTrack.dispose(); if (nativeObserver != 0) { nativeUnsetObserver(nativeRtpReceiver, nativeObserver); nativeObserver = 0; } JniCommon.nativeReleaseRef(nativeRtpReceiver); + nativeRtpReceiver = 0; } public void SetObserver(Observer observer) { + checkRtpReceiverExists(); // Unset the existing one before setting a new one. if (nativeObserver != 0) { nativeUnsetObserver(nativeRtpReceiver, nativeObserver); @@ -70,9 +76,16 @@ public class RtpReceiver { } public void setFrameDecryptor(FrameDecryptor frameDecryptor) { + checkRtpReceiverExists(); nativeSetFrameDecryptor(nativeRtpReceiver, frameDecryptor.getNativeFrameDecryptor()); } + private void checkRtpReceiverExists() { + if (nativeRtpReceiver == 0) { + throw new IllegalStateException("RtpReceiver has been disposed."); + } + } + // This should increment the reference count of the track. // Will be released in dispose(). private static native long nativeGetTrack(long rtpReceiver); diff --git a/sdk/android/api/org/webrtc/RtpSender.java b/sdk/android/api/org/webrtc/RtpSender.java index e2a993282d..9d7451d839 100644 --- a/sdk/android/api/org/webrtc/RtpSender.java +++ b/sdk/android/api/org/webrtc/RtpSender.java @@ -14,7 +14,7 @@ import javax.annotation.Nullable; /** Java wrapper for a C++ RtpSenderInterface. */ public class RtpSender { - final long nativeRtpSender; + private long nativeRtpSender; @Nullable private MediaStreamTrack cachedTrack; private boolean ownsTrack = true; @@ -45,7 +45,8 @@ public class RtpSender { * @return true on success and false on failure. */ public boolean setTrack(@Nullable MediaStreamTrack track, boolean takeOwnership) { - if (!nativeSetTrack(nativeRtpSender, (track == null) ? 0 : track.nativeTrack)) { + checkRtpSenderExists(); + if (!nativeSetTrack(nativeRtpSender, (track == null) ? 0 : track.getNativeMediaStreamTrack())) { return false; } if (cachedTrack != null && ownsTrack) { @@ -62,14 +63,17 @@ public class RtpSender { } public boolean setParameters(RtpParameters parameters) { + checkRtpSenderExists(); return nativeSetParameters(nativeRtpSender, parameters); } public RtpParameters getParameters() { + checkRtpSenderExists(); return nativeGetParameters(nativeRtpSender); } public String id() { + checkRtpSenderExists(); return nativeGetId(nativeRtpSender); } @@ -79,10 +83,12 @@ public class RtpSender { } public void setFrameEncryptor(FrameEncryptor frameEncryptor) { + checkRtpSenderExists(); nativeSetFrameEncryptor(nativeRtpSender, frameEncryptor.getNativeFrameEncryptor()); } public void dispose() { + checkRtpSenderExists(); if (dtmfSender != null) { dtmfSender.dispose(); } @@ -90,6 +96,19 @@ public class RtpSender { cachedTrack.dispose(); } JniCommon.nativeReleaseRef(nativeRtpSender); + nativeRtpSender = 0; + } + + /** Returns a pointer to webrtc::RtpSenderInterface. */ + long getNativeRtpSender() { + checkRtpSenderExists(); + return nativeRtpSender; + } + + private void checkRtpSenderExists() { + if (nativeRtpSender == 0) { + throw new IllegalStateException("RtpSender has been disposed."); + } } private static native boolean nativeSetTrack(long rtpSender, long nativeTrack); diff --git a/sdk/android/api/org/webrtc/RtpTransceiver.java b/sdk/android/api/org/webrtc/RtpTransceiver.java index 93326a41a3..a4a5aa0540 100644 --- a/sdk/android/api/org/webrtc/RtpTransceiver.java +++ b/sdk/android/api/org/webrtc/RtpTransceiver.java @@ -13,7 +13,6 @@ package org.webrtc; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.webrtc.RtpParameters.Encoding; /** * Java wrapper for a C++ RtpTransceiverInterface. @@ -96,7 +95,7 @@ public class RtpTransceiver { } } - private final long nativeRtpTransceiver; + private long nativeRtpTransceiver; private RtpSender cachedSender; private RtpReceiver cachedReceiver; @@ -112,6 +111,7 @@ public class RtpTransceiver { * type as well. */ public MediaStreamTrack.MediaType getMediaType() { + checkRtpTransceiverExists(); return nativeGetMediaType(nativeRtpTransceiver); } @@ -122,6 +122,7 @@ public class RtpTransceiver { * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid */ public String getMid() { + checkRtpTransceiverExists(); return nativeGetMid(nativeRtpTransceiver); } @@ -153,6 +154,7 @@ public class RtpTransceiver { * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped */ public boolean isStopped() { + checkRtpTransceiverExists(); return nativeStopped(nativeRtpTransceiver); } @@ -162,6 +164,7 @@ public class RtpTransceiver { * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction */ public RtpTransceiverDirection getDirection() { + checkRtpTransceiverExists(); return nativeDirection(nativeRtpTransceiver); } @@ -172,6 +175,7 @@ public class RtpTransceiver { * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection */ public RtpTransceiverDirection getCurrentDirection() { + checkRtpTransceiverExists(); return nativeCurrentDirection(nativeRtpTransceiver); } @@ -183,6 +187,7 @@ public class RtpTransceiver { * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction */ public void setDirection(RtpTransceiverDirection rtpTransceiverDirection) { + checkRtpTransceiverExists(); nativeSetDirection(nativeRtpTransceiver, rtpTransceiverDirection); } @@ -192,14 +197,23 @@ public class RtpTransceiver { * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop */ public void stop() { + checkRtpTransceiverExists(); nativeStop(nativeRtpTransceiver); } @CalledByNative public void dispose() { + checkRtpTransceiverExists(); cachedSender.dispose(); cachedReceiver.dispose(); JniCommon.nativeReleaseRef(nativeRtpTransceiver); + nativeRtpTransceiver = 0; + } + + private void checkRtpTransceiverExists() { + if (nativeRtpTransceiver == 0) { + throw new IllegalStateException("RtpTransceiver has been disposed."); + } } private static native MediaStreamTrack.MediaType nativeGetMediaType(long rtpTransceiver); diff --git a/sdk/android/api/org/webrtc/TurnCustomizer.java b/sdk/android/api/org/webrtc/TurnCustomizer.java index bfc72ea2d0..41bedb7dcb 100644 --- a/sdk/android/api/org/webrtc/TurnCustomizer.java +++ b/sdk/android/api/org/webrtc/TurnCustomizer.java @@ -12,20 +12,30 @@ package org.webrtc; /** Java wrapper for a C++ TurnCustomizer. */ public class TurnCustomizer { - final long nativeTurnCustomizer; + private long nativeTurnCustomizer; public TurnCustomizer(long nativeTurnCustomizer) { this.nativeTurnCustomizer = nativeTurnCustomizer; } public void dispose() { + checkTurnCustomizerExists(); nativeFreeTurnCustomizer(nativeTurnCustomizer); + nativeTurnCustomizer = 0; } private static native void nativeFreeTurnCustomizer(long turnCustomizer); + /** Return a pointer to webrtc::TurnCustomizer. */ @CalledByNative long getNativeTurnCustomizer() { + checkTurnCustomizerExists(); return nativeTurnCustomizer; } + + private void checkTurnCustomizerExists() { + if (nativeTurnCustomizer == 0) { + throw new IllegalStateException("TurnCustomizer has been disposed."); + } + } } diff --git a/sdk/android/api/org/webrtc/VideoSource.java b/sdk/android/api/org/webrtc/VideoSource.java index e0c61675bc..7f9f3e5323 100644 --- a/sdk/android/api/org/webrtc/VideoSource.java +++ b/sdk/android/api/org/webrtc/VideoSource.java @@ -30,13 +30,18 @@ public class VideoSource extends MediaSource { * maintain the input orientation, so it doesn't matter if e.g. 1280x720 or 720x1280 is requested. */ public void adaptOutputFormat(int width, int height, int fps) { - nativeAdaptOutputFormat(nativeSource, width, height, fps); + nativeAdaptOutputFormat(getNativeVideoTrackSource(), width, height, fps); } public CapturerObserver getCapturerObserver() { return capturerObserver; } + /** Returns a pointer to webrtc::VideoTrackSourceInterface. */ + long getNativeVideoTrackSource() { + return getNativeMediaSource(); + } + // Returns source->internal() from webrtc::VideoTrackSourceProxy. private static native long nativeGetInternalSource(long source); private static native void nativeAdaptOutputFormat(long source, int width, int height, int fps); diff --git a/sdk/android/api/org/webrtc/VideoTrack.java b/sdk/android/api/org/webrtc/VideoTrack.java index 5495ee82b1..5e33e1e5f1 100644 --- a/sdk/android/api/org/webrtc/VideoTrack.java +++ b/sdk/android/api/org/webrtc/VideoTrack.java @@ -10,8 +10,8 @@ package org.webrtc; -import java.util.IdentityHashMap; import java.util.ArrayList; +import java.util.IdentityHashMap; import java.util.List; /** Java version of VideoTrackInterface. */ @@ -39,7 +39,7 @@ public class VideoTrack extends MediaStreamTrack { if (!sinks.containsKey(sink)) { final long nativeSink = nativeWrapSink(sink); sinks.put(sink, nativeSink); - nativeAddSink(nativeTrack, nativeSink); + nativeAddSink(getNativeMediaStreamTrack(), nativeSink); } } @@ -51,7 +51,7 @@ public class VideoTrack extends MediaStreamTrack { public void removeSink(VideoSink sink) { final Long nativeSink = sinks.remove(sink); if (nativeSink != null) { - nativeRemoveSink(nativeTrack, nativeSink); + nativeRemoveSink(getNativeMediaStreamTrack(), nativeSink); nativeFreeSink(nativeSink); } } @@ -59,13 +59,18 @@ public class VideoTrack extends MediaStreamTrack { @Override public void dispose() { for (long nativeSink : sinks.values()) { - nativeRemoveSink(nativeTrack, nativeSink); + nativeRemoveSink(getNativeMediaStreamTrack(), nativeSink); nativeFreeSink(nativeSink); } sinks.clear(); super.dispose(); } + /** Returns a pointer to webrtc::VideoTrackInterface. */ + long getNativeVideoTrack() { + return getNativeMediaStreamTrack(); + } + private static native void nativeAddSink(long track, long nativeSink); private static native void nativeRemoveSink(long track, long nativeSink); private static native long nativeWrapSink(VideoSink sink);