Skip to content

Commit

Permalink
add 444/422/440 support to vp9, remove extra copy of image data
Browse files Browse the repository at this point in the history
  • Loading branch information
RicardoLuis0 authored and madame-rachelle committed Apr 18, 2024
1 parent 06566c0 commit 5b2673f
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 46 deletions.
43 changes: 12 additions & 31 deletions src/common/cutscenes/movieplayer.cpp
Expand Up @@ -362,8 +362,6 @@ class VpxPlayer : public MoviePlayer

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, iface, &cfg, 0))
{
Expand Down Expand Up @@ -489,32 +487,6 @@ class VpxPlayer : public MoviePlayer
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;
}

//---------------------------------------------------------------------------
//
//
Expand All @@ -539,7 +511,7 @@ class VpxPlayer : public MoviePlayer
Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false));
}
}
animtex.SetSize(AnimTexture::YUV, width, height);
animtex.SetSize(AnimTexture::VPX, width, height);
}

//---------------------------------------------------------------------------
Expand All @@ -548,6 +520,12 @@ class VpxPlayer : public MoviePlayer
//
//---------------------------------------------------------------------------

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)
Expand Down Expand Up @@ -578,15 +556,18 @@ class VpxPlayer : public MoviePlayer
{
nextframetime += nsecsperframe;

if (!CreateNextFrame())
auto img = GetFrameData();

if (!img || !FormatSupported(img->fmt))
{
Printf(PRINT_BOLD, "Failed reading next frame\n");
stop = true;
}
else
{
animtex.SetFrame(nullptr, Pic.Data());
animtex.SetFrame(nullptr, img);
}

framenum++;
if (framenum >= numframes) stop = true;

Expand Down
119 changes: 105 additions & 14 deletions src/common/textures/animtexture.cpp
Expand Up @@ -35,6 +35,8 @@
#include "bitmap.h"
#include "texturemanager.h"

#include "vpx/vpx_image.h"


//==========================================================================
//
Expand All @@ -50,6 +52,24 @@ void AnimTexture::SetFrameSize(int format, int width, int height)
memset(Image.Data(), 0, Image.Size());
}

//TODO optimize
static inline void YUVtoRGB(float y, float u, float v, uint8_t * rgb)
{
y = y * (1 / 255.f);
u = u * (1 / 255.f) - 0.5f;
v = v * (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[0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255);
rgb[1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255);
rgb[2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255);
}

void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
{
if (palette) memcpy(Palette, palette, 768);
Expand All @@ -61,24 +81,95 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
auto dpix = Image.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);
spix += 4;
dpix += 3;
}
}
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];

float r = y + 1.5958f * v;
float g = y - 0.39173f * u - 0.81290f * v;
float b = y + 2.017f * u;
auto dpix = Image.Data();

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);
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 += 3;
}
}
}
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 += 3;
}
}
}
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 += 3;
}
}
}
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 += 3;
}
}
}
}
else
{
memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3));
}
else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3));
}
}

Expand Down Expand Up @@ -108,7 +199,7 @@ FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
dpix[p + 3] = 255;
}
}
else if (pixelformat == RGB || pixelformat == YUV)
else if (pixelformat == RGB || pixelformat == YUV || pixelformat == VPX)
{
for (int i = 0; i < Width * Height; i++)
{
Expand Down
3 changes: 2 additions & 1 deletion src/common/textures/animtexture.h
Expand Up @@ -13,7 +13,8 @@ class AnimTexture : public FTexture
{
Paletted = 0,
RGB = 1,
YUV = 2
YUV = 2,
VPX = 3
};
AnimTexture() = default;
void SetFrameSize(int format, int width, int height);
Expand Down

0 comments on commit 5b2673f

Please sign in to comment.