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

📄 htrencftr.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        return VFW_S_NO_MORE_ITEMS;
    }

    // Convert wrapper videoType to GUID and FOURCC
    const GUID* pVideoTypeGuid;
    DWORD videoTypeFourcc;
    if( m_settings.videoType == CHantroEncoderWrapper::VIDEOTYPE_MPEG4 )
    {
        pVideoTypeGuid  = &ENCOUTPUT_MP4V;
        videoTypeFourcc = MAKEFOURCC('M', 'P', '4', 'V');
    }
    else
    {
        pVideoTypeGuid  = &ENCOUTPUT_H263;
        videoTypeFourcc = MAKEFOURCC('H', '2', '6', '3');
    }

    pMediaType->InitMediaType();
	pMediaType->SetType( &MEDIATYPE_Video );
	pMediaType->SetSubtype( pVideoTypeGuid );
	pMediaType->SetFormatType( &FORMAT_VideoInfo );
	pMediaType->SetVariableSize();
    pMediaType->SetTemporalCompression(TRUE);

    VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*)pMediaType->AllocFormatBuffer( sizeof(VIDEOINFOHEADER) );
    if( pVih == NULL )
    {
        HTRENC_DEBUG( "CHtrEncFltr::GetMediaType: FAILED allocating format buffer!\n" );
        return E_OUTOFMEMORY;
    }

    // Use cached avgTimePerFrame is present. Otherwise calculate from frameRate.
    pVih->AvgTimePerFrame = m_cachedAvgFrameTime != 0 ? m_cachedAvgFrameTime :
                            HTRENC_FRAMERATE2TIME(m_settings.frameRate);

	pVih->bmiHeader.biBitCount      = 0;
	pVih->bmiHeader.biClrImportant  = 0;
	pVih->bmiHeader.biClrUsed       = 0;
    pVih->bmiHeader.biCompression   = videoTypeFourcc;
	pVih->bmiHeader.biWidth         = m_settings.frameWidth;
	pVih->bmiHeader.biHeight        = m_settings.frameHeight;
	pVih->bmiHeader.biPlanes        = 1;
	pVih->bmiHeader.biSize          = 0;
	pVih->bmiHeader.biSizeImage     = 0;
	pVih->bmiHeader.biXPelsPerMeter = 0;
	pVih->bmiHeader.biYPelsPerMeter = 0;

    pVih->dwBitRate       = m_settings.bitrate;
    pVih->dwBitErrorRate  = 0;

    pVih->rcSource.bottom = 0;
	pVih->rcSource.left   = 0;
	pVih->rcSource.right  = 0;
	pVih->rcSource.top    = 0;
	pVih->rcTarget.bottom = 0;
	pVih->rcTarget.left   = 0;
	pVih->rcTarget.right  = 0;
	pVih->rcTarget.top    = 0;

    HTRENC_DEBUG_EXTRA( "CHtrEncFltr::GetMediaType Ok\n" );
	return S_OK;
}

HRESULT CHtrEncFltr::SetMediaType( PIN_DIRECTION direction, const CMediaType* pmt )
{
    // No action when setting input format, settings are already
    // incorporated in CheckInputType
    if( direction == PINDIR_INPUT ) return S_OK;

    // One assumes that SetMediaType is called after type has been checked,
    // so *no* duplicated check is done here!

    VIDEOINFOHEADER* vih = reinterpret_cast<VIDEOINFOHEADER*>(pmt->Format());
	BITMAPINFOHEADER* bh = &vih->bmiHeader;

    m_settings.videoType = *pmt->Subtype() == ENCOUTPUT_MP4V || *pmt->Subtype() == ENCOUTPUT_mp4v ?
                           CHantroEncoderWrapper::VIDEOTYPE_MPEG4 :
                           CHantroEncoderWrapper::VIDEOTYPE_H263;

    if( vih->AvgTimePerFrame != 0 )
    {
        m_settings.frameRate = (LONG)HTRENC_FRAMETIME2RATE(vih->AvgTimePerFrame);
        m_cachedAvgFrameTime = vih->AvgTimePerFrame;
    }

    if( vih->dwBitRate != 0 )
    {
        m_settings.bitrate = vih->dwBitRate;
    }

    HTRENC_DEBUG_EXTRA( "CHtrEncFltr::SetMediaType (diretion=%d) Ok\n", direction );
	return S_OK;
}


HRESULT CHtrEncFltr::Transform(IMediaSample* pIn, IMediaSample* pOut)
{
	HRESULT hr;
	BYTE* pInputBuffer;
	BYTE* pOutputBuffer;
	LONG outputBufSize;
	DWORD pInputBufferBusAddr, pOutputBufferBusAddr;
	REFERENCE_TIME start, end;
	BOOL keyFrame = FALSE;

	// Get the pointer to the input buffer & the physical address
	hr = pIn->GetPointer(&pInputBuffer);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to get the input buffer\n" );
		return hr;
	}

    // Get bus address for input buffer
	hr = ((CHtrEncInputPin*)m_pInput)->m_pHtrAlloc->MapToPhysicalAddr(pInputBuffer, &pInputBufferBusAddr);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to map the virtual address to physical\n" );
		return hr;
	}

	// Get the pointer to the output buffer, size of the output buffer & the physical address
	hr = pOut->GetPointer(&pOutputBuffer);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to get the output buffer\n" );
		return hr;
	}
	outputBufSize = pOut->GetSize();

    // Get bus address for output buffer
	hr = ((CHtrEncOutputPin*)m_pOutput)->m_pHtrAlloc->MapToPhysicalAddr(pOutputBuffer, &pOutputBufferBusAddr);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to map the virtual address to physical\n" );
		return hr;
	}
	
	// Get the timing for the sample
	hr = pIn->GetTime(&start, &end);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to get timing for the sample\n" );
		return hr;
	}
	
	// Encode the stream
	hr = m_pWrapper->Encode( pInputBufferBusAddr, &start, &end, pOutputBuffer, pOutputBufferBusAddr, &outputBufSize, &keyFrame );
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to encode the frame\n" );
		return hr;
	}

	// Set the timestamp according to start and end times
	hr = pOut->SetTime(&start, &end);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform setting the time stamp failed\n" );
		return hr;
	}

	hr = pOut->SetActualDataLength(outputBufSize);
	if( FAILED(hr) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::Transform failed to set actual data length\n" );
		return hr;
	}

	return S_OK;
}


HRESULT CHtrEncFltr::StartStreaming()
{
	// Get the downstream buffer to fill (downstream filter should be already running)
    IMediaSample* pOutSample;
	BYTE* pBuffer;
	LONG size;
	HRESULT hr;

    hr = m_pOutput->GetDeliveryBuffer( &pOutSample, NULL, NULL, 0 ); 
	if( FAILED(hr) )
    {
        HTRENC_DEBUG( "CHtrEncFltr::StartStreaming: FAILED getting delivery buffer for stream headers!\n" );
	    return hr;
	}

    size = pOutSample->GetSize();
	hr = pOutSample->GetPointer(&pBuffer);
	if( FAILED(hr) )
    {
        HTRENC_DEBUG( "CHtrEncFltr::StartStreaming: pOutSample->GetPointer FAILED!\n" );
		pOutSample->Release();
	    return hr;
	}

    // Create the encoder wrapper instance
    m_pWrapper = new CHantroEncoderWrapper();
    if( m_pWrapper == NULL )
    {
        HTRENC_DEBUG( "CHtrEncFltr::StartStreaming: FAILED creating encoder wrapper!\n" );
        return E_OUTOFMEMORY;
    }

	// Initialize the encoder
	hr = m_pWrapper->Init( &m_settings );
	if( FAILED(hr) )
	{
        HTRENC_DEBUG( "CHtrEncFltr::StartStreaming: pWrapper->Init FAILED!\n" );
		pOutSample->Release();
        return hr;
	}

	// Generate the stream headers and set the output correctly
	hr = m_pWrapper->StartStream( pBuffer, &size );
    if( FAILED(hr) )
    {
        HTRENC_DEBUG( "CHtrEncFltr::StartStreaming: pWrapper->StartStream FAILED!\n" );
		pOutSample->Release();
        return hr;
	}

    // Output only if headers were in fact generated
    if( size>0 )
    {
	    hr = pOutSample->SetActualDataLength(size);
	
	    // Deliver the sample downstream
	    hr = m_pOutput->Deliver( pOutSample );
	    if( FAILED(hr) )
	    {
            HTRENC_DEBUG( "CHtrEncFltr::StartStreaming: pOutSample->Deliver FAILED!\n" );
		    pOutSample->Release();
		    return hr;
	    }
    }

	// Release the sample
	pOutSample->Release();
	
    HTRENC_DEBUG_EXTRA( "CHtrEncFltr::StartStreaming: Ok!\n" );
	return S_OK;
}

HRESULT CHtrEncFltr::EndOfStream()
{
	// Get the downstream buffer
    IMediaSample* pOutSample;
	HRESULT hr;

    hr = m_pOutput->GetDeliveryBuffer( &pOutSample, NULL, NULL, 0 ); 
    if (FAILED(hr)) {
        return hr;
    }

	BYTE* pBuffer;
	LONG size;
	size = pOutSample->GetSize();
	hr = pOutSample->GetPointer(&pBuffer);
    if (FAILED(hr)) {
		pOutSample->Release();
        return hr;
    }

	hr = m_pWrapper->EndStream(pBuffer, &size);
	if( FAILED(hr) )
	{
		// Release the sample
		pOutSample->Release();
		return hr;
	}

    // Output only if "footers" were generated
	if( size>0 )
    {
        // Fix size for sample
	    hr = pOutSample->SetActualDataLength( size );

        // Deliver the sample downstream
    	hr = m_pOutput->Deliver( pOutSample );
    	if( FAILED(hr) )
    	{
		    // Release the sample
		    pOutSample->Release();
		    return hr;
	    }
    }

	// Release the sample
	pOutSample->Release();

    HTRENC_DEBUG_EXTRA( "CHtrEncFltr::EndOfStream Ok!\n" );
	return CTransformFilter::EndOfStream();
}

CBasePin* CHtrEncFltr::GetPin(int n)
{
    HRESULT hr = S_OK;

    // Test for input pin
    if(  n == 0 )
    {
        // Create pin if necessary
        if( m_pInput == NULL )
        {
            m_pInput = new CHtrEncInputPin( NAME("Hantro Encoder Input Pin"),
                                            this, &hr, L"HtrEnc In" );
        }

        // Workaround: make sure GetPin does not fail, otherwise the destruction of
        // the graph filter gets stucked.
        ASSERT( m_pInput && SUCCEEDED(hr) );

        // if( m_pInput == NULL )
        // {
        //     HTRENC_DEBUG( "CHtrEncFltr::GetPin: FAILED creating input pin (memory allocation?)\n" );
        //     return NULL;
        // }
        // if( FAILED(hr) )
        // {
        //     HTRENC_DEBUG( "CHtrEncFltr::GetPin: FAILED creating input pin (wrong parameters?)\n" );
        //     delete m_pInput;
        //     m_pInput = NULL;
        //     return NULL;
        // }

        HTRENC_DEBUG_EXTRA( "CHtrEncFltr::GetPin Ok!\n" );
        return m_pInput;
    }
    // Test output pin
    else if( n == 1 )
    {
        // Create pin if necessary
        if( m_pOutput == NULL )
        {
            m_pOutput = new CHtrEncOutputPin( NAME("Hantro Encoder Output Pin"),
                                                 this, &hr, L"HtrEnc Out" );
        }

        // Workaround: make sure GetPin does not fail, otherwise the destruction of
        // the graph filter gets stucked.
        ASSERT( m_pOutput && SUCCEEDED(hr) );

        // if( m_pOutput == NULL )
        // {
        //     HTRENC_DEBUG( "CHtrEncFltr::GetPin: FAILED creating output pin\n" );
        //     return NULL;
        // }
        // if( FAILED(hr) )
        // {
        //     HTRENC_DEBUG( "CHtrEncFltr::GetPin: FAILED creating output pin\n" );
        //     delete m_pOutput;
        //     m_pOutput = NULL;
        //     return NULL;
        // }

        HTRENC_DEBUG_EXTRA( "CHtrEncFltr::GetPin (n=1, outputPin) Ok!\n" );
        return m_pOutput;
    }

    HTRENC_DEBUG( "CHtrEncFltr::GetPin: FAILED, unkown pin index %d\n", n );
    return NULL;
}

/*------------------------------------------------------------------------------
    5. CHtrEncPhysicalAllocator class
------------------------------------------------------------------------------*/

CHtrEncPhysicalAllocator::CHtrEncPhysicalAllocator(HRESULT* phr)
: CBaseAllocator(NAME("Hantro Custom Physical Memory Allocator"), NULL, phr),
m_pMappingsList(NULL)
{
}

STDMETHODIMP CHtrEncPhysicalAllocator::NonDelegatingQueryInterface(REFIID iid, void **ppv)
{
    if (iid == IID_IHtrAllocator ) {
        return GetInterface(static_cast<IHtrAllocator*>(this), ppv);
    }
    return CBaseAllocator::NonDelegatingQueryInterface(iid,ppv);
}

HRESULT CHtrEncPhysicalAllocator::MapToPhysicalAddr(LPVOID pVirAddr, DWORD* pPhysAddr)
{
	Mapping* map;
	
	// Find the mapping
	map = FindMapping(pVirAddr);
	if( map != NULL )
	{
		*pPhysAddr = map->pPhysAddr;
		HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::MapToPhysicalAddr Ok\n" );
		return S_OK;	
	}

	// No mapping found 
    HTRENC_DEBUG( "CHtrEncPhysicalAllocator::MapToPhysicalAddr FAILED, no mapping from virtual to physical address found\n" );
	// Can't return E_FAIL because the graph will hang if we do
	return S_FALSE;
}

HRESULT CHtrEncPhysicalAllocator::AddMapping(LPVOID pVirAddr, DWORD physAddr)
{
	// Create a new mapping
	Mapping* mapping = new Mapping( pVirAddr, physAddr );
	if( NULL == mapping )
	{
	    HTRENC_DEBUG( "CHtrEncPhysicalAllocator::AddMapping FAILED, out of memory\n" );
		return E_OUTOFMEMORY;
	}

	// Add it to our list of mappings
	if( NULL == m_pMappingsList )
	{
		m_pMappingsList = mapping;
		HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::AddMapping Ok\n" );
		return S_OK;
	}
	Mapping* pNext = m_pMappingsList;
	while( pNext->p_next != NULL )
	{
		pNext = pNext->p_next;
	}
	pNext->p_next = mapping;
	HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::AddMapping Ok\n" );
	return S_OK;
}

CHtrEncPhysicalAllocator::Mapping* CHtrEncPhysicalAllocator::FindMapping(LPVOID pVirAddr)
{

⌨️ 快捷键说明

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