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

📄 theoradecodefilter.cpp

📁 Window Mobile Capture with DirectDraw
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//===========================================================================
//Copyright (C) 2003-2006 Zentaro Kavanagh
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
//- Redistributions of source code must retain the above copyright
//  notice, this list of conditions and the following disclaimer.
//
//- Redistributions in binary form must reproduce the above copyright
//  notice, this list of conditions and the following disclaimer in the
//  documentation and/or other materials provided with the distribution.
//
//- Neither the name of Zentaro Kavanagh nor the names of contributors 
//  may be used to endorse or promote products derived from this software 
//  without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
//PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===========================================================================

#include "stdafx.h"

#include "TheoraDecodeFilter.h"



//COM Factory Template
CFactoryTemplate g_Templates[] = 
{
    { 
		L"Theora Decode Filter",					// Name
	    &CLSID_TheoraDecodeFilter,				// CLSID
	    TheoraDecodeFilter::CreateInstance,		// Method to create an instance of Theora Decoder
        NULL,									// Initialization function
#ifdef WINCE
		&TheoraDecodeFilterReg
#else
        NULL									// Set-up information (for filters)
#endif
    }

};

// Generic way of determining the number of items in the template
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 



TheoraDecodeFilter::TheoraDecodeFilter() 
	:	CTransformFilter( NAME("Theora Decode Filter"), NULL, CLSID_TheoraDecodeFilter)
	,	mPictureWidth(0)
	,	mPictureHeight(0)
	,	mBMIFrameSize(0)
	,	mFrameCount(0)
	,	mYOffset(0)
	,	mXOffset(0)
	,	mFrameDuration(0)
	,	mBegun(false)
	,	mSeekTimeBase(0)
	,	mLastSeenStartGranPos(0)

	,	mSegStart(0)
	,	mSegEnd(0)
	,	mPlaybackRate(0.0)
	,	mTheoraFormatInfo(NULL)
	,	mScratchBuffer(NULL)
{
#ifdef OGGCODECS_LOGGING
	debugLog.open("G:\\logs\\newtheofilter.log", ios_base::out);
#endif

#ifdef WINCE
	debugLog.clear();
	debugLog.open(L"\\Storage Card\\theo.txt", ios_base::out);
	debugLog<<"Loaded theora filter"<<endl;
	//debugLog.close();

#endif

	mCurrentOutputSubType = MEDIASUBTYPE_None;
	sOutputVideoParams locVideoParams;

	//YV12 media type
	CMediaType* locAcceptMediaType = NULL;
	locAcceptMediaType = new CMediaType(&MEDIATYPE_Video);		//Deleted in pin destructor
	locAcceptMediaType->subtype = MEDIASUBTYPE_YV12;
	locAcceptMediaType->formattype = FORMAT_VideoInfo2;
	mOutputMediaTypes.push_back(locAcceptMediaType);

	locVideoParams.bitsPerPixel = 12;
	locVideoParams.fourCC = MAKEFOURCC('Y','V','1','2');
	mOutputVideoParams.push_back(locVideoParams);


	//YUY2 Media Type
	locAcceptMediaType = new CMediaType(&MEDIATYPE_Video);		//Deleted in pin destructor
	locAcceptMediaType->subtype = MEDIASUBTYPE_YUY2;
	locAcceptMediaType->formattype = FORMAT_VideoInfo2;
	mOutputMediaTypes.push_back(locAcceptMediaType);

	locVideoParams.bitsPerPixel = 16;
	locVideoParams.fourCC = MAKEFOURCC('Y','U','Y','2');
	mOutputVideoParams.push_back(locVideoParams);

    /*
	//RGB565 Media Type
	locAcceptMediaType = new CMediaType(&MEDIATYPE_Video);		//Deleted in pin destructor
	locAcceptMediaType->subtype = MEDIASUBTYPE_RGB565;
	locAcceptMediaType->formattype = FORMAT_VideoInfo;
	mOutputMediaTypes.push_back(locAcceptMediaType);

	locVideoParams.bitsPerPixel = 16;
	locVideoParams.fourCC = 0;
	mOutputVideoParams.push_back(locVideoParams);

	//RGB24 Media Type
	locAcceptMediaType = new CMediaType(&MEDIATYPE_Video);		//Deleted in pin destructor
	locAcceptMediaType->subtype = MEDIASUBTYPE_RGB24;
	locAcceptMediaType->formattype = FORMAT_VideoInfo;
	mOutputMediaTypes.push_back(locAcceptMediaType);

	locVideoParams.bitsPerPixel = 32;
	locVideoParams.fourCC = 0;
	mOutputVideoParams.push_back(locVideoParams);

    */


	mTheoraDecoder = new TheoraDecoder;
	mTheoraDecoder->initCodec();

	mScratchBuffer = new BYTE[1024*1024*2];

}

TheoraDecodeFilter::~TheoraDecodeFilter() 
{
	delete[] mScratchBuffer;
	for (size_t i = 0; i < mOutputMediaTypes.size(); i++) {
		delete mOutputMediaTypes[i];
	}

	delete mTheoraDecoder;
	mTheoraDecoder = NULL;

	delete mTheoraFormatInfo;
	mTheoraFormatInfo = NULL;
	debugLog.close();

}


#ifdef WINCE
LPAMOVIESETUP_FILTER TheoraDecodeFilter::GetSetupData()
{	
	return (LPAMOVIESETUP_FILTER)&TheoraDecodeFilterReg;	
}

HRESULT TheoraDecodeFilter::Register()
{
	return CBaseFilter::Register();
}
#endif

CUnknown* WINAPI TheoraDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
{
	//This routine is the COM implementation to create a new Filter
	TheoraDecodeFilter *pNewObject = new TheoraDecodeFilter();
    if (pNewObject == NULL) {
        *pHr = E_OUTOFMEMORY;
    }
	return pNewObject;
} 
void TheoraDecodeFilter::FillMediaType(int inPosition, CMediaType* outMediaType, unsigned long inSampleSize) 
{
	outMediaType->SetType(&(mOutputMediaTypes[inPosition]->majortype));
	outMediaType->SetSubtype(&(mOutputMediaTypes[inPosition]->subtype));
	outMediaType->SetFormatType(&(mOutputMediaTypes[inPosition]->formattype));
	outMediaType->SetTemporalCompression(FALSE);
	outMediaType->SetSampleSize(inSampleSize);		

}
bool TheoraDecodeFilter::FillVideoInfoHeader(int inPosition, VIDEOINFOHEADER* inFormatBuffer) 
{
	//MTS::: Needs changes for alternate media types. FOURCC and bitCOunt
	TheoraDecodeFilter* locFilter = this;

	inFormatBuffer->AvgTimePerFrame = (UNITS * locFilter->mTheoraFormatInfo->frameRateDenominator) / locFilter->mTheoraFormatInfo->frameRateNumerator;
	inFormatBuffer->dwBitRate = locFilter->mTheoraFormatInfo->targetBitrate;
	
	inFormatBuffer->bmiHeader.biBitCount = mOutputVideoParams[inPosition].bitsPerPixel;  

	inFormatBuffer->bmiHeader.biClrImportant = 0;   //All colours important
	inFormatBuffer->bmiHeader.biClrUsed = 0;        //Use max colour depth

	inFormatBuffer->bmiHeader.biCompression = mOutputVideoParams[inPosition].fourCC;
	inFormatBuffer->bmiHeader.biHeight = locFilter->mTheoraFormatInfo->pictureHeight;   //Not sure
	inFormatBuffer->bmiHeader.biPlanes = 1;    //Must be 1
	inFormatBuffer->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    //????? Size of what ?
	inFormatBuffer->bmiHeader.biSizeImage = ((locFilter->mTheoraFormatInfo->pictureHeight * locFilter->mTheoraFormatInfo->pictureWidth) * inFormatBuffer->bmiHeader.biBitCount)/8;    //Size in bytes of image ??
	inFormatBuffer->bmiHeader.biWidth = locFilter->mTheoraFormatInfo->pictureWidth;
	inFormatBuffer->bmiHeader.biXPelsPerMeter = 0;   //Fuck knows
	inFormatBuffer->bmiHeader.biYPelsPerMeter = 0;   //" " " " " 
	
	inFormatBuffer->rcSource.top = 0;
	inFormatBuffer->rcSource.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
	inFormatBuffer->rcSource.left = 0;
	inFormatBuffer->rcSource.right = locFilter->mTheoraFormatInfo->pictureWidth;

	inFormatBuffer->rcTarget.top = 0;
	inFormatBuffer->rcTarget.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
	inFormatBuffer->rcTarget.left = 0;
	inFormatBuffer->rcTarget.right = locFilter->mTheoraFormatInfo->pictureWidth;

	inFormatBuffer->dwBitErrorRate=0;
	return true;
}

bool TheoraDecodeFilter::FillVideoInfoHeader2(int inPosition, VIDEOINFOHEADER2* inFormatBuffer) 
{
	//MTS::: Needs changes for alternate media types. FOURCC and bitCOunt
	TheoraDecodeFilter* locFilter = this;

	inFormatBuffer->AvgTimePerFrame = (UNITS * locFilter->mTheoraFormatInfo->frameRateDenominator) / locFilter->mTheoraFormatInfo->frameRateNumerator;
	inFormatBuffer->dwBitRate = locFilter->mTheoraFormatInfo->targetBitrate;
	
	inFormatBuffer->bmiHeader.biBitCount = mOutputVideoParams[inPosition].bitsPerPixel;  

	inFormatBuffer->bmiHeader.biClrImportant = 0;   //All colours important
	inFormatBuffer->bmiHeader.biClrUsed = 0;        //Use max colour depth

	inFormatBuffer->bmiHeader.biCompression = mOutputVideoParams[inPosition].fourCC;
	inFormatBuffer->bmiHeader.biHeight = locFilter->mTheoraFormatInfo->pictureHeight;   //Not sure
	inFormatBuffer->bmiHeader.biPlanes = 1;    //Must be 1
	inFormatBuffer->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    //????? Size of what ?
	inFormatBuffer->bmiHeader.biSizeImage = ((locFilter->mTheoraFormatInfo->pictureHeight * locFilter->mTheoraFormatInfo->pictureWidth) * inFormatBuffer->bmiHeader.biBitCount)/8;    //Size in bytes of image ??
	inFormatBuffer->bmiHeader.biWidth = locFilter->mTheoraFormatInfo->pictureWidth;
	inFormatBuffer->bmiHeader.biXPelsPerMeter = 0;   //Fuck knows
	inFormatBuffer->bmiHeader.biYPelsPerMeter = 0;   //" " " " " 
	
	inFormatBuffer->rcSource.top = 0;
	inFormatBuffer->rcSource.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
	inFormatBuffer->rcSource.left = 0;
	inFormatBuffer->rcSource.right = locFilter->mTheoraFormatInfo->pictureWidth;

	inFormatBuffer->rcTarget.top = 0;
	inFormatBuffer->rcTarget.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
	inFormatBuffer->rcTarget.left = 0;
	inFormatBuffer->rcTarget.right = locFilter->mTheoraFormatInfo->pictureWidth;

	inFormatBuffer->dwBitErrorRate=0;

    //Info 2 extensions
    inFormatBuffer->dwInterlaceFlags = 0;
    inFormatBuffer->dwCopyProtectFlags = 0;


    if ((mTheoraFormatInfo->aspectNumerator == 0) || (mTheoraFormatInfo->aspectDenominator == 0)) {
        //Maybe setting to 0?
        inFormatBuffer->dwPictAspectRatioX = mTheoraFormatInfo->pictureWidth;
        inFormatBuffer->dwPictAspectRatioY = mTheoraFormatInfo->pictureHeight;
    } else {
        inFormatBuffer->dwPictAspectRatioX = mTheoraFormatInfo->pictureWidth * mTheoraFormatInfo->aspectNumerator;
        inFormatBuffer->dwPictAspectRatioY = mTheoraFormatInfo->pictureHeight * mTheoraFormatInfo->aspectDenominator;

    }
    inFormatBuffer->dwControlFlags = 0;
    inFormatBuffer->dwReserved2 = 0;
	return true;
}

HRESULT TheoraDecodeFilter::CheckInputType(const CMediaType* inMediaType) 
{
	if	( (inMediaType->majortype == MEDIATYPE_OggPacketStream) &&
			(inMediaType->subtype == MEDIASUBTYPE_None) && (inMediaType->formattype == FORMAT_OggIdentHeader)
		)
	{
		if (inMediaType->cbFormat == THEORA_IDENT_HEADER_SIZE) {
			if (strncmp((char*)inMediaType->pbFormat, "\200theora", 7) == 0) {
				//TODO::: Possibly verify version
				debugLog<<"Input type ok"<<endl;
				return S_OK;
			}
		}
	}
	return S_FALSE;
}

HRESULT TheoraDecodeFilter::CheckOutputType(const CMediaType* inMediaType)
{
	for (size_t i = 0; i < mOutputMediaTypes.size(); i++) {
		if	(		(inMediaType->majortype == mOutputMediaTypes[i]->majortype) 
				&&	(inMediaType->subtype == mOutputMediaTypes[i]->subtype) 
				&&	(inMediaType->formattype == mOutputMediaTypes[i]->formattype)
			)
		{
			debugLog<<"Output type ok"<<endl;
			return S_OK;
		} 
	}
	debugLog<<"Output type no good"<<endl;

	if (inMediaType->majortype == MEDIATYPE_Video) {
		debugLog<<"Querying for video - FAIL"<<endl;
		debugLog<<"Sub type = "<<inMediaType->subtype.Data1<<"-"<<inMediaType->subtype.Data2<<"-"<<inMediaType->subtype.Data3<<"-"<<endl;
		debugLog<<"format type = "<<inMediaType->formattype.Data1<<"-"<<inMediaType->formattype.Data2<<"-"<<inMediaType->formattype.Data3<<"-"<<endl;
	} else {
		debugLog<<"Querying for non-video type"<<endl;
	}

	//If it matched none... return false.
	return S_FALSE;
}
HRESULT TheoraDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType) {
	//MTS::: Needs multiple media types
	if ((CheckInputType(inInputMediaType) == S_OK) && (CheckOutputType(inOutputMediaType) == S_OK)) {
		VIDEOINFOHEADER2* locVideoHeader = (VIDEOINFOHEADER2*)inOutputMediaType->Format();

		mBMIHeight = (unsigned long)abs(locVideoHeader->bmiHeader.biHeight);
		mBMIWidth = (unsigned long)abs(locVideoHeader->bmiHeader.biWidth);


		mBMIFrameSize = (mBMIHeight * mBMIWidth * locVideoHeader->bmiHeader.biBitCount) / 8;
		debugLog<<"Check transform OK"<<endl;
		return S_OK;
	} else {
		debugLog<<"Check transform FAILED"<<endl;
		return S_FALSE;
	}
}
HRESULT TheoraDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest) 
{

	HRESULT locHR = S_OK;

⌨️ 快捷键说明

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