Merge branches 'lua_api' and 'misc' into feature

This commit is contained in:
arch1t3cht 2024-02-20 15:04:04 +01:00
commit dcca721543
3 changed files with 68 additions and 22 deletions

View file

@ -40,7 +40,7 @@ Returns: number
Get RGB pixel value at a certain position of frame object.
function frame:frame:getPixel(x, y)
function frame:getPixel(x, y)
@x (number)
Pixel to retrieve on the x-axis
@ -48,8 +48,10 @@ function frame:frame:getPixel(x, y)
@y (number)
Pixel to retrieve on the y-axis
Returns: number
Integer value representing the RGB pixel value.
Returns: 3 values, all numbers
1. R value of the pixel
2. G value of the pixel
3. B value of the pixel
---
@ -67,3 +69,25 @@ Returns: string
String in ASS format representing the pixel value. e.g. "&H0073FF&"
---
Get raw BGRA (alpha being irrelevant) data of frame object, whose pixel values
can then be accessed via LuaJIT's FFI.
The frame data is valid until the frame object is garbage-collected.
Example usage (which does not account for flipped frames for simplicity)
data, pitch = frame:data()
buf = require("ffi").cast("unsigned char *", data)
-- Get the R value of the pixel at coordinates (42, 34)
pix_val = buf[34 * pitch + 4 * 42 + 2]
function frame:data()
Returns: 3 values - a lightuserdata, a number, and a boolean
1. Lightuserdata object which can be cast to "unsigned char *" via ffi.cast, a pointer
to the raw frame data.
2. The pitch of the frame data.
3. Whether the frame is flipped upside-down.
---

View file

@ -198,25 +198,25 @@ namespace {
}
}
std::shared_ptr<VideoFrame> check_VideoFrame(lua_State *L) {
std::shared_ptr<VideoFrame> *check_VideoFrame(lua_State *L) {
auto framePtr = static_cast<std::shared_ptr<VideoFrame>*>(luaL_checkudata(L, 1, "VideoFrame"));
return *framePtr;
return framePtr;
}
int FrameWidth(lua_State *L) {
std::shared_ptr<VideoFrame> frame = check_VideoFrame(L);
std::shared_ptr<VideoFrame> frame = *check_VideoFrame(L);
push_value(L, frame->width);
return 1;
}
int FrameHeight(lua_State *L) {
std::shared_ptr<VideoFrame> frame = check_VideoFrame(L);
std::shared_ptr<VideoFrame> frame = *check_VideoFrame(L);
push_value(L, frame->height);
return 1;
}
int FramePixel(lua_State *L) {
std::shared_ptr<VideoFrame> frame = check_VideoFrame(L);
std::shared_ptr<VideoFrame> frame = *check_VideoFrame(L);
size_t x = lua_tointeger(L, -2);
size_t y = lua_tointeger(L, -1);
lua_pop(L, 2);
@ -227,16 +227,17 @@ namespace {
size_t pos = y * frame->pitch + x * 4;
// VideoFrame is stored as BGRA, but we want to return RGB
int pixelValue = frame->data[pos+2] * 65536 + frame->data[pos+1] * 256 + frame->data[pos];
push_value(L, pixelValue);
push_value(L, frame->data[pos+2]);
push_value(L, frame->data[pos+1]);
push_value(L, frame->data[pos]);
} else {
lua_pushnil(L);
}
return 1;
return 3;
}
int FramePixelFormatted(lua_State *L) {
std::shared_ptr<VideoFrame> frame = check_VideoFrame(L);
std::shared_ptr<VideoFrame> frame = *check_VideoFrame(L);
size_t x = lua_tointeger(L, -2);
size_t y = lua_tointeger(L, -1);
lua_pop(L, 2);
@ -255,9 +256,19 @@ namespace {
return 1;
}
int FrameDestory(lua_State *L) {
std::shared_ptr<VideoFrame> frame = check_VideoFrame(L);
frame.~shared_ptr<VideoFrame>();
int FrameData(lua_State *L) {
std::shared_ptr<VideoFrame> frame = *check_VideoFrame(L);
push_value(L, frame->data.data());
push_value(L, frame->pitch);
push_value(L, frame->flipped);
return 3;
}
int FrameDestroy(lua_State *L) {
std::shared_ptr<VideoFrame> *frame = check_VideoFrame(L);
frame->~shared_ptr<VideoFrame>();
return 0;
}
@ -279,7 +290,8 @@ namespace {
{"height", FrameHeight},
{"getPixel", FramePixel},
{"getPixelFormatted", FramePixelFormatted},
{"__gc", FrameDestory},
{"data", FrameData},
{"__gc", FrameDestroy},
{NULL, NULL}
};

View file

@ -205,9 +205,14 @@ struct GridColumnStartTime final : GridColumnTime {
int Width(const agi::Context *c, WidthHelper &helper) const override {
agi::Time max_time = max_value(&AssDialogue::Start, c->ass->Events);
if (!by_frame)
return helper(max_time.GetAssFormatted());
return helper(std::to_wstring(c->videoController->FrameAtTime(max_time, agi::vfr::START)));
std::string value = by_frame ? std::to_string(c->videoController->FrameAtTime(max_time, agi::vfr::START)) : max_time.GetAssFormatted();
for (char &c : value) {
if (c >= '0' && c <= '9')
c = '0';
}
return helper(value);
}
};
@ -223,9 +228,14 @@ struct GridColumnEndTime final : GridColumnTime {
int Width(const agi::Context *c, WidthHelper &helper) const override {
agi::Time max_time = max_value(&AssDialogue::End, c->ass->Events);
if (!by_frame)
return helper(max_time.GetAssFormatted());
return helper(std::to_wstring(c->videoController->FrameAtTime(max_time, agi::vfr::END)));
std::string value = by_frame ? std::to_string(c->videoController->FrameAtTime(max_time, agi::vfr::END)) : max_time.GetAssFormatted();
for (char &c : value) {
if (c >= '0' && c <= '9')
c = '0';
}
return helper(value);
}
};