📄 cvideomixcontroller.cpp
字号:
//
// CVideoMixController.cpp
//
/*-----------------------------------------------------*\
HQ Tech, Make Technology Easy!
More information, please go to http://hqtech.nease.net.
/*-----------------------------------------------------*/
#include <streams.h>
#include <stdio.h>
#include "CVideoMixController.h"
///////////////////////////////////////////////////////////////////////////
CVideoMixController::CVideoMixController()
{
mMixingFrames = NULL;
mMixingFrameSize = 0;
mTotalPixels = 0;
mBitCount = 0;
mEOSMixing = FALSE;
mEOSMainVideo = FALSE;
mStopped = FALSE;
mMixingFlushing = FALSE;
mDetectType = CUSTOMIZE;
mDetectOnceFinished = FALSE;
mBackColorR = 0;
mBackColorG = 0;
mBackColorB = 0;
mBackDrift = DEFAULT_RGB565_DRIFT;
mIsMMXSupported = IsMMXSupported();
}
CVideoMixController::~CVideoMixController()
{
ReleaseMixingBuffer();
}
void CVideoMixController::ReleaseMixingBuffer(void)
{
if (mMixingFrames)
{
delete mMixingFrames;
mMixingFrames = NULL;
}
}
__inline BYTE CVideoMixController::MyAbs(__int16 inValue)
{
if (inValue < 0)
{
return -inValue;
}
return inValue;
}
// using __inline will not be allowed to debug in
__inline void CVideoMixController::ActualMixing16Bits(BYTE * outPrimary, BYTE * inMixing)
{
WORD * pPrimary = (WORD *) outPrimary;
WORD * pMixing = (WORD *) inMixing;
static BYTE backRed, backGreen, backBlue;
static BYTE mixingR, mixingG, mixingB;
// Pick up the background color
WORD temp = *pMixing;
if (mDetectType == DETECT_ALWAYS)
{
backRed = (temp & RGB565_MASK_RED) >> 11;
backGreen = (temp & RGB565_MASK_GREEN) >> 5;
backBlue = temp & RGB565_MASK_BLUE;
}
else if (mDetectType == DETECT_ONCE)
{
if (!mDetectOnceFinished)
{
mDetectOnceFinished = TRUE;
backRed = (temp & RGB565_MASK_RED) >> 11;
backGreen = (temp & RGB565_MASK_GREEN) >> 5;
backBlue = temp & RGB565_MASK_BLUE;
}
}
else
{
backRed = mBackColorR;
backGreen = mBackColorG;
backBlue = mBackColorB;
}
// Do Actual mixing
// If the image width is not a multiple of 4, sth goes wrong
for (long i = 0; i < mTotalPixels; i++)
{
temp = *pMixing;
mixingR = (temp & RGB565_MASK_RED) >> 11;
mixingG = (temp & RGB565_MASK_GREEN) >> 5;
mixingB = temp & RGB565_MASK_BLUE;
if (MyAbs(mixingR - backRed) < mBackDrift &&
MyAbs(mixingG - backGreen) < mBackDrift &&
MyAbs(mixingB - backBlue) < mBackDrift)
{
// The similar pixel with the background color
pPrimary++;
}
else
{
*pPrimary = *pMixing;
pPrimary++;
}
pMixing++;
}
}
__inline void CVideoMixController::ActualMixing32Bits(BYTE * outPrimary, BYTE * inMixing)
{
DWORD * pPrimary = (DWORD *) outPrimary;
DWORD * pMixing = (DWORD *) inMixing;
static BYTE backRed, backGreen, backBlue;
static BYTE mixingR, mixingG, mixingB;
// Pick up the background color
DWORD temp = *pMixing;
if (mDetectType == DETECT_ALWAYS)
{
backRed = BYTE((temp & RGB32_MASK_RED) >> 16);
backGreen = BYTE((temp & RGB32_MASK_GREEN) >> 8);
backBlue = BYTE(temp & RGB32_MASK_BLUE);
}
else if (mDetectType == DETECT_ONCE)
{
if (!mDetectOnceFinished)
{
mDetectOnceFinished = TRUE;
backRed = BYTE((temp & RGB32_MASK_RED) >> 16);
backGreen = BYTE((temp & RGB32_MASK_GREEN) >> 8);
backBlue = BYTE(temp & RGB32_MASK_BLUE);
}
}
else
{
backRed = mBackColorR;
backGreen = mBackColorG;
backBlue = mBackColorB;
}
// Do Actual mixing
// If the image width is not a multiple of 4, sth goes wrong
for (long i = 0; i < mTotalPixels; i++)
{
temp = *pMixing;
mixingR = BYTE((temp & RGB32_MASK_RED) >> 16);
mixingG = BYTE((temp & RGB32_MASK_GREEN) >> 8);
mixingB = BYTE(temp & RGB32_MASK_BLUE);
if (MyAbs(mixingR - backRed) < mBackDrift &&
MyAbs(mixingG - backGreen) < mBackDrift &&
MyAbs(mixingB - backBlue) < mBackDrift)
{
// The similar pixel with the background color
pPrimary++;
}
else
{
*pPrimary = *pMixing;
pPrimary++;
}
pMixing++;
}
}
__inline void CVideoMixController::IdealMixing16Bits(BYTE * outPrimary, BYTE * inMixing)
{
WORD * pPrimary = (WORD *) outPrimary;
WORD * pMixing = (WORD *) inMixing;
static WORD backColor;
// Pick up the background color
WORD temp = *pMixing;
if (mDetectType == DETECT_ALWAYS)
{
backColor = temp;
}
else if (mDetectType == DETECT_ONCE)
{
if (!mDetectOnceFinished)
{
mDetectOnceFinished = TRUE;
backColor = temp;
}
}
else
{
backColor = (mBackColorR << 11) + (mBackColorG << 5) + mBackColorB;
}
// Do Actual mixing
// If the image width is not a multiple of 4, sth goes wrong
for (long i = 0; i < mTotalPixels; i++)
{
if (*pMixing != backColor)
{
*pPrimary = *pMixing;
}
pPrimary++;
pMixing++;
}
}
__inline void CVideoMixController::IdealMixing32Bits(BYTE * outPrimary, BYTE * inMixing)
{
DWORD * pPrimary = (DWORD *) outPrimary;
DWORD * pMixing = (DWORD *) inMixing;
static DWORD backColor;
// Pick up the background color
DWORD temp = *pMixing;
if (mDetectType == DETECT_ALWAYS)
{
backColor = temp;
}
else if (mDetectType == DETECT_ONCE)
{
if (!mDetectOnceFinished)
{
mDetectOnceFinished = TRUE;
backColor = temp;
}
}
else
{
backColor = (mBackColorR << 16) + (mBackColorG << 8) + mBackColorB;
}
// Do Actual mixing
// If the image width is not a multiple of 4, sth goes wrong
for (long i = 0; i < mTotalPixels; i++)
{
if (*pMixing != backColor)
{
*pPrimary = *pMixing;
}
pPrimary++;
pMixing++;
}
}
BOOL CVideoMixController::IsMMXSupported(void)
{
BOOL isSupported = TRUE;
__asm
{
mov eax, 1
CPUID
test edx, 00800000H
jnz found
mov isSupported, 0
found:
}
return isSupported;
}
// Use MMX optimization
// Every time we can process 64 bits
__inline void CVideoMixController::IdealMMXMixing16Bits(BYTE * outPrimary, BYTE * inMixing)
{
static int backR = mBackColorR;
static int backG = mBackColorG;
static int backB = mBackColorB;
static __int64 mask = 0xFFFFFFFFFFFFFFFF;
static long pixelCount = mTotalPixels;
__asm
{
mov esi, inMixing
mov edi, outPrimary
mov ecx, pixelCount
shr ecx, 2 ; every time we deal with 4 pixels
mov eax, backR
mov ebx, backG
shl eax, 11
shl ebx, 5
add eax, ebx
add eax, backB
pxor mm6, mm6
movd mm6, eax
punpcklwd mm6, mm6
punpckldq mm6, mm6
movq mm7, mask
next_4pixel:
movq mm0, [esi]
movq mm1, [edi]
movq mm2, mm6
pcmpeqw mm2, mm0
pand mm1, mm2
pxor mm2, mm7
pand mm0, mm2
paddw mm1, mm0
movq [edi], mm1
add esi, 8
add edi, 8
sub ecx, 1
cmp ecx, 0
jg next_4pixel
emms
}
}
void CVideoMixController::Start(void)
{
mEOSMixing = FALSE;
mEOSMainVideo = FALSE;
mStopped = FALSE;
mMixingFlushing = FALSE;
mMixingFrames->SetReachEnd(FALSE);
}
void CVideoMixController::Stop(void)
{
mStopped = TRUE;
}
void CVideoMixController::SetInputVideoInfo(VIDEOINFOHEADER * inInfo)
{
ASSERT(inInfo);
mBitCount = inInfo->bmiHeader.biBitCount;
mTotalPixels = inInfo->bmiHeader.biWidth * abs(inInfo->bmiHeader.biHeight);
// Expand to bytes and round up to a multiple of 4
long stride = (inInfo->bmiHeader.biWidth * (mBitCount / 8) + 3) & ~3;
mMixingFrameSize = stride * abs(inInfo->bmiHeader.biHeight);
mBackDrift = (mBitCount == 16) ? DEFAULT_RGB565_DRIFT : DEFAULT_RGB32_DRIFT;
// Allocate mixing frame buffers
ReleaseMixingBuffer();
mMixingFrames = new CFrameList(mMixingFrameSize, BUFFERED_FRAME_COUNT);
}
void CVideoMixController::SetDetectType(DETECT_TYPE inType)
{
mDetectType = inType;
}
void CVideoMixController::GetDetectType(DETECT_TYPE * outType)
{
*outType = mDetectType;
}
void CVideoMixController::SetBackgroundColor(BYTE inRed, BYTE inGreen, BYTE inBlue)
{
mBackColorR = inRed;
mBackColorG = inGreen;
mBackColorB = inBlue;
// Change detect-type to CUSTOMIZE
mDetectType = CUSTOMIZE;
}
void CVideoMixController::GetBackgroundColor(BYTE * outRed, BYTE * outGreen, BYTE * outBlue)
{
*outRed = mBackColorR;
*outGreen = mBackColorG;
*outBlue = mBackColorB;
}
// Just the mixing video sample pointer, waiting for mixing
HRESULT CVideoMixController::ReceiveMixingVideo(IMediaSample * inMixingSample)
{
if (mEOSMixing || mStopped || mMixingFlushing)
{
return NOERROR;
}
PBYTE pData;
inMixingSample->GetPointer(&pData);
LONG length = inMixingSample->GetActualDataLength();
if (mMixingFrames)
{
mMixingFrames->AddFrame(pData);
}
return NOERROR;
}
HRESULT CVideoMixController::MixingEndOfStream(void)
{
mEOSMixing = TRUE;
mMixingFrames->SetReachEnd(TRUE);
return NOERROR;
}
HRESULT CVideoMixController::MixingBeginFlush(void)
{
mMixingFlushing = TRUE;
if (mMixingFrames)
{
mMixingFrames->Flush();
}
return NOERROR;
}
HRESULT CVideoMixController::MixingEndFlush(void)
{
mMixingFlushing = FALSE;
return NOERROR;
}
// Provided main video sample, we do mixing on it!
HRESULT CVideoMixController::DoMixing(IMediaSample * inMainSample)
{
if (mEOSMainVideo || mStopped)
{
return NOERROR;
}
ASSERT(inMainSample);
ASSERT(mMixingFrames);
PBYTE pSrc = NULL, pMixing = NULL;
inMainSample->GetPointer(&pSrc);
mMixingFrames->GetFrame(&pMixing);
if (pMixing != NULL)
{
// DWORD dw1 = ::timeGetTime();
if (mBitCount == 16)
{
if (mIsMMXSupported)
{
IdealMMXMixing16Bits(pSrc, pMixing);
}
else
{
IdealMixing16Bits(pSrc, pMixing);
}
// ActualMixing16Bits(pSrc, pMixing);
}
else
{
IdealMixing32Bits(pSrc, pMixing);
// ActualMixing32Bits(pSrc, pMixing);
}
mMixingFrames->ReleaseFrame();
/* DWORD dw2 = ::timeGetTime();
DWORD span = dw2 - dw1;
FILE * fp = fopen("C:\\VideoKey.txt", "a");
fprintf(fp, "%10d\n", span);
fclose(fp);*/
}
return NOERROR;
}
HRESULT CVideoMixController::MainVideoEndOfStream(void)
{
mEOSMainVideo = TRUE;
return NOERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -