mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
4.6 KiB
C++
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
|