- 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 void Stop() {}
virtual ~MoviePlayer() = default;
virtual FTextureID GetTexture() = 0;
};
//---------------------------------------------------------------------------
@ -119,17 +120,12 @@ public:
if (currentclock < nextframetime - 1)
{
twod->ClearScreen();
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Masked, false, TAG_DONE);
return true;
}
animtex.SetFrame(ANIM_GetPalette(&anim), ANIM_DrawFrame(&anim, curframe));
frametime = currentclock;
twod->ClearScreen();
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Masked, false, TAG_DONE);
int delay = 20;
if (frameTicks)
{
@ -168,6 +164,11 @@ public:
buffer.Reset();
animtex.Clean();
}
FTextureID GetTexture() override
{
return animtex.GetFrameID();
}
};
//---------------------------------------------------------------------------
@ -199,8 +200,6 @@ public:
{
if (failed) return false;
bool playon = decoder.RunFrame(clock);
twod->ClearScreen();
DrawTexture(twod, decoder.animTex().GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
return playon;
}
@ -208,6 +207,11 @@ public:
{
decoder.Close();
}
FTextureID GetTexture() override
{
return decoder.animTex().GetFrameID();
}
};
//---------------------------------------------------------------------------
@ -466,7 +470,6 @@ public:
lastsoundframe = soundframe;
}
}
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit, TAG_DONE);
return !stop;
}
@ -482,6 +485,11 @@ public:
vpx_codec_destroy(&codec);
animtex.Clean();
}
FTextureID GetTexture() override
{
return animtex.GetFrameID();
}
};
//---------------------------------------------------------------------------
@ -567,7 +575,6 @@ public:
nFrameNs = 1'000'000'000 / nFrameRate;
nFrames = Smacker_GetNumFrames(hSMK);
Smacker_GetPalette(hSMK, palette);
fullscreenScale = (!(flags & FIXEDVIEWPORT) || (nWidth <= 320 && nHeight <= 200) || nWidth >= 640 || nHeight >= 480);
numAudioTracks = Smacker_GetNumAudioTracks(hSMK);
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)
{
nFrame++;
@ -670,6 +670,12 @@ public:
Smacker_Close(hSMK);
animtex.Clean();
}
FTextureID GetTexture() override
{
return animtex.GetFrameID();
}
};
//---------------------------------------------------------------------------
@ -812,3 +818,9 @@ DEFINE_ACTION_FUNCTION(_MoviePlayer, Destroy)
delete self;
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 bool Frame(double clock);
native void Destroy();
native TextureID GetTexture();
}
//---------------------------------------------------------------------------
@ -242,10 +243,12 @@ class MoviePlayerJob : SkippableScreenJob
{
MoviePlayer player;
bool started;
int flag;
ScreenJob Init(MoviePlayer mp)
ScreenJob Init(MoviePlayer mp, int flags)
{
Super.Init();
flag = flags;
player = mp;
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)
{
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;
}
static ScreenJob Create(String filename, int flags, int frametime = -1)
@ -269,6 +272,22 @@ class MoviePlayerJob : SkippableScreenJob
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)
{
if (!player)
@ -286,6 +305,7 @@ class MoviePlayerJob : SkippableScreenJob
{
jobstate = finished;
}
DrawFrame();
}
override void OnDestroy()