1 /* 2 * Copyright (c) 2025 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 #ifndef RING_BUFFER_WRAPPER_H 16 #define RING_BUFFER_WRAPPER_H 17 18 #include <map> 19 #include <set> 20 #include <string> 21 #include <unordered_map> 22 #include <parcel.h> 23 24 #include "audio_buffer_desc.h" 25 #include "audio_errors.h" 26 #include "audio_log.h" 27 #include "securec.h" 28 29 namespace OHOS { 30 namespace AudioStandard { 31 /* If buflength is 0, buffer must be nullptr; 32 conversely, if buffer is nullptr, buflength must be 0. 33 Otherwise, the behavior is undefined. */ 34 struct BasicBufferDesc { 35 uint8_t *buffer = nullptr; 36 size_t bufLength = 0; 37 IsLegalBasicBufferDesc38 bool IsLegal() const 39 { 40 if ((buffer == nullptr) && (bufLength == 0)) { 41 return true; 42 } 43 44 if ((buffer != nullptr) && (bufLength > 0)) { 45 return true; 46 } 47 48 return false; 49 } 50 IsBufferOverlapBasicBufferDesc51 bool IsBufferOverlap(const BasicBufferDesc &inBuffer) const 52 { 53 if ((buffer == nullptr) || (inBuffer.buffer == nullptr)) { 54 return false; 55 } 56 57 if ((buffer >= (inBuffer.buffer + inBuffer.bufLength)) || (inBuffer.buffer >= buffer + bufLength)) { 58 return false; 59 } 60 61 return true; 62 } 63 SeekFromStartBasicBufferDesc64 int32_t SeekFromStart(size_t offset) 65 { 66 if (offset > bufLength) { 67 return ERR_INVALID_PARAM; 68 } 69 70 bufLength -= offset; 71 72 if (bufLength == 0) { 73 buffer = nullptr; 74 } else { 75 buffer += offset; 76 } 77 return SUCCESS; 78 } 79 }; 80 81 /** 82 * Precondition: dataLength must not exceed the total buffer capacity 83 * (sum of all bufLength). 84 * The two memory blocks must not overlap in any part of their address ranges. 85 * If first buffer is null, second is null. 86 * Violation results in undefined behavior. 87 */ 88 struct RingBufferWrapper { 89 static inline constexpr size_t DESC_SIZE = 2; 90 91 std::array<BasicBufferDesc, DESC_SIZE> basicBufferDescs = {}; 92 size_t dataLength = 0; 93 GetBufferSizeRingBufferWrapper94 size_t GetBufferSize() const 95 { 96 size_t size = 0; 97 for (const auto &[buffer, bufLength] : basicBufferDescs) { 98 size += bufLength; 99 } 100 return size; 101 } 102 IsLegalRingBufferWrapper103 bool IsLegal() const 104 { 105 if ((!basicBufferDescs[0].IsLegal()) || (!basicBufferDescs[1].IsLegal())) { 106 return false; 107 } 108 109 if (basicBufferDescs[0].IsBufferOverlap(basicBufferDescs[1])) { 110 return false; 111 } 112 113 if (dataLength > GetBufferSize()) { 114 return false; 115 } 116 117 if ((basicBufferDescs[0].buffer) == nullptr && (basicBufferDescs[1].buffer != nullptr)) { 118 return false; 119 } 120 121 return true; 122 } 123 ResetRingBufferWrapper124 void Reset() 125 { 126 dataLength = 0; 127 for (auto &[buffer, bufLength] : basicBufferDescs) { 128 buffer = nullptr; 129 bufLength = 0; 130 } 131 } 132 SetBuffersValueWithBufLenRingBufferWrapper133 void SetBuffersValueWithBufLen(int8_t ch) const 134 { 135 for (auto &[buffer, bufLength] : basicBufferDescs) { 136 if (buffer != nullptr && bufLength != 0) { 137 memset_s(buffer, bufLength, ch, bufLength); 138 } 139 } 140 } 141 SetBuffersValueWithSpecifyDataLenRingBufferWrapper142 void SetBuffersValueWithSpecifyDataLen(int8_t ch) const 143 { 144 size_t remainSize = dataLength; 145 for (auto &[buffer, bufLength] : basicBufferDescs) { 146 size_t setSize = std::min(remainSize, bufLength); 147 remainSize -= setSize; 148 if (buffer != nullptr && bufLength != 0 && setSize != 0) { 149 auto ret = memset_s(buffer, bufLength, ch, setSize); 150 [[unlikely]] if (ret != EOK) { 151 AUDIO_ERR_LOG("memset err :%{public}d", ret); 152 } 153 } 154 } 155 } 156 SeekFromStartRingBufferWrapper157 int32_t SeekFromStart(size_t offset) 158 { 159 if (offset > GetBufferSize()) { 160 return ERR_INVALID_PARAM; 161 } 162 163 size_t remainSeek = offset; 164 dataLength <= offset ? dataLength = 0 : dataLength -= offset; 165 166 for (auto &basicBuffer : basicBufferDescs) { 167 size_t seekSize = std::min(remainSeek, basicBuffer.bufLength); 168 basicBuffer.SeekFromStart(seekSize); 169 remainSeek -= seekSize; 170 } 171 172 if (basicBufferDescs[0].bufLength == 0) { 173 std::swap(basicBufferDescs[0], basicBufferDescs[1]); 174 } 175 return SUCCESS; 176 } 177 CopyInputBufferValueToCurBufferRingBufferWrapper178 int32_t CopyInputBufferValueToCurBuffer(const RingBufferWrapper &buffer) 179 { 180 if (GetBufferSize() < buffer.dataLength) { 181 return ERR_INVALID_PARAM; 182 } 183 184 RingBufferWrapper dstBuffer(*this); 185 RingBufferWrapper srcBuffer(buffer); 186 dstBuffer.dataLength = buffer.dataLength; 187 188 size_t remainSize = buffer.dataLength; 189 while (remainSize > 0) { 190 auto copySize = std::min({srcBuffer.basicBufferDescs[0].bufLength, dstBuffer.basicBufferDescs[0].bufLength, 191 remainSize}); 192 remainSize -= copySize; 193 194 [[unlikely]] if (copySize == 0) { 195 // This branch should never be executed under any valid conditions. Consider let it crash? 196 AUDIO_ERR_LOG("copySize is 0"); 197 return ERR_INVALID_PARAM; 198 } 199 auto ret = memcpy_s(dstBuffer.basicBufferDescs[0].buffer, dstBuffer.basicBufferDescs[0].bufLength, 200 srcBuffer.basicBufferDescs[0].buffer, copySize); 201 [[unlikely]] if (ret != EOK) { 202 AUDIO_ERR_LOG("memcpy err :%{public}d", ret); 203 } 204 dstBuffer.SeekFromStart(copySize); 205 srcBuffer.SeekFromStart(copySize); 206 } 207 208 dataLength = buffer.dataLength; 209 return SUCCESS; 210 } 211 }; 212 } // namespace AudioStandard 213 } // namespace OHOS 214 #endif // RING_BUFFER_WRAPPER_H 215