1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Video playback is now time-based, using video file timings

This commit is contained in:
Ivan Savenko 2023-01-27 01:52:40 +02:00
parent 7bbaae75a2
commit a9fefffc65
2 changed files with 35 additions and 58 deletions

View File

@ -18,6 +18,14 @@
extern CGuiHandler GH; //global gui handler
#ifndef DISABLE_VIDEO
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
//reads events and returns true on key down
static bool keyDown()
{
@ -56,22 +64,20 @@ static si64 lodSeek(void * opaque, si64 pos, int whence)
}
CVideoPlayer::CVideoPlayer()
{
stream = -1;
format = nullptr;
codecContext = nullptr;
codec = nullptr;
frame = nullptr;
sws = nullptr;
context = nullptr;
texture = nullptr;
dest = nullptr;
destRect = CSDL_Ext::genRect(0,0,0,0);
pos = CSDL_Ext::genRect(0,0,0,0);
refreshWait = 0;
refreshCount = 0;
doLoop = false;
}
: stream(-1)
, format (nullptr)
, codecContext(nullptr)
, codec(nullptr)
, frame(nullptr)
, sws(nullptr)
, context(nullptr)
, texture(nullptr)
, dest(nullptr)
, destRect(0,0,0,0)
, pos(0,0,0,0)
, frameTime(0)
, doLoop(false)
{}
bool CVideoPlayer::open(std::string fname, bool scale)
{
@ -85,9 +91,8 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
close();
this->fname = fname;
refreshWait = 3;
refreshCount = -1;
doLoop = loop;
frameTime = 0;
ResourceID resource(std::string("Video/") + fname, EResType::VIDEO);
@ -254,6 +259,7 @@ bool CVideoPlayer::nextFrame()
if (doLoop && !gotError)
{
// Rewind
frameTime = 0;
if (av_seek_frame(format, stream, 0, AVSEEK_FLAG_BYTE) < 0)
break;
gotError = true;
@ -354,9 +360,11 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
if (sws == nullptr)
return;
if (refreshCount <= 0)
double frameEndTime = (frame->pts + frame->pkt_duration) * av_q2d(format->streams[stream]->time_base);
frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.0;
if (frameTime >= frameEndTime )
{
refreshCount = refreshWait;
if (nextFrame())
show(x,y,dst,update);
else
@ -374,8 +382,6 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
{
redraw(x, y, dst, update);
}
refreshCount --;
}
void CVideoPlayer::close()

View File

@ -56,39 +56,11 @@ public:
#include "../lib/filesystem/CInputStream.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
//compatibility for libav 9.18 in ubuntu 14.04, 52.66.100 is ffmpeg 2.2.3
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 66, 100))
inline AVFrame * av_frame_alloc()
{
return avcodec_alloc_frame();
}
inline void av_frame_free(AVFrame ** frame)
{
av_free(*frame);
*frame = nullptr;
}
#endif // VCMI_USE_OLD_AVUTIL
//fix for travis-ci
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 0, 0))
#define AVPixelFormat PixelFormat
#define AV_PIX_FMT_NONE PIX_FMT_NONE
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
#define AV_PIX_FMT_BGR565 PIX_FMT_BGR565
#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
#define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
#define AV_PIX_FMT_RGB565 PIX_FMT_RGB565
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
#define AV_PIX_FMT_RGB32 PIX_FMT_RGB32
#endif
struct AVFormatContext;
struct AVCodecContext;
struct AVCodec;
struct AVFrame;
struct AVIOContext;
class CVideoPlayer : public IMainVideoPlayer
{
@ -108,8 +80,8 @@ class CVideoPlayer : public IMainVideoPlayer
Rect destRect; // valid when dest is used
Rect pos; // destination on screen
int refreshWait; // Wait several refresh before updating the image
int refreshCount;
/// video playback currnet progress, in seconds
double frameTime;
bool doLoop; // loop through video
bool playVideo(int x, int y, bool stopOnKey);
@ -141,4 +113,3 @@ public:
};
#endif