parent
222c810b07
commit
c36208016e
@ -1,7 +1,7 @@ |
|||||||
idf_component_register( |
idf_component_register( |
||||||
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp" |
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp" |
||||||
"stream_info.cpp" |
"stream_info.cpp" "stream_message.cpp" |
||||||
INCLUDE_DIRS "include" |
INCLUDE_DIRS "include" |
||||||
REQUIRES "codecs" "drivers" "cbor_wrapper" "result" "tasks") |
REQUIRES "codecs" "drivers" "cbor" "result" "tasks") |
||||||
|
|
||||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) |
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) |
||||||
|
@ -1,11 +1,60 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include <functional> |
||||||
|
#include <optional> |
||||||
|
|
||||||
|
#include "cbor.h" |
||||||
|
#include "result.hpp" |
||||||
|
|
||||||
namespace audio { |
namespace audio { |
||||||
|
|
||||||
|
extern const int kEncoderFlags; |
||||||
|
extern const int kDecoderFlags; |
||||||
|
|
||||||
enum MessageType { |
enum MessageType { |
||||||
TYPE_UNKNOWN, |
TYPE_UNKNOWN, |
||||||
TYPE_CHUNK_HEADER, |
TYPE_CHUNK_HEADER, |
||||||
TYPE_STREAM_INFO, |
TYPE_STREAM_INFO, |
||||||
}; |
}; |
||||||
|
|
||||||
|
template <typename Writer> |
||||||
|
auto WriteMessage(MessageType type, |
||||||
|
Writer&& writer, |
||||||
|
uint8_t* buffer, |
||||||
|
size_t length) -> cpp::result<size_t, CborError> { |
||||||
|
CborEncoder root; |
||||||
|
CborEncoder container; |
||||||
|
|
||||||
|
cbor_encoder_init(&root, buffer, length, kEncoderFlags); |
||||||
|
cbor_encoder_create_array(&root, &container, 2); |
||||||
|
cbor_encode_uint(&container, type); |
||||||
|
|
||||||
|
std::optional<CborError> inner_err = std::invoke(writer, container); |
||||||
|
if (inner_err) { |
||||||
|
return cpp::fail(inner_err.value()); |
||||||
|
} |
||||||
|
|
||||||
|
cbor_encoder_close_container(&root, &container); |
||||||
|
return cbor_encoder_get_buffer_size(&root, buffer); |
||||||
|
} |
||||||
|
|
||||||
|
template <typename Result, typename Reader> |
||||||
|
auto ReadMessage(Reader&& reader, uint8_t* buffer, size_t length) |
||||||
|
-> cpp::result<Result, CborError> { |
||||||
|
CborParser parser; |
||||||
|
CborValue root; |
||||||
|
CborValue container; |
||||||
|
|
||||||
|
cbor_parser_init(buffer, length, kDecoderFlags, &parser, &root); |
||||||
|
cbor_value_enter_container(&root, &container); |
||||||
|
// Skip the type header
|
||||||
|
cbor_value_advance_fixed(&container); |
||||||
|
|
||||||
|
return std::invoke(reader, container); |
||||||
|
} |
||||||
|
|
||||||
|
auto ReadMessageType(uint8_t* buffer, size_t length) -> MessageType; |
||||||
|
|
||||||
} // namespace audio
|
} // namespace audio
|
||||||
|
@ -0,0 +1,26 @@ |
|||||||
|
#include "stream_message.hpp" |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
#include "cbor.h" |
||||||
|
|
||||||
|
namespace audio { |
||||||
|
|
||||||
|
const int kEncoderFlags = 0; |
||||||
|
const int kDecoderFlags = 0; |
||||||
|
|
||||||
|
auto ReadMessageType(uint8_t* buffer, size_t length) -> MessageType { |
||||||
|
CborParser parser; |
||||||
|
CborValue root; |
||||||
|
CborValue container; |
||||||
|
|
||||||
|
cbor_parser_init(buffer, length, kDecoderFlags, &parser, &root); |
||||||
|
cbor_value_enter_container(&root, &container); |
||||||
|
|
||||||
|
uint64_t header = 0; |
||||||
|
cbor_value_get_uint64(&container, &header); |
||||||
|
|
||||||
|
return static_cast<MessageType>(header); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace audio
|
@ -1,6 +0,0 @@ |
|||||||
idf_component_register( |
|
||||||
SRCS "cbor_decoder.cpp" "cbor_encoder.cpp" |
|
||||||
INCLUDE_DIRS "include" |
|
||||||
REQUIRES "cbor" "result") |
|
||||||
|
|
||||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) |
|
@ -1,112 +0,0 @@ |
|||||||
#include "cbor_decoder.hpp" |
|
||||||
|
|
||||||
#include <cstdint> |
|
||||||
#include <string> |
|
||||||
|
|
||||||
#include "cbor.h" |
|
||||||
#include "result.hpp" |
|
||||||
|
|
||||||
static const int kDecoderFlags = 0; |
|
||||||
|
|
||||||
namespace cbor { |
|
||||||
|
|
||||||
auto parse_stdstring(const CborValue* val, std::string* out) -> CborError { |
|
||||||
char* buf; |
|
||||||
size_t len; |
|
||||||
CborError err = cbor_value_dup_text_string(val, &buf, &len, NULL); |
|
||||||
if (err != CborNoError) { |
|
||||||
return err; |
|
||||||
} |
|
||||||
*out = std::string(buf, len); |
|
||||||
free(buf); |
|
||||||
return err; |
|
||||||
} |
|
||||||
|
|
||||||
auto ArrayDecoder::Create(uint8_t* buffer, size_t buffer_len) |
|
||||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError> { |
|
||||||
auto decoder = std::make_unique<ArrayDecoder>(); |
|
||||||
cbor_parser_init(buffer, buffer_len, kDecoderFlags, &decoder->parser_, |
|
||||||
&decoder->root_); |
|
||||||
if (!cbor_value_is_array(&decoder->root_)) { |
|
||||||
return cpp::fail(CborErrorIllegalType); |
|
||||||
} |
|
||||||
CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_); |
|
||||||
if (err != CborNoError) { |
|
||||||
return cpp::fail(err); |
|
||||||
} |
|
||||||
return std::move(decoder); |
|
||||||
} |
|
||||||
|
|
||||||
auto ArrayDecoder::Create(CborValue& root) |
|
||||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError> { |
|
||||||
auto decoder = std::make_unique<ArrayDecoder>(); |
|
||||||
decoder->root_ = root; |
|
||||||
if (!cbor_value_is_array(&decoder->root_)) { |
|
||||||
return cpp::fail(CborErrorIllegalType); |
|
||||||
} |
|
||||||
|
|
||||||
CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_); |
|
||||||
if (err != CborNoError) { |
|
||||||
return cpp::fail(err); |
|
||||||
} |
|
||||||
return std::move(decoder); |
|
||||||
} |
|
||||||
|
|
||||||
template <> |
|
||||||
auto ArrayDecoder::NextValue() -> cpp::result<int64_t, CborError> { |
|
||||||
return NextValue(&cbor_value_is_integer, &cbor_value_get_int); |
|
||||||
} |
|
||||||
template <> |
|
||||||
auto ArrayDecoder::NextValue() -> cpp::result<uint64_t, CborError> { |
|
||||||
return NextValue(&cbor_value_is_unsigned_integer, &cbor_value_get_uint64); |
|
||||||
} |
|
||||||
template <> |
|
||||||
auto ArrayDecoder::NextValue() -> cpp::result<std::string, CborError> { |
|
||||||
return NextValue(&cbor_value_is_byte_string, &parse_stdstring); |
|
||||||
} |
|
||||||
|
|
||||||
auto MapDecoder::Create(uint8_t* buffer, size_t buffer_len) |
|
||||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError> { |
|
||||||
auto decoder = std::make_unique<MapDecoder>(); |
|
||||||
cbor_parser_init(buffer, buffer_len, kDecoderFlags, &decoder->parser_, |
|
||||||
&decoder->root_); |
|
||||||
if (!cbor_value_is_map(&decoder->root_)) { |
|
||||||
return cpp::fail(CborErrorIllegalType); |
|
||||||
} |
|
||||||
CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_); |
|
||||||
if (err != CborNoError) { |
|
||||||
return cpp::fail(err); |
|
||||||
} |
|
||||||
return std::move(decoder); |
|
||||||
} |
|
||||||
|
|
||||||
auto MapDecoder::Create(CborValue& root) |
|
||||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError> { |
|
||||||
auto decoder = std::make_unique<MapDecoder>(); |
|
||||||
decoder->root_ = root; |
|
||||||
if (!cbor_value_is_map(&decoder->root_)) { |
|
||||||
return cpp::fail(CborErrorIllegalType); |
|
||||||
} |
|
||||||
CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_); |
|
||||||
if (err != CborNoError) { |
|
||||||
return cpp::fail(err); |
|
||||||
} |
|
||||||
return std::move(decoder); |
|
||||||
} |
|
||||||
|
|
||||||
template <> |
|
||||||
auto MapDecoder::FindValue(const std::string& key) -> std::optional<int64_t> { |
|
||||||
return FindValue(key, &cbor_value_is_integer, &cbor_value_get_int); |
|
||||||
} |
|
||||||
template <> |
|
||||||
auto MapDecoder::FindValue(const std::string& key) -> std::optional<uint64_t> { |
|
||||||
return FindValue(key, &cbor_value_is_unsigned_integer, |
|
||||||
&cbor_value_get_uint64); |
|
||||||
} |
|
||||||
template <> |
|
||||||
auto MapDecoder::FindValue(const std::string& key) |
|
||||||
-> std::optional<std::string> { |
|
||||||
return FindValue(key, &cbor_value_is_byte_string, &parse_stdstring); |
|
||||||
} |
|
||||||
|
|
||||||
} // namespace cbor
|
|
@ -1,63 +0,0 @@ |
|||||||
#include "cbor_encoder.hpp" |
|
||||||
|
|
||||||
#include <cstdint> |
|
||||||
#include <string> |
|
||||||
|
|
||||||
#include "cbor.h" |
|
||||||
#include "cbor_decoder.hpp" |
|
||||||
#include "result.hpp" |
|
||||||
|
|
||||||
namespace cbor { |
|
||||||
|
|
||||||
static const int kEncoderFlags = 0; |
|
||||||
|
|
||||||
Encoder::Encoder(ContainerType type, |
|
||||||
uint32_t container_len, |
|
||||||
uint8_t* buffer, |
|
||||||
size_t buffer_len) { |
|
||||||
cbor_encoder_init(&root_encoder_, buffer, buffer_len, kEncoderFlags); |
|
||||||
switch (type) { |
|
||||||
case CONTAINER_ARRAY: |
|
||||||
error_ = cbor_encoder_create_array(&root_encoder_, &container_encoder_, |
|
||||||
container_len); |
|
||||||
break; |
|
||||||
case CONTAINER_MAP: |
|
||||||
error_ = cbor_encoder_create_map(&root_encoder_, &container_encoder_, |
|
||||||
container_len); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
auto Encoder::WriteValue(const std::string& val) -> void { |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return; |
|
||||||
} |
|
||||||
error_ = |
|
||||||
cbor_encode_text_string(&container_encoder_, val.c_str(), val.size()); |
|
||||||
} |
|
||||||
|
|
||||||
auto Encoder::WriteValue(uint32_t val) -> void { |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return; |
|
||||||
} |
|
||||||
error_ = cbor_encode_uint(&container_encoder_, val); |
|
||||||
} |
|
||||||
|
|
||||||
auto Encoder::WriteValue(int32_t val) -> void { |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return; |
|
||||||
} |
|
||||||
error_ = cbor_encode_int(&container_encoder_, val); |
|
||||||
} |
|
||||||
|
|
||||||
auto Encoder::Finish() -> cpp::result<size_t, CborError> { |
|
||||||
if (error_ == CborNoError) { |
|
||||||
error_ = cbor_encoder_close_container(&root_encoder_, &container_encoder_); |
|
||||||
} |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return cpp::fail(error_); |
|
||||||
} |
|
||||||
return cbor_encoder_get_buffer_size(&root_encoder_, buffer_); |
|
||||||
} |
|
||||||
|
|
||||||
} // namespace cbor
|
|
@ -1,113 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
#include <cstdint> |
|
||||||
#include <string> |
|
||||||
|
|
||||||
#include "cbor.h" |
|
||||||
#include "result.hpp" |
|
||||||
|
|
||||||
namespace cbor { |
|
||||||
|
|
||||||
class ArrayDecoder { |
|
||||||
public: |
|
||||||
static auto Create(uint8_t* buffer, size_t buffer_len) |
|
||||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError>; |
|
||||||
|
|
||||||
static auto Create(CborValue& root) |
|
||||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError>; |
|
||||||
|
|
||||||
ArrayDecoder() {} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
auto NextValue() -> cpp::result<T, CborError>; |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
auto NextValue(bool (*is_valid)(const CborValue*), |
|
||||||
CborError (*parse)(const CborValue*, T*)) |
|
||||||
-> cpp::result<T, CborError> { |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return cpp::fail(error_); |
|
||||||
} |
|
||||||
if (!is_valid(&it_)) { |
|
||||||
error_ = CborErrorIllegalType; |
|
||||||
return cpp::fail(error_); |
|
||||||
} |
|
||||||
T ret; |
|
||||||
error_ = parse(&it_, &ret); |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return cpp::fail(error_); |
|
||||||
} |
|
||||||
error_ = cbor_value_advance(&it_); |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return cpp::fail(error_); |
|
||||||
} |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
auto Failed() -> CborError { return error_; } |
|
||||||
|
|
||||||
auto Iterator() -> CborValue& { return it_; } |
|
||||||
|
|
||||||
ArrayDecoder(const ArrayDecoder&) = delete; |
|
||||||
ArrayDecoder& operator=(const ArrayDecoder&) = delete; |
|
||||||
|
|
||||||
private: |
|
||||||
CborParser parser_; |
|
||||||
CborValue root_; |
|
||||||
|
|
||||||
CborValue it_; |
|
||||||
CborError error_ = CborNoError; |
|
||||||
}; |
|
||||||
|
|
||||||
class MapDecoder { |
|
||||||
public: |
|
||||||
static auto Create(uint8_t* buffer, size_t buffer_len) |
|
||||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError>; |
|
||||||
|
|
||||||
static auto Create(CborValue& root) |
|
||||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError>; |
|
||||||
|
|
||||||
MapDecoder() {} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
auto FindValue(const std::string& key) -> std::optional<T>; |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
auto FindValue(const std::string& key, |
|
||||||
bool (*is_valid)(const CborValue*), |
|
||||||
CborError (*parse)(const CborValue*, T*)) -> std::optional<T> { |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return {}; |
|
||||||
} |
|
||||||
CborValue val; |
|
||||||
if (cbor_value_map_find_value(&it_, key.c_str(), &val) != CborNoError) { |
|
||||||
return {}; |
|
||||||
} |
|
||||||
if (!is_valid(&val)) { |
|
||||||
error_ = CborErrorIllegalType; |
|
||||||
return {}; |
|
||||||
} |
|
||||||
T ret; |
|
||||||
error_ = parse(&val, &ret); |
|
||||||
if (error_ != CborNoError) { |
|
||||||
return {}; |
|
||||||
} |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
auto Failed() -> CborError { return error_; } |
|
||||||
|
|
||||||
MapDecoder(const MapDecoder&) = delete; |
|
||||||
MapDecoder& operator=(const MapDecoder&) = delete; |
|
||||||
|
|
||||||
private: |
|
||||||
CborParser parser_; |
|
||||||
CborValue root_; |
|
||||||
|
|
||||||
CborValue it_; |
|
||||||
CborError error_ = CborNoError; |
|
||||||
}; |
|
||||||
|
|
||||||
} // namespace cbor
|
|
@ -1,52 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <cstdint> |
|
||||||
#include <optional> |
|
||||||
#include <string> |
|
||||||
|
|
||||||
#include "cbor.h" |
|
||||||
#include "result.hpp" |
|
||||||
|
|
||||||
namespace cbor { |
|
||||||
|
|
||||||
enum ContainerType { CONTAINER_ARRAY, CONTAINER_MAP }; |
|
||||||
|
|
||||||
class Encoder { |
|
||||||
public: |
|
||||||
Encoder(ContainerType type, |
|
||||||
uint32_t container_len, |
|
||||||
uint8_t* buffer, |
|
||||||
size_t buffer_len); |
|
||||||
|
|
||||||
auto WriteValue(const std::string& val) -> void; |
|
||||||
auto WriteValue(uint32_t val) -> void; |
|
||||||
auto WriteValue(int32_t val) -> void; |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
auto WriteKeyValue(const std::string& key, const T&& val) -> void { |
|
||||||
WriteValue(key); |
|
||||||
WriteValue(val); |
|
||||||
} |
|
||||||
|
|
||||||
template <typename T> |
|
||||||
auto WriteKeyValue(const std::string& key, const std::optional<T>& val) |
|
||||||
-> void { |
|
||||||
if (val) { |
|
||||||
WriteKeyValue<T>(key, val.value()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
auto Finish() -> cpp::result<size_t, CborError>; |
|
||||||
|
|
||||||
Encoder(const Encoder&) = delete; |
|
||||||
Encoder& operator=(const Encoder&) = delete; |
|
||||||
|
|
||||||
private: |
|
||||||
uint8_t* buffer_; |
|
||||||
CborEncoder root_encoder_; |
|
||||||
CborEncoder container_encoder_; |
|
||||||
|
|
||||||
CborError error_ = CborNoError; |
|
||||||
}; |
|
||||||
|
|
||||||
} // namespace cbor
|
|
Loading…
Reference in new issue