Files
ChargeVideo/src/ChargeVideo.hpp
cat c424ec2c65 Huge update - Fixed memory leak, read description
changed frames to unreference instead of allocate and free on the load frame loop, changed frameConvert to use vCodecCtx data, added reinit and dealt with memory leak from it, adjusted the destructor
2025-10-24 02:09:21 +03:00

174 lines
4.5 KiB
C++

#ifndef CHARGE_VIDEO_BASE_H
#define CHARGE_VIDEO_BASE_H
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <map>
#include <type_traits>
#include <vector>
#include <Corrade/Containers/Array.h>
#include <Magnum/GL/Texture.h>
#include <Magnum/Image.h>
#include <Magnum/ImageView.h>
#include <Magnum/Magnum.h>
#include <Magnum/Timeline.h>
#include <Charge/ChargeAudio.hpp>
namespace ChargeVideo {
namespace _ffmpeg {
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavcodec/codec.h>
#include <libavcodec/packet.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/pixdesc.h>
#include <libavutil/pixfmt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}
} // namespace _ffmpeg
using namespace Corrade;
using namespace Magnum;
using namespace Math::Literals;
// ======================== CLASSES ========================
class Manager {
public:
static void Advance();
static float DeltaTime;
private:
static Timeline time;
static uint16_t videoIDCounter;
static std::unordered_map<uint16_t, std::function<void()>> videoPlayMethods;
static std::vector<uint16_t> toUnhook;
// Specific for internal controls
static uint16_t hookVideo(std::function<void()> videoPlay);
static void unhookVideo(uint16_t ID);
friend class Video;
};
class Video {
public:
// Enums & Flags
enum class State { Playing, Finished, Paused, Idle };
enum class Flags : uint32_t { None = 0, Looping = 1 << 0 };
Video(std::string path, ChargeAudio::Engine *audioEngine = nullptr,
Flags videoFlags = Flags::None, float bufferSizeInSeconds = 1.0f);
~Video();
// Manual Control
void AdvanceToNextFrame();
// Automatic play
void Play();
void Pause();
void SwitchLooping();
void Restart();
// Info
const double GetDuration();
const double GetPlaybackTime();
const Vector2i GetDimensions();
State GetState();
Flags GetFlags();
// Frame and buffer
GL::Texture2D CurrentFrame;
// Audio
ChargeAudio::SoundContainer Sound;
private:
// Contextes
_ffmpeg::AVFormatContext *ctx;
const _ffmpeg::AVCodec *vCodec;
const _ffmpeg::AVCodec *aCodec;
_ffmpeg::AVCodecContext *vCodecCtx, *aCodecCtx;
_ffmpeg::AVStream *videoStream, *audioStream;
struct _ffmpeg::SwsContext *swsCtx = NULL; // Visual
struct _ffmpeg::SwrContext *swrCtx = NULL; // Audio
// State
int8_t videoStreamNum = -1, audioStreamNum = -1;
State videoState;
Flags videoFlags;
uint16_t ID = 0;
// Frames
_ffmpeg::AVFrame *frame = _ffmpeg::av_frame_alloc(),
*convertedFrame = _ffmpeg::av_frame_alloc(),
*audioFrame = _ffmpeg::av_frame_alloc(),
*convertedAudioFrame = _ffmpeg::av_frame_alloc();
_ffmpeg::AVPacket *packet = _ffmpeg::av_packet_alloc();
// Time specific
uint32_t currentFrameNumber = 0;
double timeBase = 0, clock = 0;
// Audio
ChargeAudio::Engine *audioEngine;
// Audio Channel data
_ffmpeg::AVChannelLayout outLayout;
_ffmpeg::AVSampleFormat sampleFormat = _ffmpeg::AV_SAMPLE_FMT_FLT;
// Image Buffering
std::map<double, Image2D> frameBuffer;
uint32_t bufferMaxFrames = 0;
// SAR / Sizing
uint32_t scaleFactor = 1;
Vector2i Dimensions{0, 0};
// Frame handling
bool frameSet = false;
float bufferLenghtInSeconds;
// Methods
void continueVideo();
std::pair<double, Containers::Array<char>> loadNextFrame();
inline void frameDebug(_ffmpeg::AVFrame *frame);
inline void frameSetScaleSAR(_ffmpeg::AVFrame *frame);
inline void frameConvert();
inline void frameFlip(_ffmpeg::AVFrame *frame);
inline void restartVideo();
void dumpAndRefillBuffer();
void loadTexture(Containers::Array<char> data);
void loadTexture(ImageView2D image);
Image2D loadImage(Containers::Array<char> data);
void reinitSound();
};
inline Video::Flags operator|(Video::Flags x, Video::Flags y) {
return static_cast<Video::Flags>(
static_cast<std::underlying_type_t<Video::Flags>>(x) |
static_cast<std::underlying_type_t<Video::Flags>>(y));
}
inline Video::Flags operator&(Video::Flags x, Video::Flags y) {
return static_cast<Video::Flags>(
static_cast<std::underlying_type_t<Video::Flags>>(x) &
static_cast<std::underlying_type_t<Video::Flags>>(y));
}
inline Video::Flags operator^(Video::Flags x, Video::Flags y) {
return static_cast<Video::Flags>(
static_cast<std::underlying_type_t<Video::Flags>>(x) ^
static_cast<std::underlying_type_t<Video::Flags>>(y));
}
} // namespace ChargeVideo
#endif