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

📄 t264enc.cpp

📁 T264是中国的视频编码自由组织合力开发的264编解码程序
💻 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"

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 + -