• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "daudio_ringbuffer.h"
17 
18 #include <cstdint>
19 #include <securec.h>
20 
21 #undef DH_LOG_TAG
22 #define DH_LOG_TAG "DaudioRingBuffer"
23 
24 namespace OHOS {
25 namespace DistributedHardware {
~DaudioRingBuffer()26 DaudioRingBuffer::~DaudioRingBuffer()
27 {
28     if (array_ != nullptr) {
29         delete[] array_;
30         array_ = nullptr;
31     }
32 }
33 
RingBufferInit(uint8_t * & audioData)34 int32_t DaudioRingBuffer::RingBufferInit(uint8_t *&audioData)
35 {
36     array_ = new (std::nothrow) uint8_t[RINGBUFFERLEN] {0};
37     CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_FAILED, "Buffer is malloced failed.");
38     writePos_ = 0;
39     readPos_ = 0;
40     tag_ = 0;
41     audioData = new (std::nothrow) uint8_t[DAUDIO_DATA_SIZE] {0};
42     CHECK_AND_RETURN_RET_LOG(audioData == nullptr, ERR_DH_AUDIO_FAILED, "Audio data is malloced failed.");
43     return DH_SUCCESS;
44 }
45 
GetFullState()46 bool DaudioRingBuffer::GetFullState()
47 {
48     if ((writePos_ == readPos_) && tag_ == 1) {
49         return true;
50     }
51     return false;
52 }
53 
GetEmptyState()54 bool DaudioRingBuffer::GetEmptyState()
55 {
56     if ((writePos_ == readPos_) && tag_ == 0) {
57         return true;
58     }
59     return false;
60 }
61 
RingBufferInsert(uint8_t * data,int32_t len)62 int32_t DaudioRingBuffer::RingBufferInsert(uint8_t *data, int32_t len)
63 {
64     int32_t avaliable = RINGBUFFERLEN - writePos_;
65     if (avaliable < len) {
66         int32_t ret = RingBufferInsertOnce(data, avaliable);
67         CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED,
68             "write first once error. errorcode: %{public}d", ret);
69         ret = RingBufferInsertOnce(data + avaliable, len - avaliable);
70         CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED,
71             "write next once error. errorcode: %{public}d", ret);
72     } else {
73         int32_t ret = RingBufferInsertOnce(data, len);
74         CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED,
75             "write only once error. errorcode: %{public}d", ret);
76     }
77     return DH_SUCCESS;
78 }
79 
RingBufferInsertOnce(uint8_t * data,int32_t len)80 int32_t DaudioRingBuffer::RingBufferInsertOnce(uint8_t *data, int32_t len)
81 {
82     CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_NULLPTR, "buffer is nullptr.");
83     CHECK_AND_RETURN_RET_LOG(data == nullptr, ERR_DH_AUDIO_NULLPTR, "data is nullptr.");
84     if (len < 0) {
85         DHLOGE("len < 0 error.");
86         return ERR_DH_AUDIO_NULLPTR;
87     }
88     if (GetFullState()) {
89         DHLOGE("buffer is full.");
90         return ERR_DH_AUDIO_FAILED;
91     }
92     int32_t avaliable = RINGBUFFERLEN - writePos_;
93     if (avaliable < len) {
94         DHLOGE("buffer is not avaliable. now avaliable: %{public}d.", avaliable);
95         return ERR_DH_AUDIO_FAILED;
96     }
97     if (writePos_ >= RINGBUFFERLEN || len >= RINGBUFFERLEN) {
98         DHLOGE("writePos_ or len is out of range.");
99         return ERR_DH_AUDIO_FAILED;
100     }
101     int32_t ret = memcpy_s(array_ + writePos_, len, data, len);
102     CHECK_AND_RETURN_RET_LOG(ret!= EOK, ERR_DH_AUDIO_FAILED, "memcpy_s error.");
103     writePos_ = (writePos_ + len) % RINGBUFFERLEN;
104     if (writePos_ == readPos_) {
105         tag_ = 1;
106     }
107     return DH_SUCCESS;
108 }
109 
RingBufferGetData(uint8_t * data,int32_t len)110 int32_t DaudioRingBuffer::RingBufferGetData(uint8_t *data, int32_t len)
111 {
112     CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_NULLPTR, "buffer is nullptr.");
113     CHECK_AND_RETURN_RET_LOG(data == nullptr, ERR_DH_AUDIO_NULLPTR, "data is nullptr.");
114     int32_t avaliable = writePos_ - readPos_;
115     if (avaliable >= len) {
116         int32_t ret = RingBufferGetDataOnce(data, len);
117         CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read only once error");
118     } else if (avaliable > 0) {
119         DHLOGI("buffer is not enough. avaliable: %{public}d. len: %{public}d.", avaliable, len);
120         return ERR_DH_AUDIO_FAILED;
121     } else {
122         int32_t firstReadLen = RINGBUFFERLEN - readPos_;
123         if (firstReadLen >= len) {
124             int32_t ret = RingBufferGetDataOnce(data, len);
125             CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read only once error");
126         } else {
127             int32_t ret = RingBufferGetDataOnce(data, firstReadLen);
128             CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read first once error");
129             ret = RingBufferGetDataOnce(data + firstReadLen, len - firstReadLen);
130             CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read next once error");
131         }
132     }
133     return DH_SUCCESS;
134 }
135 
RingBufferGetDataOnce(uint8_t * data,int32_t len)136 int32_t DaudioRingBuffer::RingBufferGetDataOnce(uint8_t *data, int32_t len)
137 {
138     CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_NULLPTR, "buffer is nullptr.");
139     CHECK_AND_RETURN_RET_LOG(data == nullptr, ERR_DH_AUDIO_NULLPTR, "data is nullptr.");
140     if (len < 0) {
141         DHLOGE("len < 0 error.");
142         return ERR_DH_AUDIO_NULLPTR;
143     }
144     int32_t avaliable = writePos_ - readPos_;
145     if (GetEmptyState()) {
146         DHLOGE("buffer is empty.");
147         return ERR_DH_AUDIO_FAILED;
148     }
149     if ((avaliable < len && avaliable > 0) ||
150         (avaliable < 0 && RINGBUFFERLEN - readPos_ + writePos_ < len)) {
151         DHLOGE("buffer is not enough.");
152         return ERR_DH_AUDIO_FAILED;
153     }
154     if (readPos_ >= RINGBUFFERLEN || len >= RINGBUFFERLEN) {
155         DHLOGE("readPos_ or len is out of range.");
156         return ERR_DH_AUDIO_FAILED;
157     }
158     int32_t ret = memcpy_s(data, len, array_ + readPos_, len);
159     CHECK_AND_RETURN_RET_LOG(ret != EOK, ERR_DH_AUDIO_FAILED, "memcpy_s error.");
160     readPos_ = (readPos_ + len) % RINGBUFFERLEN;
161     if (readPos_ == writePos_) {
162         tag_ = 0;
163     }
164     return DH_SUCCESS;
165 }
166 
CanBufferReadLen(int32_t readLen)167 bool DaudioRingBuffer::CanBufferReadLen(int32_t readLen)
168 {
169     if (GetEmptyState()) {
170         DHLOGD("buffer is empty.");
171         return false;
172     }
173     int32_t aval = writePos_ - readPos_;
174     if ((aval < readLen) && (aval > 0)) {
175         DHLOGD("remain : %{public}d, but not enough readLen: %{public}d", aval, readLen);
176         return false;
177     } else if (aval <= 0) {
178         int32_t avalRead = RINGBUFFERLEN - readPos_ + writePos_;
179         if (avalRead < readLen) {
180             DHLOGD("avalRead : %{public}d, but not enough readLen: %{public}d", avalRead, readLen);
181             return false;
182         }
183     }
184     return true;
185 }
186 } // namespace DistributedHardware
187 } // namespace OHOS