Add video encoder fps and bitrate statistics to
Android AppRTCDemo UI.
BUG=4045
R=jiayl@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/25229004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7747 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/examples/android/res/layout/activity_fullscreen.xml b/talk/examples/android/res/layout/activity_fullscreen.xml
index fc9ee9e..f3fc003 100644
--- a/talk/examples/android/res/layout/activity_fullscreen.xml
+++ b/talk/examples/android/res/layout/activity_fullscreen.xml
@@ -13,6 +13,15 @@
android:layout_height="match_parent" />
<TextView
+ android:id="@+id/encoder_stat"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:textStyle="bold"
+ android:textColor="#800000FF"
+ android:textSize="12dp"
+ android:layout_margin="8dp"/>
+ <TextView
android:id="@+id/room_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
index 1c5790f..5743a47 100644
--- a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
@@ -27,6 +27,9 @@
package org.appspot.apprtc;
+import java.util.HashMap;
+import java.util.Map;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
@@ -83,6 +86,7 @@
private final LayoutParams hudLayout =
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
private TextView hudView;
+ private TextView encoderStatView;
private TextView roomName;
private ImageButton videoScalingButton;
private boolean commandLineRun;
@@ -111,6 +115,7 @@
iceConnected = false;
rootView = findViewById(android.R.id.content);
+ encoderStatView = (TextView)findViewById(R.id.encoder_stat);
menuBar = findViewById(R.id.menubar_fragment);
roomName = (TextView) findViewById(R.id.room_name);
videoView = (GLSurfaceView) findViewById(R.id.glview);
@@ -126,9 +131,11 @@
public void onClick(View view) {
int visibility = menuBar.getVisibility() == View.VISIBLE
? View.INVISIBLE : View.VISIBLE;
+ encoderStatView.setVisibility(visibility);
menuBar.setVisibility(visibility);
roomName.setVisibility(visibility);
if (visibility == View.VISIBLE) {
+ encoderStatView.bringToFront();
menuBar.bringToFront();
roomName.bringToFront();
rootView.invalidate();
@@ -283,53 +290,6 @@
}
}
- // Update the heads-up display with information from |reports|.
- private void updateHUD(StatsReport[] reports) {
- StringBuilder builder = new StringBuilder();
- for (StatsReport report : reports) {
- // bweforvideo to show statistics for video Bandwidth Estimation,
- // which is global per-session.
- if (report.id.equals("bweforvideo")) {
- for (StatsReport.Value value : report.values) {
- String name = value.name.replace("goog", "")
- .replace("Available", "").replace("Bandwidth", "")
- .replace("Bitrate", "").replace("Enc", "");
-
- builder.append(name).append("=").append(value.value)
- .append(" ");
- }
- builder.append("\n");
- } else if (report.type.equals("googCandidatePair")) {
- String activeConnectionStats = getActiveConnectionStats(report);
- if (activeConnectionStats == null) {
- continue;
- }
- builder.append(activeConnectionStats);
- } else {
- continue;
- }
- builder.append("\n");
- }
- hudView.setText(builder.toString() + hudView.getText());
- }
-
- // Return the active connection stats else return null
- private String getActiveConnectionStats(StatsReport report) {
- StringBuilder activeConnectionbuilder = new StringBuilder();
- // googCandidatePair to show information about the active
- // connection.
- for (StatsReport.Value value : report.values) {
- if (value.name.equals("googActiveConnection")
- && value.value.equals("false")) {
- return null;
- }
- String name = value.name.replace("goog", "");
- activeConnectionbuilder.append(name).append("=")
- .append(value.value).append("\n");
- }
- return activeConnectionbuilder.toString();
- }
-
// Disconnect from remote resources, dispose of local resources, and exit.
private void disconnect() {
if (appRtcClient != null) {
@@ -387,6 +347,99 @@
logToast.show();
}
+ // Return the active connection stats,
+ // or null if active connection is not found.
+ private String getActiveConnectionStats(StatsReport report) {
+ StringBuilder activeConnectionbuilder = new StringBuilder();
+ // googCandidatePair to show information about the active
+ // connection.
+ for (StatsReport.Value value : report.values) {
+ if (value.name.equals("googActiveConnection")
+ && value.value.equals("false")) {
+ return null;
+ }
+ String name = value.name.replace("goog", "");
+ activeConnectionbuilder.append(name).append("=")
+ .append(value.value).append("\n");
+ }
+ return activeConnectionbuilder.toString();
+ }
+
+ // Update the heads-up display with information from |reports|.
+ private void updateHUD(StatsReport[] reports) {
+ StringBuilder builder = new StringBuilder();
+ for (StatsReport report : reports) {
+ Log.d(TAG, "Stats: " + report.toString());
+ // bweforvideo to show statistics for video Bandwidth Estimation,
+ // which is global per-session.
+ if (report.id.equals("bweforvideo")) {
+ for (StatsReport.Value value : report.values) {
+ String name = value.name.replace("goog", "")
+ .replace("Available", "").replace("Bandwidth", "")
+ .replace("Bitrate", "").replace("Enc", "");
+
+ builder.append(name).append("=").append(value.value)
+ .append(" ");
+ }
+ builder.append("\n");
+ } else if (report.type.equals("googCandidatePair")) {
+ String activeConnectionStats = getActiveConnectionStats(report);
+ if (activeConnectionStats == null) {
+ continue;
+ }
+ builder.append(activeConnectionStats);
+ } else {
+ continue;
+ }
+ builder.append("\n");
+ }
+ hudView.setText(builder.toString() + hudView.getText());
+ }
+
+ private Map<String, String> getReportMap(StatsReport report) {
+ Map<String, String> reportMap = new HashMap<String, String>();
+ for (StatsReport.Value value : report.values) {
+ reportMap.put(value.name, value.value);
+ }
+ return reportMap;
+ }
+
+ // Update encoder statistics view with information from |reports|.
+ private void updateEncoderStatistics(StatsReport[] reports) {
+ if (!iceConnected) {
+ return;
+ }
+ String fps = null;
+ String targetBitrate = null;
+ String actualBitrate = null;
+ for (StatsReport report : reports) {
+ if (report.type.equals("ssrc") && report.id.contains("ssrc") &&
+ report.id.contains("send")) {
+ Map<String, String> reportMap = getReportMap(report);
+ String trackId = reportMap.get("googTrackId");
+ if (trackId != null &&
+ trackId.contains(PeerConnectionClient.VIDEO_TRACK_ID)) {
+ fps = reportMap.get("googFrameRateSent");
+ }
+ } else if (report.id.equals("bweforvideo")) {
+ Map<String, String> reportMap = getReportMap(report);
+ targetBitrate = reportMap.get("googTargetEncBitrate");
+ actualBitrate = reportMap.get("googActualEncBitrate");
+ }
+ }
+ String stat = "";
+ if (fps != null) {
+ stat += "Fps: " + fps + "\n";
+ }
+ if (targetBitrate != null) {
+ stat += "Target BR: " + targetBitrate + "\n";
+ }
+ if (actualBitrate != null) {
+ stat += "Actual BR: " + actualBitrate;
+ }
+ encoderStatView.setText(stat);
+ }
+
// -----Implementation of AppRTCClient.AppRTCSignalingEvents ---------------
// All events are called from UI thread.
@Override
@@ -410,37 +463,39 @@
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
- {
- final Runnable repeatedStatsLogger = new Runnable() {
- public void run() {
- if (pc == null) {
- return;
- }
- final Runnable runnableThis = this;
- if (hudView.getVisibility() == View.INVISIBLE) {
- videoView.postDelayed(runnableThis, 1000);
- return;
- }
- boolean success = pc.getStats(new StatsObserver() {
- public void onComplete(final StatsReport[] reports) {
- runOnUiThread(new Runnable() {
- public void run() {
- updateHUD(reports);
- }
- });
- for (StatsReport report : reports) {
- Log.d(TAG, "Stats: " + report.toString());
+ // Schedule statistics display.
+ final Runnable repeatedStatsLogger = new Runnable() {
+ public void run() {
+ if (pc == null) {
+ return;
+ }
+ final Runnable runnableThis = this;
+ if (hudView.getVisibility() == View.INVISIBLE &&
+ encoderStatView.getVisibility() == View.INVISIBLE) {
+ videoView.postDelayed(runnableThis, 1000);
+ return;
+ }
+ boolean success = pc.getStats(new StatsObserver() {
+ public void onComplete(final StatsReport[] reports) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if (hudView.getVisibility() == View.VISIBLE) {
+ updateHUD(reports);
+ }
+ if (encoderStatView.getVisibility() == View.VISIBLE) {
+ updateEncoderStatistics(reports);
+ }
}
- videoView.postDelayed(runnableThis, 1000);
- }
- }, null);
- if (!success) {
- throw new RuntimeException("getStats() return false!");
+ });
+ videoView.postDelayed(runnableThis, 1000);
}
- }
- };
- videoView.postDelayed(repeatedStatsLogger, 1000);
- }
+ }, null);
+ if (!success) {
+ throw new RuntimeException("getStats() return false!");
+ }
+ }
+ };
+ videoView.postDelayed(repeatedStatsLogger, 1000);
logAndToast("Waiting for remote connection...");
}
diff --git a/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java b/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
index 247b0aa..0b357e0 100644
--- a/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
+++ b/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
@@ -54,6 +54,9 @@
public class PeerConnectionClient {
private static final String TAG = "PCRTCClient";
+ public static final String VIDEO_TRACK_ID = "ARDAMSv0";
+ public static final String AUDIO_TRACK_ID = "ARDAMSa0";
+
private final Activity activity;
private PeerConnectionFactory factory;
private PeerConnection pc;
@@ -119,7 +122,7 @@
if (signalingParameters.audioConstraints != null) {
MediaStream lMS = factory.createLocalMediaStream("ARDAMSAudio");
lMS.addTrack(factory.createAudioTrack(
- "ARDAMSa0",
+ AUDIO_TRACK_ID,
factory.createAudioSource(signalingParameters.audioConstraints)));
pc.addStream(lMS);
}
@@ -320,7 +323,7 @@
capturer, videoConstraints);
String trackExtension = frontFacing ? "frontFacing" : "backFacing";
VideoTrack videoTrack =
- factory.createVideoTrack("ARDAMSv0" + trackExtension, videoSource);
+ factory.createVideoTrack(VIDEO_TRACK_ID + trackExtension, videoSource);
videoTrack.addRenderer(new VideoRenderer(localRender));
return videoTrack;
}