1 /* 2 * Copyright 2017 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 #ifndef NATIVEOBOE_OBOESTREAMCALLBACKPROXY_H 18 #define NATIVEOBOE_OBOESTREAMCALLBACKPROXY_H 19 20 #include <unistd.h> 21 #include <sys/types.h> 22 23 #include "oboe/Oboe.h" 24 25 class DoubleStatistics { 26 public: add(double statistic)27 void add(double statistic) { 28 if (skipCount < kNumberStatisticsToSkip) { 29 skipCount++; 30 } else { 31 if (statistic <= 0.0) return; 32 sum = statistic + sum; 33 count++; 34 minimum = std::min(statistic, minimum.load()); 35 maximum = std::max(statistic, maximum.load()); 36 } 37 } 38 getAverage()39 double getAverage() const { 40 return sum / count; 41 } 42 dump()43 std::string dump() const { 44 if (count == 0) return "?"; 45 char buff[100]; 46 snprintf(buff, sizeof(buff), "%3.1f/%3.1f/%3.1f ms", minimum.load(), getAverage(), maximum.load()); 47 std::string buffAsStr = buff; 48 return buffAsStr; 49 } 50 clear()51 void clear() { 52 skipCount = 0; 53 sum = 0; 54 count = 0; 55 minimum = DBL_MAX; 56 maximum = 0; 57 } 58 59 private: 60 static constexpr double kNumberStatisticsToSkip = 5; // Skip the first 5 frames 61 std::atomic<int> skipCount { 0 }; 62 std::atomic<double> sum { 0 }; 63 std::atomic<int> count { 0 }; 64 std::atomic<double> minimum { DBL_MAX }; 65 std::atomic<double> maximum { 0 }; 66 }; 67 68 class OboeStreamCallbackProxy : public oboe::AudioStreamCallback { 69 public: setCallback(oboe::AudioStreamCallback * callback)70 void setCallback(oboe::AudioStreamCallback *callback) { 71 mCallback = callback; 72 setCallbackCount(0); 73 mStatistics.clear(); 74 } 75 setCallbackReturnStop(bool b)76 static void setCallbackReturnStop(bool b) { 77 mCallbackReturnStop = b; 78 } 79 getCallbackCount()80 int64_t getCallbackCount() { 81 return mCallbackCount; 82 } 83 setCallbackCount(int64_t count)84 void setCallbackCount(int64_t count) { 85 mCallbackCount = count; 86 } 87 getFramesPerCallback()88 int32_t getFramesPerCallback() { 89 return mFramesPerCallback.load(); 90 } 91 92 /** 93 * Called when the stream is ready to process audio. 94 */ 95 oboe::DataCallbackResult onAudioReady( 96 oboe::AudioStream *audioStream, 97 void *audioData, 98 int numFrames) override; 99 100 /** 101 * Specify the amount of artificial workload that will waste CPU cycles 102 * and increase the CPU load. 103 * @param workload typically ranges from 0.0 to 100.0 104 */ setWorkload(double workload)105 void setWorkload(double workload) { 106 mWorkload = std::max(0.0, workload); 107 } 108 getWorkload()109 double getWorkload() const { 110 return mWorkload; 111 } 112 getCpuLoad()113 double getCpuLoad() const { 114 return mCpuLoad; 115 } 116 getCallbackTimeString()117 std::string getCallbackTimeString() const { 118 return mStatistics.dump(); 119 } 120 121 static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC); 122 123 private: 124 static constexpr int32_t kWorkloadScaler = 500; 125 static constexpr double kNsToMsScaler = 0.000001; 126 double mWorkload = 0.0; 127 std::atomic<double> mCpuLoad{0}; 128 int64_t mPreviousCallbackTimeNs = 0; 129 DoubleStatistics mStatistics; 130 131 oboe::AudioStreamCallback *mCallback = nullptr; 132 static bool mCallbackReturnStop; 133 int64_t mCallbackCount = 0; 134 std::atomic<int32_t> mFramesPerCallback{0}; 135 }; 136 137 138 #endif //NATIVEOBOE_OBOESTREAMCALLBACKPROXY_H 139