Video Filters: Reorganize the VideoFilter class and simplify RenderDeposterize().
This commit is contained in:
parent
d9a0c0ef00
commit
a09763f8c3
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue