• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 package org.appspot.apprtc;
12 
13 import android.app.Fragment;
14 import android.os.Bundle;
15 import android.util.TypedValue;
16 import android.view.LayoutInflater;
17 import android.view.View;
18 import android.view.ViewGroup;
19 import android.widget.ImageButton;
20 import android.widget.TextView;
21 
22 import org.webrtc.StatsReport;
23 
24 import java.util.HashMap;
25 import java.util.Map;
26 
27 /**
28  * Fragment for HUD statistics display.
29  */
30 public class HudFragment extends Fragment {
31   private TextView encoderStatView;
32   private TextView hudViewBwe;
33   private TextView hudViewConnection;
34   private TextView hudViewVideoSend;
35   private TextView hudViewVideoRecv;
36   private ImageButton toggleDebugButton;
37   private boolean videoCallEnabled;
38   private boolean displayHud;
39   private volatile boolean isRunning;
40   private CpuMonitor cpuMonitor;
41 
42   @Override
onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)43   public View onCreateView(
44       LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
45     View controlView = inflater.inflate(R.layout.fragment_hud, container, false);
46 
47     // Create UI controls.
48     encoderStatView = controlView.findViewById(R.id.encoder_stat_call);
49     hudViewBwe = controlView.findViewById(R.id.hud_stat_bwe);
50     hudViewConnection = controlView.findViewById(R.id.hud_stat_connection);
51     hudViewVideoSend = controlView.findViewById(R.id.hud_stat_video_send);
52     hudViewVideoRecv = controlView.findViewById(R.id.hud_stat_video_recv);
53     toggleDebugButton = controlView.findViewById(R.id.button_toggle_debug);
54 
55     toggleDebugButton.setOnClickListener(new View.OnClickListener() {
56       @Override
57       public void onClick(View view) {
58         if (displayHud) {
59           int visibility =
60               (hudViewBwe.getVisibility() == View.VISIBLE) ? View.INVISIBLE : View.VISIBLE;
61           hudViewsSetProperties(visibility);
62         }
63       }
64     });
65 
66     return controlView;
67   }
68 
69   @Override
onStart()70   public void onStart() {
71     super.onStart();
72 
73     Bundle args = getArguments();
74     if (args != null) {
75       videoCallEnabled = args.getBoolean(CallActivity.EXTRA_VIDEO_CALL, true);
76       displayHud = args.getBoolean(CallActivity.EXTRA_DISPLAY_HUD, false);
77     }
78     int visibility = displayHud ? View.VISIBLE : View.INVISIBLE;
79     encoderStatView.setVisibility(visibility);
80     toggleDebugButton.setVisibility(visibility);
81     hudViewsSetProperties(View.INVISIBLE);
82     isRunning = true;
83   }
84 
85   @Override
onStop()86   public void onStop() {
87     isRunning = false;
88     super.onStop();
89   }
90 
setCpuMonitor(CpuMonitor cpuMonitor)91   public void setCpuMonitor(CpuMonitor cpuMonitor) {
92     this.cpuMonitor = cpuMonitor;
93   }
94 
hudViewsSetProperties(int visibility)95   private void hudViewsSetProperties(int visibility) {
96     hudViewBwe.setVisibility(visibility);
97     hudViewConnection.setVisibility(visibility);
98     hudViewVideoSend.setVisibility(visibility);
99     hudViewVideoRecv.setVisibility(visibility);
100     hudViewBwe.setTextSize(TypedValue.COMPLEX_UNIT_PT, 5);
101     hudViewConnection.setTextSize(TypedValue.COMPLEX_UNIT_PT, 5);
102     hudViewVideoSend.setTextSize(TypedValue.COMPLEX_UNIT_PT, 5);
103     hudViewVideoRecv.setTextSize(TypedValue.COMPLEX_UNIT_PT, 5);
104   }
105 
getReportMap(StatsReport report)106   private Map<String, String> getReportMap(StatsReport report) {
107     Map<String, String> reportMap = new HashMap<>();
108     for (StatsReport.Value value : report.values) {
109       reportMap.put(value.name, value.value);
110     }
111     return reportMap;
112   }
113 
updateEncoderStatistics(final StatsReport[] reports)114   public void updateEncoderStatistics(final StatsReport[] reports) {
115     if (!isRunning || !displayHud) {
116       return;
117     }
118     StringBuilder encoderStat = new StringBuilder(128);
119     StringBuilder bweStat = new StringBuilder();
120     StringBuilder connectionStat = new StringBuilder();
121     StringBuilder videoSendStat = new StringBuilder();
122     StringBuilder videoRecvStat = new StringBuilder();
123     String fps = null;
124     String targetBitrate = null;
125     String actualBitrate = null;
126 
127     for (StatsReport report : reports) {
128       if (report.type.equals("ssrc") && report.id.contains("ssrc") && report.id.contains("send")) {
129         // Send video statistics.
130         Map<String, String> reportMap = getReportMap(report);
131         String trackId = reportMap.get("googTrackId");
132         if (trackId != null && trackId.contains(PeerConnectionClient.VIDEO_TRACK_ID)) {
133           fps = reportMap.get("googFrameRateSent");
134           videoSendStat.append(report.id).append("\n");
135           for (StatsReport.Value value : report.values) {
136             String name = value.name.replace("goog", "");
137             videoSendStat.append(name).append("=").append(value.value).append("\n");
138           }
139         }
140       } else if (report.type.equals("ssrc") && report.id.contains("ssrc")
141           && report.id.contains("recv")) {
142         // Receive video statistics.
143         Map<String, String> reportMap = getReportMap(report);
144         // Check if this stat is for video track.
145         String frameWidth = reportMap.get("googFrameWidthReceived");
146         if (frameWidth != null) {
147           videoRecvStat.append(report.id).append("\n");
148           for (StatsReport.Value value : report.values) {
149             String name = value.name.replace("goog", "");
150             videoRecvStat.append(name).append("=").append(value.value).append("\n");
151           }
152         }
153       } else if (report.id.equals("bweforvideo")) {
154         // BWE statistics.
155         Map<String, String> reportMap = getReportMap(report);
156         targetBitrate = reportMap.get("googTargetEncBitrate");
157         actualBitrate = reportMap.get("googActualEncBitrate");
158 
159         bweStat.append(report.id).append("\n");
160         for (StatsReport.Value value : report.values) {
161           String name = value.name.replace("goog", "").replace("Available", "");
162           bweStat.append(name).append("=").append(value.value).append("\n");
163         }
164       } else if (report.type.equals("googCandidatePair")) {
165         // Connection statistics.
166         Map<String, String> reportMap = getReportMap(report);
167         String activeConnection = reportMap.get("googActiveConnection");
168         if (activeConnection != null && activeConnection.equals("true")) {
169           connectionStat.append(report.id).append("\n");
170           for (StatsReport.Value value : report.values) {
171             String name = value.name.replace("goog", "");
172             connectionStat.append(name).append("=").append(value.value).append("\n");
173           }
174         }
175       }
176     }
177     hudViewBwe.setText(bweStat.toString());
178     hudViewConnection.setText(connectionStat.toString());
179     hudViewVideoSend.setText(videoSendStat.toString());
180     hudViewVideoRecv.setText(videoRecvStat.toString());
181 
182     if (videoCallEnabled) {
183       if (fps != null) {
184         encoderStat.append("Fps:  ").append(fps).append("\n");
185       }
186       if (targetBitrate != null) {
187         encoderStat.append("Target BR: ").append(targetBitrate).append("\n");
188       }
189       if (actualBitrate != null) {
190         encoderStat.append("Actual BR: ").append(actualBitrate).append("\n");
191       }
192     }
193 
194     if (cpuMonitor != null) {
195       encoderStat.append("CPU%: ")
196           .append(cpuMonitor.getCpuUsageCurrent())
197           .append("/")
198           .append(cpuMonitor.getCpuUsageAverage())
199           .append(". Freq: ")
200           .append(cpuMonitor.getFrequencyScaleAverage());
201     }
202     encoderStatView.setText(encoderStat.toString());
203   }
204 }
205