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

📄 cflickerlogo.cpp

📁 DmoVideoWatermark 这是一个DMO组件
💻 CPP
字号:
// CFlickerLogo.cpp : Implementation of CDmoVideoWatermarkApp and DLL registration.
/**
 ** Copyright (C) 2005 EnjoyView Inc., all rights reserved.
 **           Your View, Our Passion. Just Enjoy It!
 **
 **            http://spaces.msn.com/members/jemylu
 **
 **/

/*************************************************************************/

#include "stdafx.h"
#include "DmoVideoWatermark.h"

#define FIX_LOCK_NAME
#include <dmo.h>
#include <limits.h>     //  _I64_MAX
#include <crtdbg.h>
#include <dmoimpl.h>
#include <uuids.h>      // DirectShow media type guids
#include <amvideo.h>    // VIDEOINFOHEADER definition

#include "CFlickerLogo.h"

#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
/////////////////////////////////////////////////////////////////////////////
//
/*
STDMETHODIMP CFlickerLogo::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IFlickerLogo,
	};

	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}*/

CFlickerLogo::CFlickerLogo()
{
	mUnkMarshaler  = NULL;
	mInputFrame    = NULL;
	mFrameTime     = 0;
	mFrameDuration = 0;

	mIsInputInited = FALSE;
	mImageWidth  = 0;
	mImageHeight = 0;
	mImageStride = 0;
	mLogoStride  = 0;
	mFrameCount  = 0;
}

CFlickerLogo::~CFlickerLogo()
{
	SAFE_RELEASE(mInputFrame);
}

HRESULT CFlickerLogo::FinalConstruct()
{
	return CoCreateFreeThreadedMarshaler(GetControllingUnknown(), 
		&mUnkMarshaler.p);
}

void CFlickerLogo::FinalRelease()
{
	// Make sure we clean up
	FreeStreamingResources();
	mUnkMarshaler.Release();
}

// Helper - compares media types - ignoring the advisory fields
bool CFlickerLogo::TypesMatch(const DMO_MEDIA_TYPE *pmt1, 
							  const DMO_MEDIA_TYPE *pmt2)
{
	if (pmt1->majortype   == pmt2->majortype &&
		pmt1->subtype     == pmt2->subtype &&
		pmt1->lSampleSize == pmt2->lSampleSize &&
		pmt1->formattype  == pmt2->formattype &&
		pmt1->cbFormat    == pmt2->cbFormat &&
		0 == memcmp(pmt1->pbFormat, pmt2->pbFormat, pmt1->cbFormat)) 
	{
		return true;
	} 
	else 
	{
		return false;
	}
}


// --- IMediaObjectImpl methods ---
HRESULT CFlickerLogo::InternalGetInputStreamInfo(DWORD dwInputStreamIndex, 
												 DWORD *pdwFlags)
{
	// We can process data on any boundary
    *pdwFlags = 0;
    return S_OK;
}

HRESULT CFlickerLogo::InternalGetOutputStreamInfo(DWORD dwOutputStreamIndex,
												  DWORD *pdwFlags)
{
	// We output single frames
	*pdwFlags = DMO_OUTPUT_STREAMF_WHOLE_SAMPLES |
		DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
		DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE;
    return S_OK;
}

// RGB Video supported only
HRESULT CFlickerLogo::InternalCheckInputType(DWORD dwInputStreamIndex, 
											 const DMO_MEDIA_TYPE *pmt)
{
	// Check if the type is already set 
	// and if so reject any type that's not identical
	if (InputTypeSet(dwInputStreamIndex)) 
	{
		if (!TypesMatch(pmt, InputType(dwInputStreamIndex))) 
		{
			return DMO_E_INVALIDTYPE;
		} 
		else 
		{
			return S_OK;
		}
	}
    
	// We accept MEDIATYPE_Video
	if (pmt->majortype == MEDIATYPE_Video && pmt->pbFormat != NULL) 
	{
		return S_OK;
	}
	return DMO_E_INVALIDTYPE;
}

HRESULT CFlickerLogo::InternalCheckOutputType(DWORD dwOutputStreamIndex, 
											  const DMO_MEDIA_TYPE *pmt)
{
	// Check if the type is already set 
	// and if so reject any type that's not identical
	if (OutputTypeSet(dwOutputStreamIndex)) 
	{
		if (!TypesMatch(pmt, OutputType(dwOutputStreamIndex))) 
		{
			return DMO_E_INVALIDTYPE;
		} 
		else 
		{
			return S_OK;
		}
	}

	// Input mediatype should be set first
	// And we specify input and output use the same media type
	if (InputTypeSet(0)) 
	{
		if (!TypesMatch(pmt, InputType(0))) 
		{
			return DMO_E_INVALIDTYPE;
		} 
		else 
		{
			return S_OK;
		}
	}
	return DMO_E_INVALIDTYPE;
}

HRESULT CFlickerLogo::InternalGetInputType(DWORD dwInputStreamIndex, 
										   DWORD dwTypeIndex,
										   DMO_MEDIA_TYPE *pmt)
{
	// No types to all indices for dwTypeIndex are out of range
	return DMO_E_NO_MORE_ITEMS;
}

HRESULT CFlickerLogo::InternalGetOutputType(DWORD dwOutputStreamIndex,
											DWORD dwTypeIndex,
											DMO_MEDIA_TYPE *pmt)
{
	if (!InputTypeSet(0)) // Input media type must be set first
	{
		return DMO_E_TYPE_NOT_SET;
	}
	if (dwTypeIndex != 0) 
	{
		return DMO_E_NO_MORE_ITEMS;
	}

	// If GetOutputType()'s pmt parameter is NULL, return S_OK if the type exists.
	// Return DMO_E_NO_MORE_ITEMS if the type does not exists.  See the 
	// documentation for IMediaObject::GetOutputType() for more information.
	if (pmt != NULL)
	{
        HRESULT hr = MoCopyMediaType(pmt, InputType(0));
        if (FAILED(hr)) 
		{
            return hr;
        }
	}
	return S_OK;
}

HRESULT CFlickerLogo::InternalGetInputSizeInfo(DWORD dwInputStreamIndex, 
											   DWORD *pcbSize,
											   DWORD *pcbMaxLookahead, 
											   DWORD *pcbAlignment)
{
	*pcbSize         = 1;
    *pcbMaxLookahead = 0;
    *pcbAlignment    = 1;
	return S_OK;
}

HRESULT CFlickerLogo::InternalGetOutputSizeInfo(DWORD dwOutputStreamIndex, 
												DWORD *pcbSize,
												DWORD *pcbAlignment)
{
	*pcbAlignment = 1;
	*pcbSize      = OutputType(0)->lSampleSize;
    return S_OK;
}

HRESULT CFlickerLogo::InternalGetInputMaxLatency(DWORD dwInputStreamIndex, 
												 REFERENCE_TIME *prtMaxLatency)
{
	return E_NOTIMPL;
}

HRESULT CFlickerLogo::InternalSetInputMaxLatency(DWORD dwInputStreamIndex, 
												 REFERENCE_TIME rtMaxLatency)
{
	return E_NOTIMPL;
}

HRESULT CFlickerLogo::InternalFlush()
{
	InternalDiscontinuity(0);
	return S_OK;
}

HRESULT CFlickerLogo::InternalDiscontinuity(DWORD dwInputStreamIndex)
{
	SAFE_RELEASE(mInputFrame);
	mFrameCount = 0;
	return S_OK;
}

HRESULT CFlickerLogo::InternalAllocateStreamingResources()
{
	// Reinitialize variables
    InternalDiscontinuity(0);
	mIsInputInited = FALSE;

	return S_OK;
}

HRESULT CFlickerLogo::InternalFreeStreamingResources()
{
	return S_OK;
}

HRESULT CFlickerLogo::InternalProcessInput(DWORD dwInputStreamIndex, 
										   IMediaBuffer *pBuffer,
										   DWORD dwFlags, 
										   REFERENCE_TIME rtTimestamp,
										   REFERENCE_TIME rtTimelength)
{
	if (!mIsInputInited)
	{
		mIsInputInited = TRUE;
		VIDEOINFOHEADER * pvi = (VIDEOINFOHEADER *) InputType(0)->pbFormat;
		mImageWidth  = pvi->bmiHeader.biWidth;
		mImageHeight = pvi->bmiHeader.biHeight;
		mImageStride = (pvi->bmiHeader.biWidth * pvi->bmiHeader.biBitCount / 8 + 3) & ~3;
		mLogoStride  = cLogoWidth * pvi->bmiHeader.biBitCount / 8;
	}

	BYTE * pData;
	DWORD  dataLength = 0;
	HRESULT hr = pBuffer->GetBufferAndLength(&pData, &dataLength);
	if (FAILED(hr)) 
	{
		return hr;
	}

	// Do watermark overlay here >>>
	pBuffer->AddRef();              // Add a reference count
	mInputFrame = pBuffer;
	mFrameTime     = rtTimestamp;   // Save time stamp
	mFrameDuration = rtTimelength;
	if (cLogoWidth <= mImageWidth && cLogoHeight <= mImageHeight)
	{
		BYTE * pLine  = pData;
		BYTE newValue = (mFrameCount++ % 3 == 0) ? 0xFF : 0;
		for (int i = 0; i < cLogoHeight; i++)
		{
			if (i % 2 == 0)
			{
				memset(pLine, newValue, mLogoStride);
			}
			pLine += mImageStride;
		}
	}

	return S_OK;
}

HRESULT CFlickerLogo::InternalProcessOutput(DWORD dwFlags, 
											DWORD cOutputBufferCount,
											DMO_OUTPUT_DATA_BUFFER *pOutputBuffers, 
											DWORD *pdwStatus)
{
	PBYTE   pOutData;
	DWORD   cbCurrent;
	HRESULT hr = pOutputBuffers[0].pBuffer->GetBufferAndLength(&pOutData, &cbCurrent);
	if (FAILED(hr)) 
	{
		return hr;
	}

	// Copy watermark-overlayed image data
	if (mInputFrame)
	{
		PBYTE  pInData;
		DWORD  dataLength = 0;
		mInputFrame->GetBufferAndLength(&pInData, &dataLength);
		memcpy(pOutData, pInData, dataLength);
	}
	SAFE_RELEASE(mInputFrame);

	pOutputBuffers[0].pBuffer->SetLength(OutputType(0)->lSampleSize);
	pOutputBuffers[0].rtTimestamp  = mFrameTime;
	pOutputBuffers[0].rtTimelength = mFrameDuration;
	// Uncompressed video must always have a timestamp
	pOutputBuffers[0].dwStatus |= (DMO_OUTPUT_DATA_BUFFERF_TIME | DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH);

	return S_OK;
}

// Be asked if we can accept more input data?
HRESULT CFlickerLogo::InternalAcceptingInput(DWORD dwInputStreamIndex)
{
	return (mInputFrame == NULL) ? S_OK : S_FALSE;
}


// IPropertyBag
STDMETHODIMP CFlickerLogo::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
{
	return S_OK;
}

STDMETHODIMP CFlickerLogo::Write(LPCOLESTR pszPropName, VARIANT *pVar)
{
	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -