1 # Copyright (c) 2017 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import json 6 7 from autotest_lib.server.cros import cfm_jmidata_helper_base 8 9 # Start index in the JSON object that contains Audio/Video streams related info. 10 AV_INDEX = 4 11 12 SSRC = u'ssrc' 13 GLOBAL = u'global' 14 15 AUDIO_INPUT = u'audioInputLevel' 16 AUDIO_OUTPUT = u'audioOutputLevel' 17 BYTES_RECEIVED = u'bytesReceived' 18 BYTES_SENT = u'bytesSent' 19 ADAPTATION_CHANGES = u'googAdaptationChanges' 20 AVERAGE_ENCODE_TIME = u'googAvgEncodeMs' 21 BANDWIDTH_LIMITED_RESOLUTION = u'googBandwidthLimitedResolution' 22 CPU_LIMITED_RESOLUTION = u'googCpuLimitedResolution' 23 VIDEO_ENCODE_CPU_USAGE = u'googEncodeUsagePercent' 24 VIDEO_RECEIVED_FRAME_HEIGHT = u'googFrameHeightReceived' 25 VIDEO_RECEIVED_FRAME_WIDTH = u'googFrameWidthReceived' 26 FRAMERATE_OUTGOING = u'googFrameRateInput' 27 FRAMERATE_RECEIVED = u'googFrameRateReceived' 28 FRAMERATE_SENT = u'googFrameRateSent' 29 FRAMERATE_DECODED = u'googFrameRateDecoded' 30 FRAMERATE_OUTPUT = u'googFrameRateOutput' 31 FRAME_WIDTH_SENT = u'googFrameWidthSent' 32 FRAME_HEIGHT_SENT = u'googFrameHeightSent' 33 FRAMES_DECODED = u'framesDecoded' 34 FRAMES_ENCODED = u'framesEncoded' 35 VIDEO_PACKETS_LOST = u'packetsLost' 36 VIDEO_PACKETS_SENT = u'packetsSent' 37 38 BROWSER_CPU = u'browserCpuUsage' 39 GPU_CPU = u'gpuCpuUsage' 40 NUM_PROCESSORS = u'numOfProcessors' 41 NACL_EFFECTS_CPU = u'pluginCpuUsage' 42 RENDERER_CPU = u'tabCpuUsage' 43 TOTAL_CPU = u'totalCpuUsage' 44 45 46 class JMIDataV3Helper(cfm_jmidata_helper_base.JMIDataHelperBase): 47 """Helper class for JMI data v3 parsing. This class helps in extracting 48 relevant JMI data from javascript log. 49 50 The class takes javascript file as input and extracts jmidata elements from 51 the file that is internally stored as a list. Whenever we need to extract 52 data i.e. audio received bytes we call a method such as 53 getAudioReceivedDataList. This method converts each string element in the 54 internal list to a json object and retrieves the relevant info from it which 55 is then stored and returned as a list. 56 """ 57 58 def __init__(self, log_file_content): 59 super(JMIDataV3Helper, self).__init__(log_file_content, 'jmidatav3') 60 61 def _ExtractAllJMIDataPointsWithKey(self, jmi_type, is_audio, key): 62 """Extracts all values from the data points with the given key.""" 63 data_list = [] 64 for jmi_data_point in self._jmi_list: 65 json_arr = json.loads(jmi_data_point) 66 for i in range(AV_INDEX, len(json_arr)): 67 if json_arr[i] and jmi_type in json_arr[i]: 68 jmi_obj = json_arr[i][jmi_type] 69 this_is_audio = (AUDIO_INPUT in jmi_obj or 70 AUDIO_OUTPUT in jmi_obj) 71 if this_is_audio == is_audio and key in jmi_obj: 72 if (not isinstance(jmi_obj[key], int) and 73 (jmi_obj[key] == 'false' or 74 jmi_obj[key] == 'true')): 75 jmi_obj[key] = 1 if jmi_obj[key] == 'true' else 0 76 data_list.append(jmi_obj[key]) 77 if not data_list: 78 data_list = [0] 79 return data_list 80 81 def GetAudioReceivedBytesList(self): 82 return self._ExtractAllJMIDataPointsWithKey( 83 jmi_type=SSRC, is_audio=True, key=BYTES_RECEIVED) 84 85 def GetAudioSentBytesList(self): 86 return self._ExtractAllJMIDataPointsWithKey( 87 jmi_type=SSRC, is_audio=True, key=BYTES_SENT) 88 89 def GetAudioReceivedEnergyList(self): 90 return self._ExtractAllJMIDataPointsWithKey( 91 jmi_type=SSRC, is_audio=True, key=AUDIO_OUTPUT) 92 93 def GetAudioSentEnergyList(self): 94 return self._ExtractAllJMIDataPointsWithKey( 95 jmi_type=SSRC, is_audio=True, key=AUDIO_INPUT) 96 97 def GetVideoSentBytesList(self): 98 return self._ExtractAllJMIDataPointsWithKey( 99 jmi_type=SSRC, is_audio=False, key=BYTES_SENT) 100 101 def GetVideoReceivedBytesList(self): 102 return self._ExtractAllJMIDataPointsWithKey( 103 jmi_type=SSRC, is_audio=False, key=BYTES_RECEIVED) 104 105 def GetVideoIncomingFramerateReceivedList(self): 106 return self._ExtractAllJMIDataPointsWithKey( 107 jmi_type=SSRC, is_audio=False, key=FRAMERATE_RECEIVED) 108 109 def GetVideoOutgoingFramerateSentList(self): 110 return self._ExtractAllJMIDataPointsWithKey( 111 jmi_type=SSRC, is_audio=False, key=FRAMERATE_SENT) 112 113 def GetVideoIncomingFramerateDecodedList(self): 114 return self._ExtractAllJMIDataPointsWithKey( 115 jmi_type=SSRC, is_audio=False, key=FRAMERATE_DECODED) 116 117 def GetVideoIncomingFramerateList(self): 118 return self._ExtractAllJMIDataPointsWithKey( 119 jmi_type=SSRC, is_audio=False, key=FRAMERATE_OUTPUT) 120 121 def GetVideoSentFrameWidthList(self): 122 return self._ExtractAllJMIDataPointsWithKey( 123 jmi_type=SSRC, is_audio=False, key=FRAME_WIDTH_SENT) 124 125 def GetVideoSentFrameHeightList(self): 126 return self._ExtractAllJMIDataPointsWithKey( 127 jmi_type=SSRC, is_audio=False, key=FRAME_HEIGHT_SENT) 128 129 def GetCPULimitedResolutionList(self): 130 return self._ExtractAllJMIDataPointsWithKey( 131 jmi_type=SSRC, is_audio=False, key=CPU_LIMITED_RESOLUTION) 132 133 def GetVideoPacketsSentList(self): 134 return self._ExtractAllJMIDataPointsWithKey( 135 jmi_type=SSRC, is_audio=False, key=VIDEO_PACKETS_SENT) 136 137 def GetVideoPacketsLostList(self): 138 return self._ExtractAllJMIDataPointsWithKey( 139 jmi_type=SSRC, is_audio=False, key=VIDEO_PACKETS_LOST) 140 141 def GetVideoIncomingFramesDecodedList(self): 142 return self._ExtractAllJMIDataPointsWithKey( 143 jmi_type=SSRC, is_audio=False, key=FRAMES_DECODED) 144 145 def GetVideoOutgoingFramesEncodedList(self): 146 return self._ExtractAllJMIDataPointsWithKey( 147 jmi_type=SSRC, is_audio=False, key=FRAMES_ENCODED) 148 149 def GetVideoAdaptationChangeList(self): 150 return self._ExtractAllJMIDataPointsWithKey( 151 jmi_type=SSRC, is_audio=False, key=ADAPTATION_CHANGES) 152 153 def GetVideoEncodeTimeList(self): 154 return self._ExtractAllJMIDataPointsWithKey( 155 jmi_type=SSRC, is_audio=False, key=AVERAGE_ENCODE_TIME) 156 157 def GetBandwidthLimitedResolutionList(self): 158 return self._ExtractAllJMIDataPointsWithKey( 159 jmi_type=SSRC, is_audio=False, key=BANDWIDTH_LIMITED_RESOLUTION) 160 161 def GetVideoReceivedFrameHeightList(self): 162 return self._ExtractAllJMIDataPointsWithKey( 163 jmi_type=SSRC, is_audio=False, key=VIDEO_RECEIVED_FRAME_HEIGHT) 164 165 def GetVideoOutgoingFramerateInputList(self): 166 return self._ExtractAllJMIDataPointsWithKey( 167 jmi_type=SSRC, is_audio=False, key=FRAMERATE_OUTGOING) 168 169 def GetVideoReceivedFrameWidthList(self): 170 return self._ExtractAllJMIDataPointsWithKey( 171 jmi_type=SSRC, is_audio=False, key=VIDEO_RECEIVED_FRAME_WIDTH) 172 173 def GetVideoEncodeCpuUsagePercentList(self): 174 return self._ExtractAllJMIDataPointsWithKey( 175 jmi_type=SSRC, is_audio=False, key=VIDEO_ENCODE_CPU_USAGE) 176 177 def GetNumberOfActiveIncomingVideoStreams(self): 178 """Retrieve number of active incoming video streams.""" 179 if not self._jmi_list: 180 # JMI data hasn't started populating yet. 181 return 0 182 183 num_video_streams = [] 184 185 # If JMI data has started getting populated and has video stream data. 186 for jmi_data_point in self._jmi_list: 187 json_arr = json.loads(jmi_data_point) 188 video_streams = 0 189 for i in range(AV_INDEX, len(json_arr)): 190 if json_arr[i] and SSRC in json_arr[i]: 191 ssrc_obj = json_arr[i][SSRC] 192 is_audio = ('audioInputLevel' in ssrc_obj or 193 'audioOutputLevel' in ssrc_obj) 194 is_incoming = 'bytesReceived' in ssrc_obj 195 frame_rate_received = 'googFrameRateReceived' in ssrc_obj 196 if ssrc_obj['mediaType'] == 'video' and \ 197 frame_rate_received: 198 frame_rate = ssrc_obj['googFrameRateReceived'] 199 if (is_incoming and not is_audio) and \ 200 frame_rate != 0: 201 video_streams += 1 202 num_video_streams.append(video_streams) 203 if not num_video_streams: 204 num_video_streams = [0] 205 return num_video_streams 206 207 def GetCpuUsageList(self, cpu_type): 208 """Retrieves cpu usage data from JMI data. 209 210 @param cpu_type: Cpu usage type. 211 @returns List containing CPU usage data. 212 """ 213 data_list = [] 214 for jmi_data_point in self._jmi_list: 215 json_arr = json.loads(jmi_data_point) 216 for i in range(AV_INDEX, len(json_arr)): 217 if json_arr[i] and GLOBAL in json_arr[i]: 218 global_obj = json_arr[i][GLOBAL] 219 # Some values in JMIDataV3 are set to 'null'. 220 if cpu_type == u'numOfProcessors': 221 return global_obj[cpu_type] 222 elif (cpu_type in global_obj and 223 self.IsFloat(global_obj[cpu_type])): 224 data_list.append(float(global_obj[cpu_type])) 225 if not data_list: 226 data_list = [0] 227 return data_list 228 229 def GetNumOfProcessors(self): 230 return self.GetCpuUsageList(NUM_PROCESSORS) 231 232 def GetTotalCpuPercentage(self): 233 return self.GetCpuUsageList(TOTAL_CPU) 234 235 def GetBrowserCpuPercentage(self): 236 return self.GetCpuUsageList(BROWSER_CPU) 237 238 def GetGpuCpuPercentage(self): 239 return self.GetCpuUsageList(GPU_CPU) 240 241 def GetNaclEffectsCpuPercentage(self): 242 return self.GetCpuUsageList(NACL_EFFECTS_CPU) 243 244 def GetRendererCpuPercentage(self): 245 return self.GetCpuUsageList(RENDERER_CPU) 246 247 def IsFloat(self, value): 248 try: 249 float(value) 250 return True 251 except TypeError: 252 return False 253