Remove peer connection and signaling calls from UI thread.

- Add separate looper threads for peer connection and websocket
signaling classes.
- To improve the connection speed start peer connection factory
initialization once EGL context is ready in parallel with the room
connection.
- Add asynchronious http request class and start using it in
webscoket signaling and room parameters extractor.
- Add helper looper based executor class.
- Port some of henrika changes from
https://webrtc-codereview.appspot.com/36629004/ to fix sensor
crashes on non L devices - will remove the change if CL will
be submitted soon.

R=jiayl@webrtc.org, wzh@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/41369004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@8006 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
glaznev@webrtc.org
2015-01-06 22:24:09 +00:00
parent 2ec50f2b0f
commit f6a9714760
15 changed files with 1234 additions and 780 deletions

View File

@@ -27,6 +27,8 @@
package org.appspot.apprtc;
import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
@@ -49,9 +51,7 @@ import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import org.webrtc.IceCandidate;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.SessionDescription;
import org.webrtc.StatsObserver;
import org.webrtc.StatsReport;
@@ -71,7 +71,7 @@ public class AppRTCDemoActivity extends Activity
implements AppRTCClient.SignalingEvents,
PeerConnectionClient.PeerConnectionEvents {
private static final String TAG = "AppRTCClient";
private PeerConnectionClient pc;
private PeerConnectionClient pc = null;
private AppRTCClient appRtcClient;
private SignalingParameters signalingParameters;
private AppRTCAudioManager audioManager = null;
@@ -123,7 +123,12 @@ public class AppRTCDemoActivity extends Activity
roomNameView = (TextView) findViewById(R.id.room_name);
videoView = (GLSurfaceView) findViewById(R.id.glview);
VideoRendererGui.setView(videoView);
VideoRendererGui.setView(videoView, new Runnable() {
@Override
public void run() {
createPeerConnectionFactory();
}
});
scalingType = ScalingType.SCALE_ASPECT_FILL;
remoteRender = VideoRendererGui.create(0, 0, 100, 100, scalingType, false);
localRender = VideoRendererGui.create(0, 0, 100, 100, scalingType, true);
@@ -201,17 +206,6 @@ public class AppRTCDemoActivity extends Activity
hudView.setVisibility(View.INVISIBLE);
addContentView(hudView, hudLayout);
// Create and audio manager that will take care of audio routing,
// audio modes, audio device enumeration etc.
audioManager = AppRTCAudioManager.create(this, new Runnable() {
// This method will be called each time the audio state (number and
// type of devices) has been changed.
public void run() {
onAudioManagerChangedState();
}
}
);
final Intent intent = getIntent();
Uri url = intent.getData();
roomName = intent.getStringExtra(ConnectActivity.EXTRA_ROOMNAME);
@@ -225,6 +219,7 @@ public class AppRTCDemoActivity extends Activity
if (url != null) {
if (loopback || (roomName != null && !roomName.equals(""))) {
// Start room connection.
logAndToast(getString(R.string.connecting_to, url));
appRtcClient = new WebSocketRTCClient(this);
appRtcClient.connectToRoom(url.toString(), loopback);
@@ -233,6 +228,23 @@ public class AppRTCDemoActivity extends Activity
} else {
roomNameView.setText(roomName);
}
// Create and audio manager that will take care of audio routing,
// audio modes, audio device enumeration etc.
audioManager = AppRTCAudioManager.create(this, new Runnable() {
// This method will be called each time the audio state (number and
// type of devices) has been changed.
@Override
public void run() {
onAudioManagerChangedState();
}
}
);
// Store existing audio settings and change audio mode to
// MODE_IN_COMMUNICATION for best possible VoIP performance.
Log.d(TAG, "Initializing the audio manager...");
audioManager.init();
// For command line execution run connection for <runTimeMs> and exit.
if (commandLineRun && runTimeMs > 0) {
videoView.postDelayed(new Runnable() {
@@ -254,6 +266,21 @@ public class AppRTCDemoActivity extends Activity
}
}
// Create peer connection factory when EGL context is ready.
private void createPeerConnectionFactory() {
final AppRTCDemoActivity thisCopy = this;
runOnUiThread(new Runnable() {
@Override
public void run() {
if (pc == null) {
pc = new PeerConnectionClient();
pc.createPeerConnectionFactory(
thisCopy, hwCodec, VideoRendererGui.getEGLContext(), thisCopy);
}
}
});
}
/**
* MenuBar fragment for AppRTC.
*/
@@ -291,6 +318,9 @@ public class AppRTCDemoActivity extends Activity
protected void onDestroy() {
disconnect();
super.onDestroy();
if (logToast != null) {
logToast.cancel();
}
activityRunning = false;
}
@@ -312,7 +342,7 @@ public class AppRTCDemoActivity extends Activity
// Disconnect from remote resources, dispose of local resources, and exit.
private void disconnect() {
if (appRtcClient != null) {
appRtcClient.disconnect();
appRtcClient.disconnectFromRoom();
appRtcClient = null;
}
if (pc != null) {
@@ -349,13 +379,6 @@ public class AppRTCDemoActivity extends Activity
}
}
// Poor-man's assert(): die with |msg| unless |condition| is true.
private static void abortUnless(boolean condition, String msg) {
if (!condition) {
throw new RuntimeException(msg);
}
}
// Log |msg| and Toast about it.
private void logAndToast(String msg) {
Log.d(TAG, msg);
@@ -460,22 +483,20 @@ public class AppRTCDemoActivity extends Activity
}
// -----Implementation of AppRTCClient.AppRTCSignalingEvents ---------------
// All events are called from UI thread.
@Override
public void onConnectedToRoom(final SignalingParameters params) {
if (audioManager != null) {
// Store existing audio settings and change audio mode to
// MODE_IN_COMMUNICATION for best possible VoIP performance.
Log.d(TAG, "Initializing the audio manager...");
audioManager.init();
}
// All callbacks are invoked from websocket signaling looper thread and
// are routed to UI thread.
private void onConnectedToRoomInternal(final SignalingParameters params) {
signalingParameters = params;
abortUnless(PeerConnectionFactory.initializeAndroidGlobals(
this, true, true, hwCodec, VideoRendererGui.getEGLContext()),
"Failed to initializeAndroidGlobals");
logAndToast("Creating peer connection...");
pc = new PeerConnectionClient(localRender, remoteRender,
signalingParameters, this, startBitrate);
if (pc == null) {
// Create peer connection factory if render EGL context ready event
// has not been fired yet.
pc = new PeerConnectionClient();
pc.createPeerConnectionFactory(
this, hwCodec, VideoRendererGui.getEGLContext(), this);
}
pc.createPeerConnection(
localRender, remoteRender, signalingParameters, startBitrate);
if (pc.isHDVideo()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
@@ -510,7 +531,7 @@ public class AppRTCDemoActivity extends Activity
}
}, null);
if (!success) {
throw new RuntimeException("getStats() return false!");
Log.e(TAG, "getStats() return false!");
}
}
};
@@ -524,75 +545,127 @@ public class AppRTCDemoActivity extends Activity
}
}
@Override
public void onConnectedToRoom(final SignalingParameters params) {
runOnUiThread(new Runnable() {
@Override
public void run() {
onConnectedToRoomInternal(params);
}
});
}
@Override
public void onRemoteDescription(final SessionDescription sdp) {
if (pc == null) {
return;
}
logAndToast("Received remote " + sdp.type + " ...");
pc.setRemoteDescription(sdp);
if (!signalingParameters.initiator) {
logAndToast("Creating ANSWER...");
// Create answer. Answer SDP will be sent to offering client in
// PeerConnectionEvents.onLocalDescription event.
pc.createAnswer();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (pc == null) {
return;
}
logAndToast("Received remote " + sdp.type + " ...");
pc.setRemoteDescription(sdp);
if (!signalingParameters.initiator) {
logAndToast("Creating ANSWER...");
// Create answer. Answer SDP will be sent to offering client in
// PeerConnectionEvents.onLocalDescription event.
pc.createAnswer();
}
}
});
}
@Override
public void onRemoteIceCandidate(final IceCandidate candidate) {
if (pc != null) {
pc.addRemoteIceCandidate(candidate);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (pc != null) {
pc.addRemoteIceCandidate(candidate);
}
}
});
}
@Override
public void onChannelClose() {
logAndToast("Remote end hung up; dropping PeerConnection");
disconnect();
runOnUiThread(new Runnable() {
@Override
public void run() {
logAndToast("Remote end hung up; dropping PeerConnection");
disconnect();
}
});
}
@Override
public void onChannelError(final String description) {
if (!isError) {
isError = true;
disconnectWithErrorMessage(description);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (!isError) {
isError = true;
disconnectWithErrorMessage(description);
}
}
});
}
// -----Implementation of PeerConnectionClient.PeerConnectionEvents.---------
// Send local peer connection SDP and ICE candidates to remote party.
// All callbacks are invoked from UI thread.
// All callbacks are invoked from peer connection client looper thread and
// are routed to UI thread.
@Override
public void onLocalDescription(final SessionDescription sdp) {
if (appRtcClient != null) {
logAndToast("Sending " + sdp.type + " ...");
if (signalingParameters.initiator) {
appRtcClient.sendOfferSdp(sdp);
} else {
appRtcClient.sendAnswerSdp(sdp);
runOnUiThread(new Runnable() {
@Override
public void run() {
if (appRtcClient != null) {
logAndToast("Sending " + sdp.type + " ...");
if (signalingParameters.initiator) {
appRtcClient.sendOfferSdp(sdp);
} else {
appRtcClient.sendAnswerSdp(sdp);
}
}
}
}
});
}
@Override
public void onIceCandidate(final IceCandidate candidate) {
if (appRtcClient != null) {
appRtcClient.sendLocalIceCandidate(candidate);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (appRtcClient != null) {
appRtcClient.sendLocalIceCandidate(candidate);
}
}
});
}
@Override
public void onIceConnected() {
logAndToast("ICE connected");
iceConnected = true;
updateVideoView();
runOnUiThread(new Runnable() {
@Override
public void run() {
logAndToast("ICE connected");
iceConnected = true;
updateVideoView();
}
});
}
@Override
public void onIceDisconnected() {
logAndToast("ICE disconnected");
disconnect();
runOnUiThread(new Runnable() {
@Override
public void run() {
logAndToast("ICE disconnected");
iceConnected = false;
disconnect();
}
});
}
@Override
@@ -600,10 +673,15 @@ public class AppRTCDemoActivity extends Activity
}
@Override
public void onPeerConnectionError(String description) {
if (!isError) {
isError = true;
disconnectWithErrorMessage(description);
}
public void onPeerConnectionError(final String description) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (!isError) {
isError = true;
disconnectWithErrorMessage(description);
}
}
});
}
}