diff --git a/src/common/cutscenes/movieplayer.cpp b/src/common/cutscenes/movieplayer.cpp index e5acaad7f5e..3a79577fa6c 100644 --- a/src/common/cutscenes/movieplayer.cpp +++ b/src/common/cutscenes/movieplayer.cpp @@ -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)) { @@ -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; - } - //--------------------------------------------------------------------------- // // @@ -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); } //--------------------------------------------------------------------------- @@ -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) @@ -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; diff --git a/src/common/textures/animtexture.cpp b/src/common/textures/animtexture.cpp index a3be030794b..bee0b5771d9 100644 --- a/src/common/textures/animtexture.cpp +++ b/src/common/textures/animtexture.cpp @@ -35,6 +35,8 @@ #include "bitmap.h" #include "texturemanager.h" +#include "vpx/vpx_image.h" + //========================================================================== // @@ -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); @@ -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(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)); } } @@ -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++) { diff --git a/src/common/textures/animtexture.h b/src/common/textures/animtexture.h index 1f79d0af1c2..a51b39cde59 100644 --- a/src/common/textures/animtexture.h +++ b/src/common/textures/animtexture.h @@ -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);