Video Filters: Reorganize the VideoFilter class and simplify RenderDeposterize().

This commit is contained in:
rogerman 2017-02-07 15:19:32 -08:00
parent d9a0c0ef00
commit a09763f8c3
3 changed files with 313 additions and 228 deletions

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2016 DeSmuME team
Copyright (C) 2016-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -38,11 +38,11 @@ static u32 Deposterize_InterpLTE(const u32 pixA, const u32 pixB)
const u32 gB = (pixB & 0x0000FF00) >> 8;
const u32 bB = (pixB & 0x00FF0000) >> 16;
const u32 rC = ( (rB - rA <= DEPOSTERIZE_THRESHOLD) || (rA - rB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((rA+rB)>>1) ) : rA;
const u32 gC = ( (gB - gA <= DEPOSTERIZE_THRESHOLD) || (gA - gB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((gA+gB)>>1) ) : gA;
const u32 bC = ( (bB - bA <= DEPOSTERIZE_THRESHOLD) || (bA - bB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((bA+bB)>>1) ) : bA;
const u32 aC = ( (bB - aA <= DEPOSTERIZE_THRESHOLD) || (aA - aB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((aA+aB)>>1) ) : aA;
const u32 rC = ( (rB - rA <= DEPOSTERIZE_THRESHOLD) || (rA - rB <= DEPOSTERIZE_THRESHOLD) ) ? ((rA+rB)>>1) : rA;
const u32 gC = ( (gB - gA <= DEPOSTERIZE_THRESHOLD) || (gA - gB <= DEPOSTERIZE_THRESHOLD) ) ? ((gA+gB)>>1) : gA;
const u32 bC = ( (bB - bA <= DEPOSTERIZE_THRESHOLD) || (bA - bB <= DEPOSTERIZE_THRESHOLD) ) ? ((bA+bB)>>1) : bA;
const u32 aC = ( (aB - aA <= DEPOSTERIZE_THRESHOLD) || (aA - aB <= DEPOSTERIZE_THRESHOLD) ) ? ((aA+aB)>>1) : aA;
return (rC | (gC << 8) | (bC << 16) | (aC << 24));
}
@ -54,8 +54,6 @@ static u32 Deposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA,
return pixA;
}
const u32 weightSum = weightA + weightB;
const u32 rbA = pixA & 0x00FF00FF;
const u32 gA = pixA & 0x0000FF00;
const u32 aA = (pixA & 0xFF000000) >> 24;
@ -63,13 +61,45 @@ static u32 Deposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA,
const u32 rbB = pixB & 0x00FF00FF;
const u32 gB = pixB & 0x0000FF00;
const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / weightSum ) & 0x00FF00FF;
const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / weightSum ) & 0x0000FF00;
const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / weightSum ) << 24;
// Note: The sum of weightA and weightB must equal 16.
const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / 16 ) & 0x00FF00FF;
const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / 16 ) & 0x0000FF00;
const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / 16 ) << 24;
return (rbC | gC | aC);
}
static u32 Deposterize_BlendPixel(const u32 color[9])
{
const u32 blend[9] = {
color[0],
Deposterize_InterpLTE(color[0], color[1]),
Deposterize_InterpLTE(color[0], color[2]),
Deposterize_InterpLTE(color[0], color[3]),
Deposterize_InterpLTE(color[0], color[4]),
Deposterize_InterpLTE(color[0], color[5]),
Deposterize_InterpLTE(color[0], color[6]),
Deposterize_InterpLTE(color[0], color[7]),
Deposterize_InterpLTE(color[0], color[8])
};
return Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 2, 14),
Deposterize_Blend(blend[0], blend[1], 2, 14),
8, 8),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 2, 14),
Deposterize_Blend(blend[0], blend[3], 2, 14),
8, 8),
8, 8),
Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9),
Deposterize_Blend(blend[0], blend[2], 7, 9),
8, 8),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9),
Deposterize_Blend(blend[0], blend[4], 7, 9),
8, 8),
8, 8),
12, 4);
}
void RenderDeposterize(SSurface Src, SSurface Dst)
{
//---------------------------------------\n\
@ -79,19 +109,40 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
//
// Output Pixel Mapping: 00
const int w = Src.Width;
const int h = Src.Height;
const size_t w = Src.Width;
const size_t h = Src.Height;
u32 color[9];
u32 blend[9];
u32 *src = (u32 *)Src.Surface;
u32 *workingDst = (u32 *)Dst.workingSurface[0];
u32 *finalDst = (u32 *)Dst.Surface;
int i = 0;
for (int y = 0; y < h; y++)
size_t i = 0;
for (size_t x = 0; x < w; x++, i++)
{
for (int x = 0; x < w; x++, i++)
if ((src[i] & 0xFF000000) == 0)
{
workingDst[i] = src[i];
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = (x < w-1) ? src[i+w+1] : src[i];
color[3] = src[i];
color[4] = (x > 0) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = src[i];
color[7] = src[i];
color[8] = src[i];
workingDst[i] = Deposterize_BlendPixel(color);
}
for (size_t y = 1; y < h-1; y++)
{
for (size_t x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
@ -99,48 +150,67 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = ((x < w-1) && (y < h-1)) ? src[i+w+1] : src[i];
color[3] = (y < h-1) ? src[i+w] : src[i];
color[4] = ((x > 0) && (y < h-1)) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = ((x > 0) && (y > 0)) ? src[i-w-1] : src[i];
color[7] = (y > 0) ? src[i-w] : src[i];
color[8] = ((x < w-1) && (y > 0)) ? src[i-w+1] : src[i];
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = (x < w-1) ? src[i+w+1] : src[i];
color[3] = src[i+w];
color[4] = (x > 0) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = (x > 0) ? src[i-w-1] : src[i];
color[7] = src[i-w];
color[8] = (x < w-1) ? src[i-w+1] : src[i];
blend[0] = color[0];
blend[1] = Deposterize_InterpLTE(color[0], color[1]);
blend[2] = Deposterize_InterpLTE(color[0], color[2]);
blend[3] = Deposterize_InterpLTE(color[0], color[3]);
blend[4] = Deposterize_InterpLTE(color[0], color[4]);
blend[5] = Deposterize_InterpLTE(color[0], color[5]);
blend[6] = Deposterize_InterpLTE(color[0], color[6]);
blend[7] = Deposterize_InterpLTE(color[0], color[7]);
blend[8] = Deposterize_InterpLTE(color[0], color[8]);
workingDst[i] = Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 1, 7),
Deposterize_Blend(blend[0], blend[1], 1, 7),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 1, 7),
Deposterize_Blend(blend[0], blend[3], 1, 7),
1, 1),
1, 1),
Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9),
Deposterize_Blend(blend[0], blend[2], 7, 9),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9),
Deposterize_Blend(blend[0], blend[4], 7, 9),
1, 1),
1, 1),
3, 1);
workingDst[i] = Deposterize_BlendPixel(color);
}
}
i = 0;
for (int y = 0; y < h; y++)
for (size_t x = 0; x < w; x++, i++)
{
for (int x = 0; x < w; x++, i++)
if ((src[i] & 0xFF000000) == 0)
{
workingDst[i] = src[i];
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = src[i];
color[3] = src[i];
color[4] = src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = (x > 0) ? src[i-w-1] : src[i];
color[7] = src[i];
color[8] = (x < w-1) ? src[i-w+1] : src[i];
workingDst[i] = Deposterize_BlendPixel(color);
}
i = 0;
for (size_t x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
finalDst[i] = src[i];
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i];
color[3] = workingDst[i];
color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = workingDst[i];
color[7] = workingDst[i];
color[8] = workingDst[i];
finalDst[i] = Deposterize_BlendPixel(color);
}
for (size_t y = 1; y < h-1; y++)
{
for (size_t x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
@ -148,41 +218,38 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = ((x < w-1) && (y < h-1)) ? workingDst[i+w+1] : workingDst[i];
color[3] = (y < h-1) ? workingDst[i+w] : workingDst[i];
color[4] = ((x > 0) && (y < h-1)) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = ((x > 0) && (y > 0)) ? workingDst[i-w-1] : workingDst[i];
color[7] = (y > 0) ? workingDst[i-w] : workingDst[i];
color[8] = ((x < w-1) && (y > 0)) ? workingDst[i-w+1] : workingDst[i];
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i];
color[3] = workingDst[i+w];
color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i];
color[7] = workingDst[i-w];
color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i];
blend[0] = color[0];
blend[1] = Deposterize_InterpLTE(color[0], color[1]);
blend[2] = Deposterize_InterpLTE(color[0], color[2]);
blend[3] = Deposterize_InterpLTE(color[0], color[3]);
blend[4] = Deposterize_InterpLTE(color[0], color[4]);
blend[5] = Deposterize_InterpLTE(color[0], color[5]);
blend[6] = Deposterize_InterpLTE(color[0], color[6]);
blend[7] = Deposterize_InterpLTE(color[0], color[7]);
blend[8] = Deposterize_InterpLTE(color[0], color[8]);
finalDst[i] = Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 1, 7),
Deposterize_Blend(blend[0], blend[1], 1, 7),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 1, 7),
Deposterize_Blend(blend[0], blend[3], 1, 7),
1, 1),
1, 1),
Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9),
Deposterize_Blend(blend[0], blend[2], 7, 9),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9),
Deposterize_Blend(blend[0], blend[4], 7, 9),
1, 1),
1, 1),
3, 1);
finalDst[i] = Deposterize_BlendPixel(color);
}
}
for (size_t x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
finalDst[i] = src[i];
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = workingDst[i];
color[3] = workingDst[i];
color[4] = workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i];
color[7] = workingDst[i];
color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i];
finalDst[i] = Deposterize_BlendPixel(color);
}
}

View File

@ -76,10 +76,71 @@ static const _VideoFilterParamAttributes _VideoFilterParamAttributesList[] = {
/********************************************************************************************
CLASS CONSTRUCTORS
********************************************************************************************/
VideoFilter::VideoFilter()
{
__InstanceInit(32, 32, VideoFilterTypeID_None, 0);
}
VideoFilter::VideoFilter(size_t srcWidth,
size_t srcHeight,
VideoFilterTypeID typeID = VideoFilterTypeID_None,
size_t threadCount = 0)
{
__InstanceInit(srcWidth, srcHeight, VideoFilterTypeID_None, threadCount);
}
/********************************************************************************************
CLASS DESTRUCTOR
********************************************************************************************/
VideoFilter::~VideoFilter()
{
// Destroy all threads first
for (size_t i = 0; i < __vfThread.size(); i++)
{
__vfThread[i].task->finish();
__vfThread[i].task->shutdown();
delete __vfThread[i].task;
}
__vfThread.clear();
// Destroy everything else
ThreadLockLock(&_lockSrc);
ThreadLockLock(&_lockDst);
while (__isCPUFilterRunning)
{
ThreadCondWait(&__condCPUFilterRunning, &_lockDst);
}
if (_useInternalDstBuffer)
{
free(__vfDstSurface.Surface);
__vfDstSurface.Surface = NULL;
}
for (size_t i = 0; i < _vfAttributes.workingSurfaceCount; i++)
{
free(__vfDstSurface.workingSurface[i]);
__vfDstSurface.workingSurface[i] = NULL;
}
ThreadLockUnlock(&_lockDst);
free(__vfSrcSurfacePixBuffer);
__vfSrcSurfacePixBuffer = NULL;
__vfSrcSurface.Surface = NULL;
ThreadLockUnlock(&_lockSrc);
ThreadLockDestroy(&_lockSrc);
ThreadLockDestroy(&_lockDst);
ThreadLockDestroy(&_lockAttributes);
ThreadCondDestroy(&__condCPUFilterRunning);
}
void VideoFilter::__InstanceInit(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount)
{
SSurface newSurface;
newSurface.Surface = NULL;
@ -93,12 +154,12 @@ VideoFilter::VideoFilter(size_t srcWidth,
newSurface.workingSurface[i] = NULL;
}
_vfSrcSurface = newSurface;
_vfDstSurface = newSurface;
__vfSrcSurface = newSurface;
__vfDstSurface = newSurface;
_useInternalDstBuffer = true;
_isFilterRunning = false;
_vfSrcSurfacePixBuffer = NULL;
__isCPUFilterRunning = false;
__vfSrcSurfacePixBuffer = NULL;
if (typeID < VideoFilterTypeIDCount)
{
@ -109,80 +170,31 @@ VideoFilter::VideoFilter(size_t srcWidth,
_vfAttributes = VideoFilterAttributesList[VideoFilterTypeID_None];
}
_pixelScale = (float)_vfAttributes.scaleMultiply / (float)_vfAttributes.scaleDivide;
ThreadLockInit(&_lockSrc);
ThreadLockInit(&_lockDst);
ThreadLockInit(&_lockAttributes);
ThreadCondInit(&_condRunning);
ThreadCondInit(&__condCPUFilterRunning);
// Create all threads
_vfThread.resize(threadCount);
__vfThread.resize(threadCount);
for (size_t i = 0; i < threadCount; i++)
{
_vfThread[i].param.srcSurface = _vfSrcSurface;
_vfThread[i].param.dstSurface = _vfDstSurface;
_vfThread[i].param.filterFunction = NULL;
__vfThread[i].param.srcSurface = __vfSrcSurface;
__vfThread[i].param.dstSurface = __vfDstSurface;
__vfThread[i].param.filterFunction = NULL;
_vfThread[i].task = new Task;
_vfThread[i].task->start(false);
__vfThread[i].task = new Task;
__vfThread[i].task->start(false);
}
_vfFunc = _vfAttributes.filterFunction;
__vfFunc = _vfAttributes.filterFunction;
SetSourceSize(srcWidth, srcHeight);
}
/********************************************************************************************
CLASS DESTRUCTOR
********************************************************************************************/
VideoFilter::~VideoFilter()
{
// Destroy all threads first
for (size_t i = 0; i < _vfThread.size(); i++)
{
_vfThread[i].task->finish();
_vfThread[i].task->shutdown();
delete _vfThread[i].task;
}
_vfThread.clear();
// Destroy everything else
ThreadLockLock(&_lockSrc);
ThreadLockLock(&_lockDst);
while (_isFilterRunning)
{
ThreadCondWait(&_condRunning, &_lockDst);
}
if (_useInternalDstBuffer)
{
free(_vfDstSurface.Surface);
_vfDstSurface.Surface = NULL;
}
for (size_t i = 0; i < _vfAttributes.workingSurfaceCount; i++)
{
free(_vfDstSurface.workingSurface[i]);
_vfDstSurface.workingSurface[i] = NULL;
}
ThreadLockUnlock(&_lockDst);
free(_vfSrcSurfacePixBuffer);
_vfSrcSurfacePixBuffer = NULL;
_vfSrcSurface.Surface = NULL;
ThreadLockUnlock(&_lockSrc);
ThreadLockDestroy(&_lockSrc);
ThreadLockDestroy(&_lockDst);
ThreadLockDestroy(&_lockAttributes);
ThreadCondDestroy(&_condRunning);
}
bool VideoFilter::AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount)
bool VideoFilter::__AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount)
{
bool result = false;
unsigned char *newSurfaceBuffer = NULL;
@ -201,32 +213,32 @@ bool VideoFilter::AllocateDstBuffer(const size_t dstWidth, const size_t dstHeigh
for (size_t i = 0; i < FILTER_MAX_WORKING_SURFACE_COUNT; i++)
{
unsigned char *oldWorkingSurface = this->_vfDstSurface.workingSurface[i];
this->_vfDstSurface.workingSurface[i] = (i < workingSurfaceCount) ? (unsigned char *)calloc(dstWidth * dstHeight, sizeof(uint32_t)) : NULL;
unsigned char *oldWorkingSurface = this->__vfDstSurface.workingSurface[i];
this->__vfDstSurface.workingSurface[i] = (i < workingSurfaceCount) ? (unsigned char *)calloc(dstWidth * dstHeight, sizeof(uint32_t)) : NULL;
free(oldWorkingSurface);
}
// Set up SSurface structure.
this->_vfDstSurface.Width = dstWidth;
this->_vfDstSurface.Height = dstHeight;
this->_vfDstSurface.Pitch = dstWidth * 2;
this->__vfDstSurface.Width = dstWidth;
this->__vfDstSurface.Height = dstHeight;
this->__vfDstSurface.Pitch = dstWidth * 2;
if (_useInternalDstBuffer)
{
unsigned char *oldBuffer = this->_vfDstSurface.Surface;
this->_vfDstSurface.Surface = newSurfaceBuffer;
unsigned char *oldBuffer = this->__vfDstSurface.Surface;
this->__vfDstSurface.Surface = newSurfaceBuffer;
free(oldBuffer);
}
// Update the surfaces on threads.
const size_t threadCount = this->_vfThread.size();
const size_t threadCount = this->__vfThread.size();
const unsigned int linesPerThread = (threadCount > 1) ? dstHeight/threadCount : dstHeight;
unsigned int remainingLines = dstHeight;
for (size_t i = 0; i < threadCount; i++)
{
SSurface &threadDstSurface = this->_vfThread[i].param.dstSurface;
threadDstSurface = this->_vfDstSurface;
SSurface &threadDstSurface = this->__vfThread[i].param.dstSurface;
threadDstSurface = this->__vfDstSurface;
threadDstSurface.Height = (linesPerThread < remainingLines) ? linesPerThread : remainingLines;
remainingLines -= threadDstSurface.Height;
@ -238,7 +250,7 @@ bool VideoFilter::AllocateDstBuffer(const size_t dstWidth, const size_t dstHeigh
if (i > 0)
{
SSurface &prevThreadDstSurface = this->_vfThread[i - 1].param.dstSurface;
SSurface &prevThreadDstSurface = this->__vfThread[i - 1].param.dstSurface;
threadDstSurface.Surface = (unsigned char *)((uint32_t *)prevThreadDstSurface.Surface + (prevThreadDstSurface.Width * prevThreadDstSurface.Height));
for (size_t j = 0; j < workingSurfaceCount; j++)
@ -284,30 +296,30 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height)
return result;
}
if (this->_vfSrcSurface.Surface == NULL || this->_vfSrcSurface.Width != width || this->_vfSrcSurface.Height != height)
if (this->__vfSrcSurface.Surface == NULL || this->__vfSrcSurface.Width != width || this->__vfSrcSurface.Height != height)
{
sizeChanged = true;
}
this->_vfSrcSurface.Width = width;
this->_vfSrcSurface.Height = height;
this->_vfSrcSurface.Pitch = width * 2;
this->__vfSrcSurface.Width = width;
this->__vfSrcSurface.Height = height;
this->__vfSrcSurface.Pitch = width * 2;
// Set the working source buffer pointer so that the working memory block is padded
// with 4 pixel rows worth of memory on both sides.
this->_vfSrcSurface.Surface = (unsigned char *)(newPixBuffer + (width * 4));
this->__vfSrcSurface.Surface = (unsigned char *)(newPixBuffer + (width * 4));
free(this->_vfSrcSurfacePixBuffer);
this->_vfSrcSurfacePixBuffer = newPixBuffer;
free(this->__vfSrcSurfacePixBuffer);
this->__vfSrcSurfacePixBuffer = newPixBuffer;
// Update the surfaces on threads.
size_t threadCount = this->_vfThread.size();
const unsigned int linesPerThread = (threadCount > 1) ? this->_vfSrcSurface.Height/threadCount : this->_vfSrcSurface.Height;
unsigned int remainingLines = this->_vfSrcSurface.Height;
size_t threadCount = this->__vfThread.size();
const unsigned int linesPerThread = (threadCount > 1) ? this->__vfSrcSurface.Height/threadCount : this->__vfSrcSurface.Height;
unsigned int remainingLines = this->__vfSrcSurface.Height;
for (size_t i = 0; i < threadCount; i++)
{
SSurface &threadSrcSurface = this->_vfThread[i].param.srcSurface;
threadSrcSurface = this->_vfSrcSurface;
SSurface &threadSrcSurface = this->__vfThread[i].param.srcSurface;
threadSrcSurface = this->__vfSrcSurface;
threadSrcSurface.Height = (linesPerThread < remainingLines) ? linesPerThread : remainingLines;
remainingLines -= threadSrcSurface.Height;
@ -319,7 +331,7 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height)
if (i > 0)
{
SSurface &prevThreadSrcSurface = this->_vfThread[i - 1].param.srcSurface;
SSurface &prevThreadSrcSurface = this->__vfThread[i - 1].param.srcSurface;
threadSrcSurface.Surface = (unsigned char *)((uint32_t *)prevThreadSrcSurface.Surface + (prevThreadSrcSurface.Width * prevThreadSrcSurface.Height));
}
}
@ -332,7 +344,9 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height)
const size_t dstWidth = width * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const size_t dstHeight = height * vfAttr.scaleMultiply / vfAttr.scaleDivide;
result = this->AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount);
this->_pixelScale = (float)vfAttr.scaleMultiply / (float)vfAttr.scaleDivide;
result = this->__AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount);
if (!result)
{
return result;
@ -392,11 +406,11 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr)
}
ThreadLockLock(&this->_lockDst);
unsigned char *dstSurface = this->_vfDstSurface.Surface;
unsigned char *dstSurface = this->__vfDstSurface.Surface;
ThreadLockUnlock(&this->_lockDst);
const VideoFilterAttributes currentAttr = this->GetAttributes();
const size_t threadCount = this->_vfThread.size();
const size_t threadCount = this->__vfThread.size();
if (dstSurface != NULL &&
currentAttr.scaleMultiply == vfAttr.scaleMultiply &&
@ -408,18 +422,18 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr)
ThreadLockLock(&this->_lockDst);
const size_t bufferSizeBytes = this->_vfDstSurface.Width * this->_vfDstSurface.Height * sizeof(uint32_t);
const size_t bufferSizeBytes = this->__vfDstSurface.Width * this->__vfDstSurface.Height * sizeof(uint32_t);
memset(this->_vfDstSurface.Surface, 0, bufferSizeBytes);
memset(this->__vfDstSurface.Surface, 0, bufferSizeBytes);
for (size_t i = 0; i < currentAttr.workingSurfaceCount; i++)
{
memset(this->_vfDstSurface.workingSurface[i], 0, bufferSizeBytes);
memset(this->__vfDstSurface.workingSurface[i], 0, bufferSizeBytes);
}
this->_vfFunc = vfAttr.filterFunction;
this->__vfFunc = vfAttr.filterFunction;
for (size_t i = 0; i < threadCount; i++)
{
this->_vfThread[i].param.filterFunction = this->_vfFunc;
this->__vfThread[i].param.filterFunction = this->__vfFunc;
}
ThreadLockUnlock(&this->_lockDst);
@ -428,28 +442,30 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr)
{
// Construct a new destination buffer per filter attributes.
ThreadLockLock(&this->_lockSrc);
const size_t dstWidth = this->_vfSrcSurface.Width * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const size_t dstHeight = this->_vfSrcSurface.Height * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const size_t dstWidth = this->__vfSrcSurface.Width * vfAttr.scaleMultiply / vfAttr.scaleDivide;
const size_t dstHeight = this->__vfSrcSurface.Height * vfAttr.scaleMultiply / vfAttr.scaleDivide;
ThreadLockUnlock(&this->_lockSrc);
ThreadLockLock(&this->_lockDst);
this->_vfFunc = vfAttr.filterFunction;
this->__vfFunc = vfAttr.filterFunction;
for (size_t i = 0; i < threadCount; i++)
{
this->_vfThread[i].param.filterFunction = this->_vfFunc;
this->__vfThread[i].param.filterFunction = this->__vfFunc;
}
ThreadLockUnlock(&this->_lockDst);
result = this->AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount);
result = this->__AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount);
if (!result)
{
return result;
}
}
this->SetAttributes(vfAttr);
ThreadLockLock(&this->_lockAttributes);
this->_vfAttributes = vfAttr;
ThreadLockUnlock(&this->_lockAttributes);
result = true;
return result;
@ -472,40 +488,40 @@ uint32_t* VideoFilter::RunFilter()
ThreadLockLock(&this->_lockSrc);
ThreadLockLock(&this->_lockDst);
this->_isFilterRunning = true;
this->__isCPUFilterRunning = true;
if (this->_vfFunc == NULL)
if (this->__vfFunc == NULL)
{
memcpy(this->_vfDstSurface.Surface, this->_vfSrcSurface.Surface, this->_vfDstSurface.Width * this->_vfDstSurface.Height * sizeof(uint32_t));
memcpy(this->__vfDstSurface.Surface, this->__vfSrcSurface.Surface, this->__vfDstSurface.Width * this->__vfDstSurface.Height * sizeof(uint32_t));
}
else
{
const size_t threadCount = this->_vfThread.size();
const size_t threadCount = this->__vfThread.size();
if (threadCount > 0)
{
for (size_t i = 0; i < threadCount; i++)
{
this->_vfThread[i].task->execute(&RunVideoFilterTask, &this->_vfThread[i].param);
this->__vfThread[i].task->execute(&RunVideoFilterTask, &this->__vfThread[i].param);
}
for (size_t i = 0; i < threadCount; i++)
{
this->_vfThread[i].task->finish();
this->__vfThread[i].task->finish();
}
}
else
{
this->_vfFunc(this->_vfSrcSurface, this->_vfDstSurface);
this->__vfFunc(this->__vfSrcSurface, this->__vfDstSurface);
}
}
this->_isFilterRunning = false;
ThreadCondSignal(&this->_condRunning);
this->__isCPUFilterRunning = false;
ThreadCondSignal(&this->__condCPUFilterRunning);
ThreadLockUnlock(&this->_lockDst);
ThreadLockUnlock(&this->_lockSrc);
return (uint32_t *)this->_vfDstSurface.Surface;
return (uint32_t *)this->__vfDstSurface.Surface;
}
/********************************************************************************************
@ -686,13 +702,6 @@ VideoFilterAttributes VideoFilter::GetAttributes()
return vfAttr;
}
void VideoFilter::SetAttributes(const VideoFilterAttributes &vfAttr)
{
ThreadLockLock(&this->_lockAttributes);
this->_vfAttributes = vfAttr;
ThreadLockUnlock(&this->_lockAttributes);
}
VideoFilterTypeID VideoFilter::GetTypeID()
{
ThreadLockLock(&this->_lockAttributes);
@ -714,7 +723,7 @@ const char* VideoFilter::GetTypeString()
uint32_t* VideoFilter::GetSrcBufferPtr()
{
ThreadLockLock(&this->_lockSrc);
uint32_t *ptr = (uint32_t *)this->_vfSrcSurface.Surface;
uint32_t *ptr = (uint32_t *)this->__vfSrcSurface.Surface;
ThreadLockUnlock(&this->_lockSrc);
return ptr;
@ -723,7 +732,7 @@ uint32_t* VideoFilter::GetSrcBufferPtr()
uint32_t* VideoFilter::GetDstBufferPtr()
{
ThreadLockLock(&this->_lockDst);
uint32_t *ptr = (uint32_t *)this->_vfDstSurface.Surface;
uint32_t *ptr = (uint32_t *)this->__vfDstSurface.Surface;
ThreadLockUnlock(&this->_lockDst);
return ptr;
@ -759,8 +768,8 @@ void VideoFilter::SetDstBufferPtr(uint32_t *theBuffer)
}
else
{
unsigned char *oldDstBuffer = this->_vfDstSurface.Surface;
this->_vfDstSurface.Surface = (unsigned char *)theBuffer;
unsigned char *oldDstBuffer = this->__vfDstSurface.Surface;
this->__vfDstSurface.Surface = (unsigned char *)theBuffer;
if (this->_useInternalDstBuffer)
{
@ -772,13 +781,13 @@ void VideoFilter::SetDstBufferPtr(uint32_t *theBuffer)
ThreadLockUnlock(&this->_lockDst);
this->AllocateDstBuffer(this->_vfDstSurface.Width, this->_vfDstSurface.Height, this->_vfAttributes.workingSurfaceCount);
this->__AllocateDstBuffer(this->__vfDstSurface.Width, this->__vfDstSurface.Height, this->_vfAttributes.workingSurfaceCount);
}
size_t VideoFilter::GetSrcWidth()
{
ThreadLockLock(&this->_lockSrc);
size_t width = this->_vfSrcSurface.Width;
size_t width = this->__vfSrcSurface.Width;
ThreadLockUnlock(&this->_lockSrc);
return width;
@ -787,7 +796,7 @@ size_t VideoFilter::GetSrcWidth()
size_t VideoFilter::GetSrcHeight()
{
ThreadLockLock(&this->_lockSrc);
size_t height = this->_vfSrcSurface.Height;
size_t height = this->__vfSrcSurface.Height;
ThreadLockUnlock(&this->_lockSrc);
return height;
@ -796,7 +805,7 @@ size_t VideoFilter::GetSrcHeight()
size_t VideoFilter::GetDstWidth()
{
ThreadLockLock(&this->_lockDst);
size_t width = this->_vfDstSurface.Width;
size_t width = this->__vfDstSurface.Width;
ThreadLockUnlock(&this->_lockDst);
return width;
@ -805,12 +814,17 @@ size_t VideoFilter::GetDstWidth()
size_t VideoFilter::GetDstHeight()
{
ThreadLockLock(&this->_lockDst);
size_t height = this->_vfDstSurface.Height;
size_t height = this->__vfDstSurface.Height;
ThreadLockUnlock(&this->_lockDst);
return height;
}
float VideoFilter::GetPixelScale()
{
return this->_pixelScale;
}
VideoFilterParamType VideoFilter::GetFilterParameterType(VideoFilterParamID paramID) const
{
return _VideoFilterParamAttributesList[paramID].type;

View File

@ -151,25 +151,28 @@ typedef struct
class VideoFilter
{
private:
VideoFilterAttributes _vfAttributes;
SSurface _vfSrcSurface;
SSurface _vfDstSurface;
uint32_t *_vfSrcSurfacePixBuffer;
VideoFilterFunc _vfFunc;
std::vector<VideoFilterThread> _vfThread;
SSurface __vfSrcSurface;
SSurface __vfDstSurface;
uint32_t *__vfSrcSurfacePixBuffer;
VideoFilterFunc __vfFunc;
std::vector<VideoFilterThread> __vfThread;
bool _useInternalDstBuffer;
bool _isFilterRunning;
bool __isCPUFilterRunning;
ThreadCond __condCPUFilterRunning;
void __InstanceInit(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount);
bool __AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount);
protected:
VideoFilterAttributes _vfAttributes;
ThreadLock _lockSrc;
ThreadLock _lockDst;
ThreadLock _lockAttributes;
ThreadCond _condRunning;
bool AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount);
void SetAttributes(const VideoFilterAttributes &vfAttr);
float _pixelScale;
public:
VideoFilter();
VideoFilter(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount);
~VideoFilter();
@ -193,6 +196,7 @@ public:
size_t GetSrcHeight();
size_t GetDstWidth();
size_t GetDstHeight();
float GetPixelScale();
VideoFilterParamType GetFilterParameterType(VideoFilterParamID paramID) const;
int GetFilterParameteri(VideoFilterParamID paramID);
unsigned int GetFilterParameterui(VideoFilterParamID paramID);