feat: add tactile codec
This commit is contained in:
133
components/ffmsep/cpdecoder.hh
Normal file
133
components/ffmsep/cpdecoder.hh
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Simple FFmpeg-inspired serial decoding toolkit.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace ffmsep {
|
||||
|
||||
// Error codes loosely mirroring FFmpeg semantics.
|
||||
inline constexpr int CP_SUCCESS = 0;
|
||||
inline constexpr int CP_ERROR_EOF = -1;
|
||||
inline constexpr int CP_ERROR_EAGAIN = -2;
|
||||
inline constexpr int CP_ERROR_NOT_OPEN = -3;
|
||||
inline constexpr int CP_ERROR_INVALID_STATE = -4;
|
||||
inline constexpr int CP_ERROR_INVALID_ARGUMENT = -5;
|
||||
|
||||
enum class CPMediaType : std::uint8_t {
|
||||
Unknown = 0,
|
||||
Data,
|
||||
Audio,
|
||||
Video
|
||||
};
|
||||
|
||||
enum class CPCodecID : std::uint32_t {
|
||||
Unknown = 0,
|
||||
Tactile = 0x54514354u // 'T','Q','C','T' marker for tactile quick codec.
|
||||
};
|
||||
|
||||
struct CPPacket {
|
||||
std::vector<std::uint8_t> payload;
|
||||
std::int64_t pts = 0;
|
||||
std::int64_t dts = 0;
|
||||
bool end_of_stream = false;
|
||||
bool flush = false;
|
||||
|
||||
CPPacket() = default;
|
||||
CPPacket(std::vector<std::uint8_t> data, std::int64_t pts_value = 0, std::int64_t dts_value = 0) noexcept
|
||||
: payload(std::move(data)), pts(pts_value), dts(dts_value) {}
|
||||
|
||||
[[nodiscard]] bool empty() const noexcept { return payload.empty(); }
|
||||
};
|
||||
|
||||
struct CPFrame {
|
||||
std::vector<std::uint8_t> data;
|
||||
std::int64_t pts = 0;
|
||||
bool key_frame = false;
|
||||
bool valid = false;
|
||||
|
||||
void reset() noexcept {
|
||||
data.clear();
|
||||
pts = 0;
|
||||
key_frame = false;
|
||||
valid = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct CPCodecContext;
|
||||
|
||||
struct CPCodec {
|
||||
using InitFn = int (*)(CPCodecContext*);
|
||||
using CloseFn = void (*)(CPCodecContext*);
|
||||
using SendPacketFn = int (*)(CPCodecContext*, const CPPacket&);
|
||||
using ReceiveFrameFn = int (*)(CPCodecContext*, CPFrame&);
|
||||
|
||||
const char* name = nullptr;
|
||||
const char* long_name = nullptr;
|
||||
CPMediaType type = CPMediaType::Unknown;
|
||||
CPCodecID id = CPCodecID::Unknown;
|
||||
std::size_t priv_data_size = 0;
|
||||
InitFn init = nullptr;
|
||||
CloseFn close = nullptr;
|
||||
SendPacketFn send_packet = nullptr;
|
||||
ReceiveFrameFn receive_frame = nullptr;
|
||||
};
|
||||
|
||||
struct CPCodecContext {
|
||||
const CPCodec* codec = nullptr;
|
||||
void* priv_data = nullptr;
|
||||
CPMediaType codec_type = CPMediaType::Unknown;
|
||||
bool is_open = false;
|
||||
|
||||
void clear() noexcept {
|
||||
codec = nullptr;
|
||||
priv_data = nullptr;
|
||||
codec_type = CPMediaType::Unknown;
|
||||
is_open = false;
|
||||
priv_storage.clear();
|
||||
}
|
||||
|
||||
void* ensure_priv_storage(std::size_t size);
|
||||
void release_priv_storage() noexcept;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] T* priv_as() noexcept {
|
||||
return static_cast<T*>(priv_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] const T* priv_as() const noexcept {
|
||||
return static_cast<const T*>(priv_data);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::uint8_t> priv_storage;
|
||||
|
||||
friend CPCodecContext* cpcodec_alloc_context3(const CPCodec*);
|
||||
friend int cpcodec_open2(CPCodecContext*, const CPCodec*);
|
||||
friend int cpcodec_close(CPCodecContext*);
|
||||
};
|
||||
|
||||
void cpcodec_register(const CPCodec* codec);
|
||||
void cpcodec_register_many(std::initializer_list<const CPCodec*> codecs);
|
||||
const CPCodec* cpcodec_find_decoder(CPCodecID id);
|
||||
const CPCodec* cpcodec_find_decoder_by_name(std::string_view name);
|
||||
std::vector<const CPCodec*> cpcodec_list_codecs();
|
||||
|
||||
CPCodecContext* cpcodec_alloc_context3(const CPCodec* codec);
|
||||
int cpcodec_open2(CPCodecContext* ctx, const CPCodec* codec = nullptr);
|
||||
int cpcodec_close(CPCodecContext* ctx);
|
||||
void cpcodec_free_context(CPCodecContext** ctx);
|
||||
int cpcodec_send_packet(CPCodecContext* ctx, const CPPacket* packet);
|
||||
int cpcodec_receive_frame(CPCodecContext* ctx, CPFrame* frame);
|
||||
|
||||
} // namespace ffmsep
|
||||
Reference in New Issue
Block a user