/*************************************************************************** * Copyright (C) 2010 by Dimok * (C) 2014 by FIX94 * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any * purpose, including commercial applications, and to alter it and * redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you * must not claim that you wrote the original software. If you use * this software in a product, an acknowledgment in the product * documentation would be appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and * must not be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. * * WiiMovie.cpp * * for WiiXplorer 2010 ***************************************************************************/ #include #include "memory/mem2.hpp" #include "WiiMovie.hpp" #include "gecko/gecko.hpp" WiiMovie movie; void WiiMovie::Init(const char *filepath) { Frame = NULL; BufferPos = 0; Buffer[0].thread = false; Buffer[1].thread = false; VideoFrameCount = 0; fps = 0.0f; ExitRequested = false; Playing = false; ThreadStack = NULL; //gprintf("Opening video '%s'\n", filepath); ReadThread = LWP_THREAD_NULL; vFile = fopen(filepath, "rb"); if(!vFile) { //gprintf("Open video failed\n"); ExitRequested = true; return; } if(Video.Init(vFile) == false) { //gprintf("Memory Allocation failed\n"); ExitRequested = true; return; } fps = Video.getFps(); inited = true; } void WiiMovie::DeInit() { if(inited == false) return; inited = false; //gprintf("Destructing WiiMovie object\n"); Playing = false; ExitRequested = true; Stop(); if(ReadThread != LWP_THREAD_NULL) { LWP_ResumeThread(ReadThread); LWP_JoinThread(ReadThread, NULL); } if(ThreadStack != NULL) { MEM2_lo_free(ThreadStack); ThreadStack = NULL; } Video.DeInit(); if(vFile != NULL) fclose(vFile); VideoF.dealloc(); vFile = NULL; Frame = NULL; TexHandle.Cleanup(Buffer[0]); TexHandle.Cleanup(Buffer[1]); Buffer[0].thread = false; Buffer[1].thread = false; BufferPos = 0; } bool WiiMovie::Play(bool loop) { if(!vFile) return false; ThreadStack = (u8*)MEM2_lo_alloc(32768); if(!ThreadStack) return false; //gprintf("Start playing video\n"); Video.loop = loop; PlayTime.reset(); Playing = true; Buffer[0].thread = false; Buffer[1].thread = false; LWP_CreateThread(&ReadThread, UpdateThread, this, ThreadStack, 32768, 63); //gprintf("Reading frames thread started\n"); return true; } void WiiMovie::Stop() { //gprintf("Stopping WiiMovie video\n"); ExitRequested = true; } void * WiiMovie::UpdateThread(void *arg) { WiiMovie *movie = static_cast(arg); while(!movie->ExitRequested) { movie->ReadNextFrame(); if(movie->Buffer[movie->BufferPos].thread == false) movie->LoadNextFrame(); else if(movie->Frame->thread == false) { movie->Frame = &movie->Buffer[movie->BufferPos]; movie->BufferPos ^= 1; } } return NULL; } void WiiMovie::ReadNextFrame() { for(u32 FramesNeeded = (u32)(PlayTime.elapsed()*fps); VideoFrameCount <= FramesNeeded; ++VideoFrameCount) { if(VideoFrameCount == FramesNeeded) Playing = Video.loadNextFrame(); else Video.loadNextFrame(true); } } void WiiMovie::LoadNextFrame() { if(!vFile || !Playing) return; Video.getCurrentFrame(VideoF); if(!VideoF.data) return; TexData *CurFrame = &Buffer[BufferPos]; if(TexHandle.fromTHP(CurFrame, VideoF.data, VideoF.getWidth(), VideoF.getHeight()) == TE_OK) { CurFrame->thread = true; Frame = CurFrame; BufferPos ^= 1; } } bool WiiMovie::Continue() { if(!vFile || !Playing) return false; return true; }