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

📄 htrencftr.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------------
--                                                                            --
--       This software is confidential and proprietary and may be used        --
--        only as expressly authorized by a licensing agreement from          --
--                                                                            --
--                            Hantro Products Oy.                             --
--                                                                            --
--      In the event of publication, the following notice is applicable:      --
--                                                                            --
--                   (C) COPYRIGHT 2005 HANTRO PRODUCTS OY                    --
--                            ALL RIGHTS RESERVED                             --
--                                                                            --
--          The entire notice above must be reproduced on all copies.         --
--                                                                            --
--------------------------------------------------------------------------------
--
--  Abstract : Transform filter for Hantro HW encoder in DirectShow integration
--
-------------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------

    Table of context

    1. Include headers
    2. Module defines
    3. DLL entry points
    4. CHtrEncFltr class
    5. CHtrEncPhysicalAllocator class
    6. CHtrEncInputPin class
    7. CHtrEncOutputPin class

------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    1. Include headers
------------------------------------------------------------------------------*/

#include "stdafx.h"
#include <stdio.h>
#include "htrencftr.h"
#include "htrencwrapper.h"
#ifdef UNDER_CE
#include "pkfuncs.h" // For AllocPhysMem
#endif /* UNDER_CE */

/*------------------------------------------------------------------------------
    2. Module defines
------------------------------------------------------------------------------*/

#define HTRENC_DEBUG            printf
#define HTRENC_DEBUG_EXTRA      //printf

//  t = frameDuration            ; REFERENCE_TIME, 100ns units (10.000.000 units in 1s)
// fr = 10.000.000 / (t/1000)    ; frame/1000s
// fr = (fr+999)/1000            ; rounded frame/s
#define HTRENC_FRAMETIME2RATE(t)   ( ((REFERENCE_TIME)10000000000 / (REFERENCE_TIME)(t) + 999)/1000 )

// r = frameRate                 ; frame/s
// t = 10.000.000/r              ; duration, in 100ns units
#define HTRENC_FRAMERATE2TIME(r)   ((REFERENCE_TIME)10000000/(REFERENCE_TIME)(r))

static const WCHAR g_wszName[] = L"Hantro MPEG-4/H.263 Video Encoder Filter";

AMOVIESETUP_MEDIATYPE inputMediaTypes[] = {
    { &MEDIATYPE_Video, &MEDIASUBTYPE_IYUV }
};

AMOVIESETUP_MEDIATYPE outputMediaTypes[] = {
    { &MEDIATYPE_Video, &ENCOUTPUT_MP4V }, // MPEG-4
    { &MEDIATYPE_Video, &ENCOUTPUT_mp4v }, // mpeg-4
    { &MEDIATYPE_Video, &ENCOUTPUT_H263 }, // H.263
    { &MEDIATYPE_Video, &ENCOUTPUT_h263 }  // h.263
};

AMOVIESETUP_PIN inputPin = {
    L"",            // Obsolete, not used.
    FALSE,          // Is this pin rendered?
    FALSE,          // Is it an output pin?
    FALSE,          // Can the filter create zero instances?
    FALSE,          // Does the filter create multiple instances?
    &GUID_NULL,     // Obsolete.
    NULL,           // Obsolete.
    1,              // Number of media types.
    inputMediaTypes   // Pointer to media types.
};

AMOVIESETUP_PIN outputPin = {
    L"",            // Obsolete, not used.
    FALSE,          // Is this pin rendered?
    TRUE,           // Is it an output pin?
    FALSE,          // Can the filter create zero instances?
    FALSE,          // Does the filter create multiple instances?
    &GUID_NULL,     // Obsolete.
    NULL,           // Obsolete.
    4,              // Number of media types.
    outputMediaTypes   // Pointer to media types.
};

AMOVIESETUP_PIN pins[2] = 
{
	inputPin,
	outputPin
};

AMOVIESETUP_FILTER encFilterReg = {
    &CLSID_HtrEncFltr,      // Filter CLSID.
    g_wszName,              // Filter name.
    MERIT_NORMAL,           // Merit.
    2,                      // Number of pin types.
    pins					// Pointer to pin information.
};

#ifndef UNDER_CE
// Declare filter information.
REGFILTER2 rf2EncFilterReg = {
    1,                // Version number.
    MERIT_NORMAL,	  // Merit.
    2,                // Number of pins.
    pins			  // Pointer to pin information.
};
#endif /* UNDER_CE */

CFactoryTemplate g_Templates[1] = 
{
    { 
      L"Hantro MPEG-4/H.263 Video Encoder Filter", // Name
      &CLSID_HtrEncFltr,                           // CLSID
      CHtrEncFltr::CreateInstance,                 // Method to create an instance of CHtrEncFltr
      NULL,                                        // Initialization function
      &encFilterReg                                // Set-up information (for filters)
    }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);    

/*------------------------------------------------------------------------------
    2. DLL entry points
------------------------------------------------------------------------------*/

// Entry point for the DLL
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

STDAPI DllRegisterServer()
{
    HRESULT hr = AMovieDllRegisterServer2( TRUE );
    if (FAILED(hr))
    {
        return hr;
    }
#ifndef UNDER_CE
    IFilterMapper2 *pFM2 = NULL;
    hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            IID_IFilterMapper2, (void **)&pFM2);
    if (SUCCEEDED(hr))
    {
        hr = pFM2->RegisterFilter(
            CLSID_HtrEncFltr,                // Filter CLSID. 
            g_wszName,                       // Filter name.
            NULL,                            // Device moniker. 
            &CLSID_VideoCompressorCategory,  // Video compressor category.
            g_wszName,                       // Instance data.
            &rf2EncFilterReg                 // Filter information.
            );
        pFM2->Release();
    }
#endif /* UNDER_CE */
	return hr;
}

STDAPI DllUnregisterServer()
{
    HRESULT hr = AMovieDllRegisterServer2(FALSE);
    if (FAILED(hr))
    {
        return hr;
    }
#ifndef UNDER_CE
    IFilterMapper2 *pFM2 = NULL;
    hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            IID_IFilterMapper2, (void **)&pFM2);
    if (SUCCEEDED(hr))
    {
        hr = pFM2->UnregisterFilter(&CLSID_VideoCompressorCategory, 
            g_wszName, CLSID_HtrEncFltr);
        pFM2->Release();
    }
#endif /* UNDER_CE */
    return hr;
}

/*------------------------------------------------------------------------------
    4. CHtrEncFltr class
------------------------------------------------------------------------------*/
// Public method that returns a new instance. 
CUnknown * WINAPI CHtrEncFltr::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
{
    CHtrEncFltr* pNewEnc = new CHtrEncFltr(NAME("Hantro MPEG-4/H.263 Video Encoder Filter"), pUnk, pHr);
    if (pNewEnc == NULL) {
        *pHr = E_OUTOFMEMORY;
    }
    return pNewEnc;
} 

CHtrEncFltr::CHtrEncFltr(TCHAR* pObjectName, LPUNKNOWN pUnk, HRESULT *pHr)
: CTransformFilter(pObjectName, pUnk, CLSID_HtrEncFltr)
, m_pWrapper(NULL), m_cachedAvgFrameTime(0)
{
    // Set default encoding settings, overridable by output and/or input pin.
    // Frame rate is taken from input format, if present, and also exposed
    // on output pin for correct settings. Video size must be taken from
    // from input format.
    m_settings.videoType        = CHantroEncoderWrapper::VIDEOTYPE_MPEG4;  
   // m_settings.videoType        = CHantroEncoderWrapper::VIDEOTYPE_H263;
    m_settings.bitrate          = 384000;
    m_settings.frameRate        = 30;
    m_settings.intraRefreshRate = 90;

	HTRENC_DEBUG_EXTRA( "CHtrEncFltr::CHtrEncFltr Ok\n" );
}

CHtrEncFltr::~CHtrEncFltr(void)
{
	delete m_pWrapper;
}

HRESULT CHtrEncFltr::CheckInputType(const CMediaType* mtIn)
{
	// Check that input type is video of IYUV format
	if( *mtIn->Type()    != *((GUID*)inputMediaTypes[0].clsMajorType) ||
        *mtIn->Subtype() != *((GUID*)inputMediaTypes[0].clsMinorType)  )
    {
        HTRENC_DEBUG( "CHtrEncFltr::CheckInputType FAILED, input major or subtype mismatch\n" );
        return VFW_E_TYPE_NOT_ACCEPTED;
    }

	// Check the format type (could be that it is not defined as well)
	if( !mtIn->IsPartiallySpecified() )
    {
        const GUID* formatType = mtIn->FormatType();
		if( *formatType != FORMAT_VideoInfo )
		{		
	        HTRENC_DEBUG( "CHtrEncFltr::CheckInputType FAILED, invalid format description\n" );
			return VFW_E_TYPE_NOT_ACCEPTED;
        }

        VIDEOINFOHEADER* vih = reinterpret_cast<VIDEOINFOHEADER*>(mtIn->Format());
		BITMAPINFOHEADER bh = vih->bmiHeader;
		HRESULT hr = S_OK;

		// Double check color space 'iyuv' (FourCC)
		if( bh.biCompression != MAKEFOURCC('I', 'Y', 'U', 'V') &&
			bh.biCompression != MAKEFOURCC('i', 'y', 'u', 'v') )
		{
			HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, invalid compression type in format description\n" );
			return VFW_E_TYPE_NOT_ACCEPTED;
		}

        // Validate and use settings from input format: video size and frame rate (if present).
        // Important! Default values for encoder settings must be carefuly chosen as validation
        // is done using new input settings *and* default values

        CHantroEncoderWrapper::Settings inputSettings = m_settings;

        inputSettings.frameWidth  = bh.biWidth;
        inputSettings.frameHeight = bh.biHeight;

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

        hr = CHantroEncoderWrapper::ValidateSettings( &inputSettings );
        if( FAILED(hr) )
        {
            HTRENC_DEBUG( "CHtrEncFltr::CheckInputType FAILED, invalid video size and/or frame rate\n" );
	    	return VFW_E_TYPE_NOT_ACCEPTED;
    	}

        // Incorporate new encoder settings and make a cache copy of
        // avgTimePerFrame to avoid rounding errors
        m_settings = inputSettings;
        m_cachedAvgFrameTime = vih->AvgTimePerFrame;
    }

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

HRESULT CHtrEncFltr::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
{
	// Firstly validate the input
	if( FAILED(CheckInputType(mtIn)) )
	{
	    HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, input type mismatch\n" );
		return VFW_E_TYPE_NOT_ACCEPTED;
	}

	// Check that desired output type is either MPEG-4 or H.263
	for( int i=0; i<sizeof(inputMediaTypes)/sizeof(inputMediaTypes[0]); i++ )
	{
		if( *mtOut->Type()    == *((GUID*)outputMediaTypes[i].clsMajorType) ||
		    *mtOut->Subtype() == *((GUID*)outputMediaTypes[i].clsMinorType)  )
		{
			if( !mtOut->IsPartiallySpecified() )
			{
				const GUID* formatType = mtOut->FormatType();
				if( *formatType == FORMAT_VideoInfo )
				{		
					VIDEOINFOHEADER* vih = reinterpret_cast<VIDEOINFOHEADER*>(mtOut->Format());
					BITMAPINFOHEADER& bh = vih->bmiHeader;

                    // We'll ignore the biCompression flag in the bitmap header as the
					// submediatype is more reliable and it has been checked already.

					// Compare source & target rectangles (only cropping allowed, no scaling)
					// Format should be video info(verified in checkinputtype), let's assert to be sure
					ASSERT(mtIn->formattype == FORMAT_VideoInfo);
					RECT rcImg;
				    BITMAPINFOHEADER *pBmiOut = HEADER(mtOut->pbFormat);
					BITMAPINFOHEADER *pBmiIn = HEADER(mtIn->pbFormat);
					SetRect(&rcImg, 0, 0, m_settings.frameWidth, m_settings.frameHeight);
					RECT *prcSrc = &((VIDEOINFOHEADER*)(mtIn->pbFormat))->rcSource;
					RECT *prcTarget = &((VIDEOINFOHEADER*)(mtOut->pbFormat))->rcTarget;
					// Cropping should be allowed, not allowed at the moment
					// Currently we allow no scaling or cropping
					if (!IsRectEmpty(prcSrc) && !EqualRect(prcSrc, &rcImg))
					{
						HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, no cropping allowed\n" );
						return VFW_E_TYPE_NOT_ACCEPTED;
					}
					if (!IsRectEmpty(prcTarget) && !EqualRect(prcTarget, &rcImg))
					{
						HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, no scaling allowed\n" );
						return VFW_E_TYPE_NOT_ACCEPTED;
    				}					

                    // Check video type, bitrate and frame rate settings but do *not* set them
                    CHantroEncoderWrapper::Settings checkSettings = m_settings;

                    checkSettings.videoType = bh.biCompression == MAKEFOURCC('M', 'P', '4', 'V') ||
						                      bh.biCompression == MAKEFOURCC('m', 'p', '4', 'v')  ?
                                              CHantroEncoderWrapper::VIDEOTYPE_MPEG4              :
                                              CHantroEncoderWrapper::VIDEOTYPE_H263;

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

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

                    HRESULT hr = CHantroEncoderWrapper::ValidateSettings( &checkSettings );
                    if( FAILED(hr) )
                    {
                        HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, invalid video type, bit and/or frame rate\n" );
	    	            return VFW_E_TYPE_NOT_ACCEPTED;
    	            }

					// Everything OK, let's accept this
					HTRENC_DEBUG_EXTRA( "CHtrEncFltr::CheckTransform Ok\n" );
					return S_OK;
				}
				else
				{
				    HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, invalid format description\n" );
					return VFW_E_TYPE_NOT_ACCEPTED;
				}
			}
			else
			{
				// If format is not specified, don't accept the type
				HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, no format description\n" );
				return S_OK;
			}
		}
	}
	
	HTRENC_DEBUG( "CHtrEncFltr::CheckTransform FAILED, transform type mismatch\n" );
	return VFW_E_TYPE_NOT_ACCEPTED;
}

HRESULT CHtrEncFltr::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* ppropInputRequest)
{
    // Ask minimum size for output stream buffer from encoder wrapper, based
    // on current encoding settings
    LONG minOutputStreamSize;
    HRESULT hr = CHantroEncoderWrapper::GetMinOutputStreamSize( &m_settings, &minOutputStreamSize );
    if( FAILED(hr) )
    {
        HTRENC_DEBUG( "CHtrEncFltr::DecideBufferSize: GetMinOutputStreamSize FAILED, wrong settings?\n" );
        return E_FAIL;
    }

    ALLOCATOR_PROPERTIES pReq, pAct;
	pReq.cbAlign  = 1;
	pReq.cbBuffer = minOutputStreamSize;
	pReq.cBuffers = 1;
	pReq.cbPrefix = 0;

    // Setup allocator with buffer requirements
    hr = pAlloc->SetProperties(&pReq, &pAct);
    if( FAILED(hr) )
    {
        HTRENC_DEBUG( "CHtrEncFltr::DecideBufferSize: Allocator SetProperties FAILED!\n" );
        return hr;
    }

    // Check properties actually set
    if( pAct.cbBuffer < minOutputStreamSize )
    {
        HTRENC_DEBUG_EXTRA( "CHtrEncFltr::DecideBufferSize WARNING: stream buffer size smaller than required (%d<%d)\n", pAct.cbBuffer, minOutputStreamSize );
        // Not a critical error, encoder wrapper *may* be able to use smaller buffer
    }
    
    HTRENC_DEBUG_EXTRA( "CHtrEncFltr::DecideBufferSize Ok\n" );
    return S_OK;
}

HRESULT CHtrEncFltr::GetMediaType(int iPosition, CMediaType* pMediaType)
{
    if( iPosition > 0 )
    {
        HTRENC_DEBUG_EXTRA( "CHtrEncFltr::GetMediaType: WARNING, received invalid iPosition\n" );

⌨️ 快捷键说明

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