📄 umc_h264_npf.cpp
字号:
m_options.v = opt.v;
m_options.tf_thres1 = LIMIT_THRESHOLD_RANGE_TF(opt.tf_thres1);
m_options.tf_thres2 = LIMIT_THRESHOLD_RANGE_TF(opt.tf_thres2);
m_options.tf_thres3 = LIMIT_THRESHOLD_RANGE_TF(opt.tf_thres3);
m_options.mf_simple = opt.mf_simple;
m_options.mf_thres_s = LIMIT_THRESHOLD_RANGE(opt.mf_thres_s);
m_options.mf_thres_t = LIMIT_THRESHOLD_RANGE(opt.mf_thres_t);
UpdateAndScaleThresholds();
} // PutNoiseReductionOptions
//----------------------------------------------------------------------------
// Set up calls to filter a single plane
template <class PixType>
#if defined(_MSC_VER)
inline
#endif
void CNoiseReductionFilter<PixType>::FilterPlane(
PixType* x,
PixType* xp,
Ipp32s pitchPixels,
Ipp32s width,
Ipp32s height)
{
if (m_uMode & H264_Noise_Reduction_INR_Mode)
{
SpatioTemporalFilter(x, xp, pitchPixels, width, height);
}
if (m_uMode & H264_Noise_Reduction_TNR_Mode)
TemporalFilter(x, xp, pitchPixels, width, height);
} // FilterPlane
//----------------------------------------------------------------------------
// Perform noise reduction filtering on the Y, U, and V planes
//
// Note : Due to limitations in the mmx noise reduction filter, the pitch of
// the buffer must be 8x. The width and height of the picture must be
// 4x and no smaller than 8.
template <class PixType>
bool CNoiseReductionFilter<PixType>::DoFiltering(
PixType* y,
PixType* u,
PixType* v,
Ipp32s y_pitch_pixels,
Ipp32s uv_pitch_pixels,
Ipp32s width,
Ipp32s height)
{
// Skip all if the filter has been disabled
if (!m_bEnabled)
return true;
// Make sure that the picture dimensions are supported
if ((y_pitch_pixels & 3) || (uv_pitch_pixels & 1) || (width & 3) || (height & 3) ||
(width < 8) || (height < 8))
{
return false;
}
// Proceed with noisy edge removal if enabled
if (m_uMode & H264_Noise_Reduction_NER_Mode)
RemoveNoisyEdges(y, u, v, y_pitch_pixels, uv_pitch_pixels, width, height);
// Done if none of the other noise reduction modes is enabled
if (!(m_uMode & H264_Noise_Reduction_INR_Mode) &&
!(m_uMode & H264_Noise_Reduction_TNR_Mode))
return true;
// Make sure that the local buffer size is correct
if (!CheckBuffer(y_pitch_pixels, uv_pitch_pixels, width, height))
return false;
// m_bFirstFrame must be false if m_bFirstFrame_MF is false
// Filter Y plane if m_options.y is set
if (m_options.y)
FilterPlane(y, m_pLastFrameY, y_pitch_pixels, width, height);
// Update Y plane in last frame buffer
Ipp32u i, j;
for (i = 0, j = (height >> 1) * y_pitch_pixels; i < j; i += y_pitch_pixels)
{
memcpy(m_pLastFrameY + i, y + i, sizeof(PixType)*width);
memcpy(m_pLastFrameY + i + j, y + i + j, sizeof(PixType)*width);
}
// Adjust dimensions for U and V planes
width >>= 1;
height >>= 1;
// Filter U plane if m_options.u is set
if (m_options.u)
FilterPlane(u, m_pLastFrameU, uv_pitch_pixels, width, height);
// Filter V plane if m_options.v is set
if (m_options.v)
FilterPlane(v, m_pLastFrameV, uv_pitch_pixels, width, height);
// Update U and V planes in last frame buffer
for (i = 0, j = (height >> 1) * uv_pitch_pixels; i < j; i += uv_pitch_pixels)
{
memcpy(m_pLastFrameU + i, u + i, sizeof(PixType)*width);
memcpy(m_pLastFrameU + i + j, u + i + j, sizeof(PixType)*width);
memcpy(m_pLastFrameV + i, v + i, sizeof(PixType)*width);
memcpy(m_pLastFrameV + i + j, v + i + j, sizeof(PixType)*width);
}
// Last frame buffer has been filled, clear flag
m_bFirstFrame = false;
// Done filtering
return true;
} // DoFiltering
//----------------------------------------------------------------------------
// Sort given array of 5 into ascending order
template <class PixType>
#if defined(_MSC_VER)
// Some compilation systems don't like "inline" here, given that "inline"
// is not specified at the declaration in "umc_h264_npf.h", and thus not seen
// when Sort5 is called within "npf_c.cpp".
// But, MSVC doesn't seem to mind.
inline
#endif
void CNoiseReductionFilter<PixType>::Sort5(PixType* v)
{
PixType u;
if (v[1] > v[0])
{
u = v[1];
v[1] = v[0];
v[0] = u;
}
if (v[2] > v[1])
{
u = v[2];
v[2] = v[1];
if (u > v[0])
{
v[1] = v[0];
v[0] = u;
}
else
v[1] = u;
}
if (v[3] > v[2])
{
u = v[3];
v[3] = v[2];
if (u > v[1])
{
v[2] = v[1];
if (u > v[0])
{
v[1] = v[0];
v[0] = u;
}
else
v[1] = u;
}
else
v[2] = u;
}
if (v[4] > v[3])
{
u = v[4];
v[4] = v[3];
if (u > v[2])
{
v[3] = v[2];
if (u > v[1])
{
v[2] = v[1];
if (u > v[0])
{
v[1] = v[0];
v[0] = u;
}
else
v[1] = u;
}
else
v[2] = u;
}
else
v[3] = u;
}
} // Sort5
//----------------------------------------------------------------------------
// Sort given array v of n elements into ascending order
template <class PixType>
#if defined(_MSC_VER)
// Some compilation systems don't like "inline" here, given that "inline"
// is not specified at the declaration in "umc_h264_npf.h", and thus not seen
// when Sort is called within "npf_c.cpp".
// But, MSVC doesn't seem to mind.
inline
#endif
void CNoiseReductionFilter<PixType>::Sort(PixType* v, const Ipp32u n)
{
Ipp32u i;
Ipp32s j;
PixType u;
for (i = 1; i < n; i ++)
{
u = v[i];
for (j = i; j > 0 && u > v[j - 1]; j --)
v[j] = v[j - 1];
v[j] = u;
}
} // Sort
//----------------------------------------------------------------------------
// Compute a weighted average on given inputs
// 0.625 * y + 0.375 * x if |x - y| < thres1
// z = 0.5 * y + 0.5 * x else if |x - y| < thres2
// 0.375 * y + 0.625 * x else if |x - y| < thres3
// x otherwise
template <class PixType>
#if defined(_MSC_VER)
// Some compilation systems don't like "inline" here, given that "inline"
// is not specified at the declaration in "umc_h264_npf.h", and thus not seen
// when WeightedAvg is called within "npf_c.cpp".
// But, MSVC doesn't seem to mind.
inline
#endif
Ipp32u CNoiseReductionFilter<PixType>::WeightedAvg(register Ipp32u x, register Ipp32u y)
{
return Ipp32u(x + m_pTFtaps[255 + y - x]); // 16 bits????
} // WeightedAvg
//----------------------------------------------------------------------------
// Perform spatio-temporal filtering on a given plane
// x : pointer to input buffer
// y : pointer to output buffer
// yp : pointer to previous output buffer
// width : width of color plane
// height : height of color plane
//
// Notes : pitch >= width
// width must be 2x and >= 4
// height must be 2x and >= 4
#define FILTERING(offs) \
if (Ipp32u(labs(y[offs] - yp[offs])) >= m_mf_thres_t) \
y[offs] = MedianFilter(y, pitchPixels, offs);
template <class PixType>
void CNoiseReductionFilter<PixType>::SpatioTemporalFilter(
PixType* y,
PixType* yp,
const Ipp32s pitchPixels,
const Ipp32u width,
const Ipp32u height)
{
// Spatial median filtering
// Filter second row thru second last row, two rows at a time
Ipp32u i, j, k;
Ipp32u dpitch = (pitchPixels - width) + pitchPixels;
for (k = pitchPixels, i = 1; i < height - 1; i += 2, k += dpitch)
{
// Col 1 thru 2: no median filtering on column 0
FILTERING(k+1)
FILTERING(k+1+pitchPixels)
k += 2;
// Col 3 thru Col width-2
for (j = k + width - 4; k < j; k += 2)
{
FILTERING(k)
FILTERING(k+1)
FILTERING(k+pitchPixels)
FILTERING(k+1+pitchPixels)
}
// Last two columns: no median filtering on last column
FILTERING(k)
FILTERING(k+pitchPixels)
k += 2;
}
// If this is the first frame, clear flag and skip temporal filtering
if (m_bFirstFrame_MF)
{
m_bFirstFrame_MF = false;
return;
}
// Temporal filtering
for (i = 0; i < height; i ++, y += pitchPixels, yp += pitchPixels)
{
for (j = 0; j < width; j += 4)
{
y[j + 0] = PixType(WeightedAvg(y[j + 0], yp[j + 0]));
y[j + 1] = PixType(WeightedAvg(y[j + 1], yp[j + 1]));
y[j + 2] = PixType(WeightedAvg(y[j + 2], yp[j + 2]));
y[j + 3] = PixType(WeightedAvg(y[j + 3], yp[j + 3]));
}
}
} // SpatioTemporalFilter
//----------------------------------------------------------------------------
// Find the median of a given point from it neighbors
// x : pointer to input buffer
// y : pointer to output buffer
// width : width of color plane
// height : height of color plane
// k : index to point of interest
template <class PixType>
PixType CNoiseReductionFilter<PixType>::MedianFilter(
PixType* y,
const Ipp32s pitchPixels,
const Ipp32s k)
{
Ipp32s m, n;
PixType s[9];
// Initialize the sort buffer with given input, x[k], and 0's
s[0] = y[k];
s[1] = s[2] = s[3] = s[4] = s[5] = s[6] = s[7] = s[8] = 0;
m = 1;
// Check to include neighbors x[k + 1], x[k + width]
// Neighbors x[k - 1] and x[k - width] are substituted by the output
// y[k - 1] and y[k - width]
// Also, outliers that differ from x[k] by more than the threshold
// m_mfo.thres_s are excluded
if ((Ipp32u) labs(y[k] - y[k - 1]) < m_mf_thres_s)
s[m ++] = y[k - 1];
if ((Ipp32u) labs(y[k] - y[k + 1]) < m_mf_thres_s)
s[m ++] = y[k + 1];
if ((Ipp32u) labs(y[k] - y[k - pitchPixels]) < m_mf_thres_s)
s[m ++] = y[k - pitchPixels];
if ((Ipp32u) labs(y[k] - y[k + pitchPixels]) < m_mf_thres_s)
s[m ++] = y[k + pitchPixels];
// Check to include diagonal neighbors x[k + width - 1], x[k + width + 1]
// Neighbors x[k - width - 1] and x[k - width + 1] are substituted by the
// output y[k - width - 1] and y[k - width + 1]
// Again excluded outliers
if (!m_options.mf_simple)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -