aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/fmv
diff options
context:
space:
mode:
authorPaul Gilbert2010-08-30 07:48:27 +0000
committerEugene Sandulenko2010-10-12 23:20:33 +0000
commitcb95db7cc04a5a3d14f408835cd371e0a0abd4ed (patch)
tree0022ad1ca99c0fb5b623d612285e12fde2bc2434 /engines/sword25/fmv
parentffce890f66bc34b356c8df89591bc4f56e5a9e4e (diff)
downloadscummvm-rg350-cb95db7cc04a5a3d14f408835cd371e0a0abd4ed.tar.gz
scummvm-rg350-cb95db7cc04a5a3d14f408835cd371e0a0abd4ed.tar.bz2
scummvm-rg350-cb95db7cc04a5a3d14f408835cd371e0a0abd4ed.zip
SWORD25: Commit of in-progress MoviePlayer code
Frames aren't being corrected decoded yet; still trying to locate the cause svn-id: r53295
Diffstat (limited to 'engines/sword25/fmv')
-rw-r--r--engines/sword25/fmv/movieplayer.cpp481
-rw-r--r--engines/sword25/fmv/movieplayer.h68
-rw-r--r--engines/sword25/fmv/oggtheora/audiobuffer.cpp54
-rw-r--r--engines/sword25/fmv/oggtheora/audiobuffer.h26
-rw-r--r--engines/sword25/fmv/oggtheora/moviefile.cpp34
-rw-r--r--engines/sword25/fmv/oggtheora/moviefile.h17
-rw-r--r--engines/sword25/fmv/oggtheora/oggstate.cpp19
-rw-r--r--engines/sword25/fmv/oggtheora/oggstate.h36
-rw-r--r--engines/sword25/fmv/oggtheora/oggstreamstate.cpp40
-rw-r--r--engines/sword25/fmv/oggtheora/oggstreamstate.h48
-rw-r--r--engines/sword25/fmv/oggtheora/oggtheora.cpp723
-rw-r--r--engines/sword25/fmv/oggtheora/oggtheora.h124
-rw-r--r--engines/sword25/fmv/oggtheora/theorastate.cpp27
-rw-r--r--engines/sword25/fmv/oggtheora/theorastate.h19
-rw-r--r--engines/sword25/fmv/oggtheora/vorbisstate.cpp35
-rw-r--r--engines/sword25/fmv/oggtheora/vorbisstate.h21
-rw-r--r--engines/sword25/fmv/oggtheora/yuvtorgba.cpp587
-rw-r--r--engines/sword25/fmv/oggtheora/yuvtorgba.h14
18 files changed, 911 insertions, 1462 deletions
diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index e4b33bdf8c..69b8fe41ec 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -33,59 +33,524 @@
*/
#include "sword25/fmv/movieplayer.h"
+#include "sword25/fmv/oggtheora/oggstate.h"
+#include "sword25/fmv/oggtheora/oggstreamstate.h"
+#include "sword25/fmv/oggtheora/vorbisstate.h"
+#include "sword25/fmv/oggtheora/yuvtorgba.h"
+#include "sword25/gfx/graphicengine.h"
+#include "sword25/gfx/panel.h"
+#include "sword25/kernel/kernel.h"
+#include "sword25/sfx/soundengine.h"
+
+#define BS_LOG_PREFIX "MOVIEPLAYER"
+
+#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
namespace Sword25 {
-#define BS_LOG_PREFIX "MOVIEPLAYER"
+const int MAX_FRAMES_PER_TICK = 10;
+const int READ_BLOCK_SIZE = 1024 * 40;
+const float MAX_AUDIO_BUFFER_LENGTH = 1.0f;
Service *OggTheora_CreateObject(Kernel *pKernel) {
return new MoviePlayer(pKernel);
}
-MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel) {
+// -----------------------------------------------------------------------------
+
+inline bool VerifyRequiredServiceAvailability() {
+ char *RequiredServices[] = { "gfx", "sfx", "package" };
+ for (size_t i = 0; i < sizeof(RequiredServices) / sizeof(RequiredServices[0]); ++i) {
+ if (!Kernel::GetInstance()->GetService(RequiredServices[i])) {
+ BS_LOG_ERRORLN("Required service \"%s\" is not active.", RequiredServices[i]);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ParseStreamHeaders(Common::SharedPtr<MovieFile> &File,
+ Common::SharedPtr<OggState> &OggState,
+ Common::SharedPtr<OggStreamState> &TheoraStreamState,
+ Common::SharedPtr<OggStreamState> &VorbisStreamState,
+ Common::SharedPtr<TheoraState> &TheoraState,
+ Common::SharedPtr<VorbisState> &VorbisState,
+ bool &TheoraPresent,
+ bool &VorbisPresent,
+ const Common::String &Filename) {
+ TheoraPresent = false;
+ VorbisPresent = false;
+
+ // Ogg file open; parse the headers
+ // Only interested in Vorbis/Theora streams
+ bool FinishedHeaderParsing = false;
+ while (!FinishedHeaderParsing) {
+ if (File->BufferData(*OggState.get()) == 0) return false;
+
+ ogg_page Page;
+ while(OggState->SyncPageout(&Page) > 0) {
+ // is this a mandated initial header? If not, stop parsing
+ if (!ogg_page_bos(&Page)) {
+ // don't leak the page; get it into the appropriate stream
+ if (TheoraPresent) TheoraStreamState->PageIn(&Page);
+ if (VorbisPresent) VorbisStreamState->PageIn(&Page);
+
+ FinishedHeaderParsing = true;
+ break;
+ }
+
+ Common::SharedPtr<OggStreamState> streamState(new OggStreamState(ogg_page_serialno(&Page)));
+
+ streamState->PageIn(&Page);
+
+ ogg_packet Packet;
+ streamState->PacketOut(&Packet);
+
+ // identify the codec: try theora
+ if (!TheoraPresent && TheoraState->DecodeHeader(&Packet) >= 0) {
+ // it is theora
+ TheoraStreamState = streamState;
+ TheoraPresent = true;
+ } else if (!VorbisPresent && VorbisState->SynthesisHeaderIn(&Packet) >=0) {
+ // it is vorbis
+ VorbisStreamState = streamState;
+ VorbisPresent = true;
+ }
+ }
+ // fall through to non-bos page parsing
+ }
+
+ // we're expecting more header packets.
+ unsigned int TheoraPacketsRead = TheoraPresent ? 1 : 0;
+ unsigned int VorbisPacketsRead = VorbisPresent ? 1 : 0;
+ while ((TheoraPresent && TheoraPacketsRead < 3) || (VorbisPresent && VorbisPacketsRead < 3)) {
+ int ret;
+ ogg_packet Packet;
+
+ // look for further theora headers
+ while(TheoraPresent && (TheoraPacketsRead < 3) && (ret = TheoraStreamState->PacketOut(&Packet))) {
+ if (ret < 0 || TheoraState->DecodeHeader(&Packet)) {
+ BS_LOG_ERRORLN("Error parsing Theora stream headers. Stream is possibly corrupt. (%s)", Filename.c_str());
+ return false;
+ }
+
+ ++TheoraPacketsRead;
+ if (TheoraPacketsRead == 3) break;
+ }
+
+ // look for more vorbis header packets
+ while(VorbisPresent && (VorbisPacketsRead < 3) && (ret = VorbisStreamState->PacketOut(&Packet))) {
+ if (ret < 0 || VorbisState->SynthesisHeaderIn(&Packet)) {
+ BS_LOG_ERRORLN("Error parsing Vorbis stream headers. Stream is possibly corrupt. (%s)", Filename.c_str());
+ return false;
+ }
+
+ ++VorbisPacketsRead;
+ if (VorbisPacketsRead == 3) break;
+ }
+
+ // The header pages/packets will arrive before anything else we care about, or the stream is not obeying spec
+ ogg_page Page;
+ if (OggState->SyncPageout(&Page) > 0) {
+ // demux into the appropriate stream
+ if (TheoraPresent) TheoraStreamState->PageIn(&Page);
+ if (VorbisPresent) VorbisStreamState->PageIn(&Page);
+ } else {
+ if (File->BufferData(*OggState.get()) == 0) {
+ BS_LOG_ERRORLN("End of file while searching for codec headers. (%s)", Filename.c_str());
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel),
+ m_SoundHandle(0), _pixels(NULL) {
if (!_RegisterScriptBindings())
BS_LOG_ERRORLN("Script bindings could not be registered.");
else
BS_LOGLN("Script bindings registered.");
+
+ UnloadMovie();
+}
+
+MoviePlayer::~MoviePlayer() {
+ delete _pixels;
}
bool MoviePlayer::LoadMovie(const Common::String &Filename, unsigned int Z) {
+ if (!VerifyRequiredServiceAvailability()) return false;
+
+ UnloadMovie();
+
+ // Alle Objekte die in dieser Funktion erzeugt werden, werden in zunächst lokalen Auto-Pointern gehalten.
+ // Bei erfolgreicher Beendigung dieser Funktion werden sie den objektlokalen Auto-Pointern zugewiesen.
+ // So wird sichergestellt, dass sie korrekt deinitialisiert werden, wenn in dieser Funktion ein Fehler auftritt, denn beim Zerstören der
+ // lokalen Auto-Pointer werden die entsprechenden Destruktoren aufgerufen.
+
+ // Film laden
+ // Für Filmdateien wird das Cachingsystem nicht benutzt, da Filme in der Regel nur ein Mal abgespielt werden.
+ bool Success = false;
+ Common::SharedPtr<MovieFile> File(new MovieFile(Filename, READ_BLOCK_SIZE, Success));
+ if (!Success) return false;
+
+ // States erzeugen für Ogg, Vorbis und Theora, sowie die Ogg und Theora Streams
+ Common::SharedPtr<OggState> OggState(new OggState());
+ Common::SharedPtr<VorbisState> VorbisState(new VorbisState());
+ Common::SharedPtr<TheoraState> TheoraState(new TheoraState());
+
+ Common::SharedPtr<OggStreamState> TheoraStreamState;
+ Common::SharedPtr<OggStreamState> VorbisStreamState;
+
+ if (!ParseStreamHeaders(File, OggState, TheoraStreamState, VorbisStreamState, TheoraState, VorbisState, m_TheoraPresent, m_VorbisPresent, Filename)) return false;
+
+ // Theora-Decoder Initialisieren
+ if (m_TheoraPresent) {
+ TheoraState->DecodeInit();
+
+ const theora_info & TheoraInfo = TheoraState->GetInfo();
+
+ if (TheoraInfo.pixelformat != OC_PF_444 &&
+ TheoraInfo.pixelformat != OC_PF_422 &&
+ TheoraInfo.pixelformat != OC_PF_420) {
+ BS_LOG_ERRORLN("Unknown chroma sampling. (%s)", Filename.c_str());
+ return false;
+ }
+
+ // Ausgabebitmap erstellen
+ GraphicEngine *pGfx = Kernel::GetInstance()->GetGfx();
+ m_OutputBitmap = pGfx->GetMainPanel()->AddDynamicBitmap(TheoraInfo.frame_width, TheoraInfo.frame_height);
+ if (!m_OutputBitmap.IsValid()) {
+ BS_LOG_ERRORLN("Output bitmap for movie playback could not be created.");
+ return false;
+ }
+
+ // Skalierung des Ausgabebitmaps berechnen, so dass es möglichst viel Bildschirmfläche einnimmt.
+ float ScreenToVideoWidth = (float) pGfx->GetDisplayWidth() / (float) m_OutputBitmap->GetWidth();
+ float ScreenToVideoHeight = (float) pGfx->GetDisplayHeight() / (float) m_OutputBitmap->GetHeight();
+ float ScaleFactor = MIN(ScreenToVideoWidth, ScreenToVideoHeight);
+ if (abs(ScaleFactor - 1.0f) < FLT_EPSILON) ScaleFactor = 1.0f;
+ m_OutputBitmap->SetScaleFactor(ScaleFactor);
+
+ // Z-Wert setzen
+ m_OutputBitmap->SetZ(Z);
+
+ // Ausgabebitmap auf dem Bildschirm zentrieren
+ m_OutputBitmap->SetX((pGfx->GetDisplayWidth() - m_OutputBitmap->GetWidth()) / 2);
+ m_OutputBitmap->SetY((pGfx->GetDisplayHeight() - m_OutputBitmap->GetHeight()) / 2);
+
+ // Buffer für die Pixeldaten erstellen
+ delete _pixels;
+ _pixelsSize = TheoraInfo.width * TheoraInfo.height * 4;
+ _pixels = (byte *)malloc(_pixelsSize);
+ assert(_pixels);
+
+ m_VideoEnded = false;
+ }
+
+ // Vorbis-Decoder initialisieren
+ if (m_VorbisPresent) {
+ VorbisState->SynthesisInit();
+ VorbisState->BlockInit();
+ m_AudioBuffer = Common::SharedPtr<AudioBuffer>(new AudioBuffer());
+
+ m_AudioEnded = false;
+ }
+
+ // Keine Kopie, überträgt Besitz der erzeugten Objekte von der Funktion auf das Objekt.
+ m_File = File;
+ m_OggState = OggState;
+ m_TheoraState = TheoraState;
+ m_TheoraStreamState = TheoraStreamState;
+ m_VorbisState = VorbisState;
+ m_VorbisStreamState = VorbisStreamState;
+ m_MovieLoaded = true;
+ m_Timer = 0;
+
return true;
}
bool MoviePlayer::UnloadMovie() {
+ m_MovieLoaded = false;
+ m_Paused = true;
+
+ m_VorbisStreamState.reset();
+ m_VorbisPresent = false;
+ m_VorbisState.reset();
+ if (m_SoundHandle) {
+ Kernel::GetInstance()->GetSfx()->StopSound(m_SoundHandle);
+ m_SoundHandle = 0;
+ }
+ m_AudioEnded = true;
+ m_AudioBuffer.reset();
+
+ m_TheoraStreamState.reset();
+ m_TheoraPresent = false;
+ m_TheoraState.reset();
+ m_VideoEnded = true;
+
+ m_OggState.reset();
+
+ m_File.reset();
+
+ m_StartTime = 0;
+ m_LastFrameTime = 0;
+ m_Timer = 0.0f;
+
+// Common::Array<unsigned char>().swap(m_Pixels);
+ m_OutputBitmap.Erase();
+
return true;
}
bool MoviePlayer::Play() {
- return true;
+ if (m_MovieLoaded) {
+ if (m_Paused) {
+ if (m_SoundHandle) {
+ SoundEngine * SfxPtr = Kernel::GetInstance()->GetSfx();
+ SfxPtr->ResumeSound(m_SoundHandle);
+ }
+ m_Paused = false;
+ }
+
+ return true;
+ } else {
+ BS_LOG_WARNINGLN("Cannot play movie, when no movie is loaded.");
+ return false;
+ }
}
bool MoviePlayer::Pause() {
- return true;
+ if (m_MovieLoaded) {
+ if (m_SoundHandle) {
+ SoundEngine *SfxPtr = Kernel::GetInstance()->GetSfx();
+ SfxPtr->PauseSound(m_SoundHandle);
+ }
+
+ m_Paused = true;
+ return true;
+ } else {
+ BS_LOG_WARNINGLN("Cannot pause movie, when no movie is loaded.");
+ return false;
+ }
}
void MoviePlayer::Update() {
+ if (m_AudioEnded && m_VideoEnded) {
+ m_Paused = true;
+
+ // Falls der Sound noch läuft, muss er jetzt beendet werden.
+ if (m_SoundHandle) {
+ SoundEngine *SfxPtr = Kernel::GetInstance()->GetSfx();
+ SfxPtr->StopSound(m_SoundHandle);
+ m_SoundHandle = 0;
+ }
+ }
+
+ if (m_Paused) return;
+
+ // Timer aktualisieren.
+ // Wird nur genutzt, wenn keine Audiodaten vorhanden sind.
+ m_Timer += Kernel::GetInstance()->GetGfx()->GetSecondaryFrameDuration();
+
+ // Audiodaten dekodieren
+ if (m_VorbisPresent && !m_AudioEnded) DecodeVorbis();
+
+
+ // Videodaten dekodieren
+ if (m_TheoraPresent && !m_VideoEnded) {
+ bool Result = DecodeTheora();
+
+ if (Result) {
+ // YUV Framebuffer holen
+ yuv_buffer YUVBuffer;
+ m_TheoraState->DecodeYUVOut(&YUVBuffer);
+
+ // YUV Bilddaten nach RGBA konvertieren
+ BS_YUVtoRGBA::YUVtoRGBA(YUVBuffer, m_TheoraState->GetInfo(), _pixels, _pixelsSize);
+
+ // RGBA Bilddaten auf das Ausgabebild kopieren, dabei die Postion des Theoraframes innerhalb des dekodierten Frames beachten.
+ const theora_info &TheoraInfo = m_TheoraState->GetInfo();
+ m_OutputBitmap->SetContent(_pixels, _pixelsSize,
+ (TheoraInfo.offset_x + TheoraInfo.width * TheoraInfo.offset_y) * 4,
+ (TheoraInfo.width - TheoraInfo.frame_width) * 4);
+ }
+ }
}
bool MoviePlayer::IsMovieLoaded() {
- return true;
+ return m_MovieLoaded;
}
bool MoviePlayer::IsPaused() {
- return true;
+ return m_Paused;
}
float MoviePlayer::GetScaleFactor() {
- return 1.0f;
+ if (m_MovieLoaded)
+ return m_OutputBitmap->GetScaleFactorX();
+ else
+ return 0;
}
void MoviePlayer::SetScaleFactor(float ScaleFactor) {
+ if (m_MovieLoaded) {
+ m_OutputBitmap->SetScaleFactor(ScaleFactor);
+
+ // Ausgabebitmap auf dem Bildschirm zentrieren
+ GraphicEngine *gfxPtr = Kernel::GetInstance()->GetGfx();
+ m_OutputBitmap->SetX((gfxPtr->GetDisplayWidth() - m_OutputBitmap->GetWidth()) / 2);
+ m_OutputBitmap->SetY((gfxPtr->GetDisplayHeight() - m_OutputBitmap->GetHeight()) / 2);
+ }
}
double MoviePlayer::GetTime() {
- return 1.0;
+ if (m_VorbisPresent) {
+ if (m_SoundHandle) {
+ float time = Kernel::GetInstance()->GetSfx()->GetSoundTime(m_SoundHandle);
+ return time;
+ } else
+ return 0.0f;
+ } else
+ return m_Timer;
}
+// -----------------------------------------------------------------------------
+
+bool MoviePlayer::DecodeTheora() {
+ double MovieTime = GetTime();
+
+ // Check if this frame time has not passed yet. If the frame is late we need
+ // to decode additonal ones and keep looping, since theora at this stage
+ // needs to decode all frames (due to keyframing)
+ // Getting the current time once at the beginning of the function rather than
+ // every time at the beginning of the loop produces the smoothest framerate
+
+ unsigned int FramesDecoded = 0;
+ bool FrameReady = false;
+ while (m_TheoraState->GranuleTime() < MovieTime) {
+ // theora is one in, one out...
+ ogg_packet Packet;
+ if (m_TheoraStreamState->PacketOut(&Packet) > 0) {
+ if (FramesDecoded < MAX_FRAMES_PER_TICK || Packet.granulepos >= MovieTime) {
+ m_TheoraState->DecodePacketIn(&Packet);
+ FrameReady = true;
+ ++FramesDecoded;
+ }
+ } else {
+ if (m_TheoraStreamState->GetPageBufferSize() > 0)
+ m_TheoraStreamState->PageInBufferedPage();
+ else {
+ if (m_File->IsEOF()) {
+ m_VideoEnded = true;
+ break;
+ } else
+ ReadData();
+ }
+ }
+ }
+ m_LastFrameTime = MovieTime;
+
+ return FrameReady;
+}
+
+void MoviePlayer::DecodeVorbis() {
+ // Vorbis-Stream Infos holen.
+ const vorbis_info &Info = m_VorbisState->GetInfo();
+
+ // Maximalgröße des Audiobuffers berechnen.
+ size_t MaxAudioBufferSamples = static_cast<size_t>(Info.channels * Info.rate * MAX_AUDIO_BUFFER_LENGTH);
+
+ // Zwischenspeicher für die Samples.
+ Common::Array<signed short> Samples;
+
+ // Audiobuffer bis zur Maximalgröße füllen, wenn möglich.
+ while (m_AudioBuffer->Size() < MaxAudioBufferSamples) {
+ // Vorhandene Audiodaten auslesen
+ float **PCM;
+ int SampleCount = m_VorbisState->SynthesisPCMout(&PCM);
+
+ // Wenn Audiodaten gelesen werden konnten, werden diese in 16-Bit Sample umgewandelt und in den Audiobuffer geschrieben.
+ if (SampleCount > 0) {
+ // Im Samplezwischenspeicher leeren und genügend Platz für die kommenden Samples reservieren.
+ Samples.reserve(SampleCount);
+ Samples.clear();
+
+ // Samples konvertieren und in die Samplezwischenspeicher schreiben.
+ for (int i = 0; i < SampleCount; ++i) {
+ for (int j = 0; j < Info.channels; ++j) {
+ int SampleValue = static_cast<int>(PCM[j][i] * 32767.0f);
+ Samples.push_back(CLIP(SampleValue, -32700, 32700));
+ }
+ }
+
+ // Daten aus dem Samplezwischenspeicher in den Audiobuffer schreiben.
+ m_AudioBuffer->Push(&Samples[0], Samples.size());
+
+ // Vorbis mitteilen, dass wir alle Samples gelesen haben.
+ m_VorbisState->SynthesisRead(SampleCount);
+ } else {
+ // Wir konnten, keine Audiodaten auslesen, versuchen ein neues Paket zu dekodieren.
+ ogg_packet Packet;
+ if (m_VorbisStreamState->PacketOut(&Packet) > 0) {
+ if (m_VorbisState->Synthesis(&Packet) == 0) m_VorbisState->SynthesisBlockIn();
+ } else {
+ // Gepufferte Daten in den Stream einfügen.
+ if (m_VorbisStreamState->GetPageBufferSize() > 0)
+ m_VorbisStreamState->PageInBufferedPage();
+ else {
+ // Nicht genug Daten vorhanden. Wenn die Datei leer ist und bereits alle Audiodaten gelesen wurden, ist der Audiostream am Ende.
+ // Ansonsten Daten nachladen.
+ if (m_File->IsEOF()) {
+ if (m_AudioBuffer->Size() == 0) {
+ m_AudioEnded = true;
+ }
+
+ break;
+ } else
+ ReadData();
+ }
+ }
+ }
+ }
+
+ // Soundkanal abspielen, wenn er noch nicht spielt und Audiodaten vorhanden sind.
+ if (m_SoundHandle == 0 && m_AudioBuffer->Size()) {
+ SoundEngine *SfxPtr = Kernel::GetInstance()->GetSfx();
+ m_SoundHandle = SfxPtr->PlayDynamicSoundEx(&DynamicSoundCallBack, this, SoundEngine::SFX, Info.rate, 16, Info.channels);
+ }
+}
+
+void MoviePlayer::ReadData() {
+ if (!m_File->IsEOF()) m_File->BufferData(*m_OggState.get());
+
+ ogg_page Page;
+ while(m_OggState->SyncPageout(&Page) > 0) {
+ if (m_TheoraPresent) m_TheoraStreamState->BufferPage(&Page);
+ if (m_VorbisPresent) m_VorbisStreamState->BufferPage(&Page);
+ }
+}
+
+void MoviePlayer::DynamicSoundCallBack(void *UserData, void *Data, unsigned int DataLength) {
+ MoviePlayer &t = *reinterpret_cast<MoviePlayer *>(UserData);
+
+ signed short *Buffer = reinterpret_cast<signed short *>(Data);
+
+ // Audiodaten in den Soundbuffer schreiben.
+ DataLength -= t.m_AudioBuffer->Pop(Buffer, DataLength / 2) * 2;
+
+ // Falls nicht genug Audiodaten vorhanden waren, wird der Rest mit Stille überschrieben.
+ if (DataLength) {
+ char *ByteBuffer = reinterpret_cast<char *>(Buffer);
+ while (DataLength--) {
+ *ByteBuffer++ = 0;
+ }
+ }
+}
} // End of namespace Sword25
diff --git a/engines/sword25/fmv/movieplayer.h b/engines/sword25/fmv/movieplayer.h
index 3404eaacd8..46890991d9 100644
--- a/engines/sword25/fmv/movieplayer.h
+++ b/engines/sword25/fmv/movieplayer.h
@@ -39,11 +39,38 @@
// Includes
// -----------------------------------------------------------------------------
+#include "common/ptr.h"
#include "sword25/kernel/common.h"
#include "sword25/kernel/service.h"
+#include "sword25/fmv/oggtheora/audiobuffer.h"
+#include "sword25/fmv/oggtheora/moviefile.h"
+#include "sword25/fmv/oggtheora/oggstreamstate.h"
+#include "sword25/fmv/oggtheora/theorastate.h"
+#include "sword25/fmv/oggtheora/vorbisstate.h"
+#include "sword25/gfx/bitmap.h"
namespace Sword25 {
+/* FIXME: Audio stubs
+class OggStreamState {
+public:
+ OggStreamState(int v) {}
+ void PageIn(void *v) {}
+ bool PacketOut(void *v) { return true; }
+};
+class VorbisState {
+public:
+ void BlockInit() {}
+ void SynthesisInit() {}
+ bool SynthesisHeaderIn(void *v) { return false; }
+};
+class OggState {
+public:
+ bool SyncPageout(void *v) { return false; }
+ char *SyncBuffer(int v) { return NULL; }
+};
+*/
+
// -----------------------------------------------------------------------------
// Class definitions
// -----------------------------------------------------------------------------
@@ -55,10 +82,10 @@ public:
// -----------------------------------------------------------------------------
MoviePlayer(Kernel *pKernel);
- ~MoviePlayer() {};
+ ~MoviePlayer();
// -----------------------------------------------------------------------------
- // Abstract interface must be implemented by each Movie Player
+ // Player interface must be implemented by a Movie Player
// -----------------------------------------------------------------------------
/**
@@ -137,9 +164,44 @@ public:
* @remark This method can only be called when IsMovieLoaded() returns true.
*/
double GetTime();
-
private:
+ // -----------------------------------------------------------------------------
+ // Internal support methods
+ // -----------------------------------------------------------------------------
bool _RegisterScriptBindings();
+ bool DecodeTheora();
+ void DecodeVorbis();
+ void ReadData();
+ static void DynamicSoundCallBack(void *UserData, void *Data, unsigned int DataLength);
+
+private:
+ bool m_MovieLoaded;
+ bool m_Paused;
+
+ Common::SharedPtr<OggStreamState> m_VorbisStreamState;
+ bool m_VorbisPresent;
+ Common::SharedPtr<VorbisState> m_VorbisState;
+ unsigned int m_SoundHandle;
+ bool m_AudioEnded;
+ Common::SharedPtr<AudioBuffer> m_AudioBuffer;
+
+ Common::SharedPtr<OggStreamState> m_TheoraStreamState;
+ bool m_TheoraPresent;
+ Common::SharedPtr<TheoraState> m_TheoraState;
+ bool m_VideoEnded;
+
+ Common::SharedPtr<OggState> m_OggState;
+
+ Common::SharedPtr<MovieFile> m_File;
+
+ uint64_t m_StartTime;
+ double m_LastFrameTime;
+
+ float m_Timer;
+
+ byte * _pixels;
+ int _pixelsSize;
+ RenderObjectPtr<Bitmap> m_OutputBitmap;
};
} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/audiobuffer.cpp b/engines/sword25/fmv/oggtheora/audiobuffer.cpp
index f9e6667ce5..1e5828f41b 100644
--- a/engines/sword25/fmv/oggtheora/audiobuffer.cpp
+++ b/engines/sword25/fmv/oggtheora/audiobuffer.cpp
@@ -37,72 +37,46 @@
// -----------------------------------------------------------------------------
#include "sword25/fmv/oggtheora/audiobuffer.h"
-#include <windows.h>
-#include <queue>
-
-using namespace std;
// -----------------------------------------------------------------------------
-struct BS_AudioBuffer::Impl
-{
- CRITICAL_SECTION CS;
- queue<signed short> Buffer;
-};
+namespace Sword25 {
// -----------------------------------------------------------------------------
-BS_AudioBuffer::BS_AudioBuffer() : t(new Impl())
-{
- InitializeCriticalSection(&t->CS);
+AudioBuffer::AudioBuffer() {
}
// -----------------------------------------------------------------------------
-BS_AudioBuffer::~BS_AudioBuffer()
-{
- DeleteCriticalSection(&t->CS);
-
- delete t;
+AudioBuffer::~AudioBuffer() {
}
// -----------------------------------------------------------------------------
-void BS_AudioBuffer::Push(signed short * SamplePtr, unsigned int SampleCount)
-{
- EnterCriticalSection(&t->CS);
-
- signed short * SampleEndPtr = SamplePtr + SampleCount;
- while (SamplePtr != SampleEndPtr) t->Buffer.push(*SamplePtr++);
-
- LeaveCriticalSection(&t->CS);
+void AudioBuffer::Push(signed short *SamplePtr, unsigned int SampleCount) {
+ signed short *SampleEndPtr = SamplePtr + SampleCount;
+ while (SamplePtr != SampleEndPtr) _buffer.push(*SamplePtr++);
}
// -----------------------------------------------------------------------------
-unsigned int BS_AudioBuffer::Pop(signed short * SamplePtr, unsigned int SampleCount)
-{
- EnterCriticalSection(&t->CS);
-
+unsigned int AudioBuffer::Pop(signed short *SamplePtr, unsigned int SampleCount) {
unsigned int i = 0;
- for (; i < SampleCount && !t->Buffer.empty(); ++i)
- {
- SamplePtr[i] = t->Buffer.front();
- t->Buffer.pop();
+ for (; i < SampleCount && !_buffer.empty(); ++i) {
+ SamplePtr[i] = _buffer.front();
+ _buffer.pop();
}
- LeaveCriticalSection(&t->CS);
-
return i;
}
// -----------------------------------------------------------------------------
-unsigned int BS_AudioBuffer::Size() const
-{
- EnterCriticalSection(&t->CS);
- unsigned int result = t->Buffer.size();
- LeaveCriticalSection(&t->CS);
+unsigned int AudioBuffer::Size() const {
+ unsigned int result = _buffer.size();
return result;
}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/audiobuffer.h b/engines/sword25/fmv/oggtheora/audiobuffer.h
index 0b4233bc4e..fad227a2bc 100644
--- a/engines/sword25/fmv/oggtheora/audiobuffer.h
+++ b/engines/sword25/fmv/oggtheora/audiobuffer.h
@@ -39,30 +39,32 @@
// Includes
// -----------------------------------------------------------------------------
+#include "common/queue.h"
#include "sword25/kernel/common.h"
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-// Klassendefinition
+// Class definitions
// -----------------------------------------------------------------------------
-class BS_AudioBuffer
-{
+class AudioBuffer {
public:
- BS_AudioBuffer();
- virtual ~BS_AudioBuffer();
+ AudioBuffer();
+ virtual ~AudioBuffer();
- void Push(signed short * SamplePtr, unsigned int SampleCount);
- unsigned int Pop(signed short * SamplePtr, unsigned int SampleCount);
+ void Push(signed short *SamplePtr, unsigned int SampleCount);
+ unsigned int Pop(signed short *SamplePtr, unsigned int SampleCount);
unsigned int Size() const;
private:
- // PIMPL Pattern
- struct Impl;
- Impl * t;
+ Common::Queue<unsigned short> _buffer;
// Kopie verbieten
- BS_AudioBuffer(const BS_AudioBuffer &);
- const BS_AudioBuffer & operator=(const BS_AudioBuffer &);
+ AudioBuffer(const AudioBuffer &);
+ const AudioBuffer & operator=(const AudioBuffer &);
};
+} // End of namespace Sword25
+
#endif
diff --git a/engines/sword25/fmv/oggtheora/moviefile.cpp b/engines/sword25/fmv/oggtheora/moviefile.cpp
index b764ab2d22..33c214a1c2 100644
--- a/engines/sword25/fmv/oggtheora/moviefile.cpp
+++ b/engines/sword25/fmv/oggtheora/moviefile.cpp
@@ -47,42 +47,37 @@
#include "sword25/fmv/oggtheora/oggstate.h"
#include "sword25/fmv/oggtheora/moviefile.h"
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-BS_MovieFile::BS_MovieFile(const std::string & Filename, unsigned int ReadBlockSize, bool & Success) :
- m_Data(0), m_Size(0), m_ReadPos(0), m_ReadBlockSize(ReadBlockSize)
-{
- m_Data = reinterpret_cast<char *>(BS_Kernel::GetInstance()->GetPackage()->GetFile(Filename, &m_Size));
- if (!m_Data)
- {
+MovieFile::MovieFile(const Common::String &Filename, unsigned int ReadBlockSize, bool &Success) :
+ m_Data(0), m_Size(0), m_ReadPos(0), m_ReadBlockSize(ReadBlockSize) {
+ m_Data = reinterpret_cast<char *>(Kernel::GetInstance()->GetPackage()->GetFile(Filename, &m_Size));
+ if (!m_Data) {
BS_LOG_ERRORLN("Could not load movie file \"%s\".", Filename.c_str());
Success = false;
- }
- else
+ } else
Success = true;
}
// -----------------------------------------------------------------------------
-BS_MovieFile::~BS_MovieFile()
-{
+MovieFile::~MovieFile() {
if (m_Data) delete [] m_Data;
}
// -----------------------------------------------------------------------------
-int BS_MovieFile::BufferData(BS_OggState & OggState)
-{
- if (!m_Data || !m_Size || m_ReadPos >= m_Size)
- {
+int MovieFile::BufferData(OggState &OggState) {
+ if (!m_Data || !m_Size || m_ReadPos >= m_Size) {
BS_LOG_ERRORLN("Tried to read past the movie buffer's end.");
return 0;
}
// just grab some more compressed bitstream and sync it for page extraction
- char * Buffer = OggState.SyncBuffer(m_ReadBlockSize);
- if (!Buffer)
- {
+ char *Buffer = OggState.SyncBuffer(m_ReadBlockSize);
+ if (!Buffer) {
BS_LOG_ERRORLN("ogg_sync_buffer() failed.");
return 0;
}
@@ -99,7 +94,8 @@ int BS_MovieFile::BufferData(BS_OggState & OggState)
// -----------------------------------------------------------------------------
-bool BS_MovieFile::IsEOF() const
-{
+bool MovieFile::IsEOF() const {
return m_ReadPos >= m_Size;
}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/moviefile.h b/engines/sword25/fmv/oggtheora/moviefile.h
index 5aa0ef5617..bdae585d73 100644
--- a/engines/sword25/fmv/oggtheora/moviefile.h
+++ b/engines/sword25/fmv/oggtheora/moviefile.h
@@ -41,25 +41,22 @@
#include "sword25/kernel/common.h"
-#include "sword25/kernel/memlog_off.h"
-#include <string>
-#include "sword25/kernel/memlog_on.h"
+namespace Sword25 {
// -----------------------------------------------------------------------------
-class BS_OggState;
+class OggState;
// -----------------------------------------------------------------------------
// Klassendefinition
// -----------------------------------------------------------------------------
-class BS_MovieFile
-{
+class MovieFile {
public:
- BS_MovieFile(const std::string & Filename, unsigned int ReadBlockSize, bool & Success);
- virtual ~BS_MovieFile();
+ MovieFile(const Common::String &Filename, unsigned int ReadBlockSize, bool &Success);
+ virtual ~MovieFile();
- int BufferData(BS_OggState & OggState);
+ int BufferData(OggState &OggState);
bool IsEOF() const;
private:
@@ -69,4 +66,6 @@ private:
unsigned int m_ReadBlockSize;
};
+} // End of namespace Sword25
+
#endif
diff --git a/engines/sword25/fmv/oggtheora/oggstate.cpp b/engines/sword25/fmv/oggtheora/oggstate.cpp
index 11788ce53b..750fe382d4 100644
--- a/engines/sword25/fmv/oggtheora/oggstate.cpp
+++ b/engines/sword25/fmv/oggtheora/oggstate.cpp
@@ -38,37 +38,36 @@
#include "sword25/fmv/oggtheora/oggstate.h"
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-BS_OggState::BS_OggState()
-{
+OggState::OggState() {
ogg_sync_init(&m_SyncState);
}
// -----------------------------------------------------------------------------
-BS_OggState::~BS_OggState()
-{
+OggState::~OggState() {
ogg_sync_clear(&m_SyncState);
}
// -----------------------------------------------------------------------------
-int BS_OggState::SyncPageout(ogg_page * OggPage)
-{
+int OggState::SyncPageout(ogg_page *OggPage) {
return ogg_sync_pageout(&m_SyncState, OggPage);
}
// -----------------------------------------------------------------------------
-char * BS_OggState::SyncBuffer(long Size)
-{
+char *OggState::SyncBuffer(long Size) {
return ogg_sync_buffer(&m_SyncState, Size);
}
// -----------------------------------------------------------------------------
-int BS_OggState::SyncWrote(long Bytes)
-{
+int OggState::SyncWrote(long Bytes) {
return ogg_sync_wrote(&m_SyncState, Bytes);
}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/oggstate.h b/engines/sword25/fmv/oggtheora/oggstate.h
index 1c25ca5e3a..7df178b681 100644
--- a/engines/sword25/fmv/oggtheora/oggstate.h
+++ b/engines/sword25/fmv/oggtheora/oggstate.h
@@ -40,39 +40,37 @@
// -----------------------------------------------------------------------------
#include "sword25/kernel/common.h"
-#include "ogg/ogg.h"
-// XXX
-#include <iostream>
-// XXX
+#include <ogg/ogg.h>
+
+namespace Sword25 {
// -----------------------------------------------------------------------------
-// Klassendefinition
+// Class definitions
// -----------------------------------------------------------------------------
-class BS_OggState
-{
+class OggState {
public:
- BS_OggState();
- virtual ~BS_OggState();
+ OggState();
+ virtual ~OggState();
- int SyncPageout(ogg_page * OggPage);
+ int SyncPageout(ogg_page *OggPage);
char * SyncBuffer(long Size);
int SyncWrote(long Bytes);
// XXX
- void DumpInternals()
- {
- std::cout << "bodybytes: " << m_SyncState.bodybytes << std::endl;
- std::cout << "fill: " << m_SyncState.fill << std::endl;
- std::cout << "headerbytes: " << m_SyncState.headerbytes << std::endl;
- std::cout << "returned: " << m_SyncState.returned << std::endl;
- std::cout << "storage: " << m_SyncState.storage << std::endl;
- std::cout << "unsynched: " << m_SyncState.unsynced << std::endl;
- std::cout << std::endl;
+ void DumpInternals() {
+ warning("bodybytes: %d", m_SyncState.bodybytes);
+ warning("fill: %d", m_SyncState.fill);
+ warning("headerbytes: %d", m_SyncState.headerbytes );
+ warning("returned: %d", m_SyncState.returned );
+ warning("storage: %d", m_SyncState.storage );
+ warning("unsynched: %d", m_SyncState.unsynced );
}
// XXX
private:
ogg_sync_state m_SyncState;
};
+} // End of namespace Sword25
+
#endif
diff --git a/engines/sword25/fmv/oggtheora/oggstreamstate.cpp b/engines/sword25/fmv/oggtheora/oggstreamstate.cpp
index d787a96af2..70388cf2b1 100644
--- a/engines/sword25/fmv/oggtheora/oggstreamstate.cpp
+++ b/engines/sword25/fmv/oggtheora/oggstreamstate.cpp
@@ -38,22 +38,21 @@
#include "sword25/fmv/oggtheora/oggstreamstate.h"
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-BS_OggStreamState::BS_OggStreamState(int SerialNo)
-{
+OggStreamState::OggStreamState(int SerialNo) {
ogg_stream_init(&m_State, SerialNo);
}
// -----------------------------------------------------------------------------
-BS_OggStreamState::~BS_OggStreamState()
-{
+OggStreamState::~OggStreamState() {
ogg_stream_clear(&m_State);
// Alle gepufferten Pages löschen.
- while (!m_PageBuffer.empty())
- {
+ while (!m_PageBuffer.empty()) {
delete [] m_PageBuffer.front().header;
delete [] m_PageBuffer.front().body;
m_PageBuffer.pop();
@@ -62,24 +61,20 @@ BS_OggStreamState::~BS_OggStreamState()
// -----------------------------------------------------------------------------
-int BS_OggStreamState::PageIn(ogg_page * PagePtr)
-{
+int OggStreamState::PageIn(ogg_page *PagePtr) {
return ogg_stream_pagein(&m_State, PagePtr);
}
// -----------------------------------------------------------------------------
-int BS_OggStreamState::PacketOut(ogg_packet * PacketPtr)
-{
+int OggStreamState::PacketOut(ogg_packet *PacketPtr) {
return ogg_stream_packetout(&m_State, PacketPtr);
}
// -----------------------------------------------------------------------------
-void BS_OggStreamState::BufferPage(ogg_page * PagePtr)
-{
- if (PageBelongsToStream(PagePtr))
- {
+void OggStreamState::BufferPage(ogg_page *PagePtr) {
+ if (PageBelongsToStream(PagePtr)) {
// Pages können nicht direkt gespeichert werden, da die Pointer im Laufe der Zeit ungültig werden.
// Daher wird an dieser Stelle eine tiefe Kopie der Page im erzeugt und im Pagebuffer angelegt.
ogg_page PageCopy;
@@ -96,10 +91,8 @@ void BS_OggStreamState::BufferPage(ogg_page * PagePtr)
// -----------------------------------------------------------------------------
-int BS_OggStreamState::PageInBufferedPage()
-{
- if (GetPageBufferSize() > 0)
- {
+int OggStreamState::PageInBufferedPage() {
+ if (GetPageBufferSize() > 0) {
// Page in den Stream einfügen, löschen und aus dem Puffer entfernen.
int Result = PageIn(&m_PageBuffer.front());
delete [] m_PageBuffer.front().header;
@@ -113,21 +106,20 @@ int BS_OggStreamState::PageInBufferedPage()
// -----------------------------------------------------------------------------
-unsigned int BS_OggStreamState::GetPageBufferSize() const
-{
+unsigned int OggStreamState::GetPageBufferSize() const {
return m_PageBuffer.size();
}
// -----------------------------------------------------------------------------
-unsigned int BS_OggStreamState::GetUnprocessedBytes() const
-{
+unsigned int OggStreamState::GetUnprocessedBytes() const {
return m_State.body_fill - m_State.body_returned;
}
// -----------------------------------------------------------------------------
-bool BS_OggStreamState::PageBelongsToStream(ogg_page * PagePtr) const
-{
+bool OggStreamState::PageBelongsToStream(ogg_page *PagePtr) const {
return m_State.serialno == ogg_page_serialno(PagePtr);
}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/oggstreamstate.h b/engines/sword25/fmv/oggtheora/oggstreamstate.h
index 7e291bd107..3ed845c51d 100644
--- a/engines/sword25/fmv/oggtheora/oggstreamstate.h
+++ b/engines/sword25/fmv/oggtheora/oggstreamstate.h
@@ -40,50 +40,46 @@
// -----------------------------------------------------------------------------
#include "sword25/kernel/common.h"
-#include "ogg/ogg.h"
-#include <queue>
-// XXX
-#include <iostream>
-// XXX
+#include <ogg/ogg.h>
+#include "common/queue.h"
+
+namespace Sword25 {
// -----------------------------------------------------------------------------
-// Klassendefinition
+// Class definitions
// -----------------------------------------------------------------------------
-class BS_OggStreamState
-{
+class OggStreamState {
public:
- BS_OggStreamState(int SerialNo);
- virtual ~BS_OggStreamState();
+ OggStreamState(int SerialNo);
+ virtual ~OggStreamState();
- int PageIn(ogg_page * PagePtr);
- int PacketOut(ogg_packet * PacketPtr);
+ int PageIn(ogg_page *PagePtr);
+ int PacketOut(ogg_packet *PacketPtr);
- void BufferPage(ogg_page * PagePtr);
+ void BufferPage(ogg_page *PagePtr);
int PageInBufferedPage();
unsigned int GetPageBufferSize() const;
unsigned int GetUnprocessedBytes() const;
- bool PageBelongsToStream(ogg_page * PagePtr) const;
+ bool PageBelongsToStream(ogg_page *PagePtr) const;
// XXX
- void DumpInternals()
- {
- using namespace std;
-
- cout << "body_storage: " << m_State.body_storage << endl;
- cout << "body_fill: " << m_State.body_fill << endl;
- cout << "body_returned: " << m_State.body_returned << endl;
- cout << "lacing_storage: " << m_State.lacing_storage << endl;
- cout << "lacing_fill: " << m_State.lacing_fill << endl;
- cout << "lacing_returned: " << m_State.lacing_returned << endl;
- cout << endl;
+ void DumpInternals() {
+ warning("body_storage: %d", m_State.body_storage);
+ warning("body_fill: %d", m_State.body_fill);
+ warning("body_returned: %d", m_State.body_returned);
+ warning("lacing_storage: %d", m_State.lacing_storage);
+ warning("lacing_fill: %d", m_State.lacing_fill);
+ warning("lacing_returned: %d", m_State.lacing_returned);
}
// XXX
private:
ogg_stream_state m_State;
- std::queue<ogg_page> m_PageBuffer;
+ Common::Queue<ogg_page> m_PageBuffer;
};
+} // End of namespace Sword25
+
#endif
diff --git a/engines/sword25/fmv/oggtheora/oggtheora.cpp b/engines/sword25/fmv/oggtheora/oggtheora.cpp
deleted file mode 100644
index 9d6eaa0baf..0000000000
--- a/engines/sword25/fmv/oggtheora/oggtheora.cpp
+++ /dev/null
@@ -1,723 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/*
- * This code is based on Broken Sword 2.5 engine
- *
- * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
- *
- * Licensed under GNU GPL v2
- *
- */
-
-// The code in this file is based in part on code from the OggTheora Software
-// codec source released under the following terms:
-//
-// Copyright (C) 2002-2007 Xiph.org Foundation
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-// - Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//
-// - Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// - Neither the name of the Xiph.org Foundation nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
-// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// -----------------------------------------------------------------------------
-// Logging
-// -----------------------------------------------------------------------------
-
-#define BS_LOG_PREFIX "OGGTHEORA"
-
-// -----------------------------------------------------------------------------
-// Includes
-// -----------------------------------------------------------------------------
-
-#include "sword25/kernel/memlog_off.h"
-#include <algorithm>
-#include "sword25/kernel/memlog_on.h"
-#include <float.h>
-
-#include "sword25/package/packagemanager.h"
-#include "sword25/sfx/soundengine.h"
-#include "sword25/gfx/graphicengine.h"
-#include "sword25/gfx/panel.h"
-#include "sword25/fmv/oggtheora/oggtheora.h"
-#include "sword25/fmv/oggtheora/yuvtorgba.h"
-
-using namespace std;
-
-// -----------------------------------------------------------------------------
-// Konstanten und Hilfsfunktionen
-// -----------------------------------------------------------------------------
-
-namespace
-{
- // --------------------------------------------------------------------------
-
- const int MAX_FRAMES_PER_TICK = 10;
- const int READ_BLOCK_SIZE = 1024 * 40;
- const float MAX_AUDIO_BUFFER_LENGTH = 1.0f;
-
- // --------------------------------------------------------------------------
-
- template<typename T>
- inline T Clamp(T x, T low, T high)
- {
- return ((x > high) ? high : (( x < low) ? low : x));
- }
-}
-
-// -----------------------------------------------------------------------------
-// Konstruktion / Destruktion
-// -----------------------------------------------------------------------------
-
-BS_OggTheora::BS_OggTheora(BS_Kernel * pKernel) : BS_MoviePlayer(pKernel), m_SoundHandle(0)
-{
- UnloadMovie();
-}
-
-// -----------------------------------------------------------------------------
-
-BS_OggTheora::~BS_OggTheora()
-{
- UnloadMovie();
-}
-
-// -----------------------------------------------------------------------------
-
-BS_Service * BS_OggTheora_CreateObject(BS_Kernel* pKernel) { return new BS_OggTheora(pKernel); }
-
-// -----------------------------------------------------------------------------
-// BS_MoviePlayer Interface
-// -----------------------------------------------------------------------------
-
-
-// -----------------------------------------------------------------------------
-// LoadMovie() mit Hilfsfunktionen
-// -----------------------------------------------------------------------------
-
-namespace
-{
- inline bool VerifyRequiredServiceAvailability()
- {
- char * RequiredServices[] = { "gfx", "sfx", "package" };
- for (size_t i = 0; i < sizeof(RequiredServices) / sizeof(RequiredServices[0]); ++i)
- {
- if (!BS_Kernel::GetInstance()->GetService(RequiredServices[i]))
- {
- BS_LOG_ERRORLN("Required service \"%s\" is not active.", RequiredServices[i]);
- return false;
- }
- }
-
- return true;
- }
-
- // -------------------------------------------------------------------------
-
- bool ParseStreamHeaders(auto_ptr<BS_MovieFile> & File,
- auto_ptr<BS_OggState> & OggState,
- auto_ptr<BS_OggStreamState> & TheoraStreamState,
- auto_ptr<BS_OggStreamState> & VorbisStreamState,
- auto_ptr<BS_TheoraState> & TheoraState,
- auto_ptr<BS_VorbisState> & VorbisState,
- bool & TheoraPresent,
- bool & VorbisPresent,
- const std::string & Filename)
- {
- TheoraPresent = false;
- VorbisPresent = false;
-
- // Ogg file open; parse the headers
- // Only interested in Vorbis/Theora streams
- bool FinishedHeaderParsing = false;
- while (!FinishedHeaderParsing)
- {
- if (File->BufferData(*OggState.get()) == 0) return false;
-
- ogg_page Page;
- while(OggState->SyncPageout(&Page) > 0)
- {
- // is this a mandated initial header? If not, stop parsing
- if(!ogg_page_bos(&Page))
- {
- // don't leak the page; get it into the appropriate stream
- if (TheoraPresent) TheoraStreamState->PageIn(&Page);
- if (VorbisPresent) VorbisStreamState->PageIn(&Page);
-
- FinishedHeaderParsing = true;
- break;
- }
-
- auto_ptr<BS_OggStreamState> streamState(new BS_OggStreamState(ogg_page_serialno(&Page)));
-
- streamState->PageIn(&Page);
-
- ogg_packet Packet;
- streamState->PacketOut(&Packet);
-
- // identify the codec: try theora
- if(!TheoraPresent && TheoraState->DecodeHeader(&Packet) >= 0)
- {
- // it is theora
- TheoraStreamState = streamState;
- TheoraPresent = true;
- }
- else if(!VorbisPresent && VorbisState->SynthesisHeaderIn(&Packet) >=0)
- {
- // it is vorbis
- VorbisStreamState = streamState;
- VorbisPresent = true;
- }
- }
- // fall through to non-bos page parsing
- }
-
- // we're expecting more header packets.
- unsigned int TheoraPacketsRead = TheoraPresent ? 1 : 0;
- unsigned int VorbisPacketsRead = VorbisPresent ? 1 : 0;
- while((TheoraPresent && TheoraPacketsRead < 3) || (VorbisPresent && VorbisPacketsRead < 3))
- {
- int ret;
- ogg_packet Packet;
-
- // look for further theora headers
- while(TheoraPresent && (TheoraPacketsRead < 3) && (ret = TheoraStreamState->PacketOut(&Packet)))
- {
- if(ret < 0 || TheoraState->DecodeHeader(&Packet))
- {
- BS_LOG_ERRORLN("Error parsing Theora stream headers. Stream is possibly corrupt. (%s)", Filename.c_str());
- return false;
- }
-
- ++TheoraPacketsRead;
- if (TheoraPacketsRead == 3) break;
- }
-
- // look for more vorbis header packets
- while(VorbisPresent && (VorbisPacketsRead < 3) && (ret = VorbisStreamState->PacketOut(&Packet)))
- {
- if(ret < 0 || VorbisState->SynthesisHeaderIn(&Packet))
- {
- BS_LOG_ERRORLN("Error parsing Vorbis stream headers. Stream is possibly corrupt. (%s)", Filename.c_str());
- return false;
- }
-
- ++VorbisPacketsRead;
- if (VorbisPacketsRead == 3) break;
- }
-
- // The header pages/packets will arrive before anything else we care about, or the stream is not obeying spec
- ogg_page Page;
- if(OggState->SyncPageout(&Page) > 0)
- {
- // demux into the appropriate stream
- if(TheoraPresent) TheoraStreamState->PageIn(&Page);
- if(VorbisPresent) VorbisStreamState->PageIn(&Page);
- }
- else
- {
- if(File->BufferData(*OggState.get()) == 0)
- {
- BS_LOG_ERRORLN("End of file while searching for codec headers. (%s)", Filename.c_str());
- return false;
- }
- }
- }
-
- return true;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::LoadMovie(const std::string & Filename, unsigned int Z)
-{
- if (!VerifyRequiredServiceAvailability()) return false;
-
- UnloadMovie();
-
- // Alle Objekte die in dieser Funktion erzeugt werden, werden in zunächst lokalen Auto-Pointern gehalten.
- // Bei erfolgreicher Beendigung dieser Funktion werden sie den objektlokalen Auto-Pointern zugewiesen.
- // So wird sichergestellt, dass sie korrekt deinitialisiert werden, wenn in dieser Funktion ein Fehler auftritt, denn beim Zerstören der
- // lokalen Auto-Pointer werden die entsprechenden Destruktoren aufgerufen.
-
- // Film laden
- // Für Filmdateien wird das Cachingsystem nicht benutzt, da Filme in der Regel nur ein Mal abgespielt werden.
- bool Success;
- auto_ptr<BS_MovieFile> File(new BS_MovieFile(Filename, READ_BLOCK_SIZE, Success));
- if (!Success) return false;
-
- // States erzeugen für Ogg, Vorbis und Theora, sowie die Ogg und Theora Streams
- auto_ptr<BS_OggState> OggState(new BS_OggState());
- auto_ptr<BS_VorbisState> VorbisState(new BS_VorbisState());
- auto_ptr<BS_TheoraState> TheoraState(new BS_TheoraState());
-
- auto_ptr<BS_OggStreamState> TheoraStreamState;
- auto_ptr<BS_OggStreamState> VorbisStreamState;
-
- if (!ParseStreamHeaders(File, OggState, TheoraStreamState, VorbisStreamState, TheoraState, VorbisState, m_TheoraPresent, m_VorbisPresent, Filename)) return false;
-
- // Theora-Decoder Initialisieren
- if(m_TheoraPresent)
- {
- TheoraState->DecodeInit();
-
- const theora_info & TheoraInfo = TheoraState->GetInfo();
-
- if (TheoraInfo.pixelformat != OC_PF_444 &&
- TheoraInfo.pixelformat != OC_PF_422 &&
- TheoraInfo.pixelformat != OC_PF_420)
- {
- BS_LOG_ERRORLN("Unknown chroma sampling. (%s)", Filename.c_str());
- return false;
- }
-
- // Ausgabebitmap erstellen
- BS_GraphicEngine * pGfx = BS_Kernel::GetInstance()->GetGfx();
- m_OutputBitmap = pGfx->GetMainPanel()->AddDynamicBitmap(TheoraInfo.frame_width, TheoraInfo.frame_height);
- if (!m_OutputBitmap.IsValid())
- {
- BS_LOG_ERRORLN("Output bitmap for movie playback could not be created.");
- return false;
- }
-
- // Skalierung des Ausgabebitmaps berechnen, so dass es möglichst viel Bildschirmfläche einnimmt.
- float ScreenToVideoWidth = (float) pGfx->GetDisplayWidth() / (float) m_OutputBitmap->GetWidth();
- float ScreenToVideoHeight = (float) pGfx->GetDisplayHeight() / (float) m_OutputBitmap->GetHeight();
- float ScaleFactor = std::min(ScreenToVideoWidth, ScreenToVideoHeight);
- if (ABS(ScaleFactor - 1.0f) < FLT_EPSILON) ScaleFactor = 1.0f;
- m_OutputBitmap->SetScaleFactor(ScaleFactor);
-
- // Z-Wert setzen
- m_OutputBitmap->SetZ(Z);
-
- // Ausgabebitmap auf dem Bildschirm zentrieren
- m_OutputBitmap->SetX((pGfx->GetDisplayWidth() - m_OutputBitmap->GetWidth()) / 2);
- m_OutputBitmap->SetY((pGfx->GetDisplayHeight() - m_OutputBitmap->GetHeight()) / 2);
-
- // Buffer für die Pixeldaten erstellen
- m_Pixels.resize(TheoraInfo.width * TheoraInfo.height * 4);
-
- m_VideoEnded = false;
- }
-
- // Vorbis-Decoder initialisieren
- if(m_VorbisPresent)
- {
- VorbisState->SynthesisInit();
- VorbisState->BlockInit();
- m_AudioBuffer.reset(new BS_AudioBuffer());
-
- m_AudioEnded = false;
- }
-
- // Keine Kopie, überträgt Besitz der erzeugten Objekte von der Funktion auf das Objekt.
- m_File = File;
- m_OggState = OggState;
- m_TheoraState = TheoraState;
- m_TheoraStreamState = TheoraStreamState;
- m_VorbisState = VorbisState;
- m_VorbisStreamState = VorbisStreamState;
- m_MovieLoaded = true;
- m_Timer = 0;
-
- return true;
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::UnloadMovie()
-{
- m_MovieLoaded = false;
- m_Paused = true;
-
- m_VorbisStreamState.reset();
- m_VorbisPresent = false;
- m_VorbisState.reset();
- if (m_SoundHandle)
- {
- BS_Kernel::GetInstance()->GetSfx()->StopSound(m_SoundHandle);
- m_SoundHandle = 0;
- }
- m_AudioEnded = true;
- m_AudioBuffer.reset();
-
- m_TheoraStreamState.reset();
- m_TheoraPresent = false;
- m_TheoraState.reset();
- m_VideoEnded = true;
-
- m_OggState.reset();
-
- m_File.reset();
-
- m_StartTime = 0;
- m_LastFrameTime = 0;
- m_Timer = 0.0f;
-
- vector<unsigned char>().swap(m_Pixels);
- m_OutputBitmap.Erase();
-
- return true;
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::Play()
-{
- if (m_MovieLoaded)
- {
- if (m_Paused)
- {
- if (m_SoundHandle)
- {
- BS_SoundEngine * SfxPtr = BS_Kernel::GetInstance()->GetSfx();
- SfxPtr->ResumeSound(m_SoundHandle);
- }
- m_Paused = false;
- }
-
- return true;
- }
- else
- {
- BS_LOG_WARNINGLN("Cannot play movie, when no movie is loaded.");
- return false;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::Pause()
-{
- if (m_MovieLoaded)
- {
- if (m_SoundHandle)
- {
- BS_SoundEngine * SfxPtr = BS_Kernel::GetInstance()->GetSfx();
- SfxPtr->PauseSound(m_SoundHandle);
- }
-
- m_Paused = true;
- return true;
- }
- else
- {
- BS_LOG_WARNINGLN("Cannot pause movie, when no movie is loaded.");
- return false;
- }
-}
-
-// -----------------------------------------------------------------------------
-
-void BS_OggTheora::ReadData()
-{
- if (!m_File->IsEOF()) m_File->BufferData(*m_OggState.get());
-
- ogg_page Page;
- while(m_OggState->SyncPageout(&Page) > 0)
- {
- if(m_TheoraPresent) m_TheoraStreamState->BufferPage(&Page);
- if(m_VorbisPresent) m_VorbisStreamState->BufferPage(&Page);
- }
-}
-
-void BS_OggTheora::Update()
-{
- if (m_AudioEnded && m_VideoEnded)
- {
- m_Paused = true;
-
- // Falls der Sound noch läuft, muss er jetzt beendet werden.
- if (m_SoundHandle)
- {
- BS_SoundEngine * SfxPtr = BS_Kernel::GetInstance()->GetSfx();
- SfxPtr->StopSound(m_SoundHandle);
- m_SoundHandle = 0;
- }
- }
-
- if (m_Paused) return;
-
- // Timer aktualisieren.
- // Wird nur genutzt, wenn keine Audiodaten vorhanden sind.
- m_Timer += BS_Kernel::GetInstance()->GetGfx()->GetSecondaryFrameDuration();
-
- // Audiodaten dekodieren
- if (m_VorbisPresent && !m_AudioEnded) DecodeVorbis();
-
-
- // Videodaten dekodieren
- if (m_TheoraPresent && !m_VideoEnded)
- {
- bool Result = DecodeTheora();
-
- if (Result)
- {
- // YUV Framebuffer holen
- yuv_buffer YUVBuffer;
- m_TheoraState->DecodeYUVOut(&YUVBuffer);
-
- // YUV Bilddaten nach RGBA konvertieren
- BS_YUVtoRGBA::YUVtoRGBA(YUVBuffer, m_TheoraState->GetInfo(), m_Pixels);
-
- // RGBA Bilddaten auf das Ausgabebild kopieren, dabei die Postion des Theoraframes innerhalb des dekodierten Frames beachten.
- const theora_info & TheoraInfo = m_TheoraState->GetInfo();
- m_OutputBitmap->SetContent(m_Pixels, (TheoraInfo.offset_x + TheoraInfo.width * TheoraInfo.offset_y) * 4, (TheoraInfo.width - TheoraInfo.frame_width) * 4);
- }
- }
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::DecodeTheora()
-{
- double MovieTime = GetTime();
-
- // Check if this frame time has not passed yet. If the frame is late we need
- // to decode additonal ones and keep looping, since theora at this stage
- // needs to decode all frames (due to keyframing)
- // Getting the current time once at the beginning of the function rather than
- // every time at the beginning of the loop produces the smoothest framerate
-
- unsigned int FramesDecoded = 0;
- bool FrameReady = false;
- while (m_TheoraState->GranuleTime() < MovieTime)
- {
- // theora is one in, one out...
- ogg_packet Packet;
- if(m_TheoraStreamState->PacketOut(&Packet) > 0)
- {
- if (FramesDecoded < MAX_FRAMES_PER_TICK || Packet.granulepos >= MovieTime)
- {
- m_TheoraState->DecodePacketIn(&Packet);
- FrameReady = true;
- ++FramesDecoded;
- }
- }
- else
- {
- if (m_TheoraStreamState->GetPageBufferSize() > 0)
- m_TheoraStreamState->PageInBufferedPage();
- else
- {
- if(m_File->IsEOF())
- {
- m_VideoEnded = true;
- break;
- }
- else
- ReadData();
- }
- }
- }
- m_LastFrameTime = MovieTime;
-
- return FrameReady;
-}
-
-// -----------------------------------------------------------------------------
-
-void BS_OggTheora::DynamicSoundCallBack(void * UserData, void * Data, unsigned int DataLength)
-{
- BS_OggTheora & t = *reinterpret_cast<BS_OggTheora *>(UserData);
-
- signed short * Buffer = reinterpret_cast<signed short *>(Data);
-
- // Audiodaten in den Soundbuffer schreiben.
- DataLength -= t.m_AudioBuffer->Pop(Buffer, DataLength / 2) * 2;
-
- // Falls nicht genug Audiodaten vorhanden waren, wird der Rest mit Stille überschrieben.
- if (DataLength)
- {
- char * ByteBuffer = reinterpret_cast<char *>(Buffer);
- while (DataLength--)
- {
- *ByteBuffer++ = 0;
- }
- }
-}
-
-// -----------------------------------------------------------------------------
-
-void BS_OggTheora::DecodeVorbis()
-{
- // Vorbis-Stream Infos holen.
- const vorbis_info & Info = m_VorbisState->GetInfo();
-
- // Maximalgröße des Audiobuffers berechnen.
- size_t MaxAudioBufferSamples = static_cast<size_t>(Info.channels * Info.rate * MAX_AUDIO_BUFFER_LENGTH);
-
- // Zwischenspeicher für die Samples.
- vector<signed short> Samples;
-
- // Audiobuffer bis zur Maximalgröße füllen, wenn möglich.
- while (m_AudioBuffer->Size() < MaxAudioBufferSamples)
- {
- // Vorhandene Audiodaten auslesen
- float ** PCM;
- int SampleCount = m_VorbisState->SynthesisPCMout(&PCM);
-
- // Wenn Audiodaten gelesen werden konnten, werden diese in 16-Bit Sample umgewandelt und in den Audiobuffer geschrieben.
- if(SampleCount > 0)
- {
- // Im Samplezwischenspeicher leeren und genügend Platz für die kommenden Samples reservieren.
- Samples.reserve(SampleCount);
- Samples.clear();
-
- // Samples konvertieren und in die Samplezwischenspeicher schreiben.
- for (int i = 0; i < SampleCount; ++i)
- {
- for(int j = 0; j < Info.channels; ++j)
- {
- int SampleValue = static_cast<int>(PCM[j][i] * 32767.0f);
- Samples.push_back(Clamp(SampleValue, -32700, 32700));
- }
- }
-
- // Daten aus dem Samplezwischenspeicher in den Audiobuffer schreiben.
- m_AudioBuffer->Push(&Samples[0], Samples.size());
-
- // Vorbis mitteilen, dass wir alle Samples gelesen haben.
- m_VorbisState->SynthesisRead(SampleCount);
- }
- else
- {
- // Wir konnten, keine Audiodaten auslesen, versuchen ein neues Paket zu dekodieren.
- ogg_packet Packet;
- if(m_VorbisStreamState->PacketOut(&Packet) > 0)
- {
- if (m_VorbisState->Synthesis(&Packet) == 0) m_VorbisState->SynthesisBlockIn();
- }
- else
- {
- // Gepufferte Daten in den Stream einfügen.
- if (m_VorbisStreamState->GetPageBufferSize() > 0)
- m_VorbisStreamState->PageInBufferedPage();
- else
- {
- // Nicht genug Daten vorhanden. Wenn die Datei leer ist und bereits alle Audiodaten gelesen wurden, ist der Audiostream am Ende.
- // Ansonsten Daten nachladen.
- if(m_File->IsEOF())
- {
- if (m_AudioBuffer->Size() == 0)
- {
- m_AudioEnded = true;
- }
-
- break;
- }
- else
- ReadData();
- }
- }
- }
- }
-
- // Soundkanal abspielen, wenn er noch nicht spielt und Audiodaten vorhanden sind.
- if (m_SoundHandle == 0 && m_AudioBuffer->Size())
- {
- BS_SoundEngine * SfxPtr = BS_Kernel::GetInstance()->GetSfx();
- m_SoundHandle = SfxPtr->PlayDynamicSoundEx(&DynamicSoundCallBack, this, BS_SoundEngine::SFX, Info.rate, 16, Info.channels);
- }
-}
-
-// -----------------------------------------------------------------------------
-
-double BS_OggTheora::GetTime()
-{
- if(m_VorbisPresent)
- {
- if (m_SoundHandle)
- {
- float time = BS_Kernel::GetInstance()->GetSfx()->GetSoundTime(m_SoundHandle);
- return time;
- }
- else
- return 0.0f;
- }
- else
- return m_Timer;
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::IsMovieLoaded()
-{
- return m_MovieLoaded;
-}
-
-// -----------------------------------------------------------------------------
-
-bool BS_OggTheora::IsPaused()
-{
- return m_Paused;
-}
-
-// -----------------------------------------------------------------------------
-
-float BS_OggTheora::GetScaleFactor()
-{
- if (m_MovieLoaded)
- return m_OutputBitmap->GetScaleFactorX();
- else
- return 0;
-}
-
-// -----------------------------------------------------------------------------
-
-void BS_OggTheora::SetScaleFactor(float ScaleFactor)
-{
- if (m_MovieLoaded)
- {
- m_OutputBitmap->SetScaleFactor(ScaleFactor);
-
- // Ausgabebitmap auf dem Bildschirm zentrieren
- BS_GraphicEngine * GfxPtr = BS_Kernel::GetInstance()->GetGfx();
- m_OutputBitmap->SetX((GfxPtr->GetDisplayWidth() - m_OutputBitmap->GetWidth()) / 2);
- m_OutputBitmap->SetY((GfxPtr->GetDisplayHeight() - m_OutputBitmap->GetHeight()) / 2);
- }
-}
diff --git a/engines/sword25/fmv/oggtheora/oggtheora.h b/engines/sword25/fmv/oggtheora/oggtheora.h
deleted file mode 100644
index 62fa607935..0000000000
--- a/engines/sword25/fmv/oggtheora/oggtheora.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/*
- * This code is based on Broken Sword 2.5 engine
- *
- * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
- *
- * Licensed under GNU GPL v2
- *
- */
-
-#ifndef SWORD25_OGGTHEORA_H
-#define SWORD25_OGGTHEORA_H
-
-// -----------------------------------------------------------------------------
-// Includes
-// -----------------------------------------------------------------------------
-
-#include "sword25/kernel/memlog_off.h"
-#include <vector>
-#include <memory>
-#include <queue>
-#include "sword25/kernel/memlog_on.h"
-
-#include "sword25/kernel/common.h"
-#include "sword25/kernel/bs_stdint.h"
-#include "sword25/gfx/bitmap.h"
-#include "sword25/gfx/renderobjectptr.h"
-#include "sword25/fmv/movieplayer.h"
-#include "sword25/fmv/oggtheora/vorbisstate.h"
-#include "sword25/fmv/oggtheora/theorastate.h"
-#include "sword25/fmv/oggtheora/oggstate.h"
-#include "sword25/fmv/oggtheora/oggstreamstate.h"
-#include "sword25/fmv/oggtheora/moviefile.h"
-#include "sword25/fmv/oggtheora/audiobuffer.h"
-
-// -----------------------------------------------------------------------------
-// Klassendefinition
-// -----------------------------------------------------------------------------
-
-class BS_OggTheora : public BS_MoviePlayer
-{
-public:
- // -----------------------------------------------------------------------------
- // Konstruktion / Destruktion
- // -----------------------------------------------------------------------------
-
- BS_OggTheora(BS_Kernel * pKernel);
- virtual ~BS_OggTheora();
-
- // -----------------------------------------------------------------------------
- // BS_MoviePlayer Interface
- // -----------------------------------------------------------------------------
-
- virtual bool LoadMovie(const std::string & Filename, unsigned int Z);
- virtual bool UnloadMovie();
- virtual bool Play();
- virtual bool Pause();
- virtual void Update();
- virtual bool IsMovieLoaded();
- virtual bool IsPaused();
- virtual float GetScaleFactor();
- virtual void SetScaleFactor(float ScaleFactor);
- virtual double GetTime();
-
-private:
- bool DecodeTheora();
- void DecodeVorbis();
- void RefillOggBuffer();
- void ReadData();
- static void DynamicSoundCallBack(void * UserData, void * Data, unsigned int DataLength);
-
- bool m_MovieLoaded;
- bool m_Paused;
-
- std::auto_ptr<BS_OggStreamState> m_VorbisStreamState;
- bool m_VorbisPresent;
- std::auto_ptr<BS_VorbisState> m_VorbisState;
- unsigned int m_SoundHandle;
- bool m_AudioEnded;
- std::auto_ptr<BS_AudioBuffer> m_AudioBuffer;
-
- std::auto_ptr<BS_OggStreamState> m_TheoraStreamState;
- bool m_TheoraPresent;
- std::auto_ptr<BS_TheoraState> m_TheoraState;
- bool m_VideoEnded;
-
- std::auto_ptr<BS_OggState> m_OggState;
-
- std::auto_ptr<BS_MovieFile> m_File;
-
- uint64_t m_StartTime;
- double m_LastFrameTime;
-
- float m_Timer;
-
- std::vector<unsigned char> m_Pixels;
- BS_RenderObjectPtr<BS_Bitmap> m_OutputBitmap;
-};
-
-#endif
diff --git a/engines/sword25/fmv/oggtheora/theorastate.cpp b/engines/sword25/fmv/oggtheora/theorastate.cpp
index a270bab80c..2284098d2f 100644
--- a/engines/sword25/fmv/oggtheora/theorastate.cpp
+++ b/engines/sword25/fmv/oggtheora/theorastate.cpp
@@ -38,19 +38,19 @@
#include "sword25/fmv/oggtheora/theorastate.h"
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-BS_TheoraState::BS_TheoraState() :
- m_StateInitialized(false)
-{
+TheoraState::TheoraState() :
+ m_StateInitialized(false) {
theora_comment_init(&m_Comment);
theora_info_init(&m_Info);
}
// -----------------------------------------------------------------------------
-BS_TheoraState::~BS_TheoraState()
-{
+TheoraState::~TheoraState() {
if (m_StateInitialized) theora_clear(&m_State);
theora_info_clear(&m_Info);
theora_comment_clear(&m_Comment);
@@ -58,15 +58,13 @@ BS_TheoraState::~BS_TheoraState()
// -----------------------------------------------------------------------------
-int BS_TheoraState::DecodeHeader(ogg_packet * OggPacketPtr)
-{
+int TheoraState::DecodeHeader(ogg_packet *OggPacketPtr) {
return theora_decode_header(&m_Info, &m_Comment, OggPacketPtr);
}
// -----------------------------------------------------------------------------
-int BS_TheoraState::DecodeInit()
-{
+int TheoraState::DecodeInit() {
int Result = theora_decode_init(&m_State, &m_Info);
m_StateInitialized = (Result == 0);
return Result;
@@ -74,21 +72,20 @@ int BS_TheoraState::DecodeInit()
// -----------------------------------------------------------------------------
-double BS_TheoraState::GranuleTime()
-{
+double TheoraState::GranuleTime() {
return theora_granule_time(&m_State, m_State.granulepos);
}
// -----------------------------------------------------------------------------
-int BS_TheoraState::DecodePacketIn(ogg_packet * OggPacketPtr)
-{
+int TheoraState::DecodePacketIn(ogg_packet *OggPacketPtr) {
return theora_decode_packetin(&m_State, OggPacketPtr);
}
// -----------------------------------------------------------------------------
-int BS_TheoraState::DecodeYUVOut(yuv_buffer * YUV)
-{
+int TheoraState::DecodeYUVOut(yuv_buffer *YUV) {
return theora_decode_YUVout(&m_State, YUV);
}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/theorastate.h b/engines/sword25/fmv/oggtheora/theorastate.h
index 07934c26ea..967ca259ad 100644
--- a/engines/sword25/fmv/oggtheora/theorastate.h
+++ b/engines/sword25/fmv/oggtheora/theorastate.h
@@ -42,20 +42,21 @@
#include "sword25/kernel/common.h"
#include <theora/theora.h>
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-// Klassendefinition
+// Class definitions
// -----------------------------------------------------------------------------
-class BS_TheoraState
-{
+class TheoraState {
public:
- BS_TheoraState();
- virtual ~BS_TheoraState();
+ TheoraState();
+ virtual ~TheoraState();
- int DecodeHeader(ogg_packet * OggPacketPtr);
+ int DecodeHeader(ogg_packet *OggPacketPtr);
int DecodeInit();
- int DecodePacketIn(ogg_packet * OggPacketPtr);
- int DecodeYUVOut(yuv_buffer * YUV);
+ int DecodePacketIn(ogg_packet *OggPacketPtr);
+ int DecodeYUVOut(yuv_buffer *YUV);
double GranuleTime();
const theora_info & GetInfo() const { return m_Info; }
@@ -67,4 +68,6 @@ private:
theora_state m_State;
};
+} // End of namespace Sword25
+
#endif
diff --git a/engines/sword25/fmv/oggtheora/vorbisstate.cpp b/engines/sword25/fmv/oggtheora/vorbisstate.cpp
index e9f6b7dc4f..53085a9832 100644
--- a/engines/sword25/fmv/oggtheora/vorbisstate.cpp
+++ b/engines/sword25/fmv/oggtheora/vorbisstate.cpp
@@ -38,20 +38,20 @@
#include "sword25/fmv/oggtheora/vorbisstate.h"
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-BS_VorbisState::BS_VorbisState() :
- m_DSPStateInitialized(false),
- m_BlockInitialized(false)
-{
+VorbisState::VorbisState() :
+ m_DSPStateInitialized(false),
+ m_BlockInitialized(false) {
vorbis_info_init(&m_Info);
vorbis_comment_init(&m_Comment);
}
// -----------------------------------------------------------------------------
-BS_VorbisState::~BS_VorbisState()
-{
+VorbisState::~VorbisState() {
if (m_BlockInitialized) vorbis_block_clear(&m_Block);
if (m_DSPStateInitialized) vorbis_dsp_clear(&m_DSPState);
vorbis_comment_clear(&m_Comment);
@@ -60,15 +60,13 @@ BS_VorbisState::~BS_VorbisState()
// -----------------------------------------------------------------------------
-int BS_VorbisState::SynthesisHeaderIn(ogg_packet * OggPacketPtr)
-{
+int VorbisState::SynthesisHeaderIn(ogg_packet *OggPacketPtr) {
return vorbis_synthesis_headerin(&m_Info, &m_Comment, OggPacketPtr);
}
// -----------------------------------------------------------------------------
-int BS_VorbisState::SynthesisInit()
-{
+int VorbisState::SynthesisInit() {
int Result = vorbis_synthesis_init(&m_DSPState, &m_Info);
m_DSPStateInitialized = (Result == 0);
return Result;
@@ -76,8 +74,7 @@ int BS_VorbisState::SynthesisInit()
// -----------------------------------------------------------------------------
-int BS_VorbisState::BlockInit()
-{
+int VorbisState::BlockInit() {
int Result = vorbis_block_init(&m_DSPState, &m_Block);
m_BlockInitialized = (Result == 0);
return Result;
@@ -85,28 +82,26 @@ int BS_VorbisState::BlockInit()
// -----------------------------------------------------------------------------
-int BS_VorbisState::SynthesisPCMout(float *** PCM)
-{
+int VorbisState::SynthesisPCMout(float ***PCM) {
return vorbis_synthesis_pcmout(&m_DSPState, PCM);
}
// -----------------------------------------------------------------------------
-int BS_VorbisState::SynthesisRead(int Samples)
-{
+int VorbisState::SynthesisRead(int Samples) {
return vorbis_synthesis_read(&m_DSPState, Samples);
}
// -----------------------------------------------------------------------------
-int BS_VorbisState::Synthesis(ogg_packet * OggPacketPtr)
-{
+int VorbisState::Synthesis(ogg_packet *OggPacketPtr) {
return vorbis_synthesis(&m_Block, OggPacketPtr);
}
// -----------------------------------------------------------------------------
-int BS_VorbisState::SynthesisBlockIn()
-{
+int VorbisState::SynthesisBlockIn() {
return vorbis_synthesis_blockin(&m_DSPState, &m_Block);
}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/vorbisstate.h b/engines/sword25/fmv/oggtheora/vorbisstate.h
index 126e59d0aa..4a87f13d9e 100644
--- a/engines/sword25/fmv/oggtheora/vorbisstate.h
+++ b/engines/sword25/fmv/oggtheora/vorbisstate.h
@@ -42,25 +42,26 @@
#include "sword25/kernel/common.h"
#include <vorbis/codec.h>
+namespace Sword25 {
+
// -----------------------------------------------------------------------------
-// Klassendefinition
+// Class definitions
// -----------------------------------------------------------------------------
-class BS_VorbisState
-{
+class VorbisState {
public:
- BS_VorbisState();
- virtual ~BS_VorbisState();
+ VorbisState();
+ virtual ~VorbisState();
- int SynthesisHeaderIn(ogg_packet * OggPacketPtr);
+ int SynthesisHeaderIn(ogg_packet *OggPacketPtr);
int SynthesisInit();
int BlockInit();
- int SynthesisPCMout(float *** PCM);
+ int SynthesisPCMout(float ***PCM);
int SynthesisRead(int Samples);
- int Synthesis(ogg_packet * OggPacketPtr);
+ int Synthesis(ogg_packet *OggPacketPtr);
int SynthesisBlockIn();
- const vorbis_info & GetInfo() const { return m_Info; }
+ const vorbis_info &GetInfo() const { return m_Info; }
private:
vorbis_info m_Info;
@@ -71,4 +72,6 @@ private:
vorbis_comment m_Comment;
};
+} // End of namespace Sword25
+
#endif
diff --git a/engines/sword25/fmv/oggtheora/yuvtorgba.cpp b/engines/sword25/fmv/oggtheora/yuvtorgba.cpp
index d835d2ba0b..2c950745f1 100644
--- a/engines/sword25/fmv/oggtheora/yuvtorgba.cpp
+++ b/engines/sword25/fmv/oggtheora/yuvtorgba.cpp
@@ -36,396 +36,213 @@
// Includes
// -----------------------------------------------------------------------------
-#include "sword25/kernel/cpuinfo.h"
-#include "sword25/fmv/ogghteora/yuvtorgba.h"
-
-#include <mmintrin.h>
-
-using namespace std;
+#include "sword25/fmv/oggtheora/yuvtorgba.h"
// -----------------------------------------------------------------------------
-namespace
-{
-
- static const int PRECISION = 32768;
- static const int COEFFS_Y[256] = {
- -593888, -555746, -517604, -479462, -441320, -403178, -365036, -326894, -288752, -250610, -212468, -174326, -136184, -98042, -59900, -21758,
- 16384, 54526, 92668, 130810, 168952, 207094, 245236, 283378, 321520, 359662, 397804, 435946, 474088, 512230, 550372, 588514,
- 626656, 664798, 702940, 741082, 779224, 817366, 855508, 893650, 931792, 969934, 1008076, 1046218, 1084360, 1122502, 1160644, 1198786,
- 1236928, 1275070, 1313212, 1351354, 1389496, 1427638, 1465780, 1503922, 1542064, 1580206, 1618348, 1656490, 1694632, 1732774, 1770916, 1809058,
- 1847200, 1885342, 1923484, 1961626, 1999768, 2037910, 2076052, 2114194, 2152336, 2190478, 2228620, 2266762, 2304904, 2343046, 2381188, 2419330,
- 2457472, 2495614, 2533756, 2571898, 2610040, 2648182, 2686324, 2724466, 2762608, 2800750, 2838892, 2877034, 2915176, 2953318, 2991460, 3029602,
- 3067744, 3105886, 3144028, 3182170, 3220312, 3258454, 3296596, 3334738, 3372880, 3411022, 3449164, 3487306, 3525448, 3563590, 3601732, 3639874,
- 3678016, 3716158, 3754300, 3792442, 3830584, 3868726, 3906868, 3945010, 3983152, 4021294, 4059436, 4097578, 4135720, 4173862, 4212004, 4250146,
- 4288288, 4326430, 4364572, 4402714, 4440856, 4478998, 4517140, 4555282, 4593424, 4631566, 4669708, 4707850, 4745992, 4784134, 4822276, 4860418,
- 4898560, 4936702, 4974844, 5012986, 5051128, 5089270, 5127412, 5165554, 5203696, 5241838, 5279980, 5318122, 5356264, 5394406, 5432548, 5470690,
- 5508832, 5546974, 5585116, 5623258, 5661400, 5699542, 5737684, 5775826, 5813968, 5852110, 5890252, 5928394, 5966536, 6004678, 6042820, 6080962,
- 6119104, 6157246, 6195388, 6233530, 6271672, 6309814, 6347956, 6386098, 6424240, 6462382, 6500524, 6538666, 6576808, 6614950, 6653092, 6691234,
- 6729376, 6767518, 6805660, 6843802, 6881944, 6920086, 6958228, 6996370, 7034512, 7072654, 7110796, 7148938, 7187080, 7225222, 7263364, 7301506,
- 7339648, 7377790, 7415932, 7454074, 7492216, 7530358, 7568500, 7606642, 7644784, 7682926, 7721068, 7759210, 7797352, 7835494, 7873636, 7911778,
- 7949920, 7988062, 8026204, 8064346, 8102488, 8140630, 8178772, 8216914, 8255056, 8293198, 8331340, 8369482, 8407624, 8445766, 8483908, 8522050,
- 8560192, 8598334, 8636476, 8674618, 8712760, 8750902, 8789044, 8827186, 8865328, 8903470, 8941612, 8979754, 9017896, 9056038, 9094180, 9132322,
- };
- static const int COEFFS_RV[256] = {
- -6694144, -6641846, -6589548, -6537250, -6484952, -6432654, -6380356, -6328058, -6275760, -6223462, -6171164, -6118866, -6066568, -6014270, -5961972, -5909674,
- -5857376, -5805078, -5752780, -5700482, -5648184, -5595886, -5543588, -5491290, -5438992, -5386694, -5334396, -5282098, -5229800, -5177502, -5125204, -5072906,
- -5020608, -4968310, -4916012, -4863714, -4811416, -4759118, -4706820, -4654522, -4602224, -4549926, -4497628, -4445330, -4393032, -4340734, -4288436, -4236138,
- -4183840, -4131542, -4079244, -4026946, -3974648, -3922350, -3870052, -3817754, -3765456, -3713158, -3660860, -3608562, -3556264, -3503966, -3451668, -3399370,
- -3347072, -3294774, -3242476, -3190178, -3137880, -3085582, -3033284, -2980986, -2928688, -2876390, -2824092, -2771794, -2719496, -2667198, -2614900, -2562602,
- -2510304, -2458006, -2405708, -2353410, -2301112, -2248814, -2196516, -2144218, -2091920, -2039622, -1987324, -1935026, -1882728, -1830430, -1778132, -1725834,
- -1673536, -1621238, -1568940, -1516642, -1464344, -1412046, -1359748, -1307450, -1255152, -1202854, -1150556, -1098258, -1045960, -993662, -941364, -889066,
- -836768, -784470, -732172, -679874, -627576, -575278, -522980, -470682, -418384, -366086, -313788, -261490, -209192, -156894, -104596, -52298,
- 0, 52298, 104596, 156894, 209192, 261490, 313788, 366086, 418384, 470682, 522980, 575278, 627576, 679874, 732172, 784470,
- 836768, 889066, 941364, 993662, 1045960, 1098258, 1150556, 1202854, 1255152, 1307450, 1359748, 1412046, 1464344, 1516642, 1568940, 1621238,
- 1673536, 1725834, 1778132, 1830430, 1882728, 1935026, 1987324, 2039622, 2091920, 2144218, 2196516, 2248814, 2301112, 2353410, 2405708, 2458006,
- 2510304, 2562602, 2614900, 2667198, 2719496, 2771794, 2824092, 2876390, 2928688, 2980986, 3033284, 3085582, 3137880, 3190178, 3242476, 3294774,
- 3347072, 3399370, 3451668, 3503966, 3556264, 3608562, 3660860, 3713158, 3765456, 3817754, 3870052, 3922350, 3974648, 4026946, 4079244, 4131542,
- 4183840, 4236138, 4288436, 4340734, 4393032, 4445330, 4497628, 4549926, 4602224, 4654522, 4706820, 4759118, 4811416, 4863714, 4916012, 4968310,
- 5020608, 5072906, 5125204, 5177502, 5229800, 5282098, 5334396, 5386694, 5438992, 5491290, 5543588, 5595886, 5648184, 5700482, 5752780, 5805078,
- 5857376, 5909674, 5961972, 6014270, 6066568, 6118866, 6171164, 6223462, 6275760, 6328058, 6380356, 6432654, 6484952, 6537250, 6589548, 6641846,
- };
- static const int COEFFS_GU[256] = {
- 1639936, 1627124, 1614312, 1601500, 1588688, 1575876, 1563064, 1550252, 1537440, 1524628, 1511816, 1499004, 1486192, 1473380, 1460568, 1447756,
- 1434944, 1422132, 1409320, 1396508, 1383696, 1370884, 1358072, 1345260, 1332448, 1319636, 1306824, 1294012, 1281200, 1268388, 1255576, 1242764,
- 1229952, 1217140, 1204328, 1191516, 1178704, 1165892, 1153080, 1140268, 1127456, 1114644, 1101832, 1089020, 1076208, 1063396, 1050584, 1037772,
- 1024960, 1012148, 999336, 986524, 973712, 960900, 948088, 935276, 922464, 909652, 896840, 884028, 871216, 858404, 845592, 832780,
- 819968, 807156, 794344, 781532, 768720, 755908, 743096, 730284, 717472, 704660, 691848, 679036, 666224, 653412, 640600, 627788,
- 614976, 602164, 589352, 576540, 563728, 550916, 538104, 525292, 512480, 499668, 486856, 474044, 461232, 448420, 435608, 422796,
- 409984, 397172, 384360, 371548, 358736, 345924, 333112, 320300, 307488, 294676, 281864, 269052, 256240, 243428, 230616, 217804,
- 204992, 192180, 179368, 166556, 153744, 140932, 128120, 115308, 102496, 89684, 76872, 64060, 51248, 38436, 25624, 12812,
- 0, -12812, -25624, -38436, -51248, -64060, -76872, -89684, -102496, -115308, -128120, -140932, -153744, -166556, -179368, -192180,
- -204992, -217804, -230616, -243428, -256240, -269052, -281864, -294676, -307488, -320300, -333112, -345924, -358736, -371548, -384360, -397172,
- -409984, -422796, -435608, -448420, -461232, -474044, -486856, -499668, -512480, -525292, -538104, -550916, -563728, -576540, -589352, -602164,
- -614976, -627788, -640600, -653412, -666224, -679036, -691848, -704660, -717472, -730284, -743096, -755908, -768720, -781532, -794344, -807156,
- -819968, -832780, -845592, -858404, -871216, -884028, -896840, -909652, -922464, -935276, -948088, -960900, -973712, -986524, -999336, -1012148,
- -1024960, -1037772, -1050584, -1063396, -1076208, -1089020, -1101832, -1114644, -1127456, -1140268, -1153080, -1165892, -1178704, -1191516, -1204328, -1217140,
- -1229952, -1242764, -1255576, -1268388, -1281200, -1294012, -1306824, -1319636, -1332448, -1345260, -1358072, -1370884, -1383696, -1396508, -1409320, -1422132,
- -1434944, -1447756, -1460568, -1473380, -1486192, -1499004, -1511816, -1524628, -1537440, -1550252, -1563064, -1575876, -1588688, -1601500, -1614312, -1627124,
- };
- static const int COEFFS_GV[256] = {
- 3409920, 3383280, 3356640, 3330000, 3303360, 3276720, 3250080, 3223440, 3196800, 3170160, 3143520, 3116880, 3090240, 3063600, 3036960, 3010320,
- 2983680, 2957040, 2930400, 2903760, 2877120, 2850480, 2823840, 2797200, 2770560, 2743920, 2717280, 2690640, 2664000, 2637360, 2610720, 2584080,
- 2557440, 2530800, 2504160, 2477520, 2450880, 2424240, 2397600, 2370960, 2344320, 2317680, 2291040, 2264400, 2237760, 2211120, 2184480, 2157840,
- 2131200, 2104560, 2077920, 2051280, 2024640, 1998000, 1971360, 1944720, 1918080, 1891440, 1864800, 1838160, 1811520, 1784880, 1758240, 1731600,
- 1704960, 1678320, 1651680, 1625040, 1598400, 1571760, 1545120, 1518480, 1491840, 1465200, 1438560, 1411920, 1385280, 1358640, 1332000, 1305360,
- 1278720, 1252080, 1225440, 1198800, 1172160, 1145520, 1118880, 1092240, 1065600, 1038960, 1012320, 985680, 959040, 932400, 905760, 879120,
- 852480, 825840, 799200, 772560, 745920, 719280, 692640, 666000, 639360, 612720, 586080, 559440, 532800, 506160, 479520, 452880,
- 426240, 399600, 372960, 346320, 319680, 293040, 266400, 239760, 213120, 186480, 159840, 133200, 106560, 79920, 53280, 26640,
- 0, -26640, -53280, -79920, -106560, -133200, -159840, -186480, -213120, -239760, -266400, -293040, -319680, -346320, -372960, -399600,
- -426240, -452880, -479520, -506160, -532800, -559440, -586080, -612720, -639360, -666000, -692640, -719280, -745920, -772560, -799200, -825840,
- -852480, -879120, -905760, -932400, -959040, -985680, -1012320, -1038960, -1065600, -1092240, -1118880, -1145520, -1172160, -1198800, -1225440, -1252080,
- -1278720, -1305360, -1332000, -1358640, -1385280, -1411920, -1438560, -1465200, -1491840, -1518480, -1545120, -1571760, -1598400, -1625040, -1651680, -1678320,
- -1704960, -1731600, -1758240, -1784880, -1811520, -1838160, -1864800, -1891440, -1918080, -1944720, -1971360, -1998000, -2024640, -2051280, -2077920, -2104560,
- -2131200, -2157840, -2184480, -2211120, -2237760, -2264400, -2291040, -2317680, -2344320, -2370960, -2397600, -2424240, -2450880, -2477520, -2504160, -2530800,
- -2557440, -2584080, -2610720, -2637360, -2664000, -2690640, -2717280, -2743920, -2770560, -2797200, -2823840, -2850480, -2877120, -2903760, -2930400, -2957040,
- -2983680, -3010320, -3036960, -3063600, -3090240, -3116880, -3143520, -3170160, -3196800, -3223440, -3250080, -3276720, -3303360, -3330000, -3356640, -3383280,
- };
- static const int COEFFS_BU[256] = {
- -8464128, -8398002, -8331876, -8265750, -8199624, -8133498, -8067372, -8001246, -7935120, -7868994, -7802868, -7736742, -7670616, -7604490, -7538364, -7472238,
- -7406112, -7339986, -7273860, -7207734, -7141608, -7075482, -7009356, -6943230, -6877104, -6810978, -6744852, -6678726, -6612600, -6546474, -6480348, -6414222,
- -6348096, -6281970, -6215844, -6149718, -6083592, -6017466, -5951340, -5885214, -5819088, -5752962, -5686836, -5620710, -5554584, -5488458, -5422332, -5356206,
- -5290080, -5223954, -5157828, -5091702, -5025576, -4959450, -4893324, -4827198, -4761072, -4694946, -4628820, -4562694, -4496568, -4430442, -4364316, -4298190,
- -4232064, -4165938, -4099812, -4033686, -3967560, -3901434, -3835308, -3769182, -3703056, -3636930, -3570804, -3504678, -3438552, -3372426, -3306300, -3240174,
- -3174048, -3107922, -3041796, -2975670, -2909544, -2843418, -2777292, -2711166, -2645040, -2578914, -2512788, -2446662, -2380536, -2314410, -2248284, -2182158,
- -2116032, -2049906, -1983780, -1917654, -1851528, -1785402, -1719276, -1653150, -1587024, -1520898, -1454772, -1388646, -1322520, -1256394, -1190268, -1124142,
- -1058016, -991890, -925764, -859638, -793512, -727386, -661260, -595134, -529008, -462882, -396756, -330630, -264504, -198378, -132252, -66126,
- 0, 66126, 132252, 198378, 264504, 330630, 396756, 462882, 529008, 595134, 661260, 727386, 793512, 859638, 925764, 991890,
- 1058016, 1124142, 1190268, 1256394, 1322520, 1388646, 1454772, 1520898, 1587024, 1653150, 1719276, 1785402, 1851528, 1917654, 1983780, 2049906,
- 2116032, 2182158, 2248284, 2314410, 2380536, 2446662, 2512788, 2578914, 2645040, 2711166, 2777292, 2843418, 2909544, 2975670, 3041796, 3107922,
- 3174048, 3240174, 3306300, 3372426, 3438552, 3504678, 3570804, 3636930, 3703056, 3769182, 3835308, 3901434, 3967560, 4033686, 4099812, 4165938,
- 4232064, 4298190, 4364316, 4430442, 4496568, 4562694, 4628820, 4694946, 4761072, 4827198, 4893324, 4959450, 5025576, 5091702, 5157828, 5223954,
- 5290080, 5356206, 5422332, 5488458, 5554584, 5620710, 5686836, 5752962, 5819088, 5885214, 5951340, 6017466, 6083592, 6149718, 6215844, 6281970,
- 6348096, 6414222, 6480348, 6546474, 6612600, 6678726, 6744852, 6810978, 6877104, 6943230, 7009356, 7075482, 7141608, 7207734, 7273860, 7339986,
- 7406112, 7472238, 7538364, 7604490, 7670616, 7736742, 7802868, 7868994, 7935120, 8001246, 8067372, 8133498, 8199624, 8265750, 8331876, 8398002,
- };
- static const int CLAMP_TAB[1024] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- };
-
- void YUVtoRGBA_c(const yuv_buffer & YUVBuffer, std::vector<unsigned char> & PixelData)
- {
- // Width and height of all buffers have to be divisible by 2.
- BS_ASSERT((YUVBuffer.y_width & 1) == 0);
- BS_ASSERT((YUVBuffer.y_height & 1) == 0);
- BS_ASSERT((YUVBuffer.uv_width & 1) == 0);
- BS_ASSERT((YUVBuffer.uv_height & 1) == 0);
- // UV images have to have a quarter of the Y image resolution
- BS_ASSERT(YUVBuffer.uv_width == YUVBuffer.y_width >> 1);
- BS_ASSERT(YUVBuffer.uv_height == YUVBuffer.y_height >> 1);
-
- const int *cl = &CLAMP_TAB[320];
-
- const unsigned char * ySrc0 = YUVBuffer.y;
- const unsigned char * ySrc1 = YUVBuffer.y + YUVBuffer.y_stride;
- const unsigned char * uSrc = YUVBuffer.u;
- const unsigned char * vSrc = YUVBuffer.v;
- unsigned char * dst0 = &PixelData[0];
- unsigned char * dst1 = &PixelData[0] + YUVBuffer.y_width * 4;
-
- for (int h = 0; h < YUVBuffer.y_height / 2; ++h)
- {
- for (int w = 0; w < YUVBuffer.y_width / 2; ++w)
- {
- int u = *uSrc++;
- int v = *vSrc++;
-
- int rUV = COEFFS_RV[v];
- int gUV = COEFFS_GU[u] + COEFFS_GV[v];
- int bUV = COEFFS_BU[u];
-
- int y = *ySrc0++;
- int r = COEFFS_Y[y] + rUV;
- int g = COEFFS_Y[y] + gUV;
- int b = COEFFS_Y[y] + bUV;
- *dst0++ = cl[r / PRECISION];
- *dst0++ = cl[g / PRECISION];
- *dst0++ = cl[b / PRECISION];
- *dst0++ = 255;
-
- y = *ySrc1++;
- r = COEFFS_Y[y] + rUV;
- g = COEFFS_Y[y] + gUV;
- b = COEFFS_Y[y] + bUV;
- *dst1++ = cl[r / PRECISION];
- *dst1++ = cl[g / PRECISION];
- *dst1++ = cl[b / PRECISION];
- *dst1++ = 255;
-
- y = *ySrc0++;
- r = COEFFS_Y[y] + rUV;
- g = COEFFS_Y[y] + gUV;
- b = COEFFS_Y[y] + bUV;
- *dst0++ = cl[r / PRECISION];
- *dst0++ = cl[g / PRECISION];
- *dst0++ = cl[b / PRECISION];
- *dst0++ = 255;
-
- y = *ySrc1++;
- r = COEFFS_Y[y] + rUV;
- g = COEFFS_Y[y] + gUV;
- b = COEFFS_Y[y] + bUV;
- *dst1++ = cl[r / PRECISION];
- *dst1++ = cl[g / PRECISION];
- *dst1++ = cl[b / PRECISION];
- *dst1++ = 255;
- }
-
- dst0 += YUVBuffer.y_width * 4;
- dst1 += YUVBuffer.y_width * 4;
- ySrc0 += YUVBuffer.y_stride * 2 - YUVBuffer.y_width;
- ySrc1 += YUVBuffer.y_stride * 2 - YUVBuffer.y_width;
- uSrc += YUVBuffer.uv_stride - YUVBuffer.uv_width;
- vSrc += YUVBuffer.uv_stride - YUVBuffer.uv_width;
- }
- }
-
- // -----------------------------------------------------------------------------
-
- static const __m64 COEFF_Y_MMX[256] = {
- 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000,
- 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000, 0x1fff000000000000,
- 0x1fff000000000000, 0x1fff004a004a004a, 0x1fff009500950095, 0x1fff00df00df00df, 0x1fff012a012a012a, 0x1fff017401740174, 0x1fff01bf01bf01bf, 0x1fff020902090209,
- 0x1fff025402540254, 0x1fff029e029e029e, 0x1fff02e902e902e9, 0x1fff033303330333, 0x1fff037e037e037e, 0x1fff03c803c803c8, 0x1fff041304130413, 0x1fff045d045d045d,
- 0x1fff04a804a804a8, 0x1fff04f204f204f2, 0x1fff053d053d053d, 0x1fff058705870587, 0x1fff05d205d205d2, 0x1fff061c061c061c, 0x1fff066706670667, 0x1fff06b106b106b1,
- 0x1fff06fc06fc06fc, 0x1fff074607460746, 0x1fff079107910791, 0x1fff07db07db07db, 0x1fff082608260826, 0x1fff087008700870, 0x1fff08bb08bb08bb, 0x1fff090509050905,
- 0x1fff095009500950, 0x1fff099a099a099a, 0x1fff09e509e509e5, 0x1fff0a2f0a2f0a2f, 0x1fff0a7a0a7a0a7a, 0x1fff0ac40ac40ac4, 0x1fff0b0f0b0f0b0f, 0x1fff0b590b590b59,
- 0x1fff0ba40ba40ba4, 0x1fff0bee0bee0bee, 0x1fff0c390c390c39, 0x1fff0c830c830c83, 0x1fff0cce0cce0cce, 0x1fff0d180d180d18, 0x1fff0d630d630d63, 0x1fff0dad0dad0dad,
- 0x1fff0df80df80df8, 0x1fff0e420e420e42, 0x1fff0e8d0e8d0e8d, 0x1fff0ed70ed70ed7, 0x1fff0f220f220f22, 0x1fff0f6c0f6c0f6c, 0x1fff0fb70fb70fb7, 0x1fff100110011001,
- 0x1fff104c104c104c, 0x1fff109610961096, 0x1fff10e110e110e1, 0x1fff112b112b112b, 0x1fff117611761176, 0x1fff11c011c011c0, 0x1fff120b120b120b, 0x1fff125512551255,
- 0x1fff12a012a012a0, 0x1fff12ea12ea12ea, 0x1fff133513351335, 0x1fff137f137f137f, 0x1fff13ca13ca13ca, 0x1fff141414141414, 0x1fff145f145f145f, 0x1fff14a914a914a9,
- 0x1fff14f414f414f4, 0x1fff153e153e153e, 0x1fff158915891589, 0x1fff15d315d315d3, 0x1fff161e161e161e, 0x1fff166816681668, 0x1fff16b316b316b3, 0x1fff16fd16fd16fd,
- 0x1fff174817481748, 0x1fff179217921792, 0x1fff17dd17dd17dd, 0x1fff182718271827, 0x1fff187218721872, 0x1fff18bc18bc18bc, 0x1fff190719071907, 0x1fff195119511951,
- 0x1fff199c199c199c, 0x1fff19e619e619e6, 0x1fff1a311a311a31, 0x1fff1a7b1a7b1a7b, 0x1fff1ac61ac61ac6, 0x1fff1b101b101b10, 0x1fff1b5b1b5b1b5b, 0x1fff1ba51ba51ba5,
- 0x1fff1bf01bf01bf0, 0x1fff1c3a1c3a1c3a, 0x1fff1c851c851c85, 0x1fff1ccf1ccf1ccf, 0x1fff1d1a1d1a1d1a, 0x1fff1d641d641d64, 0x1fff1daf1daf1daf, 0x1fff1df91df91df9,
- 0x1fff1e441e441e44, 0x1fff1e8e1e8e1e8e, 0x1fff1ed91ed91ed9, 0x1fff1f231f231f23, 0x1fff1f6e1f6e1f6e, 0x1fff1fb81fb81fb8, 0x1fff200320032003, 0x1fff204d204d204d,
- 0x1fff209820982098, 0x1fff20e220e220e2, 0x1fff212d212d212d, 0x1fff217721772177, 0x1fff21c221c221c2, 0x1fff220c220c220c, 0x1fff225722572257, 0x1fff22a122a122a1,
- 0x1fff22ec22ec22ec, 0x1fff233623362336, 0x1fff238123812381, 0x1fff23cb23cb23cb, 0x1fff241624162416, 0x1fff246024602460, 0x1fff24aa24aa24aa, 0x1fff24f524f524f5,
- 0x1fff253f253f253f, 0x1fff258a258a258a, 0x1fff25d425d425d4, 0x1fff261f261f261f, 0x1fff266926692669, 0x1fff26b426b426b4, 0x1fff26fe26fe26fe, 0x1fff274927492749,
- 0x1fff279327932793, 0x1fff27de27de27de, 0x1fff282828282828, 0x1fff287328732873, 0x1fff28bd28bd28bd, 0x1fff290829082908, 0x1fff295229522952, 0x1fff299d299d299d,
- 0x1fff29e729e729e7, 0x1fff2a322a322a32, 0x1fff2a7c2a7c2a7c, 0x1fff2ac72ac72ac7, 0x1fff2b112b112b11, 0x1fff2b5c2b5c2b5c, 0x1fff2ba62ba62ba6, 0x1fff2bf12bf12bf1,
- 0x1fff2c3b2c3b2c3b, 0x1fff2c862c862c86, 0x1fff2cd02cd02cd0, 0x1fff2d1b2d1b2d1b, 0x1fff2d652d652d65, 0x1fff2db02db02db0, 0x1fff2dfa2dfa2dfa, 0x1fff2e452e452e45,
- 0x1fff2e8f2e8f2e8f, 0x1fff2eda2eda2eda, 0x1fff2f242f242f24, 0x1fff2f6f2f6f2f6f, 0x1fff2fb92fb92fb9, 0x1fff300430043004, 0x1fff304e304e304e, 0x1fff309930993099,
- 0x1fff30e330e330e3, 0x1fff312e312e312e, 0x1fff317831783178, 0x1fff31c331c331c3, 0x1fff320d320d320d, 0x1fff325832583258, 0x1fff32a232a232a2, 0x1fff32ed32ed32ed,
- 0x1fff333733373337, 0x1fff338233823382, 0x1fff33cc33cc33cc, 0x1fff341734173417, 0x1fff346134613461, 0x1fff34ac34ac34ac, 0x1fff34f634f634f6, 0x1fff354135413541,
- 0x1fff358b358b358b, 0x1fff35d635d635d6, 0x1fff362036203620, 0x1fff366b366b366b, 0x1fff36b536b536b5, 0x1fff370037003700, 0x1fff374a374a374a, 0x1fff379537953795,
- 0x1fff37df37df37df, 0x1fff382a382a382a, 0x1fff387438743874, 0x1fff38bf38bf38bf, 0x1fff390939093909, 0x1fff395439543954, 0x1fff399e399e399e, 0x1fff39e939e939e9,
- 0x1fff3a333a333a33, 0x1fff3a7e3a7e3a7e, 0x1fff3ac83ac83ac8, 0x1fff3b133b133b13, 0x1fff3b5d3b5d3b5d, 0x1fff3ba83ba83ba8, 0x1fff3bf23bf23bf2, 0x1fff3c3d3c3d3c3d,
- 0x1fff3c873c873c87, 0x1fff3cd23cd23cd2, 0x1fff3d1c3d1c3d1c, 0x1fff3d673d673d67, 0x1fff3db13db13db1, 0x1fff3dfc3dfc3dfc, 0x1fff3e463e463e46, 0x1fff3e913e913e91,
- 0x1fff3edb3edb3edb, 0x1fff3f263f263f26, 0x1fff3f703f703f70, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb,
- 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb,
- 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb, 0x1fff3fbb3fbb3fbb,
- };
- static const __m64 COEFF_U_MMX[256] = {
- 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000,
- 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000, 0x1fffc7800af30000,
- 0x1fffc7800af30000, 0x1fffc8010ada0000, 0x1fffc8820ac10000, 0x1fffc9030aa80000, 0x1fffc9850a8f0000, 0x1fffca060a760000, 0x1fffca870a5d0000, 0x1fffcb080a440000,
- 0x1fffcb890a2a0000, 0x1fffcc0a0a110000, 0x1fffcc8b09f80000, 0x1fffcd0d09df0000, 0x1fffcd8e09c60000, 0x1fffce0f09ad0000, 0x1fffce9009940000, 0x1fffcf11097b0000,
- 0x1fffcf9209620000, 0x1fffd01409490000, 0x1fffd09509300000, 0x1fffd11609170000, 0x1fffd19708fe0000, 0x1fffd21808e50000, 0x1fffd29908cc0000, 0x1fffd31a08b30000,
- 0x1fffd39c089a0000, 0x1fffd41d08810000, 0x1fffd49e08680000, 0x1fffd51f084f0000, 0x1fffd5a008360000, 0x1fffd621081d0000, 0x1fffd6a308040000, 0x1fffd72407eb0000,
- 0x1fffd7a507d20000, 0x1fffd82607b90000, 0x1fffd8a707a00000, 0x1fffd92807870000, 0x1fffd9a9076e0000, 0x1fffda2b07550000, 0x1fffdaac073c0000, 0x1fffdb2d07230000,
- 0x1fffdbae070a0000, 0x1fffdc2f06f10000, 0x1fffdcb006d80000, 0x1fffdd3206bf0000, 0x1fffddb306a60000, 0x1fffde34068d0000, 0x1fffdeb506740000, 0x1fffdf36065b0000,
- 0x1fffdfb706420000, 0x1fffe03806290000, 0x1fffe0ba060f0000, 0x1fffe13b05f60000, 0x1fffe1bc05dd0000, 0x1fffe23d05c40000, 0x1fffe2be05ab0000, 0x1fffe33f05920000,
- 0x1fffe3c005790000, 0x1fffe44205600000, 0x1fffe4c305470000, 0x1fffe544052e0000, 0x1fffe5c505150000, 0x1fffe64604fc0000, 0x1fffe6c704e30000, 0x1fffe74904ca0000,
- 0x1fffe7ca04b10000, 0x1fffe84b04980000, 0x1fffe8cc047f0000, 0x1fffe94d04660000, 0x1fffe9ce044d0000, 0x1fffea4f04340000, 0x1fffead1041b0000, 0x1fffeb5204020000,
- 0x1fffebd303e90000, 0x1fffec5403d00000, 0x1fffecd503b70000, 0x1fffed56039e0000, 0x1fffedd803850000, 0x1fffee59036c0000, 0x1fffeeda03530000, 0x1fffef5b033a0000,
- 0x1fffefdc03210000, 0x1ffff05d03080000, 0x1ffff0de02ef0000, 0x1ffff16002d60000, 0x1ffff1e102bd0000, 0x1ffff26202a40000, 0x1ffff2e3028b0000, 0x1ffff36402720000,
- 0x1ffff3e502590000, 0x1ffff46702400000, 0x1ffff4e802270000, 0x1ffff569020e0000, 0x1ffff5ea01f40000, 0x1ffff66b01db0000, 0x1ffff6ec01c20000, 0x1ffff76d01a90000,
- 0x1ffff7ef01900000, 0x1ffff87001770000, 0x1ffff8f1015e0000, 0x1ffff97201450000, 0x1ffff9f3012c0000, 0x1ffffa7401130000, 0x1ffffaf500fa0000, 0x1ffffb7700e10000,
- 0x1ffffbf800c80000, 0x1ffffc7900af0000, 0x1ffffcfa00960000, 0x1ffffd7b007d0000, 0x1ffffdfc00640000, 0x1ffffe7e004b0000, 0x1ffffeff00320000, 0x1fffff8000190000,
- 0x1fff000000000000, 0x1fff0081ffe80000, 0x1fff0102ffcf0000, 0x1fff0183ffb60000, 0x1fff0205ff9d0000, 0x1fff0286ff840000, 0x1fff0307ff6b0000, 0x1fff0388ff520000,
- 0x1fff0409ff390000, 0x1fff048aff200000, 0x1fff050cff070000, 0x1fff058dfeee0000, 0x1fff060efed50000, 0x1fff068ffebc0000, 0x1fff0710fea30000, 0x1fff0791fe8a0000,
- 0x1fff0812fe710000, 0x1fff0894fe580000, 0x1fff0915fe3f0000, 0x1fff0996fe260000, 0x1fff0a17fe0d0000, 0x1fff0a98fdf30000, 0x1fff0b19fdda0000, 0x1fff0b9afdc10000,
- 0x1fff0c1cfda80000, 0x1fff0c9dfd8f0000, 0x1fff0d1efd760000, 0x1fff0d9ffd5d0000, 0x1fff0e20fd440000, 0x1fff0ea1fd2b0000, 0x1fff0f23fd120000, 0x1fff0fa4fcf90000,
- 0x1fff1025fce00000, 0x1fff10a6fcc70000, 0x1fff1127fcae0000, 0x1fff11a8fc950000, 0x1fff1229fc7c0000, 0x1fff12abfc630000, 0x1fff132cfc4a0000, 0x1fff13adfc310000,
- 0x1fff142efc180000, 0x1fff14affbff0000, 0x1fff1530fbe60000, 0x1fff15b2fbcd0000, 0x1fff1633fbb40000, 0x1fff16b4fb9b0000, 0x1fff1735fb820000, 0x1fff17b6fb690000,
- 0x1fff1837fb500000, 0x1fff18b8fb370000, 0x1fff193afb1e0000, 0x1fff19bbfb050000, 0x1fff1a3cfaec0000, 0x1fff1abdfad30000, 0x1fff1b3efaba0000, 0x1fff1bbffaa10000,
- 0x1fff1c41fa880000, 0x1fff1cc2fa6f0000, 0x1fff1d43fa560000, 0x1fff1dc4fa3d0000, 0x1fff1e45fa240000, 0x1fff1ec6fa0b0000, 0x1fff1f47f9f20000, 0x1fff1fc9f9d80000,
- 0x1fff204af9bf0000, 0x1fff20cbf9a60000, 0x1fff214cf98d0000, 0x1fff21cdf9740000, 0x1fff224ef95b0000, 0x1fff22cff9420000, 0x1fff2351f9290000, 0x1fff23d2f9100000,
- 0x1fff2453f8f70000, 0x1fff24d4f8de0000, 0x1fff2555f8c50000, 0x1fff25d6f8ac0000, 0x1fff2658f8930000, 0x1fff26d9f87a0000, 0x1fff275af8610000, 0x1fff27dbf8480000,
- 0x1fff285cf82f0000, 0x1fff28ddf8160000, 0x1fff295ef7fd0000, 0x1fff29e0f7e40000, 0x1fff2a61f7cb0000, 0x1fff2ae2f7b20000, 0x1fff2b63f7990000, 0x1fff2be4f7800000,
- 0x1fff2c65f7670000, 0x1fff2ce7f74e0000, 0x1fff2d68f7350000, 0x1fff2de9f71c0000, 0x1fff2e6af7030000, 0x1fff2eebf6ea0000, 0x1fff2f6cf6d10000, 0x1fff2fedf6b80000,
- 0x1fff306ff69f0000, 0x1fff30f0f6860000, 0x1fff3171f66d0000, 0x1fff31f2f6540000, 0x1fff3273f63b0000, 0x1fff32f4f6220000, 0x1fff3376f6090000, 0x1fff33f7f5f00000,
- 0x1fff3478f5d70000, 0x1fff34f9f5bd0000, 0x1fff357af5a40000, 0x1fff35fbf58b0000, 0x1fff367cf5720000, 0x1fff36fef5590000, 0x1fff377ff5400000, 0x1fff3800f5270000,
- 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000,
- 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000, 0x1fff3881f50e0000,
- };
- static const __m64 COEFF_V_MMX[256] = {
- 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351,
- 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351, 0x1fff000016c4d351,
- 0x1fff000016c4d351, 0x1fff00001690d3b7, 0x1fff0000165cd41d, 0x1fff00001627d483, 0x1fff000015f3d4e9, 0x1fff000015bfd550, 0x1fff0000158bd5b6, 0x1fff00001557d61c,
- 0x1fff00001523d682, 0x1fff000014efd6e8, 0x1fff000014bbd74e, 0x1fff00001487d7b4, 0x1fff00001453d81b, 0x1fff0000141fd881, 0x1fff000013ebd8e7, 0x1fff000013b7d94d,
- 0x1fff00001383d9b3, 0x1fff0000134fda19, 0x1fff0000131bda7f, 0x1fff000012e7dae6, 0x1fff000012b3db4c, 0x1fff0000127fdbb2, 0x1fff0000124bdc18, 0x1fff00001217dc7e,
- 0x1fff000011e3dce4, 0x1fff000011afdd4a, 0x1fff0000117bddb1, 0x1fff00001147de17, 0x1fff00001113de7d, 0x1fff000010dfdee3, 0x1fff000010abdf49, 0x1fff00001077dfaf,
- 0x1fff00001043e015, 0x1fff0000100fe07c, 0x1fff00000fdae0e2, 0x1fff00000fa6e148, 0x1fff00000f72e1ae, 0x1fff00000f3ee214, 0x1fff00000f0ae27a, 0x1fff00000ed6e2e0,
- 0x1fff00000ea2e347, 0x1fff00000e6ee3ad, 0x1fff00000e3ae413, 0x1fff00000e06e479, 0x1fff00000dd2e4df, 0x1fff00000d9ee545, 0x1fff00000d6ae5ab, 0x1fff00000d36e612,
- 0x1fff00000d02e678, 0x1fff00000ccee6de, 0x1fff00000c9ae744, 0x1fff00000c66e7aa, 0x1fff00000c32e810, 0x1fff00000bfee877, 0x1fff00000bcae8dd, 0x1fff00000b96e943,
- 0x1fff00000b62e9a9, 0x1fff00000b2eea0f, 0x1fff00000afaea75, 0x1fff00000ac6eadb, 0x1fff00000a92eb42, 0x1fff00000a5eeba8, 0x1fff00000a2aec0e, 0x1fff000009f6ec74,
- 0x1fff000009c2ecda, 0x1fff0000098eed40, 0x1fff00000959eda6, 0x1fff00000925ee0d, 0x1fff000008f1ee73, 0x1fff000008bdeed9, 0x1fff00000889ef3f, 0x1fff00000855efa5,
- 0x1fff00000821f00b, 0x1fff000007edf071, 0x1fff000007b9f0d8, 0x1fff00000785f13e, 0x1fff00000751f1a4, 0x1fff0000071df20a, 0x1fff000006e9f270, 0x1fff000006b5f2d6,
- 0x1fff00000681f33c, 0x1fff0000064df3a3, 0x1fff00000619f409, 0x1fff000005e5f46f, 0x1fff000005b1f4d5, 0x1fff0000057df53b, 0x1fff00000549f5a1, 0x1fff00000515f607,
- 0x1fff000004e1f66e, 0x1fff000004adf6d4, 0x1fff00000479f73a, 0x1fff00000445f7a0, 0x1fff00000411f806, 0x1fff000003ddf86c, 0x1fff000003a9f8d2, 0x1fff00000375f939,
- 0x1fff00000341f99f, 0x1fff0000030cfa05, 0x1fff000002d8fa6b, 0x1fff000002a4fad1, 0x1fff00000270fb37, 0x1fff0000023cfb9d, 0x1fff00000208fc04, 0x1fff000001d4fc6a,
- 0x1fff000001a0fcd0, 0x1fff0000016cfd36, 0x1fff00000138fd9c, 0x1fff00000104fe02, 0x1fff000000d0fe68, 0x1fff0000009cfecf, 0x1fff00000068ff35, 0x1fff00000034ff9b,
- 0x1fff000000000000, 0x1fff0000ffcd0066, 0x1fff0000ff9900cc, 0x1fff0000ff650132, 0x1fff0000ff310199, 0x1fff0000fefd01ff, 0x1fff0000fec90265, 0x1fff0000fe9502cb,
- 0x1fff0000fe610331, 0x1fff0000fe2d0397, 0x1fff0000fdf903fd, 0x1fff0000fdc50464, 0x1fff0000fd9104ca, 0x1fff0000fd5d0530, 0x1fff0000fd290596, 0x1fff0000fcf505fc,
- 0x1fff0000fcc00662, 0x1fff0000fc8c06c8, 0x1fff0000fc58072f, 0x1fff0000fc240795, 0x1fff0000fbf007fb, 0x1fff0000fbbc0861, 0x1fff0000fb8808c7, 0x1fff0000fb54092d,
- 0x1fff0000fb200993, 0x1fff0000faec09fa, 0x1fff0000fab80a60, 0x1fff0000fa840ac6, 0x1fff0000fa500b2c, 0x1fff0000fa1c0b92, 0x1fff0000f9e80bf8, 0x1fff0000f9b40c5e,
- 0x1fff0000f9800cc5, 0x1fff0000f94c0d2b, 0x1fff0000f9180d91, 0x1fff0000f8e40df7, 0x1fff0000f8b00e5d, 0x1fff0000f87c0ec3, 0x1fff0000f8480f29, 0x1fff0000f8140f90,
- 0x1fff0000f7e00ff6, 0x1fff0000f7ac105c, 0x1fff0000f77810c2, 0x1fff0000f7441128, 0x1fff0000f710118e, 0x1fff0000f6dc11f4, 0x1fff0000f6a8125b, 0x1fff0000f67312c1,
- 0x1fff0000f63f1327, 0x1fff0000f60b138d, 0x1fff0000f5d713f3, 0x1fff0000f5a31459, 0x1fff0000f56f14bf, 0x1fff0000f53b1526, 0x1fff0000f507158c, 0x1fff0000f4d315f2,
- 0x1fff0000f49f1658, 0x1fff0000f46b16be, 0x1fff0000f4371724, 0x1fff0000f403178a, 0x1fff0000f3cf17f1, 0x1fff0000f39b1857, 0x1fff0000f36718bd, 0x1fff0000f3331923,
- 0x1fff0000f2ff1989, 0x1fff0000f2cb19ef, 0x1fff0000f2971a56, 0x1fff0000f2631abc, 0x1fff0000f22f1b22, 0x1fff0000f1fb1b88, 0x1fff0000f1c71bee, 0x1fff0000f1931c54,
- 0x1fff0000f15f1cba, 0x1fff0000f12b1d21, 0x1fff0000f0f71d87, 0x1fff0000f0c31ded, 0x1fff0000f08f1e53, 0x1fff0000f05b1eb9, 0x1fff0000f0271f1f, 0x1fff0000eff21f85,
- 0x1fff0000efbe1fec, 0x1fff0000ef8a2052, 0x1fff0000ef5620b8, 0x1fff0000ef22211e, 0x1fff0000eeee2184, 0x1fff0000eeba21ea, 0x1fff0000ee862250, 0x1fff0000ee5222b7,
- 0x1fff0000ee1e231d, 0x1fff0000edea2383, 0x1fff0000edb623e9, 0x1fff0000ed82244f, 0x1fff0000ed4e24b5, 0x1fff0000ed1a251b, 0x1fff0000ece62582, 0x1fff0000ecb225e8,
- 0x1fff0000ec7e264e, 0x1fff0000ec4a26b4, 0x1fff0000ec16271a, 0x1fff0000ebe22780, 0x1fff0000ebae27e6, 0x1fff0000eb7a284d, 0x1fff0000eb4628b3, 0x1fff0000eb122919,
- 0x1fff0000eade297f, 0x1fff0000eaaa29e5, 0x1fff0000ea762a4b, 0x1fff0000ea422ab1, 0x1fff0000ea0e2b18, 0x1fff0000e9da2b7e, 0x1fff0000e9a52be4, 0x1fff0000e9712c4a,
- 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0,
- 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0, 0x1fff0000e93d2cb0,
- };
-
- // -----------------------------------------------------------------------------
-
- void YUVtoRGBA_MMX(yuv_buffer & YUVBuffer, std::vector<unsigned char> & PixelData)
- {
- // Width and height of all buffers have to be divisible by 4.
- BS_ASSERT((YUVBuffer.y_width & 3) == 0);
- BS_ASSERT((YUVBuffer.y_height & 3) == 0);
- BS_ASSERT((YUVBuffer.uv_width & 3) == 0);
- BS_ASSERT((YUVBuffer.uv_height & 3) == 0);
- // UV images have to have a quarter of the Y image resolution
- BS_ASSERT(YUVBuffer.uv_width == YUVBuffer.y_width >> 1);
- BS_ASSERT(YUVBuffer.uv_height == YUVBuffer.y_height >> 1);
-
- const unsigned char * ySrc = YUVBuffer.y;
- const unsigned char * uSrc = YUVBuffer.u;
- const unsigned char * vSrc = YUVBuffer.v;
- unsigned char * dst = &PixelData[0];
-
- const int yPadding = YUVBuffer.y_stride - YUVBuffer.y_width;
- int uvStride = YUVBuffer.uv_stride;
-
- for (int h = 0; h < YUVBuffer.y_height; ++h)
- {
- uvStride ^= YUVBuffer.uv_stride;
- for (int w = 0; w < YUVBuffer.y_width / 4; ++w)
- {
- __m64 uvCoeff0 = _m_paddw(COEFF_U_MMX[*uSrc++], COEFF_V_MMX[*vSrc++]);
- __m64 uvCoeff1 = _m_paddw(COEFF_U_MMX[*uSrc++], COEFF_V_MMX[*vSrc++]);
-
- __m64 px01 = COEFF_Y_MMX[*ySrc++];
- __m64 px23 = COEFF_Y_MMX[*ySrc++];
- __m64 px45 = COEFF_Y_MMX[*ySrc++];
- __m64 px67 = COEFF_Y_MMX[*ySrc++];
-
- px01 = _m_paddw(px01, uvCoeff0);
- px23 = _m_paddw(px23, uvCoeff0);
- px45 = _m_paddw(px45, uvCoeff1);
- px67 = _m_paddw(px67, uvCoeff1);
-
- px01 = _m_psrawi(px01, 6);
- px23 = _m_psrawi(px23, 6);
- px45 = _m_psrawi(px45, 6);
- px67 = _m_psrawi(px67, 6);
-
- ((__m64*)dst)[0] = _m_packuswb(px01, px23);
- ((__m64*)dst)[1] = _m_packuswb(px45, px67);
- dst += 16;
- }
-
- ySrc += yPadding;
- uSrc += uvStride - YUVBuffer.uv_width;
- vSrc += uvStride - YUVBuffer.uv_width;
+namespace Sword25 {
+
+static const int PRECISION = 32768;
+static const int COEFFS_Y[256] = {
+ -593888, -555746, -517604, -479462, -441320, -403178, -365036, -326894, -288752, -250610, -212468, -174326, -136184, -98042, -59900, -21758,
+ 16384, 54526, 92668, 130810, 168952, 207094, 245236, 283378, 321520, 359662, 397804, 435946, 474088, 512230, 550372, 588514,
+ 626656, 664798, 702940, 741082, 779224, 817366, 855508, 893650, 931792, 969934, 1008076, 1046218, 1084360, 1122502, 1160644, 1198786,
+ 1236928, 1275070, 1313212, 1351354, 1389496, 1427638, 1465780, 1503922, 1542064, 1580206, 1618348, 1656490, 1694632, 1732774, 1770916, 1809058,
+ 1847200, 1885342, 1923484, 1961626, 1999768, 2037910, 2076052, 2114194, 2152336, 2190478, 2228620, 2266762, 2304904, 2343046, 2381188, 2419330,
+ 2457472, 2495614, 2533756, 2571898, 2610040, 2648182, 2686324, 2724466, 2762608, 2800750, 2838892, 2877034, 2915176, 2953318, 2991460, 3029602,
+ 3067744, 3105886, 3144028, 3182170, 3220312, 3258454, 3296596, 3334738, 3372880, 3411022, 3449164, 3487306, 3525448, 3563590, 3601732, 3639874,
+ 3678016, 3716158, 3754300, 3792442, 3830584, 3868726, 3906868, 3945010, 3983152, 4021294, 4059436, 4097578, 4135720, 4173862, 4212004, 4250146,
+ 4288288, 4326430, 4364572, 4402714, 4440856, 4478998, 4517140, 4555282, 4593424, 4631566, 4669708, 4707850, 4745992, 4784134, 4822276, 4860418,
+ 4898560, 4936702, 4974844, 5012986, 5051128, 5089270, 5127412, 5165554, 5203696, 5241838, 5279980, 5318122, 5356264, 5394406, 5432548, 5470690,
+ 5508832, 5546974, 5585116, 5623258, 5661400, 5699542, 5737684, 5775826, 5813968, 5852110, 5890252, 5928394, 5966536, 6004678, 6042820, 6080962,
+ 6119104, 6157246, 6195388, 6233530, 6271672, 6309814, 6347956, 6386098, 6424240, 6462382, 6500524, 6538666, 6576808, 6614950, 6653092, 6691234,
+ 6729376, 6767518, 6805660, 6843802, 6881944, 6920086, 6958228, 6996370, 7034512, 7072654, 7110796, 7148938, 7187080, 7225222, 7263364, 7301506,
+ 7339648, 7377790, 7415932, 7454074, 7492216, 7530358, 7568500, 7606642, 7644784, 7682926, 7721068, 7759210, 7797352, 7835494, 7873636, 7911778,
+ 7949920, 7988062, 8026204, 8064346, 8102488, 8140630, 8178772, 8216914, 8255056, 8293198, 8331340, 8369482, 8407624, 8445766, 8483908, 8522050,
+ 8560192, 8598334, 8636476, 8674618, 8712760, 8750902, 8789044, 8827186, 8865328, 8903470, 8941612, 8979754, 9017896, 9056038, 9094180, 9132322,
+};
+static const int COEFFS_RV[256] = {
+ -6694144, -6641846, -6589548, -6537250, -6484952, -6432654, -6380356, -6328058, -6275760, -6223462, -6171164, -6118866, -6066568, -6014270, -5961972, -5909674,
+ -5857376, -5805078, -5752780, -5700482, -5648184, -5595886, -5543588, -5491290, -5438992, -5386694, -5334396, -5282098, -5229800, -5177502, -5125204, -5072906,
+ -5020608, -4968310, -4916012, -4863714, -4811416, -4759118, -4706820, -4654522, -4602224, -4549926, -4497628, -4445330, -4393032, -4340734, -4288436, -4236138,
+ -4183840, -4131542, -4079244, -4026946, -3974648, -3922350, -3870052, -3817754, -3765456, -3713158, -3660860, -3608562, -3556264, -3503966, -3451668, -3399370,
+ -3347072, -3294774, -3242476, -3190178, -3137880, -3085582, -3033284, -2980986, -2928688, -2876390, -2824092, -2771794, -2719496, -2667198, -2614900, -2562602,
+ -2510304, -2458006, -2405708, -2353410, -2301112, -2248814, -2196516, -2144218, -2091920, -2039622, -1987324, -1935026, -1882728, -1830430, -1778132, -1725834,
+ -1673536, -1621238, -1568940, -1516642, -1464344, -1412046, -1359748, -1307450, -1255152, -1202854, -1150556, -1098258, -1045960, -993662, -941364, -889066,
+ -836768, -784470, -732172, -679874, -627576, -575278, -522980, -470682, -418384, -366086, -313788, -261490, -209192, -156894, -104596, -52298,
+ 0, 52298, 104596, 156894, 209192, 261490, 313788, 366086, 418384, 470682, 522980, 575278, 627576, 679874, 732172, 784470,
+ 836768, 889066, 941364, 993662, 1045960, 1098258, 1150556, 1202854, 1255152, 1307450, 1359748, 1412046, 1464344, 1516642, 1568940, 1621238,
+ 1673536, 1725834, 1778132, 1830430, 1882728, 1935026, 1987324, 2039622, 2091920, 2144218, 2196516, 2248814, 2301112, 2353410, 2405708, 2458006,
+ 2510304, 2562602, 2614900, 2667198, 2719496, 2771794, 2824092, 2876390, 2928688, 2980986, 3033284, 3085582, 3137880, 3190178, 3242476, 3294774,
+ 3347072, 3399370, 3451668, 3503966, 3556264, 3608562, 3660860, 3713158, 3765456, 3817754, 3870052, 3922350, 3974648, 4026946, 4079244, 4131542,
+ 4183840, 4236138, 4288436, 4340734, 4393032, 4445330, 4497628, 4549926, 4602224, 4654522, 4706820, 4759118, 4811416, 4863714, 4916012, 4968310,
+ 5020608, 5072906, 5125204, 5177502, 5229800, 5282098, 5334396, 5386694, 5438992, 5491290, 5543588, 5595886, 5648184, 5700482, 5752780, 5805078,
+ 5857376, 5909674, 5961972, 6014270, 6066568, 6118866, 6171164, 6223462, 6275760, 6328058, 6380356, 6432654, 6484952, 6537250, 6589548, 6641846,
+};
+static const int COEFFS_GU[256] = {
+ 1639936, 1627124, 1614312, 1601500, 1588688, 1575876, 1563064, 1550252, 1537440, 1524628, 1511816, 1499004, 1486192, 1473380, 1460568, 1447756,
+ 1434944, 1422132, 1409320, 1396508, 1383696, 1370884, 1358072, 1345260, 1332448, 1319636, 1306824, 1294012, 1281200, 1268388, 1255576, 1242764,
+ 1229952, 1217140, 1204328, 1191516, 1178704, 1165892, 1153080, 1140268, 1127456, 1114644, 1101832, 1089020, 1076208, 1063396, 1050584, 1037772,
+ 1024960, 1012148, 999336, 986524, 973712, 960900, 948088, 935276, 922464, 909652, 896840, 884028, 871216, 858404, 845592, 832780,
+ 819968, 807156, 794344, 781532, 768720, 755908, 743096, 730284, 717472, 704660, 691848, 679036, 666224, 653412, 640600, 627788,
+ 614976, 602164, 589352, 576540, 563728, 550916, 538104, 525292, 512480, 499668, 486856, 474044, 461232, 448420, 435608, 422796,
+ 409984, 397172, 384360, 371548, 358736, 345924, 333112, 320300, 307488, 294676, 281864, 269052, 256240, 243428, 230616, 217804,
+ 204992, 192180, 179368, 166556, 153744, 140932, 128120, 115308, 102496, 89684, 76872, 64060, 51248, 38436, 25624, 12812,
+ 0, -12812, -25624, -38436, -51248, -64060, -76872, -89684, -102496, -115308, -128120, -140932, -153744, -166556, -179368, -192180,
+ -204992, -217804, -230616, -243428, -256240, -269052, -281864, -294676, -307488, -320300, -333112, -345924, -358736, -371548, -384360, -397172,
+ -409984, -422796, -435608, -448420, -461232, -474044, -486856, -499668, -512480, -525292, -538104, -550916, -563728, -576540, -589352, -602164,
+ -614976, -627788, -640600, -653412, -666224, -679036, -691848, -704660, -717472, -730284, -743096, -755908, -768720, -781532, -794344, -807156,
+ -819968, -832780, -845592, -858404, -871216, -884028, -896840, -909652, -922464, -935276, -948088, -960900, -973712, -986524, -999336, -1012148,
+ -1024960, -1037772, -1050584, -1063396, -1076208, -1089020, -1101832, -1114644, -1127456, -1140268, -1153080, -1165892, -1178704, -1191516, -1204328, -1217140,
+ -1229952, -1242764, -1255576, -1268388, -1281200, -1294012, -1306824, -1319636, -1332448, -1345260, -1358072, -1370884, -1383696, -1396508, -1409320, -1422132,
+ -1434944, -1447756, -1460568, -1473380, -1486192, -1499004, -1511816, -1524628, -1537440, -1550252, -1563064, -1575876, -1588688, -1601500, -1614312, -1627124,
+};
+static const int COEFFS_GV[256] = {
+ 3409920, 3383280, 3356640, 3330000, 3303360, 3276720, 3250080, 3223440, 3196800, 3170160, 3143520, 3116880, 3090240, 3063600, 3036960, 3010320,
+ 2983680, 2957040, 2930400, 2903760, 2877120, 2850480, 2823840, 2797200, 2770560, 2743920, 2717280, 2690640, 2664000, 2637360, 2610720, 2584080,
+ 2557440, 2530800, 2504160, 2477520, 2450880, 2424240, 2397600, 2370960, 2344320, 2317680, 2291040, 2264400, 2237760, 2211120, 2184480, 2157840,
+ 2131200, 2104560, 2077920, 2051280, 2024640, 1998000, 1971360, 1944720, 1918080, 1891440, 1864800, 1838160, 1811520, 1784880, 1758240, 1731600,
+ 1704960, 1678320, 1651680, 1625040, 1598400, 1571760, 1545120, 1518480, 1491840, 1465200, 1438560, 1411920, 1385280, 1358640, 1332000, 1305360,
+ 1278720, 1252080, 1225440, 1198800, 1172160, 1145520, 1118880, 1092240, 1065600, 1038960, 1012320, 985680, 959040, 932400, 905760, 879120,
+ 852480, 825840, 799200, 772560, 745920, 719280, 692640, 666000, 639360, 612720, 586080, 559440, 532800, 506160, 479520, 452880,
+ 426240, 399600, 372960, 346320, 319680, 293040, 266400, 239760, 213120, 186480, 159840, 133200, 106560, 79920, 53280, 26640,
+ 0, -26640, -53280, -79920, -106560, -133200, -159840, -186480, -213120, -239760, -266400, -293040, -319680, -346320, -372960, -399600,
+ -426240, -452880, -479520, -506160, -532800, -559440, -586080, -612720, -639360, -666000, -692640, -719280, -745920, -772560, -799200, -825840,
+ -852480, -879120, -905760, -932400, -959040, -985680, -1012320, -1038960, -1065600, -1092240, -1118880, -1145520, -1172160, -1198800, -1225440, -1252080,
+ -1278720, -1305360, -1332000, -1358640, -1385280, -1411920, -1438560, -1465200, -1491840, -1518480, -1545120, -1571760, -1598400, -1625040, -1651680, -1678320,
+ -1704960, -1731600, -1758240, -1784880, -1811520, -1838160, -1864800, -1891440, -1918080, -1944720, -1971360, -1998000, -2024640, -2051280, -2077920, -2104560,
+ -2131200, -2157840, -2184480, -2211120, -2237760, -2264400, -2291040, -2317680, -2344320, -2370960, -2397600, -2424240, -2450880, -2477520, -2504160, -2530800,
+ -2557440, -2584080, -2610720, -2637360, -2664000, -2690640, -2717280, -2743920, -2770560, -2797200, -2823840, -2850480, -2877120, -2903760, -2930400, -2957040,
+ -2983680, -3010320, -3036960, -3063600, -3090240, -3116880, -3143520, -3170160, -3196800, -3223440, -3250080, -3276720, -3303360, -3330000, -3356640, -3383280,
+};
+static const int COEFFS_BU[256] = {
+ -8464128, -8398002, -8331876, -8265750, -8199624, -8133498, -8067372, -8001246, -7935120, -7868994, -7802868, -7736742, -7670616, -7604490, -7538364, -7472238,
+ -7406112, -7339986, -7273860, -7207734, -7141608, -7075482, -7009356, -6943230, -6877104, -6810978, -6744852, -6678726, -6612600, -6546474, -6480348, -6414222,
+ -6348096, -6281970, -6215844, -6149718, -6083592, -6017466, -5951340, -5885214, -5819088, -5752962, -5686836, -5620710, -5554584, -5488458, -5422332, -5356206,
+ -5290080, -5223954, -5157828, -5091702, -5025576, -4959450, -4893324, -4827198, -4761072, -4694946, -4628820, -4562694, -4496568, -4430442, -4364316, -4298190,
+ -4232064, -4165938, -4099812, -4033686, -3967560, -3901434, -3835308, -3769182, -3703056, -3636930, -3570804, -3504678, -3438552, -3372426, -3306300, -3240174,
+ -3174048, -3107922, -3041796, -2975670, -2909544, -2843418, -2777292, -2711166, -2645040, -2578914, -2512788, -2446662, -2380536, -2314410, -2248284, -2182158,
+ -2116032, -2049906, -1983780, -1917654, -1851528, -1785402, -1719276, -1653150, -1587024, -1520898, -1454772, -1388646, -1322520, -1256394, -1190268, -1124142,
+ -1058016, -991890, -925764, -859638, -793512, -727386, -661260, -595134, -529008, -462882, -396756, -330630, -264504, -198378, -132252, -66126,
+ 0, 66126, 132252, 198378, 264504, 330630, 396756, 462882, 529008, 595134, 661260, 727386, 793512, 859638, 925764, 991890,
+ 1058016, 1124142, 1190268, 1256394, 1322520, 1388646, 1454772, 1520898, 1587024, 1653150, 1719276, 1785402, 1851528, 1917654, 1983780, 2049906,
+ 2116032, 2182158, 2248284, 2314410, 2380536, 2446662, 2512788, 2578914, 2645040, 2711166, 2777292, 2843418, 2909544, 2975670, 3041796, 3107922,
+ 3174048, 3240174, 3306300, 3372426, 3438552, 3504678, 3570804, 3636930, 3703056, 3769182, 3835308, 3901434, 3967560, 4033686, 4099812, 4165938,
+ 4232064, 4298190, 4364316, 4430442, 4496568, 4562694, 4628820, 4694946, 4761072, 4827198, 4893324, 4959450, 5025576, 5091702, 5157828, 5223954,
+ 5290080, 5356206, 5422332, 5488458, 5554584, 5620710, 5686836, 5752962, 5819088, 5885214, 5951340, 6017466, 6083592, 6149718, 6215844, 6281970,
+ 6348096, 6414222, 6480348, 6546474, 6612600, 6678726, 6744852, 6810978, 6877104, 6943230, 7009356, 7075482, 7141608, 7207734, 7273860, 7339986,
+ 7406112, 7472238, 7538364, 7604490, 7670616, 7736742, 7802868, 7868994, 7935120, 8001246, 8067372, 8133498, 8199624, 8265750, 8331876, 8398002,
+};
+static const int CLAMP_TAB[1024] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+};
+
+void BS_YUVtoRGBA::YUVtoRGBA(yuv_buffer &YUVBuffer, const theora_info &TheoraInfo, byte *Pixels, int PixelsSize) {
+ BS_ASSERT(TheoraInfo.pixelformat == OC_PF_420);
+ BS_ASSERT(PixelsSize >= (YUVBuffer.y_width * YUVBuffer.y_height));
+
+ // Width and height of all buffers have to be divisible by 2.
+ BS_ASSERT((YUVBuffer.y_width & 1) == 0);
+ BS_ASSERT((YUVBuffer.y_height & 1) == 0);
+ BS_ASSERT((YUVBuffer.uv_width & 1) == 0);
+ BS_ASSERT((YUVBuffer.uv_height & 1) == 0);
+ // UV images have to have a quarter of the Y image resolution
+ BS_ASSERT(YUVBuffer.uv_width == YUVBuffer.y_width >> 1);
+ BS_ASSERT(YUVBuffer.uv_height == YUVBuffer.y_height >> 1);
+
+ const int *cl = &CLAMP_TAB[320];
+
+ const unsigned char *ySrc0 = YUVBuffer.y;
+ const unsigned char *ySrc1 = YUVBuffer.y + YUVBuffer.y_stride;
+ const unsigned char *uSrc = YUVBuffer.u;
+ const unsigned char *vSrc = YUVBuffer.v;
+ unsigned char *dst0 = &Pixels[0];
+ unsigned char *dst1 = &Pixels[0] + YUVBuffer.y_width * 4;
+
+ for (int h = 0; h < YUVBuffer.y_height / 2; ++h) {
+ for (int w = 0; w < YUVBuffer.y_width / 2; ++w) {
+ int u = *uSrc++;
+ int v = *vSrc++;
+
+ int rUV = COEFFS_RV[v];
+ int gUV = COEFFS_GU[u] + COEFFS_GV[v];
+ int bUV = COEFFS_BU[u];
+
+ int y = *ySrc0++;
+ int r = COEFFS_Y[y] + rUV;
+ int g = COEFFS_Y[y] + gUV;
+ int b = COEFFS_Y[y] + bUV;
+ *dst0++ = cl[r / PRECISION];
+ *dst0++ = cl[g / PRECISION];
+ *dst0++ = cl[b / PRECISION];
+ *dst0++ = 255;
+
+ y = *ySrc1++;
+ r = COEFFS_Y[y] + rUV;
+ g = COEFFS_Y[y] + gUV;
+ b = COEFFS_Y[y] + bUV;
+ *dst1++ = cl[r / PRECISION];
+ *dst1++ = cl[g / PRECISION];
+ *dst1++ = cl[b / PRECISION];
+ *dst1++ = 255;
+
+ y = *ySrc0++;
+ r = COEFFS_Y[y] + rUV;
+ g = COEFFS_Y[y] + gUV;
+ b = COEFFS_Y[y] + bUV;
+ *dst0++ = cl[r / PRECISION];
+ *dst0++ = cl[g / PRECISION];
+ *dst0++ = cl[b / PRECISION];
+ *dst0++ = 255;
+
+ y = *ySrc1++;
+ r = COEFFS_Y[y] + rUV;
+ g = COEFFS_Y[y] + gUV;
+ b = COEFFS_Y[y] + bUV;
+ *dst1++ = cl[r / PRECISION];
+ *dst1++ = cl[g / PRECISION];
+ *dst1++ = cl[b / PRECISION];
+ *dst1++ = 255;
}
- _m_empty();
+ dst0 += YUVBuffer.y_width * 4;
+ dst1 += YUVBuffer.y_width * 4;
+ ySrc0 += YUVBuffer.y_stride * 2 - YUVBuffer.y_width;
+ ySrc1 += YUVBuffer.y_stride * 2 - YUVBuffer.y_width;
+ uSrc += YUVBuffer.uv_stride - YUVBuffer.uv_width;
+ vSrc += YUVBuffer.uv_stride - YUVBuffer.uv_width;
}
-
}
-// -----------------------------------------------------------------------------
-
-void BS_YUVtoRGBA::YUVtoRGBA(yuv_buffer & YUVBuffer, const theora_info & TheoraInfo, vector<unsigned char> & Pixels)
-{
- BS_ASSERT(TheoraInfo.pixelformat == OC_PF_420);
- BS_ASSERT(int(Pixels.size()) >= YUVBuffer.y_width * YUVBuffer.y_height);
-
- return YUVtoRGBA_c(YUVBuffer, Pixels);
-
- if (BS_CPUInfo::GetInstance().IsMMXSupported())
- return YUVtoRGBA_MMX(YUVBuffer, Pixels);
- else
- return YUVtoRGBA_c(YUVBuffer, Pixels);
-}
+} // End of namespace Sword25
diff --git a/engines/sword25/fmv/oggtheora/yuvtorgba.h b/engines/sword25/fmv/oggtheora/yuvtorgba.h
index 6593254ff9..5b0332a807 100644
--- a/engines/sword25/fmv/oggtheora/yuvtorgba.h
+++ b/engines/sword25/fmv/oggtheora/yuvtorgba.h
@@ -39,21 +39,19 @@
// Includes
// -----------------------------------------------------------------------------
-#include "sword25/kernel/memlog_off.h"
-#include <vector>
-#include "sword25/kernel/memlog_on.h"
-
#include "sword25/kernel/common.h"
-#include "theora/theora.h"
+#include <theora/theora.h>
+namespace Sword25 {
// -----------------------------------------------------------------------------
// Klassendefinition
// -----------------------------------------------------------------------------
-class BS_YUVtoRGBA
-{
+class BS_YUVtoRGBA {
public:
- static void YUVtoRGBA(yuv_buffer & YUVBuffer, const theora_info & TheoraInfo, std::vector<unsigned char> & Pixels);
+ static void YUVtoRGBA(yuv_buffer &YUVBuffer, const theora_info &TheoraInfo, byte *Pixels, int PixelsSize);
};
+} // End of namespace Sword25
+
#endif