#ifndef ECLIPT_DEMUXER_H #define ECLIPT_DEMUXER_H #include "Frame.h" #include "Config.h" #include #include #include #include #ifdef __cplusplus extern "C" { #endif #include #include #ifdef __cplusplus } #endif namespace eclipt { enum class MediaType { Video, Audio, Subtitle, Data, Attachment }; struct StreamMetadata { int stream_index = -1; MediaType media_type = MediaType::Video; std::string codec_name; std::string codec_long_name; std::string language; std::string title; int profile = 0; int level = 0; int width = 0; int height = 0; int64_t bitrate = 0; int sample_rate = 0; int channels = 0; std::string channel_layout; int fps_num = 0; int fps_den = 1; int64_t duration = 0; bool is_default = false; bool is_forced = false; }; struct Packet { std::vector data; int stream_index = -1; int64_t pts = AV_NOPTS_VALUE; int64_t dts = AV_NOPTS_VALUE; int64_t duration = 0; int flags = 0; MediaType media_type = MediaType::Video; Packet() = default; bool isKeyframe() const { return flags & AV_PKT_FLAG_KEY; } bool isCorrupt() const { return flags & AV_PKT_FLAG_CORRUPT; } void clear() { data.clear(); stream_index = -1; pts = AV_NOPTS_VALUE; dts = AV_NOPTS_VALUE; duration = 0; flags = 0; } }; class IDemuxer { public: virtual ~IDemuxer() = default; virtual bool open(const std::string& url, const std::string& mime_type = "") = 0; virtual void close() = 0; virtual bool isOpen() const = 0; virtual bool seek(int64_t timestamp_ms, eclipt::SeekDirection dir = eclipt::SeekDirection::Absolute) = 0; virtual bool seekToKeyframe(int64_t timestamp_ms) = 0; virtual bool readPacket(Packet& packet) = 0; virtual int getPacketCount() const = 0; virtual std::vector getStreams() const = 0; virtual const StreamMetadata* getStream(int index) const = 0; virtual const StreamMetadata* getBestVideoStream() const = 0; virtual const StreamMetadata* getBestAudioStream() const = 0; virtual const StreamMetadata* getBestSubtitleStream() const = 0; virtual int64_t getDuration() const = 0; virtual int64_t getStartTime() const = 0; virtual int64_t getBitrate() const = 0; virtual std::string getUrl() const = 0; virtual std::string getFormatName() const = 0; virtual void setPreferredStream(int media_type, int stream_index) = 0; using ReadCallback = std::function; virtual void setReadCallback(ReadCallback callback) = 0; }; class FFmpegDemuxer : public IDemuxer { public: FFmpegDemuxer(); ~FFmpegDemuxer() override; bool open(const std::string& url, const std::string& mime_type = "") override; void close() override; bool isOpen() const override; bool seek(int64_t timestamp_ms, eclipt::SeekDirection dir = eclipt::SeekDirection::Absolute) override; bool seekToKeyframe(int64_t timestamp_ms) override; bool readPacket(Packet& packet) override; int getPacketCount() const override; std::vector getStreams() const override; const StreamMetadata* getStream(int index) const override; const StreamMetadata* getBestVideoStream() const override; const StreamMetadata* getBestAudioStream() const override; const StreamMetadata* getBestSubtitleStream() const override; int64_t getDuration() const override; int64_t getStartTime() const override; int64_t getBitrate() const override; std::string getUrl() const override; std::string getFormatName() const override; void setPreferredStream(int media_type, int stream_index) override; void setReadCallback(ReadCallback callback) override; void* getAVFormatContext() const; private: struct Impl; std::unique_ptr pImpl; }; } #endif