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 AUDIO_RING_CACHE_H 17 #define AUDIO_RING_CACHE_H 18 19 #include "stdint.h" 20 #include <atomic> 21 #include <cstddef> 22 #include <memory> 23 #include <mutex> 24 25 namespace OHOS { 26 namespace AudioStandard { 27 // in plan: Using a globally unified buffer description in AudioStandard namesapce. 28 struct BufferWrap { 29 uint8_t *dataPtr = nullptr; 30 size_t dataSize = 0; 31 }; 32 enum RetType : uint32_t { 33 OPERATION_SUCCESS = 0, 34 OPERATION_FAILED, 35 INDEX_OUT_OF_RANGE, 36 DATA_INSUFFICIENT, 37 INVALID_STATUS, 38 INVALID_OPERATION, 39 INVALID_PARAMS, 40 }; 41 struct OptResult { 42 RetType ret = INVALID_OPERATION; 43 size_t size = 0; 44 }; 45 46 /** 47 * AudioRingCache itself is thread safe, but you must be careful when combining calls to GetWriteableSize and Enqueue. 48 * As the actual writable size may have changed when Enqueue is called. In this case, enqueue will return a error, and 49 * you need to handle it. The combination of calling GetReadableSize and Dequeue all also requires handling this issue. 50 */ 51 class AudioRingCache { 52 public: 53 static std::unique_ptr<AudioRingCache> Create(size_t cacheSize); 54 AudioRingCache(size_t cacheSize); 55 ~AudioRingCache(); 56 57 OptResult ReConfig(size_t cacheSize, bool copyRemained = true); 58 59 // This operation will clear the buffer and reset inner read/write index. 60 void ResetBuffer(); 61 62 size_t GetCahceSize(); 63 64 // Get the buffer size that can be written. 0 <= WritableSize <= cacheTotalSize_ 65 OptResult GetWritableSize(); 66 67 // Get the buffer size that can be read. 0 <= ReadableSize <= cacheTotalSize_ 68 OptResult GetReadableSize(); 69 70 // Call GetWritableSize first, than call Enqueue with valid buffer size that <= WritableSize. 71 // Call Enqueue will move write index ahead. 72 OptResult Enqueue(const BufferWrap &buffer); 73 74 // Call GetReadableSize first, than call Dequeue with valid buffer size that <= ReadableSize. 75 // Call Dequeue will move read index ahead, together with inner base index ahead. 76 OptResult Dequeue(const BufferWrap &buffer); 77 78 private: 79 bool Init(); 80 OptResult GetWritableSizeNoLock(); 81 OptResult GetReadableSizeNoLock(); 82 OptResult HandleCrossDequeue(size_t tempReadIndex, size_t readableSize, const BufferWrap &buffer); 83 void ReIndex(); 84 private: 85 std::mutex cacheMutex_; 86 std::unique_ptr<uint8_t[]> basePtr_; 87 size_t cacheTotalSize_ = 0; 88 89 size_t baseIndex_ = 0; 90 size_t writeIndex_ = 0; 91 size_t readIndex_ = 0; 92 }; 93 } // namespace AudioStandard 94 } // namespace OHOS 95 #endif // AUDIO_RING_CACHE_H 96