19 #include "AudioCodecs/AudioEncoded.h"
23 enum class ContainerType : uint8_t {
36 char header[2] = {
'\r',
'\n'};
67 static uint8_t
checkSum(
const uint8_t *data,
size_t len) {
69 for (
int j = 0; j < len; j++) {
93 void setEncoder(
AudioEncoder *encoder) { p_codec = encoder; }
95 void setOutput(
Print &outStream) {
96 LOGD(
"BinaryContainerEncoder::setOutput");
100 bool begin()
override {
103 bool rc = p_codec->begin();
120 LOGD(
"BinaryContainerEncoder::writeMeta: %d", (
int)len);
122 uint8_t tmp_array[meta.common.len];
123 memcpy(tmp_array, &meta,
sizeof(meta));
124 memcpy(tmp_array +
sizeof(meta), data, len);
125 output(tmp_array, meta.common.len);
130 size_t write(
const void *data,
size_t len) {
131 LOGD(
"BinaryContainerEncoder::write: %d", (
int)len);
134 is_beginning =
false;
136 writeAudio((uint8_t *)data, len);
140 void end() { p_codec->end(); }
142 operator bool() {
return true; };
144 virtual const char *
mime() {
return "audio/binary"; };
147 uint64_t packet_count = 0;
148 bool is_beginning =
true;
154 Print *p_out =
nullptr;
156 void writeAudio(
const uint8_t *data,
size_t len) {
157 LOGD(
"writeAudio: %d", (
int)len);
160 QueueStream<uint8_t> tmp{tmp_buffer};
162 p_codec->setOutput(tmp);
163 p_codec->write(data, len);
166 dh.common.len = tmp.available() +
sizeof(CommonHeader);
167 dh.common.checksum =
checkSum(tmp_buffer.data(), tmp_buffer.available());
168 output((uint8_t *)&dh,
sizeof(dh));
171 output(tmp_buffer.data(), tmp_buffer.available());
176 output((uint8_t *)&cfg,
sizeof(cfg));
179 size_t output(
const uint8_t *data,
size_t len) {
180 if (p_out !=
nullptr) {
181 int written = p_out->write((uint8_t *)data, len);
182 LOGD(
"output: %d -> %d", (
int)len, written);
184 LOGW(
"output not defined");
210 LOGD(
"BinaryContainerDecoder::setOutput")
214 void setMetaCallback(
void (*callback)(uint8_t*,
int,
void*)) {
215 meta_callback = callback;
224 void end() { TRACED(); }
226 size_t write(
const void *data,
size_t len) {
227 LOGD(
"write: %d", (
int)len);
228 uint8_t *data8 = (uint8_t *)data;
229 if (buffer.size() < len) {
231 std::max(
static_cast<int>(DEFAULT_BUFFER_SIZE + header_size),
232 static_cast<int>(len * 4 + header_size)));
235 size_t result = buffer.
writeArray(data8, len);
236 while (parseBuffer())
238 return ignore_write_errors ? len : result;
241 operator bool() {
return true; };
244 this->error_handler = error_handler;
249 ignore_write_errors = flag;
258 bool is_first =
true;
260 const size_t header_size =
sizeof(header);
263 Print *p_out =
nullptr;
264 void (*meta_callback)(uint8_t* data,
int len,
void* ref) =
nullptr;
266 bool ignore_write_errors =
true;
267 void * reference =
nullptr;
274 Str str{(
const char *)buffer.
data()};
275 int start = str.indexOf(
"\r\n");
276 LOGD(
"start: %d", start);
281 if (buffer.
available() - start >
sizeof(header)) {
283 memmove((uint8_t *)&header, buffer.
data() + start,
sizeof(header));
286 if (!isValidHeader()) {
287 LOGW(
"invalid header: %d", header.type);
288 if (error_handler) error_handler(InvalidHeader,
this, reference);
293 if (buffer.
available() - start >= header.len) {
297 result = processData();
299 LOGD(
"not enough data - available %d / req: %d", buffer.
available(),
301 if (error_handler) error_handler(DataMissing,
this, reference);
305 LOGD(
"not enough data for header: %d", buffer.
available());
306 if (error_handler) error_handler(DataMissing,
this, reference);
315 switch (header.type) {
316 case ContainerType::Header: {
318 SimpleContainerConfig config;
319 buffer.
readArray((uint8_t *)&config,
sizeof(config));
321 notifyAudioChange(info);
328 case ContainerType::Audio: {
331 int data_len = header.len - header_size;
333 if (header.checksum == crc) {
335 SingleBuffer<uint8_t> tmp_buffer{data_len * 5};
336 QueueStream<uint8_t> tmp{tmp_buffer};
339 p_codec->write(buffer.
data(), data_len);
342 output(tmp_buffer.data(), tmp_buffer.available());
345 LOGW(
"invalid checksum");
346 if (error_handler) error_handler(InvalidChecksum,
this, reference);
354 case ContainerType::Meta: {
357 int data_len = header.len - header_size;
358 if (meta_callback !=
nullptr) {
359 meta_callback(buffer.
data(), data_len, reference);
368 bool isValidHeader() {
369 switch (header.type) {
370 case ContainerType::Header:
371 return header.checksum == 0;
372 case ContainerType::Audio:
374 case ContainerType::Meta:
375 return header.checksum == 0;
388 size_t output(uint8_t *data,
size_t len) {
389 LOGD(
"output: %d", (
int)len);
390 if (p_out !=
nullptr)
391 p_out->write((uint8_t *)data, len);
393 LOGW(
"output not defined");