def calculateFrameStatistics(self, traceName): """ For each frame marker event, calculate the sum of the instrumentation data for the intermediate events. This operation will help to highlight frames that are especially resource intensive. @param traceName: Trace for which frame data should be calculated. """ if not traceName in self.analyzer.traces: self.analyzer.fail("Trace not found: %s" % traceName) trace = self.analyzer.traces[traceName] events = TraceOperations.calculateFrameStatistics(self.analyzer.project, trace) self.analyzer.reportInfo("Data for %d frames collected."% len(events))
def calculateFrameStatistics(self, traceName): """ For each frame marker event, calculate the sum of the instrumentation data for the intermediate events. This operation will help to highlight frames that are especially resource intensive. @param traceName: Trace for which frame data should be calculated. """ if not traceName in self.analyzer.traces: self.analyzer.fail("Trace not found: %s" % traceName) trace = self.analyzer.traces[traceName] events = TraceOperations.calculateFrameStatistics( self.analyzer.project, trace) self.analyzer.reportInfo("Data for %d frames collected." % len(events))
def calculateStatistics(self, frameSimilarityFunc = None, timeThreshold = .25, histogramThreshold = .96, frameCountThreshold = 20, monochromaticThreshold = .99): # Reset the list of frames self.frames = [] self.interestingFrames = [] # Combine frame level statistics TraceOperations.calculateFrameStatistics(self.project, self.trace) # Calculate some high level statistics events = [] for event in self.trace.events: func = self.library.functions[event.name] events.append(event) if func.isFrameMarker: frame = Frame() frame.startTime = events[0].time / 1e6 frame.endTime = (events[-1].time + events[-1].duration) / 1e6 frame.events = events frame.renderEvents = [e for e in events if self.library.functions[e.name].isRenderCall] frame.swapEvent = event frame.number = len(self.frames) # Calculate frame duration frame.duration = frame.endTime - frame.startTime if frame.duration < MIN_FRAME_DURATION: # If the frame has an essentially zero duration, the following event should give a proper time reading try: frame.duration = max(self.trace.events[self.trace.events.index(event) + 1].time / 1e6 - frame.startTime, MIN_FRAME_DURATION) except IndexError: frame.duration = MIN_FRAME_DURATION self.frames.append(frame) events = [] # Now prune the list of frames down to frames of special interest lastFrame = None histograms = {} def getFrameHistogram(frame): if not frame.swapEvent in histograms: try: image = player.Instrumentation.loadBuffer(frame.swapEvent) except: return if image: # Calculate a normalized histogram hist = image.histogram() f = 1.0 / (image.size[0] * image.size[1] * len(image.getbands())) hist = [h * f for h in hist] histograms[frame.swapEvent] = hist return histograms.get(frame.swapEvent) task = Task.startTask("choose-frames", "Choosing interesting frames", len(self.frames)) for frame in self.frames: task.step() if lastFrame and len(self.frames) > frameCountThreshold: # If this frame's duration is pretty much the same as the last one, skip it if abs(frame.duration - lastFrame.duration) <= timeThreshold * lastFrame.duration: continue # Get color buffer histograms for both images hist1 = getFrameHistogram(frame) hist2 = getFrameHistogram(lastFrame) if hist1 and hist2: # Calculate the Bhattacharyya distance, i.e. the cosine of the angle # between the two histograms dist = sum([math.sqrt(h2 * h1) for h1, h2 in zip(hist1, hist2)]) # If the distance is close to one, i.e. the frames are nearly identical, # skip this frame. if dist > histogramThreshold: continue # If the frame is mostly just one color, skip it if max(hist1) >= monochromaticThreshold: continue # If we have a similarity function, discard similar frames if frameSimilarityFunc and frameSimilarityFunc(lastFrame, frame): continue # Mark the new frame as interesting self.interestingFrames.append(frame) lastFrame = frame
def calculateStatistics(self, frameSimilarityFunc=None, timeThreshold=.25, histogramThreshold=.96, frameCountThreshold=20, monochromaticThreshold=.99): # Reset the list of frames self.frames = [] self.interestingFrames = [] # Combine frame level statistics TraceOperations.calculateFrameStatistics(self.project, self.trace) # Calculate some high level statistics events = [] for event in self.trace.events: func = self.library.functions[event.name] events.append(event) if func.isFrameMarker: frame = Frame() frame.startTime = events[0].time / 1e6 frame.endTime = (events[-1].time + events[-1].duration) / 1e6 frame.events = events frame.renderEvents = [ e for e in events if self.library.functions[e.name].isRenderCall ] frame.swapEvent = event frame.number = len(self.frames) # Calculate frame duration frame.duration = frame.endTime - frame.startTime if frame.duration < MIN_FRAME_DURATION: # If the frame has an essentially zero duration, the following event should give a proper time reading try: frame.duration = max( self.trace.events[self.trace.events.index(event) + 1].time / 1e6 - frame.startTime, MIN_FRAME_DURATION) except IndexError: frame.duration = MIN_FRAME_DURATION self.frames.append(frame) events = [] # Now prune the list of frames down to frames of special interest lastFrame = None histograms = {} def getFrameHistogram(frame): if not frame.swapEvent in histograms: try: image = player.Instrumentation.loadBuffer(frame.swapEvent) except: return if image: # Calculate a normalized histogram hist = image.histogram() f = 1.0 / (image.size[0] * image.size[1] * len(image.getbands())) hist = [h * f for h in hist] histograms[frame.swapEvent] = hist return histograms.get(frame.swapEvent) task = Task.startTask("choose-frames", "Choosing interesting frames", len(self.frames)) for frame in self.frames: task.step() if lastFrame and len(self.frames) > frameCountThreshold: # If this frame's duration is pretty much the same as the last one, skip it if abs(frame.duration - lastFrame.duration ) <= timeThreshold * lastFrame.duration: continue # Get color buffer histograms for both images hist1 = getFrameHistogram(frame) hist2 = getFrameHistogram(lastFrame) if hist1 and hist2: # Calculate the Bhattacharyya distance, i.e. the cosine of the angle # between the two histograms dist = sum( [math.sqrt(h2 * h1) for h1, h2 in zip(hist1, hist2)]) # If the distance is close to one, i.e. the frames are nearly identical, # skip this frame. if dist > histogramThreshold: continue # If the frame is mostly just one color, skip it if max(hist1) >= monochromaticThreshold: continue # If we have a similarity function, discard similar frames if frameSimilarityFunc and frameSimilarityFunc( lastFrame, frame): continue # Mark the new frame as interesting self.interestingFrames.append(frame) lastFrame = frame