Reworking of video frame interface, into more general RGB(A) image interface

Originally committed to SVN as r1485.
This commit is contained in:
Niels Martin Hansen 2007-08-14 00:20:59 +00:00
parent 43149f9276
commit 2699972427
5 changed files with 205 additions and 107 deletions

View file

@ -24,6 +24,9 @@
*/
// Must be included before <windows.h>, otherwise some macros from <windows.h> get in the way
#include "video_frame.h"
#include <windows.h>
#include <string.h>
#include <memory.h>
@ -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;
}

View file

@ -23,6 +23,9 @@
IRC: jfs in #aegisub on irc.rizon.net
*/
// CSRI interface is unmaintained for now
#if 0
#include <string.h>
#include <memory.h>
@ -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<Rpos,Gpos,Bpos,PixelWidth>(inst->frame_format.width, inst->frame_format.height, frame->strides[0], frame->planes[0]); \
olframe = new BaseImageAggregateImpl<PixelFormat:: ## PixFmt>(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

View file

@ -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);

View file

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

View file

@ -28,63 +28,159 @@
#define VIDEO_FRAME_H
#include "../lua51/src/lua.h"
#include "../lua51/src/lauxlib.h"
#include "cairo_wrap.h"
#include <stddef.h>
#include <memory.h>
#include <stdint.h>
#include <omp.h>
// 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 <class T, T v>
struct NopAssigningConstant {
operator T() { return v; }
void operator = (const T &n) { }
};
typedef NopAssigningConstant<uint8_t,255> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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 <class PixFmt> 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<ptrdiff_t Rpos, ptrdiff_t Gpos, ptrdiff_t Bpos, ptrdiff_t PixelWidth>
class OverLuaVideoFrame {
template<class PixFmt>
class BaseImage {
public:
typedef OverLuaVideoFrame<Rpos,Gpos,Bpos,PixelWidth> MyType;
typedef BaseImage<PixFmt> 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_compose<flines_to_compose)?slines_to_compose:flines_to_compose;
#pragma omp parallel for
for (int composition_line = 0; composition_line < lines_to_compose; composition_line++) {
uint32_t *sline = (uint32_t*)(sdata + composition_line*sstride);
PixelFormat::ARGB *sline = (PixelFormat::ARGB*)(sdata + composition_line*sstride);
int fx = xpos;
int sx = 0;
if (fx < 0) fx = 0, sx = -xpos;
for ( ; sx < swidth && fx < fwidth; fx++, sx++) {
RGBPixel pix = (*ud)->GetPixel(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<flines_to_compose)?slines_to_compose:flines_to_compose;
#pragma omp parallel for
for (int composition_line = 0; composition_line < lines_to_compose; composition_line++) {
uint32_t *sline = (uint32_t*)(sdata + composition_line*sstride);
PixelFormat::XRGB *sline = (PixelFormat::XRGB*)(sdata + composition_line*sstride);
int fx = xpos;
int sx = 0;
if (fx < 0) fx = 0, sx = -xpos;
for ( ; sx < swidth && fx < fwidth; fx++, sx++) {
RGBPixel pix(
(sline[sx] & 0x00ff0000) >> 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 <ptrdiff_t Rpos, ptrdiff_t Gpos, ptrdiff_t Bpos, ptrdiff_t PixelWidth>
class OverLuaFrameAggregateImpl : public OverLuaFrameAggregate {
template <class PixFmt>
class BaseImageAggregateImpl : public BaseImageAggregate {
public:
typedef OverLuaVideoFrame<Rpos, Gpos, Bpos, PixelWidth> VideoFrameType;
typedef BaseImage<PixFmt> 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<PixelFormat::RGB> ImageRGB;
typedef BaseImageAggregateImpl<PixelFormat::BGR> ImageBGR;
typedef BaseImageAggregateImpl<PixelFormat::RGBX> ImageRGBX;
typedef BaseImageAggregateImpl<PixelFormat::BGRX> ImageBGRX;
typedef BaseImageAggregateImpl<PixelFormat::XRGB> ImageXRGB;
typedef BaseImageAggregateImpl<PixelFormat::XBGR> ImageXBGR;
typedef BaseImageAggregateImpl<PixelFormat::RGBA> ImageRGBA;
typedef BaseImageAggregateImpl<PixelFormat::BGRA> ImageBGRA;
typedef BaseImageAggregateImpl<PixelFormat::ARGB> ImageARGB;
typedef BaseImageAggregateImpl<PixelFormat::ABGR> ImageABGR;
#endif