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

📄 t264enc.cpp

📁 h.264编码库 (T264)..........................
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#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 + -