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 5import json 6 7from autotest_lib.server.cros import cfm_jmidata_helper_base 8 9# Start index in the JSON object that contains Audio/Video streams related info. 10AV_INDEX = 4 11 12SSRC = u'ssrc' 13GLOBAL = u'global' 14 15AUDIO_INPUT = u'audioInputLevel' 16AUDIO_OUTPUT = u'audioOutputLevel' 17BYTES_RECEIVED = u'bytesReceived' 18BYTES_SENT = u'bytesSent' 19ADAPTATION_CHANGES = u'googAdaptationChanges' 20AVERAGE_ENCODE_TIME = u'googAvgEncodeMs' 21BANDWIDTH_LIMITED_RESOLUTION = u'googBandwidthLimitedResolution' 22CPU_LIMITED_RESOLUTION = u'googCpuLimitedResolution' 23VIDEO_ENCODE_CPU_USAGE = u'googEncodeUsagePercent' 24VIDEO_RECEIVED_FRAME_HEIGHT = u'googFrameHeightReceived' 25VIDEO_RECEIVED_FRAME_WIDTH = u'googFrameWidthReceived' 26FRAMERATE_OUTGOING = u'googFrameRateInput' 27FRAMERATE_RECEIVED = u'googFrameRateReceived' 28FRAMERATE_SENT = u'googFrameRateSent' 29FRAMERATE_DECODED = u'googFrameRateDecoded' 30FRAMERATE_OUTPUT = u'googFrameRateOutput' 31FRAME_WIDTH_SENT = u'googFrameWidthSent' 32FRAME_HEIGHT_SENT = u'googFrameHeightSent' 33FRAMES_DECODED = u'framesDecoded' 34FRAMES_ENCODED = u'framesEncoded' 35VIDEO_PACKETS_LOST = u'packetsLost' 36VIDEO_PACKETS_SENT = u'packetsSent' 37 38BROWSER_CPU = u'browserCpuUsage' 39GPU_CPU = u'gpuCpuUsage' 40NUM_PROCESSORS = u'numOfProcessors' 41NACL_EFFECTS_CPU = u'pluginCpuUsage' 42RENDERER_CPU = u'tabCpuUsage' 43TOTAL_CPU = u'totalCpuUsage' 44 45 46class 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 return data_list 78 79 def GetAudioReceivedBytesList(self): 80 return self._ExtractAllJMIDataPointsWithKey( 81 jmi_type=SSRC, is_audio=True, key=BYTES_RECEIVED) 82 83 def GetAudioSentBytesList(self): 84 return self._ExtractAllJMIDataPointsWithKey( 85 jmi_type=SSRC, is_audio=True, key=BYTES_SENT) 86 87 def GetAudioReceivedEnergyList(self): 88 return self._ExtractAllJMIDataPointsWithKey( 89 jmi_type=SSRC, is_audio=True, key=AUDIO_OUTPUT) 90 91 def GetAudioSentEnergyList(self): 92 return self._ExtractAllJMIDataPointsWithKey( 93 jmi_type=SSRC, is_audio=True, key=AUDIO_INPUT) 94 95 def GetVideoSentBytesList(self): 96 return self._ExtractAllJMIDataPointsWithKey( 97 jmi_type=SSRC, is_audio=False, key=BYTES_SENT) 98 99 def GetVideoReceivedBytesList(self): 100 return self._ExtractAllJMIDataPointsWithKey( 101 jmi_type=SSRC, is_audio=False, key=BYTES_RECEIVED) 102 103 def GetVideoIncomingFramerateReceivedList(self): 104 return self._ExtractAllJMIDataPointsWithKey( 105 jmi_type=SSRC, is_audio=False, key=FRAMERATE_RECEIVED) 106 107 def GetVideoOutgoingFramerateSentList(self): 108 return self._ExtractAllJMIDataPointsWithKey( 109 jmi_type=SSRC, is_audio=False, key=FRAMERATE_SENT) 110 111 def GetVideoIncomingFramerateDecodedList(self): 112 return self._ExtractAllJMIDataPointsWithKey( 113 jmi_type=SSRC, is_audio=False, key=FRAMERATE_DECODED) 114 115 def GetVideoIncomingFramerateList(self): 116 return self._ExtractAllJMIDataPointsWithKey( 117 jmi_type=SSRC, is_audio=False, key=FRAMERATE_OUTPUT) 118 119 def GetVideoSentFrameWidthList(self): 120 return self._ExtractAllJMIDataPointsWithKey( 121 jmi_type=SSRC, is_audio=False, key=FRAME_WIDTH_SENT) 122 123 def GetVideoSentFrameHeightList(self): 124 return self._ExtractAllJMIDataPointsWithKey( 125 jmi_type=SSRC, is_audio=False, key=FRAME_HEIGHT_SENT) 126 127 def GetCPULimitedResolutionList(self): 128 return self._ExtractAllJMIDataPointsWithKey( 129 jmi_type=SSRC, is_audio=False, key=CPU_LIMITED_RESOLUTION) 130 131 def GetVideoPacketsSentList(self): 132 return self._ExtractAllJMIDataPointsWithKey( 133 jmi_type=SSRC, is_audio=False, key=VIDEO_PACKETS_SENT) 134 135 def GetVideoPacketsLostList(self): 136 return self._ExtractAllJMIDataPointsWithKey( 137 jmi_type=SSRC, is_audio=False, key=VIDEO_PACKETS_LOST) 138 139 def GetVideoIncomingFramesDecodedList(self): 140 return self._ExtractAllJMIDataPointsWithKey( 141 jmi_type=SSRC, is_audio=False, key=FRAMES_DECODED) 142 143 def GetVideoOutgoingFramesEncodedList(self): 144 return self._ExtractAllJMIDataPointsWithKey( 145 jmi_type=SSRC, is_audio=False, key=FRAMES_ENCODED) 146 147 def GetVideoAdaptationChangeList(self): 148 return self._ExtractAllJMIDataPointsWithKey( 149 jmi_type=SSRC, is_audio=False, key=ADAPTATION_CHANGES) 150 151 def GetVideoEncodeTimeList(self): 152 return self._ExtractAllJMIDataPointsWithKey( 153 jmi_type=SSRC, is_audio=False, key=AVERAGE_ENCODE_TIME) 154 155 def GetBandwidthLimitedResolutionList(self): 156 return self._ExtractAllJMIDataPointsWithKey( 157 jmi_type=SSRC, is_audio=False, key=BANDWIDTH_LIMITED_RESOLUTION) 158 159 def GetVideoReceivedFrameHeightList(self): 160 return self._ExtractAllJMIDataPointsWithKey( 161 jmi_type=SSRC, is_audio=False, key=VIDEO_RECEIVED_FRAME_HEIGHT) 162 163 def GetVideoOutgoingFramerateInputList(self): 164 return self._ExtractAllJMIDataPointsWithKey( 165 jmi_type=SSRC, is_audio=False, key=FRAMERATE_OUTGOING) 166 167 def GetVideoReceivedFrameWidthList(self): 168 return self._ExtractAllJMIDataPointsWithKey( 169 jmi_type=SSRC, is_audio=False, key=VIDEO_RECEIVED_FRAME_WIDTH) 170 171 def GetVideoEncodeCpuUsagePercentList(self): 172 return self._ExtractAllJMIDataPointsWithKey( 173 jmi_type=SSRC, is_audio=False, key=VIDEO_ENCODE_CPU_USAGE) 174 175 def GetNumberOfActiveIncomingVideoStreams(self): 176 """Retrieve number of active incoming video streams.""" 177 if not self._jmi_list: 178 # JMI data hasn't started populating yet. 179 return 0 180 181 num_video_streams = [] 182 183 # If JMI data has started getting populated and has video stream data. 184 for jmi_data_point in self._jmi_list: 185 json_arr = json.loads(jmi_data_point) 186 video_streams = 0 187 for i in range(AV_INDEX, len(json_arr)): 188 if json_arr[i] and SSRC in json_arr[i]: 189 ssrc_obj = json_arr[i][SSRC] 190 is_audio = ('audioInputLevel' in ssrc_obj or 191 'audioOutputLevel' in ssrc_obj) 192 is_incoming = 'bytesReceived' in ssrc_obj 193 frame_rate_received = 'googFrameRateReceived' in ssrc_obj 194 if ssrc_obj['mediaType'] == 'video' and \ 195 frame_rate_received: 196 frame_rate = ssrc_obj['googFrameRateReceived'] 197 if (is_incoming and not is_audio) and \ 198 frame_rate != 0: 199 video_streams += 1 200 num_video_streams.append(video_streams) 201 return num_video_streams 202 203 def GetCpuUsageList(self, cpu_type): 204 """Retrieves cpu usage data from JMI data. 205 206 @param cpu_type: Cpu usage type. 207 @returns List containing CPU usage data. 208 """ 209 data_list = [] 210 for jmi_data_point in self._jmi_list: 211 json_arr = json.loads(jmi_data_point) 212 for i in range(AV_INDEX, len(json_arr)): 213 if json_arr[i] and GLOBAL in json_arr[i]: 214 global_obj = json_arr[i][GLOBAL] 215 # Some values in JMIDataV3 are set to 'null'. 216 if cpu_type == u'numOfProcessors': 217 return global_obj[cpu_type] 218 elif (cpu_type in global_obj and 219 self.IsFloat(global_obj[cpu_type])): 220 data_list.append(float(global_obj[cpu_type])) 221 if not data_list: 222 data_list = [0] 223 return data_list 224 225 def GetNumOfProcessors(self): 226 return self.GetCpuUsageList(NUM_PROCESSORS) 227 228 def GetTotalCpuPercentage(self): 229 return self.GetCpuUsageList(TOTAL_CPU) 230 231 def GetBrowserCpuPercentage(self): 232 return self.GetCpuUsageList(BROWSER_CPU) 233 234 def GetGpuCpuPercentage(self): 235 return self.GetCpuUsageList(GPU_CPU) 236 237 def GetNaclEffectsCpuPercentage(self): 238 return self.GetCpuUsageList(NACL_EFFECTS_CPU) 239 240 def GetRendererCpuPercentage(self): 241 return self.GetCpuUsageList(RENDERER_CPU) 242 243 def IsFloat(self, value): 244 try: 245 float(value) 246 return True 247 except TypeError: 248 return False 249