📄 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"
// Conversion from RGB to YUV420
int RGB2YUV_YR[256], RGB2YUV_YG[256], RGB2YUV_YB[256];
int RGB2YUV_UR[256], RGB2YUV_UG[256], RGB2YUV_UBVR[256];
int RGB2YUV_VG[256], RGB2YUV_VB[256];
void InitLookupTable();
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned int *yuv);
unsigned char* pTmp = new unsigned char[120*160*3];
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;
InitLookupTable();
}
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();
//ConvertRGB2YUV(160,120,pSrc,(unsigned int*)pTmp);
// 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
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGB2YUV_YR[i] = (float)65.481 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YG[i] = (float)128.553 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YB[i] = (float)24.966 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UR[i] = (float)37.797 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UG[i] = (float)74.203 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VG[i] = (float)93.786 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VB[i] = (float)18.214 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UBVR[i] = (float)112 * (i<<8);
}
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned int *yuv)
{
unsigned int *u,*v,*y,*uu,*vv;
unsigned int *pu1,*pu2,*pu3,*pu4;
unsigned int *pv1,*pv2,*pv3,*pv4;
unsigned char *r,*g,*b;
int i,j;
uu=new unsigned int[w*h];
vv=new unsigned int[w*h];
if(uu==NULL || vv==NULL)
return 0;
y=yuv;
u=uu;
v=vv;
// Get r,g,b pointers from bmp image data....
r=bmp;
g=bmp+1;
b=bmp+2;
//Get YUV values for rgb values...
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
*y++=( RGB2YUV_YR[*r] +RGB2YUV_YG[*g]+RGB2YUV_YB[*b]+1048576)>>16;
*u++=(-RGB2YUV_UR[*r] -RGB2YUV_UG[*g]+RGB2YUV_UBVR[*b]+8388608)>>16;
*v++=( RGB2YUV_UBVR[*r]-RGB2YUV_VG[*g]-RGB2YUV_VB[*b]+8388608)>>16;
r+=3;
g+=3;
b+=3;
}
}
// Now sample the U & V to obtain YUV 4:2:0 format
// Sampling mechanism...
/* @ -> Y
# -> U or V
@ @ @ @
# #
@ @ @ @
@ @ @ @
# #
@ @ @ @
*/
// Get the right pointers...
u=yuv+w*h;
v=u+(w*h)/4;
// For U
pu1=uu;
pu2=pu1+1;
pu3=pu1+w;
pu4=pu3+1;
// For V
pv1=vv;
pv2=pv1+1;
pv3=pv1+w;
pv4=pv3+1;
// Do sampling....
for(i=0;i<h;i+=2)
{
for(j=0;j<w;j+=2)
{
*u++=(*pu1+*pu2+*pu3+*pu4)>>2;
*v++=(*pv1+*pv2+*pv3+*pv4)>>2;
pu1+=2;
pu2+=2;
pu3+=2;
pu4+=2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -