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

📄 t264enc.cpp

📁 T264是中国的视频编码自由组织合力开发的264编解码程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
    ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));
    DWORD fcc = '462T';
    pvi->dwBitRate = m_param.bitrate;
    pvi->AvgTimePerFrame = m_avgFrameTime;
    pvi->bmiHeader.biCompression = fcc;
    pvi->bmiHeader.biBitCount    = 12;
    pvi->bmiHeader.biPlanes = 1;
    pvi->bmiHeader.biSize       = sizeof(BITMAPINFOHEADER);
    pvi->bmiHeader.biWidth      = m_param.width;
    pvi->bmiHeader.biHeight     = m_param.height;
    pvi->bmiHeader.biSizeImage  = GetBitmapSize(&pvi->bmiHeader);
    SetRectEmpty(&(pvi->rcSource));
    SetRectEmpty(&(pvi->rcTarget));
    pmt->SetFormatType(&FORMAT_VideoInfo);
    pmt->SetVariableSize();
    pmt->SetTemporalCompression(true);

    return S_OK;
}

//
// DecideBufferSize
//
// Tell the output pin's allocator what size buffers we
// require. Can only do this when the input is connected
//
HRESULT CT264Enc::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
    CheckPointer(pAlloc,E_POINTER);
    CheckPointer(pProperties,E_POINTER);

    // Is the input pin connected

    if(m_pInput->IsConnected() == FALSE)
    {
        return E_UNEXPECTED;
    }

    HRESULT hr = NOERROR;
    pProperties->cBuffers = 1;
    pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();

    ASSERT(pProperties->cbBuffer);

    // If we don't have fixed sized samples we must guess some size

    if(!m_pInput->CurrentMediaType().bFixedSizeSamples)
    {
        if(pProperties->cbBuffer < OUTPIN_BUFFER_SIZE)
        {
            // nothing more than a guess!!
            pProperties->cbBuffer = OUTPIN_BUFFER_SIZE;
        }
    }

    // Ask the allocator to reserve us some sample memory, NOTE the function
    // can succeed (that is return NOERROR) but still not have allocated the
    // memory that we requested, so we must check we got whatever we wanted

    ALLOCATOR_PROPERTIES Actual;

    hr = pAlloc->SetProperties(pProperties,&Actual);
    if(FAILED(hr))
    {
        return hr;
    }

    ASSERT(Actual.cBuffers == 1);

    if(pProperties->cBuffers > Actual.cBuffers ||
        pProperties->cbBuffer > Actual.cbBuffer)
    {
        return E_FAIL;
    }

    return NOERROR;

} // DecideBufferSize


//
// GetMediaType
//
// I support one type, namely the type of the input pin
// We must be connected to support the single output type
//
HRESULT CT264Enc::GetMediaType(int iPosition, CMediaType *pMediaType)
{
    // Is the input pin connected

    if(m_pInput->IsConnected() == FALSE)
    {
        return E_UNEXPECTED;
    }

    // This should never happen

    if(iPosition < 0)
    {
        return E_INVALIDARG;
    }

    // Do we have more items to offer

    if(iPosition > 0)
    {
        return VFW_S_NO_MORE_ITEMS;
    }

    CheckPointer(pMediaType,E_POINTER);

    InitOutMediaType(pMediaType);

    return NOERROR;

} // GetMediaType

HRESULT CT264Enc::StartStreaming()
{
    _asm emms
    if (m_t264 == NULL)
    {
        INT plane = m_param.width * m_param.height;
        m_t264 = T264_open(&m_param);
        m_pBuffer = (BYTE*)_aligned_malloc(plane + (plane >> 1), 16);
        ASSERT(m_t264);
    }
    return CTransformFilter::StartStreaming();
}

HRESULT CT264Enc::StopStreaming()
{
    if (m_t264 != NULL)
    {
        T264_close(m_t264);
        m_t264 = 0;
        _aligned_free(m_pBuffer);
        m_pBuffer = 0;
    }
    return CTransformFilter::StopStreaming();
}

//
// GetPages
//
// This is the sole member of ISpecifyPropertyPages
// Returns the clsid's of the property pages we support
//
STDMETHODIMP CT264Enc::GetPages(CAUUID *pPages)
{
    CheckPointer(pPages,E_POINTER);

    pPages->cElems = 1;
    pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
    if(pPages->pElems == NULL)
    {
        return E_OUTOFMEMORY;
    }

    *(pPages->pElems) = CLSID_T264PropPage;
    return NOERROR;
} // GetPages

HRESULT CT264Enc::get_Para(INT** pPara)
{
    *pPara = (INT*)&m_param;
    return S_OK;
}

HRESULT CT264Enc::put_Default()
{
    m_param.flags  = //USE_INTRA16x16|
        USE_INTRA4x4| 
        USE_HALFPEL|
        USE_QUARTPEL|
        USE_SUBBLOCK|
        //    USE_FULLSEARCH|
        USE_DIAMONDSEACH|
        USE_FORCEBLOCKSIZE|
        USE_FASTINTERPOLATE|
        USE_SAD|
        USE_EXTRASUBPELSEARCH|
        USE_INTRAININTER|
        USE_SCENEDETECT;

    m_param.iframe = 300;
    m_param.idrframe = 3000 * 300;
    m_param.qp       = 28;
    m_param.min_qp   = 8;
    m_param.max_qp   = 34;
    m_param.bitrate  = 600 * 1024;
    m_param.framerate= 30;

    m_param.search_x = 16;
    m_param.search_y = 16;

    m_param.block_size = SEARCH_16x16P
        |SEARCH_16x8P
        |SEARCH_8x16P
//        |SEARCH_8x8P
//        |SEARCH_8x4P
//        |SEARCH_4x8P
//        |SEARCH_4x4P;
        |SEARCH_16x16B
        |SEARCH_16x8B
        |SEARCH_8x16B;

    m_param.disable_filter = 0;
    m_param.aspect_ratio = 2;
    m_param.video_format = 1;

    m_param.ref_num  = 3;
    m_param.luma_coeff_cost = 4;    // default 4, min qp please decrease this value
    m_param.cpu      = 0;
    m_param.cabac = 1;
    m_param.b_num = 1;
    if (m_param.bitrate != 0)
        m_param.enable_rc = 1;
    else
        m_param.enable_rc = 0;

    return S_OK;
}

HRESULT CT264Enc::put_InfoWnd(INT hWnd)
{
    m_hWnd = (HWND)hWnd;

    return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// CT264Dec
CT264Dec::CT264Dec(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
CTransformFilter(tszName, punk, CLSID_T264ENC)
{
    m_t264 = 0;
    m_hWnd = 0;
}

CT264Dec::~CT264Dec()
{
    if (m_t264 != 0)
    {
        T264dec_close(m_t264);
    }
}

//
// CreateInstance
//
// Provide the way for COM to create a CT264Dec object
//
CUnknown * WINAPI CT264Dec::CreateInstance(LPUNKNOWN punk, HRESULT *phr) 
{
    ASSERT(phr);

    CT264Dec *pNewObject = new CT264Dec(NAME("T264Dec"), punk, phr);
    if (pNewObject == NULL) {
        if (phr)
            *phr = E_OUTOFMEMORY;
    }

    return pNewObject;

} // CreateInstance

//
// NonDelegatingQueryInterface
//
// Reveals IContrast and ISpecifyPropertyPages
//
STDMETHODIMP CT264Dec::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 CT264Dec::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
    return S_OK;
} // Transform

HRESULT CT264Dec::SendSample(T264_t* t, T264_frame_t *frame, IMediaSample* pSample)
{
    INT	i;
    BYTE* p, *pDst;
    HRESULT hr;
    IMediaSample* pOutSample;

    // Set up the output sample
    hr = InitializeOutputSample(pSample, &pOutSample);

    if (FAILED(hr)) 
    {
        return hr;
    }
    hr = pOutSample->GetPointer(&pDst);
    ASSERT(hr == S_OK);

    p = frame->Y[0];
    for(i = 0 ; i < t->height ; i ++)
    {
        memcpy(pDst, p, t->width);
        pDst += m_nStride;
        p += t->edged_stride;
    }
    p = frame->V;
    for(i = 0 ; i < t->height >> 1 ; i ++)
    {
        memcpy(pDst, p, t->width);
        pDst += m_nStride >> 1;
        p += t->edged_stride_uv;
    }
    p = frame->U;
    for(i = 0 ; i < t->height >> 1 ; i ++)
    {
        memcpy(pDst, p, t->width);
        pDst += m_nStride >> 1;
        p += t->edged_stride_uv;
    }

    pOutSample->SetActualDataLength(t->width * t->height + (t->width * t->height >> 1));
    pOutSample->SetSyncPoint(TRUE);
    CRefTime rtEnd = m_time + m_avgFrameTime;
    pOutSample->SetTime(&m_time.m_time, &rtEnd.m_time);
    m_time = rtEnd;

    hr = m_pNextFilterInputpin->Receive(pOutSample);
    m_bSampleSkipped = FALSE;	// last thing no longer dropped

    // release the output buffer. If the connected pin still needs it,
    // it will have addrefed it itself.
    pOutSample->Release();

    return hr;
}

HRESULT CT264Dec::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
{
    HRESULT hr = CTransformFilter::CompleteConnect(direction, pReceivePin);
    if (direction == PINDIR_OUTPUT)
    {
        hr = pReceivePin->QueryInterface(__uuidof(m_pNextFilterInputpin), (VOID**)&m_pNextFilterInputpin);
        ASSERT(hr == S_OK);
        // we do not want to hold the reference of the input pin
        m_pNextFilterInputpin->Release();
    }
    return hr;
}

HRESULT CT264Dec::Receive(IMediaSample* pSample)
{
    /*  Check for other streams and pass them on */
    AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
    if (pProps->dwStreamId != AM_STREAM_MEDIA) {
        return m_pNextFilterInputpin->Receive(pSample);
    }
    HRESULT hr;
    ASSERT(pSample);

    ASSERT (m_pOutput != NULL) ;
    {
        // some decoder does not reset emms(such as mainconcept mpeg2 decoder), and we need compute floating ...
        BYTE* pSrc;
        LONG lSrcSize;
        INT run = 1;
        hr = pSample->GetPointer(&pSrc);
        ASSERT(hr == S_OK);
        lSrcSize = pSample->GetSize();

        T264dec_buffer(m_t264, pSrc, lSrcSize);
        while (run)
        {
            decoder_state_t state = T264dec_parse(m_t264);
            switch(state) 
            {
            case DEC_STATE_SLICE:
                {
                    if (m_t264->output.poc >= 0)
                    {
                        SendSample(m_t264, &m_t264->output, pSample);
                    }
                }
                break;
            case DEC_STATE_BUFFER:
                /* read more data */
                return S_OK;
            case DEC_STATE_SEQ:
                if (m_t264->frame_id > 0)
                {
                    SendSample(m_t264, T264dec_flush_frame(m_t264), pSample);
                }
                break;
            /*case DEC_STATE_PIC:*/
            default:
                /* do not care */
                break;
            }
        }
    }

    return hr;
}

HRESULT CT264Dec::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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -