• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef OH_AUDIO_BUFFER_H
17 #define OH_AUDIO_BUFFER_H
18 
19 #include <atomic>
20 #include <string>
21 #include <type_traits>
22 #include <optional>
23 
24 #include "message_parcel.h"
25 
26 #include "audio_info.h"
27 #include "ring_buffer_wrapper.h"
28 #include "audio_shared_memory.h"
29 #include "futex_tool.h"
30 
31 namespace OHOS {
32 namespace AudioStandard {
33 const size_t BASIC_SYNC_INFO_SIZE = 8; // sizeof(uint32_t) * 2
34 static constexpr int INVALID_BUFFER_FD = -1;
35 static constexpr int INVALID_FD = -1;
36 using OnIndexChange = std::function<bool(void)>;
37 
38 // client or server.
39 enum AudioBufferHolder : uint32_t {
40     // normal stream, Client buffer created when readFromParcel
41     AUDIO_CLIENT = 0,
42     // normal stream, Server buffer shared with Client
43     AUDIO_SERVER_SHARED,
44     // normal stream, Server buffer shared with hdi
45     AUDIO_SERVER_ONLY,
46     // Server buffer shared with hdi and has sync info
47     AUDIO_SERVER_ONLY_WITH_SYNC,
48     // Independent stream
49     AUDIO_SERVER_INDEPENDENT
50 };
51 
52 enum StreamStatus : uint32_t {
53     STREAM_IDEL = 0,
54     STREAM_STARTING,
55     STREAM_RUNNING,
56     STREAM_PAUSING,
57     STREAM_PAUSED,
58     STREAM_STOPPING,
59     STREAM_STOPPED,
60     STREAM_RELEASED,
61     STREAM_STAND_BY,
62     STREAM_INVALID
63 };
64 
65 /**
66  * totalSizeInFrame = spanCount * spanSizeInFrame
67  *
68  * 0 <= write - base < 2 * totalSize
69  * 0 <= read - base < 1 * totalSize
70  * 0 <= write - read < 1 * totalSize
71  */
72 struct BasicBufferInfo {
73     uint32_t totalSizeInFrame;
74     uint32_t byteSizePerFrame;
75 
76     std::atomic<uint32_t> futexObj;
77 
78     std::atomic<StreamStatus> streamStatus;
79 
80     // basic read/write postion
81     std::atomic<uint64_t> basePosInFrame;
82     std::atomic<uint64_t> curWriteFrame;
83     std::atomic<uint64_t> curReadFrame;
84 
85     std::atomic<uint32_t> underrunCount;
86 
87     std::atomic<uint64_t> handlePos;
88     std::atomic<int64_t> handleTime;
89 
90     std::atomic<uint64_t> position;
91     std::atomic<uint64_t> timeStamp;
92 
93     std::atomic<float> streamVolume;
94     std::atomic<float> duckFactor;
95     std::atomic<float> muteFactor;
96     std::atomic<RestoreStatus> restoreStatus = NO_NEED_FOR_RESTORE;
97     std::atomic<bool> isNeedStop = false;
98 
99     RestoreInfo restoreInfo;
100 };
101 static_assert(std::is_standard_layout<BasicBufferInfo>::value == true, "is not standard layout!");
102 static_assert(std::is_trivially_copyable<BasicBufferInfo>::value == true, "is not trivially copyable!");
103 
104 enum SpanStatus : uint32_t {
105     SPAN_IDEL = 0,
106     SPAN_WRITTING,
107     SPAN_WRITE_DONE,
108     SPAN_READING,
109     SPAN_READ_DONE,
110     SPAN_INVALID
111 };
112 
113 // one span represents a collection of audio sampling data for a short period of time
114 struct SpanInfo {
115     std::atomic<SpanStatus> spanStatus;
116     uint64_t offsetInFrame = 0;
117 
118     int64_t writeStartTime;
119     int64_t writeDoneTime;
120 
121     int64_t readStartTime;
122     int64_t readDoneTime;
123 
124     // volume info for each span
125     bool isMute;
126     int32_t volumeStart;
127     int32_t volumeEnd;
128 };
129 
130 class OHAudioBufferBase : public Parcelable {
131 public:
132     friend class OHAudioBuffer;
133 
134     struct InitializationInfo {
135         AudioBufferHolder bufferHolder;
136         uint32_t totalSizeInFrame;
137         uint32_t byteSizePerFrame;
138         int dataFd;
139         int infoFd;
140     };
141 
142     OHAudioBufferBase(AudioBufferHolder bufferHolder, uint32_t totalSizeInFrame, uint32_t byteSizePerFrame);
143 
144     // create OHAudioBufferBase locally or remotely
145     static std::shared_ptr<OHAudioBufferBase> CreateFromLocal(uint32_t totalSizeInFrame,
146         uint32_t byteSizePerFrame);
147     static std::shared_ptr<OHAudioBufferBase> CreateFromRemote(uint32_t totalSizeInFrame,
148         uint32_t byteSizePerFrame, AudioBufferHolder holder, int dataFd, int infoFd = INVALID_BUFFER_FD);
149 
150     // for ipc.
151     static int32_t WriteToParcel(const std::shared_ptr<OHAudioBufferBase> &buffer, MessageParcel &parcel);
152     static std::shared_ptr<OHAudioBufferBase> ReadFromParcel(MessageParcel &parcel);
153 
154     // idl
155     bool Marshalling(Parcel &parcel) const override;
156     static OHAudioBufferBase *Unmarshalling(Parcel &parcel);
157 
158     uint32_t GetSessionId();
159     int32_t SetSessionId(uint32_t sessionId);
160 
161     AudioBufferHolder GetBufferHolder();
162 
163     int32_t GetSizeParameter(uint32_t &totalSizeInFrame, uint32_t &byteSizePerFrame);
164     uint32_t GetTotalSizeInFrame();
165 
166     std::atomic<StreamStatus> *GetStreamStatus();
167 
168     uint32_t GetUnderrunCount();
169 
170     bool SetUnderrunCount(uint32_t count);
171 
172     bool GetHandleInfo(uint64_t &frames, int64_t &nanoTime);
173 
174     void SetHandleInfo(uint64_t frames, int64_t nanoTime);
175 
176     float GetStreamVolume();
177     bool SetStreamVolume(float streamVolume);
178 
179     float GetDuckFactor();
180     bool SetDuckFactor(float duckFactor);
181 
182     float GetMuteFactor();
183     bool SetMuteFactor(float muteFactor);
184 
185     // hdi use one span as one frame
186     uint32_t GetSyncWriteFrame();
187     bool SetSyncWriteFrame(uint32_t writeFrame);
188     uint32_t GetSyncReadFrame();
189     bool SetSyncReadFrame(uint32_t readFrame);
190 
191     int32_t GetWritableDataFrames();
192     int32_t GetReadableDataFrames();
193 
194     int32_t ResetCurReadWritePos(uint64_t readFrame, uint64_t writeFrame, bool wakeFutex = true);
195 
196     uint64_t GetCurWriteFrame();
197     uint64_t GetCurReadFrame();
198     uint64_t GetBasePosInFrame();
199 
200     int32_t SetCurWriteFrame(uint64_t writeFrame, bool wakeFutex = true);
201     int32_t SetCurReadFrame(uint64_t readFrame, bool wakeFutex = true);
202 
203     int32_t GetBufferByOffset(size_t offset, size_t dataLength, RingBufferWrapper &buffer);
204     int32_t TryGetContinuousBufferByOffset(size_t offset, size_t dataLength, BufferDesc &bufferDesc);
205 
206     int32_t GetBufferByFrame(uint64_t beginPosInFrame, uint64_t sizeInFrame, RingBufferWrapper &buffer);
207 
208     int32_t GetOffsetByFrame(uint64_t posInFrame, size_t &offset);
209     int32_t GetOffsetByFrameForWrite(uint64_t writePosInFrame, size_t &offset);
210     int32_t GetOffsetByFrameForRead(uint64_t readPosInFrame, size_t &offset);
211 
212     int32_t GetAllWritableBufferFromPosFrame(uint64_t writePosInFrame, RingBufferWrapper &buffer);
213     int32_t GetAllReadableBufferFromPosFrame(uint64_t readPosInFrame, RingBufferWrapper &buffer);
214 
215     int32_t GetAllWritableBuffer(RingBufferWrapper &buffer);
216     int32_t GetAllReadableBuffer(RingBufferWrapper &buffer);
217 
218     int64_t GetLastWrittenTime();
219     void SetLastWrittenTime(int64_t time);
220 
221     std::atomic<uint32_t> *GetFutex();
222     uint8_t *GetDataBase();
223     size_t GetDataSize();
224     RestoreStatus CheckRestoreStatus();
225     RestoreStatus SetRestoreStatus(RestoreStatus restoreStatus);
226     void GetRestoreInfo(RestoreInfo &restoreInfo);
227     void SetRestoreInfo(RestoreInfo restoreInfo);
228 
229     void GetTimeStampInfo(uint64_t &position, uint64_t &timeStamp);
230     void SetTimeStampInfo(uint64_t position, uint64_t timeStamp);
231 
232     void SetStopFlag(bool isNeedStop);
233     bool GetStopFlag() const;
234 
235     FutexCode WaitFor(int64_t timeoutInNs, const OnIndexChange &pred);
236 
237     void WakeFutex(uint32_t wakeVal = IS_READY);
238 
239     RestoreStatus GetRestoreStatus();
240 private:
241     int32_t SizeCheck();
242 
243     int32_t Init(int dataFd, int infoFd, size_t statusInfoExtSize);
244 
245     void* GetStatusInfoExtPtr();
246 
247     InitializationInfo GetInitializationInfo();
248 
249     void InitBasicBufferInfo();
250 
251     void WakeFutexIfNeed(uint32_t wakeVal = IS_READY);
252 
253     uint32_t sessionId_ = 0;
254 
255     AudioBufferHolder bufferHolder_;
256 
257     uint32_t totalSizeInFrame_;
258     uint32_t byteSizePerFrame_;
259 
260     // available only in single process
261     int64_t lastWrittenTime_ = 0;
262 
263     // calculated in advance
264     size_t totalSizeInByte_ = 0;
265 
266     // for render or capturer
267     AudioMode audioMode_;
268 
269      // for StatusInfo buffer
270     mutable std::shared_ptr<AudioSharedMemory> statusInfoMem_ = nullptr;
271     BasicBufferInfo *basicBufferInfo_ = nullptr;
272 
273     // for audio data buffer
274     mutable std::shared_ptr<AudioSharedMemory> dataMem_ = nullptr;
275     uint8_t *dataBase_ = nullptr;
276     volatile uint32_t *syncReadFrame_ = nullptr;
277     volatile uint32_t *syncWriteFrame_ = nullptr;
278 };
279 
280 class OHAudioBuffer : public Parcelable {
281 public:
282     OHAudioBuffer(AudioBufferHolder bufferHolder, uint32_t totalSizeInFrame, uint32_t spanSizeInFrame,
283         uint32_t byteSizePerFrame);
284     ~OHAudioBuffer();
285 
286     // create OHAudioBuffer locally or remotely
287     static std::shared_ptr<OHAudioBuffer> CreateFromLocal(uint32_t totalSizeInFrame, uint32_t spanSizeInFrame,
288         uint32_t byteSizePerFrame);
289     static std::shared_ptr<OHAudioBuffer> CreateFromRemote(uint32_t totalSizeInFrame, uint32_t spanSizeInFrame,
290         uint32_t byteSizePerFrame, AudioBufferHolder holder, int dataFd, int infoFd = INVALID_BUFFER_FD);
291 
292     // for ipc.
293     static int32_t WriteToParcel(const std::shared_ptr<OHAudioBuffer> &buffer, MessageParcel &parcel);
294     static std::shared_ptr<OHAudioBuffer> ReadFromParcel(MessageParcel &parcel);
295 
296     // idl
297     bool Marshalling(Parcel &parcel) const override;
298     static OHAudioBuffer *Unmarshalling(Parcel &parcel);
299 
300     AudioBufferHolder GetBufferHolder();
301 
302     int32_t GetSizeParameter(uint32_t &totalSizeInFrame, uint32_t &spanSizeInFrame, uint32_t &byteSizePerFrame);
303 
304     std::atomic<StreamStatus> *GetStreamStatus();
305 
306     uint32_t GetUnderrunCount();
307 
308     bool SetUnderrunCount(uint32_t count);
309 
310     bool GetHandleInfo(uint64_t &frames, int64_t &nanoTime);
311 
312     void SetHandleInfo(uint64_t frames, int64_t nanoTime);
313 
314     float GetStreamVolume();
315     bool SetStreamVolume(float streamVolume);
316 
317     float GetDuckFactor();
318     bool SetDuckFactor(float duckFactor);
319 
320     float GetMuteFactor();
321     bool SetMuteFactor(float muteFactor);
322 
323     int32_t GetWritableDataFrames();
324 
325     int32_t ResetCurReadWritePos(uint64_t readFrame, uint64_t writeFrame, bool wakeFutex = true);
326 
327     uint64_t GetCurWriteFrame();
328     uint64_t GetCurReadFrame();
329 
330     int32_t SetCurWriteFrame(uint64_t writeFrame, bool wakeFutex = true);
331     int32_t SetCurReadFrame(uint64_t readFrame, bool wakeFutex = true);
332 
333     uint32_t GetSessionId();
334     int32_t SetSessionId(uint32_t sessionId);
335 
336     int32_t GetWriteBuffer(uint64_t writePosInFrame, BufferDesc &bufferDesc);
337 
338     int32_t GetReadbuffer(uint64_t readPosInFrame, BufferDesc &bufferDesc);
339 
340     SpanInfo *GetSpanInfo(uint64_t posInFrame);
341     SpanInfo *GetSpanInfoByIndex(uint32_t spanIndex);
342 
343     uint32_t GetSpanCount();
344 
345     int64_t GetLastWrittenTime();
346     void SetLastWrittenTime(int64_t time);
347 
348     // hdi use one span as one frame
349     uint32_t GetSyncWriteFrame();
350     bool SetSyncWriteFrame(uint32_t writeFrame);
351     uint32_t GetSyncReadFrame();
352     bool SetSyncReadFrame(uint32_t readFrame);
353 
354     std::atomic<uint32_t> *GetFutex();
355     uint8_t *GetDataBase();
356     size_t GetDataSize();
357     RestoreStatus CheckRestoreStatus();
358     RestoreStatus SetRestoreStatus(RestoreStatus restoreStatus);
359     void GetRestoreInfo(RestoreInfo &restoreInfo);
360     void SetRestoreInfo(RestoreInfo restoreInfo);
361 
362     void GetTimeStampInfo(uint64_t &position, uint64_t &timeStamp);
363     void SetTimeStampInfo(uint64_t position, uint64_t timeStamp);
364 
365     void SetStopFlag(bool isNeedStop);
366     bool GetStopFlag() const;
367 
368     FutexCode WaitFor(int64_t timeoutInNs, const OnIndexChange &pred);
369 
370 private:
371     int32_t Init(int dataFd, int infoFd);
372     int32_t SizeCheck();
373 
374     bool CheckWriteOrReadFrame(uint64_t writeOrReadFrame);
375 
376     mutable OHAudioBufferBase ohAudioBufferBase_;
377 
378     struct SpanBasicInfo {
SpanBasicInfoSpanBasicInfo379         SpanBasicInfo(uint32_t spanSizeInFrame, uint32_t totalSizeInFrame,
380             uint32_t byteSizePerFrame) : spanSizeInFrame_(spanSizeInFrame),
381             spanSizeInByte_(spanSizeInFrame * byteSizePerFrame),
382             spanConut_(spanSizeInFrame == 0 ? 0 : totalSizeInFrame / spanSizeInFrame)
383         {}
384 
385         int32_t SizeCheck(uint32_t totalSizeInFrame) const;
386         uint32_t spanSizeInFrame_;
387         size_t spanSizeInByte_;
388         uint32_t spanConut_;
389     };
390     SpanBasicInfo spanBasicInfo_;
391 
392     SpanInfo *spanInfoList_ = nullptr;
393 };
394 } // namespace AudioStandard
395 } // namespace OHOS
396 #endif // OH_AUDIO_BUFFER_H
397