1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2024-12-26 21:17:12 +00:00
OpenMW/extern/osg-ffmpeg-videoplayer/videostate.hpp
elsid 20e3eeddde
Fix libavformat version check
2a68d945cd
added const version of a callback functions but didn't enable them. They were
guarded by a version check:

2a68d945cd/libavformat/version_major.h (L48)

So for anything LIBAVFORMAT_VERSION_MAJOR < 61 they are not enabled therefore
they are enabled for everything >= 61.0.100.

See https://github.com/elsid/openmw/actions/runs/10255993574/job/28374152796 as
example of failure when building with 60.16.100.
2024-08-05 23:52:30 +02:00

214 lines
4.6 KiB
C++

#ifndef VIDEOPLAYER_VIDEOSTATE_H
#define VIDEOPLAYER_VIDEOSTATE_H
#include <cstdint>
#include <atomic>
#include <array>
#include <vector>
#include <memory>
#include <string>
#include <mutex>
#include <condition_variable>
#include <osg/ref_ptr>
namespace osg
{
class Texture2D;
}
#if defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4244)
#endif
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libavutil/channel_layout.h>
// From version 54.56 binkaudio encoding format changed from S16 to FLTP. See:
// https://gitorious.org/ffmpeg/ffmpeg/commit/7bfd1766d1c18f07b0a2dd042418a874d49ea60d
// https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=872
#include <libswresample/swresample.h>
}
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#include "videodefs.hpp"
#include "libavformatdefines.hpp"
#define VIDEO_PICTURE_QUEUE_SIZE 50
extern "C"
{
struct SwsContext;
struct AVPacket;
struct AVFormatContext;
struct AVStream;
struct AVFrame;
}
namespace Video
{
struct VideoState;
class MovieAudioFactory;
class MovieAudioDecoder;
class VideoThread;
class ParseThread;
struct ExternalClock
{
ExternalClock();
uint64_t mTimeBase;
uint64_t mPausedAt;
bool mPaused;
std::mutex mMutex;
void setPaused(bool paused);
uint64_t get();
void set(uint64_t time);
};
class PacketList
{
public:
AVPacket* pkt = nullptr;
PacketList *next = nullptr;
};
struct PacketQueue {
PacketQueue()
: first_pkt(nullptr), last_pkt(nullptr), flushing(false), nb_packets(0), size(0)
{ }
~PacketQueue()
{ clear(); }
PacketList *first_pkt, *last_pkt;
std::atomic<bool> flushing;
std::atomic<int> nb_packets;
std::atomic<int> size;
std::mutex mutex;
std::condition_variable cond;
void put(AVPacket *pkt);
int get(AVPacket *pkt, VideoState *is);
void flush();
void clear();
};
struct VideoPicture {
VideoPicture() : pts(0.0)
{ }
struct AVFrameDeleter {
void operator()(AVFrame* frame) const;
};
// Sets frame dimensions.
// Must be called before writing to `rgbaFrame`.
// Return -1 on error.
int set_dimensions(int w, int h);
std::unique_ptr<AVFrame, AVFrameDeleter> rgbaFrame;
double pts;
};
struct VideoState {
VideoState();
~VideoState();
void setAudioFactory(MovieAudioFactory* factory);
void init(std::unique_ptr<std::istream>&& inputstream, const std::string& name);
void deinit();
void setPaused(bool isPaused);
void seekTo(double time);
double getDuration() const;
int stream_open(int stream_index, AVFormatContext *pFormatCtx);
bool update();
static void video_thread_loop(VideoState *is);
static void decode_thread_loop(VideoState *is);
void video_display(VideoPicture* vp);
void video_refresh();
int queue_picture(const AVFrame &pFrame, double pts);
double synchronize_video(const AVFrame &src_frame, double pts);
double get_audio_clock();
double get_video_clock() const;
double get_external_clock();
double get_master_clock();
static int istream_read(void *user_data, uint8_t *buf, int buf_size);
#if OPENMW_FFMPEG_CONST_WRITEPACKET
static int istream_write(void *, const unsigned char *, int);
#else
static int istream_write(void *, uint8_t *, int);
#endif
static int64_t istream_seek(void *user_data, int64_t offset, int whence);
osg::ref_ptr<osg::Texture2D> mTexture;
MovieAudioFactory* mAudioFactory;
std::unique_ptr<MovieAudioDecoder> mAudioDecoder;
ExternalClock mExternalClock;
std::unique_ptr<std::istream> stream;
AVFormatContext* format_ctx;
AVCodecContext* video_ctx;
AVCodecContext* audio_ctx;
int av_sync_type;
AVStream** audio_st;
PacketQueue audioq;
uint8_t* mFlushPktData;
AVStream** video_st;
double frame_last_pts;
double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
PacketQueue videoq;
SwsContext* sws_context;
int sws_context_w, sws_context_h;
std::array<VideoPicture, VIDEO_PICTURE_QUEUE_SIZE+1> pictq; // allocate one extra to make sure we do not overwrite the osg::Image currently set on the texture
int pictq_size;
unsigned long pictq_rindex, pictq_windex;
std::mutex pictq_mutex;
std::condition_variable pictq_cond;
std::unique_ptr<ParseThread> parse_thread;
std::unique_ptr<VideoThread> video_thread;
std::atomic<bool> mSeekRequested;
uint64_t mSeekPos;
std::atomic<bool> mVideoEnded;
std::atomic<bool> mPaused;
std::atomic<bool> mQuit;
};
}
#endif