1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.media.benchmark.library; 18 19 import android.util.Log; 20 21 import java.io.File; 22 import java.io.FileDescriptor; 23 import java.io.FileOutputStream; 24 import java.io.IOException; 25 import java.util.ArrayList; 26 27 /** 28 * Measures Performance. 29 */ 30 public class Stats { 31 private static final String TAG = "Stats"; 32 private long mInitTimeNs; 33 private long mDeInitTimeNs; 34 private long mStartTimeNs; 35 private ArrayList<Integer> mFrameSizes; 36 private ArrayList<Long> mInputTimer; 37 private ArrayList<Long> mOutputTimer; 38 Stats()39 public Stats() { 40 mFrameSizes = new ArrayList<>(); 41 mInputTimer = new ArrayList<>(); 42 mOutputTimer = new ArrayList<>(); 43 mInitTimeNs = 0; 44 mDeInitTimeNs = 0; 45 } 46 getCurTime()47 public long getCurTime() { return System.nanoTime(); } 48 setInitTime(long initTime)49 public void setInitTime(long initTime) { mInitTimeNs = initTime; } 50 setDeInitTime(long deInitTime)51 public void setDeInitTime(long deInitTime) { mDeInitTimeNs = deInitTime; } 52 setStartTime()53 public void setStartTime() { mStartTimeNs = System.nanoTime(); } 54 addFrameSize(int size)55 public void addFrameSize(int size) { mFrameSizes.add(size); } 56 addInputTime()57 public void addInputTime() { mInputTimer.add(System.nanoTime()); } 58 addOutputTime()59 public void addOutputTime() { mOutputTimer.add(System.nanoTime()); } 60 reset()61 public void reset() { 62 if (mFrameSizes.size() != 0) { 63 mFrameSizes.clear(); 64 } 65 66 if (mInputTimer.size() != 0) { 67 mInputTimer.clear(); 68 } 69 70 if (mOutputTimer.size() != 0) { 71 mOutputTimer.clear(); 72 } 73 } 74 getInitTime()75 public long getInitTime() { return mInitTimeNs; } 76 getDeInitTime()77 public long getDeInitTime() { return mDeInitTimeNs; } 78 getTimeDiff(long sTime, long eTime)79 public long getTimeDiff(long sTime, long eTime) { return (eTime - sTime); } 80 getTotalTime()81 private long getTotalTime() { 82 if (mOutputTimer.size() == 0) { 83 return -1; 84 } 85 long lastTime = mOutputTimer.get(mOutputTimer.size() - 1); 86 return lastTime - mStartTimeNs; 87 } 88 getTotalSize()89 private long getTotalSize() { 90 long totalSize = 0; 91 for (long size : mFrameSizes) { 92 totalSize += size; 93 } 94 return totalSize; 95 } 96 97 /** 98 * Writes the stats header to a file 99 * <p> 100 * \param statsFile file where the stats data is to be written 101 **/ writeStatsHeader(String statsFile)102 public boolean writeStatsHeader(String statsFile) throws IOException { 103 File outputFile = new File(statsFile); 104 FileOutputStream out = new FileOutputStream(outputFile, true); 105 if (!outputFile.exists()) 106 return false; 107 String statsHeader = 108 "currentTime, fileName, operation, componentName, NDK/SDK, sync/async, setupTime, " 109 + "destroyTime, minimumTime, maximumTime, " 110 + "averageTime, timeToProcess1SecContent, totalBytesProcessedPerSec, " 111 + "timeToFirstFrame, totalSizeInBytes, totalTime\n"; 112 out.write(statsHeader.getBytes()); 113 out.close(); 114 return true; 115 } 116 117 /** 118 * Dumps the stats of the operation for a given input media. 119 * <p> 120 * \param inputReference input media 121 * \param operation describes the operation performed on the input media 122 * (i.e. extract/mux/decode/encode) 123 * \param componentName name of the codec/muxFormat/mime 124 * \param mode the operating mode: sync/async. 125 * \param durationUs is a duration of the input media in microseconds. 126 * \param statsFile the file where the stats data is to be written. 127 */ dumpStatistics(String inputReference, String operation, String componentName, String mode, long durationUs, String statsFile)128 public void dumpStatistics(String inputReference, String operation, String componentName, 129 String mode, long durationUs, String statsFile) throws IOException { 130 if (mOutputTimer.size() == 0) { 131 Log.e(TAG, "No output produced"); 132 return; 133 } 134 long totalTimeTakenNs = getTotalTime(); 135 long timeTakenPerSec = (totalTimeTakenNs * 1000000) / durationUs; 136 long timeToFirstFrameNs = mOutputTimer.get(0) - mStartTimeNs; 137 long size = getTotalSize(); 138 // get min and max output intervals. 139 long intervalNs; 140 long minTimeTakenNs = Long.MAX_VALUE; 141 long maxTimeTakenNs = 0; 142 long prevIntervalNs = mStartTimeNs; 143 for (int idx = 0; idx < mOutputTimer.size() - 1; idx++) { 144 intervalNs = mOutputTimer.get(idx) - prevIntervalNs; 145 prevIntervalNs = mOutputTimer.get(idx); 146 if (minTimeTakenNs > intervalNs) { 147 minTimeTakenNs = intervalNs; 148 } else if (maxTimeTakenNs < intervalNs) { 149 maxTimeTakenNs = intervalNs; 150 } 151 } 152 153 // Write the stats row data to file 154 String rowData = ""; 155 rowData += System.nanoTime() + ", "; 156 rowData += inputReference + ", "; 157 rowData += operation + ", "; 158 rowData += componentName + ", "; 159 rowData += "SDK, "; 160 rowData += mode + ", "; 161 rowData += mInitTimeNs + ", "; 162 rowData += mDeInitTimeNs + ", "; 163 rowData += minTimeTakenNs + ", "; 164 rowData += maxTimeTakenNs + ", "; 165 rowData += totalTimeTakenNs / mOutputTimer.size() + ", "; 166 rowData += timeTakenPerSec + ", "; 167 rowData += (size * 1000000000) / totalTimeTakenNs + ", "; 168 rowData += timeToFirstFrameNs + ", "; 169 rowData += size + ", "; 170 rowData += totalTimeTakenNs + "\n"; 171 172 File outputFile = new File(statsFile); 173 FileOutputStream out = new FileOutputStream(outputFile, true); 174 assert outputFile.exists() : "Failed to open the stats file for writing!"; 175 out.write(rowData.getBytes()); 176 out.close(); 177 } 178 } 179