blob: 6bb69d87d16ea7535df8393e88e5da87cf5c5180 [file] [log] [blame]
Tim Yao10e5d9b2020-12-30 17:38:10 -08001#include <algorithm> // for std::min
2#include <iostream>
3#include <cstring>
4
5#include <boost/interprocess/sync/scoped_lock.hpp>
6#include <boost/interprocess/managed_shared_memory.hpp>
7
8#include "audio_server_shmem.h"
9#include "IpcBuffer.h"
10#include "IpcBuffer_c.h"
11
12using namespace boost::interprocess;
13
14IpcBuffer::IpcBuffer(const char *name, size_t capacity)
15 : begin_index_(0)
16 , end_index_(0)
17 , size_(0)
18 , capacity_(capacity)
19 , name_(std::string(name))
20 , wr_position_(0)
zhaopeng.yan826c7772022-08-22 15:53:12 +080021 , blocking_(false)
22 , wr_time_(0)
Tim Yao6017d492023-08-07 15:05:53 -070023 , underrun_(0)
24 , silence_inserted_(0)
yuliang.hu3e3ab242024-07-29 14:52:31 +080025 ,meta_64_(0)
26 ,meta_32_(0)
Tim Yao10e5d9b2020-12-30 17:38:10 -080027{
28 managed_shared_memory *segment = audio_server_shmem::getInstance();
29 void *shptr = segment->allocate(capacity);
30 handle_ = segment->get_handle_from_address(shptr);
yuliang.hu3e3ab242024-07-29 14:52:31 +080031 std::memset(&meta_ts_, 0, sizeof(meta_ts_));
Tim Yao10e5d9b2020-12-30 17:38:10 -080032}
33
yuliang.hu3e3ab242024-07-29 14:52:31 +080034IpcBuffer::~IpcBuffer() noexcept (false)
Tim Yao10e5d9b2020-12-30 17:38:10 -080035{
36 managed_shared_memory *segment = audio_server_shmem::getInstance();
37 uint8_t *base = static_cast<uint8_t *>(segment->get_address_from_handle(handle_));
38 segment->deallocate(base);
39}
40
41size_t IpcBuffer::write(const uint8_t *data, size_t bytes)
42{
43 if (bytes == 0) return 0;
44
45 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
46 size_t capacity = capacity_;
47 size_t bytes_to_write = std::min(bytes, capacity - size_);
48
49 if (bytes_to_write <= capacity - end_index_) {
50 memcpy(ptr + end_index_, data, bytes_to_write);
51 end_index_ += bytes_to_write;
52 if (end_index_ == capacity) end_index_ = 0;
53 } else {
54 size_t size_1 = capacity - end_index_;
55 memcpy(ptr + end_index_, data, size_1);
56 size_t size_2 = bytes_to_write - size_1;
57 memcpy(ptr, data + size_1, size_2);
58 end_index_ = size_2;
59 }
60
61 size_ += bytes_to_write;
62 return bytes_to_write;
63}
64
65size_t IpcBuffer::read(uint8_t *data, size_t bytes)
66{
67 if (bytes == 0) return 0;
68
69 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
70 size_t capacity = capacity_;
71 size_t bytes_to_read = std::min(bytes, size_);
72
73 if (bytes_to_read <= capacity - begin_index_) {
74 memcpy(data, ptr + begin_index_, bytes_to_read);
75 begin_index_ += bytes_to_read;
76 if (begin_index_ == capacity) begin_index_ = 0;
77 } else {
78 size_t size_1 = capacity - begin_index_;
79 memcpy(data, ptr + begin_index_, size_1);
80 size_t size_2 = bytes_to_read - size_1;
81 memcpy(data + size_1, ptr, size_2);
82 begin_index_ = size_2;
83 }
84
85 size_ -= bytes_to_read;
86 return bytes_to_read;
87}
88
89void IpcBuffer::write_nb(const uint8_t *data, size_t bytes)
90{
91 if (bytes == 0) return;
92
93 const uint8_t *ptr = data;
94 size_t len = bytes;
95 uint8_t *base = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
96
97 while (len > 0) {
98 size_t bytes_to_write = std::min(capacity_ - end_index_, len);
99 memcpy(base + end_index_, ptr, bytes_to_write);
100 ptr += bytes_to_write;
101 len -= bytes_to_write;
102 end_index_ += bytes_to_write;
103 if (end_index_ == capacity_) end_index_ = 0;
104 }
105
Tim Yao6017d492023-08-07 15:05:53 -0700106 scoped_lock<interprocess_mutex> lock(mutex_);
Tim Yao10e5d9b2020-12-30 17:38:10 -0800107
108 timespec ts;
109 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
110 wr_position_ += bytes;
111 wr_time_ = uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec);
112}
113
114void IpcBuffer::get_write_position(uint64_t& time, uint64_t& position)
115{
Tim Yao6017d492023-08-07 15:05:53 -0700116 scoped_lock<interprocess_mutex> lock(mutex_);
Tim Yao10e5d9b2020-12-30 17:38:10 -0800117 time = wr_time_;
118 position = wr_position_;
119}
120
121uint8_t* IpcBuffer::start_ptr()
122{
123 return static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
124}
125
126const char *IpcBuffer::name()
127{
128 return name_.c_str();
129}
130
131void IpcBuffer::reset()
132{
Tim Yao6017d492023-08-07 15:05:53 -0700133 scoped_lock<interprocess_mutex> lock(mutex_);
Tim Yao10e5d9b2020-12-30 17:38:10 -0800134 begin_index_ = end_index_ = size_ = wr_position_ = 0;
135}
136
Tim Yao6017d492023-08-07 15:05:53 -0700137void IpcBuffer::setMeta(uint64_t meta_64, uint32_t meta_32)
138{
139 scoped_lock<interprocess_mutex> lock(mutex_);
140 clock_gettime(CLOCK_MONOTONIC_RAW, &meta_ts_);
141 meta_64_ = meta_64;
142 meta_32_ = meta_32;
143}
144
145void IpcBuffer::getMeta(struct timespec *meta_ts, uint64_t *meta_64, uint32_t *meta_32)
146{
147 scoped_lock<interprocess_mutex> lock(mutex_);
148 meta_ts->tv_sec = meta_ts_.tv_sec;
149 meta_ts->tv_nsec = meta_ts_.tv_nsec;
150 *meta_64 = meta_64_;
151 *meta_32 = meta_32_;
152}
153
Tim Yao10e5d9b2020-12-30 17:38:10 -0800154managed_shared_memory *audio_server_shmem::shm_;
155
156extern "C" {
157
158void *IpcBuffer_create(const char *name, size_t size)
159{
160 managed_shared_memory *shm = audio_server_shmem::getInstance();
161 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
162 if (cb) {
163 IpcBuffer_destroy(cb);
164 }
165 cb = shm->construct<IpcBuffer>(name)(name, size);
166 return cb;
167}
168
169void IpcBuffer_destroy(void *cb)
170{
171 managed_shared_memory *shm = audio_server_shmem::getInstance();
172 shm->destroy<IpcBuffer>(((IpcBuffer *)(cb))->name());
173}
174
175void IpcBuffer_write(void *cb, const unsigned char *buf, int size)
176{
177 ((IpcBuffer *)(cb))->write_nb(buf, size);
178}
179
Tim Yaoa8aea182021-03-03 21:53:09 -0800180uint8_t *IpcBuffer_get_ptr(const char *name)
181{
182 managed_shared_memory *shm = audio_server_shmem::getInstance();
183 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
184 if (cb) {
185 return cb->start_ptr();
186 }
187 return NULL;
188}
189
190uint64_t IpcBuffer_get_wr_pos(const char *name)
191{
192 managed_shared_memory *shm = audio_server_shmem::getInstance();
193 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
194 if (cb) {
195 uint64_t time, position;
196 cb->get_write_position(time, position);
197 return position;
198 }
199 return 0;
200}
201
Tim Yao6017d492023-08-07 15:05:53 -0700202size_t IpcBuffer_get_capacity(const char *name)
203{
204 managed_shared_memory *shm = audio_server_shmem::getInstance();
205 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
206 if (cb) {
207 return cb->capacity();
208 }
209 return 0;
Tim Yao10e5d9b2020-12-30 17:38:10 -0800210}
211
Tim Yao6017d492023-08-07 15:05:53 -0700212void *IpcBuffer_get_by_name(const char *name)
213{
214 managed_shared_memory *shm = audio_server_shmem::getInstance();
215 return shm->find<IpcBuffer>(name).first;
216}
217
218void IpcBuffer_set_meta_byname(const char *name, uint64_t meta_64, uint32_t meta_32)
219{
220 managed_shared_memory *shm = audio_server_shmem::getInstance();
221 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
222 if (cb) {
223 cb->setMeta(meta_64, meta_32);
224 }
225}
226
227void IpcBuffer_inc_underrun_byname(const char *name)
228{
229 managed_shared_memory *shm = audio_server_shmem::getInstance();
230 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
231 if (cb) {
232 cb->incUnderrun();
233 }
234}
235
236void IpcBuffer_add_silence_byname(const char *name, size_t size)
237{
238 managed_shared_memory *shm = audio_server_shmem::getInstance();
239 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
240 if (cb) {
241 cb->addSilence(size);
242 }
243}
244
245void IpcBuffer_setMeta_byname(const char *name, uint64_t meta_64, uint32_t meta_32)
246{
247 managed_shared_memory *shm = audio_server_shmem::getInstance();
248 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
249 if (cb) {
250 cb->setMeta(meta_64, meta_32);
251 }
252}
253
254void IpcBuffer_inc_underrun(void *instance)
255{
256 IpcBuffer * cb = (IpcBuffer *)instance;
257 if (cb) {
258 cb->incUnderrun();
259 }
260}
261
262void IpcBuffer_add_silence(void *instance, size_t size)
263{
264 IpcBuffer * cb = (IpcBuffer *)instance;
265 if (cb) {
266 cb->addSilence(size);
267 }
268}
269
270void IpcBuffer_setMeta(void *instance, uint64_t meta_64, uint32_t meta_32)
271{
272 IpcBuffer * cb = (IpcBuffer *)instance;
273 if (cb) {
274 cb->setMeta(meta_64, meta_32);
275 }
276}
277
278
279}