1 /*
2 * Copyright (C) 2023 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 #include "media/VectorRecorder.h"
18
19 namespace android::media {
20
21 // Convert data to string with level indentation.
22 // No need for a lock as the SimpleLog is thread-safe.
toString(size_t indent) const23 std::string VectorRecorder::toString(size_t indent) const {
24 return mRecordLog.dumpToString(std::string(indent, ' ').c_str(), mMaxLocalLogLine);
25 }
26
27 // Record into local log when it is time.
record(const std::vector<float> & record)28 void VectorRecorder::record(const std::vector<float>& record) {
29 if (record.size() != mVectorSize) return;
30
31 // Protect against concurrent calls to record().
32 std::lock_guard lg(mLock);
33
34 // if it is time, record average data and reset.
35 if (shouldRecordLog_l()) {
36 sumToAverage_l();
37 mRecordLog.log(
38 "mean: %s, min: %s, max %s, calculated %zu samples in %0.4f second(s)",
39 toString(mSum, mDelimiterIdx, mFormatString.c_str()).c_str(),
40 toString(mMin, mDelimiterIdx, mFormatString.c_str()).c_str(),
41 toString(mMax, mDelimiterIdx, mFormatString.c_str()).c_str(),
42 mNumberOfSamples,
43 mNumberOfSecondsSinceFirstSample.count());
44 resetRecord_l();
45 }
46
47 // update stream average.
48 if (mNumberOfSamples++ == 0) {
49 mFirstSampleTimestamp = std::chrono::steady_clock::now();
50 for (size_t i = 0; i < mVectorSize; ++i) {
51 const float value = record[i];
52 mSum[i] += value;
53 mMax[i] = value;
54 mMin[i] = value;
55 }
56 } else {
57 for (size_t i = 0; i < mVectorSize; ++i) {
58 const float value = record[i];
59 mSum[i] += value;
60 mMax[i] = std::max(mMax[i], value);
61 mMin[i] = std::min(mMin[i], value);
62 }
63 }
64 }
65
shouldRecordLog_l()66 bool VectorRecorder::shouldRecordLog_l() {
67 mNumberOfSecondsSinceFirstSample = std::chrono::duration_cast<std::chrono::seconds>(
68 std::chrono::steady_clock::now() - mFirstSampleTimestamp);
69 return mNumberOfSecondsSinceFirstSample >= mRecordThreshold;
70 }
71
resetRecord_l()72 void VectorRecorder::resetRecord_l() {
73 mSum.assign(mVectorSize, 0);
74 mMax.assign(mVectorSize, 0);
75 mMin.assign(mVectorSize, 0);
76 mNumberOfSamples = 0;
77 mNumberOfSecondsSinceFirstSample = std::chrono::seconds(0);
78 }
79
sumToAverage_l()80 void VectorRecorder::sumToAverage_l() {
81 if (mNumberOfSamples == 0) return;
82 const float reciprocal = 1.f / mNumberOfSamples;
83 for (auto& p : mSum) {
84 p *= reciprocal;
85 }
86 }
87
88 } // namespace android::media
89