From 243eb8e9af35f07befa733c86dd320f9f8b021bd Mon Sep 17 00:00:00 2001 From: "glaznev@webrtc.org" Date: Mon, 27 Oct 2014 17:22:15 +0000 Subject: [PATCH] Adding setting screen to AppRTCDemo. - Move server URL from connection screen to the setting screen. - Add setting for local video resolution. - Auto save last entered room number. - Use full screen mode in video renderer and fix texture offsets recalculation when rendering type is dynamically changed. BUG=3935,3953 R=kjellander@webrtc.org, pbos@webrtc.org, pthatcher@webrtc.org Review URL: https://webrtc-codereview.appspot.com/30769004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7534 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../android/org/webrtc/VideoRendererGui.java | 44 +++++----- talk/examples/android/AndroidManifest.xml | 8 +- .../android/res/layout/activity_connect.xml | 16 +--- .../android/res/menu/connect_menu.xml | 8 ++ talk/examples/android/res/values/arrays.xml | 15 ++++ talk/examples/android/res/values/strings.xml | 18 +++- talk/examples/android/res/xml/preferences.xml | 18 ++++ .../appspot/apprtc/AppRTCDemoActivity.java | 4 +- .../org/appspot/apprtc/ConnectActivity.java | 79 +++++++++++++++-- .../org/appspot/apprtc/SettingsActivity.java | 88 +++++++++++++++++++ .../org/appspot/apprtc/SettingsFragment.java | 41 +++++++++ talk/libjingle_examples.gyp | 5 ++ 12 files changed, 297 insertions(+), 47 deletions(-) create mode 100644 talk/examples/android/res/menu/connect_menu.xml create mode 100644 talk/examples/android/res/values/arrays.xml create mode 100644 talk/examples/android/res/xml/preferences.xml create mode 100644 talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java create mode 100644 talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java index a39377441..acaa31e78 100644 --- a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java +++ b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java @@ -324,6 +324,8 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { float texLeft = this.texLeft; float texTop = this.texTop; float texBottom = this.texBottom; + float texOffsetU = 0; + float texOffsetV = 0; float displayWidth = (texRight - texLeft) * screenWidth / 2; float displayHeight = (texTop - texBottom) * screenHeight / 2; Log.d(TAG, "ID: " + id + ". Display: " + displayWidth + @@ -346,36 +348,33 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { texTop -= deltaY; texBottom += deltaY; } - Log.d(TAG, " Texture vertices: (" + texLeft + "," + texBottom + - ") - (" + texRight + "," + texTop + ")"); - // Re-allocate vertices buffer to adjust to video aspect ratio. - float textureVeticesFloat[] = new float[] { - texLeft, texTop, - texLeft, texBottom, - texRight, texTop, - texRight, texBottom - }; - textureVertices = directNativeFloatBuffer(textureVeticesFloat); } if (scalingType == ScalingType.SCALE_ASPECT_FILL) { - float texOffsetU = 0; - float texOffsetV = 0; // Need to re-adjust UV coordinates to match display AR. if (displayAspectRatio > videoAspectRatio) { texOffsetV = (1.0f - videoAspectRatio / displayAspectRatio) / 2.0f; } else { texOffsetU = (1.0f - displayAspectRatio / videoAspectRatio) / 2.0f; } - Log.d(TAG, " Texture UV offsets: " + texOffsetU + ", " + texOffsetV); - // Re-allocate coordinates buffer to adjust to display aspect ratio. - float textureCoordinatesFloat[] = new float[] { - texOffsetU, texOffsetV, // left top - texOffsetU, 1.0f - texOffsetV, // left bottom - 1.0f - texOffsetU, texOffsetV, // right top - 1.0f - texOffsetU, 1.0f - texOffsetV // right bottom - }; - textureCoords = directNativeFloatBuffer(textureCoordinatesFloat); } + Log.d(TAG, " Texture vertices: (" + texLeft + "," + texBottom + + ") - (" + texRight + "," + texTop + ")"); + float textureVeticesFloat[] = new float[] { + texLeft, texTop, + texLeft, texBottom, + texRight, texTop, + texRight, texBottom + }; + textureVertices = directNativeFloatBuffer(textureVeticesFloat); + + Log.d(TAG, " Texture UV offsets: " + texOffsetU + ", " + texOffsetV); + float textureCoordinatesFloat[] = new float[] { + texOffsetU, texOffsetV, // left top + texOffsetU, 1.0f - texOffsetV, // left bottom + 1.0f - texOffsetU, texOffsetV, // right top + 1.0f - texOffsetU, 1.0f - texOffsetV // right bottom + }; + textureCoords = directNativeFloatBuffer(textureCoordinatesFloat); } updateTextureProperties = false; } @@ -501,6 +500,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { texTop = (50 - y) / 50.0f; texRight = Math.min(1.0f, (x + width - 50) / 50.0f); texBottom = Math.max(-1.0f, (50 - y - height) / 50.0f); + this.scalingType = scalingType; updateTextureProperties = true; } @@ -690,7 +690,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { onSurfaceCreatedCalled = true; } checkNoGLES2Error(); - GLES20.glClearColor(0.0f, 0.0f, 0.1f, 1.0f); + GLES20.glClearColor(0.15f, 0.15f, 0.15f, 1.0f); } @Override diff --git a/talk/examples/android/AndroidManifest.xml b/talk/examples/android/AndroidManifest.xml index cdf674deb..30fd46c01 100644 --- a/talk/examples/android/AndroidManifest.xml +++ b/talk/examples/android/AndroidManifest.xml @@ -7,7 +7,7 @@ - + @@ -18,6 +18,7 @@ + @@ -33,6 +34,11 @@ + + + + - - + + diff --git a/talk/examples/android/res/values/arrays.xml b/talk/examples/android/res/values/arrays.xml new file mode 100644 index 000000000..af56eb94a --- /dev/null +++ b/talk/examples/android/res/values/arrays.xml @@ -0,0 +1,15 @@ + + + + Default + HD (1280 x 720) + VGA (640 x 480) + QVGA (320 x 240) + + + Default + 1280 x 720 + 640 x 480 + 320 x 240 + + diff --git a/talk/examples/android/res/values/strings.xml b/talk/examples/android/res/values/strings.xml index 756a7a2fd..801548908 100644 --- a/talk/examples/android/res/values/strings.xml +++ b/talk/examples/android/res/values/strings.xml @@ -1,8 +1,8 @@ AppRTC + AppRTC Settings Disconnect Call - URL: Room name: Please enter a room name. Room names are shared with everyone, so think @@ -16,4 +16,20 @@ Connecting to: %1$s FATAL ERROR: Missing URL to connect to. OK + Settings + + + room_preference + + url_preference + Connection URL: + AppRTC connection server URL. + Enter AppRTC connection server URL. + https://apprtc.appspot.com + + resolution_preference + Video resolution. + Video resolution. + Enter AppRTC local video resolution. + Default diff --git a/talk/examples/android/res/xml/preferences.xml b/talk/examples/android/res/xml/preferences.xml new file mode 100644 index 000000000..efabd3e3b --- /dev/null +++ b/talk/examples/android/res/xml/preferences.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java index 32728aa9a..01ae7348d 100644 --- a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java +++ b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java @@ -110,9 +110,9 @@ public class AppRTCDemoActivity extends Activity VideoRendererGui.setView(videoView); remoteRender = VideoRendererGui.create(0, 0, 100, 100, - VideoRendererGui.ScalingType.SCALE_ASPECT_FIT); + VideoRendererGui.ScalingType.SCALE_ASPECT_FILL); localRender = VideoRendererGui.create(0, 0, 100, 100, - VideoRendererGui.ScalingType.SCALE_ASPECT_FIT); + VideoRendererGui.ScalingType.SCALE_ASPECT_FILL); videoView.setOnClickListener( new View.OnClickListener() { diff --git a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java index 2df6fcfa4..6a2ca5b31 100644 --- a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java +++ b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java @@ -31,9 +31,15 @@ import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.inputmethod.EditorInfo; @@ -51,16 +57,25 @@ import org.webrtc.MediaCodecVideoEncoder; public class ConnectActivity extends Activity { private static final String TAG = "ConnectActivity"; - public static final String CONNECT_URL_EXTRA = "connect_url"; private Button connectButton; - private EditText urlEditText; private EditText roomEditText; private CheckBox loopbackCheckBox; + private SharedPreferences sharedPref; + private String keyprefUrl; + private String keyprefResolution; + private String keyprefRoom; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // Get setting keys. + PreferenceManager.setDefaultValues(this, R.xml.preferences, false); + sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + keyprefUrl = getString(R.string.pref_url_key); + keyprefResolution = getString(R.string.pref_resolution_key); + keyprefRoom = getString(R.string.pref_room_key); + // If an implicit VIEW intent is launching the app, go directly to that URL. final Intent intent = getIntent(); if ("android.intent.action.VIEW".equals(intent.getAction())) { @@ -70,8 +85,6 @@ public class ConnectActivity extends Activity { setContentView(R.layout.activity_connect); - urlEditText = (EditText) findViewById(R.id.url_edittext); - loopbackCheckBox = (CheckBox) findViewById(R.id.check_loopback); loopbackCheckBox.setChecked(false); @@ -94,15 +107,33 @@ public class ConnectActivity extends Activity { connectButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - String url = urlEditText.getText().toString(); + String url = sharedPref.getString(keyprefUrl, + getString(R.string.pref_url_default)); if (loopbackCheckBox.isChecked()) { url += "/?debug=loopback"; } else { url += "/?r=" + roomEditText.getText(); } - if (MediaCodecVideoEncoder.isPlatformSupported()) { - url += "&hd=true"; + // Add video resolution constraints. + String resolution = sharedPref.getString(keyprefResolution, + getString(R.string.pref_resolution_default)); + String[] dimensions = resolution.split("[ x]+"); + if (dimensions.length == 2) { + try { + int maxWidth = Integer.parseInt(dimensions[0]); + int maxHeight = Integer.parseInt(dimensions[1]); + if (maxWidth > 0 && maxHeight > 0) { + url += "&video=minHeight=" + maxHeight + ",maxHeight=" + + maxHeight + ",minWidth=" + maxWidth + ",maxWidth=" + maxWidth; + } + } catch (NumberFormatException e) { + Log.e(TAG, "Wrong video resolution setting: " + resolution); + } + } else { + if (MediaCodecVideoEncoder.isPlatformSupported()) { + url += "&hd=true"; + } } // TODO(kjellander): Add support for custom parameters to the URL. connectToRoom(url); @@ -110,6 +141,40 @@ public class ConnectActivity extends Activity { }); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.connect_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle presses on the action bar items. + if (item.getItemId() == R.id.action_settings) { + Intent intent = new Intent(this, SettingsActivity.class); + startActivity(intent); + return true; + } else { + return super.onOptionsItemSelected(item); + } + } + + @Override + public void onPause() { + super.onPause(); + String room = roomEditText.getText().toString(); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString(keyprefRoom, room); + editor.commit(); + } + + @Override + public void onResume() { + super.onResume(); + String room = sharedPref.getString(keyprefRoom, ""); + roomEditText.setText(room); + } + private void connectToRoom(String roomUrl) { if (validateUrl(roomUrl)) { Uri url = Uri.parse(roomUrl); diff --git a/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java new file mode 100644 index 000000000..e974aafce --- /dev/null +++ b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java @@ -0,0 +1,88 @@ +/* + * libjingle + * Copyright 2014, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.appspot.apprtc; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.preference.Preference; + +public class SettingsActivity extends Activity + implements OnSharedPreferenceChangeListener{ + private SettingsFragment settingsFragment; + private String keyprefUrl; + private String keyprefResolution; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + keyprefUrl = getString(R.string.pref_url_key); + keyprefResolution = getString(R.string.pref_resolution_key); + + // Display the fragment as the main content. + settingsFragment = new SettingsFragment(); + getFragmentManager().beginTransaction() + .replace(android.R.id.content, settingsFragment) + .commit(); + } + + @Override + protected void onResume() { + super.onResume(); + // Set summary to be the user-description for the selected value + SharedPreferences sharedPreferences = + settingsFragment.getPreferenceScreen().getSharedPreferences(); + sharedPreferences.registerOnSharedPreferenceChangeListener(this); + updateSummary(sharedPreferences, keyprefUrl); + updateSummary(sharedPreferences, keyprefResolution); + } + + @Override + protected void onPause() { + super.onPause(); + SharedPreferences sharedPreferences = + settingsFragment.getPreferenceScreen().getSharedPreferences(); + sharedPreferences.unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + if (key.equals(keyprefUrl) || key.equals(keyprefResolution)) { + updateSummary(sharedPreferences, key); + } + } + + private void updateSummary(SharedPreferences sharedPreferences, String key) { + Preference updatedPref = settingsFragment.findPreference(key); + // Set summary to be the user-description for the selected value + updatedPref.setSummary(sharedPreferences.getString(key, "")); + } + +} diff --git a/talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java b/talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java new file mode 100644 index 000000000..ec4b70481 --- /dev/null +++ b/talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java @@ -0,0 +1,41 @@ +/* + * libjingle + * Copyright 2014, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.appspot.apprtc; + +import android.os.Bundle; +import android.preference.PreferenceFragment; + +public class SettingsFragment extends PreferenceFragment { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Load the preferences from an XML resource + addPreferencesFromResource(R.xml.preferences); + } +} diff --git a/talk/libjingle_examples.gyp b/talk/libjingle_examples.gyp index ff49a8e93..ae1597583 100755 --- a/talk/libjingle_examples.gyp +++ b/talk/libjingle_examples.gyp @@ -328,13 +328,18 @@ 'examples/android/res/layout/activity_connect.xml', 'examples/android/res/layout/activity_fullscreen.xml', 'examples/android/res/layout/fragment_menubar.xml', + 'examples/android/res/menu/connect_menu.xml', + 'examples/android/res/values/arrays.xml', 'examples/android/res/values/strings.xml', + 'examples/android/res/xml/preferences.xml', 'examples/android/src/org/appspot/apprtc/AppRTCClient.java', 'examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java', 'examples/android/src/org/appspot/apprtc/ConnectActivity.java', 'examples/android/src/org/appspot/apprtc/GAEChannelClient.java', 'examples/android/src/org/appspot/apprtc/GAERTCClient.java', 'examples/android/src/org/appspot/apprtc/PeerConnectionClient.java', + 'examples/android/src/org/appspot/apprtc/SettingsActivity.java', + 'examples/android/src/org/appspot/apprtc/SettingsFragment.java', 'examples/android/src/org/appspot/apprtc/UnhandledExceptionHandler.java', ], 'outputs': [