Make PeerConnectionClient non-singleton.
Ownership of EglBase is moved to PeerConnectionClient. BUG=webrtc:8135 Review-Url: https://codereview.webrtc.org/3007893002 Cr-Commit-Position: refs/heads/master@{#19634}
This commit is contained in:
@ -45,7 +45,6 @@ import org.appspot.apprtc.PeerConnectionClient.PeerConnectionParameters;
|
||||
import org.webrtc.Camera1Enumerator;
|
||||
import org.webrtc.Camera2Enumerator;
|
||||
import org.webrtc.CameraEnumerator;
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.FileVideoCapturer;
|
||||
import org.webrtc.IceCandidate;
|
||||
import org.webrtc.Logging;
|
||||
@ -162,7 +161,6 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
private AppRTCClient appRtcClient;
|
||||
private SignalingParameters signalingParameters;
|
||||
private AppRTCAudioManager audioManager = null;
|
||||
private EglBase rootEglBase;
|
||||
private SurfaceViewRenderer pipRenderer;
|
||||
private SurfaceViewRenderer fullscreenRenderer;
|
||||
private VideoFileRenderer videoFileRenderer;
|
||||
@ -234,9 +232,11 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
|
||||
final Intent intent = getIntent();
|
||||
|
||||
// Create peer connection client.
|
||||
peerConnectionClient = new PeerConnectionClient();
|
||||
|
||||
// Create video renderers.
|
||||
rootEglBase = EglBase.create();
|
||||
pipRenderer.init(rootEglBase.getEglBaseContext(), null);
|
||||
pipRenderer.init(peerConnectionClient.getRenderContext(), null);
|
||||
pipRenderer.setScalingType(ScalingType.SCALE_ASPECT_FIT);
|
||||
String saveRemoteVideoToFile = intent.getStringExtra(EXTRA_SAVE_REMOTE_VIDEO_TO_FILE);
|
||||
|
||||
@ -245,15 +245,15 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
int videoOutWidth = intent.getIntExtra(EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_WIDTH, 0);
|
||||
int videoOutHeight = intent.getIntExtra(EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT, 0);
|
||||
try {
|
||||
videoFileRenderer = new VideoFileRenderer(
|
||||
saveRemoteVideoToFile, videoOutWidth, videoOutHeight, rootEglBase.getEglBaseContext());
|
||||
videoFileRenderer = new VideoFileRenderer(saveRemoteVideoToFile, videoOutWidth,
|
||||
videoOutHeight, peerConnectionClient.getRenderContext());
|
||||
remoteRenderers.add(videoFileRenderer);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Failed to open video file for output: " + saveRemoteVideoToFile, e);
|
||||
}
|
||||
}
|
||||
fullscreenRenderer.init(rootEglBase.getEglBaseContext(), null);
|
||||
fullscreenRenderer.init(peerConnectionClient.getRenderContext(), null);
|
||||
fullscreenRenderer.setScalingType(ScalingType.SCALE_ASPECT_FILL);
|
||||
|
||||
pipRenderer.setZOrderMediaOverlay(true);
|
||||
@ -368,7 +368,6 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
}, runTimeMs);
|
||||
}
|
||||
|
||||
peerConnectionClient = PeerConnectionClient.getInstance();
|
||||
if (loopback) {
|
||||
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
|
||||
options.networkIgnoreMask = 0;
|
||||
@ -507,7 +506,6 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
logToast.cancel();
|
||||
}
|
||||
activityRunning = false;
|
||||
rootEglBase.release();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@ -623,10 +621,6 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
appRtcClient.disconnectFromRoom();
|
||||
appRtcClient = null;
|
||||
}
|
||||
if (peerConnectionClient != null) {
|
||||
peerConnectionClient.close();
|
||||
peerConnectionClient = null;
|
||||
}
|
||||
if (pipRenderer != null) {
|
||||
pipRenderer.release();
|
||||
pipRenderer = null;
|
||||
@ -639,6 +633,10 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
fullscreenRenderer.release();
|
||||
fullscreenRenderer = null;
|
||||
}
|
||||
if (peerConnectionClient != null) {
|
||||
peerConnectionClient.close();
|
||||
peerConnectionClient = null;
|
||||
}
|
||||
if (audioManager != null) {
|
||||
audioManager.stop();
|
||||
audioManager = null;
|
||||
@ -747,8 +745,8 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
||||
if (peerConnectionParameters.videoCallEnabled) {
|
||||
videoCapturer = createVideoCapturer();
|
||||
}
|
||||
peerConnectionClient.createPeerConnection(rootEglBase.getEglBaseContext(), localProxyRenderer,
|
||||
remoteRenderers, videoCapturer, signalingParameters);
|
||||
peerConnectionClient.createPeerConnection(
|
||||
localProxyRenderer, remoteRenderers, videoCapturer, signalingParameters);
|
||||
|
||||
if (signalingParameters.initiator) {
|
||||
logAndToast("Creating OFFER...");
|
||||
|
||||
@ -103,11 +103,15 @@ public class PeerConnectionClient {
|
||||
private static final int HD_VIDEO_HEIGHT = 720;
|
||||
private static final int BPS_IN_KBPS = 1000;
|
||||
|
||||
private static final PeerConnectionClient instance = new PeerConnectionClient();
|
||||
// Executor thread is started once in private ctor and is used for all
|
||||
// peer connection API calls to ensure new peer connection factory is
|
||||
// created on the same thread as previously destroyed factory.
|
||||
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final PCObserver pcObserver = new PCObserver();
|
||||
private final SDPObserver sdpObserver = new SDPObserver();
|
||||
private final ExecutorService executor;
|
||||
|
||||
private final EglBase rootEglBase;
|
||||
private PeerConnectionFactory factory;
|
||||
private PeerConnection peerConnection;
|
||||
PeerConnectionFactory.Options options = null;
|
||||
@ -288,15 +292,8 @@ public class PeerConnectionClient {
|
||||
void onPeerConnectionError(final String description);
|
||||
}
|
||||
|
||||
private PeerConnectionClient() {
|
||||
// Executor thread is started once in private ctor and is used for all
|
||||
// peer connection API calls to ensure new peer connection factory is
|
||||
// created on the same thread as previously destroyed factory.
|
||||
executor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
public static PeerConnectionClient getInstance() {
|
||||
return instance;
|
||||
public PeerConnectionClient() {
|
||||
rootEglBase = EglBase.create();
|
||||
}
|
||||
|
||||
public void setPeerConnectionFactoryOptions(PeerConnectionFactory.Options options) {
|
||||
@ -335,15 +332,15 @@ public class PeerConnectionClient {
|
||||
});
|
||||
}
|
||||
|
||||
public void createPeerConnection(final EglBase.Context renderEGLContext,
|
||||
final VideoRenderer.Callbacks localRender, final VideoRenderer.Callbacks remoteRender,
|
||||
final VideoCapturer videoCapturer, final SignalingParameters signalingParameters) {
|
||||
createPeerConnection(renderEGLContext, localRender, Collections.singletonList(remoteRender),
|
||||
videoCapturer, signalingParameters);
|
||||
public void createPeerConnection(final VideoRenderer.Callbacks localRender,
|
||||
final VideoRenderer.Callbacks remoteRender, final VideoCapturer videoCapturer,
|
||||
final SignalingParameters signalingParameters) {
|
||||
createPeerConnection(
|
||||
localRender, Collections.singletonList(remoteRender), videoCapturer, signalingParameters);
|
||||
}
|
||||
public void createPeerConnection(final EglBase.Context renderEGLContext,
|
||||
final VideoRenderer.Callbacks localRender, final List<VideoRenderer.Callbacks> remoteRenders,
|
||||
final VideoCapturer videoCapturer, final SignalingParameters signalingParameters) {
|
||||
public void createPeerConnection(final VideoRenderer.Callbacks localRender,
|
||||
final List<VideoRenderer.Callbacks> remoteRenders, final VideoCapturer videoCapturer,
|
||||
final SignalingParameters signalingParameters) {
|
||||
if (peerConnectionParameters == null) {
|
||||
Log.e(TAG, "Creating peer connection without initializing factory.");
|
||||
return;
|
||||
@ -357,7 +354,7 @@ public class PeerConnectionClient {
|
||||
public void run() {
|
||||
try {
|
||||
createMediaConstraintsInternal();
|
||||
createPeerConnectionInternal(renderEGLContext);
|
||||
createPeerConnectionInternal();
|
||||
} catch (Exception e) {
|
||||
reportError("Failed to create peer connection: " + e.getMessage());
|
||||
throw e;
|
||||
@ -583,7 +580,7 @@ public class PeerConnectionClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void createPeerConnectionInternal(EglBase.Context renderEGLContext) {
|
||||
private void createPeerConnectionInternal() {
|
||||
if (factory == null || isError) {
|
||||
Log.e(TAG, "Peerconnection factory is not created");
|
||||
return;
|
||||
@ -594,8 +591,8 @@ public class PeerConnectionClient {
|
||||
queuedRemoteCandidates = new LinkedList<IceCandidate>();
|
||||
|
||||
if (videoCallEnabled) {
|
||||
Log.d(TAG, "EGLContext: " + renderEGLContext);
|
||||
factory.setVideoHwAccelerationOptions(renderEGLContext, renderEGLContext);
|
||||
factory.setVideoHwAccelerationOptions(
|
||||
rootEglBase.getEglBaseContext(), rootEglBase.getEglBaseContext());
|
||||
}
|
||||
|
||||
PeerConnection.RTCConfiguration rtcConfig =
|
||||
@ -698,6 +695,7 @@ public class PeerConnectionClient {
|
||||
factory = null;
|
||||
}
|
||||
options = null;
|
||||
rootEglBase.release();
|
||||
Log.d(TAG, "Closing peer connection done.");
|
||||
events.onPeerConnectionClosed();
|
||||
PeerConnectionFactory.stopInternalTracingCapture();
|
||||
@ -713,6 +711,10 @@ public class PeerConnectionClient {
|
||||
return videoWidth * videoHeight >= 1280 * 720;
|
||||
}
|
||||
|
||||
public EglBase.Context getRenderContext() {
|
||||
return rootEglBase.getEglBaseContext();
|
||||
}
|
||||
|
||||
private void getStats() {
|
||||
if (peerConnection == null || isError) {
|
||||
return;
|
||||
|
||||
@ -35,7 +35,6 @@ import org.junit.runner.RunWith;
|
||||
import org.webrtc.Camera1Enumerator;
|
||||
import org.webrtc.Camera2Enumerator;
|
||||
import org.webrtc.CameraEnumerator;
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.IceCandidate;
|
||||
import org.webrtc.MediaCodecVideoEncoder;
|
||||
import org.webrtc.PeerConnection;
|
||||
@ -73,9 +72,6 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
private volatile PeerConnectionClient pcClient;
|
||||
private volatile boolean loopback;
|
||||
|
||||
// EGL context that can be used by hardware video decoders to decode to a texture.
|
||||
private EglBase eglBase;
|
||||
|
||||
// These are protected by their respective event objects.
|
||||
private ExecutorService signalingExecutor;
|
||||
private boolean isClosed;
|
||||
@ -242,22 +238,21 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
|
||||
PeerConnectionClient createPeerConnectionClient(MockRenderer localRenderer,
|
||||
MockRenderer remoteRenderer, PeerConnectionParameters peerConnectionParameters,
|
||||
VideoCapturer videoCapturer, EglBase.Context eglContext) {
|
||||
VideoCapturer videoCapturer) {
|
||||
List<PeerConnection.IceServer> iceServers = new LinkedList<PeerConnection.IceServer>();
|
||||
SignalingParameters signalingParameters =
|
||||
new SignalingParameters(iceServers, true, // iceServers, initiator.
|
||||
null, null, null, // clientId, wssUrl, wssPostUrl.
|
||||
null, null); // offerSdp, iceCandidates.
|
||||
|
||||
PeerConnectionClient client = PeerConnectionClient.getInstance();
|
||||
PeerConnectionClient client = new PeerConnectionClient();
|
||||
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
|
||||
options.networkIgnoreMask = 0;
|
||||
options.disableNetworkMonitor = true;
|
||||
client.setPeerConnectionFactoryOptions(options);
|
||||
client.createPeerConnectionFactory(
|
||||
InstrumentationRegistry.getTargetContext(), peerConnectionParameters, this);
|
||||
client.createPeerConnection(
|
||||
eglContext, localRenderer, remoteRenderer, videoCapturer, signalingParameters);
|
||||
client.createPeerConnection(localRenderer, remoteRenderer, videoCapturer, signalingParameters);
|
||||
client.createOffer();
|
||||
return client;
|
||||
}
|
||||
@ -327,17 +322,11 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
@Before
|
||||
public void setUp() {
|
||||
signalingExecutor = Executors.newSingleThreadExecutor();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
eglBase = EglBase.create();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
signalingExecutor.shutdown();
|
||||
if (eglBase != null) {
|
||||
eglBase.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -347,7 +336,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME);
|
||||
pcClient = createPeerConnectionClient(localRenderer, new MockRenderer(0, null),
|
||||
createParametersForVideoCall(VIDEO_CODEC_VP8),
|
||||
createCameraCapturer(false /* captureToTexture */), null);
|
||||
createCameraCapturer(false /* captureToTexture */));
|
||||
|
||||
// Wait for local SDP and ice candidates set events.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
@ -375,8 +364,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
} else {
|
||||
Log.d(TAG, "testLoopback for audio.");
|
||||
}
|
||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer, parameters, videoCapturer,
|
||||
decodeToTexture ? eglBase.getEglBaseContext() : null);
|
||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer, parameters, videoCapturer);
|
||||
|
||||
// Wait for local SDP, rename it to answer and set as remote SDP.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
@ -481,50 +469,6 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
createCameraCapturer(true /* captureToTexture */), true /* decodeToTexture */);
|
||||
}
|
||||
|
||||
// Test that a call can be setup even if the EGL context used during initialization is
|
||||
// released before the Video codecs are created. The HW encoder and decoder is setup to use
|
||||
// textures.
|
||||
@Test
|
||||
@SmallTest
|
||||
public void testLoopbackEglContextReleasedAfterCreatingPc() throws InterruptedException {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
Log.i(TAG, "Decode to textures is not supported. Requires SDK version 19");
|
||||
return;
|
||||
}
|
||||
|
||||
loopback = true;
|
||||
PeerConnectionParameters parameters = createParametersForVideoCall(VIDEO_CODEC_VP8);
|
||||
MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME);
|
||||
MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);
|
||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer, parameters,
|
||||
createCameraCapturer(true /* captureToTexture */), eglBase.getEglBaseContext());
|
||||
|
||||
// Wait for local SDP, rename it to answer and set as remote SDP.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
|
||||
// Release the EGL context used for creating the PeerConnectionClient.
|
||||
// Since createPeerConnectionClient is asynchronous, we must wait for the local
|
||||
// SessionDescription.
|
||||
eglBase.release();
|
||||
eglBase = null;
|
||||
|
||||
SessionDescription remoteSdp = new SessionDescription(
|
||||
SessionDescription.Type.fromCanonicalForm("answer"), localSdp.description);
|
||||
pcClient.setRemoteDescription(remoteSdp);
|
||||
|
||||
// Wait for ICE connection.
|
||||
assertTrue("ICE connection failure.", waitForIceConnected(ICE_CONNECTION_WAIT_TIMEOUT));
|
||||
// Check that local and remote video frames were rendered.
|
||||
assertTrue(
|
||||
"Local video frames were not rendered.", localRenderer.waitForFramesRendered(WAIT_TIMEOUT));
|
||||
assertTrue("Remote video frames were not rendered.",
|
||||
remoteRenderer.waitForFramesRendered(WAIT_TIMEOUT));
|
||||
|
||||
pcClient.close();
|
||||
assertTrue(waitForPeerConnectionClosed(WAIT_TIMEOUT));
|
||||
Log.d(TAG, "testLoopback done.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SmallTest
|
||||
public void testLoopbackH264CaptureToTexture() throws InterruptedException {
|
||||
@ -555,7 +499,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
|
||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
||||
createParametersForVideoCall(VIDEO_CODEC_VP8),
|
||||
createCameraCapturer(false /* captureToTexture */), null);
|
||||
createCameraCapturer(false /* captureToTexture */));
|
||||
|
||||
// Wait for local SDP, rename it to answer and set as remote SDP.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
@ -603,7 +547,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
|
||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
||||
createParametersForVideoCall(VIDEO_CODEC_VP8),
|
||||
createCameraCapturer(false /* captureToTexture */), null);
|
||||
createCameraCapturer(false /* captureToTexture */));
|
||||
|
||||
// Wait for local SDP, rename it to answer and set as remote SDP.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
@ -652,7 +596,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||
|
||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
||||
createParametersForVideoCall(VIDEO_CODEC_VP8),
|
||||
createCameraCapturer(false /* captureToTexture */), null);
|
||||
createCameraCapturer(false /* captureToTexture */));
|
||||
|
||||
// Wait for local SDP, rename it to answer and set as remote SDP.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
|
||||
Reference in New Issue
Block a user