126 lines
3.7 KiB
C++
126 lines
3.7 KiB
C++
#pragma once
|
||
#include <cstdint>
|
||
#include <cstddef>
|
||
#include <future>
|
||
#include <string_view>
|
||
#include <vector>
|
||
#include <initializer_list>
|
||
#include <nlohmann/json.hpp>
|
||
|
||
namespace ffmsep {
|
||
|
||
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 {
|
||
Unknow = 0,
|
||
Data,
|
||
};
|
||
|
||
enum class CPCodecID : std::uint32_t {
|
||
Unknow = 0,
|
||
Tactile = 0x54514354u, // 'T','Q','C','T':触觉传感器协议标识 Tactile Quick Codec Type
|
||
PiezoresistiveB = 0x54514342u // 'T','Q','C','B':压阻B测试协议
|
||
};
|
||
|
||
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();
|
||
key_frame = false;
|
||
valid = false;
|
||
pts = 0;
|
||
}
|
||
};
|
||
|
||
struct CPCodecContext;
|
||
|
||
struct CPCodec {
|
||
using InitFn = int(*)(CPCodecContext*);
|
||
using CloseFn = void(*)(CPCodecContext*);
|
||
using SendPacketFn = int(*)(CPCodecContext*, const CPPacket&);
|
||
using ReceiveFrameFn = int(*)(CPCodecContext*, CPFrame&);
|
||
using PresistFrameFn = int(*)(CPCodecContext*);
|
||
|
||
const char* name = nullptr;
|
||
const char* long_name = nullptr;
|
||
CPMediaType type = CPMediaType::Unknow;
|
||
CPCodecID id = CPCodecID::Unknow;
|
||
std::size_t priv_data_size = 0;
|
||
InitFn init = nullptr;
|
||
CloseFn close = nullptr;
|
||
SendPacketFn send_packet = nullptr;
|
||
ReceiveFrameFn receive_frame = nullptr;
|
||
PresistFrameFn presistend = nullptr;
|
||
};
|
||
|
||
struct CPCodecContext {
|
||
const CPCodec* codec = nullptr;
|
||
void* priv_data = nullptr;
|
||
void* record_data = nullptr;
|
||
CPMediaType codec_type = CPMediaType::Unknow;
|
||
bool is_open = false;
|
||
|
||
void clear() noexcept {
|
||
codec = nullptr;
|
||
priv_data = nullptr;
|
||
codec_type = CPMediaType::Unknow;
|
||
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_context(const CPCodec*);
|
||
friend int cpcodec_open(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_context(const CPCodec* codec);
|
||
int cpcodec_open(CPCodecContext*, const CPCodec*);
|
||
int cpcodec_close(CPCodecContext*);
|
||
void cpcodec_free_context(CPCodecContext **ctx);
|
||
int cpcodec_send_packet(CPCodecContext*, const CPPacket*);
|
||
int cpcodec_receive_frame(CPCodecContext*, CPFrame*);
|
||
}
|