- rewrote movie player so that the decoder backends only perform the decoding but do not draw the frames themselves.

This caused twq problems:

1. It made it impossible to let the client apply effects to the video.
2. The client had no control when rendering stopped.

Now the backends only provide a texture handle that the client must draw. One immediate benefit is that Blood's fixed viewport scaling is now available to all video formats.
This commit is contained in:
Christoph Oelckers 2021-05-01 18:59:16 +02:00
parent 47a09b4f14
commit 27799def63
2 changed files with 51 additions and 19 deletions

View file

@ -67,6 +67,7 @@ public:
virtual bool Frame(uint64_t clock) = 0; virtual bool Frame(uint64_t clock) = 0;
virtual void Stop() {} virtual void Stop() {}
virtual ~MoviePlayer() = default; virtual ~MoviePlayer() = default;
virtual FTextureID GetTexture() = 0;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -119,17 +120,12 @@ public:
if (currentclock < nextframetime - 1) if (currentclock < nextframetime - 1)
{ {
twod->ClearScreen();
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Masked, false, TAG_DONE);
return true; return true;
} }
animtex.SetFrame(ANIM_GetPalette(&anim), ANIM_DrawFrame(&anim, curframe)); animtex.SetFrame(ANIM_GetPalette(&anim), ANIM_DrawFrame(&anim, curframe));
frametime = currentclock; frametime = currentclock;
twod->ClearScreen();
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Masked, false, TAG_DONE);
int delay = 20; int delay = 20;
if (frameTicks) if (frameTicks)
{ {
@ -168,6 +164,11 @@ public:
buffer.Reset(); buffer.Reset();
animtex.Clean(); animtex.Clean();
} }
FTextureID GetTexture() override
{
return animtex.GetFrameID();
}
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -199,8 +200,6 @@ public:
{ {
if (failed) return false; if (failed) return false;
bool playon = decoder.RunFrame(clock); bool playon = decoder.RunFrame(clock);
twod->ClearScreen();
DrawTexture(twod, decoder.animTex().GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
return playon; return playon;
} }
@ -208,6 +207,11 @@ public:
{ {
decoder.Close(); decoder.Close();
} }
FTextureID GetTexture() override
{
return decoder.animTex().GetFrameID();
}
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -466,7 +470,6 @@ public:
lastsoundframe = soundframe; lastsoundframe = soundframe;
} }
} }
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit, TAG_DONE);
return !stop; return !stop;
} }
@ -482,6 +485,11 @@ public:
vpx_codec_destroy(&codec); vpx_codec_destroy(&codec);
animtex.Clean(); animtex.Clean();
} }
FTextureID GetTexture() override
{
return animtex.GetFrameID();
}
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -567,7 +575,6 @@ public:
nFrameNs = 1'000'000'000 / nFrameRate; nFrameNs = 1'000'000'000 / nFrameRate;
nFrames = Smacker_GetNumFrames(hSMK); nFrames = Smacker_GetNumFrames(hSMK);
Smacker_GetPalette(hSMK, palette); Smacker_GetPalette(hSMK, palette);
fullscreenScale = (!(flags & FIXEDVIEWPORT) || (nWidth <= 320 && nHeight <= 200) || nWidth >= 640 || nHeight >= 480);
numAudioTracks = Smacker_GetNumAudioTracks(hSMK); numAudioTracks = Smacker_GetNumAudioTracks(hSMK);
if (numAudioTracks) if (numAudioTracks)
@ -629,14 +636,7 @@ public:
} }
} }
if (fullscreenScale)
{
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
}
else
{
DrawTexture(twod, animtex.GetFrame(), 320, 240, DTA_VirtualWidth, 640, DTA_VirtualHeight, 480, DTA_CenterOffset, true, TAG_DONE);
}
if (frame > nFrame) if (frame > nFrame)
{ {
nFrame++; nFrame++;
@ -670,6 +670,12 @@ public:
Smacker_Close(hSMK); Smacker_Close(hSMK);
animtex.Clean(); animtex.Clean();
} }
FTextureID GetTexture() override
{
return animtex.GetFrameID();
}
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -812,3 +818,9 @@ DEFINE_ACTION_FUNCTION(_MoviePlayer, Destroy)
delete self; delete self;
return 0; return 0;
} }
DEFINE_ACTION_FUNCTION(_MoviePlayer, GetTexture)
{
PARAM_SELF_STRUCT_PROLOGUE(MoviePlayer);
ACTION_RETURN_INT(self->GetTexture().GetIndex());
}

View file

@ -230,6 +230,7 @@ struct MoviePlayer native
native void Start(); native void Start();
native bool Frame(double clock); native bool Frame(double clock);
native void Destroy(); native void Destroy();
native TextureID GetTexture();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -242,10 +243,12 @@ class MoviePlayerJob : SkippableScreenJob
{ {
MoviePlayer player; MoviePlayer player;
bool started; bool started;
int flag;
ScreenJob Init(MoviePlayer mp) ScreenJob Init(MoviePlayer mp, int flags)
{ {
Super.Init(); Super.Init();
flag = flags;
player = mp; player = mp;
return self; return self;
} }
@ -253,7 +256,7 @@ class MoviePlayerJob : SkippableScreenJob
static ScreenJob CreateWithSoundInfo(String filename, Array<int> soundinfo, int flags, int frametime, int firstframetime = -1, int lastframetime = -1) static ScreenJob CreateWithSoundInfo(String filename, Array<int> soundinfo, int flags, int frametime, int firstframetime = -1, int lastframetime = -1)
{ {
let movie = MoviePlayer.Create(filename, soundinfo, flags, frametime, firstframetime, lastframetime); let movie = MoviePlayer.Create(filename, soundinfo, flags, frametime, firstframetime, lastframetime);
if (movie) return new("MoviePlayerJob").Init(movie); if (movie) return new("MoviePlayerJob").Init(movie, flags);
return null; return null;
} }
static ScreenJob Create(String filename, int flags, int frametime = -1) static ScreenJob Create(String filename, int flags, int frametime = -1)
@ -268,6 +271,22 @@ class MoviePlayerJob : SkippableScreenJob
empty.Push(int(soundname)); empty.Push(int(soundname));
return CreateWithSoundInfo(filename, empty, flags, frametime); return CreateWithSoundInfo(filename, empty, flags, frametime);
} }
virtual void DrawFrame()
{
let tex = player.GetTexture();
let size = TexMan.GetScaledSize(tex);
if (!(flag & MoviePlayer.FIXEDVIEWPORT) || (size.x <= 320 && size.y <= 200) || size.x >= 640 || size.y >= 480)
{
Screen.DrawTexture(tex, false, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Masked, false);
}
else
{
Screen.DrawTexture(tex, false, 320, 240, DTA_VirtualWidth, 640, DTA_VirtualHeight, 480, DTA_CenterOffset, true, DTA_Masked, false);
}
}
override void Draw(double smoothratio) override void Draw(double smoothratio)
{ {
@ -286,6 +305,7 @@ class MoviePlayerJob : SkippableScreenJob
{ {
jobstate = finished; jobstate = finished;
} }
DrawFrame();
} }
override void OnDestroy() override void OnDestroy()