• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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