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