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