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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Stats"
19 
20 #include <ctime>
21 #include <iostream>
22 #include <stdint.h>
23 #include <fstream>
24 
25 #include "Stats.h"
26 
27 /**
28  * Dumps the stats of the operation for a given input media.
29  *
30  * \param operation      describes the operation performed on the input media
31  *                       (i.e. extract/mux/decode/encode)
32  * \param inputReference input media
33  * \param durationUs     is a duration of the input media in microseconds.
34  * \param componentName  describes the codecName/muxFormat/mimeType.
35  * \param mode           the operating mode: sync/async.
36  * \param statsFile      the file where the stats data is to be written.
37  */
dumpStatistics(string operation,string inputReference,int64_t durationUs,string componentName,string mode,string statsFile)38 void Stats::dumpStatistics(string operation, string inputReference, int64_t durationUs,
39                            string componentName, string mode, string statsFile) {
40     ALOGV("In %s", __func__);
41     if (!mOutputTimer.size()) {
42         ALOGE("No output produced");
43         return;
44     }
45     nsecs_t totalTimeTakenNs = getTotalTime();
46     nsecs_t timeTakenPerSec = (totalTimeTakenNs * 1000000) / durationUs;
47     nsecs_t timeToFirstFrameNs = *mOutputTimer.begin() - mStartTimeNs;
48     int32_t size = std::accumulate(mFrameSizes.begin(), mFrameSizes.end(), 0);
49     // get min and max output intervals.
50     nsecs_t intervalNs;
51     nsecs_t minTimeTakenNs = INT64_MAX;
52     nsecs_t maxTimeTakenNs = 0;
53     nsecs_t prevIntervalNs = mStartTimeNs;
54     for (int32_t idx = 0; idx < mOutputTimer.size() - 1; idx++) {
55         intervalNs = mOutputTimer.at(idx) - prevIntervalNs;
56         prevIntervalNs = mOutputTimer.at(idx);
57         if (minTimeTakenNs > intervalNs) minTimeTakenNs = intervalNs;
58         else if (maxTimeTakenNs < intervalNs) maxTimeTakenNs = intervalNs;
59     }
60 
61     // Write the stats data to file.
62     int64_t dataSize = size;
63     int64_t bytesPerSec = ((int64_t)dataSize * 1000000000) / totalTimeTakenNs;
64     string rowData = "";
65     rowData.append(to_string(systemTime(CLOCK_MONOTONIC)) + ", ");
66     rowData.append(inputReference + ", ");
67     rowData.append(operation + ", ");
68     rowData.append(componentName + ", ");
69     rowData.append("NDK, ");
70     rowData.append(mode + ", ");
71     rowData.append(to_string(mInitTimeNs) + ", ");
72     rowData.append(to_string(mDeInitTimeNs) + ", ");
73     rowData.append(to_string(minTimeTakenNs) + ", ");
74     rowData.append(to_string(maxTimeTakenNs) + ", ");
75     rowData.append(to_string(totalTimeTakenNs / mOutputTimer.size()) + ", ");
76     rowData.append(to_string(timeTakenPerSec) + ", ");
77     rowData.append(to_string(bytesPerSec) + ", ");
78     rowData.append(to_string(timeToFirstFrameNs) + ", ");
79     rowData.append(to_string(size) + ",");
80     rowData.append(to_string(totalTimeTakenNs) + ",\n");
81 
82     ofstream out(statsFile, ios::out | ios::app);
83     if(out.bad()) {
84         ALOGE("Failed to open stats file for writing!");
85         return;
86     }
87     out << rowData;
88     out.close();
89 }
90