diff --git a/talk/examples/android/res/values/arrays.xml b/talk/examples/android/res/values/arrays.xml
index d6ec4d2522..ba8c8918ce 100644
--- a/talk/examples/android/res/values/arrays.xml
+++ b/talk/examples/android/res/values/arrays.xml
@@ -28,6 +28,12 @@
- VP8
- VP9
+ - H264
+
+
+
+ - OPUS
+ - ISAC
diff --git a/talk/examples/android/res/values/strings.xml b/talk/examples/android/res/values/strings.xml
index b4d9095fba..428b0eb8be 100644
--- a/talk/examples/android/res/values/strings.xml
+++ b/talk/examples/android/res/values/strings.xml
@@ -28,6 +28,14 @@
room_preference
room_list_preference
+ video_settings_key
+ WebRTC video settings.
+
+ videocall_preference
+ Video call.
+ Enable video in a call.
+ true
+
resolution_preference
Video resolution.
Enter AppRTC local video resolution.
@@ -38,20 +46,15 @@
Enter local camera fps.
Default
- cpu_usage_detection
- CPU overuse detection.
- Adapt transmission to CPU status.
- true
+ startvideobitrate_preference
+ Start video bitrate setting.
+ Start video bitrate setting.
+ Default
- startbitrate_preference
- Start bitrate setting.
- Start bitrate setting.
- Default
-
- startbitratevalue_preference
- Video encoder start bitrate.
- Enter video encoder start bitrate in kbps.
- 1000
+ startvideobitratevalue_preference
+ Video encoder start bitrate.
+ Enter video encoder start bitrate in kbps.
+ 1000
videocodec_preference
Default video codec.
@@ -66,6 +69,32 @@
Enabled
Disabled
+ audio_settings_key
+ WebRTC audio settings.
+
+ startaudiobitrate_preference
+ Audio bitrate setting.
+ Audio bitrate setting.
+ Default
+
+ startaudiobitratevalue_preference
+ Audio codec bitrate.
+ Enter audio codec bitrate in kbps.
+ 32
+
+ audiocodec_preference
+ Default audio codec.
+ Select default audio codec.
+ OPUS
+
+ misc_settings_key
+ Miscellaneous settings.
+
+ cpu_usage_detection
+ CPU overuse detection.
+ Adapt transmission to CPU status.
+ true
+
room_server_url_preference
Room server URL.
Enter a room server URL.
diff --git a/talk/examples/android/res/xml/preferences.xml b/talk/examples/android/res/xml/preferences.xml
index 3d77418437..ad0affb478 100644
--- a/talk/examples/android/res/xml/preferences.xml
+++ b/talk/examples/android/res/xml/preferences.xml
@@ -1,67 +1,111 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/talk/examples/android/src/org/appspot/apprtc/CallActivity.java b/talk/examples/android/src/org/appspot/apprtc/CallActivity.java
index 1c80266038..815081183a 100644
--- a/talk/examples/android/src/org/appspot/apprtc/CallActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/CallActivity.java
@@ -66,18 +66,24 @@ public class CallActivity extends Activity
"org.appspot.apprtc.ROOMID";
public static final String EXTRA_LOOPBACK =
"org.appspot.apprtc.LOOPBACK";
- public static final String EXTRA_HWCODEC =
- "org.appspot.apprtc.HWCODEC";
- public static final String EXTRA_VIDEO_BITRATE =
- "org.appspot.apprtc.VIDEO_BITRATE";
+ public static final String EXTRA_VIDEO_CALL =
+ "org.appspot.apprtc.VIDEO_CALL";
public static final String EXTRA_VIDEO_WIDTH =
"org.appspot.apprtc.VIDEO_WIDTH";
public static final String EXTRA_VIDEO_HEIGHT =
"org.appspot.apprtc.VIDEO_HEIGHT";
public static final String EXTRA_VIDEO_FPS =
"org.appspot.apprtc.VIDEO_FPS";
+ public static final String EXTRA_VIDEO_BITRATE =
+ "org.appspot.apprtc.VIDEO_BITRATE";
public static final String EXTRA_VIDEOCODEC =
"org.appspot.apprtc.VIDEOCODEC";
+ public static final String EXTRA_HWCODEC_ENABLED =
+ "org.appspot.apprtc.HWCODEC";
+ public static final String EXTRA_AUDIO_BITRATE =
+ "org.appspot.apprtc.AUDIO_BITRATE";
+ public static final String EXTRA_AUDIOCODEC =
+ "org.appspot.apprtc.AUDIOCODEC";
public static final String EXTRA_CPUOVERUSE_DETECTION =
"org.appspot.apprtc.CPUOVERUSE_DETECTION";
public static final String EXTRA_DISPLAY_HUD =
@@ -118,11 +124,10 @@ public class CallActivity extends Activity
private boolean activityRunning;
private RoomConnectionParameters roomConnectionParameters;
private PeerConnectionParameters peerConnectionParameters;
- private boolean hwCodecAcceleration;
- private String videoCodec;
private boolean iceConnected;
private boolean isError;
private boolean callControlFragmentVisible = true;
+ private long callStartedTimeMs = 0;
// Controls
private GLSurfaceView videoView;
@@ -194,17 +199,17 @@ public class CallActivity extends Activity
return;
}
boolean loopback = intent.getBooleanExtra(EXTRA_LOOPBACK, false);
- hwCodecAcceleration = intent.getBooleanExtra(EXTRA_HWCODEC, true);
- if (intent.hasExtra(EXTRA_VIDEOCODEC)) {
- videoCodec = intent.getStringExtra(EXTRA_VIDEOCODEC);
- } else {
- videoCodec = PeerConnectionClient.VIDEO_CODEC_VP8; // use VP8 by default.
- }
peerConnectionParameters = new PeerConnectionParameters(
+ intent.getBooleanExtra(EXTRA_VIDEO_CALL, true),
+ loopback,
intent.getIntExtra(EXTRA_VIDEO_WIDTH, 0),
intent.getIntExtra(EXTRA_VIDEO_HEIGHT, 0),
intent.getIntExtra(EXTRA_VIDEO_FPS, 0),
intent.getIntExtra(EXTRA_VIDEO_BITRATE, 0),
+ intent.getStringExtra(EXTRA_VIDEOCODEC),
+ intent.getBooleanExtra(EXTRA_HWCODEC_ENABLED, true),
+ intent.getIntExtra(EXTRA_AUDIO_BITRATE, 0),
+ intent.getStringExtra(EXTRA_AUDIOCODEC),
intent.getBooleanExtra(EXTRA_CPUOVERUSE_DETECTION, true));
commandLineRun = intent.getBooleanExtra(EXTRA_CMDLINE, false);
runTimeMs = intent.getIntExtra(EXTRA_RUNTIME, 0);
@@ -319,6 +324,8 @@ public class CallActivity extends Activity
Log.e(TAG, "AppRTC client is not allocated for a call.");
return;
}
+ callStartedTimeMs = System.currentTimeMillis();
+
// Start room connection.
logAndToast(getString(R.string.connecting_to,
roomConnectionParameters.roomUrl));
@@ -343,6 +350,9 @@ public class CallActivity extends Activity
// Should be called from UI thread
private void callConnected() {
+ final long delta = System.currentTimeMillis() - callStartedTimeMs;
+ Log.i(TAG, "Call connected: delay=" + delta + "ms");
+
// Update video view.
updateVideoView();
// Enable statistics callback.
@@ -360,10 +370,12 @@ public class CallActivity extends Activity
@Override
public void run() {
if (peerConnectionClient == null) {
+ final long delta = System.currentTimeMillis() - callStartedTimeMs;
+ Log.d(TAG, "Creating peer connection factory, delay=" + delta + "ms");
peerConnectionClient = new PeerConnectionClient();
peerConnectionClient.createPeerConnectionFactory(CallActivity.this,
- videoCodec, hwCodecAcceleration,
- VideoRendererGui.getEGLContext(), CallActivity.this);
+ VideoRendererGui.getEGLContext(), peerConnectionParameters,
+ CallActivity.this);
}
if (signalingParameters != null) {
Log.w(TAG, "EGL context is ready after room connection.");
@@ -428,15 +440,16 @@ public class CallActivity extends Activity
// All callbacks are invoked from websocket signaling looper thread and
// are routed to UI thread.
private void onConnectedToRoomInternal(final SignalingParameters params) {
+ final long delta = System.currentTimeMillis() - callStartedTimeMs;
+
signalingParameters = params;
if (peerConnectionClient == null) {
Log.w(TAG, "Room is connected, but EGL context is not ready yet.");
return;
}
- logAndToast("Creating peer connection...");
+ logAndToast("Creating peer connection, delay=" + delta + "ms");
peerConnectionClient.createPeerConnection(
- localRender, remoteRender,
- signalingParameters, peerConnectionParameters);
+ localRender, remoteRender, signalingParameters);
if (signalingParameters.initiator) {
logAndToast("Creating OFFER...");
@@ -472,6 +485,7 @@ public class CallActivity extends Activity
@Override
public void onRemoteDescription(final SessionDescription sdp) {
+ final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -479,7 +493,7 @@ public class CallActivity extends Activity
Log.e(TAG, "Received remote SDP for non-initilized peer connection.");
return;
}
- logAndToast("Received remote " + sdp.type + " ...");
+ logAndToast("Received remote " + sdp.type + ", delay=" + delta + "ms");
peerConnectionClient.setRemoteDescription(sdp);
if (!signalingParameters.initiator) {
logAndToast("Creating ANSWER...");
@@ -536,11 +550,12 @@ public class CallActivity extends Activity
// are routed to UI thread.
@Override
public void onLocalDescription(final SessionDescription sdp) {
+ final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
@Override
public void run() {
if (appRtcClient != null) {
- logAndToast("Sending " + sdp.type + " ...");
+ logAndToast("Sending " + sdp.type + ", delay=" + delta + "ms");
if (signalingParameters.initiator) {
appRtcClient.sendOfferSdp(sdp);
} else {
@@ -565,10 +580,11 @@ public class CallActivity extends Activity
@Override
public void onIceConnected() {
+ final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
@Override
public void run() {
- logAndToast("ICE connected");
+ logAndToast("ICE connected, delay=" + delta + "ms");
iceConnected = true;
callConnected();
}
diff --git a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
index 8c2323dd87..5a6f99ca9e 100644
--- a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
@@ -71,11 +71,15 @@ public class ConnectActivity extends Activity {
private EditText roomEditText;
private ListView roomListView;
private SharedPreferences sharedPref;
+ private String keyprefVideoCallEnabled;
private String keyprefResolution;
private String keyprefFps;
- private String keyprefBitrateType;
- private String keyprefBitrateValue;
+ private String keyprefVideoBitrateType;
+ private String keyprefVideoBitrateValue;
private String keyprefVideoCodec;
+ private String keyprefAudioBitrateType;
+ private String keyprefAudioBitrateValue;
+ private String keyprefAudioCodec;
private String keyprefHwCodecAcceleration;
private String keyprefCpuUsageDetection;
private String keyprefDisplayHud;
@@ -92,12 +96,16 @@ public class ConnectActivity extends Activity {
// Get setting keys.
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+ keyprefVideoCallEnabled = getString(R.string.pref_videocall_key);
keyprefResolution = getString(R.string.pref_resolution_key);
keyprefFps = getString(R.string.pref_fps_key);
- keyprefBitrateType = getString(R.string.pref_startbitrate_key);
- keyprefBitrateValue = getString(R.string.pref_startbitratevalue_key);
+ keyprefVideoBitrateType = getString(R.string.pref_startvideobitrate_key);
+ keyprefVideoBitrateValue = getString(R.string.pref_startvideobitratevalue_key);
keyprefVideoCodec = getString(R.string.pref_videocodec_key);
keyprefHwCodecAcceleration = getString(R.string.pref_hwcodec_key);
+ keyprefAudioBitrateType = getString(R.string.pref_startaudiobitrate_key);
+ keyprefAudioBitrateValue = getString(R.string.pref_startaudiobitratevalue_key);
+ keyprefAudioCodec = getString(R.string.pref_audiocodec_key);
keyprefCpuUsageDetection = getString(R.string.pref_cpu_usage_detection_key);
keyprefDisplayHud = getString(R.string.pref_displayhud_key);
keyprefRoomServerUrl = getString(R.string.pref_room_server_url_key);
@@ -244,9 +252,15 @@ public class ConnectActivity extends Activity {
keyprefRoomServerUrl,
getString(R.string.pref_room_server_url_default));
- // Get default video codec.
+ // Video call enabled flag.
+ boolean videoCallEnabled = sharedPref.getBoolean(keyprefVideoCallEnabled,
+ Boolean.valueOf(getString(R.string.pref_videocall_default)));
+
+ // Get default codecs.
String videoCodec = sharedPref.getString(keyprefVideoCodec,
getString(R.string.pref_videocodec_default));
+ String audioCodec = sharedPref.getString(keyprefAudioCodec,
+ getString(R.string.pref_audiocodec_default));
// Check HW codec flag.
boolean hwCodec = sharedPref.getBoolean(keyprefHwCodecAcceleration,
@@ -282,15 +296,25 @@ public class ConnectActivity extends Activity {
}
}
- // Get start bitrate.
- int startBitrate = 0;
- String bitrateTypeDefault = getString(R.string.pref_startbitrate_default);
+ // Get video and audio start bitrate.
+ int videoStartBitrate = 0;
+ String bitrateTypeDefault = getString(
+ R.string.pref_startvideobitrate_default);
String bitrateType = sharedPref.getString(
- keyprefBitrateType, bitrateTypeDefault);
+ keyprefVideoBitrateType, bitrateTypeDefault);
if (!bitrateType.equals(bitrateTypeDefault)) {
- String bitrateValue = sharedPref.getString(keyprefBitrateValue,
- getString(R.string.pref_startbitratevalue_default));
- startBitrate = Integer.parseInt(bitrateValue);
+ String bitrateValue = sharedPref.getString(keyprefVideoBitrateValue,
+ getString(R.string.pref_startvideobitratevalue_default));
+ videoStartBitrate = Integer.parseInt(bitrateValue);
+ }
+ int audioStartBitrate = 0;
+ bitrateTypeDefault = getString(R.string.pref_startaudiobitrate_default);
+ bitrateType = sharedPref.getString(
+ keyprefAudioBitrateType, bitrateTypeDefault);
+ if (!bitrateType.equals(bitrateTypeDefault)) {
+ String bitrateValue = sharedPref.getString(keyprefAudioBitrateValue,
+ getString(R.string.pref_startaudiobitratevalue_default));
+ audioStartBitrate = Integer.parseInt(bitrateValue);
}
// Test if CpuOveruseDetection should be disabled. By default is on.
@@ -311,12 +335,15 @@ public class ConnectActivity extends Activity {
intent.setData(uri);
intent.putExtra(CallActivity.EXTRA_ROOMID, roomId);
intent.putExtra(CallActivity.EXTRA_LOOPBACK, loopback);
- intent.putExtra(CallActivity.EXTRA_VIDEOCODEC, videoCodec);
- intent.putExtra(CallActivity.EXTRA_HWCODEC, hwCodec);
- intent.putExtra(CallActivity.EXTRA_VIDEO_BITRATE, startBitrate);
+ intent.putExtra(CallActivity.EXTRA_VIDEO_CALL, videoCallEnabled);
intent.putExtra(CallActivity.EXTRA_VIDEO_WIDTH, videoWidth);
intent.putExtra(CallActivity.EXTRA_VIDEO_HEIGHT, videoHeight);
intent.putExtra(CallActivity.EXTRA_VIDEO_FPS, cameraFps);
+ intent.putExtra(CallActivity.EXTRA_VIDEO_BITRATE, videoStartBitrate);
+ intent.putExtra(CallActivity.EXTRA_VIDEOCODEC, videoCodec);
+ intent.putExtra(CallActivity.EXTRA_HWCODEC_ENABLED, hwCodec);
+ intent.putExtra(CallActivity.EXTRA_AUDIO_BITRATE, audioStartBitrate);
+ intent.putExtra(CallActivity.EXTRA_AUDIOCODEC, audioCodec);
intent.putExtra(CallActivity.EXTRA_CPUOVERUSE_DETECTION,
cpuOveruseDetection);
intent.putExtra(CallActivity.EXTRA_DISPLAY_HUD, displayHud);
diff --git a/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java b/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
index 78fe1762dd..7910023845 100644
--- a/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
+++ b/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
@@ -67,13 +67,15 @@ public class PeerConnectionClient {
public static final String VIDEO_TRACK_ID = "ARDAMSv0";
public static final String AUDIO_TRACK_ID = "ARDAMSa0";
private static final String TAG = "PCRTCClient";
- private static final boolean PREFER_ISAC = false;
- private static final boolean PREFER_H264 = false;
- public static final String AUDIO_CODEC_ISAC = "ISAC";
- public static final String VIDEO_CODEC_VP8 = "VP8";
- public static final String VIDEO_CODEC_VP9 = "VP9";
- public static final String VIDEO_CODEC_H264 = "H264";
private static final String FIELD_TRIAL_VP9 = "WebRTC-SupportVP9/Enabled/";
+ private static final String VIDEO_CODEC_VP8 = "VP8";
+ private static final String VIDEO_CODEC_VP9 = "VP9";
+ private static final String VIDEO_CODEC_H264 = "H264";
+ private static final String AUDIO_CODEC_OPUS = "opus";
+ private static final String AUDIO_CODEC_ISAC = "ISAC";
+ private static final String VIDEO_CODEC_PARAM_START_BITRATE =
+ "x-google-start-bitrate";
+ private static final String AUDIO_CODEC_PARAM_BITRATE = "maxaveragebitrate";
private static final String MAX_VIDEO_WIDTH_CONSTRAINT = "maxWidth";
private static final String MIN_VIDEO_WIDTH_CONSTRAINT = "minWidth";
private static final String MAX_VIDEO_HEIGHT_CONSTRAINT = "maxHeight";
@@ -90,9 +92,11 @@ public class PeerConnectionClient {
private PeerConnectionFactory factory = null;
private PeerConnection peerConnection = null;
private VideoSource videoSource;
+ private boolean videoCallEnabled = true;
+ private boolean preferIsac = false;
+ private boolean preferH264 = false;
private boolean videoSourceStopped = false;
private boolean isError = false;
- private boolean videoCodecHwAcceleration;
private final Timer statsTimer = new Timer();
private final PCObserver pcObserver = new PCObserver();
private final SDPObserver sdpObserver = new SDPObserver();
@@ -120,18 +124,34 @@ public class PeerConnectionClient {
* Peer connection parameters.
*/
public static class PeerConnectionParameters {
+ public final boolean videoCallEnabled;
+ public final boolean loopback;
public final int videoWidth;
public final int videoHeight;
public final int videoFps;
public final int videoStartBitrate;
+ public final String videoCodec;
+ public final boolean videoCodecHwAcceleration;
+ public final int audioStartBitrate;
+ public final String audioCodec;
public final boolean cpuOveruseDetection;
- public PeerConnectionParameters(int videoWidth, int videoHeight,
- int videoFps, int videoStartBitrate, boolean cpuOveruseDetection) {
+ public PeerConnectionParameters(
+ boolean videoCallEnabled, boolean loopback,
+ int videoWidth, int videoHeight, int videoFps, int videoStartBitrate,
+ String videoCodec, boolean videoCodecHwAcceleration,
+ int audioStartBitrate, String audioCodec,
+ boolean cpuOveruseDetection) {
+ this.videoCallEnabled = videoCallEnabled;
+ this.loopback = loopback;
this.videoWidth = videoWidth;
this.videoHeight = videoHeight;
this.videoFps = videoFps;
this.videoStartBitrate = videoStartBitrate;
+ this.videoCodec = videoCodec;
+ this.videoCodecHwAcceleration = videoCodecHwAcceleration;
+ this.audioStartBitrate = audioStartBitrate;
+ this.audioCodec = audioCodec;
this.cpuOveruseDetection = cpuOveruseDetection;
}
}
@@ -184,18 +204,16 @@ public class PeerConnectionClient {
public void createPeerConnectionFactory(
final Context context,
- final String videoCodec,
- final boolean videoCodecHwAcceleration,
final EGLContext renderEGLContext,
+ final PeerConnectionParameters peerConnectionParameters,
final PeerConnectionEvents events) {
+ this.peerConnectionParameters = peerConnectionParameters;
this.events = events;
- this.videoCodecHwAcceleration = videoCodecHwAcceleration;
executor.requestStart();
executor.execute(new Runnable() {
@Override
public void run() {
- createPeerConnectionFactoryInternal(
- context, videoCodec, renderEGLContext);
+ createPeerConnectionFactoryInternal(context, renderEGLContext);
}
});
}
@@ -203,23 +221,29 @@ public class PeerConnectionClient {
public void createPeerConnection(
final VideoRenderer.Callbacks localRender,
final VideoRenderer.Callbacks remoteRender,
- final SignalingParameters signalingParameters,
- final PeerConnectionParameters peerConnectionParameters) {
+ final SignalingParameters signalingParameters) {
+ if (peerConnectionParameters == null) {
+ Log.e(TAG, "Creating peer connection without initializing factory.");
+ return;
+ }
this.localRender = localRender;
this.remoteRender = remoteRender;
this.signalingParameters = signalingParameters;
- this.peerConnectionParameters = peerConnectionParameters;
// Merge video constraints from signaling parameters and peer connection
// parameters.
videoConstraints = signalingParameters.videoConstraints;
- if (videoConstraints != null && peerConnectionParameters != null) {
+ if (signalingParameters.videoConstraints == null) {
+ videoCallEnabled = false;
+ }
+ if (videoCallEnabled) {
int videoWidth = peerConnectionParameters.videoWidth;
int videoHeight = peerConnectionParameters.videoHeight;
// If HW video encoder is supported and video resolution is not
// specified force it to HD.
- if ((videoWidth == 0 || videoHeight == 0) && videoCodecHwAcceleration &&
- MediaCodecVideoEncoder.isVp8HwSupported()) {
+ if ((videoWidth == 0 || videoHeight == 0)
+ && peerConnectionParameters.videoCodecHwAcceleration
+ && MediaCodecVideoEncoder.isVp8HwSupported()) {
videoWidth = HD_VIDEO_WIDTH;
videoHeight = HD_VIDEO_HEIGHT;
}
@@ -268,19 +292,34 @@ public class PeerConnectionClient {
}
private void createPeerConnectionFactoryInternal(
- Context context,
- String videoCodec,
- EGLContext renderEGLContext) {
+ Context context, EGLContext renderEGLContext) {
Log.d(TAG, "Create peer connection factory with EGLContext "
- + renderEGLContext);
+ + renderEGLContext + ". Use video: "
+ + peerConnectionParameters.videoCallEnabled);
+ videoCallEnabled = peerConnectionParameters.videoCallEnabled;
isError = false;
- if (videoCodec.equals(VIDEO_CODEC_VP9)) {
+ // Check if VP9 is used by default.
+ if (videoCallEnabled && peerConnectionParameters.videoCodec != null
+ && peerConnectionParameters.videoCodec.equals(VIDEO_CODEC_VP9)) {
PeerConnectionFactory.initializeFieldTrials(FIELD_TRIAL_VP9);
} else {
PeerConnectionFactory.initializeFieldTrials(null);
}
+ // Check if H.264 is used by default.
+ preferH264 = false;
+ if (videoCallEnabled && peerConnectionParameters.videoCodec != null
+ && peerConnectionParameters.videoCodec.equals(VIDEO_CODEC_H264)) {
+ preferH264 = true;
+ }
+ // Check if ISAC is used by default.
+ preferIsac = false;
+ if (peerConnectionParameters.audioCodec != null
+ && peerConnectionParameters.audioCodec.equals(AUDIO_CODEC_ISAC)) {
+ preferIsac = true;
+ }
if (!PeerConnectionFactory.initializeAndroidGlobals(
- context, true, true, videoCodecHwAcceleration, renderEGLContext)) {
+ context, true, true,
+ peerConnectionParameters.videoCodecHwAcceleration, renderEGLContext)) {
events.onPeerConnectionError("Failed to initializeAndroidGlobals");
}
factory = new PeerConnectionFactory();
@@ -292,16 +331,23 @@ public class PeerConnectionClient {
Log.e(TAG, "Peerconnection factory is not created");
return;
}
- Log.d(TAG, "Create peer connection. VideoConstraints: "
- + videoConstraints.toString());
+ Log.d(TAG, "Create peer connection");
+ if (videoConstraints != null) {
+ Log.d(TAG, "VideoConstraints: " + videoConstraints.toString());
+ }
isInitiator = signalingParameters.initiator;
queuedRemoteCandidates = new LinkedList();
sdpMediaConstraints = new MediaConstraints();
sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
"OfferToReceiveAudio", "true"));
- sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
- "OfferToReceiveVideo", "true"));
+ if (videoCallEnabled || peerConnectionParameters.loopback) {
+ sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
+ "OfferToReceiveVideo", "true"));
+ } else {
+ sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
+ "OfferToReceiveVideo", "false"));
+ }
MediaConstraints pcConstraints = signalingParameters.pcConstraints;
pcConstraints.optional.add(
@@ -318,7 +364,7 @@ public class PeerConnectionClient {
// Logging.Severity.LS_SENSITIVE);
mediaStream = factory.createLocalMediaStream("ARDAMS");
- if (videoConstraints != null) {
+ if (videoCallEnabled) {
videoCapturer = VideoCapturerAndroid.create(
VideoCapturerAndroid.getNameOfFrontFacingDevice());
mediaStream.addTrack(createVideoTrack(videoCapturer));
@@ -355,7 +401,7 @@ public class PeerConnectionClient {
}
public boolean isHDVideo() {
- if (videoConstraints == null) {
+ if (!videoCallEnabled) {
return false;
}
int minWidth = 0;
@@ -479,17 +525,23 @@ public class PeerConnectionClient {
return;
}
String sdpDescription = sdp.description;
- if (PREFER_ISAC) {
+ if (preferIsac) {
sdpDescription = preferCodec(sdpDescription, AUDIO_CODEC_ISAC, true);
}
- if (PREFER_H264) {
+ if (videoCallEnabled && preferH264) {
sdpDescription = preferCodec(sdpDescription, VIDEO_CODEC_H264, false);
}
- if (peerConnectionParameters.videoStartBitrate > 0) {
- sdpDescription = setStartBitrate(VIDEO_CODEC_VP8,
+ if (videoCallEnabled && peerConnectionParameters.videoStartBitrate > 0) {
+ sdpDescription = setStartBitrate(VIDEO_CODEC_VP8, true,
sdpDescription, peerConnectionParameters.videoStartBitrate);
- sdpDescription = setStartBitrate(VIDEO_CODEC_VP9,
+ sdpDescription = setStartBitrate(VIDEO_CODEC_VP9, true,
sdpDescription, peerConnectionParameters.videoStartBitrate);
+ sdpDescription = setStartBitrate(VIDEO_CODEC_H264, true,
+ sdpDescription, peerConnectionParameters.videoStartBitrate);
+ }
+ if (peerConnectionParameters.audioStartBitrate > 0) {
+ sdpDescription = setStartBitrate(AUDIO_CODEC_OPUS, false,
+ sdpDescription, peerConnectionParameters.audioStartBitrate);
}
Log.d(TAG, "Set remote SDP.");
SessionDescription sdpRemote = new SessionDescription(
@@ -549,12 +601,13 @@ public class PeerConnectionClient {
return localVideoTrack;
}
- // Mangle SDP to add video start bitrate.
- private static String setStartBitrate(String codec,
+ private static String setStartBitrate(String codec, boolean isVideoCodec,
String sdpDescription, int bitrateKbps) {
String[] lines = sdpDescription.split("\r\n");
- int lineIndex = -1;
+ int rtpmapLineIndex = -1;
+ boolean sdpFormatUpdated = false;
String codecRtpMap = null;
+ // Search for codec rtpmap in format
// a=rtpmap: / [/]
String regex = "^a=rtpmap:(\\d+) " + codec + "(/\\d+)+[\r]?$";
Pattern codecPattern = Pattern.compile(regex);
@@ -562,7 +615,7 @@ public class PeerConnectionClient {
Matcher codecMatcher = codecPattern.matcher(lines[i]);
if (codecMatcher.matches()) {
codecRtpMap = codecMatcher.group(1);
- lineIndex = i;
+ rtpmapLineIndex = i;
break;
}
}
@@ -571,16 +624,46 @@ public class PeerConnectionClient {
return sdpDescription;
}
Log.d(TAG, "Found " + codec + " rtpmap " + codecRtpMap
- + " at " + lines[lineIndex]);
+ + " at " + lines[rtpmapLineIndex]);
+
+ // Check if a=fmtp string already exist in remote SDP for this codec and
+ // update it with new bitrate parameter.
+ regex = "^a=fmtp:" + codecRtpMap + " \\w+=\\d+.*[\r]?$";
+ codecPattern = Pattern.compile(regex);
+ for (int i = 0; i < lines.length; i++) {
+ Matcher codecMatcher = codecPattern.matcher(lines[i]);
+ if (codecMatcher.matches()) {
+ Log.d(TAG, "Found " + codec + " " + lines[i]);
+ if (isVideoCodec) {
+ lines[i] += "; " + VIDEO_CODEC_PARAM_START_BITRATE
+ + "=" + bitrateKbps;
+ } else {
+ lines[i] += "; " + AUDIO_CODEC_PARAM_BITRATE
+ + "=" + (bitrateKbps * 1000);
+ }
+ Log.d(TAG, "Update remote SDP line: " + lines[i]);
+ sdpFormatUpdated = true;
+ break;
+ }
+ }
+
StringBuilder newSdpDescription = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
newSdpDescription.append(lines[i]).append("\r\n");
- if (i == lineIndex) {
- String bitrateSet = "a=fmtp:" + codecRtpMap
- + " x-google-start-bitrate=" + bitrateKbps;
- Log.d(TAG, "Add bitrate SDP line: " + bitrateSet);
+ // Append new a=fmtp line if no such line exist for a codec.
+ if (!sdpFormatUpdated && i == rtpmapLineIndex) {
+ String bitrateSet;
+ if (isVideoCodec) {
+ bitrateSet = "a=fmtp:" + codecRtpMap + " "
+ + VIDEO_CODEC_PARAM_START_BITRATE + "=" + bitrateKbps;
+ } else {
+ bitrateSet = "a=fmtp:" + codecRtpMap + " "
+ + AUDIO_CODEC_PARAM_BITRATE + "=" + (bitrateKbps * 1000);
+ }
+ Log.d(TAG, "Add remote SDP line: " + bitrateSet);
newSdpDescription.append(bitrateSet).append("\r\n");
}
+
}
return newSdpDescription.toString();
}
@@ -652,7 +735,7 @@ public class PeerConnectionClient {
}
private void switchCameraInternal() {
- if (videoConstraints == null) {
+ if (!videoCallEnabled) {
return; // No video is sent.
}
Log.d(TAG, "Switch camera");
@@ -770,10 +853,10 @@ public class PeerConnectionClient {
return;
}
String sdpDescription = origSdp.description;
- if (PREFER_ISAC) {
+ if (preferIsac) {
sdpDescription = preferCodec(sdpDescription, AUDIO_CODEC_ISAC, true);
}
- if (PREFER_H264) {
+ if (videoCallEnabled && preferH264) {
sdpDescription = preferCodec(sdpDescription, VIDEO_CODEC_H264, false);
}
final SessionDescription sdp = new SessionDescription(
diff --git a/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java
index 0e9278d778..1a017001e2 100644
--- a/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java
@@ -39,12 +39,18 @@ import android.preference.Preference;
public class SettingsActivity extends Activity
implements OnSharedPreferenceChangeListener{
private SettingsFragment settingsFragment;
+ private String keyprefVideoCall;
private String keyprefResolution;
private String keyprefFps;
- private String keyprefStartBitrateType;
- private String keyprefStartBitrateValue;
+ private String keyprefStartVideoBitrateType;
+ private String keyprefStartVideoBitrateValue;
private String keyPrefVideoCodec;
private String keyprefHwCodec;
+
+ private String keyprefStartAudioBitrateType;
+ private String keyprefStartAudioBitrateValue;
+ private String keyPrefAudioCodec;
+
private String keyprefCpuUsageDetection;
private String keyPrefRoomServerUrl;
private String keyPrefDisplayHud;
@@ -52,12 +58,18 @@ public class SettingsActivity extends Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ keyprefVideoCall = getString(R.string.pref_videocall_key);
keyprefResolution = getString(R.string.pref_resolution_key);
keyprefFps = getString(R.string.pref_fps_key);
- keyprefStartBitrateType = getString(R.string.pref_startbitrate_key);
- keyprefStartBitrateValue = getString(R.string.pref_startbitratevalue_key);
+ keyprefStartVideoBitrateType = getString(R.string.pref_startvideobitrate_key);
+ keyprefStartVideoBitrateValue = getString(R.string.pref_startvideobitratevalue_key);
keyPrefVideoCodec = getString(R.string.pref_videocodec_key);
keyprefHwCodec = getString(R.string.pref_hwcodec_key);
+
+ keyprefStartAudioBitrateType = getString(R.string.pref_startaudiobitrate_key);
+ keyprefStartAudioBitrateValue = getString(R.string.pref_startaudiobitratevalue_key);
+ keyPrefAudioCodec = getString(R.string.pref_audiocodec_key);
+
keyprefCpuUsageDetection = getString(R.string.pref_cpu_usage_detection_key);
keyPrefRoomServerUrl = getString(R.string.pref_room_server_url_key);
keyPrefDisplayHud = getString(R.string.pref_displayhud_key);
@@ -76,13 +88,20 @@ public class SettingsActivity extends Activity
SharedPreferences sharedPreferences =
settingsFragment.getPreferenceScreen().getSharedPreferences();
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ updateSummaryB(sharedPreferences, keyprefVideoCall);
updateSummary(sharedPreferences, keyprefResolution);
updateSummary(sharedPreferences, keyprefFps);
- updateSummary(sharedPreferences, keyprefStartBitrateType);
- updateSummaryBitrate(sharedPreferences, keyprefStartBitrateValue);
- setBitrateEnable(sharedPreferences);
+ updateSummary(sharedPreferences, keyprefStartVideoBitrateType);
+ updateSummaryBitrate(sharedPreferences, keyprefStartVideoBitrateValue);
+ setVideoBitrateEnable(sharedPreferences);
updateSummary(sharedPreferences, keyPrefVideoCodec);
updateSummaryB(sharedPreferences, keyprefHwCodec);
+
+ updateSummary(sharedPreferences, keyprefStartAudioBitrateType);
+ updateSummaryBitrate(sharedPreferences, keyprefStartAudioBitrateValue);
+ setAudioBitrateEnable(sharedPreferences);
+ updateSummary(sharedPreferences, keyPrefAudioCodec);
+
updateSummaryB(sharedPreferences, keyprefCpuUsageDetection);
updateSummary(sharedPreferences, keyPrefRoomServerUrl);
updateSummaryB(sharedPreferences, keyPrefDisplayHud);
@@ -101,18 +120,26 @@ public class SettingsActivity extends Activity
String key) {
if (key.equals(keyprefResolution)
|| key.equals(keyprefFps)
- || key.equals(keyprefStartBitrateType)
- || key.equals(keyPrefRoomServerUrl)
- || key.equals(keyPrefVideoCodec)) {
+ || key.equals(keyprefStartVideoBitrateType)
+ || key.equals(keyPrefVideoCodec)
+ || key.equals(keyprefStartAudioBitrateType)
+ || key.equals(keyPrefAudioCodec)
+ || key.equals(keyPrefRoomServerUrl)) {
updateSummary(sharedPreferences, key);
- } else if (key.equals(keyprefStartBitrateValue)) {
+ } else if (key.equals(keyprefStartVideoBitrateValue)
+ || key.equals(keyprefStartAudioBitrateValue)) {
updateSummaryBitrate(sharedPreferences, key);
- } else if (key.equals(keyprefCpuUsageDetection)
- || key.equals(keyprefHwCodec) || key.equals(keyPrefDisplayHud)) {
+ } else if (key.equals(keyprefVideoCall)
+ || key.equals(keyprefHwCodec)
+ || key.equals(keyprefCpuUsageDetection)
+ || key.equals(keyPrefDisplayHud)) {
updateSummaryB(sharedPreferences, key);
}
- if (key.equals(keyprefStartBitrateType)) {
- setBitrateEnable(sharedPreferences);
+ if (key.equals(keyprefStartVideoBitrateType)) {
+ setVideoBitrateEnable(sharedPreferences);
+ }
+ if (key.equals(keyprefStartAudioBitrateType)) {
+ setAudioBitrateEnable(sharedPreferences);
}
}
@@ -135,12 +162,25 @@ public class SettingsActivity extends Activity
: getString(R.string.pref_value_disabled));
}
- private void setBitrateEnable(SharedPreferences sharedPreferences) {
+ private void setVideoBitrateEnable(SharedPreferences sharedPreferences) {
Preference bitratePreferenceValue =
- settingsFragment.findPreference(keyprefStartBitrateValue);
- String bitrateTypeDefault = getString(R.string.pref_startbitrate_default);
+ settingsFragment.findPreference(keyprefStartVideoBitrateValue);
+ String bitrateTypeDefault = getString(R.string.pref_startvideobitrate_default);
String bitrateType = sharedPreferences.getString(
- keyprefStartBitrateType, bitrateTypeDefault);
+ keyprefStartVideoBitrateType, bitrateTypeDefault);
+ if (bitrateType.equals(bitrateTypeDefault)) {
+ bitratePreferenceValue.setEnabled(false);
+ } else {
+ bitratePreferenceValue.setEnabled(true);
+ }
+ }
+
+ private void setAudioBitrateEnable(SharedPreferences sharedPreferences) {
+ Preference bitratePreferenceValue =
+ settingsFragment.findPreference(keyprefStartAudioBitrateValue);
+ String bitrateTypeDefault = getString(R.string.pref_startaudiobitrate_default);
+ String bitrateType = sharedPreferences.getString(
+ keyprefStartAudioBitrateType, bitrateTypeDefault);
if (bitrateType.equals(bitrateTypeDefault)) {
bitratePreferenceValue.setEnabled(false);
} else {
diff --git a/talk/examples/android/src/org/appspot/apprtc/util/AsyncHttpURLConnection.java b/talk/examples/android/src/org/appspot/apprtc/util/AsyncHttpURLConnection.java
index 120644c5d6..888434f881 100644
--- a/talk/examples/android/src/org/appspot/apprtc/util/AsyncHttpURLConnection.java
+++ b/talk/examples/android/src/org/appspot/apprtc/util/AsyncHttpURLConnection.java
@@ -39,7 +39,7 @@ import java.util.Scanner;
* Asynchronous http requests implementation.
*/
public class AsyncHttpURLConnection {
- private static final int HTTP_TIMEOUT_MS = 5000;
+ private static final int HTTP_TIMEOUT_MS = 8000;
private final String method;
private final String url;
private final String message;