camera

Read-only. Everything the capture card reports about itself — its name, the live frame format, and every format it advertises — plus one thing the user tells us: source(). A USB capture card exposes nothing about the game, the source console, or signal presence, so anything content-aware must come from the pixels (via OnFrameReceived); the source label is the one exception, and it's user-declared, not detected. The table is locked: assigning to it or replacing its metatable raises an error.

functioncamera.isOpen() → boolean

Whether a capture device is currently open and streaming. Takes no parameters.

functioncamera.name() → string | nil

The device's name, e.g. "UGREEN-25854" — the card's USB name, not the console or game. nil if no device is open. Takes no parameters.

functioncamera.source() → string | nil

The user-declared label for whatever HDMI device is plugged into this card, e.g. "Nintendo Switch". The card cannot detect this — the user types it in Options → Connected device, and it's remembered per card name. nil until they set it. Useful for source-specific mods: if camera.source() == "Nintendo Switch" then …. Takes no parameters.

functioncamera.width() → number

Width in pixels of the live frame format (0 if none). Takes no parameters.

functioncamera.height() → number

Height in pixels of the live frame format (0 if none). Takes no parameters.

functioncamera.format() → string | nil

Pixel format name of the live frame, e.g. "SDL_PIXELFORMAT_NV12". Matches frame:format(). nil if none. Takes no parameters.

functioncamera.fps() → number

Frame rate of the live format in frames per second (0 if unknown). Takes no parameters.

functioncamera.colorspace() → number

The frame colorspace as SDL's numeric SDL_Colorspace enum value (0 if none). Niche — most mods won't need it. Takes no parameters.

functioncamera.pictureRect() → x, y, w, h

Where the video actually is, in window pixels. The picture is letterboxed: it keeps the card's own shape and is centred, so it does not fill the window unless the two happen to match. Anything you draw on the game — a marker glued to a menu entry, a panel that has to sit beside a health bar — has to map through this rectangle, or it slides into the black bars the moment the window is resized. Anything you draw on the app (a settings panel, a note) wants window coordinates as before and should ignore this. Returns four zeroes until the first frame has been drawn, which means "no picture yet" rather than "the picture is at 0,0". Takes no parameters.

-- a native GBA point, in screen pixels
local px, py, pw, ph = camera.pictureRect()
if pw > 0 then
    local x = px + (gx / 240) * pw
    local y = py + (gy / 160) * ph
end
functioncamera.formats() → table[]

Every format/resolution/framerate the device advertises, as an array of tables. A fresh copy each call — safe to modify. Takes no parameters.

Field of each entryTypeNotes
width, heightnumberResolution in pixels.
fpsnumberFrame rate for this combination.
formatstringPixel format name, e.g. "SDL_PIXELFORMAT_MJPG".
if camera.isOpen() then
    log(camera.name() .. ": " .. camera.width() .. "x" .. camera.height()
        .. " " .. camera.format() .. " @ " .. camera.fps() .. " fps")
    log("advertises " .. #camera.formats() .. " formats")
end
One page of the MCCP modding reference. Every section is its own document; search covers all of them.