|
@@ -21,555 +21,6 @@ static bool keyDown()
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
-#endif
|
|
|
-
|
|
|
-#if defined(VCMI_WINDOWS) && (_MSC_VER < 1800 || !defined(USE_FFMPEG))
|
|
|
-
|
|
|
-void checkForError(bool throwing = true)
|
|
|
-{
|
|
|
- int error = GetLastError();
|
|
|
- if(!error)
|
|
|
- return;
|
|
|
-
|
|
|
- logGlobal->errorStream() << "Error " << error << " encountered!";
|
|
|
- std::string msg;
|
|
|
- char* pTemp = nullptr;
|
|
|
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
- nullptr, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&pTemp, 1, nullptr );
|
|
|
- logGlobal->errorStream() << "Error: " << pTemp;
|
|
|
- msg = pTemp;
|
|
|
- LocalFree( pTemp );
|
|
|
- pTemp = nullptr;
|
|
|
- if(throwing)
|
|
|
- throw std::runtime_error(msg);
|
|
|
-}
|
|
|
-
|
|
|
-void blitBuffer(char *buffer, int x, int y, int w, int h, SDL_Surface *dst)
|
|
|
-{
|
|
|
- const int bpp = dst->format->BytesPerPixel;
|
|
|
- char *dest;
|
|
|
- for(int i = h; i > 0; i--)
|
|
|
- {
|
|
|
- dest = (char*)dst->pixels + dst->pitch*(y+h-i) + x*dst->format->BytesPerPixel;
|
|
|
- memcpy(dest, buffer, bpp*w);
|
|
|
- buffer += bpp*w;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void DLLHandler::Instantiate(const char *filename)
|
|
|
-{
|
|
|
- name = filename;
|
|
|
- dll = LoadLibraryA(filename);
|
|
|
- if(!dll)
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "Failed loading " << filename;
|
|
|
- checkForError(true);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void *DLLHandler::FindAddress(const char *symbol)
|
|
|
-{
|
|
|
- void *ret;
|
|
|
-
|
|
|
- if(!dll)
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "Cannot look for " << symbol << " because DLL hasn't been appropriately loaded!";
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
- ret = (void*) GetProcAddress(dll,symbol);
|
|
|
- if(!ret)
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "Failed to find " << symbol << " in " << name;
|
|
|
- checkForError();
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-DLLHandler::~DLLHandler()
|
|
|
-{
|
|
|
- if(dll)
|
|
|
- {
|
|
|
- if(!FreeLibrary(dll))
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "Failed to free " << name;
|
|
|
- checkForError();
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-DLLHandler::DLLHandler()
|
|
|
-{
|
|
|
- dll = nullptr;
|
|
|
-}
|
|
|
-
|
|
|
-CBIKHandler::CBIKHandler()
|
|
|
-{
|
|
|
- Instantiate("BINKW32.DLL");
|
|
|
- //binkGetError = FindAddress("_BinkGetError@0");
|
|
|
- binkOpen = (BinkOpen)FindAddress("_BinkOpen@8");
|
|
|
- binkSetSoundSystem = (BinkSetSoundSystem)FindAddress("_BinkSetSoundSystem@8");
|
|
|
- //getPalette = (BinkGetPalette)FindAddress("_BinkGetPalette@4");
|
|
|
- binkNextFrame = (BinkNextFrame)FindAddress("_BinkNextFrame@4");
|
|
|
- binkDoFrame = (BinkDoFrame)FindAddress("_BinkDoFrame@4");
|
|
|
- binkCopyToBuffer = (BinkCopyToBuffer)FindAddress("_BinkCopyToBuffer@28");
|
|
|
- binkWait = (BinkWait)FindAddress("_BinkWait@4");
|
|
|
- binkClose = (BinkClose)FindAddress("_BinkClose@4");
|
|
|
-
|
|
|
-
|
|
|
- hBinkFile = nullptr;
|
|
|
- hBink = nullptr;
|
|
|
-
|
|
|
- buffer = nullptr;
|
|
|
- bufferSize = 0;
|
|
|
-}
|
|
|
-
|
|
|
-bool CBIKHandler::open(std::string name)
|
|
|
-{
|
|
|
- hBinkFile = CreateFileA
|
|
|
- (
|
|
|
- name.c_str(), // file name
|
|
|
- GENERIC_READ, // access mode
|
|
|
- FILE_SHARE_READ, // share mode
|
|
|
- nullptr, // Security Descriptor
|
|
|
- OPEN_EXISTING, // how to create
|
|
|
- FILE_ATTRIBUTE_NORMAL,//FILE_FLAG_SEQUENTIAL_SCAN, // file attributes
|
|
|
- 0 // handle to template file
|
|
|
- );
|
|
|
-
|
|
|
- if(hBinkFile == INVALID_HANDLE_VALUE)
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "BIK handler: failed to open " << name;
|
|
|
- goto checkErrorAndClean;
|
|
|
- }
|
|
|
- //GCC wants scope of waveout to don`t cross labels/swith/goto
|
|
|
- {
|
|
|
- void *waveout = (void *)GetProcAddress(dll,"_BinkOpenWaveOut@4");
|
|
|
- if(waveout)
|
|
|
- binkSetSoundSystem(waveout,nullptr);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- hBink = binkOpen(hBinkFile, 0x8a800000);
|
|
|
- if(!hBink)
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "bink failed to open " << name;
|
|
|
- goto checkErrorAndClean;
|
|
|
- }
|
|
|
-
|
|
|
- allocBuffer();
|
|
|
- return true;
|
|
|
-
|
|
|
-checkErrorAndClean:
|
|
|
- CloseHandle(hBinkFile);
|
|
|
- hBinkFile = nullptr;
|
|
|
- checkForError();
|
|
|
- throw std::runtime_error("BIK failed opening video!");
|
|
|
-}
|
|
|
-
|
|
|
-void CBIKHandler::show( int x, int y, SDL_Surface *dst, bool update )
|
|
|
-{
|
|
|
- const int w = hBink->width,
|
|
|
- h = hBink->height,
|
|
|
- Bpp = dst->format->BytesPerPixel;
|
|
|
-
|
|
|
- int mode = -1;
|
|
|
-
|
|
|
- //screen color depth might have changed... (eg. because F4)
|
|
|
- if(bufferSize != w * h * Bpp)
|
|
|
- {
|
|
|
- freeBuffer();
|
|
|
- allocBuffer(Bpp);
|
|
|
- }
|
|
|
-
|
|
|
- switch(Bpp)
|
|
|
- {
|
|
|
- case 2:
|
|
|
- mode = 3; //565, mode 2 is 555 probably
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- mode = 0;
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- mode = 1;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return; //not supported screen depth
|
|
|
- }
|
|
|
-
|
|
|
- binkDoFrame(hBink);
|
|
|
- binkCopyToBuffer(hBink, buffer, w*Bpp, h, 0, 0, mode);
|
|
|
- blitBuffer(buffer, x, y, w, h, dst);
|
|
|
- if(update)
|
|
|
- SDL_UpdateRect(dst, x, y, w, h);
|
|
|
-}
|
|
|
-
|
|
|
-bool CBIKHandler::nextFrame()
|
|
|
-{
|
|
|
- binkNextFrame(hBink);
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-void CBIKHandler::close()
|
|
|
-{
|
|
|
- binkClose(hBink);
|
|
|
- hBink = nullptr;
|
|
|
- CloseHandle(hBinkFile);
|
|
|
- hBinkFile = nullptr;
|
|
|
- delete [] buffer;
|
|
|
-
|
|
|
- buffer = nullptr;
|
|
|
- bufferSize = 0;
|
|
|
-}
|
|
|
-
|
|
|
-bool CBIKHandler::wait()
|
|
|
-{
|
|
|
- return binkWait(hBink);
|
|
|
-}
|
|
|
-
|
|
|
-int CBIKHandler::curFrame() const
|
|
|
-{
|
|
|
- return hBink->currentFrame;
|
|
|
-}
|
|
|
-
|
|
|
-int CBIKHandler::frameCount() const
|
|
|
-{
|
|
|
- return hBink->frameCount;
|
|
|
-}
|
|
|
-
|
|
|
-void CBIKHandler::redraw( int x, int y, SDL_Surface *dst, bool update )
|
|
|
-{
|
|
|
- int w = hBink->width, h = hBink->height;
|
|
|
- blitBuffer(buffer, x, y, w, h, dst);
|
|
|
- if(update)
|
|
|
- SDL_UpdateRect(dst, x, y, w, h);
|
|
|
-}
|
|
|
-
|
|
|
-void CBIKHandler::allocBuffer(int Bpp)
|
|
|
-{
|
|
|
- if(!Bpp) Bpp = screen->format->BytesPerPixel;
|
|
|
-
|
|
|
- bufferSize = hBink->width * hBink->height * Bpp;
|
|
|
- buffer = new char[bufferSize];
|
|
|
-}
|
|
|
-
|
|
|
-void CBIKHandler::freeBuffer()
|
|
|
-{
|
|
|
- delete [] buffer;
|
|
|
- buffer = nullptr;
|
|
|
- bufferSize = 0;
|
|
|
-}
|
|
|
-
|
|
|
-bool CSmackPlayer::nextFrame()
|
|
|
-{
|
|
|
- ptrSmackNextFrame(data);
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-bool CSmackPlayer::wait()
|
|
|
-{
|
|
|
- return ptrSmackWait(data);
|
|
|
-}
|
|
|
-
|
|
|
-CSmackPlayer::CSmackPlayer() : data(nullptr)
|
|
|
-{
|
|
|
- Instantiate("smackw32.dll");
|
|
|
- ptrSmackNextFrame = (SmackNextFrame)FindAddress("_SmackNextFrame@4");
|
|
|
- ptrSmackWait = (SmackWait)FindAddress("_SmackWait@4");
|
|
|
- ptrSmackDoFrame = (SmackDoFrame)FindAddress("_SmackDoFrame@4");
|
|
|
- ptrSmackToBuffer = (SmackToBuffer)FindAddress("_SmackToBuffer@28");
|
|
|
- ptrSmackOpen = (SmackOpen)FindAddress("_SmackOpen@12");
|
|
|
- ptrSmackSoundOnOff = (SmackSoundOnOff)FindAddress("_SmackSoundOnOff@8");
|
|
|
- ptrSmackClose = (SmackClose)FindAddress("_SmackClose@4");
|
|
|
- ptrVolumePan = (SmackVolumePan)FindAddress("_SmackVolumePan@16");
|
|
|
-}
|
|
|
-
|
|
|
-CSmackPlayer::~CSmackPlayer()
|
|
|
-{
|
|
|
- if(data)
|
|
|
- close();
|
|
|
-}
|
|
|
-
|
|
|
-void CSmackPlayer::close()
|
|
|
-{
|
|
|
- ptrSmackClose(data);
|
|
|
- data = nullptr;
|
|
|
-}
|
|
|
-
|
|
|
-bool CSmackPlayer::open( std::string name )
|
|
|
-{
|
|
|
- Uint32 flags[2] = {0xff400, 0xfe400};
|
|
|
-
|
|
|
- data = ptrSmackOpen( (void*)name.c_str(), flags[1], -1);
|
|
|
- if (!data)
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "Smack cannot open " << name;
|
|
|
- checkForError();
|
|
|
- throw std::runtime_error("SMACK failed opening video");
|
|
|
- }
|
|
|
-
|
|
|
- buffer = new char[data->width*data->height*2];
|
|
|
- buf = buffer+data->width*(data->height-1)*2; // adjust pointer position for later use by 'SmackToBuffer'
|
|
|
-
|
|
|
- //ptrVolumePan(data, 0xfe000, 3640 * GDefaultOptions.musicVolume / 11, 0x8000); //set volume
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-void CSmackPlayer::show( int x, int y, SDL_Surface *dst, bool update)
|
|
|
-{
|
|
|
- int w = data->width;
|
|
|
- int stripe = (-w*2) & (~3);
|
|
|
-
|
|
|
- //put frame to the buffer
|
|
|
- ptrSmackToBuffer(data, 0, 0, stripe, w, buf, 0x80000000);
|
|
|
- ptrSmackDoFrame(data);
|
|
|
- redraw(x, y, dst, update);
|
|
|
-}
|
|
|
-
|
|
|
-int CSmackPlayer::curFrame() const
|
|
|
-{
|
|
|
- return data->currentFrame;
|
|
|
-}
|
|
|
-
|
|
|
-int CSmackPlayer::frameCount() const
|
|
|
-{
|
|
|
- return data->frameCount;
|
|
|
-}
|
|
|
-
|
|
|
-void CSmackPlayer::redraw( int x, int y, SDL_Surface *dst, bool update )
|
|
|
-{
|
|
|
- int w = std::min<int>(data->width, dst->w - x), h = std::min<int>(data->height, dst->h - y);
|
|
|
- /* Lock the screen for direct access to the pixels */
|
|
|
- if ( SDL_MUSTLOCK(dst) )
|
|
|
- {
|
|
|
- if ( SDL_LockSurface(dst) < 0 )
|
|
|
- {
|
|
|
- fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // draw the frame
|
|
|
- Uint16* addr = (Uint16*) (buffer+w*(h-1)*2-2);
|
|
|
- if(dst->format->BytesPerPixel >= 3)
|
|
|
- {
|
|
|
- for( int j=0; j<h-1; j++) // why -1 ?
|
|
|
- {
|
|
|
- for ( int i=w-1; i>=0; i--)
|
|
|
- {
|
|
|
- Uint16 pixel = *addr;
|
|
|
-
|
|
|
- Uint8 *p = (Uint8 *)dst->pixels + (j+y) * dst->pitch + (i + x) * dst->format->BytesPerPixel;
|
|
|
- p[2] = ((pixel & 0x7c00) >> 10) * 8;
|
|
|
- p[1] = ((pixel & 0x3e0) >> 5) * 8;
|
|
|
- p[0] = ((pixel & 0x1F)) * 8;
|
|
|
-
|
|
|
- addr--;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else if(dst->format->BytesPerPixel == 2)
|
|
|
- {
|
|
|
- for( int j=0; j<h-1; j++) // why -1 ?
|
|
|
- {
|
|
|
- for ( int i=w-1; i>=0; i--)
|
|
|
- {
|
|
|
- //convert rgb 555 to 565
|
|
|
- Uint16 pixel = *addr;
|
|
|
- Uint16 *p = (Uint16 *)((Uint8 *)dst->pixels + (j+y) * dst->pitch + (i + x) * dst->format->BytesPerPixel);
|
|
|
- *p = (pixel & 0x1F)
|
|
|
- + ((pixel & 0x3e0) << 1)
|
|
|
- + ((pixel & 0x7c00) << 1);
|
|
|
-
|
|
|
- addr--;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if ( SDL_MUSTLOCK(dst) )
|
|
|
- {
|
|
|
- SDL_UnlockSurface(dst);
|
|
|
- }
|
|
|
-
|
|
|
- if(update)
|
|
|
- SDL_UpdateRect(dst, x, y, w, h);
|
|
|
-}
|
|
|
-
|
|
|
-CVideoPlayer::CVideoPlayer()
|
|
|
-{
|
|
|
- current = nullptr;
|
|
|
-}
|
|
|
-
|
|
|
-CVideoPlayer::~CVideoPlayer()
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-bool CVideoPlayer::open(std::string name)
|
|
|
-{
|
|
|
- fname = name;
|
|
|
- first = true;
|
|
|
-
|
|
|
- try
|
|
|
- {
|
|
|
- // Extract video from video.vid so we can play it.
|
|
|
- // We can handle only videos in form of single file, no archive support yet.
|
|
|
- {
|
|
|
- ResourceID videoID = ResourceID("VIDEO/" + name, EResType::VIDEO);
|
|
|
- auto data = CResourceHandler::get()->load(videoID)->readAll();
|
|
|
-
|
|
|
- // try to determine video format using magic number from header (3 bytes, SMK or BIK)
|
|
|
- std::string magic(reinterpret_cast<char*>(data.first.get()), 3);
|
|
|
- if (magic == "BIK")
|
|
|
- current = &bikPlayer;
|
|
|
- else if (magic == "SMK")
|
|
|
- current = &smkPlayer;
|
|
|
- else
|
|
|
- throw std::runtime_error("Unknown video format: " + magic);
|
|
|
-
|
|
|
- std::ofstream out(name, std::ofstream::binary);
|
|
|
- out.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
|
- out.write(reinterpret_cast<char*>(data.first.get()), data.second);
|
|
|
- }
|
|
|
-
|
|
|
- current->open(name);
|
|
|
- return true;
|
|
|
- }
|
|
|
- catch(std::exception &e)
|
|
|
- {
|
|
|
- current = nullptr;
|
|
|
- logGlobal->warnStream() << "Failed to open video file " << name << ": " << e.what();
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-void CVideoPlayer::close()
|
|
|
-{
|
|
|
- if(!current)
|
|
|
- {
|
|
|
- logGlobal->warnStream() << "Closing no opened player...?";
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- current->close();
|
|
|
- current = nullptr;
|
|
|
- if(!DeleteFileA(fname.c_str()))
|
|
|
- {
|
|
|
- logGlobal->errorStream() << "Cannot remove temporarily extracted video file: " << fname;
|
|
|
- checkForError(false);
|
|
|
- }
|
|
|
- fname.clear();
|
|
|
-}
|
|
|
-
|
|
|
-bool CVideoPlayer::nextFrame()
|
|
|
-{
|
|
|
- if(current)
|
|
|
- {
|
|
|
- current->nextFrame();
|
|
|
- return true;
|
|
|
- }
|
|
|
- else
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-void CVideoPlayer::show(int x, int y, SDL_Surface *dst, bool update)
|
|
|
-{
|
|
|
- if(current)
|
|
|
- current->show(x, y, dst, update);
|
|
|
-}
|
|
|
-
|
|
|
-bool CVideoPlayer::wait()
|
|
|
-{
|
|
|
- if(current)
|
|
|
- return current->wait();
|
|
|
- else
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-int CVideoPlayer::curFrame() const
|
|
|
-{
|
|
|
- if(current)
|
|
|
- return current->curFrame();
|
|
|
- else
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-int CVideoPlayer::frameCount() const
|
|
|
-{
|
|
|
- if(current)
|
|
|
- return current->frameCount();
|
|
|
- else
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey)
|
|
|
-{
|
|
|
- if(!open(name))
|
|
|
- return false;
|
|
|
-
|
|
|
- bool ret = playVideo(x, y, dst, stopOnKey);
|
|
|
- close();
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, bool update )
|
|
|
-{
|
|
|
- if(!current)
|
|
|
- return;
|
|
|
-
|
|
|
- bool w = false;
|
|
|
- if(!first)
|
|
|
- {
|
|
|
- w = wait(); //check if should keep current frame
|
|
|
- if(!w)
|
|
|
- nextFrame();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- first = false;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if(!w)
|
|
|
- {
|
|
|
- show(x,y,dst,update);
|
|
|
- }
|
|
|
- else if (forceRedraw)
|
|
|
- {
|
|
|
- redraw(x, y, dst, update);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void CVideoPlayer::redraw( int x, int y, SDL_Surface *dst, bool update )
|
|
|
-{
|
|
|
- if(current)
|
|
|
- current->redraw(x, y, dst, update);
|
|
|
-}
|
|
|
-
|
|
|
-bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
|
|
|
-{
|
|
|
- if(!current)
|
|
|
- return false;
|
|
|
-
|
|
|
- int frame = 0;
|
|
|
- while(frame < frameCount()) //play all frames
|
|
|
- {
|
|
|
- if(stopOnKey && keyDown())
|
|
|
- return false;
|
|
|
-
|
|
|
- if(!wait())
|
|
|
- {
|
|
|
- show(x, y, dst);
|
|
|
- nextFrame();
|
|
|
- frame++;
|
|
|
- }
|
|
|
- SDL_Delay(20);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-#else
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
#pragma comment(lib, "avcodec.lib")
|
|
@@ -578,9 +29,6 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
|
|
|
#pragma comment(lib, "swscale.lib")
|
|
|
#endif // _MSC_VER
|
|
|
|
|
|
-
|
|
|
-#ifndef DISABLE_VIDEO
|
|
|
-
|
|
|
// Define a set of functions to read data
|
|
|
static int lodRead(void* opaque, uint8_t* buf, int size)
|
|
|
{
|
|
@@ -619,14 +67,14 @@ CVideoPlayer::CVideoPlayer()
|
|
|
av_register_all();
|
|
|
}
|
|
|
|
|
|
-bool CVideoPlayer::open(std::string fname)
|
|
|
+bool CVideoPlayer::open(std::string fname, bool scale/* = false*/)
|
|
|
{
|
|
|
return open(fname, true, false);
|
|
|
}
|
|
|
|
|
|
// loop = to loop through the video
|
|
|
// useOverlay = directly write to the screen.
|
|
|
-bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
|
|
|
+bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scale /*= false*/)
|
|
|
{
|
|
|
close();
|
|
|
|
|
@@ -708,24 +156,37 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
|
|
|
|
|
|
// Allocate video frame
|
|
|
frame = avcodec_alloc_frame();
|
|
|
+
|
|
|
+ //setup scaling
|
|
|
+
|
|
|
+ if(scale)
|
|
|
+ {
|
|
|
+ pos.w = screen->w;
|
|
|
+ pos.h = screen->h;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ pos.w = codecContext->width;
|
|
|
+ pos.h = codecContext->height;
|
|
|
+ }
|
|
|
|
|
|
// Allocate a place to put our YUV image on that screen
|
|
|
if (useOverlay)
|
|
|
{
|
|
|
#ifdef VCMI_SDL1
|
|
|
- overlay = SDL_CreateYUVOverlay(codecContext->width, codecContext->height,
|
|
|
+ overlay = SDL_CreateYUVOverlay(pos.w, pos.h,
|
|
|
SDL_YV12_OVERLAY, screen);
|
|
|
#else
|
|
|
- texture = SDL_CreateTexture( mainRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STATIC, codecContext->width, codecContext->height);
|
|
|
+ texture = SDL_CreateTexture( mainRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STATIC, pos.w, pos.h);
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- dest = CSDL_Ext::newSurface(codecContext->width, codecContext->height);
|
|
|
+ dest = CSDL_Ext::newSurface(pos.w, pos.h);
|
|
|
destRect.x = destRect.y = 0;
|
|
|
- destRect.w = codecContext->width;
|
|
|
- destRect.h = codecContext->height;
|
|
|
+ destRect.w = pos.w;
|
|
|
+ destRect.h = pos.h;
|
|
|
}
|
|
|
#ifdef VCMI_SDL1
|
|
|
if (overlay == nullptr && dest == nullptr)
|
|
@@ -739,9 +200,9 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
|
|
|
if (texture)
|
|
|
#endif
|
|
|
{ // Convert the image into YUV format that SDL uses
|
|
|
- sws = sws_getContext(codecContext->width, codecContext->height,
|
|
|
- codecContext->pix_fmt, codecContext->width, codecContext->height,
|
|
|
- PIX_FMT_YUV420P, SWS_BICUBIC, nullptr, nullptr, nullptr);
|
|
|
+ sws = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
|
|
|
+ pos.w, pos.h, PIX_FMT_YUV420P,
|
|
|
+ SWS_BICUBIC, nullptr, nullptr, nullptr);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -770,17 +231,14 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- sws = sws_getContext(codecContext->width, codecContext->height,
|
|
|
- codecContext->pix_fmt, codecContext->width, codecContext->height,
|
|
|
- screenFormat, SWS_BICUBIC, nullptr, nullptr, nullptr);
|
|
|
+ sws = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
|
|
|
+ pos.w, pos.h, screenFormat,
|
|
|
+ SWS_BICUBIC, nullptr, nullptr, nullptr);
|
|
|
}
|
|
|
|
|
|
if (sws == nullptr)
|
|
|
return false;
|
|
|
|
|
|
- pos.w = codecContext->width;
|
|
|
- pos.h = codecContext->height;
|
|
|
-
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -844,7 +302,7 @@ bool CVideoPlayer::nextFrame()
|
|
|
SDL_UnlockYUVOverlay(overlay);
|
|
|
#else
|
|
|
if (texture) {
|
|
|
- avpicture_alloc(&pict, AV_PIX_FMT_YUV420P, codecContext->width, codecContext->height);
|
|
|
+ avpicture_alloc(&pict, AV_PIX_FMT_YUV420P, pos.w, pos.h);
|
|
|
|
|
|
sws_scale(sws, frame->data, frame->linesize,
|
|
|
0, codecContext->height, pict.data, pict.linesize);
|
|
@@ -1000,7 +458,7 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
|
|
|
#ifdef VCMI_SDL1
|
|
|
SDL_DisplayYUVOverlay(overlay, &pos);
|
|
|
#else
|
|
|
- SDL_RenderCopy(mainRenderer, texture, NULL, NULL);
|
|
|
+ SDL_RenderCopy(mainRenderer, texture, NULL, &pos);
|
|
|
SDL_RenderPresent(mainRenderer);
|
|
|
#endif
|
|
|
|
|
@@ -1014,9 +472,9 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey)
|
|
|
+bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey, bool scale/* = false*/)
|
|
|
{
|
|
|
- open(name, false, true);
|
|
|
+ open(name, false, true, scale);
|
|
|
bool ret = playVideo(x, y, dst, stopOnKey);
|
|
|
close();
|
|
|
return ret;
|
|
@@ -1029,4 +487,3 @@ CVideoPlayer::~CVideoPlayer()
|
|
|
|
|
|
#endif
|
|
|
|
|
|
-#endif
|