diff --git a/client/BattleInterface/CBattleInterfaceClasses.cpp b/client/BattleInterface/CBattleInterfaceClasses.cpp index 583599c14..a9c2bc684 100644 --- a/client/BattleInterface/CBattleInterfaceClasses.cpp +++ b/client/BattleInterface/CBattleInterfaceClasses.cpp @@ -418,7 +418,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect } CCS->musich->playMusic("Music/Win Battle", false); - CCS->videoh->open(VIDEO_WIN); + CCS->videoh->open("WIN3.BIK"); std::string str = CGI->generaltexth->allTexts[text]; const CGHeroInstance * ourHero = weAreAttacker? owner->attackingHeroInstance : owner->defendingHeroInstance; @@ -438,21 +438,21 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect case 0: //normal victory { CCS->musich->playMusic("Music/LoseCombat", false); - CCS->videoh->open(VIDEO_LOSE_BATTLE_START); + CCS->videoh->open("LBSTART.BIK"); new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[311]); break; } case 1: //flee { CCS->musich->playMusic("Music/Retreat Battle", false); - CCS->videoh->open(VIDEO_RETREAT_START); + CCS->videoh->open("RTSTART.BIK"); new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[310]); break; } case 2: //surrender { CCS->musich->playMusic("Music/Surrender Battle", false); - CCS->videoh->open(VIDEO_SURRENDER); + CCS->videoh->open("SURRENDER.BIK"); new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[309]); break; } diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index 51320a32c..bd00b3504 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -569,23 +569,41 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) #ifndef DISABLE_VIDEO -//Workaround for compile error in ffmpeg (UINT_64C was not declared) -#define __STDC_CONSTANT_MACROS -#ifdef _STDINT_H -#undef _STDINT_H -#endif -#include +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 117, 0) +// Define a set of functions to read data +static int lodRead(void* opaque, uint8_t* buf, int size) +{ + auto video = reinterpret_cast(opaque); -extern "C" { -#include -#include + vstd::amin(size, video->length - video->offset); + + if (size < 0) + return -1; + + memcpy(buf, video->data + video->offset, size); + video->offset += size; + return size; } +static si64 lodSeek(void * opaque, si64 pos, int whence) +{ + auto video = reinterpret_cast(opaque); + + if (whence & AVSEEK_SIZE) + return video->length; + + video->offset = pos; + vstd::amin(video->offset, video->length); + return video->offset; +} + +#else + static const char *protocol_name = "lod"; // Open a pseudo file. Name is something like 'lod:0x56432ab6c43df8fe' -static int lod_open(URLContext *context, const char *filename, int flags) +static int lodOpen(URLContext *context, const char *filename, int flags) { CVideoPlayer *video; @@ -600,13 +618,13 @@ static int lod_open(URLContext *context, const char *filename, int flags) return 0; } -static int lod_close(URLContext* h) +static int lodClose(URLContext* h) { return 0; } // Define a set of functions to read data -static int lod_read(URLContext *context, ui8 *buf, int size) +static int lodRead(URLContext *context, ui8 *buf, int size) { CVideoPlayer *video = (CVideoPlayer *)context->priv_data; @@ -623,7 +641,7 @@ static int lod_read(URLContext *context, ui8 *buf, int size) return size; } -static si64 lod_seek(URLContext *context, si64 pos, int whence) +static si64 lodSeek(URLContext *context, si64 pos, int whence) { CVideoPlayer *video = (CVideoPlayer *)context->priv_data; @@ -632,19 +650,21 @@ static si64 lod_seek(URLContext *context, si64 pos, int whence) video->offset = pos; vstd::amin(video->offset, video->length); - return -1;//video->offset; + return video->offset; } static URLProtocol lod_protocol = { protocol_name, - lod_open, - lod_read, + lodOpen, + lodRead, NULL, // no write - lod_seek, - lod_close + lodSeek, + lodClose }; +#endif + CVideoPlayer::CVideoPlayer() { format = NULL; @@ -653,17 +673,17 @@ CVideoPlayer::CVideoPlayer() sws = NULL; overlay = NULL; dest = NULL; + context = nullptr; + buffer = nullptr; // Register codecs. TODO: May be overkill. Should call a // combination of av_register_input_format() / // av_register_output_format() / av_register_protocol() instead. av_register_all(); +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 117, 0) +#elif LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 69, 0) // Register our protocol 'lod' so we can directly read from mmaped memory - // TODO: URL protocol marked as deprecated in favor of avioContext - // VCMI should to it if URL protocol will be removed from ffmpeg or - // when new avioContext will be available in all distros (ETA: late 2012) -#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 69, 0) av_register_protocol2(&lod_protocol, sizeof(lod_protocol)); #else av_register_protocol(&lod_protocol); @@ -702,17 +722,30 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) return false; } +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 117, 0) + + static const int BUFFER_SIZE = 4096; + buffer = (unsigned char *)av_malloc(BUFFER_SIZE);// will be freed by ffmpeg + context = avio_alloc_context( buffer, BUFFER_SIZE, 0, (void *)this, lodRead, NULL, lodSeek); + + format = avformat_alloc_context(); + format->pb = context; + // filename is not needed - file was already open and stored in this->data; + int avfopen = avformat_open_input(&format, "dummyFilename", nullptr, nullptr); + +#else + std::string filePath; filePath.resize(100); // Create our URL name with the 'lod' protocol as a prefix and a // back pointer to our object. Should be 32 and 64 bits compatible. sprintf(&filePath[0], "%s:0x%016llx", protocol_name, (unsigned long long)(uintptr_t)this); - #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 0, 0) int avfopen = av_open_input_file(&format, filePath.c_str(), NULL, 0, NULL); #else int avfopen = avformat_open_input(&format, filePath.c_str(), NULL, NULL); +#endif #endif if (avfopen != 0) @@ -994,6 +1027,14 @@ void CVideoPlayer::close() avformat_close_input(&format); #endif } + +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 117, 0) + if (context) + { + av_free(context); + context = nullptr; + } +#endif } // Plays a video. Only works for overlays. diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h index 3d65ca520..396a9bea4 100644 --- a/client/CVideoHandler.h +++ b/client/CVideoHandler.h @@ -213,14 +213,6 @@ public: bool playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey = false); //plays whole opened video; returns: true when whole video has been shown, false when it has been interrupted }; -#define VIDEO_TAVERN "TAVERN.BIK" -#define VIDEO_WIN "WIN3.BIK" -#define VIDEO_LOSE_BATTLE_START "LBSTART.BIK" -#define VIDEO_LOSE_BATTLE_LOOP "LBLOOP.BIK" -#define VIDEO_RETREAT_START "RTSTART.BIK" -#define VIDEO_RETREAT_LOOP "RTLOOP.BIK" -#define VIDEO_SURRENDER "SURRENDER.BIK" - #else #ifndef DISABLE_VIDEO @@ -231,11 +223,18 @@ public: #include #endif -typedef struct AVFormatContext AVFormatContext; -typedef struct AVCodecContext AVCodecContext; -typedef struct AVCodec AVCodec; -typedef struct AVFrame AVFrame; -struct SwsContext; +//Workaround for compile error in ffmpeg (UINT_64C was not declared) +#define __STDC_CONSTANT_MACROS +#ifdef _STDINT_H +#undef _STDINT_H +#endif +#include + + +extern "C" { +#include +#include +} class CVideoPlayer : public IMainVideoPlayer { @@ -247,6 +246,9 @@ private: AVFrame *frame; struct SwsContext *sws; + unsigned char* buffer; + AVIOContext * context; + // Destination. Either overlay or dest. SDL_Overlay *overlay; SDL_Surface *dest; @@ -287,13 +289,4 @@ public: }; #endif - -#define VIDEO_TAVERN "tavern.mjpg" -#define VIDEO_WIN "win3.mjpg" -#define VIDEO_LOSE_BATTLE_START "lbstart.mjpg" -#define VIDEO_LOSE_BATTLE_LOOP "lbloop.mjpg" -#define VIDEO_RETREAT_START "rtstart.mjpg" -#define VIDEO_RETREAT_LOOP "rtloop.mjpg" -#define VIDEO_SURRENDER "surrender.mjpg" - #endif diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index b9e2bc700..a1fcb49b9 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -3533,7 +3533,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj): recruit->block(1); } - CCS->videoh->open(VIDEO_TAVERN); + CCS->videoh->open("TAVERN.BIK"); } void CTavernWindow::recruitb()