- backend sync from gzdoom, again

This commit is contained in:
Rachael Alexanderson 2024-04-18 02:25:13 -04:00
parent 6dcb8c0f6e
commit d2b209261d
No known key found for this signature in database
GPG key ID: 26A8ACCE97115EE0
8 changed files with 217 additions and 111 deletions

View file

@ -322,11 +322,11 @@ class VpxPlayer : public MoviePlayer
unsigned width, height;
TArray<uint8_t> Pic;
TArray<uint8_t> readBuf;
vpx_codec_iface_t *iface;
vpx_codec_ctx_t codec{};
vpx_codec_iter_t iter = nullptr;
uint32_t convnumer;
uint32_t convdenom;
double convrate;
uint64_t nsecsperframe;
uint64_t nextframetime;
@ -362,10 +362,8 @@ public:
Pic.Resize(width * height * 4);
// Todo: Support VP9 as well?
vpx_codec_dec_cfg_t cfg = { 1, width, height };
if (vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0))
if (vpx_codec_dec_init(&codec, iface, &cfg, 0))
{
error.Format("Error initializing VPX codec.\n");
failed = true;
@ -388,7 +386,16 @@ public:
uint16_t length = fr.ReadUInt16();
if (length != 32) return false;
fr.Read(&magic, 4);
if (magic != MAKE_ID('V', 'P', '8', '0')) return false;
switch (magic)
{
case MAKE_ID('V', 'P', '8', '0'):
iface = &vpx_codec_vp8_dx_algo; break;
case MAKE_ID('V', 'P', '9', '0'):
iface = &vpx_codec_vp9_dx_algo; break;
default:
return false;
}
width = fr.ReadUInt16();
height = fr.ReadUInt16();
@ -398,15 +405,20 @@ public:
if (numframes == 0) return false;
fr.Seek(4, FileReader::SeekCur);
if (fpsdenominator > 1000 || fpsnumerator == 0 || fpsdenominator == 0)
if (fpsnumerator == 0 || fpsdenominator == 0)
{
// default to 30 fps if the header does not provide useful info.
fpsdenominator = 30;
fpsnumerator = 1;
}
convnumer = 120 * fpsnumerator;
convdenom = fpsdenominator * origframedelay;
if (origframedelay < 1)
convrate = 0.0;
else
{
convrate = 120.0 * double(fpsnumerator);
convrate /= double(fpsdenominator) * double(origframedelay);
}
nsecsperframe = int64_t(fpsnumerator) * 1'000'000'000 / fpsdenominator;
nextframetime = 0;
@ -475,32 +487,6 @@ public:
dest[2] = v;
}
bool CreateNextFrame()
{
auto img = GetFrameData();
if (!img) return false;
uint8_t const* const yplane = img->planes[VPX_PLANE_Y];
uint8_t const* const uplane = img->planes[VPX_PLANE_U];
uint8_t const* const vplane = img->planes[VPX_PLANE_V];
const int ystride = img->stride[VPX_PLANE_Y];
const int ustride = img->stride[VPX_PLANE_U];
const int vstride = img->stride[VPX_PLANE_V];
for (unsigned int y = 0; y < height; y++)
{
for (unsigned int x = 0; x < width; x++)
{
uint8_t u = uplane[ustride * (y >> 1) + (x >> 1)];
uint8_t v = vplane[vstride * (y >> 1) + (x >> 1)];
SetPixel(&Pic[(x + y * width) << 2], yplane[ystride * y + x], u, v);
}
}
return true;
}
//---------------------------------------------------------------------------
//
//
@ -525,7 +511,7 @@ public:
Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false));
}
}
animtex.SetSize(AnimTexture::YUV, width, height);
animtex.SetSize(AnimTexture::VPX, width, height);
}
//---------------------------------------------------------------------------
@ -534,6 +520,12 @@ public:
//
//---------------------------------------------------------------------------
bool FormatSupported(vpx_img_fmt_t fmt)
{
return fmt == VPX_IMG_FMT_I420 || fmt == VPX_IMG_FMT_I444 || fmt == VPX_IMG_FMT_I422 || fmt == VPX_IMG_FMT_I440;
}
bool Frame(uint64_t clock) override
{
if (!AudioTrack.GetAudioStream() && MusicStream && clock != 0)
@ -562,22 +554,38 @@ public:
bool stop = false;
if (clock >= nextframetime)
{
nextframetime += nsecsperframe;
if (!CreateNextFrame())
{
Printf(PRINT_BOLD, "Failed reading next frame\n");
stop = true;
while(clock >= nextframetime)
{ // frameskipping
auto img = GetFrameData();
framenum++;
nextframetime += nsecsperframe;
if (framenum >= numframes || !img) break;
}
else
if (framenum < numframes)
{
animtex.SetFrame(nullptr, Pic.Data());
auto img = GetFrameData();
if (!img || !FormatSupported(img->fmt))
{
Printf(PRINT_BOLD, "Failed reading next frame\n");
stop = true;
}
else
{
animtex.SetFrame(nullptr, img);
}
framenum++;
}
framenum++;
if (framenum >= numframes) stop = true;
bool nostopsound = (flags & NOSOUNDCUTOFF);
int soundframe = convdenom ? Scale(framenum, convnumer, convdenom) : framenum;
int soundframe = (convrate > 0.0) ? int(convrate * framenum) : framenum;
if (soundframe > lastsoundframe)
{
if (soundtrack == -1)
@ -895,7 +903,7 @@ MoviePlayer* OpenMovie(const char* filename, TArray<int>& ans, const int* framet
}
return anm;
}
else if (!memcmp(id, "DKIF\0\0 \0VP80", 12))
else if (!memcmp(id, "DKIF\0\0 \0VP80", 12) || !memcmp(id, "DKIF\0\0 \0VP90", 12))
{
auto anm = new VpxPlayer(fr, ans, frameticks ? frameticks[1] : 0, flags, error);
if (!anm->isvalid())

View file

@ -599,14 +599,14 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, float in
if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0))
{
prev = inter1_prev < 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
}
TRS next;
if(frame2 >= 0 && (frame2_prev >= 0 || inter2_prev < 0))
{
next = inter2_prev < 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2);
next = inter2_prev <= 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2);
}
TRS bone;

View file

@ -214,10 +214,6 @@ class TObjPtr
mutable DObject *o;
};
public:
// before doing a backend sync - this needs to be addressed: https://github.com/ZDoom/Raze/actions/runs/8727418834/job/23944876872
//TObjPtr() = default;
//TObjPtr(T t) : pp(t) {}
constexpr TObjPtr<T>& operator=(T q) noexcept
{

View file

@ -35,6 +35,8 @@
#include "bitmap.h"
#include "texturemanager.h"
#include "vpx/vpx_image.h"
//==========================================================================
//
@ -46,39 +48,152 @@ void AnimTexture::SetFrameSize(int format, int width, int height)
{
pixelformat = format;
FTexture::SetSize(width, height);
Image.Resize(width * height * (format == Paletted ? 1 : 3));
Image.Resize(width * height * 4);
memset(Image.Data(), 0, Image.Size());
}
void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
//TODO optimize
static inline void YUVtoRGB(uint8_t yi, uint8_t ui, uint8_t vi, uint8_t * rgb)
{
float Y = yi * (1 / 255.f);
float U = ui * (1 / 255.f) - 0.5f;
float V = vi * (1 / 255.f) - 0.5f;
Y = 1.1643f * (Y - 0.0625f);
float r = Y + 1.5958f * V;
float g = Y - 0.39173f * U - 0.81290f * V;
float b = Y + 2.017f * U;
(rgb)[2] = (uint8_t)(clamp(r, 0.f, 1.f) * 255);
(rgb)[1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255);
(rgb)[0] = (uint8_t)(clamp(b, 0.f, 1.f) * 255);
(rgb)[3] = 255;
}
void AnimTexture::SetFrame(const uint8_t* Palette, const void* data_)
{
if (palette) memcpy(Palette, palette, 768);
if (data_)
{
auto dpix = Image.Data();
if (pixelformat == YUV)
{
auto spix = (const uint8_t*)data_;
auto dpix = Image.Data();
const uint8_t * spix = reinterpret_cast<const uint8_t *>(data_);
for (int i = 0; i < Width * Height; i++)
{
int p = i * 4;
int q = i * 3;
float y = spix[p] * (1 / 255.f);
float u = spix[p + 1] * (1 / 255.f) - 0.5f;
float v = spix[p + 2] * (1 / 255.f) - 0.5f;
{
YUVtoRGB(spix[0], spix[1], spix[2], dpix);
y = 1.1643f * (y - 0.0625f);
float r = y + 1.5958f * v;
float g = y - 0.39173f * u - 0.81290f * v;
float b = y + 2.017f * u;
dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255);
dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255);
dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255);
spix += 4;
dpix += 4;
}
}
else if(pixelformat == VPX)
{
const vpx_image_t *img = reinterpret_cast<const vpx_image_t *>(data_);
uint8_t const* const yplane = img->planes[VPX_PLANE_Y];
uint8_t const* const uplane = img->planes[VPX_PLANE_U];
uint8_t const* const vplane = img->planes[VPX_PLANE_V];
const int ystride = img->stride[VPX_PLANE_Y];
const int ustride = img->stride[VPX_PLANE_U];
const int vstride = img->stride[VPX_PLANE_V];
if(img->fmt == VPX_IMG_FMT_I420)
{
for (unsigned int y = 0; y < Height; y++)
{
for (unsigned int x = 0; x < Width; x++)
{
YUVtoRGB(
yplane[ystride * y + x],
uplane[ustride * (y >> 1) + (x >> 1)],
vplane[vstride * (y >> 1) + (x >> 1)],
dpix
);
dpix += 4;
}
}
}
else if(img->fmt == VPX_IMG_FMT_I444)
{
for (unsigned int y = 0; y < Height; y++)
{
for (unsigned int x = 0; x < Width; x++)
{
YUVtoRGB(
yplane[ystride * y + x],
uplane[ustride * y + x],
vplane[vstride * y + x],
dpix
);
dpix += 4;
}
}
}
else if(img->fmt == VPX_IMG_FMT_I422)
{ // 422 and 440 untested
for (unsigned int y = 0; y < Height; y++)
{
for (unsigned int x = 0; x < Width; x++)
{
YUVtoRGB(
yplane[ystride * y + x],
uplane[ustride * y + (x >> 1)],
vplane[vstride * y + (x >> 1)],
dpix
);
dpix += 4;
}
}
}
else if(img->fmt == VPX_IMG_FMT_I440)
{
for (unsigned int y = 0; y < Height; y++)
{
for (unsigned int x = 0; x < Width; x++)
{
YUVtoRGB(
yplane[ystride * y + x],
uplane[ustride * (y >> 1) + x],
vplane[vstride * (y >> 1) + x],
dpix
);
dpix += 4;
}
}
}
}
else if(pixelformat == RGB)
{
const uint8_t *img = reinterpret_cast<const uint8_t *>(data_);
for (int i = 0; i < Width * Height; i++)
{
dpix[0] = img[2];
dpix[1] = img[1];
dpix[2] = img[0];
dpix[3] = 255;
dpix += 4;
}
}
else if (pixelformat == Paletted)
{
assert(Palette);
const uint8_t *img = reinterpret_cast<const uint8_t *>(data_);
for (int i = 0; i < Width * Height; i++)
{
int index = img[i];
dpix[0] = Palette[index * 3 + 2];
dpix[1] = Palette[index * 3 + 1];
dpix[2] = Palette[index * 3];
dpix[3] = 255;
dpix += 4;
}
}
else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3));
}
}
@ -90,37 +205,7 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
{
FBitmap bmp;
bmp.Create(Width, Height);
auto spix = Image.Data();
auto dpix = bmp.GetPixels();
if (pixelformat == Paletted)
{
for (int i = 0; i < Width * Height; i++)
{
int p = i * 4;
int index = spix[i];
dpix[p + 0] = Palette[index * 3 + 2];
dpix[p + 1] = Palette[index * 3 + 1];
dpix[p + 2] = Palette[index * 3];
dpix[p + 3] = 255;
}
}
else if (pixelformat == RGB || pixelformat == YUV)
{
for (int i = 0; i < Width * Height; i++)
{
int p = i * 4;
int q = i * 3;
dpix[p + 0] = spix[q + 2];
dpix[p + 1] = spix[q + 1];
dpix[p + 2] = spix[q];
dpix[p + 3] = 255;
}
}
return bmp;
return FBitmap(Image.Data(), Width * 4, Width, Height);
}
//==========================================================================

View file

@ -5,7 +5,6 @@
class AnimTexture : public FTexture
{
uint8_t Palette[768];
TArray<uint8_t> Image;
int pixelformat;
public:
@ -13,7 +12,8 @@ public:
{
Paletted = 0,
RGB = 1,
YUV = 2
YUV = 2,
VPX = 3
};
AnimTexture() = default;
void SetFrameSize(int format, int width, int height);

View file

@ -253,6 +253,8 @@ public:
CopyPixelDataRGB(originx, originy, src.GetPixels(), src.GetWidth(), src.GetHeight(), 4, src.GetWidth()*4, 0, CF_BGRA, inf);
}
friend class FTexture;
};
bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy,

View file

@ -354,17 +354,29 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
if (!checkonly)
{
buffer = new unsigned char[W * (H + 1) * 4];
memset(buffer, 0, W * (H + 1) * 4);
auto remap = translation <= 0 || IsLuminosityTranslation(translation) ? nullptr : GPalette.TranslationToTable(translation);
if (remap && remap->Inactive) remap = nullptr;
if (remap) translation = remap->Index;
FBitmap bmp(buffer, W * 4, W, H);
int trans;
auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans);
bmp.Blit(exx, exx, Pixels);
if(!exx && Pixels.ClipRect.x == 0 && Pixels.ClipRect.y == 0 && Pixels.ClipRect.width == Pixels.Width && Pixels.ClipRect.height == Pixels.Height && (Pixels.FreeBuffer || !IsLuminosityTranslation(translation)))
{
buffer = Pixels.data;
result.mFreeBuffer = Pixels.FreeBuffer;
Pixels.FreeBuffer = false;
}
else
{
buffer = new unsigned char[W * (H + 1) * 4];
memset(buffer, 0, W * (H + 1) * 4);
FBitmap bmp(buffer, W * 4, W, H);
bmp.Blit(exx, exx, Pixels);
}
if (IsLuminosityTranslation(translation))
{
V_ApplyLuminosityTranslation(LuminosityTranslationDesc::fromInt(translation), buffer, W * H);

View file

@ -169,6 +169,7 @@ union FContentIdBuilder
struct FTextureBuffer
{
uint8_t *mBuffer = nullptr;
bool mFreeBuffer = true;
int mWidth = 0;
int mHeight = 0;
uint64_t mContentId = 0; // unique content identifier. (Two images created from the same image source with the same settings will return the same value.)
@ -177,7 +178,7 @@ struct FTextureBuffer
~FTextureBuffer()
{
if (mBuffer) delete[] mBuffer;
if (mBuffer && mFreeBuffer) delete[] mBuffer;
}
FTextureBuffer(const FTextureBuffer &other) = delete;
@ -187,6 +188,7 @@ struct FTextureBuffer
mWidth = other.mWidth;
mHeight = other.mHeight;
mContentId = other.mContentId;
mFreeBuffer = other.mFreeBuffer;
other.mBuffer = nullptr;
}
@ -196,6 +198,7 @@ struct FTextureBuffer
mWidth = other.mWidth;
mHeight = other.mHeight;
mContentId = other.mContentId;
mFreeBuffer = other.mFreeBuffer;
other.mBuffer = nullptr;
return *this;
}