| # Lint as: python2, python3 |
| # Copyright (c) 2017 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| |
| import json |
| |
| from autotest_lib.server.cros import cfm_jmidata_helper_base |
| from six.moves import range |
| |
| # Start index in the JSON object that contains Audio/Video streams related info. |
| AV_INDEX = 4 |
| |
| SSRC = u'ssrc' |
| GLOBAL = u'global' |
| |
| AUDIO_INPUT = u'audioInputLevel' |
| AUDIO_OUTPUT = u'audioOutputLevel' |
| BYTES_RECEIVED = u'bytesReceived' |
| BYTES_SENT = u'bytesSent' |
| ADAPTATION_CHANGES = u'googAdaptationChanges' |
| AVERAGE_ENCODE_TIME = u'googAvgEncodeMs' |
| BANDWIDTH_LIMITED_RESOLUTION = u'googBandwidthLimitedResolution' |
| CPU_LIMITED_RESOLUTION = u'googCpuLimitedResolution' |
| VIDEO_ENCODE_CPU_USAGE = u'googEncodeUsagePercent' |
| VIDEO_RECEIVED_FRAME_HEIGHT = u'googFrameHeightReceived' |
| VIDEO_RECEIVED_FRAME_WIDTH = u'googFrameWidthReceived' |
| FRAMERATE_OUTGOING = u'googFrameRateInput' |
| FRAMERATE_RECEIVED = u'googFrameRateReceived' |
| FRAMERATE_SENT = u'googFrameRateSent' |
| FRAMERATE_DECODED = u'googFrameRateDecoded' |
| FRAMERATE_OUTPUT = u'googFrameRateOutput' |
| FRAME_WIDTH_SENT = u'googFrameWidthSent' |
| FRAME_HEIGHT_SENT = u'googFrameHeightSent' |
| FRAMES_DECODED = u'framesDecoded' |
| FRAMES_ENCODED = u'framesEncoded' |
| VIDEO_PACKETS_LOST = u'packetsLost' |
| VIDEO_PACKETS_SENT = u'packetsSent' |
| |
| BROWSER_CPU = u'browserCpuUsage' |
| GPU_CPU = u'gpuCpuUsage' |
| NUM_PROCESSORS = u'numOfProcessors' |
| NACL_EFFECTS_CPU = u'pluginCpuUsage' |
| RENDERER_CPU = u'tabCpuUsage' |
| TOTAL_CPU = u'totalCpuUsage' |
| |
| |
| class JMIDataV3Helper(cfm_jmidata_helper_base.JMIDataHelperBase): |
| """Helper class for JMI data v3 parsing. This class helps in extracting |
| relevant JMI data from javascript log. |
| |
| The class takes javascript file as input and extracts jmidata elements from |
| the file that is internally stored as a list. Whenever we need to extract |
| data i.e. audio received bytes we call a method such as |
| getAudioReceivedDataList. This method converts each string element in the |
| internal list to a json object and retrieves the relevant info from it which |
| is then stored and returned as a list. |
| """ |
| |
| def __init__(self, log_file_content): |
| super(JMIDataV3Helper, self).__init__(log_file_content, 'jmidatav3') |
| |
| def _ExtractAllJMIDataPointsWithKey(self, jmi_type, is_audio, key): |
| """Extracts all values from the data points with the given key.""" |
| data_list = [] |
| for jmi_data_point in self._jmi_list: |
| json_arr = json.loads(jmi_data_point) |
| for i in range(AV_INDEX, len(json_arr)): |
| if json_arr[i] and jmi_type in json_arr[i]: |
| jmi_obj = json_arr[i][jmi_type] |
| this_is_audio = (AUDIO_INPUT in jmi_obj or |
| AUDIO_OUTPUT in jmi_obj) |
| if this_is_audio == is_audio and key in jmi_obj: |
| if (not isinstance(jmi_obj[key], int) and |
| (jmi_obj[key] == 'false' or |
| jmi_obj[key] == 'true')): |
| jmi_obj[key] = 1 if jmi_obj[key] == 'true' else 0 |
| data_list.append(jmi_obj[key]) |
| if not data_list: |
| data_list = [0] |
| return data_list |
| |
| def GetAudioReceivedBytesList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=True, key=BYTES_RECEIVED) |
| |
| def GetAudioSentBytesList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=True, key=BYTES_SENT) |
| |
| def GetAudioReceivedEnergyList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=True, key=AUDIO_OUTPUT) |
| |
| def GetAudioSentEnergyList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=True, key=AUDIO_INPUT) |
| |
| def GetVideoSentBytesList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=BYTES_SENT) |
| |
| def GetVideoReceivedBytesList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=BYTES_RECEIVED) |
| |
| def GetVideoIncomingFramerateReceivedList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMERATE_RECEIVED) |
| |
| def GetVideoOutgoingFramerateSentList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMERATE_SENT) |
| |
| def GetVideoIncomingFramerateDecodedList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMERATE_DECODED) |
| |
| def GetVideoIncomingFramerateList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMERATE_OUTPUT) |
| |
| def GetVideoSentFrameWidthList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAME_WIDTH_SENT) |
| |
| def GetVideoSentFrameHeightList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAME_HEIGHT_SENT) |
| |
| def GetCPULimitedResolutionList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=CPU_LIMITED_RESOLUTION) |
| |
| def GetVideoPacketsSentList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=VIDEO_PACKETS_SENT) |
| |
| def GetVideoPacketsLostList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=VIDEO_PACKETS_LOST) |
| |
| def GetVideoIncomingFramesDecodedList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMES_DECODED) |
| |
| def GetVideoOutgoingFramesEncodedList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMES_ENCODED) |
| |
| def GetVideoAdaptationChangeList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=ADAPTATION_CHANGES) |
| |
| def GetVideoEncodeTimeList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=AVERAGE_ENCODE_TIME) |
| |
| def GetBandwidthLimitedResolutionList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=BANDWIDTH_LIMITED_RESOLUTION) |
| |
| def GetVideoReceivedFrameHeightList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=VIDEO_RECEIVED_FRAME_HEIGHT) |
| |
| def GetVideoOutgoingFramerateInputList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=FRAMERATE_OUTGOING) |
| |
| def GetVideoReceivedFrameWidthList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=VIDEO_RECEIVED_FRAME_WIDTH) |
| |
| def GetVideoEncodeCpuUsagePercentList(self): |
| return self._ExtractAllJMIDataPointsWithKey( |
| jmi_type=SSRC, is_audio=False, key=VIDEO_ENCODE_CPU_USAGE) |
| |
| def GetNumberOfActiveIncomingVideoStreams(self): |
| """Retrieve number of active incoming video streams.""" |
| if not self._jmi_list: |
| # JMI data hasn't started populating yet. |
| return 0 |
| |
| num_video_streams = [] |
| |
| # If JMI data has started getting populated and has video stream data. |
| for jmi_data_point in self._jmi_list: |
| json_arr = json.loads(jmi_data_point) |
| video_streams = 0 |
| for i in range(AV_INDEX, len(json_arr)): |
| if json_arr[i] and SSRC in json_arr[i]: |
| ssrc_obj = json_arr[i][SSRC] |
| is_audio = ('audioInputLevel' in ssrc_obj or |
| 'audioOutputLevel' in ssrc_obj) |
| is_incoming = 'bytesReceived' in ssrc_obj |
| frame_rate_received = 'googFrameRateReceived' in ssrc_obj |
| if ssrc_obj['mediaType'] == 'video' and \ |
| frame_rate_received: |
| frame_rate = ssrc_obj['googFrameRateReceived'] |
| if (is_incoming and not is_audio) and \ |
| frame_rate != 0: |
| video_streams += 1 |
| num_video_streams.append(video_streams) |
| if not num_video_streams: |
| num_video_streams = [0] |
| return num_video_streams |
| |
| def GetCpuUsageList(self, cpu_type): |
| """Retrieves cpu usage data from JMI data. |
| |
| @param cpu_type: Cpu usage type. |
| @returns List containing CPU usage data. |
| """ |
| data_list = [] |
| for jmi_data_point in self._jmi_list: |
| json_arr = json.loads(jmi_data_point) |
| for i in range(AV_INDEX, len(json_arr)): |
| if json_arr[i] and GLOBAL in json_arr[i]: |
| global_obj = json_arr[i][GLOBAL] |
| # Some values in JMIDataV3 are set to 'null'. |
| if cpu_type == u'numOfProcessors': |
| return global_obj[cpu_type] |
| elif (cpu_type in global_obj and |
| self.IsFloat(global_obj[cpu_type])): |
| data_list.append(float(global_obj[cpu_type])) |
| if not data_list: |
| data_list = [0] |
| return data_list |
| |
| def GetNumOfProcessors(self): |
| return self.GetCpuUsageList(NUM_PROCESSORS) |
| |
| def GetTotalCpuPercentage(self): |
| return self.GetCpuUsageList(TOTAL_CPU) |
| |
| def GetBrowserCpuPercentage(self): |
| return self.GetCpuUsageList(BROWSER_CPU) |
| |
| def GetGpuCpuPercentage(self): |
| return self.GetCpuUsageList(GPU_CPU) |
| |
| def GetNaclEffectsCpuPercentage(self): |
| return self.GetCpuUsageList(NACL_EFFECTS_CPU) |
| |
| def GetRendererCpuPercentage(self): |
| return self.GetCpuUsageList(RENDERER_CPU) |
| |
| def IsFloat(self, value): |
| try: |
| float(value) |
| return True |
| except TypeError: |
| return False |