Skip to content

Commit

Permalink
Merge branches 'lua_api' and 'misc' into feature
Browse files Browse the repository at this point in the history
  • Loading branch information
arch1t3cht committed Feb 20, 2024
3 parents ba9f48a + f52b699 + 1515c77 commit dcca721
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 22 deletions.
30 changes: 27 additions & 3 deletions automation/v4-docs/get-frame.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,18 @@ 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

@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

---

Expand All @@ -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.

---
38 changes: 25 additions & 13 deletions src/auto4_lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
}

Expand All @@ -279,7 +290,8 @@ namespace {
{"height", FrameHeight},
{"getPixel", FramePixel},
{"getPixelFormatted", FramePixelFormatted},
{"__gc", FrameDestory},
{"data", FrameData},
{"__gc", FrameDestroy},
{NULL, NULL}
};

Expand Down
22 changes: 16 additions & 6 deletions src/grid_column.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};

Expand All @@ -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);
}
};

Expand Down

0 comments on commit dcca721

Please sign in to comment.