* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with License.
* You may obtain a copy of License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "audio_buffer_queue.h"
#include <cstring>
#include <hilog/log.h>
#include <unistd.h>
#include "securec.h"
#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0x3200
#define LOG_TAG "AUDIO_BUFFER_QUEUE"
AudioBufferQueue::AudioBufferQueue(size_t size) {
bufferSize = size;
buffer.resize(size);
writePos = 0;
readPos = 0;
availableData = 0;
}
AudioBufferQueue::~AudioBufferQueue() {
buffer.clear();
}
size_t AudioBufferQueue::Write(int fd, size_t bytesToWrite) {
std::lock_guard<std::mutex> lock(mutex);
size_t availableSpace = bufferSize - availableData;
size_t actualWrite = std::min(bytesToWrite, availableSpace);
if (actualWrite == 0) {
return 0;
}
if (writePos + actualWrite > bufferSize) {
size_t firstPart = bufferSize - writePos;
size_t secondPart = actualWrite - firstPart;
ssize_t bytesRead = read(fd, buffer.data() + writePos, firstPart);
if (bytesRead != firstPart) {
OH_LOG_ERROR(LOG_APP, "Read audio data error.");
return 0;
}
bytesRead = read(fd, buffer.data(), secondPart);
if (bytesRead != secondPart) {
OH_LOG_ERROR(LOG_APP, "Read audio data error.");
return 0;
}
writePos = secondPart;
} else {
ssize_t bytesRead = read(fd, buffer.data() + writePos, actualWrite);
if (bytesRead != actualWrite) {
OH_LOG_ERROR(LOG_APP, "Read audio data error.");
return 0;
}
writePos += actualWrite;
}
availableData += actualWrite;
return actualWrite;
}
size_t AudioBufferQueue::Read(void* dest, size_t bytesToRead) {
if (dest == nullptr) {
return 0;
}
std::lock_guard<std::mutex> lock(mutex);
size_t actualRead = std::min(bytesToRead, availableData);
if (actualRead == 0) {
return 0;
}
if (readPos + actualRead > bufferSize) {
size_t firstPart = bufferSize - readPos;
size_t secondPart = actualRead - firstPart;
errno_t ret = memcpy_s(static_cast<uint8_t*>(dest), buffer.size(), buffer.data() + readPos, firstPart);
if (ret != EOK) {
return -1;
}
ret = memcpy_s(static_cast<uint8_t*>(dest) + firstPart, buffer.size(), buffer.data(), secondPart);
if (ret != EOK) {
return -1;
}
readPos = secondPart;
} else {
errno_t ret = memcpy_s(static_cast<uint8_t*>(dest), buffer.size(), buffer.data() + readPos, actualRead);
if (ret != EOK) {
return -1;
}
readPos += actualRead;
}
availableData -= actualRead;
return actualRead;
}
size_t AudioBufferQueue::GetAvailableSpace() const {
return bufferSize - availableData;
}
void AudioBufferQueue::Clear() {
std::lock_guard<std::mutex> lock(mutex);
writePos = 0;
readPos = 0;
availableData = 0;
}
bool AudioBufferQueue::IsFull() const {
return availableData == bufferSize;
}