Video Filters:

- Have the xBRZ filter handle the alpha channel.
- Minor code cleanup of video filter managing code.
This commit is contained in:
rogerman 2014-02-13 23:30:01 +00:00
parent 9a642be896
commit 9d44ca55f6
3 changed files with 37 additions and 34 deletions

View File

@ -189,7 +189,7 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height)
ThreadLockUnlock(&this->_lockSrc);
const VideoFilterAttributes vfAttr = this->GetAttributes();
result = this->ChangeFilterByAttributes(&vfAttr);
result = this->ChangeFilterByAttributes(vfAttr);
return result;
}
@ -216,7 +216,7 @@ bool VideoFilter::ChangeFilterByID(const VideoFilterTypeID typeID)
return result;
}
result = this->ChangeFilterByAttributes(&VideoFilterAttributesList[typeID]);
result = this->ChangeFilterByAttributes(VideoFilterAttributesList[typeID]);
return result;
}
@ -233,28 +233,23 @@ bool VideoFilter::ChangeFilterByID(const VideoFilterTypeID typeID)
A bool that reports if the filter change was successful. A value of true means
success, while a value of false means failure.
********************************************************************************************/
bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr)
bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr)
{
bool result = false;
if (vfAttr == NULL)
if (vfAttr.scaleMultiply == 0 || vfAttr.scaleDivide < 1)
{
return result;
}
if (vfAttr->scaleMultiply == 0 || vfAttr->scaleDivide < 1)
{
return result;
}
if (this->_vfDstSurface.Surface != NULL && this->_vfAttributes.scaleMultiply == vfAttr->scaleMultiply && this->_vfAttributes.scaleDivide == vfAttr->scaleDivide)
if (this->_vfDstSurface.Surface != NULL && this->_vfAttributes.scaleMultiply == vfAttr.scaleMultiply && this->_vfAttributes.scaleDivide == vfAttr.scaleDivide)
{
// If we have an existing buffer and the new size is identical to the old size,
// we can skip the costly construction of the buffer and simply clear it instead.
ThreadLockLock(&this->_lockDst);
memset(this->_vfDstSurface.Surface, 0, this->_vfDstSurface.Width * _vfDstSurface.Height * sizeof(uint32_t));
this->_vfFunc = vfAttr->filterFunction;
this->_vfFunc = vfAttr.filterFunction;
const size_t threadCount = this->_vfThread.size();
for (size_t i = 0; i < threadCount; i++)
@ -272,9 +267,9 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr)
const size_t srcHeight = this->_vfSrcSurface.Height;
ThreadLockUnlock(&this->_lockSrc);
const size_t dstWidth = srcWidth * vfAttr->scaleMultiply / vfAttr->scaleDivide;
const size_t dstHeight = srcHeight * vfAttr->scaleMultiply / vfAttr->scaleDivide;
const VideoFilterFunc filterFunction = vfAttr->filterFunction;
const size_t dstWidth = srcWidth * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const size_t dstHeight = srcHeight * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const VideoFilterFunc filterFunction = vfAttr.filterFunction;
ThreadLockLock(&this->_lockDst);
@ -312,7 +307,7 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr)
ThreadLockUnlock(&this->_lockDst);
}
this->SetAttributes(*vfAttr);
this->SetAttributes(vfAttr);
result = true;
return result;
@ -408,7 +403,7 @@ void VideoFilter::RunFilterCustomByID(const uint32_t *__restrict srcBuffer, uint
return;
}
VideoFilter::RunFilterCustomByAttributes(srcBuffer, dstBuffer, srcWidth, srcHeight, &VideoFilterAttributesList[typeID]);
VideoFilter::RunFilterCustomByAttributes(srcBuffer, dstBuffer, srcWidth, srcHeight, VideoFilterAttributesList[typeID]);
}
/********************************************************************************************
@ -440,24 +435,23 @@ void VideoFilter::RunFilterCustomByID(const uint32_t *__restrict srcBuffer, uint
********************************************************************************************/
void VideoFilter::RunFilterCustomByAttributes(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer,
const size_t srcWidth, const size_t srcHeight,
const VideoFilterAttributes *vfAttr)
const VideoFilterAttributes &vfAttr)
{
// Parameter check
if (srcBuffer == NULL ||
dstBuffer == NULL ||
srcWidth < 1 ||
srcHeight < 1 ||
vfAttr == NULL ||
vfAttr->scaleMultiply == 0 ||
vfAttr->scaleDivide < 1)
vfAttr.scaleMultiply == 0 ||
vfAttr.scaleDivide < 1)
{
return;
}
// Get the filter attributes
const size_t dstWidth = srcWidth * vfAttr->scaleMultiply / vfAttr->scaleDivide;
const size_t dstHeight = srcHeight * vfAttr->scaleMultiply / vfAttr->scaleDivide;
const VideoFilterFunc filterFunction = vfAttr->filterFunction;
const size_t dstWidth = srcWidth * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const size_t dstHeight = srcHeight * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const VideoFilterFunc filterFunction = vfAttr.filterFunction;
// Assign the surfaces and run the filter
SSurface srcSurface;
@ -517,7 +511,7 @@ VideoFilterAttributes VideoFilter::GetAttributes()
return vfAttr;
}
void VideoFilter::SetAttributes(const VideoFilterAttributes vfAttr)
void VideoFilter::SetAttributes(const VideoFilterAttributes &vfAttr)
{
ThreadLockLock(&this->_lockAttributes);
this->_vfAttributes = vfAttr;

View File

@ -180,7 +180,7 @@ private:
ThreadLock _lockAttributes;
ThreadCond _condRunning;
void SetAttributes(const VideoFilterAttributes vfAttr);
void SetAttributes(const VideoFilterAttributes &vfAttr);
public:
VideoFilter(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount);
@ -188,11 +188,11 @@ public:
bool SetSourceSize(const size_t width, const size_t height);
bool ChangeFilterByID(const VideoFilterTypeID typeID);
bool ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr);
bool ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr);
uint32_t* RunFilter();
static void RunFilterCustomByID(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, const VideoFilterTypeID typeID);
static void RunFilterCustomByAttributes(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, const VideoFilterAttributes *vfAttr);
static void RunFilterCustomByAttributes(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, const VideoFilterAttributes &vfAttr);
static const char* GetTypeStringByID(const VideoFilterTypeID typeID);
VideoFilterAttributes GetAttributes();

View File

@ -27,6 +27,7 @@ namespace
template <uint32_t N> inline
unsigned char getByte(uint32_t val) { return static_cast<unsigned char>((val >> (8 * N)) & 0xff); }
inline unsigned char getAlpha(uint32_t val) { return getByte<3>(val); }
inline unsigned char getRed (uint32_t val) { return getByte<2>(val); }
inline unsigned char getGreen(uint32_t val) { return getByte<1>(val); }
inline unsigned char getBlue (uint32_t val) { return getByte<0>(val); }
@ -38,9 +39,10 @@ T abs(T value)
return value < 0 ? -value : value;
}
const uint32_t redMask = 0xff0000;
const uint32_t greenMask = 0x00ff00;
const uint32_t blueMask = 0x0000ff;
static const uint32_t alphaMask = 0xFF000000;
static const uint32_t redMask = 0x00FF0000;
static const uint32_t greenMask = 0x0000FF00;
static const uint32_t blueMask = 0x000000FF;
template <unsigned int N, unsigned int M> inline
void alphaBlend(uint32_t& dst, uint32_t col) //blend color over destination with opacity N / M
@ -48,9 +50,15 @@ void alphaBlend(uint32_t& dst, uint32_t col) //blend color over destination with
//static_assert(N < 256, "possible overflow of (col & redMask) * N");
//static_assert(M < 256, "possible overflow of (col & redMask ) * N + (dst & redMask ) * (M - N)");
//static_assert(0 < N && N < M, "");
dst = (redMask & ((col & redMask ) * N + (dst & redMask ) * (M - N)) / M) | //this works because 8 upper bits are free
(greenMask & ((col & greenMask) * N + (dst & greenMask) * (M - N)) / M) |
(blueMask & ((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M);
//dst = (redMask & ((col & redMask ) * N + (dst & redMask ) * (M - N)) / M) | //this works because 8 upper bits are free
// (greenMask & ((col & greenMask) * N + (dst & greenMask) * (M - N)) / M) |
// (blueMask & ((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M);
// 2014-02-06 (rogerman): Modified to take the alpha channel into account.
dst = ((((col >> 24) * N + (dst >> 24) * (M - N) ) / M) << 24) |
(redMask & (((col & redMask ) * N + (dst & redMask ) * (M - N)) / M)) |
(greenMask & (((col & greenMask) * N + (dst & greenMask) * (M - N)) / M)) |
(blueMask & (((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M));
}
@ -397,7 +405,8 @@ double distYCbCr(uint32_t pix1, uint32_t pix2, double lumaWeight)
const double c_r = scale_r * (r_diff - y);
//we skip division by 255 to have similar range like other distance functions
return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r));
//return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r));
return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)+ square(static_cast<int>(getAlpha(pix1)) - getAlpha(pix2)));
}