diff --git a/CMakeLists.txt b/CMakeLists.txt index e44861fa..d1f67422 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ include(FindPkgConfig) include(FetchContent) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(SOURCE_FILES natives/common/riff.cc) + set(IMAGE_SOURCE_FILES natives/image/blur.cc natives/image/bounce.cc natives/image/caption.cc @@ -69,7 +71,7 @@ if (WITH_ZXING) list(APPEND IMAGE_SOURCE_FILES natives/image/qr.cc) endif() -set(SOURCE_FILES "${IMAGE_SOURCE_FILES}") +list(APPEND SOURCE_FILES "${IMAGE_SOURCE_FILES}") if (CMAKE_JS_VERSION) add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC} natives/node/media.cc natives/node/worker.cc) diff --git a/natives/common/riff.cc b/natives/common/riff.cc new file mode 100644 index 00000000..b856d2e5 --- /dev/null +++ b/natives/common/riff.cc @@ -0,0 +1,21 @@ +#include + +#include "../shared.h" +#include "riff.h" + +int RIFF::findChunk(char *data, size_t length, const char *chunk, size_t &position, uint32_t *size) { + int pos = -1; + uint32_t chunkSize = 0; + while (position + 8 <= length && pos == -1) { + const char *fourCC = &data[position]; + chunkSize = readUint32LE(reinterpret_cast(data) + position + 4); + + if (memcmp(fourCC, chunk, 4) == 0) { + pos = position + 8; + } + + position += 8 + chunkSize + (chunkSize % 2); + } + if (size != NULL) *size = chunkSize; + return pos; +} diff --git a/natives/common/riff.h b/natives/common/riff.h new file mode 100644 index 00000000..a682a22b --- /dev/null +++ b/natives/common/riff.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +namespace RIFF { + struct RIFFHeader { + char riff[4]; + uint32_t chunkSize; + char tag[4]; + }; + + struct ChunkHeader { + char id[4]; + uint32_t size; + }; + + int findChunk(char *data, size_t length, const char *fourCC, size_t &position, uint32_t *size); +} // namespace RIFF diff --git a/natives/image/freeze.cc b/natives/image/freeze.cc index f3362ccd..e4684606 100644 --- a/natives/image/freeze.cc +++ b/natives/image/freeze.cc @@ -1,6 +1,7 @@ #include #include +#include "../common/riff.h" #include "common.h" using namespace std; @@ -31,7 +32,7 @@ char *vipsTrim(const char *data, size_t length, size_t &dataSize, int frame, str } CmdOutput esmb::Image::Freeze(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - esmb::ArgumentMap arguments, bool *shouldKill) { + esmb::ArgumentMap arguments, bool *shouldKill) { bool loop = GetArgumentWithFallback(arguments, "loop", false); int frame = GetArgumentWithFallback(arguments, "frame", -1); @@ -100,18 +101,10 @@ CmdOutput esmb::Image::Freeze(const string &type, string &outType, const char *b size_t position = 12; - while (position + 8 <= bufferLength) { - const char *fourCC = &fileData[position]; - uint32_t chunkSize = readUint32LE(reinterpret_cast(fileData) + position + 4); - - if (memcmp(fourCC, "ANIM", 4) == 0) { - size_t dataStart = position + 8; - - fileData[dataStart + 4] = loop ? 0 : 1; - fileData[dataStart + 5] = 0; - } - - position += 8 + chunkSize + (chunkSize % 2); + int dataStart = 0; + while ((dataStart = RIFF::findChunk(fileData, bufferLength, "ANIM", position, NULL)) != -1) { + fileData[dataStart + 4] = loop ? 0 : 1; + fileData[dataStart + 5] = 0; } output.buf = fileData; diff --git a/natives/image/speed.cc b/natives/image/speed.cc index 75dfebf9..ffb1c9e6 100644 --- a/natives/image/speed.cc +++ b/natives/image/speed.cc @@ -1,6 +1,7 @@ #include #include +#include "../common/riff.h" #include "common.h" using namespace std; @@ -43,8 +44,9 @@ char *vipsRemove(const char *data, size_t length, size_t &dataSize, int speed, s return buf; } -CmdOutput esmb::Image::Speed([[maybe_unused]] const string &type, [[maybe_unused]] string &outType, const char *bufferdata, - size_t bufferLength, esmb::ArgumentMap arguments, bool *shouldKill) { +CmdOutput esmb::Image::Speed([[maybe_unused]] const string &type, [[maybe_unused]] string &outType, + const char *bufferdata, size_t bufferLength, esmb::ArgumentMap arguments, + bool *shouldKill) { bool slow = GetArgumentWithFallback(arguments, "slow", false); int speed = GetArgumentWithFallback(arguments, "speed", 2); @@ -100,25 +102,18 @@ CmdOutput esmb::Image::Speed([[maybe_unused]] const string &type, [[maybe_unused size_t position = 12; bool removeFrames = false; - while (position + 8 <= bufferLength) { - const char *fourCC = &fileData[position]; - uint32_t chunkSize = readUint32LE(reinterpret_cast(fileData) + position + 4); - - if (memcmp(fourCC, "ANMF", 4) == 0) { - size_t dataStart = position + 8; - uint32_t duration = readUint32LE(reinterpret_cast(fileData) + dataStart + 12) & 0x00FFFFFF; - uint32_t newDuration = slow ? duration * speed : duration / speed; - if (!slow && newDuration <= 10) { - removeFrames = true; - break; - } - - fileData[dataStart + 12] = static_cast(newDuration & 0xFF); - fileData[dataStart + 13] = static_cast((newDuration >> 8) & 0xFF); - fileData[dataStart + 14] = static_cast((newDuration >> 16) & 0xFF); + int dataStart = 0; + while ((dataStart = RIFF::findChunk(fileData, bufferLength, "ANMF", position, NULL)) != -1) { + uint32_t duration = readUint32LE(reinterpret_cast(fileData) + dataStart + 12) & 0x00FFFFFF; + uint32_t newDuration = slow ? duration * speed : duration / speed; + if (!slow && newDuration <= 10) { + removeFrames = true; + break; } - position += 8 + chunkSize + (chunkSize % 2); + fileData[dataStart + 12] = static_cast(newDuration & 0xFF); + fileData[dataStart + 13] = static_cast((newDuration >> 8) & 0xFF); + fileData[dataStart + 14] = static_cast((newDuration >> 16) & 0xFF); } if (removeFrames) { diff --git a/natives/shared.h b/natives/shared.h index 30d210c7..45db6598 100644 --- a/natives/shared.h +++ b/natives/shared.h @@ -27,7 +27,7 @@ typedef const std::map FunctionArgs; CmdOutput NAME(const std::string &type, std::string &outType, esmb::ArgumentMap arguments, bool *shouldKill) #define declare_input_args(NAME) extern FunctionArgs NAME; -inline uint32_t readUint32LE(unsigned char *buffer) { +inline uint32_t readUint32LE(const unsigned char *buffer) { return static_cast(buffer[0]) | (static_cast(buffer[1]) << 8) | (static_cast(buffer[2]) << 16) | (static_cast(buffer[3]) << 24); } \ No newline at end of file