From 7bc252a0e77c10001abbd2549d881ed3c79e778c Mon Sep 17 00:00:00 2001 From: VDm Date: Sun, 27 Apr 2025 01:31:24 +0400 Subject: [PATCH 01/10] feat(ui): implement CSimpleMovieFrame::Render method --- src/ui/CSimpleMovieFrame.cpp | 312 ++++++++++++++++++++++++++++++++++- 1 file changed, 309 insertions(+), 3 deletions(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index fcc5abc..eb176ef 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -1,18 +1,284 @@ #include "ui/CSimpleMovieFrame.hpp" #include "ui/CSimpleMovieFrameScript.hpp" #include "util/SFile.hpp" +#include "gx/Buffer.hpp" +#include "gx/RenderState.hpp" #include "gx/Texture.hpp" +#include "gx/Transform.hpp" +#include "gx/Draw.hpp" #include +#include +#if defined(WHOA_SYSTEM_WIN) + +#include +#include + +#define XVID_MAKE_VERSION(a, b, c) ((((a) & 0xff) << 16) | (((b) & 0xff) << 8) | ((c) & 0xff)) +#define XVID_VERSION_MAJOR(a) ((char)(((a) >> 16) & 0xff)) +#define XVID_VERSION_MINOR(a) ((char)(((a) >> 8) & 0xff)) +#define XVID_VERSION_PATCH(a) ((char)(((a) >> 0) & 0xff)) + +#define XVID_MAKE_API(a, b) ((((a) & 0xff) << 16) | (((b) & 0xff) << 0)) +#define XVID_API_MAJOR(a) (((a) >> 16) & 0xff) +#define XVID_API_MINOR(a) (((a) >> 0) & 0xff) + +#define XVID_VERSION XVID_MAKE_VERSION(1, 4, -127) +#define XVID_API XVID_MAKE_API(4, 4) + +extern "C" { + +/* xvid_image_t + for non-planar colorspaces use only plane[0] and stride[0] + four plane reserved for alpha*/ +typedef struct { + int csp; /* [in] colorspace; or with XVID_CSP_VFLIP to perform vertical flip */ + void* plane[4]; /* [in] image plane ptrs */ + int stride[4]; /* [in] image stride; "bytes per row"*/ +} xvid_image_t; + +/* XVID_GBL_INIT param1 */ +typedef struct { + int version; + unsigned int cpu_flags; /* [in:opt] zero = autodetect cpu; XVID_CPU_FORCE|{cpu features} = force cpu features */ + int debug; /* [in:opt] debug level */ +} xvid_gbl_init_t; + +/* XVID_GBL_INFO param1 */ +typedef struct { + int version; + int actual_version; /* [out] returns the actual xvidcore version */ + const char* build; /* [out] if !null, points to description of this xvid core build */ + unsigned int cpu_flags; /* [out] detected cpu features */ + int num_threads; /* [out] detected number of cpus/threads */ +} xvid_gbl_info_t; + +#define XVID_GBL_INIT 0 /* initialize xvidcore; must be called before using xvid_decore, or xvid_encore) */ +#define XVID_GBL_INFO 1 /* return some info about xvidcore, and the host computer */ +#define XVID_GBL_CONVERT 2 /* colorspace conversion utility */ + +typedef int (*XVID_GLOBAL)(void* handle, int opt, void* param1, void* param2); + +#define XVID_DEC_CREATE 0 /* create decore instance; return 0 on success */ +#define XVID_DEC_DESTROY 1 /* destroy decore instance: return 0 on success */ +#define XVID_DEC_DECODE 2 /* decode a frame: returns number of bytes consumed >= 0 */ + +typedef int (*XVID_DECORE)(void* handle, int opt, void* param1, void* param2); + +/* XVID_DEC_CREATE param 1 + image width & height as well as FourCC code may be specified + here when known in advance (e.g. being read from container) */ +typedef struct { + int version; + int width; /* [in:opt] image width */ + int height; /* [in:opt] image width */ + void* handle; /* [out] decore context handle */ + /* ------- v1.3.x ------- */ + int fourcc; /* [in:opt] fourcc of the input video */ + int num_threads; /* [in:opt] number of threads to use in decoder */ +} xvid_dec_create_t; + +typedef struct { + int version; + int general; /* [in:opt] general flags */ + void* bitstream; /* [in] bitstream (read from)*/ + int length; /* [in] bitstream length */ + xvid_image_t output; /* [in] output image (written to) */ + /* ------- v1.1.x ------- */ + int brightness; /* [in] brightness offset (0=none) */ +} xvid_dec_frame_t; + +/* XVID_DEC_DECODE param2 :: optional */ +typedef struct +{ + int version; + + int type; /* [out] output data type */ + union { + struct { /* type>0 {XVID_TYPE_IVOP,XVID_TYPE_PVOP,XVID_TYPE_BVOP,XVID_TYPE_SVOP} */ + int general; /* [out] flags */ + int time_base; /* [out] time base */ + int time_increment; /* [out] time increment */ + + /* XXX: external deblocking stuff */ + int* qscale; /* [out] pointer to quantizer table */ + int qscale_stride; /* [out] quantizer scale stride */ + + } vop; + struct { /* XVID_TYPE_VOL */ + int general; /* [out] flags */ + int width; /* [out] width */ + int height; /* [out] height */ + int par; /* [out] pixel aspect ratio (refer to XVID_PAR_xxx above) */ + int par_width; /* [out] aspect ratio width [1..255] */ + int par_height; /* [out] aspect ratio height [1..255] */ + } vol; + } data; +} xvid_dec_stats_t; + +} // extern "C" + +static std::map s_divxHandles; +static uint32_t s_divxRefCounter = 0; + +static XVID_GLOBAL s_xvid_global = nullptr; +static XVID_DECORE s_xvid_decore = nullptr; + +static uint32_t LoadDivxDecoder() { + auto library = LoadLibraryA("xvidcore.dll"); + if (!library) { + return 0; + } + + s_xvid_global = reinterpret_cast(GetProcAddress(library, "xvid_global")); + s_xvid_decore = reinterpret_cast(GetProcAddress(library, "xvid_decore")); + + if (!s_xvid_global || !s_xvid_decore) { + FreeLibrary(library); + return 0; + } + + xvid_gbl_info_t info = {}; + info.version = XVID_VERSION; + + if (s_xvid_global(nullptr, XVID_GBL_INFO, &info, nullptr) < 0) { + return 0; + } + + xvid_gbl_init_t init = {}; + init.version = XVID_VERSION; + if (s_xvid_global(nullptr, XVID_GBL_INIT, &init, nullptr) < 0) { + return 0; + } + + xvid_dec_create_t decoder = {}; + decoder.version = XVID_VERSION; + decoder.num_threads = info.num_threads; + if (s_xvid_decore(nullptr, XVID_DEC_CREATE, &decoder, nullptr)) { + return 0; + } + + if (++s_divxRefCounter == 0) { + ++s_divxRefCounter; + } + + s_divxHandles[s_divxRefCounter] = decoder.handle; + return s_divxRefCounter; +} + +static int write_tga(char* filename, char* image) { + FILE* f; + char hdr[18]; + + f = fopen(filename, "wb"); + if (f == NULL) { + return -1; + } + + int BPP = 1; + int XDIM = 1024; + int YDIM = 464; + + hdr[0] = 0; /* ID length */ + hdr[1] = 0; /* Color map type */ + hdr[2] = (BPP > 1) ? 2 : 3; /* Uncompressed true color (2) or greymap (3) */ + hdr[3] = 0; /* Color map specification (not used) */ + hdr[4] = 0; /* Color map specification (not used) */ + hdr[5] = 0; /* Color map specification (not used) */ + hdr[6] = 0; /* Color map specification (not used) */ + hdr[7] = 0; /* Color map specification (not used) */ + hdr[8] = 0; /* LSB X origin */ + hdr[9] = 0; /* MSB X origin */ + hdr[10] = 0; /* LSB Y origin */ + hdr[11] = 0; /* MSB Y origin */ + hdr[12] = (XDIM >> 0) & 0xff; /* LSB Width */ + hdr[13] = (XDIM >> 8) & 0xff; /* MSB Width */ + if (BPP > 1) { + hdr[14] = (YDIM >> 0) & 0xff; /* LSB Height */ + hdr[15] = (YDIM >> 8) & 0xff; /* MSB Height */ + } else { + hdr[14] = ((YDIM * 3) >> 1) & 0xff; /* LSB Height */ + hdr[15] = ((YDIM * 3) >> 9) & 0xff; /* MSB Height */ + } + hdr[16] = BPP * 8; + hdr[17] = 0x00 | (1 << 5) /* Up to down */ | (0 << 4); /* Image descriptor */ + + /* Write header */ + fwrite(hdr, 1, sizeof(hdr), f); + + fwrite(image, 1, XDIM * YDIM * BPP, f); + + /* Write Y and V planes for YUV formats */ + if (BPP == 1) { + int i; + + /* Write the two chrominance planes */ + for (i = 0; i < YDIM / 2; i++) { + fwrite(image + XDIM * YDIM + i * XDIM / 2, 1, XDIM / 2, f); + fwrite(image + 5 * XDIM * YDIM / 4 + i * XDIM / 2, 1, XDIM / 2, f); + } + } + + /* Close the file */ + fclose(f); + + return (0); +} + +static int32_t DivxDecode(uint32_t decoder, char* input, char* output) { + xvid_dec_frame_t frame = {}; + xvid_dec_stats_t stats = {}; + + frame.version = XVID_VERSION; + stats.version = XVID_VERSION; + + frame.bitstream = input + 4; + frame.length = *reinterpret_cast(input); + + char* frameData = (char*)ALLOC(1024 * 464 * 4); + + frame.output.plane[0] = frameData; + frame.output.stride[0] = 1024; + frame.output.csp = (1 << 1); + + static int frameNo = 0; + + while (true) { + int bytes = s_xvid_decore(s_divxHandles[decoder], XVID_DEC_DECODE, &frame, &stats); + if (bytes < 1) { + break; + } + frame.bitstream = (char*)frame.bitstream + bytes; + frame.length -= bytes; + } + + frameNo++; + + //if (frameNo == 168) { + // write_tga("movie.tga", frameData); + //} + + FREE(frameData); + + return 1; +} + +#else static uint32_t LoadDivxDecoder() { return 0; } +#endif + + static void UnloadDivxDecoder(uint32_t decoder) { } +static const uint32_t textureCountByFormat[6] = { 6, 2, 3, 4, 6, 2 }; + + int32_t CSimpleMovieFrame::s_metatable; int32_t CSimpleMovieFrame::s_objectType; @@ -336,8 +602,6 @@ int32_t CSimpleMovieFrame::OpenVideo() { return 0; } - const uint32_t textureCountByFormat[6] = { 6, 2, 3, 4, 6, 2 }; - int32_t hasTextures = 1; for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { // TODO: GxTexCreate() @@ -429,8 +693,50 @@ int32_t CSimpleMovieFrame::UpdateTiming() { } int32_t CSimpleMovieFrame::DecodeFrame(bool unk) { - return 0; + auto frameSize = *reinterpret_cast(this->m_currentFrameData); + if (!DivxDecode(this->m_decoder, this->m_currentFrameData, this->m_imageData)) { + return 0; + } + this->m_currentFrameData += frameSize + 4; + return 1; } void CSimpleMovieFrame::Render() { + float minX; + float maxX; + float minY; + float maxY; + float minZ; + float maxZ; + GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ); + + GxXformSetViewport(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); + CImVector clearColor = { 0x00, 0x00, 0x80, 0xFF }; + GxSceneClear(3, clearColor); + C44Matrix matrix; + GxuXformCreateOrtho(0.0, 1.0, -0.5, 0.5, 0.0, 500.0, matrix); + GxXformSetView(C44Matrix()); + GxXformSetProjection(matrix); + + // TODO + + GxRsPush(); + GxRsSet(GxRs_Lighting, 0); + GxRsSet(GxRs_Fog, 0); + GxRsSet(GxRs_BlendingMode, 0); + GxRsSetAlphaRef(); + + for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { + C3Vector pos; + C3Vector normal(0.0f, 0.0f, 1.0f); + C2Vector tex(0.0f, 0.0f); + GxPrimLockVertexPtrs(4, &pos, sizeof(pos), &normal, 0, nullptr, 0, nullptr, 0, &tex, sizeof(tex), nullptr, 0); + GxRsSet(GxRs_Texture0, this->m_textures[i]); + uint16_t indices[] = { 0, 1, 2, 3 }; + GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices); + GxPrimUnlockVertexPtrs(); + } + + GxRsPop(); + GxXformSetViewport(minX, maxX, minY, maxY, minZ, maxZ); } From 5bd40352e15cf7a88f718cc057b7adb1d417dd31 Mon Sep 17 00:00:00 2001 From: VDm Date: Sun, 27 Apr 2025 14:36:01 +0400 Subject: [PATCH 02/10] feat(ui): first working implementation of CSimpleMovieFrame with real video --- src/ui/CSimpleMovieFrame.cpp | 144 ++++++++++++++++------------------- src/ui/CSimpleMovieFrame.hpp | 7 +- 2 files changed, 69 insertions(+), 82 deletions(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index eb176ef..fcb6186 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -166,66 +166,7 @@ static uint32_t LoadDivxDecoder() { return s_divxRefCounter; } -static int write_tga(char* filename, char* image) { - FILE* f; - char hdr[18]; - - f = fopen(filename, "wb"); - if (f == NULL) { - return -1; - } - - int BPP = 1; - int XDIM = 1024; - int YDIM = 464; - - hdr[0] = 0; /* ID length */ - hdr[1] = 0; /* Color map type */ - hdr[2] = (BPP > 1) ? 2 : 3; /* Uncompressed true color (2) or greymap (3) */ - hdr[3] = 0; /* Color map specification (not used) */ - hdr[4] = 0; /* Color map specification (not used) */ - hdr[5] = 0; /* Color map specification (not used) */ - hdr[6] = 0; /* Color map specification (not used) */ - hdr[7] = 0; /* Color map specification (not used) */ - hdr[8] = 0; /* LSB X origin */ - hdr[9] = 0; /* MSB X origin */ - hdr[10] = 0; /* LSB Y origin */ - hdr[11] = 0; /* MSB Y origin */ - hdr[12] = (XDIM >> 0) & 0xff; /* LSB Width */ - hdr[13] = (XDIM >> 8) & 0xff; /* MSB Width */ - if (BPP > 1) { - hdr[14] = (YDIM >> 0) & 0xff; /* LSB Height */ - hdr[15] = (YDIM >> 8) & 0xff; /* MSB Height */ - } else { - hdr[14] = ((YDIM * 3) >> 1) & 0xff; /* LSB Height */ - hdr[15] = ((YDIM * 3) >> 9) & 0xff; /* MSB Height */ - } - hdr[16] = BPP * 8; - hdr[17] = 0x00 | (1 << 5) /* Up to down */ | (0 << 4); /* Image descriptor */ - - /* Write header */ - fwrite(hdr, 1, sizeof(hdr), f); - - fwrite(image, 1, XDIM * YDIM * BPP, f); - - /* Write Y and V planes for YUV formats */ - if (BPP == 1) { - int i; - - /* Write the two chrominance planes */ - for (i = 0; i < YDIM / 2; i++) { - fwrite(image + XDIM * YDIM + i * XDIM / 2, 1, XDIM / 2, f); - fwrite(image + 5 * XDIM * YDIM / 4 + i * XDIM / 2, 1, XDIM / 2, f); - } - } - - /* Close the file */ - fclose(f); - - return (0); -} - -static int32_t DivxDecode(uint32_t decoder, char* input, char* output) { +static int32_t DivxDecode(uint32_t decoder, char* input, char* output, int32_t width) { xvid_dec_frame_t frame = {}; xvid_dec_stats_t stats = {}; @@ -235,11 +176,9 @@ static int32_t DivxDecode(uint32_t decoder, char* input, char* output) { frame.bitstream = input + 4; frame.length = *reinterpret_cast(input); - char* frameData = (char*)ALLOC(1024 * 464 * 4); - - frame.output.plane[0] = frameData; - frame.output.stride[0] = 1024; - frame.output.csp = (1 << 1); + frame.output.plane[0] = output; + frame.output.stride[0] = 4 * width; + frame.output.csp = (1 << 15); static int frameNo = 0; @@ -254,12 +193,6 @@ static int32_t DivxDecode(uint32_t decoder, char* input, char* output) { frameNo++; - //if (frameNo == 168) { - // write_tga("movie.tga", frameData); - //} - - FREE(frameData); - return 1; } @@ -309,6 +242,13 @@ void CSimpleMovieFrame::RenderMovie(void* param) { } } +void CSimpleMovieFrame::TextureCallback(EGxTexCommand command, uint32_t width, uint32_t height, uint32_t, uint32_t, void* userData, uint32_t& texelStrideInBytes, const void*& texels) { + if (command == GxTex_Latch) { + texelStrideInBytes = 4 * width; + texels = reinterpret_cast(userData)->data; + } +} + FrameScript_Object::ScriptIx* CSimpleMovieFrame::GetScriptByName(const char* name, ScriptData& data) { auto parentScript = CSimpleFrame::GetScriptByName(name, data); @@ -604,8 +544,18 @@ int32_t CSimpleMovieFrame::OpenVideo() { int32_t hasTextures = 1; for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { - // TODO: GxTexCreate() - hasTextures = 0; + CGxTexParms parms = {}; + parms.target = GxTex_2d; + parms.width = widthByFormat[this->m_textureFormat]; + parms.height = heightByFormat[this->m_textureFormat]; + parms.format = GxTex_Argb8888; + parms.dataFormat = GxTex_Argb8888; + parms.flags = CGxTexFlags(GxTex_Linear, 0, 0, 0, 0, 0, 1); + parms.userArg = &this->m_textureData[i]; + parms.userFunc = &CSimpleMovieFrame::TextureCallback; + this->m_textureData[i].params = parms; + this->m_textureData[i].data = this->m_imageData; + hasTextures &= GxTexCreate(parms, this->m_textures[i]); } if (hasTextures) { @@ -692,12 +642,21 @@ int32_t CSimpleMovieFrame::UpdateTiming() { // TODO: Subtitle stuff } -int32_t CSimpleMovieFrame::DecodeFrame(bool unk) { +int32_t CSimpleMovieFrame::DecodeFrame(bool update) { auto frameSize = *reinterpret_cast(this->m_currentFrameData); - if (!DivxDecode(this->m_decoder, this->m_currentFrameData, this->m_imageData)) { + if (!DivxDecode(this->m_decoder, this->m_currentFrameData, this->m_imageData, this->m_videoWidth)) { return 0; } this->m_currentFrameData += frameSize + 4; + + if (!update) { + return 1; + } + + for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { + GxTexUpdate(this->m_textures[i], 0, 0, this->m_textureData[i].params.width, this->m_textureData[i].params.height, 1); + } + return 1; } @@ -711,7 +670,7 @@ void CSimpleMovieFrame::Render() { GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ); GxXformSetViewport(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); - CImVector clearColor = { 0x00, 0x00, 0x80, 0xFF }; + CImVector clearColor = { 0x00, 0x00, 0x00, 0xFF }; GxSceneClear(3, clearColor); C44Matrix matrix; GxuXformCreateOrtho(0.0, 1.0, -0.5, 0.5, 0.0, 500.0, matrix); @@ -727,10 +686,35 @@ void CSimpleMovieFrame::Render() { GxRsSetAlphaRef(); for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { - C3Vector pos; - C3Vector normal(0.0f, 0.0f, 1.0f); - C2Vector tex(0.0f, 0.0f); - GxPrimLockVertexPtrs(4, &pos, sizeof(pos), &normal, 0, nullptr, 0, nullptr, 0, &tex, sizeof(tex), nullptr, 0); + if (i > 0) + continue; + + float inX = 0.1f; + float inY = -0.4f; + + float axX = 0.9f; + float axY = 0.4f; + + C3Vector position[] = { + { inX, inY, 0.0f }, + { axX, inY, 0.0f }, + { inX, axY, 0.0f }, + { axX, axY, 0.0f } + }; + + C3Vector normal[] = { + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 1.0f } + }; + C2Vector tex[] = { + { 0.0f, 0.0f }, + { 1.0f, 0.0f }, + { 0.0f, 1.0f }, + { 1.0f, 1.0f } + }; + GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, nullptr, 0, nullptr, 0, tex, sizeof(C2Vector), nullptr, 0); GxRsSet(GxRs_Texture0, this->m_textures[i]); uint16_t indices[] = { 0, 1, 2, 3 }; GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices); diff --git a/src/ui/CSimpleMovieFrame.hpp b/src/ui/CSimpleMovieFrame.hpp index 71681a8..f7db01f 100644 --- a/src/ui/CSimpleMovieFrame.hpp +++ b/src/ui/CSimpleMovieFrame.hpp @@ -2,6 +2,8 @@ #define UI_C_SIMPLE_MOVIE_FRAME_HPP #include "ui/CSimpleFrame.hpp" +#include "gx/Types.hpp" +#include "gx/Texture.hpp" #include class CRect; @@ -12,7 +14,7 @@ class CGxTexParms; class CSimpleMovieFrame : public CSimpleFrame { public: struct TextureData { - CGxTexParms* params; + CGxTexParms params; char* data; }; @@ -26,6 +28,7 @@ class CSimpleMovieFrame : public CSimpleFrame { static int32_t GetObjectType(); static void RegisterScriptMethods(lua_State* L); static void RenderMovie(void* param); + static void TextureCallback(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&); // Member variables void* m_audioChannel = nullptr; @@ -72,7 +75,7 @@ class CSimpleMovieFrame : public CSimpleFrame { int32_t OpenVideo(); void CloseVideo(); int32_t UpdateTiming(); - int32_t DecodeFrame(bool unk); + int32_t DecodeFrame(bool update); void Render(); }; From 690a90a65bf6e3a076b7393cdb67a8777e1d8e52 Mon Sep 17 00:00:00 2001 From: VDm Date: Wed, 30 Apr 2025 00:25:17 +0400 Subject: [PATCH 03/10] feat(ui): switch to original DivX decoder (32-bit only) --- src/ui/CSimpleMovieFrame.cpp | 335 +++++++++++++---------------------- src/ui/CSimpleMovieFrame.hpp | 2 +- 2 files changed, 129 insertions(+), 208 deletions(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index fcb6186..1460288 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -11,189 +11,57 @@ #if defined(WHOA_SYSTEM_WIN) -#include #include -#define XVID_MAKE_VERSION(a, b, c) ((((a) & 0xff) << 16) | (((b) & 0xff) << 8) | ((c) & 0xff)) -#define XVID_VERSION_MAJOR(a) ((char)(((a) >> 16) & 0xff)) -#define XVID_VERSION_MINOR(a) ((char)(((a) >> 8) & 0xff)) -#define XVID_VERSION_PATCH(a) ((char)(((a) >> 0) & 0xff)) +typedef int32_t(__cdecl* INITIALIZEDIVXDECODER)(uint32_t index, uint32_t width, uint32_t height); +typedef int32_t(__cdecl* SETOUTPUTFORMAT)(uint32_t index, uint32_t unk, uint32_t width, uint32_t height); +typedef int32_t(__cdecl* DIVXDECODE)(uint32_t index, void* data, uint32_t unk); +typedef int32_t(__cdecl* UNINITIALIZEDIVXDECODER)(uint32_t index); -#define XVID_MAKE_API(a, b) ((((a) & 0xff) << 16) | (((b) & 0xff) << 0)) -#define XVID_API_MAJOR(a) (((a) >> 16) & 0xff) -#define XVID_API_MINOR(a) (((a) >> 0) & 0xff) - -#define XVID_VERSION XVID_MAKE_VERSION(1, 4, -127) -#define XVID_API XVID_MAKE_API(4, 4) - -extern "C" { - -/* xvid_image_t - for non-planar colorspaces use only plane[0] and stride[0] - four plane reserved for alpha*/ -typedef struct { - int csp; /* [in] colorspace; or with XVID_CSP_VFLIP to perform vertical flip */ - void* plane[4]; /* [in] image plane ptrs */ - int stride[4]; /* [in] image stride; "bytes per row"*/ -} xvid_image_t; - -/* XVID_GBL_INIT param1 */ -typedef struct { - int version; - unsigned int cpu_flags; /* [in:opt] zero = autodetect cpu; XVID_CPU_FORCE|{cpu features} = force cpu features */ - int debug; /* [in:opt] debug level */ -} xvid_gbl_init_t; - -/* XVID_GBL_INFO param1 */ -typedef struct { - int version; - int actual_version; /* [out] returns the actual xvidcore version */ - const char* build; /* [out] if !null, points to description of this xvid core build */ - unsigned int cpu_flags; /* [out] detected cpu features */ - int num_threads; /* [out] detected number of cpus/threads */ -} xvid_gbl_info_t; - -#define XVID_GBL_INIT 0 /* initialize xvidcore; must be called before using xvid_decore, or xvid_encore) */ -#define XVID_GBL_INFO 1 /* return some info about xvidcore, and the host computer */ -#define XVID_GBL_CONVERT 2 /* colorspace conversion utility */ - -typedef int (*XVID_GLOBAL)(void* handle, int opt, void* param1, void* param2); - -#define XVID_DEC_CREATE 0 /* create decore instance; return 0 on success */ -#define XVID_DEC_DESTROY 1 /* destroy decore instance: return 0 on success */ -#define XVID_DEC_DECODE 2 /* decode a frame: returns number of bytes consumed >= 0 */ - -typedef int (*XVID_DECORE)(void* handle, int opt, void* param1, void* param2); - -/* XVID_DEC_CREATE param 1 - image width & height as well as FourCC code may be specified - here when known in advance (e.g. being read from container) */ -typedef struct { - int version; - int width; /* [in:opt] image width */ - int height; /* [in:opt] image width */ - void* handle; /* [out] decore context handle */ - /* ------- v1.3.x ------- */ - int fourcc; /* [in:opt] fourcc of the input video */ - int num_threads; /* [in:opt] number of threads to use in decoder */ -} xvid_dec_create_t; - -typedef struct { - int version; - int general; /* [in:opt] general flags */ - void* bitstream; /* [in] bitstream (read from)*/ - int length; /* [in] bitstream length */ - xvid_image_t output; /* [in] output image (written to) */ - /* ------- v1.1.x ------- */ - int brightness; /* [in] brightness offset (0=none) */ -} xvid_dec_frame_t; - -/* XVID_DEC_DECODE param2 :: optional */ -typedef struct -{ - int version; - - int type; /* [out] output data type */ - union { - struct { /* type>0 {XVID_TYPE_IVOP,XVID_TYPE_PVOP,XVID_TYPE_BVOP,XVID_TYPE_SVOP} */ - int general; /* [out] flags */ - int time_base; /* [out] time base */ - int time_increment; /* [out] time increment */ - - /* XXX: external deblocking stuff */ - int* qscale; /* [out] pointer to quantizer table */ - int qscale_stride; /* [out] quantizer scale stride */ - - } vop; - struct { /* XVID_TYPE_VOL */ - int general; /* [out] flags */ - int width; /* [out] width */ - int height; /* [out] height */ - int par; /* [out] pixel aspect ratio (refer to XVID_PAR_xxx above) */ - int par_width; /* [out] aspect ratio width [1..255] */ - int par_height; /* [out] aspect ratio height [1..255] */ - } vol; - } data; -} xvid_dec_stats_t; - -} // extern "C" - -static std::map s_divxHandles; static uint32_t s_divxRefCounter = 0; -static XVID_GLOBAL s_xvid_global = nullptr; -static XVID_DECORE s_xvid_decore = nullptr; +static INITIALIZEDIVXDECODER InitializeDivxDecoder = nullptr; +static SETOUTPUTFORMAT SetOutputFormat = nullptr; +static DIVXDECODE DivxDecode = nullptr; +static UNINITIALIZEDIVXDECODER UnInitializeDivxDecoder = nullptr; -static uint32_t LoadDivxDecoder() { - auto library = LoadLibraryA("xvidcore.dll"); - if (!library) { - return 0; - } +static uint32_t LoadDivxDecoder(uint32_t width, uint32_t height) { + if (!InitializeDivxDecoder || !SetOutputFormat || !DivxDecode || !UnInitializeDivxDecoder) { + auto library = LoadLibraryA("DivxDecoder.dll"); + if (!library) { + return 0; + } - s_xvid_global = reinterpret_cast(GetProcAddress(library, "xvid_global")); - s_xvid_decore = reinterpret_cast(GetProcAddress(library, "xvid_decore")); + InitializeDivxDecoder = reinterpret_cast(GetProcAddress(library, "InitializeDivxDecoder")); + SetOutputFormat = reinterpret_cast(GetProcAddress(library, "SetOutputFormat")); + DivxDecode = reinterpret_cast(GetProcAddress(library, "DivxDecode")); + UnInitializeDivxDecoder = reinterpret_cast(GetProcAddress(library, "UnInitializeDivxDecoder")); - if (!s_xvid_global || !s_xvid_decore) { - FreeLibrary(library); - return 0; - } - - xvid_gbl_info_t info = {}; - info.version = XVID_VERSION; - - if (s_xvid_global(nullptr, XVID_GBL_INFO, &info, nullptr) < 0) { - return 0; - } - - xvid_gbl_init_t init = {}; - init.version = XVID_VERSION; - if (s_xvid_global(nullptr, XVID_GBL_INIT, &init, nullptr) < 0) { - return 0; - } - - xvid_dec_create_t decoder = {}; - decoder.version = XVID_VERSION; - decoder.num_threads = info.num_threads; - if (s_xvid_decore(nullptr, XVID_DEC_CREATE, &decoder, nullptr)) { - return 0; + if (!InitializeDivxDecoder || !SetOutputFormat || !DivxDecode || !UnInitializeDivxDecoder) { + InitializeDivxDecoder = nullptr; + SetOutputFormat = nullptr; + DivxDecode = nullptr; + UnInitializeDivxDecoder = nullptr; + FreeLibrary(library); + return 0; + } } if (++s_divxRefCounter == 0) { ++s_divxRefCounter; } - s_divxHandles[s_divxRefCounter] = decoder.handle; - return s_divxRefCounter; -} - -static int32_t DivxDecode(uint32_t decoder, char* input, char* output, int32_t width) { - xvid_dec_frame_t frame = {}; - xvid_dec_stats_t stats = {}; - - frame.version = XVID_VERSION; - stats.version = XVID_VERSION; - - frame.bitstream = input + 4; - frame.length = *reinterpret_cast(input); - - frame.output.plane[0] = output; - frame.output.stride[0] = 4 * width; - frame.output.csp = (1 << 15); - - static int frameNo = 0; - - while (true) { - int bytes = s_xvid_decore(s_divxHandles[decoder], XVID_DEC_DECODE, &frame, &stats); - if (bytes < 1) { - break; - } - frame.bitstream = (char*)frame.bitstream + bytes; - frame.length -= bytes; + if (InitializeDivxDecoder(s_divxRefCounter, width, height)) { + UnInitializeDivxDecoder(s_divxRefCounter--); + return 0; } - frameNo++; + if (SetOutputFormat(s_divxRefCounter, 1, width, height)) { + UnInitializeDivxDecoder(s_divxRefCounter--); + return 0; + } - return 1; + return s_divxRefCounter; } #else @@ -244,8 +112,10 @@ void CSimpleMovieFrame::RenderMovie(void* param) { void CSimpleMovieFrame::TextureCallback(EGxTexCommand command, uint32_t width, uint32_t height, uint32_t, uint32_t, void* userData, uint32_t& texelStrideInBytes, const void*& texels) { if (command == GxTex_Latch) { + auto textureData = reinterpret_cast(userData); + //texelStrideInBytes = textureData->strideData[3] / 2; texelStrideInBytes = 4 * width; - texels = reinterpret_cast(userData)->data; + texels = &textureData->data[textureData->strideData[2]]; } } @@ -501,7 +371,7 @@ int32_t CSimpleMovieFrame::ParseAVIFile(const char* filename) { int32_t CSimpleMovieFrame::OpenVideo() { this->m_startTime = OsGetAsyncTimeMs(); this->m_elapsedTime = 0; - this->m_decoder = LoadDivxDecoder(); + this->m_decoder = LoadDivxDecoder(this->m_videoWidth, this->m_videoHeight); this->m_currentFrame = 0; this->m_prevFrame = -1; this->m_lastKeyFrame = 0; @@ -534,6 +404,7 @@ int32_t CSimpleMovieFrame::OpenVideo() { const uint32_t widthByFormat[6] = { 800, 1024, 800, 1024, 800, 1024 }; const uint32_t heightByFormat[6] = { 384, 512, 512, 576, 384, 512 }; + static uint32_t s_strideData[144] = { 512, 256, 0, 3200, 256, 256, 2048, 3200, 32, 256, 3072, 3200, 512, 128, 819200, 3200, 256, 128, 821248, 3200, 32, 128, 822272, 3200, 512, 512, 0, 4096, 512, 512, 2048, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 512, 0, 3200, 256, 512, 2048, 3200, 32, 512, 3072, 3200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 512, 0, 4096, 512, 512, 2048, 4096, 512, 64, 2097152, 4096, 512, 64, 2099200, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 512, 256, 0, 3200, 256, 256, 2048, 3200, 32, 256, 3072, 3200, 512, 128, 819200, 3200, 256, 128, 821248, 3200, 32, 128, 822272, 3200, 512, 512, 0, 4096, 512, 512, 2048, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint32_t imageSize = widthByFormat[this->m_textureFormat] * heightByFormat[this->m_textureFormat] * 4; this->m_imageData = reinterpret_cast(ALLOC_ZERO(imageSize)); @@ -544,18 +415,18 @@ int32_t CSimpleMovieFrame::OpenVideo() { int32_t hasTextures = 1; for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { - CGxTexParms parms = {}; - parms.target = GxTex_2d; - parms.width = widthByFormat[this->m_textureFormat]; - parms.height = heightByFormat[this->m_textureFormat]; - parms.format = GxTex_Argb8888; - parms.dataFormat = GxTex_Argb8888; - parms.flags = CGxTexFlags(GxTex_Linear, 0, 0, 0, 0, 0, 1); - parms.userArg = &this->m_textureData[i]; - parms.userFunc = &CSimpleMovieFrame::TextureCallback; - this->m_textureData[i].params = parms; + uint32_t stride = (6 * this->m_textureFormat + i) * 4; + this->m_textureData[i].strideData = &s_strideData[stride]; this->m_textureData[i].data = this->m_imageData; - hasTextures &= GxTexCreate(parms, this->m_textures[i]); + + hasTextures &= GxTexCreate( + s_strideData[stride], + s_strideData[stride + 1], + GxTex_Argb8888, + CGxTexFlags(), + &this->m_textureData[i], + CSimpleMovieFrame::TextureCallback, + this->m_textures[i]); } if (hasTextures) { @@ -640,21 +511,64 @@ int32_t CSimpleMovieFrame::UpdateTiming() { this->m_prevFrame = this->m_currentFrame; // TODO: Subtitle stuff + return 1; } int32_t CSimpleMovieFrame::DecodeFrame(bool update) { +#pragma pack(push, 1) + struct DecoderData + { + char* output; + char* input; + uint32_t inputSize; + uint32_t update; + uint32_t v14; + uint32_t v15; + }; +#pragma pack(pop) + + DecoderData decoderData = {}; + + const uint32_t imageDataOffsets[6] = { + 19200, 98304, 102400, 0, 67200, 155648 + }; + auto frameSize = *reinterpret_cast(this->m_currentFrameData); - if (!DivxDecode(this->m_decoder, this->m_currentFrameData, this->m_imageData, this->m_videoWidth)) { + + decoderData.output = this->m_imageData + imageDataOffsets[this->m_textureFormat]; + decoderData.input = this->m_currentFrameData + 4; + decoderData.inputSize = frameSize; + decoderData.update = update ? 1 : 0; + + this->m_currentFrameData += frameSize + 4; + + if (DivxDecode(this->m_decoder, &decoderData, 0)) { return 0; } - this->m_currentFrameData += frameSize + 4; if (!update) { return 1; } + int32_t s_movieTextureUpdate[144] = { + 0, 6, 512, 256, 0, 6, 256, 256, 0, 6, 32, 256, 0, 0, 512, 122, + 0, 0, 256, 122, 0, 0, 32, 122, 0, 24, 512, 512, 0, 0, 512, 488, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 512, 480, 0, + 32, 256, 480, 0, 32, 32, 480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 512, 512, 0, 0, 512, 512, 0, 0, 512, 64, 0, 0, 512, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 21, 512, 256, 0, 21, 256, 256, 0, 21, 32, 256, 0, 0, 512, + 107, 0, 0, 256, 107, 0, 0, 32, 107, 0, 38, 512, 512, 0, 0, 512, 474, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { - GxTexUpdate(this->m_textures[i], 0, 0, this->m_textureData[i].params.width, this->m_textureData[i].params.height, 1); + uint32_t v9 = 4 * (i + 6 * this->m_textureFormat); + GxTexUpdate( + this->m_textures[i], + s_movieTextureUpdate[v9], + s_movieTextureUpdate[v9 + 1], + s_movieTextureUpdate[v9 + 2], + s_movieTextureUpdate[v9 + 3], + 1); } return 1; @@ -677,7 +591,28 @@ void CSimpleMovieFrame::Render() { GxXformSetView(C44Matrix()); GxXformSetProjection(matrix); - // TODO + static uint32_t s_movieRenderFlag = 0; + static C3Vector s_movieFrameNormalVec; + static C2Vector s_movieFrameTexVec[4]; + + if ((s_movieRenderFlag & 1) == 0) { + s_movieFrameNormalVec.x = 0.0; + s_movieFrameNormalVec.y = 0.0; + s_movieFrameNormalVec.z = 1.0; + s_movieRenderFlag |= 1; + } + + if ((s_movieRenderFlag & 2) == 0) { + s_movieFrameTexVec[0].x = 0.0; + s_movieFrameTexVec[0].y = 0.0; + s_movieFrameTexVec[1].y = 0.0; + s_movieFrameTexVec[2].x = 0.0; + s_movieFrameTexVec[1].x = 1.0; + s_movieFrameTexVec[2].y = s_movieFrameTexVec[1].x; + s_movieFrameTexVec[3].x = s_movieFrameTexVec[1].x; + s_movieFrameTexVec[3].y = s_movieFrameTexVec[1].x; + s_movieRenderFlag |= 2; + } GxRsPush(); GxRsSet(GxRs_Lighting, 0); @@ -685,36 +620,22 @@ void CSimpleMovieFrame::Render() { GxRsSet(GxRs_BlendingMode, 0); GxRsSetAlphaRef(); + static float s_layout[] = {0.0, 0.63999999, 0.11, -0.33000001, 0.63999999, 0.95999998, 0.11, -0.33000001, 0.95999998, 1.0, 0.11, -0.33000001, 0.0, 0.63999999, 0.33000001, 0.11, 0.63999999, 0.95999998, 0.33000001, 0.11, 0.95999998, 1.0, 0.33000001, 0.11, 0.0, 0.5, 0.333, -0.333, 0.5, 1.0, 0.333, -0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.63999999, 0.41999999, -0.41999999, 0.63999999, 0.95999998, 0.41999999, -0.41999999, 0.95999998, 1.0, 0.41999999, -0.41999999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.32659999, -0.41999999, 0.5, 1.0, 0.32659999, -0.41999999, 0.0, 0.5, 0.41999999, 0.32659999, 0.5, 1.0, 0.41999999, 0.32659999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.63999999, 0.11, -0.33000001, 0.63999999, 0.95999998, 0.11, -0.33000001, 0.95999998, 1.0, 0.11, -0.33000001, 0.0, 0.63999999, 0.33000001, 0.11, 0.63999999, 0.95999998, 0.33000001, 0.11, 0.95999998, 1.0, 0.33000001, 0.11, 0.0, 0.5, 0.333, -0.333, 0.5, 1.0, 0.333, -0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { - if (i > 0) - continue; + float* rect = &s_layout[24 * this->m_textureFormat + 4 * i]; - float inX = 0.1f; - float inY = -0.4f; - - float axX = 0.9f; - float axY = 0.4f; + float v16 = rect[3]; // * aspectCompensation + float v17 = rect[2]; // * aspectCompensation C3Vector position[] = { - { inX, inY, 0.0f }, - { axX, inY, 0.0f }, - { inX, axY, 0.0f }, - { axX, axY, 0.0f } + { rect[0], v16, 0.0f }, + { rect[1], v16, 0.0f }, + { rect[0], v17, 0.0f }, + { rect[1], v17, 0.0f } }; - C3Vector normal[] = { - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f } - }; - C2Vector tex[] = { - { 0.0f, 0.0f }, - { 1.0f, 0.0f }, - { 0.0f, 1.0f }, - { 1.0f, 1.0f } - }; - GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, nullptr, 0, nullptr, 0, tex, sizeof(C2Vector), nullptr, 0); + GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), &s_movieFrameNormalVec, 0, nullptr, 0, nullptr, 0, s_movieFrameTexVec, sizeof(C2Vector), nullptr, 0); GxRsSet(GxRs_Texture0, this->m_textures[i]); uint16_t indices[] = { 0, 1, 2, 3 }; GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices); diff --git a/src/ui/CSimpleMovieFrame.hpp b/src/ui/CSimpleMovieFrame.hpp index f7db01f..d9c8323 100644 --- a/src/ui/CSimpleMovieFrame.hpp +++ b/src/ui/CSimpleMovieFrame.hpp @@ -14,7 +14,7 @@ class CGxTexParms; class CSimpleMovieFrame : public CSimpleFrame { public: struct TextureData { - CGxTexParms params; + uint32_t* strideData; char* data; }; From c721538698f0dd98232cbcf441bcc6cdb9d3d2b5 Mon Sep 17 00:00:00 2001 From: VDm Date: Thu, 1 May 2025 00:10:25 +0400 Subject: [PATCH 04/10] fix(gx): fix Blit_uint32_uint32 when inStride != outStride --- src/gx/Blit.cpp | 2 +- src/ui/CSimpleMovieFrame.cpp | 43 ++++++++++++++++++++++-------------- src/ui/CSimpleMovieFrame.hpp | 4 ++-- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/gx/Blit.cpp b/src/gx/Blit.cpp index 870c26f..044d37e 100644 --- a/src/gx/Blit.cpp +++ b/src/gx/Blit.cpp @@ -53,7 +53,7 @@ void Blit_uint32_uint32(const C2iVector& size, const void* in, uint32_t inStride char* out_ = reinterpret_cast(out); for (int32_t i = 0; i < size.y; i++) { - memcpy(out, in, 4 * size.x); + memcpy(out_, in_, 4 * size.x); in_ += inStride; out_ += outStride; } diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index 1460288..1b13ec4 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -1,6 +1,7 @@ #include "ui/CSimpleMovieFrame.hpp" #include "ui/CSimpleMovieFrameScript.hpp" #include "util/SFile.hpp" +#include "gx/Coordinate.hpp" #include "gx/Buffer.hpp" #include "gx/RenderState.hpp" #include "gx/Texture.hpp" @@ -112,10 +113,13 @@ void CSimpleMovieFrame::RenderMovie(void* param) { void CSimpleMovieFrame::TextureCallback(EGxTexCommand command, uint32_t width, uint32_t height, uint32_t, uint32_t, void* userData, uint32_t& texelStrideInBytes, const void*& texels) { if (command == GxTex_Latch) { - auto textureData = reinterpret_cast(userData); - //texelStrideInBytes = textureData->strideData[3] / 2; - texelStrideInBytes = 4 * width; - texels = &textureData->data[textureData->strideData[2]]; + auto data = reinterpret_cast(userData); + + STORM_ASSERT(width == data->data[0]); + STORM_ASSERT(height == data->data[1]); + + texels = &data->buffer[data->data[2]]; + texelStrideInBytes = data->data[3]; } } @@ -416,8 +420,8 @@ int32_t CSimpleMovieFrame::OpenVideo() { int32_t hasTextures = 1; for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { uint32_t stride = (6 * this->m_textureFormat + i) * 4; - this->m_textureData[i].strideData = &s_strideData[stride]; - this->m_textureData[i].data = this->m_imageData; + this->m_textureData[i].data = &s_strideData[stride]; + this->m_textureData[i].buffer = this->m_imageData; hasTextures &= GxTexCreate( s_strideData[stride], @@ -599,18 +603,23 @@ void CSimpleMovieFrame::Render() { s_movieFrameNormalVec.x = 0.0; s_movieFrameNormalVec.y = 0.0; s_movieFrameNormalVec.z = 1.0; + s_movieRenderFlag |= 1; } if ((s_movieRenderFlag & 2) == 0) { - s_movieFrameTexVec[0].x = 0.0; - s_movieFrameTexVec[0].y = 0.0; - s_movieFrameTexVec[1].y = 0.0; - s_movieFrameTexVec[2].x = 0.0; - s_movieFrameTexVec[1].x = 1.0; - s_movieFrameTexVec[2].y = s_movieFrameTexVec[1].x; - s_movieFrameTexVec[3].x = s_movieFrameTexVec[1].x; - s_movieFrameTexVec[3].y = s_movieFrameTexVec[1].x; + s_movieFrameTexVec[0].x = 0.0f; + s_movieFrameTexVec[0].y = 0.0f; + + s_movieFrameTexVec[1].x = 1.0f; + s_movieFrameTexVec[1].y = 0.0f; + + s_movieFrameTexVec[2].x = 0.0f; + s_movieFrameTexVec[2].y = 1.0f; + + s_movieFrameTexVec[3].x = 1.0f; + s_movieFrameTexVec[3].y = 1.0f; + s_movieRenderFlag |= 2; } @@ -622,11 +631,13 @@ void CSimpleMovieFrame::Render() { static float s_layout[] = {0.0, 0.63999999, 0.11, -0.33000001, 0.63999999, 0.95999998, 0.11, -0.33000001, 0.95999998, 1.0, 0.11, -0.33000001, 0.0, 0.63999999, 0.33000001, 0.11, 0.63999999, 0.95999998, 0.33000001, 0.11, 0.95999998, 1.0, 0.33000001, 0.11, 0.0, 0.5, 0.333, -0.333, 0.5, 1.0, 0.333, -0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.63999999, 0.41999999, -0.41999999, 0.63999999, 0.95999998, 0.41999999, -0.41999999, 0.95999998, 1.0, 0.41999999, -0.41999999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.32659999, -0.41999999, 0.5, 1.0, 0.32659999, -0.41999999, 0.0, 0.5, 0.41999999, 0.32659999, 0.5, 1.0, 0.41999999, 0.32659999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.63999999, 0.11, -0.33000001, 0.63999999, 0.95999998, 0.11, -0.33000001, 0.95999998, 1.0, 0.11, -0.33000001, 0.0, 0.63999999, 0.33000001, 0.11, 0.63999999, 0.95999998, 0.33000001, 0.11, 0.95999998, 1.0, 0.33000001, 0.11, 0.0, 0.5, 0.333, -0.333, 0.5, 1.0, 0.333, -0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + float aspectCompensation = CoordinateGetAspectCompensation(); + for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { float* rect = &s_layout[24 * this->m_textureFormat + 4 * i]; - float v16 = rect[3]; // * aspectCompensation - float v17 = rect[2]; // * aspectCompensation + float v16 = rect[3] * aspectCompensation; + float v17 = rect[2] * aspectCompensation; C3Vector position[] = { { rect[0], v16, 0.0f }, diff --git a/src/ui/CSimpleMovieFrame.hpp b/src/ui/CSimpleMovieFrame.hpp index d9c8323..f75d607 100644 --- a/src/ui/CSimpleMovieFrame.hpp +++ b/src/ui/CSimpleMovieFrame.hpp @@ -14,8 +14,8 @@ class CGxTexParms; class CSimpleMovieFrame : public CSimpleFrame { public: struct TextureData { - uint32_t* strideData; - char* data; + uint32_t* data; + char* buffer; }; From 2a526e61965c983d83920d2e5ed7a2c9e6a44664 Mon Sep 17 00:00:00 2001 From: VDm Date: Thu, 1 May 2025 01:35:16 +0400 Subject: [PATCH 05/10] style(ui): update code style in CSimpleMovieFrame.cpp --- src/ui/CSimpleMovieFrame.cpp | 98 ++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 11 deletions(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index 1b13ec4..c41cd1a 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -554,21 +554,55 @@ int32_t CSimpleMovieFrame::DecodeFrame(bool update) { return 1; } - int32_t s_movieTextureUpdate[144] = { - 0, 6, 512, 256, 0, 6, 256, 256, 0, 6, 32, 256, 0, 0, 512, 122, - 0, 0, 256, 122, 0, 0, 32, 122, 0, 24, 512, 512, 0, 0, 512, 488, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 512, 480, 0, - 32, 256, 480, 0, 32, 32, 480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 512, 512, 0, 0, 512, 512, 0, 0, 512, 64, 0, 0, 512, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 21, 512, 256, 0, 21, 256, 256, 0, 21, 32, 256, 0, 0, 512, - 107, 0, 0, 256, 107, 0, 0, 32, 107, 0, 38, 512, 512, 0, 0, 512, 474, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static int32_t s_movieTextureUpdate[] = { + 0, 6, 512, 256, // Format: 0, Texture: 0 + 0, 6, 256, 256, // Format: 0, Texture: 1 + 0, 6, 32, 256, // Format: 0, Texture: 2 + 0, 0, 512, 122, // Format: 0, Texture: 3 + 0, 0, 256, 122, // Format: 0, Texture: 4 + 0, 0, 32, 122, // Format: 0, Texture: 5 + + 0, 24, 512, 512, // Format: 1, Texture: 0 + 0, 0, 512, 488, // Format: 1, Texture: 1 + 0, 0, 0, 0, // Format: 1, Texture: 2 + 0, 0, 0, 0, // Format: 1, Texture: 3 + 0, 0, 0, 0, // Format: 1, Texture: 4 + 0, 0, 0, 0, // Format: 1, Texture: 5 + + 0, 32, 512, 480, // Format: 2, Texture: 0 + 0, 32, 256, 480, // Format: 2, Texture: 1 + 0, 32, 32, 480, // Format: 2, Texture: 2 + 0, 0, 0, 0, // Format: 2, Texture: 3 + 0, 0, 0, 0, // Format: 2, Texture: 4 + 0, 0, 0, 0, // Format: 2, Texture: 5 + + 0, 0, 512, 512, // Format: 3, Texture: 0 + 0, 0, 512, 512, // Format: 3, Texture: 1 + 0, 0, 512, 64, // Format: 3, Texture: 2 + 0, 0, 512, 64, // Format: 3, Texture: 3 + 0, 0, 0, 0, // Format: 3, Texture: 4 + 0, 0, 0, 0, // Format: 3, Texture: 5 + + 0, 21, 512, 256, // Format: 4, Texture: 0 + 0, 21, 256, 256, // Format: 4, Texture: 1 + 0, 21, 32, 256, // Format: 4, Texture: 2 + 0, 0, 512, 107, // Format: 4, Texture: 3 + 0, 0, 256, 107, // Format: 4, Texture: 4 + 0, 0, 32, 107, // Format: 4, Texture: 5 + + 0, 38, 512, 512, // Format: 5, Texture: 0 + 0, 0, 512, 474, // Format: 5, Texture: 1 + 0, 0, 0, 0, // Format: 5, Texture: 2 + 0, 0, 0, 0, // Format: 5, Texture: 3 + 0, 0, 0, 0, // Format: 5, Texture: 4 + 0, 0, 0, 0 // Format: 5, Texture: 5 + }; for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { uint32_t v9 = 4 * (i + 6 * this->m_textureFormat); GxTexUpdate( this->m_textures[i], - s_movieTextureUpdate[v9], + s_movieTextureUpdate[v9 + 0], s_movieTextureUpdate[v9 + 1], s_movieTextureUpdate[v9 + 2], s_movieTextureUpdate[v9 + 3], @@ -629,7 +663,49 @@ void CSimpleMovieFrame::Render() { GxRsSet(GxRs_BlendingMode, 0); GxRsSetAlphaRef(); - static float s_layout[] = {0.0, 0.63999999, 0.11, -0.33000001, 0.63999999, 0.95999998, 0.11, -0.33000001, 0.95999998, 1.0, 0.11, -0.33000001, 0.0, 0.63999999, 0.33000001, 0.11, 0.63999999, 0.95999998, 0.33000001, 0.11, 0.95999998, 1.0, 0.33000001, 0.11, 0.0, 0.5, 0.333, -0.333, 0.5, 1.0, 0.333, -0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.63999999, 0.41999999, -0.41999999, 0.63999999, 0.95999998, 0.41999999, -0.41999999, 0.95999998, 1.0, 0.41999999, -0.41999999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.32659999, -0.41999999, 0.5, 1.0, 0.32659999, -0.41999999, 0.0, 0.5, 0.41999999, 0.32659999, 0.5, 1.0, 0.41999999, 0.32659999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.63999999, 0.11, -0.33000001, 0.63999999, 0.95999998, 0.11, -0.33000001, 0.95999998, 1.0, 0.11, -0.33000001, 0.0, 0.63999999, 0.33000001, 0.11, 0.63999999, 0.95999998, 0.33000001, 0.11, 0.95999998, 1.0, 0.33000001, 0.11, 0.0, 0.5, 0.333, -0.333, 0.5, 1.0, 0.333, -0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + static float s_layout[] = { + 0.0, 0.63999999, 0.11, -0.33000001, + 0.63999999, 0.95999998, 0.11, -0.33000001, + 0.95999998, 1.0, 0.11, -0.33000001, + 0.0, 0.63999999, 0.33000001, 0.11, + 0.63999999, 0.95999998, 0.33000001, 0.11, + 0.95999998, 1.0, 0.33000001, 0.11, + + 0.0, 0.5, 0.333, -0.333, + 0.5, 1.0, 0.333, -0.333, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + + 0.0, 0.63999999, 0.41999999, -0.41999999, + 0.63999999, 0.95999998, 0.41999999, -0.41999999, + 0.95999998, 1.0, 0.41999999, -0.41999999, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + + 0.0, 0.5, 0.32659999, -0.41999999, + 0.5, 1.0, 0.32659999, -0.41999999, + 0.0, 0.5, 0.41999999, 0.32659999, + 0.5, 1.0, 0.41999999, 0.32659999, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + + 0.0, 0.63999999, 0.11, -0.33000001, + 0.63999999, 0.95999998, 0.11, -0.33000001, + 0.95999998, 1.0, 0.11, -0.33000001, + 0.0, 0.63999999, 0.33000001, 0.11, + 0.63999999, 0.95999998, 0.33000001, 0.11, + 0.95999998, 1.0, 0.33000001, 0.11, + + 0.0, 0.5, 0.333, -0.333, + 0.5, 1.0, 0.333, -0.333, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0 + }; float aspectCompensation = CoordinateGetAspectCompensation(); From 6ec90df6630ec78353e909a0bcef2a92a4a8798c Mon Sep 17 00:00:00 2001 From: VDm Date: Thu, 1 May 2025 01:42:45 +0400 Subject: [PATCH 06/10] style(ui): update stride data array declaration in CSimpleMovieFrame.cpp --- src/ui/CSimpleMovieFrame.cpp | 44 +++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index c41cd1a..fc907d4 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -408,7 +408,49 @@ int32_t CSimpleMovieFrame::OpenVideo() { const uint32_t widthByFormat[6] = { 800, 1024, 800, 1024, 800, 1024 }; const uint32_t heightByFormat[6] = { 384, 512, 512, 576, 384, 512 }; - static uint32_t s_strideData[144] = { 512, 256, 0, 3200, 256, 256, 2048, 3200, 32, 256, 3072, 3200, 512, 128, 819200, 3200, 256, 128, 821248, 3200, 32, 128, 822272, 3200, 512, 512, 0, 4096, 512, 512, 2048, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 512, 0, 3200, 256, 512, 2048, 3200, 32, 512, 3072, 3200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 512, 0, 4096, 512, 512, 2048, 4096, 512, 64, 2097152, 4096, 512, 64, 2099200, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 512, 256, 0, 3200, 256, 256, 2048, 3200, 32, 256, 3072, 3200, 512, 128, 819200, 3200, 256, 128, 821248, 3200, 32, 128, 822272, 3200, 512, 512, 0, 4096, 512, 512, 2048, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static uint32_t s_strideData[144] = { + 512, 256, 0, 3200, + 256, 256, 2048, 3200, + 32, 256, 3072, 3200, + 512, 128, 819200, 3200, + 256, 128, 821248, 3200, + 32, 128, 822272, 3200, + + 512, 512, 0, 4096, + 512, 512, 2048, 4096, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 512, 512, 0, 3200, + 256, 512, 2048, 3200, + 32, 512, 3072, 3200, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 512, 512, 0, 4096, + 512, 512, 2048, 4096, + 512, 64, 2097152, 4096, + 512, 64, 2099200, 4096, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 512, 256, 0, 3200, + 256, 256, 2048, 3200, + 32, 256, 3072, 3200, + 512, 128, 819200, 3200, + 256, 128, 821248, 3200, + 32, 128, 822272, 3200, + + 512, 512, 0, 4096, + 512, 512, 2048, 4096, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; const uint32_t imageSize = widthByFormat[this->m_textureFormat] * heightByFormat[this->m_textureFormat] * 4; this->m_imageData = reinterpret_cast(ALLOC_ZERO(imageSize)); From 4caed1318e6e42d5150d2f461865c7798258dc9d Mon Sep 17 00:00:00 2001 From: VDm Date: Thu, 1 May 2025 02:12:18 +0400 Subject: [PATCH 07/10] fix(ui): use workaround to update movie textures --- src/ui/CSimpleMovieFrame.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index fc907d4..e071c24 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -642,6 +642,8 @@ int32_t CSimpleMovieFrame::DecodeFrame(bool update) { for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { uint32_t v9 = 4 * (i + 6 * this->m_textureFormat); + // WARNING(workaround): Uncomment the code below when GxTexUpdate will be working properly + /* GxTexUpdate( this->m_textures[i], s_movieTextureUpdate[v9 + 0], @@ -649,6 +651,8 @@ int32_t CSimpleMovieFrame::DecodeFrame(bool update) { s_movieTextureUpdate[v9 + 2], s_movieTextureUpdate[v9 + 3], 1); + */ + GxTexUpdate(this->m_textures[i], 0, 0, 0, 0, 1); } return 1; From 1cc668be95bf04fb3642c635a813cfcc6df3544f Mon Sep 17 00:00:00 2001 From: VDm Date: Sat, 3 May 2025 15:48:16 +0400 Subject: [PATCH 08/10] feat(ui): update CSimpleMovieFrame to support Divx/Xvid Decoders (Windows only) --- src/ui/CSimpleMovieFrame.cpp | 433 ++++++++++++++++++----------------- 1 file changed, 223 insertions(+), 210 deletions(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index e071c24..1293a31 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -10,63 +10,86 @@ #include #include -#if defined(WHOA_SYSTEM_WIN) -#include +extern "C" { -typedef int32_t(__cdecl* INITIALIZEDIVXDECODER)(uint32_t index, uint32_t width, uint32_t height); -typedef int32_t(__cdecl* SETOUTPUTFORMAT)(uint32_t index, uint32_t unk, uint32_t width, uint32_t height); -typedef int32_t(__cdecl* DIVXDECODE)(uint32_t index, void* data, uint32_t unk); -typedef int32_t(__cdecl* UNINITIALIZEDIVXDECODER)(uint32_t index); +typedef struct { + void* output; + void* input; + unsigned int input_size; + int update; + int zero0; + int zero1; +} decoder_data_t; -static uint32_t s_divxRefCounter = 0; +typedef int(__cdecl* INITIALIZEDIVXDECODER)(unsigned int index, unsigned int width, unsigned int height); +typedef int(__cdecl* SETOUTPUTFORMAT)(unsigned int index, unsigned int one, unsigned int width, unsigned int height); +typedef int(__cdecl* DIVXDECODE)(unsigned int index, void* data, unsigned int zero); +typedef int(__cdecl* UNINITIALIZEDIVXDECODER)(unsigned int index); + +} static INITIALIZEDIVXDECODER InitializeDivxDecoder = nullptr; static SETOUTPUTFORMAT SetOutputFormat = nullptr; static DIVXDECODE DivxDecode = nullptr; static UNINITIALIZEDIVXDECODER UnInitializeDivxDecoder = nullptr; -static uint32_t LoadDivxDecoder(uint32_t width, uint32_t height) { +#if defined(WHOA_SYSTEM_WIN) + +#include + +static HMODULE s_decoderLibrary = NULL; + +static int32_t UnloadDivxDecoder() { + if (s_decoderLibrary == NULL) { + return 0; + } + + InitializeDivxDecoder = nullptr; + SetOutputFormat = nullptr; + DivxDecode = nullptr; + UnInitializeDivxDecoder = nullptr; + + FreeLibrary(s_decoderLibrary); + s_decoderLibrary = NULL; + + return 1; +} + +static int32_t LoadDivxDecoder() { + if (InitializeDivxDecoder && SetOutputFormat && DivxDecode && UnInitializeDivxDecoder) { + return 1; + } + + // Try to load original decoder first + s_decoderLibrary = LoadLibraryA("DivxDecoder.dll"); + if (s_decoderLibrary == NULL) { + // Try to load open source decoder + s_decoderLibrary = LoadLibraryA("XvidDecoder.dll"); + if (s_decoderLibrary == NULL) { + return 0; + } + } + + InitializeDivxDecoder = reinterpret_cast(GetProcAddress(s_decoderLibrary, "InitializeDivxDecoder")); + SetOutputFormat = reinterpret_cast(GetProcAddress(s_decoderLibrary, "SetOutputFormat")); + DivxDecode = reinterpret_cast(GetProcAddress(s_decoderLibrary, "DivxDecode")); + UnInitializeDivxDecoder = reinterpret_cast(GetProcAddress(s_decoderLibrary, "UnInitializeDivxDecoder")); + if (!InitializeDivxDecoder || !SetOutputFormat || !DivxDecode || !UnInitializeDivxDecoder) { - auto library = LoadLibraryA("DivxDecoder.dll"); - if (!library) { - return 0; - } - - InitializeDivxDecoder = reinterpret_cast(GetProcAddress(library, "InitializeDivxDecoder")); - SetOutputFormat = reinterpret_cast(GetProcAddress(library, "SetOutputFormat")); - DivxDecode = reinterpret_cast(GetProcAddress(library, "DivxDecode")); - UnInitializeDivxDecoder = reinterpret_cast(GetProcAddress(library, "UnInitializeDivxDecoder")); - - if (!InitializeDivxDecoder || !SetOutputFormat || !DivxDecode || !UnInitializeDivxDecoder) { - InitializeDivxDecoder = nullptr; - SetOutputFormat = nullptr; - DivxDecode = nullptr; - UnInitializeDivxDecoder = nullptr; - FreeLibrary(library); - return 0; - } - } - - if (++s_divxRefCounter == 0) { - ++s_divxRefCounter; - } - - if (InitializeDivxDecoder(s_divxRefCounter, width, height)) { - UnInitializeDivxDecoder(s_divxRefCounter--); + UnloadDivxDecoder(); return 0; } - if (SetOutputFormat(s_divxRefCounter, 1, width, height)) { - UnInitializeDivxDecoder(s_divxRefCounter--); - return 0; - } - - return s_divxRefCounter; + return 1; } #else +static int32_t UnloadDivxDecoder() { + return 0; +} + static uint32_t LoadDivxDecoder() { return 0; } @@ -74,11 +97,140 @@ static uint32_t LoadDivxDecoder() { #endif -static void UnloadDivxDecoder(uint32_t decoder) { +static uint32_t s_decoderIndex = 0; +static uint32_t s_strideData[144] = { + 512, 256, 0, 3200, + 256, 256, 2048, 3200, + 32, 256, 3072, 3200, + 512, 128, 819200, 3200, + 256, 128, 821248, 3200, + 32, 128, 822272, 3200, -} + 512, 512, 0, 4096, + 512, 512, 2048, 4096, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, -static const uint32_t textureCountByFormat[6] = { 6, 2, 3, 4, 6, 2 }; + 512, 512, 0, 3200, + 256, 512, 2048, 3200, + 32, 512, 3072, 3200, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 512, 512, 0, 4096, + 512, 512, 2048, 4096, + 512, 64, 2097152, 4096, + 512, 64, 2099200, 4096, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 512, 256, 0, 3200, + 256, 256, 2048, 3200, + 32, 256, 3072, 3200, + 512, 128, 819200, 3200, + 256, 128, 821248, 3200, + 32, 128, 822272, 3200, + + 512, 512, 0, 4096, + 512, 512, 2048, 4096, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static int32_t s_movieTextureUpdate[] = { + 0, 6, 512, 256, // Format: 0, Texture: 0 + 0, 6, 256, 256, // Format: 0, Texture: 1 + 0, 6, 32, 256, // Format: 0, Texture: 2 + 0, 0, 512, 122, // Format: 0, Texture: 3 + 0, 0, 256, 122, // Format: 0, Texture: 4 + 0, 0, 32, 122, // Format: 0, Texture: 5 + + 0, 24, 512, 512, // Format: 1, Texture: 0 + 0, 0, 512, 488, // Format: 1, Texture: 1 + 0, 0, 0, 0, // Format: 1, Texture: 2 + 0, 0, 0, 0, // Format: 1, Texture: 3 + 0, 0, 0, 0, // Format: 1, Texture: 4 + 0, 0, 0, 0, // Format: 1, Texture: 5 + + 0, 32, 512, 480, // Format: 2, Texture: 0 + 0, 32, 256, 480, // Format: 2, Texture: 1 + 0, 32, 32, 480, // Format: 2, Texture: 2 + 0, 0, 0, 0, // Format: 2, Texture: 3 + 0, 0, 0, 0, // Format: 2, Texture: 4 + 0, 0, 0, 0, // Format: 2, Texture: 5 + + 0, 0, 512, 512, // Format: 3, Texture: 0 + 0, 0, 512, 512, // Format: 3, Texture: 1 + 0, 0, 512, 64, // Format: 3, Texture: 2 + 0, 0, 512, 64, // Format: 3, Texture: 3 + 0, 0, 0, 0, // Format: 3, Texture: 4 + 0, 0, 0, 0, // Format: 3, Texture: 5 + + 0, 21, 512, 256, // Format: 4, Texture: 0 + 0, 21, 256, 256, // Format: 4, Texture: 1 + 0, 21, 32, 256, // Format: 4, Texture: 2 + 0, 0, 512, 107, // Format: 4, Texture: 3 + 0, 0, 256, 107, // Format: 4, Texture: 4 + 0, 0, 32, 107, // Format: 4, Texture: 5 + + 0, 38, 512, 512, // Format: 5, Texture: 0 + 0, 0, 512, 474, // Format: 5, Texture: 1 + 0, 0, 0, 0, // Format: 5, Texture: 2 + 0, 0, 0, 0, // Format: 5, Texture: 3 + 0, 0, 0, 0, // Format: 5, Texture: 4 + 0, 0, 0, 0 // Format: 5, Texture: 5 +}; +static float s_layout[144] = { + 0.0f, 0.63999999f, 0.11f, -0.33000001f, + 0.63999999f, 0.95999998f, 0.11f, -0.33000001f, + 0.95999998f, 1.0f, 0.11f, -0.33000001f, + 0.0f, 0.63999999f, 0.33000001f, 0.11f, + 0.63999999f, 0.95999998f, 0.33000001f, 0.11f, + 0.95999998f, 1.0f, 0.33000001f, 0.11f, + + 0.0f, 0.5f, 0.333f, -0.333f, + 0.5f, 1.0f, 0.333f, -0.333f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + + 0.0f, 0.63999999f, 0.41999999f, -0.41999999f, + 0.63999999f, 0.95999998f, 0.41999999f, -0.41999999f, + 0.95999998f, 1.0f, 0.41999999f, -0.41999999f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + + 0.0f, 0.5f, 0.32659999f, -0.41999999f, + 0.5f, 1.0f, 0.32659999f, -0.41999999f, + 0.0f, 0.5f, 0.41999999f, 0.32659999f, + 0.5f, 1.0f, 0.41999999f, 0.32659999f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + + 0.0f, 0.63999999f, 0.11f, -0.33000001f, + 0.63999999f, 0.95999998f, 0.11f, -0.33000001f, + 0.95999998f, 1.0f, 0.11f, -0.33000001f, + 0.0f, 0.63999999f, 0.33000001f, 0.11f, + 0.63999999f, 0.95999998f, 0.33000001f, 0.11f, + 0.95999998f, 1.0f, 0.33000001f, 0.11f, + + 0.0f, 0.5f, 0.333f, -0.333f, + 0.5f, 1.0f, 0.333f, -0.333f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f +}; +static const uint32_t s_textureCountByFormat[6] = { 6, 2, 3, 4, 6, 2 }; +static const uint32_t s_imageDataOffsets[6] = { + 19200, 98304, 102400, 0, 67200, 155648 +}; int32_t CSimpleMovieFrame::s_metatable; @@ -169,6 +321,10 @@ CSimpleMovieFrame::CSimpleMovieFrame(CSimpleFrame* parent) } int32_t CSimpleMovieFrame::StartMovie(const char* filename, int32_t volume) { + if (!LoadDivxDecoder()) { + return 0; + } + if (!this->ParseAVIFile(filename) || !this->OpenVideo()) { return 0; } @@ -304,9 +460,9 @@ int32_t CSimpleMovieFrame::ParseAVIFile(const char* filename) { } else { offset += 8; if (!SStrCmpI(&data[offset], "vids", 4)) { - float scale = *reinterpret_cast(&data[offset + 20]); - float rate = *reinterpret_cast(&data[offset + 24]); - this->m_frameRate = rate / scale; + uint32_t scale = *reinterpret_cast(&data[offset + 20]); + uint32_t rate = *reinterpret_cast(&data[offset + 24]); + this->m_frameRate = static_cast(rate) / static_cast(scale); this->m_numFrames = *reinterpret_cast(&data[offset + 32]); v39 = v41; } @@ -375,13 +531,16 @@ int32_t CSimpleMovieFrame::ParseAVIFile(const char* filename) { int32_t CSimpleMovieFrame::OpenVideo() { this->m_startTime = OsGetAsyncTimeMs(); this->m_elapsedTime = 0; - this->m_decoder = LoadDivxDecoder(this->m_videoWidth, this->m_videoHeight); + this->m_decoder = ++s_decoderIndex; + this->m_currentFrame = 0; this->m_prevFrame = -1; this->m_lastKeyFrame = 0; this->m_frameAudioSync = 0; - if (!this->m_decoder) { + if (InitializeDivxDecoder(this->m_decoder, this->m_videoWidth, this->m_videoHeight) || + SetOutputFormat(this->m_decoder, 1, this->m_videoWidth, this->m_videoHeight)) { + this->CloseVideo(); return 0; } @@ -402,55 +561,12 @@ int32_t CSimpleMovieFrame::OpenVideo() { this->m_textureFormat = 0; } } else { - CloseVideo(); + this->CloseVideo(); return 0; } const uint32_t widthByFormat[6] = { 800, 1024, 800, 1024, 800, 1024 }; const uint32_t heightByFormat[6] = { 384, 512, 512, 576, 384, 512 }; - static uint32_t s_strideData[144] = { - 512, 256, 0, 3200, - 256, 256, 2048, 3200, - 32, 256, 3072, 3200, - 512, 128, 819200, 3200, - 256, 128, 821248, 3200, - 32, 128, 822272, 3200, - - 512, 512, 0, 4096, - 512, 512, 2048, 4096, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - - 512, 512, 0, 3200, - 256, 512, 2048, 3200, - 32, 512, 3072, 3200, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - - 512, 512, 0, 4096, - 512, 512, 2048, 4096, - 512, 64, 2097152, 4096, - 512, 64, 2099200, 4096, - 0, 0, 0, 0, - 0, 0, 0, 0, - - 512, 256, 0, 3200, - 256, 256, 2048, 3200, - 32, 256, 3072, 3200, - 512, 128, 819200, 3200, - 256, 128, 821248, 3200, - 32, 128, 822272, 3200, - - 512, 512, 0, 4096, - 512, 512, 2048, 4096, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; const uint32_t imageSize = widthByFormat[this->m_textureFormat] * heightByFormat[this->m_textureFormat] * 4; this->m_imageData = reinterpret_cast(ALLOC_ZERO(imageSize)); @@ -460,7 +576,7 @@ int32_t CSimpleMovieFrame::OpenVideo() { } int32_t hasTextures = 1; - for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { + for (uint32_t i = 0; i < s_textureCountByFormat[this->m_textureFormat]; ++i) { uint32_t stride = (6 * this->m_textureFormat + i) * 4; this->m_textureData[i].data = &s_strideData[stride]; this->m_textureData[i].buffer = this->m_imageData; @@ -476,7 +592,7 @@ int32_t CSimpleMovieFrame::OpenVideo() { } if (hasTextures) { - for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { + for (uint32_t i = 0; i < s_textureCountByFormat[this->m_textureFormat]; ++i) { GxTexUpdate(this->m_textures[i], 0, 0, 0, 0, 1); } } @@ -486,7 +602,8 @@ int32_t CSimpleMovieFrame::OpenVideo() { void CSimpleMovieFrame::CloseVideo() { if (this->m_decoder) { - UnloadDivxDecoder(this->m_decoder); + UnInitializeDivxDecoder(this->m_decoder); + --s_decoderIndex; this->m_decoder = 0; } @@ -561,34 +678,18 @@ int32_t CSimpleMovieFrame::UpdateTiming() { } int32_t CSimpleMovieFrame::DecodeFrame(bool update) { -#pragma pack(push, 1) - struct DecoderData - { - char* output; - char* input; - uint32_t inputSize; - uint32_t update; - uint32_t v14; - uint32_t v15; - }; -#pragma pack(pop) + decoder_data_t frame; - DecoderData decoderData = {}; + frame.output = this->m_imageData + s_imageDataOffsets[this->m_textureFormat]; + frame.input = this->m_currentFrameData + 4; + frame.input_size = *reinterpret_cast(this->m_currentFrameData); + frame.update = update ? 1 : 0; + frame.zero0 = 0; + frame.zero1 = 0; - const uint32_t imageDataOffsets[6] = { - 19200, 98304, 102400, 0, 67200, 155648 - }; + this->m_currentFrameData += frame.input_size + 4; - auto frameSize = *reinterpret_cast(this->m_currentFrameData); - - decoderData.output = this->m_imageData + imageDataOffsets[this->m_textureFormat]; - decoderData.input = this->m_currentFrameData + 4; - decoderData.inputSize = frameSize; - decoderData.update = update ? 1 : 0; - - this->m_currentFrameData += frameSize + 4; - - if (DivxDecode(this->m_decoder, &decoderData, 0)) { + if (DivxDecode(this->m_decoder, &frame, 0)) { return 0; } @@ -596,51 +697,7 @@ int32_t CSimpleMovieFrame::DecodeFrame(bool update) { return 1; } - static int32_t s_movieTextureUpdate[] = { - 0, 6, 512, 256, // Format: 0, Texture: 0 - 0, 6, 256, 256, // Format: 0, Texture: 1 - 0, 6, 32, 256, // Format: 0, Texture: 2 - 0, 0, 512, 122, // Format: 0, Texture: 3 - 0, 0, 256, 122, // Format: 0, Texture: 4 - 0, 0, 32, 122, // Format: 0, Texture: 5 - - 0, 24, 512, 512, // Format: 1, Texture: 0 - 0, 0, 512, 488, // Format: 1, Texture: 1 - 0, 0, 0, 0, // Format: 1, Texture: 2 - 0, 0, 0, 0, // Format: 1, Texture: 3 - 0, 0, 0, 0, // Format: 1, Texture: 4 - 0, 0, 0, 0, // Format: 1, Texture: 5 - - 0, 32, 512, 480, // Format: 2, Texture: 0 - 0, 32, 256, 480, // Format: 2, Texture: 1 - 0, 32, 32, 480, // Format: 2, Texture: 2 - 0, 0, 0, 0, // Format: 2, Texture: 3 - 0, 0, 0, 0, // Format: 2, Texture: 4 - 0, 0, 0, 0, // Format: 2, Texture: 5 - - 0, 0, 512, 512, // Format: 3, Texture: 0 - 0, 0, 512, 512, // Format: 3, Texture: 1 - 0, 0, 512, 64, // Format: 3, Texture: 2 - 0, 0, 512, 64, // Format: 3, Texture: 3 - 0, 0, 0, 0, // Format: 3, Texture: 4 - 0, 0, 0, 0, // Format: 3, Texture: 5 - - 0, 21, 512, 256, // Format: 4, Texture: 0 - 0, 21, 256, 256, // Format: 4, Texture: 1 - 0, 21, 32, 256, // Format: 4, Texture: 2 - 0, 0, 512, 107, // Format: 4, Texture: 3 - 0, 0, 256, 107, // Format: 4, Texture: 4 - 0, 0, 32, 107, // Format: 4, Texture: 5 - - 0, 38, 512, 512, // Format: 5, Texture: 0 - 0, 0, 512, 474, // Format: 5, Texture: 1 - 0, 0, 0, 0, // Format: 5, Texture: 2 - 0, 0, 0, 0, // Format: 5, Texture: 3 - 0, 0, 0, 0, // Format: 5, Texture: 4 - 0, 0, 0, 0 // Format: 5, Texture: 5 - }; - - for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { + for (uint32_t i = 0; i < s_textureCountByFormat[this->m_textureFormat]; ++i) { uint32_t v9 = 4 * (i + 6 * this->m_textureFormat); // WARNING(workaround): Uncomment the code below when GxTexUpdate will be working properly /* @@ -709,53 +766,9 @@ void CSimpleMovieFrame::Render() { GxRsSet(GxRs_BlendingMode, 0); GxRsSetAlphaRef(); - static float s_layout[] = { - 0.0, 0.63999999, 0.11, -0.33000001, - 0.63999999, 0.95999998, 0.11, -0.33000001, - 0.95999998, 1.0, 0.11, -0.33000001, - 0.0, 0.63999999, 0.33000001, 0.11, - 0.63999999, 0.95999998, 0.33000001, 0.11, - 0.95999998, 1.0, 0.33000001, 0.11, - - 0.0, 0.5, 0.333, -0.333, - 0.5, 1.0, 0.333, -0.333, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - - 0.0, 0.63999999, 0.41999999, -0.41999999, - 0.63999999, 0.95999998, 0.41999999, -0.41999999, - 0.95999998, 1.0, 0.41999999, -0.41999999, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - - 0.0, 0.5, 0.32659999, -0.41999999, - 0.5, 1.0, 0.32659999, -0.41999999, - 0.0, 0.5, 0.41999999, 0.32659999, - 0.5, 1.0, 0.41999999, 0.32659999, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - - 0.0, 0.63999999, 0.11, -0.33000001, - 0.63999999, 0.95999998, 0.11, -0.33000001, - 0.95999998, 1.0, 0.11, -0.33000001, - 0.0, 0.63999999, 0.33000001, 0.11, - 0.63999999, 0.95999998, 0.33000001, 0.11, - 0.95999998, 1.0, 0.33000001, 0.11, - - 0.0, 0.5, 0.333, -0.333, - 0.5, 1.0, 0.333, -0.333, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0 - }; - float aspectCompensation = CoordinateGetAspectCompensation(); - for (uint32_t i = 0; i < textureCountByFormat[this->m_textureFormat]; ++i) { + for (uint32_t i = 0; i < s_textureCountByFormat[this->m_textureFormat]; ++i) { float* rect = &s_layout[24 * this->m_textureFormat + 4 * i]; float v16 = rect[3] * aspectCompensation; From bd0e59a795f911fc9443ba1ad0b66242c1c40836 Mon Sep 17 00:00:00 2001 From: VDm Date: Sat, 3 May 2025 15:54:49 +0400 Subject: [PATCH 09/10] fix(d3d): fix calling conventions --- src/gx/d3d/CGxDeviceD3d.cpp | 8 +++++--- src/gx/d3d/CGxDeviceD3d.hpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gx/d3d/CGxDeviceD3d.cpp b/src/gx/d3d/CGxDeviceD3d.cpp index e9b355b..afceedd 100644 --- a/src/gx/d3d/CGxDeviceD3d.cpp +++ b/src/gx/d3d/CGxDeviceD3d.cpp @@ -225,11 +225,13 @@ int32_t CGxDeviceD3d::ILoadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d) { d3dLib = LoadLibrary(TEXT("d3d9.dll")); + typedef LPDIRECT3D9 (WINAPI *DIRECT3DCREATE9)(UINT SDKVersion); + if (d3dLib) { - auto d3dCreateProc = GetProcAddress(d3dLib, "Direct3DCreate9"); + auto d3dCreateProc = reinterpret_cast(GetProcAddress(d3dLib, "Direct3DCreate9")); if (d3dCreateProc) { - d3d = reinterpret_cast(d3dCreateProc()); + d3d = d3dCreateProc(D3D_SDK_VERSION); if (d3d) { return 1; @@ -258,7 +260,7 @@ void CGxDeviceD3d::IUnloadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d) { } } -LRESULT CGxDeviceD3d::WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { +LRESULT CALLBACK CGxDeviceD3d::WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { auto device = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); switch (uMsg) { diff --git a/src/gx/d3d/CGxDeviceD3d.hpp b/src/gx/d3d/CGxDeviceD3d.hpp index c4b786b..95ef1ef 100644 --- a/src/gx/d3d/CGxDeviceD3d.hpp +++ b/src/gx/d3d/CGxDeviceD3d.hpp @@ -218,7 +218,7 @@ class CGxDeviceD3d : public CGxDevice { // Static functions static int32_t ILoadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d); static void IUnloadD3dLib(HINSTANCE& d3dLib, LPDIRECT3D9& d3d); - static LRESULT WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // Member variables HWND m_hwnd = nullptr; From fbaeb2e052c1b56a819491c75eec34cb0e3aa309 Mon Sep 17 00:00:00 2001 From: VDm Date: Tue, 6 May 2025 21:29:28 +0400 Subject: [PATCH 10/10] feat(ui): introduce cross-platform solution for CSimpleMovieFrame --- src/ui/CSimpleMovieFrame.cpp | 96 +++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/src/ui/CSimpleMovieFrame.cpp b/src/ui/CSimpleMovieFrame.cpp index 1293a31..e2795a4 100644 --- a/src/ui/CSimpleMovieFrame.cpp +++ b/src/ui/CSimpleMovieFrame.cpp @@ -11,6 +11,38 @@ #include +#define XVDEC_CALL + +#if defined(WHOA_SYSTEM_WIN) +#include + +#if defined(WHOA_ARCH_32) +#undef XVDEC_CALL +#define XVDEC_CALL __cdecl +#elif defined(__GNUC__) || defined(__clang__) +#undef XVDEC_CALL +#define XVDEC_CALL __attribute__((cdecl)) +#endif + +#define RTLD_LAZY 1 + +static inline void* dlopen(const char* filename, int flag) { + (void)flag; + return LoadLibraryA(filename); +} + +static inline void* dlsym(void* handle, const char* symbol) { + return GetProcAddress(reinterpret_cast(handle), symbol); +} + +static inline int dlclose(void* handle) { + return static_cast(FreeLibrary(reinterpret_cast(handle))); +} + +#else // !defined(WHOA_SYSTEM_WIN) +#include +#endif + extern "C" { typedef struct { @@ -22,26 +54,34 @@ typedef struct { int zero1; } decoder_data_t; -typedef int(__cdecl* INITIALIZEDIVXDECODER)(unsigned int index, unsigned int width, unsigned int height); -typedef int(__cdecl* SETOUTPUTFORMAT)(unsigned int index, unsigned int one, unsigned int width, unsigned int height); -typedef int(__cdecl* DIVXDECODE)(unsigned int index, void* data, unsigned int zero); -typedef int(__cdecl* UNINITIALIZEDIVXDECODER)(unsigned int index); +typedef int (XVDEC_CALL * INITIALIZEDIVXDECODER)(unsigned int index, unsigned int width, unsigned int height); +typedef int (XVDEC_CALL * SETOUTPUTFORMAT)(unsigned int index, unsigned int one, unsigned int width, unsigned int height); +typedef int (XVDEC_CALL * DIVXDECODE)(unsigned int index, void* data, unsigned int zero); +typedef int (XVDEC_CALL * UNINITIALIZEDIVXDECODER)(unsigned int index); } +static void* s_decoderLibrary = nullptr; + static INITIALIZEDIVXDECODER InitializeDivxDecoder = nullptr; static SETOUTPUTFORMAT SetOutputFormat = nullptr; static DIVXDECODE DivxDecode = nullptr; static UNINITIALIZEDIVXDECODER UnInitializeDivxDecoder = nullptr; -#if defined(WHOA_SYSTEM_WIN) -#include +static const char* s_decoderNames[] = { + "DivxDecoder.dll", + "XvidDecoder.dll", + "libXvidDecoder.dylib", + "XvidDecoder.dylib", + "libXvidDecoder.so", + "XvidDecoder.so", + nullptr +}; -static HMODULE s_decoderLibrary = NULL; static int32_t UnloadDivxDecoder() { - if (s_decoderLibrary == NULL) { + if (!s_decoderLibrary) { return 0; } @@ -50,8 +90,8 @@ static int32_t UnloadDivxDecoder() { DivxDecode = nullptr; UnInitializeDivxDecoder = nullptr; - FreeLibrary(s_decoderLibrary); - s_decoderLibrary = NULL; + dlclose(s_decoderLibrary); + s_decoderLibrary = nullptr; return 1; } @@ -61,20 +101,20 @@ static int32_t LoadDivxDecoder() { return 1; } - // Try to load original decoder first - s_decoderLibrary = LoadLibraryA("DivxDecoder.dll"); - if (s_decoderLibrary == NULL) { - // Try to load open source decoder - s_decoderLibrary = LoadLibraryA("XvidDecoder.dll"); - if (s_decoderLibrary == NULL) { - return 0; - } + const char** decoderName = s_decoderNames; + while (!s_decoderLibrary && *decoderName) { + s_decoderLibrary = dlopen(*decoderName, RTLD_LAZY); + ++decoderName; } - InitializeDivxDecoder = reinterpret_cast(GetProcAddress(s_decoderLibrary, "InitializeDivxDecoder")); - SetOutputFormat = reinterpret_cast(GetProcAddress(s_decoderLibrary, "SetOutputFormat")); - DivxDecode = reinterpret_cast(GetProcAddress(s_decoderLibrary, "DivxDecode")); - UnInitializeDivxDecoder = reinterpret_cast(GetProcAddress(s_decoderLibrary, "UnInitializeDivxDecoder")); + if (!s_decoderLibrary) { + return 0; + } + + InitializeDivxDecoder = reinterpret_cast(dlsym(s_decoderLibrary, "InitializeDivxDecoder")); + SetOutputFormat = reinterpret_cast(dlsym(s_decoderLibrary, "SetOutputFormat")); + DivxDecode = reinterpret_cast(dlsym(s_decoderLibrary, "DivxDecode")); + UnInitializeDivxDecoder = reinterpret_cast(dlsym(s_decoderLibrary, "UnInitializeDivxDecoder")); if (!InitializeDivxDecoder || !SetOutputFormat || !DivxDecode || !UnInitializeDivxDecoder) { UnloadDivxDecoder(); @@ -84,18 +124,6 @@ static int32_t LoadDivxDecoder() { return 1; } -#else - -static int32_t UnloadDivxDecoder() { - return 0; -} - -static uint32_t LoadDivxDecoder() { - return 0; -} - -#endif - static uint32_t s_decoderIndex = 0; static uint32_t s_strideData[144] = {