diff --git a/OverLua/avisynth.cpp b/OverLua/avisynth.cpp index 84c850196..2838b5325 100644 --- a/OverLua/avisynth.cpp +++ b/OverLua/avisynth.cpp @@ -24,6 +24,9 @@ */ +// Must be included before , otherwise some macros from get in the way +#include "video_frame.h" + #include #include #include @@ -95,11 +98,11 @@ public: try { switch (vi.pixel_type) { case VideoInfo::CS_BGR24: { - OverLuaVideoFrameBGR *frame = new OverLuaVideoFrameBGR(vi.width, vi.height, stride, plane); + ImageBGR *frame = new ImageBGR(vi.width, vi.height, stride, plane); script->RenderFrameRGB(*frame, frametime); } break; case VideoInfo::CS_BGR32: { - OverLuaVideoFrameBGRX *frame = new OverLuaVideoFrameBGRX(vi.width, vi.height, stride, plane); + ImageBGRX *frame = new ImageBGRX(vi.width, vi.height, stride, plane); script->RenderFrameRGB(*frame, frametime); } break; } diff --git a/OverLua/csri.cpp b/OverLua/csri.cpp index 85c7b52b9..6239989b8 100644 --- a/OverLua/csri.cpp +++ b/OverLua/csri.cpp @@ -23,6 +23,9 @@ IRC: jfs in #aegisub on irc.rizon.net */ + +// CSRI interface is unmaintained for now +#if 0 #include #include @@ -112,22 +115,22 @@ CSRIAPI void csri_render(csri_inst *inst, struct csri_frame *frame, double time) // check for correct pixfmt if (frame->pixfmt != inst->frame_format.pixfmt) return; - OverLuaFrameAggregate *olframe = 0; + BaseImageAggregate *olframe = 0; switch (frame->pixfmt) { -#define HANDLE_RGB_FORMAT(fmtname, Rpos, Gpos, Bpos, PixelWidth) \ +#define HANDLE_RGB_FORMAT(fmtname, PixFmt) \ case fmtname: \ - olframe = new OverLuaFrameAggregateImpl(inst->frame_format.width, inst->frame_format.height, frame->strides[0], frame->planes[0]); \ + olframe = new BaseImageAggregateImpl(inst->frame_format.width, inst->frame_format.height, frame->strides[0], frame->planes[0]); \ break; - HANDLE_RGB_FORMAT(CSRI_F_RGBA, 0, 1, 2, 4) - HANDLE_RGB_FORMAT(CSRI_F_ARGB, 1, 2, 3, 4) - HANDLE_RGB_FORMAT(CSRI_F_BGRA, 2, 1, 0, 4) - HANDLE_RGB_FORMAT(CSRI_F_ABGR, 3, 2, 1, 4) - HANDLE_RGB_FORMAT(CSRI_F_RGB_, 0, 1, 2, 4) - HANDLE_RGB_FORMAT(CSRI_F__RGB, 1, 2, 3, 4) - HANDLE_RGB_FORMAT(CSRI_F_BGR_, 2, 1, 0, 4) - HANDLE_RGB_FORMAT(CSRI_F__BGR, 3, 2, 1, 4) - HANDLE_RGB_FORMAT(CSRI_F_RGB, 0, 1, 2, 3) - HANDLE_RGB_FORMAT(CSRI_F_BGR, 2, 1, 0, 3) + HANDLE_RGB_FORMAT(CSRI_F_RGBA, RGBA) + HANDLE_RGB_FORMAT(CSRI_F_ARGB, ARGB) + HANDLE_RGB_FORMAT(CSRI_F_BGRA, BGRA) + HANDLE_RGB_FORMAT(CSRI_F_ABGR, ABGR) + HANDLE_RGB_FORMAT(CSRI_F_RGB_, RGBX) + HANDLE_RGB_FORMAT(CSRI_F__RGB, XRGB) + HANDLE_RGB_FORMAT(CSRI_F_BGR_, BGRX) + HANDLE_RGB_FORMAT(CSRI_F__BGR, XBGR) + HANDLE_RGB_FORMAT(CSRI_F_RGB, RGB) + HANDLE_RGB_FORMAT(CSRI_F_BGR, BGR) default: break; // what, we don't support this! #undef HANDLE_RGB_FORMAT } @@ -200,3 +203,5 @@ CSRIAPI csri_rend *csri_renderer_next(csri_rend *prev) else return 0; } + +#endif \ No newline at end of file diff --git a/OverLua/overlua.cpp b/OverLua/overlua.cpp index ecdeda6b2..83547cb01 100644 --- a/OverLua/overlua.cpp +++ b/OverLua/overlua.cpp @@ -105,7 +105,7 @@ OverLuaScript::~OverLuaScript() lua_close(L); } -void OverLuaScript::RenderFrameRGB(OverLuaFrameAggregate &frame, double time) +void OverLuaScript::RenderFrameRGB(BaseImageAggregate &frame, double time) { lua_getglobal(L, "render_frame"); frame.CreateLuaObject(L); diff --git a/OverLua/overlua.h b/OverLua/overlua.h index 00b488d19..f881efa3d 100644 --- a/OverLua/overlua.h +++ b/OverLua/overlua.h @@ -89,7 +89,7 @@ public: OverLuaScript(const void *data, size_t length, const char *_datastring = 0); virtual ~OverLuaScript(); - void RenderFrameRGB(OverLuaFrameAggregate &frame, double time); + void RenderFrameRGB(BaseImageAggregate &frame, double time); }; diff --git a/OverLua/video_frame.h b/OverLua/video_frame.h index 1f3aecf74..c89cb4e47 100644 --- a/OverLua/video_frame.h +++ b/OverLua/video_frame.h @@ -28,63 +28,159 @@ #define VIDEO_FRAME_H #include "../lua51/src/lua.h" +#include "../lua51/src/lauxlib.h" #include "cairo_wrap.h" #include #include #include #include -// Forward -class OverLuaFrameAggregate; -// store a colour value -struct RGBPixel { - unsigned char r, g, b; - RGBPixel(unsigned char R, unsigned char G, unsigned char B) : r(R), g(G), b(B) { } +// Forward +class BaseImageAggregate; + + +// Supported pixel formats +namespace PixelFormat { + // A constant value with a fake assignment operator + template + struct NopAssigningConstant { + operator T() { return v; } + void operator = (const T &n) { } + }; + typedef NopAssigningConstant ROA; // "read only alpha" + + // 24 bit formats + struct RGB { + uint8_t r, g, b; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline ROA A() const { return ROA(); } + RGB() : r(0), g(0), b(0) { } + template RGB(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); } + }; + struct BGR { + uint8_t b, g, r; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline ROA A() const { return ROA(); } + BGR() : r(0), g(0), b(0) { } + template BGR(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); } + }; + + // 32 bit alpha-less formats + struct RGBX { + uint8_t r, g, b, x; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline ROA A() const { return ROA(); } + RGBX() : r(0), g(0), b(0) { } + template RGBX(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); } + }; + struct BGRX { + uint8_t b, g, r, x; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline ROA A() const { return ROA(); } + BGRX() : r(0), g(0), b(0) { } + template BGRX(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); } + }; + struct XRGB { + uint8_t x, r, g, b; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline ROA A() const { return ROA(); } + XRGB() : r(0), g(0), b(0) { } + template XRGB(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); } + }; + struct XBGR { + uint8_t x, b, g, r; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline ROA A() const { return ROA(); } + XBGR() : r(0), g(0), b(0) { } + template XBGR(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); } + }; + + // 32 bit with alpha + struct RGBA { + uint8_t r, g, b, a; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline uint8_t &A() { return a; } inline uint8_t A() const { return a; } + RGBA() : r(0), g(0), b(0), a(0) { } + template RGBA(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); } + }; + struct BGRA { + uint8_t b, g, r, a; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline uint8_t &A() { return a; } inline uint8_t A() const { return a; } + BGRA() : r(0), g(0), b(0), a(0) { } + template BGRA(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); } + }; + struct ARGB { + uint8_t a, r, g, b; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline uint8_t &A() { return a; } inline uint8_t A() const { return a; } + ARGB() : r(0), g(0), b(0), a(0) { } + template ARGB(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); } + }; + struct ABGR { + uint8_t a, b, g, r; + inline uint8_t &R() { return r; } inline uint8_t R() const { return r; } + inline uint8_t &G() { return g; } inline uint8_t G() const { return g; } + inline uint8_t &B() { return b; } inline uint8_t B() const { return b; } + inline uint8_t &A() { return a; } inline uint8_t A() const { return a; } + ABGR() : r(0), g(0), b(0), a(0) { } + template ABGR(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); } + }; }; + // Support any interleaved RGB format with 8 bit per channel // You usually don't want to instance this class directly, // look at OverLuaFrameAggregate defined below -template -class OverLuaVideoFrame { +template +class BaseImage { public: - typedef OverLuaVideoFrame MyType; + typedef BaseImage MyType; // video properties - unsigned width; - unsigned height; + int width; + int height; ptrdiff_t stride; unsigned char *data; - // read a pixel value - inline const RGBPixel GetPixel(unsigned x, unsigned y) + // Access a pixel value + inline const PixFmt &Pixel(int x, int y) const { - RGBPixel res(0, 0, 0); - unsigned char *ptr = data + y*stride + x*PixelWidth; - res.r = ptr[Rpos]; - res.g = ptr[Gpos]; - res.b = ptr[Bpos]; - return res; + return *((PixFmt*)(data + y*stride) + x) } - // write a pixel value - inline void SetPixel(unsigned x, unsigned y, const RGBPixel &val) + inline PixFmt &Pixel(int x, int y) { - unsigned char *ptr = data + y*stride + x*PixelWidth; - ptr[Rpos] = val.r; - ptr[Gpos] = val.g; - ptr[Bpos] = val.b; + return *((PixFmt*)(data + y*stride) + x); } - OverLuaVideoFrame(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data) + BaseImage(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data) : width(_width), height(_height), stride(_stride), data(_data) { owndata = false; // nothing further to init } - OverLuaVideoFrame(const MyType &src, bool copydata = false) + BaseImage(const MyType &src, bool copydata = false) { width = src.width; height = src.height; @@ -98,14 +194,14 @@ public: } } - ~OverLuaVideoFrame() + ~BaseImage() { if (owndata) delete[] data; } // should never be called more than once on the same C++ object - void CreateLuaObject(lua_State *L, OverLuaFrameAggregate *aggregate = 0) + void CreateLuaObject(lua_State *L, BaseImageAggregate *aggregate = 0) { // create userdata object MyType **ud = (MyType**)lua_newuserdata(L, sizeof(MyType*)); @@ -123,7 +219,7 @@ public: lua_setfield(L, -2, "__gc"); if (aggregate) { lua_pushlightuserdata(L, aggregate); - lua_setfield(L, -2, "videoframe"); + lua_setfield(L, -2, "image"); } lua_setmetatable(L, -2); } @@ -142,32 +238,32 @@ private: if (lua_isnumber(L, 2)) { if (lua_istable(L, 3)) { int n = (int)lua_tointeger(L, 2); - unsigned x = n % (*ud)->width; - unsigned y = n / (*ud)->width; + int x = n % (*ud)->width; + int y = n / (*ud)->width; if (x < 0 || y < 0 || x >= (*ud)->width || y >= (*ud)->height) return 0; // read first three entries from table - RGBPixel color(0,0,0); + PixFmt color; lua_pushnil(L); if (!lua_next(L, 3)) goto badtable; if (!lua_isnumber(L, -1)) goto badtable; - color.r = (unsigned char)lua_tointeger(L, -1); + color.R() = (unsigned char)lua_tointeger(L, -1); lua_pop(L, 1); if (!lua_next(L, 3)) goto badtable; if (!lua_isnumber(L, -1)) goto badtable; - color.g = (unsigned char)lua_tointeger(L, -1); + color.G() = (unsigned char)lua_tointeger(L, -1); lua_pop(L, 1); if (!lua_next(L, 3)) goto badtable; if (!lua_isnumber(L, -1)) goto badtable; - color.b = (unsigned char)lua_tointeger(L, -1); + color.B() = (unsigned char)lua_tointeger(L, -1); lua_pop(L, 2); - (*ud)->SetPixel(x, y, color); + (*ud)->Pixel(x, y) = color; return 0; } else { badtable: - lua_pushliteral(L, "Value set into video frame pixel must be a table with at least 3 entries"); + lua_pushliteral(L, "Value set into image pixel must be a table with at least 3 entries"); lua_error(L); return 0; } @@ -201,7 +297,7 @@ badtable: lua_pushvalue(L, 1); lua_pushcclosure(L, lua_overlay_cairo_surface, 1); } else { - lua_pushfstring(L, "Undefined field name in video frame: %s", fieldname); + lua_pushfstring(L, "Undefined field name in image: %s", fieldname); lua_error(L); } @@ -209,7 +305,7 @@ badtable: } - lua_pushfstring(L, "Unhandled field type indexing video frame: %s", lua_typename(L, lua_type(L, 2))); + lua_pushfstring(L, "Unhandled field type indexing image: %s", lua_typename(L, lua_type(L, 2))); lua_error(L); return 0; } @@ -221,19 +317,19 @@ badtable: // third arg = y MyType **ud = (MyType**)lua_touserdata(L, 1); - unsigned x = luaL_checkint(L, 2); - unsigned y = luaL_checkint(L, 3); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); - RGBPixel color(0,0,0); if (x < 0 || y < 0 || x >= (*ud)->width || y >= (*ud)->height) { - // already black, leave it + lua_pushinteger(L, 0); + lua_pushinteger(L, 0); + lua_pushinteger(L, 0); } else { - // get it - color = (*ud)->GetPixel(x, y); + const PixFmt &p = (*ud)->Pixel(x, y); + lua_pushinteger(L, p.r); + lua_pushinteger(L, p.g); + lua_pushinteger(L, p.b); } - lua_pushinteger(L, color.r); - lua_pushinteger(L, color.g); - lua_pushinteger(L, color.b); return 3; } @@ -274,12 +370,11 @@ badtable: int width = (*ud)->width; #pragma omp parallel for for (int y = 0; y < height; y++) { - uint32_t *opix = (uint32_t*)(surfdata + y*surfstride); + PixFmt *ipix = (PixFmt*)((*ud)->data + y*((*ud)->stride)); + PixelFormat::XBGR *opix = (PixelFormat::XBGR*)(surfdata + y*surfstride); for (int x = 0; x < width; x++) { // Hoping this will get optimised at least a bit by the compiler - RGBPixel ipix = (*ud)->GetPixel(x, y); - *opix = ipix.r << 16 | ipix.g << 8 | ipix.b; - opix++; + *opix++ = PixelFormat::XBGR(*ipix++); } } cairo_surface_mark_dirty(surf); @@ -338,17 +433,16 @@ badtable: int lines_to_compose = (slines_to_composeGetPixel(fx, fy+composition_line); - unsigned char a = 0xff - ((sline[sx] & 0xff000000) >> 24); - pix.r = ((sline[sx] & 0x00ff0000) >> 16) + a*pix.r/255; - pix.g = ((sline[sx] & 0x0000ff00) >> 8) + a*pix.g/255; - pix.b = (sline[sx] & 0x000000ff) + a*pix.b/255; - (*ud)->SetPixel(fx, fy+composition_line, pix); + PixFmt &pix = (*ud)->Pixel(fx, fy+composition_line); + unsigned char a = 0xff - sline[sx].A(); + pix.R() = sline[sx].R() + a*pix.R()/255; + pix.G() = sline[sx].G() + a*pix.G()/255; + pix.B() = sline[sx].B() + a*pix.B()/255; } } } @@ -361,16 +455,12 @@ badtable: int lines_to_compose = (slines_to_compose> 16, - (sline[sx] & 0x0000ff00) >> 8, - sline[sx] & 0x000000ff); - (*ud)->SetPixel(fx, fy+composition_line, pix); + sline[sx] = PixelFormat::XRGB((*ud)->Pixel(fx, fy+composition_line)); } } } @@ -409,45 +499,45 @@ badtable: // in the C++ code. It nicely hides all templatyness away into various implementations. // This could probably have been designed better. Shame on me. -class OverLuaFrameAggregate { +class BaseImageAggregate { public: - virtual RGBPixel GetPixel(unsigned x, unsigned y) = 0; - virtual void SetPixel(unsigned x, unsigned y, const RGBPixel &val) = 0; + virtual PixelFormat::ARGB GetPixel(int x, int y) = 0; + virtual void SetPixel(int x, int y, const PixelFormat::ARGB &val) = 0; virtual unsigned GetWidth() = 0; virtual unsigned GetHeight() = 0; virtual void CreateLuaObject(lua_State *L) = 0; }; -template -class OverLuaFrameAggregateImpl : public OverLuaFrameAggregate { +template +class BaseImageAggregateImpl : public BaseImageAggregate { public: - typedef OverLuaVideoFrame VideoFrameType; + typedef BaseImage ImageType; private: - VideoFrameType *frame; + ImageType *frame; bool ownframe; public: - OverLuaFrameAggregateImpl(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data) + BaseImageAggregateImpl(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data) { - frame = new VideoFrameType(_width, _height, _stride, _data); + frame = new ImageType(_width, _height, _stride, _data); ownframe = true; } - OverLuaFrameAggregateImpl(VideoFrameType *_frame) + BaseImageAggregateImpl(ImageType *_frame) { frame = _frame; ownframe = false; } - RGBPixel GetPixel(unsigned x, unsigned y) + PixelFormat::ARGB GetPixel(int x, int y) { - return frame->GetPixel(x, y); + return PixelFormat::ARGB(frame->Pixel(x, y)); } - void SetPixel(unsigned x, unsigned y, const RGBPixel &val) + void SetPixel(int x, int y, const PixelFormat::ARGB &val) { - frame->SetPixel(x, y, val); + frame->Pixel(x, y) = PixFmt(val); } unsigned GetWidth() @@ -468,15 +558,15 @@ public: }; // All common, sensible formats -typedef OverLuaFrameAggregateImpl<2, 1, 0, 3> OverLuaVideoFrameBGR; -typedef OverLuaFrameAggregateImpl<2, 1, 0, 4> OverLuaVideoFrameBGRX; -typedef OverLuaFrameAggregateImpl<2, 1, 0, 4> OverLuaVideoFrameBGRA; -typedef OverLuaFrameAggregateImpl<0, 1, 2, 3> OverLuaVideoFrameRGB; -typedef OverLuaFrameAggregateImpl<0, 1, 2, 4> OverLuaVideoFrameRGBX; -typedef OverLuaFrameAggregateImpl<0, 1, 2, 4> OverLuaVideoFrameRGBA; -typedef OverLuaFrameAggregateImpl<1, 2, 3, 4> OverLuaVideoFrameXRGB; -typedef OverLuaFrameAggregateImpl<1, 2, 3, 4> OverLuaVideoFrameARGB; -typedef OverLuaFrameAggregateImpl<3, 2, 1, 4> OverLuaVideoFrameXBGR; -typedef OverLuaFrameAggregateImpl<3, 2, 1, 4> OverLuaVideoFrameABGR; +typedef BaseImageAggregateImpl ImageRGB; +typedef BaseImageAggregateImpl ImageBGR; +typedef BaseImageAggregateImpl ImageRGBX; +typedef BaseImageAggregateImpl ImageBGRX; +typedef BaseImageAggregateImpl ImageXRGB; +typedef BaseImageAggregateImpl ImageXBGR; +typedef BaseImageAggregateImpl ImageRGBA; +typedef BaseImageAggregateImpl ImageBGRA; +typedef BaseImageAggregateImpl ImageARGB; +typedef BaseImageAggregateImpl ImageABGR; #endif