⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cvideomixcontroller.cpp

📁 最近在学习directshow, Directshow实务精选的源代码
💻 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 + -