// Minimal FFmpeg-based video player (video) that decodes into an SDL texture. // Audio for the intro is currently handled outside this class. #pragma once #include #include struct AVFormatContext; struct AVCodecContext; struct SwsContext; struct AVFrame; class VideoPlayer { public: VideoPlayer(); ~VideoPlayer(); // Open video file and attach to SDL_Renderer for texture creation bool open(const std::string& path, SDL_Renderer* renderer); // Decode the first frame immediately so it can be used for fade-in. bool decodeFirstFrame(); // Start time-based playback. void start(); // Update playback using elapsed time in milliseconds. // Returns false if finished or error. bool update(double deltaMs); // Compatibility: advance by one decoded frame. bool update(); // Render video frame fullscreen to the given renderer using provided output size. void render(SDL_Renderer* renderer, int winW, int winH); bool isFinished() const { return m_finished; } bool isTextureReady() const { return m_textureReady; } double getFrameIntervalMs() const { return m_frameIntervalMs; } bool isStarted() const { return m_started; } private: bool decodeOneFrame(); AVFormatContext* m_fmt = nullptr; AVCodecContext* m_dec = nullptr; SwsContext* m_sws = nullptr; AVFrame* m_frame = nullptr; int m_videoStream = -1; double m_frameIntervalMs = 33.333; double m_frameAccumulatorMs = 0.0; bool m_started = false; int m_width = 0, m_height = 0; SDL_Texture* m_texture = nullptr; uint8_t* m_rgbBuffer = nullptr; int m_rgbBufferSize = 0; bool m_textureReady = false; bool m_finished = true; std::string m_path; };