#pragma once #include #include #include #include #include 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 }; struct CPPacket { std::vector payload; std::int64_t pts = 0; std::int64_t dts = 0; bool end_of_stream = false; bool flush = false; CPPacket() = default; CPPacket(std::vector 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 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&); 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; }; struct CPCodecContext { const CPCodec* codec = nullptr; void* priv_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 [[nodiscard]] T* priv_as() noexcept { return static_cast(priv_data); } template [[nodiscard]] const T* priv_as() const noexcept { return static_cast(priv_data); } private: std::vector 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 codecs); const CPCodec* cpcodec_find_decoder(CPCodecID id); const CPCodec* cpcodec_find_decoder_by_name(std::string_view name); std::vector 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*); }