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
This commit is contained in:
parent
008731868a
commit
58edb83fd4
@ -12,6 +12,15 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
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
|
<TextView
|
||||||
android:id="@+id/room_name"
|
android:id="@+id/room_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
|
|
||||||
package org.appspot.apprtc;
|
package org.appspot.apprtc;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
@ -83,6 +86,7 @@ public class AppRTCDemoActivity extends Activity
|
|||||||
private final LayoutParams hudLayout =
|
private final LayoutParams hudLayout =
|
||||||
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||||
private TextView hudView;
|
private TextView hudView;
|
||||||
|
private TextView encoderStatView;
|
||||||
private TextView roomName;
|
private TextView roomName;
|
||||||
private ImageButton videoScalingButton;
|
private ImageButton videoScalingButton;
|
||||||
private boolean commandLineRun;
|
private boolean commandLineRun;
|
||||||
@ -111,6 +115,7 @@ public class AppRTCDemoActivity extends Activity
|
|||||||
iceConnected = false;
|
iceConnected = false;
|
||||||
|
|
||||||
rootView = findViewById(android.R.id.content);
|
rootView = findViewById(android.R.id.content);
|
||||||
|
encoderStatView = (TextView)findViewById(R.id.encoder_stat);
|
||||||
menuBar = findViewById(R.id.menubar_fragment);
|
menuBar = findViewById(R.id.menubar_fragment);
|
||||||
roomName = (TextView) findViewById(R.id.room_name);
|
roomName = (TextView) findViewById(R.id.room_name);
|
||||||
videoView = (GLSurfaceView) findViewById(R.id.glview);
|
videoView = (GLSurfaceView) findViewById(R.id.glview);
|
||||||
@ -126,9 +131,11 @@ public class AppRTCDemoActivity extends Activity
|
|||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
int visibility = menuBar.getVisibility() == View.VISIBLE
|
int visibility = menuBar.getVisibility() == View.VISIBLE
|
||||||
? View.INVISIBLE : View.VISIBLE;
|
? View.INVISIBLE : View.VISIBLE;
|
||||||
|
encoderStatView.setVisibility(visibility);
|
||||||
menuBar.setVisibility(visibility);
|
menuBar.setVisibility(visibility);
|
||||||
roomName.setVisibility(visibility);
|
roomName.setVisibility(visibility);
|
||||||
if (visibility == View.VISIBLE) {
|
if (visibility == View.VISIBLE) {
|
||||||
|
encoderStatView.bringToFront();
|
||||||
menuBar.bringToFront();
|
menuBar.bringToFront();
|
||||||
roomName.bringToFront();
|
roomName.bringToFront();
|
||||||
rootView.invalidate();
|
rootView.invalidate();
|
||||||
@ -283,53 +290,6 @@ public class AppRTCDemoActivity extends Activity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// Disconnect from remote resources, dispose of local resources, and exit.
|
||||||
private void disconnect() {
|
private void disconnect() {
|
||||||
if (appRtcClient != null) {
|
if (appRtcClient != null) {
|
||||||
@ -387,6 +347,99 @@ public class AppRTCDemoActivity extends Activity
|
|||||||
logToast.show();
|
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 ---------------
|
// -----Implementation of AppRTCClient.AppRTCSignalingEvents ---------------
|
||||||
// All events are called from UI thread.
|
// All events are called from UI thread.
|
||||||
@Override
|
@Override
|
||||||
@ -410,37 +463,39 @@ public class AppRTCDemoActivity extends Activity
|
|||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// Schedule statistics display.
|
||||||
final Runnable repeatedStatsLogger = new Runnable() {
|
final Runnable repeatedStatsLogger = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (pc == null) {
|
if (pc == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Runnable runnableThis = this;
|
final Runnable runnableThis = this;
|
||||||
if (hudView.getVisibility() == View.INVISIBLE) {
|
if (hudView.getVisibility() == View.INVISIBLE &&
|
||||||
videoView.postDelayed(runnableThis, 1000);
|
encoderStatView.getVisibility() == View.INVISIBLE) {
|
||||||
return;
|
videoView.postDelayed(runnableThis, 1000);
|
||||||
}
|
return;
|
||||||
boolean success = pc.getStats(new StatsObserver() {
|
}
|
||||||
public void onComplete(final StatsReport[] reports) {
|
boolean success = pc.getStats(new StatsObserver() {
|
||||||
runOnUiThread(new Runnable() {
|
public void onComplete(final StatsReport[] reports) {
|
||||||
public void run() {
|
runOnUiThread(new Runnable() {
|
||||||
updateHUD(reports);
|
public void run() {
|
||||||
}
|
if (hudView.getVisibility() == View.VISIBLE) {
|
||||||
});
|
updateHUD(reports);
|
||||||
for (StatsReport report : reports) {
|
}
|
||||||
Log.d(TAG, "Stats: " + report.toString());
|
if (encoderStatView.getVisibility() == View.VISIBLE) {
|
||||||
|
updateEncoderStatistics(reports);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
videoView.postDelayed(runnableThis, 1000);
|
});
|
||||||
}
|
videoView.postDelayed(runnableThis, 1000);
|
||||||
}, null);
|
|
||||||
if (!success) {
|
|
||||||
throw new RuntimeException("getStats() return false!");
|
|
||||||
}
|
}
|
||||||
}
|
}, null);
|
||||||
};
|
if (!success) {
|
||||||
videoView.postDelayed(repeatedStatsLogger, 1000);
|
throw new RuntimeException("getStats() return false!");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
videoView.postDelayed(repeatedStatsLogger, 1000);
|
||||||
|
|
||||||
logAndToast("Waiting for remote connection...");
|
logAndToast("Waiting for remote connection...");
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,9 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
public class PeerConnectionClient {
|
public class PeerConnectionClient {
|
||||||
private static final String TAG = "PCRTCClient";
|
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 final Activity activity;
|
||||||
private PeerConnectionFactory factory;
|
private PeerConnectionFactory factory;
|
||||||
private PeerConnection pc;
|
private PeerConnection pc;
|
||||||
@ -119,7 +122,7 @@ public class PeerConnectionClient {
|
|||||||
if (signalingParameters.audioConstraints != null) {
|
if (signalingParameters.audioConstraints != null) {
|
||||||
MediaStream lMS = factory.createLocalMediaStream("ARDAMSAudio");
|
MediaStream lMS = factory.createLocalMediaStream("ARDAMSAudio");
|
||||||
lMS.addTrack(factory.createAudioTrack(
|
lMS.addTrack(factory.createAudioTrack(
|
||||||
"ARDAMSa0",
|
AUDIO_TRACK_ID,
|
||||||
factory.createAudioSource(signalingParameters.audioConstraints)));
|
factory.createAudioSource(signalingParameters.audioConstraints)));
|
||||||
pc.addStream(lMS);
|
pc.addStream(lMS);
|
||||||
}
|
}
|
||||||
@ -320,7 +323,7 @@ public class PeerConnectionClient {
|
|||||||
capturer, videoConstraints);
|
capturer, videoConstraints);
|
||||||
String trackExtension = frontFacing ? "frontFacing" : "backFacing";
|
String trackExtension = frontFacing ? "frontFacing" : "backFacing";
|
||||||
VideoTrack videoTrack =
|
VideoTrack videoTrack =
|
||||||
factory.createVideoTrack("ARDAMSv0" + trackExtension, videoSource);
|
factory.createVideoTrack(VIDEO_TRACK_ID + trackExtension, videoSource);
|
||||||
videoTrack.addRenderer(new VideoRenderer(localRender));
|
videoTrack.addRenderer(new VideoRenderer(localRender));
|
||||||
return videoTrack;
|
return videoTrack;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user