blob: 6dc7868874ec5d61fc5930a879619482a92e387a [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)
Tim Yao10e5d9b2020-12-30 17:38:10 -080025{
26 managed_shared_memory *segment = audio_server_shmem::getInstance();
27 void *shptr = segment->allocate(capacity);
28 handle_ = segment->get_handle_from_address(shptr);
29}
30
31IpcBuffer::~IpcBuffer()
32{
33 managed_shared_memory *segment = audio_server_shmem::getInstance();
34 uint8_t *base = static_cast<uint8_t *>(segment->get_address_from_handle(handle_));
35 segment->deallocate(base);
36}
37
38size_t IpcBuffer::write(const uint8_t *data, size_t bytes)
39{
40 if (bytes == 0) return 0;
41
42 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
43 size_t capacity = capacity_;
44 size_t bytes_to_write = std::min(bytes, capacity - size_);
45
46 if (bytes_to_write <= capacity - end_index_) {
47 memcpy(ptr + end_index_, data, bytes_to_write);
48 end_index_ += bytes_to_write;
49 if (end_index_ == capacity) end_index_ = 0;
50 } else {
51 size_t size_1 = capacity - end_index_;
52 memcpy(ptr + end_index_, data, size_1);
53 size_t size_2 = bytes_to_write - size_1;
54 memcpy(ptr, data + size_1, size_2);
55 end_index_ = size_2;
56 }
57
58 size_ += bytes_to_write;
59 return bytes_to_write;
60}
61
62size_t IpcBuffer::read(uint8_t *data, size_t bytes)
63{
64 if (bytes == 0) return 0;
65
66 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
67 size_t capacity = capacity_;
68 size_t bytes_to_read = std::min(bytes, size_);
69
70 if (bytes_to_read <= capacity - begin_index_) {
71 memcpy(data, ptr + begin_index_, bytes_to_read);
72 begin_index_ += bytes_to_read;
73 if (begin_index_ == capacity) begin_index_ = 0;
74 } else {
75 size_t size_1 = capacity - begin_index_;
76 memcpy(data, ptr + begin_index_, size_1);
77 size_t size_2 = bytes_to_read - size_1;
78 memcpy(data + size_1, ptr, size_2);
79 begin_index_ = size_2;
80 }
81
82 size_ -= bytes_to_read;
83 return bytes_to_read;
84}
85
86void IpcBuffer::write_nb(const uint8_t *data, size_t bytes)
87{
88 if (bytes == 0) return;
89
90 const uint8_t *ptr = data;
91 size_t len = bytes;
92 uint8_t *base = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
93
94 while (len > 0) {
95 size_t bytes_to_write = std::min(capacity_ - end_index_, len);
96 memcpy(base + end_index_, ptr, bytes_to_write);
97 ptr += bytes_to_write;
98 len -= bytes_to_write;
99 end_index_ += bytes_to_write;
100 if (end_index_ == capacity_) end_index_ = 0;
101 }
102
Tim Yao6017d492023-08-07 15:05:53 -0700103 scoped_lock<interprocess_mutex> lock(mutex_);
Tim Yao10e5d9b2020-12-30 17:38:10 -0800104
105 timespec ts;
106 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
107 wr_position_ += bytes;
108 wr_time_ = uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec);
109}
110
111void IpcBuffer::get_write_position(uint64_t& time, uint64_t& position)
112{
Tim Yao6017d492023-08-07 15:05:53 -0700113 scoped_lock<interprocess_mutex> lock(mutex_);
Tim Yao10e5d9b2020-12-30 17:38:10 -0800114 time = wr_time_;
115 position = wr_position_;
116}
117
118uint8_t* IpcBuffer::start_ptr()
119{
120 return static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
121}
122
123const char *IpcBuffer::name()
124{
125 return name_.c_str();
126}
127
128void IpcBuffer::reset()
129{
Tim Yao6017d492023-08-07 15:05:53 -0700130 scoped_lock<interprocess_mutex> lock(mutex_);
Tim Yao10e5d9b2020-12-30 17:38:10 -0800131 begin_index_ = end_index_ = size_ = wr_position_ = 0;
132}
133
Tim Yao6017d492023-08-07 15:05:53 -0700134void IpcBuffer::setMeta(uint64_t meta_64, uint32_t meta_32)
135{
136 scoped_lock<interprocess_mutex> lock(mutex_);
137 clock_gettime(CLOCK_MONOTONIC_RAW, &meta_ts_);
138 meta_64_ = meta_64;
139 meta_32_ = meta_32;
140}
141
142void IpcBuffer::getMeta(struct timespec *meta_ts, uint64_t *meta_64, uint32_t *meta_32)
143{
144 scoped_lock<interprocess_mutex> lock(mutex_);
145 meta_ts->tv_sec = meta_ts_.tv_sec;
146 meta_ts->tv_nsec = meta_ts_.tv_nsec;
147 *meta_64 = meta_64_;
148 *meta_32 = meta_32_;
149}
150
Tim Yao10e5d9b2020-12-30 17:38:10 -0800151managed_shared_memory *audio_server_shmem::shm_;
152
153extern "C" {
154
155void *IpcBuffer_create(const char *name, size_t size)
156{
157 managed_shared_memory *shm = audio_server_shmem::getInstance();
158 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
159 if (cb) {
160 IpcBuffer_destroy(cb);
161 }
162 cb = shm->construct<IpcBuffer>(name)(name, size);
163 return cb;
164}
165
166void IpcBuffer_destroy(void *cb)
167{
168 managed_shared_memory *shm = audio_server_shmem::getInstance();
169 shm->destroy<IpcBuffer>(((IpcBuffer *)(cb))->name());
170}
171
172void IpcBuffer_write(void *cb, const unsigned char *buf, int size)
173{
174 ((IpcBuffer *)(cb))->write_nb(buf, size);
175}
176
Tim Yaoa8aea182021-03-03 21:53:09 -0800177uint8_t *IpcBuffer_get_ptr(const char *name)
178{
179 managed_shared_memory *shm = audio_server_shmem::getInstance();
180 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
181 if (cb) {
182 return cb->start_ptr();
183 }
184 return NULL;
185}
186
187uint64_t IpcBuffer_get_wr_pos(const char *name)
188{
189 managed_shared_memory *shm = audio_server_shmem::getInstance();
190 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
191 if (cb) {
192 uint64_t time, position;
193 cb->get_write_position(time, position);
194 return position;
195 }
196 return 0;
197}
198
Tim Yao6017d492023-08-07 15:05:53 -0700199size_t IpcBuffer_get_capacity(const char *name)
200{
201 managed_shared_memory *shm = audio_server_shmem::getInstance();
202 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
203 if (cb) {
204 return cb->capacity();
205 }
206 return 0;
Tim Yao10e5d9b2020-12-30 17:38:10 -0800207}
208
Tim Yao6017d492023-08-07 15:05:53 -0700209void *IpcBuffer_get_by_name(const char *name)
210{
211 managed_shared_memory *shm = audio_server_shmem::getInstance();
212 return shm->find<IpcBuffer>(name).first;
213}
214
215void IpcBuffer_set_meta_byname(const char *name, uint64_t meta_64, uint32_t meta_32)
216{
217 managed_shared_memory *shm = audio_server_shmem::getInstance();
218 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
219 if (cb) {
220 cb->setMeta(meta_64, meta_32);
221 }
222}
223
224void IpcBuffer_inc_underrun_byname(const char *name)
225{
226 managed_shared_memory *shm = audio_server_shmem::getInstance();
227 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
228 if (cb) {
229 cb->incUnderrun();
230 }
231}
232
233void IpcBuffer_add_silence_byname(const char *name, size_t size)
234{
235 managed_shared_memory *shm = audio_server_shmem::getInstance();
236 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
237 if (cb) {
238 cb->addSilence(size);
239 }
240}
241
242void IpcBuffer_setMeta_byname(const char *name, uint64_t meta_64, uint32_t meta_32)
243{
244 managed_shared_memory *shm = audio_server_shmem::getInstance();
245 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
246 if (cb) {
247 cb->setMeta(meta_64, meta_32);
248 }
249}
250
251void IpcBuffer_inc_underrun(void *instance)
252{
253 IpcBuffer * cb = (IpcBuffer *)instance;
254 if (cb) {
255 cb->incUnderrun();
256 }
257}
258
259void IpcBuffer_add_silence(void *instance, size_t size)
260{
261 IpcBuffer * cb = (IpcBuffer *)instance;
262 if (cb) {
263 cb->addSilence(size);
264 }
265}
266
267void IpcBuffer_setMeta(void *instance, uint64_t meta_64, uint32_t meta_32)
268{
269 IpcBuffer * cb = (IpcBuffer *)instance;
270 if (cb) {
271 cb->setMeta(meta_64, meta_32);
272 }
273}
274
275
276}