• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import java.util.List;
27 
28 /**
29  * Measures Performance.
30  */
31 public class Stats {
32     private static final String TAG = "Stats";
33     private long mInitTimeNs;
34     private long mDeInitTimeNs;
35     private long mStartTimeNs;
36     private ArrayList<Integer> mFrameSizes;
37     /*
38      * Array for holding the wallclock time
39      * for each input buffer available.
40      */
41     private ArrayList<Long> mInputTimer;
42     /*
43      * Array for holding the wallclock time
44      * for each output buffer available.
45      * This is used for determining the decoded
46      * frame intervals.
47      */
48     private ArrayList<Long> mOutputTimer;
49 
Stats()50     public Stats() {
51         mFrameSizes = new ArrayList<>();
52         mInputTimer = new ArrayList<>();
53         mOutputTimer = new ArrayList<>();
54         mInitTimeNs = 0;
55         mDeInitTimeNs = 0;
56     }
57 
getCurTime()58     public long getCurTime() { return System.nanoTime(); }
59 
setInitTime(long initTime)60     public void setInitTime(long initTime) { mInitTimeNs = initTime; }
61 
setDeInitTime(long deInitTime)62     public void setDeInitTime(long deInitTime) { mDeInitTimeNs = deInitTime; }
63 
setStartTime()64     public void setStartTime() { mStartTimeNs = System.nanoTime(); }
65 
addFrameSize(int size)66     public void addFrameSize(int size) { mFrameSizes.add(size); }
67 
addInputTime()68     public void addInputTime() { mInputTimer.add(System.nanoTime()); }
69 
addOutputTime()70     public void addOutputTime() { mOutputTimer.add(System.nanoTime()); }
71 
reset()72     public void reset() {
73         if (mFrameSizes.size() != 0) {
74             mFrameSizes.clear();
75         }
76 
77         if (mInputTimer.size() != 0) {
78             mInputTimer.clear();
79         }
80 
81         if (mOutputTimer.size() != 0) {
82             mOutputTimer.clear();
83         }
84     }
85 
getInitTime()86     public long getInitTime() { return mInitTimeNs; }
87 
getDeInitTime()88     public long getDeInitTime() { return mDeInitTimeNs; }
89 
getStartTime()90     public long getStartTime() { return mStartTimeNs; }
91 
getOutputTimers()92     public List<Long> getOutputTimers() { return mOutputTimer; }
93 
getInputTimers()94     public List<Long> getInputTimers() { return mInputTimer; }
95 
getTimeDiff(long sTime, long eTime)96     public long getTimeDiff(long sTime, long eTime) { return (eTime - sTime); }
97 
getTotalTime()98     public long getTotalTime() {
99         if (mOutputTimer.size() == 0) {
100             return -1;
101         }
102         long lastTime = mOutputTimer.get(mOutputTimer.size() - 1);
103         return lastTime - mStartTimeNs;
104     }
105 
getTotalSize()106     public long getTotalSize() {
107         long totalSize = 0;
108         for (long size : mFrameSizes) {
109             totalSize += size;
110         }
111         return totalSize;
112     }
113 
114     /**
115      * Writes the stats header to a file
116      * <p>
117      * \param statsFile    file where the stats data is to be written
118      **/
writeStatsHeader(String statsFile)119     public boolean writeStatsHeader(String statsFile) throws IOException {
120         File outputFile = new File(statsFile);
121         FileOutputStream out = new FileOutputStream(outputFile, true);
122         if (!outputFile.exists())
123             return false;
124         String statsHeader =
125                 "currentTime, fileName, operation, componentName, NDK/SDK, sync/async, setupTime, "
126                         + "destroyTime, minimumTime, maximumTime, "
127                         + "averageTime, timeToProcess1SecContent, totalBytesProcessedPerSec, "
128                         + "timeToFirstFrame, totalSizeInBytes, totalTime\n";
129         out.write(statsHeader.getBytes());
130         out.close();
131         return true;
132     }
133 
134     /**
135      * Dumps the stats of the operation for a given input media.
136      * <p>
137      * \param inputReference input media
138      * \param operation      describes the operation performed on the input media
139      * (i.e. extract/mux/decode/encode)
140      * \param componentName  name of the codec/muxFormat/mime
141      * \param mode           the operating mode: sync/async.
142      * \param durationUs     is a duration of the input media in microseconds.
143      * \param statsFile      the file where the stats data is to be written.
144      */
dumpStatistics(String inputReference, String operation, String componentName, String mode, long durationUs, String statsFile)145     public void dumpStatistics(String inputReference, String operation, String componentName,
146             String mode, long durationUs, String statsFile) throws IOException {
147         if (mOutputTimer.size() == 0) {
148             Log.e(TAG, "No output produced");
149             return;
150         }
151         long totalTimeTakenNs = getTotalTime();
152         long timeTakenPerSec = (totalTimeTakenNs * 1000000) / durationUs;
153         long timeToFirstFrameNs = mOutputTimer.get(0) - mStartTimeNs;
154         long size = getTotalSize();
155         // get min and max output intervals.
156         long intervalNs;
157         long minTimeTakenNs = Long.MAX_VALUE;
158         long maxTimeTakenNs = 0;
159         long prevIntervalNs = mStartTimeNs;
160         for (int idx = 0; idx < mOutputTimer.size() - 1; idx++) {
161             intervalNs = mOutputTimer.get(idx) - prevIntervalNs;
162             prevIntervalNs = mOutputTimer.get(idx);
163             if (minTimeTakenNs > intervalNs) {
164                 minTimeTakenNs = intervalNs;
165             } else if (maxTimeTakenNs < intervalNs) {
166                 maxTimeTakenNs = intervalNs;
167             }
168         }
169 
170         // Write the stats row data to file
171         String rowData = "";
172         rowData += System.nanoTime() + ", ";
173         rowData += inputReference + ", ";
174         rowData += operation + ", ";
175         rowData += componentName + ", ";
176         rowData += "SDK, ";
177         rowData += mode + ", ";
178         rowData += mInitTimeNs + ", ";
179         rowData += mDeInitTimeNs + ", ";
180         rowData += minTimeTakenNs + ", ";
181         rowData += maxTimeTakenNs + ", ";
182         rowData += totalTimeTakenNs / mOutputTimer.size() + ", ";
183         rowData += timeTakenPerSec + ", ";
184         rowData += (size * 1000000000) / totalTimeTakenNs + ", ";
185         rowData += timeToFirstFrameNs + ", ";
186         rowData += size + ", ";
187         rowData += totalTimeTakenNs + "\n";
188 
189         File outputFile = new File(statsFile);
190         FileOutputStream out = new FileOutputStream(outputFile, true);
191         assert outputFile.exists() : "Failed to open the stats file for writing!";
192         out.write(rowData.getBytes());
193         out.close();
194     }
195 }
196