📄 theoradecodefilter.cpp
字号:
//===========================================================================
//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 + -