📄 chenvideo.cpp
字号:
// ChenVideo.cpp
#include <ChenVideo.h>
#ifdef _USEIPP
#include <ippi.h>
#endif
int ChenVideo_loadYUVVideo(const char* pVideoFileName, Resolution resolution, const int nStartFrame, const int nEndFrame, short**& pFramesY, short**& pFramesU, short**& pFramesV)
{
#ifdef _USEIPP
bool bSuccess = true;
// Determine dimensions
int nWidth, nHeight;
if (resolution == QCIF) {
nWidth = QCIF_WIDTH;
nHeight = QCIF_HEIGHT;
}
else if (resolution == CIF) {
nWidth = CIF_WIDTH;
nHeight = CIF_HEIGHT;
}
else if (resolution == FOURCIF) {
nWidth = FOURCIF_WIDTH;
nHeight = FOURCIF_HEIGHT;
}
else if (resolution == SIXTEENCIF) {
nWidth = SIXTEENCIF_WIDTH;
nHeight = SIXTEENCIF_HEIGHT;
}
int nPixelsPerChannel = nWidth * nHeight;
// Allocate space
int nFrames = nEndFrame - nStartFrame + 1;
if (nFrames <= 0) {
fprintf(stderr, "Invalid frame bounds: %d %d\n", nStartFrame, nEndFrame);
return BAD_RETURN;
}
pFramesY = new short*[nFrames];
pFramesU = new short*[nFrames];
pFramesV = new short*[nFrames];
for (int nFrame = 0; nFrame < nFrames; nFrame++) {
pFramesY[nFrame] = new short[nPixelsPerChannel];
pFramesU[nFrame] = new short[nPixelsPerChannel];
pFramesV[nFrame] = new short[nPixelsPerChannel];
}
uchar* pBufferY = new uchar[nPixelsPerChannel];
uchar* pBufferU = new uchar[nPixelsPerChannel/4];
uchar* pBufferV = new uchar[nPixelsPerChannel/4];
// Skip frames before start of subsequence
FILE* pFile = fopen(pVideoFileName, "rb");
if (pFile == NULL) {
fprintf(stderr, "Video file cannot be opened: %s\n", pVideoFileName);
return BAD_RETURN;
}
for (int nFrame = 1; nFrame < nStartFrame; nFrame++) {
// Read Y frame
size_t nRead = fread(pBufferY, 1, nPixelsPerChannel, pFile);
// Read U frame
nRead = fread(pBufferU, 1, nPixelsPerChannel/4, pFile);
// Read V frame
nRead = fread(pBufferV, 1, nPixelsPerChannel/4, pFile);
} // end nFrame
// Process frames of subsequence
for (int nFrame = nStartFrame; nFrame <= nEndFrame; nFrame++) {
// Read Y frame
size_t nRead = fread(pBufferY, 1, nPixelsPerChannel, pFile);
int nSrcStep = nWidth * sizeof(uchar);
int nDstStep = nWidth * sizeof(short);
IppiSize roiSize = {nWidth, nHeight};
RECORD_SUCCESS( ippiConvert_8u16s_C1R((const Ipp8u*)pBufferY, nSrcStep, (Ipp16s*)pFramesY[nFrame-nStartFrame], nDstStep, roiSize), bSuccess );
// Read U frame
nRead = fread(pBufferU, 1, nPixelsPerChannel/4, pFile);
nSrcStep = nWidth/2 * sizeof(uchar);
nDstStep = nWidth/2 * sizeof(short);
roiSize.width = nWidth/2;
roiSize.height = nHeight/2;
RECORD_SUCCESS( ippiConvert_8u16s_C1R((const Ipp8u*)pBufferU, nSrcStep, (Ipp16s*)pFramesU[nFrame-nStartFrame], nDstStep, roiSize), bSuccess );
// Read V frame
nRead = fread(pBufferV, 1, nPixelsPerChannel/4, pFile);
RECORD_SUCCESS( ippiConvert_8u16s_C1R((const Ipp8u*)pBufferV, nSrcStep, (Ipp16s*)pFramesV[nFrame-nStartFrame], nDstStep, roiSize), bSuccess );
}
fclose(pFile);
delete [] pBufferY;
delete [] pBufferU;
delete [] pBufferV;
return bSuccess ? GOOD_RETURN : BAD_RETURN;
#else
bool bSuccess = true;
// Determine dimensions
int nWidth, nHeight;
if (resolution == QCIF) {
nWidth = QCIF_WIDTH;
nHeight = QCIF_HEIGHT;
}
else if (resolution == CIF) {
nWidth = CIF_WIDTH;
nHeight = CIF_HEIGHT;
}
else if (resolution == FOURCIF) {
nWidth = FOURCIF_WIDTH;
nHeight = FOURCIF_HEIGHT;
}
else if (resolution == SIXTEENCIF) {
nWidth = SIXTEENCIF_WIDTH;
nHeight = SIXTEENCIF_HEIGHT;
}
int nPixelsPerChannel = nWidth * nHeight;
// Allocate space
int nFrames = nEndFrame - nStartFrame + 1;
if (nFrames <= 0) {
fprintf(stderr, "Invalid frame bounds: %d %d\n", nStartFrame, nEndFrame);
return BAD_RETURN;
}
pFramesY = new short*[nFrames];
pFramesU = new short*[nFrames];
pFramesV = new short*[nFrames];
for (int nFrame = 0; nFrame < nFrames; nFrame++) {
pFramesY[nFrame] = new short[nPixelsPerChannel];
pFramesU[nFrame] = new short[nPixelsPerChannel];
pFramesV[nFrame] = new short[nPixelsPerChannel];
}
uchar* pBufferY = new uchar[nPixelsPerChannel];
uchar* pBufferU = new uchar[nPixelsPerChannel/4];
uchar* pBufferV = new uchar[nPixelsPerChannel/4];
// Skip frames before start of subsequence
FILE* pFile = fopen(pVideoFileName, "rb");
if (pFile == NULL) {
fprintf(stderr, "Video file cannot be opened: %s\n", pVideoFileName);
return BAD_RETURN;
}
for (int nFrame = 1; nFrame < nStartFrame; nFrame++) {
// Read Y frame
size_t nRead = fread(pBufferY, 1, nPixelsPerChannel, pFile);
// Read U frame
nRead = fread(pBufferU, 1, nPixelsPerChannel/4, pFile);
// Read V frame
nRead = fread(pBufferV, 1, nPixelsPerChannel/4, pFile);
} // end nFrame
// Process frames of subsequence
for (int nFrame = nStartFrame; nFrame <= nEndFrame; nFrame++) {
// Read Y frame
size_t nRead = fread(pBufferY, 1, nPixelsPerChannel, pFile);
for (int ii = 0; ii < nPixelsPerChannel; ii++)
{
pFramesY[nFrame-nStartFrame][ii] = pBufferY[ii];
}
// Read U frame
nRead = fread(pBufferU, 1, nPixelsPerChannel/4, pFile);
for (int ii = 0; ii < nPixelsPerChannel/4; ii++)
{
pFramesU[nFrame-nStartFrame][ii] = pBufferU[ii];
}
// Read V frame
nRead = fread(pBufferV, 1, nPixelsPerChannel/4, pFile);
for (int ii = 0; ii < nPixelsPerChannel/4; ii++)
{
pFramesV[nFrame-nStartFrame][ii] = pBufferV[ii];
}
}
fclose(pFile);
delete [] pBufferY;
delete [] pBufferU;
delete [] pBufferV;
return bSuccess ? GOOD_RETURN : BAD_RETURN;
#endif
}
int ChenVideo_motionCompensateInterpolate(const int nWidth, const int nHeight, const int nBlockSize, const int nMaxShift, const short* pSrc1, const short* pSrc2, const short* pShiftsX, const short* pShiftsY, short* pDst)
{
bool bSuccess = true;
// Set local variables
int nPixels = nWidth * nHeight;
int nBlockRows = nHeight / nBlockSize;
int nBlockCols = nWidth / nBlockSize;
int nBlocks = nBlockRows * nBlockCols;
int nBlockPixels = nBlockSize * nBlockSize;
short* pShiftedImg = new short[nPixels];
short* pResidual = new short[nPixels];
// Shift both source images to all possible shift positions
int nShifts1D = 2*nMaxShift+1;
int nShifts2D = nShifts1D * nShifts1D;
short* pShifted = new short[nPixels];
short* pShiftedStore1 = new short[nPixels * nShifts2D];
short* pShiftedStore2 = new short[nPixels * nShifts2D];
for (int nShiftY = -nMaxShift; nShiftY <= nMaxShift; nShiftY++) {
for (int nShiftX = -nMaxShift; nShiftX <= nMaxShift; nShiftX++) {
int nShift = (nShiftY+nMaxShift)*nShifts1D + (nShiftX+nMaxShift);
// Shift source 1
RECORD_SUCCESS( ChenImage_shiftImage(nWidth, nHeight, pSrc1, nShiftX, nShiftY, pShifted), bSuccess );
int nStoreStart = nShift*nPixels;
memcpy(pShiftedStore1+nStoreStart, pShifted, nPixels*sizeof(short));
// Shift source 2
RECORD_SUCCESS( ChenImage_shiftImage(nWidth, nHeight, pSrc2, nShiftX, nShiftY, pShifted), bSuccess );
memcpy(pShiftedStore2+nStoreStart, pShifted, nPixels*sizeof(short));
} // end nShiftX
} // end nShiftY
// Perform blockwise motion-compensated interpolation
short* pBlock1 = new short[nBlockPixels];
short* pBlock2 = new short[nBlockPixels];
for (int nBlockRow = 0; nBlockRow < nBlockRows; nBlockRow++) {
for (int nBlockCol = 0; nBlockCol < nBlockCols; nBlockCol++) {
int nBlock = nBlockRow*nBlockCols + nBlockCol;
// Form half motion vector
short nShiftX = pShiftsX[nBlock] / 2;
short nShiftY = pShiftsY[nBlock] / 2;
int nShift = (nShiftY+nMaxShift)*nShifts1D + (nShiftX+nMaxShift);
int nShiftStart = nShift*nPixels;
// Extract block from shifted source 1
for (int nRow = 0; nRow < nBlockSize; nRow++) {
for (int nCol = 0; nCol < nBlockSize; nCol++) {
pBlock1[nRow*nBlockSize + nCol] = pShiftedStore1[nShiftStart + (nBlockRow*nBlockSize + nRow)*nWidth + (nBlockCol*nBlockSize + nCol)];
}
}
// Extract block from shifted source 2
for (int nRow = 0; nRow < nBlockSize; nRow++) {
for (int nCol = 0; nCol < nBlockSize; nCol++) {
pBlock2[nRow*nBlockSize + nCol] = pShiftedStore2[nShiftStart + (nBlockRow*nBlockSize + nRow)*nWidth + (nBlockCol*nBlockSize + nCol)];
}
}
// Average blocks and place in output
for (int nRow = 0; nRow < nBlockSize; nRow++) {
for (int nCol = 0; nCol < nBlockSize; nCol++) {
pBlock1[nRow*nBlockSize + nCol] += pBlock2[nRow*nBlockSize + nCol];
pBlock1[nRow*nBlockSize + nCol] /= 2;
pDst[(nBlockRow*nBlockSize + nRow)*nWidth + (nBlockCol*nBlockSize + nCol)] = pBlock1[nRow*nBlockSize + nCol];
}
}
}
} // end nBlockRow
delete [] pShiftedImg;
delete [] pResidual;
delete [] pShiftsX;
delete [] pShiftsY;
delete [] pShifted;
delete [] pShiftedStore1;
delete [] pShiftedStore2;
return bSuccess ? GOOD_RETURN : BAD_RETURN;
}
int ChenVideo_motionCompensateInterpolateYUV(const int nWidth, const int nHeight, const int nBlockSize, const int nMaxShift, const short** pSrc1, const short** pSrc2, short** pDst)
{
bool bSuccess = true;
// Set local variables
int nPixels = nWidth * nHeight;
int nBlockRows = nHeight / nBlockSize;
int nBlockCols = nWidth / nBlockSize;
int nBlocks = nBlockRows * nBlockCols;
int nBlockPixels = nBlockSize * nBlockSize;
// Perform block matching between Y components
short* pShiftsX = new short[nBlocks];
short* pShiftsY = new short[nBlocks];
short* pShiftedImg = new short[nPixels];
short* pResidual = new short[nPixels];
RECORD_SUCCESS( ChenImage_imageBlockMatch2D(nWidth, nHeight, nBlockSize, nMaxShift, pSrc1[0], pSrc2[0], pShiftedImg, pResidual, pShiftsX, pShiftsY), bSuccess );
// Motion-compensated interpolation for Y component
RECORD_SUCCESS( ChenVideo_motionCompensateInterpolate(nWidth, nHeight, nBlockSize, nMaxShift, pSrc1[0], pSrc2[0], pShiftsX, pShiftsY, pDst[0]), bSuccess );
// Motion-compensated interpolation for U,V components
for (int nChannel = 1; nChannel <= 2; nChannel++) {
RECORD_SUCCESS( ChenImage_imageBlockMatch2D(nWidth/2, nHeight/2, nBlockSize, nMaxShift, pSrc1[nChannel], pSrc2[nChannel], pShiftedImg, pResidual, pShiftsX, pShiftsY), bSuccess );
RECORD_SUCCESS( ChenVideo_motionCompensateInterpolate(nWidth/2, nHeight/2, nBlockSize, nMaxShift, pSrc1[nChannel], pSrc2[nChannel], pShiftsX, pShiftsY, pDst[nChannel]), bSuccess );
}
delete [] pShiftsX;
delete [] pShiftsY;
delete [] pShiftedImg;
delete [] pResidual;
return bSuccess ? GOOD_RETURN : BAD_RETURN;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -