📄 t264enc.cpp
字号:
#include "stdafx.h"
#include <initguid.h> // declares DEFINE_GUID to declare an EXTERN_C const.
#if (_MSC_VER < 1100)
#include <olectlid.h>
#else
#include <olectl.h>
#endif
#include "T264Enc.h"
#include "malloc.h"
#include "T264EncProp.h"
#include "dvdmedia.h"
static const WCHAR g_wszEncName[] = L"T264 Encoder";
static const WCHAR g_wszEncPropName[] = L"T264 Properties";
static const WCHAR g_wszDecName[] = L"T264 Decoder";
static const WCHAR g_wszDecPropName[] = L"T264 decoder properties";
static const WCHAR g_wszSplitterName[] = L"T264 splitter";
// dshow needs this
STDAPI
DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
}
STDAPI
DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
}
//
// DllEntryPoint
//
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
// {6D2616AA-3C89-4703-9CEB-693C051C9E5F}
DEFINE_GUID(CLSID_T264ENC,
0x6d2616aa, 0x3c89, 0x4703, 0x9c, 0xeb, 0x69, 0x3c, 0x5, 0x1c, 0x9e, 0x5f);
// {EAB4831B-121B-4568-86A7-E8058BABA62E}
DEFINE_GUID(CLSID_T264DEC,
0xeab4831b, 0x121b, 0x4568, 0x86, 0xa7, 0xe8, 0x5, 0x8b, 0xab, 0xa6, 0x2e);
// {0CA6ED63-793D-4a4e-BF64-6E37F6F4D44E}
DEFINE_GUID(CLSID_T264SUBTYPE,
0xca6ed63, 0x793d, 0x4a4e, 0xbf, 0x64, 0x6e, 0x37, 0xf6, 0xf4, 0xd4, 0x4e);
// {E795D14A-879D-4ea9-95EE-B6884276AEEF}
DEFINE_GUID(CLSID_T264PropPage,
0xe795d14a, 0x879d, 0x4ea9, 0x95, 0xee, 0xb6, 0x88, 0x42, 0x76, 0xae, 0xef);
// {F3957FA3-98EE-4568-942D-953BBF79136F}
DEFINE_GUID(CLSID_T264Splitter,
0xf3957fa3, 0x98ee, 0x4568, 0x94, 0x2d, 0x95, 0x3b, 0xbf, 0x79, 0x13, 0x6f);
// setup data - allows the self-registration to work.
const AMOVIESETUP_MEDIATYPE sudInPinTypes[] =
{
{
&MEDIATYPE_Video,
&MEDIASUBTYPE_NULL
}
};
const AMOVIESETUP_MEDIATYPE sudOutPinTypes[] =
{
{
&MEDIATYPE_Stream,
&MEDIASUBTYPE_NULL
}
};
const AMOVIESETUP_MEDIATYPE sudInPinTypes1[] =
{
{
&MEDIATYPE_Stream,
&MEDIASUBTYPE_NULL
}
};
// encoder
const AMOVIESETUP_PIN psudPins[] =
{
{
L"Input", // strName
FALSE, // bRendered
FALSE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
L"", // strConnectsToPin
1, // nTypes
sudInPinTypes, // lpTypes
},
{
L"Output", // strName
FALSE, // bRendered
TRUE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
L"", // strConnectsToPin
1, // nTypes
sudOutPinTypes, // lpTypes
}
};
// decoder
const AMOVIESETUP_PIN psudPinsdec[] =
{
{
L"Input", // strName
FALSE, // bRendered
FALSE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
L"", // strConnectsToPin
1, // nTypes
sudInPinTypes, // lpTypes
},
{
L"Output", // strName
FALSE, // bRendered
TRUE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
L"", // strConnectsToPin
1, // nTypes
sudInPinTypes, // lpTypes
}
};
// splitter
const AMOVIESETUP_PIN psudPinssplitter[] =
{
{
L"Input", // strName
FALSE, // bRendered
FALSE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
L"", // strConnectsToPin
1, // nTypes
sudInPinTypes1, // lpTypes
},
{
L"Output", // strName
FALSE, // bRendered
TRUE, // bOutput
FALSE, // bZero
FALSE, // bMany
&CLSID_NULL, // clsConnectsToFilter
L"", // strConnectsToPin
1, // nTypes
sudInPinTypes, // lpTypes
}
};
const AMOVIESETUP_FILTER sudDST264ENC =
{
&CLSID_T264ENC, // clsID
g_wszEncName, // strName
MERIT_DO_NOT_USE, // dwMerit
2, // nPins
psudPins,
};
const AMOVIESETUP_FILTER sudDST264DEC =
{
&CLSID_T264DEC, // clsID
g_wszDecName, // strName
MERIT_NORMAL, // dwMerit
2, // nPins
psudPinsdec,
};
const AMOVIESETUP_FILTER subDST264Splitter =
{
&CLSID_T264Splitter, // clsID
g_wszSplitterName, // strName
MERIT_NORMAL + 3, // dwMerit
2, // nPins
psudPinssplitter,
};
CFactoryTemplate g_Templates[]=
{
{
g_wszEncName,
&CLSID_T264ENC,
CT264Enc::CreateInstance, // function called by class factory
NULL,
&sudDST264ENC
},
{
g_wszEncPropName,
&CLSID_T264PropPage,
CT264EncProp::CreateInstance
},
{
g_wszDecName,
&CLSID_T264DEC,
CT264Dec::CreateInstance, // function called by class factory
NULL,
&sudDST264DEC
},
{
g_wszSplitterName,
&CLSID_T264Splitter,
CT264Splitter::CreateInstance,
NULL,
&subDST264Splitter
}
};
int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
//////////////////////////////////////////////////////////////////////////
// CT264Enc
CT264Enc::CT264Enc(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
CTransformFilter(tszName, punk, CLSID_T264ENC)
{
m_t264 = 0;
memset(&m_param, 0, sizeof(m_param));
put_Default();
m_hWnd = 0;
}
CT264Enc::~CT264Enc()
{
if (m_t264 != 0)
{
T264_close(m_t264);
_aligned_free(m_pBuffer);
}
}
//
// CreateInstance
//
// Provide the way for COM to create a CT264Enc object
//
CUnknown * WINAPI CT264Enc::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
ASSERT(phr);
CT264Enc *pNewObject = new CT264Enc(NAME("T264Enc"), punk, phr);
if (pNewObject == NULL) {
if (phr)
*phr = E_OUTOFMEMORY;
}
return pNewObject;
} // CreateInstance
//
// NonDelegatingQueryInterface
//
// Reveals IContrast and ISpecifyPropertyPages
//
STDMETHODIMP CT264Enc::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv, E_POINTER);
if (riid == IID_IProp)
{
return GetInterface((IProp*) this, ppv);
}
else if (riid == IID_ISpecifyPropertyPages)
{
return GetInterface((ISpecifyPropertyPages*) this, ppv);
}
else
{
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}
} // NonDelegatingQueryInterface
HRESULT CT264Enc::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
INT plane = m_param.width * m_param.height;
HRESULT hr;
// some decoder does not reset emms(such as mainconcept mpeg2 decoder), and we need compute floating ...
__asm emms
BYTE* pSrc, *pDst;
LONG lDstSize, lActualSize;
hr = pIn->GetPointer(&pSrc);
ASSERT(hr == S_OK);
hr = pOut->GetPointer(&pDst);
ASSERT(hr == S_OK);
lDstSize = pOut->GetSize();
// convert yv12 ==> iyuv
CopyMemory(m_pBuffer, pSrc, plane);
CopyMemory(m_pBuffer + plane, pSrc + plane + (plane >> 2), plane >> 2);
CopyMemory(m_pBuffer + plane + (plane >> 2), pSrc + plane, plane >> 2);
lActualSize = T264_encode(m_t264, m_pBuffer, pDst, lDstSize);
ASSERT(lActualSize <= lDstSize);
pOut->SetActualDataLength(lActualSize);
if (m_hWnd && lActualSize)
{
wsprintf(m_szInfo, "Frame = %d, Qp = %d, Length = %d.", m_t264->frame_id, m_t264->qp_y, lActualSize);
SendMessage(m_hWnd, WM_SETTEXT, 0, (LPARAM)m_szInfo);
}
return hr;
} // Transform
HRESULT CT264Enc::Copy(IMediaSample *pSource, IMediaSample *pDest) const
{
CheckPointer(pSource,E_POINTER);
CheckPointer(pDest,E_POINTER);
// Copy the sample data
BYTE *pSourceBuffer, *pDestBuffer;
long lSourceSize = pSource->GetActualDataLength();
#ifdef DEBUG
long lDestSize = pDest->GetSize();
ASSERT(lDestSize >= lSourceSize);
#endif
pSource->GetPointer(&pSourceBuffer);
pDest->GetPointer(&pDestBuffer);
CopyMemory((PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize);
// Copy the sample times
REFERENCE_TIME TimeStart, TimeEnd;
if(NOERROR == pSource->GetTime(&TimeStart, &TimeEnd))
{
pDest->SetTime(&TimeStart, &TimeEnd);
}
LONGLONG MediaStart, MediaEnd;
if(pSource->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)
{
pDest->SetMediaTime(&MediaStart,&MediaEnd);
}
// Copy the Sync point property
HRESULT hr = pSource->IsSyncPoint();
if(hr == S_OK)
{
pDest->SetSyncPoint(TRUE);
}
else if(hr == S_FALSE)
{
pDest->SetSyncPoint(FALSE);
}
else
{ // an unexpected error has occured...
return E_UNEXPECTED;
}
// Copy the media type
AM_MEDIA_TYPE *pMediaType;
pSource->GetMediaType(&pMediaType);
pDest->SetMediaType(pMediaType);
DeleteMediaType(pMediaType);
// Copy the preroll property
hr = pSource->IsPreroll();
if(hr == S_OK)
{
pDest->SetPreroll(TRUE);
}
else if(hr == S_FALSE)
{
pDest->SetPreroll(FALSE);
}
else
{ // an unexpected error has occured...
return E_UNEXPECTED;
}
// Copy the discontinuity property
hr = pSource->IsDiscontinuity();
if(hr == S_OK)
{
pDest->SetDiscontinuity(TRUE);
}
else if(hr == S_FALSE)
{
pDest->SetDiscontinuity(FALSE);
}
else
{ // an unexpected error has occured...
return E_UNEXPECTED;
}
// Copy the actual data length
long lDataLength = pSource->GetActualDataLength();
pDest->SetActualDataLength(lDataLength);
return NOERROR;
} // Copy
HRESULT CT264Enc::CheckInputType(const CMediaType *mtIn)
{
CheckPointer(mtIn,E_POINTER);
if(*mtIn->FormatType() == FORMAT_VideoInfo)
{
if(IsEqualGUID(*mtIn->Subtype(), MEDIASUBTYPE_YV12))
{
if(mtIn->FormatLength() < sizeof(VIDEOINFOHEADER))
return E_INVALIDARG;
VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
m_param.width = pInput->bmiHeader.biWidth;
m_param.height = pInput->bmiHeader.biHeight;
m_param.framerate = (float)(INT)((float)10000000 / pInput->AvgTimePerFrame + 0.5);
m_avgFrameTime = pInput->AvgTimePerFrame;
return NOERROR;
}
}
else if (*mtIn->FormatType() == FORMAT_VideoInfo2)
{
if(IsEqualGUID(*mtIn->Subtype(), MEDIASUBTYPE_YV12))
{
if(mtIn->FormatLength() < sizeof(VIDEOINFOHEADER2))
return E_INVALIDARG;
VIDEOINFOHEADER2 *pInput = (VIDEOINFOHEADER2*) mtIn->Format();
m_param.width = pInput->bmiHeader.biWidth;
m_param.height = pInput->bmiHeader.biHeight;
m_avgFrameTime = (LONGLONG)((float)10000000 / m_param.framerate);//pInput->AvgTimePerFrame;
m_param.framerate = (float)(INT)(m_param.framerate + 0.5f);
return NOERROR;
}
}
return E_INVALIDARG;
} // CheckInputType
HRESULT CT264Enc::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
{
CheckPointer(mtIn,E_POINTER);
CheckPointer(mtOut,E_POINTER);
HRESULT hr;
if(FAILED(hr = CheckInputType(mtIn)))
{
return hr;
}
if(*mtOut->FormatType() != FORMAT_VideoInfo)
{
return E_INVALIDARG;
}
// formats must be big enough
if(mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) ||
mtOut->FormatLength() < sizeof(VIDEOINFOHEADER))
return E_INVALIDARG;
return NOERROR;
} // CheckTransform
HRESULT CT264Enc::InitOutMediaType(CMediaType* pmt)
{
pmt->InitMediaType();
pmt->SetType(&MEDIATYPE_Video);
pmt->SetSubtype(&CLSID_T264SUBTYPE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -