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

📄 videoenc.cpp

📁 mpeg4 video codec mpeg4 video codec
💻 CPP
字号:
//*@@@+++@@@@******************************************************************//// Copyright (C) Microsoft Corporation. All rights reserved.////*@@@---@@@@******************************************************************////  Interlace encoding mode is disabled by default.//  Interlace WMV 9 (4cc WMV3) bit streams should not//  currently be created in AVI, because AVI does not//  provide the ability to specify top-field-first or//  bottom-field-first at frame level. However, the code//  is provided in case the user may want to wrap interlace//  WMV 9 streams in other file formats.//#include "stdafx.h"#include <strmif.h>#include <amvideo.h>#include <uuids.h>#include <dvdmedia.h>#include <wmcodeciface.h>#include "wmsbuffer.h"#include "encappErr.h"#include "videoenc.h"#include "encode.h"//////////////////////////////////////////////////////////////////////////////HRESULT MakeVideoOutputType(IMediaObject   *pDMO,							AM_MEDIA_TYPE  *pmtIn,							VideoEncParams *pParams,							AM_MEDIA_TYPE  *pmt      ){	HRESULT             hr                   = S_OK;	VIDEOINFOHEADER2    *pvih2               = NULL;	VIDEOINFOHEADER     vih;	IWMCodecPrivateData *pWMCodecPrivateData = NULL;	DWORD               cbPrivateData        = 0;	BYTE                *pbPrivateData       = NULL;	BYTE                *pNewFormat          = NULL;	if( NULL == pDMO    ||		NULL == pmtIn   ||		NULL == pParams ||		NULL == pmt     )	{		return ( E_INVALIDARG );	}	if( NULL == pmtIn->pbFormat || pmtIn->cbFormat < sizeof( VIDEOINFOHEADER ) )	{		return ( E_INVALIDARG );	}	// make up a partial media type	pmt->majortype            = MEDIATYPE_Video;	pmt->formattype           = FORMAT_VideoInfo;	pmt->bFixedSizeSamples    = FALSE;	pmt->bTemporalCompression = TRUE;	if( pmtIn->formattype == FORMAT_VideoInfo )	{		vih = *(VIDEOINFOHEADER*)pmtIn->pbFormat;	}	else if( pmtIn->formattype == FORMAT_VideoInfo2 )	{		pvih2 = (VIDEOINFOHEADER2*)pmtIn->pbFormat;		vih.rcSource        = pvih2->rcSource;		vih.rcTarget        = pvih2->rcTarget;		vih.AvgTimePerFrame = pvih2->AvgTimePerFrame;		vih.bmiHeader       = pvih2->bmiHeader;	}	else		return ( E_VIDEO_INVALID_INPUT_TYPE );	vih.dwBitRate            = (DWORD)pParams->nBitrate;	vih.dwBitErrorRate       = 0;	vih.bmiHeader.biPlanes   = 1;	vih.bmiHeader.biBitCount = 24;	pmt->subtype = WMCMEDIASUBTYPE_WMV1;	pmt->subtype.Data1=pParams->dwTag;	vih.bmiHeader.biCompression = pParams->dwTag;	//	//use the partial format above to get the private data	//	pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof( VIDEOINFOHEADER));	memcpy( pmt->pbFormat , &vih, sizeof( VIDEOINFOHEADER));	pmt->cbFormat = sizeof( vih );	do	{		hr = pDMO->QueryInterface(IID_IWMCodecPrivateData, (void**)&pWMCodecPrivateData);		if( FAILED( hr ) )		{			hr = E_NO_PRIVATE_DATA;			break;		}		hr = pWMCodecPrivateData->SetPartialOutputType( pmt );		if( FAILED( hr ) )		{			hr = E_PARTIAL_TYPE_REJECTED;			break;		}		hr = pWMCodecPrivateData->GetPrivateData( NULL, &cbPrivateData );		if( FAILED( hr ) )		{			hr = E_NO_PRIVATE_DATA_COUNT;			break;		}		if( 0 == cbPrivateData )		{ // No private data			hr = S_OK;			break;		}		pbPrivateData = new BYTE[ cbPrivateData ];		if( pbPrivateData == NULL )		{			hr = E_OUTOFMEMORY;			break;		}		//		// get the private data		//		hr = pWMCodecPrivateData->GetPrivateData( pbPrivateData, &cbPrivateData );		if( FAILED( hr ) )		{			hr = E_PRIVATE_DATA_FAILED;			break;		}		//		//modify the media type accordingly		//		pNewFormat = (BYTE*)CoTaskMemAlloc( sizeof( VIDEOINFOHEADER) + cbPrivateData );		if( NULL == pNewFormat )		{			hr = E_OUTOFMEMORY;			break;		}		memcpy( pNewFormat, pmt->pbFormat, sizeof( VIDEOINFOHEADER));		CoTaskMemFree(pmt->pbFormat);		memcpy( pNewFormat + sizeof( VIDEOINFOHEADER), pbPrivateData, cbPrivateData);		pmt->pbFormat = pNewFormat;		pmt->cbFormat = sizeof( VIDEOINFOHEADER) + cbPrivateData;		((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biSize         += cbPrivateData;		((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biClrUsed       = 0;		((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biClrImportant  = 0;		((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biXPelsPerMeter = 0;		((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biYPelsPerMeter = 0;	}	while( FALSE );	SAFERELEASE( pWMCodecPrivateData );	SAFEDELETE( pbPrivateData );	return ( hr );}//////////////////////////////////////////////////////////////////////////////HRESULT SetVideoTypes( IMediaObject   *pDMO,    \					  AM_MEDIA_TYPE  *pmtIn,   \					  VideoEncParams *pParams, \					  AM_MEDIA_TYPE  *pmtOut,  \					  DWORD *pcbIn,            \					  DWORD *pcbOut ){	HRESULT hr;	DWORD   dwDummy;	hr = pDMO->SetInputType(0, pmtIn, 0);	if( S_OK != hr )	{		return ( hr );	}	hr = MakeVideoOutputType( pDMO, pmtIn, pParams, pmtOut );	if( FAILED( hr ) )	{		return ( hr );	}	hr = pDMO->SetOutputType(0, pmtOut, 0);	if( S_OK != hr )	{		return ( hr );	}	hr = pDMO->GetInputSizeInfo( 0, pcbIn, &dwDummy, &dwDummy);	if( FAILED(hr) )	{		return ( hr );	}	hr = pDMO->GetOutputSizeInfo( 0, pcbOut, &dwDummy);	if( FAILED( hr ) )	{		return ( hr );	}	return ( hr == S_FALSE ? E_VIDEO_TYPE_NOT_SET: hr );}//////////////////////////////////////////////////////////////////////////////HRESULT SetVideoParams( IMediaObject *pDMO, VideoEncParams *pParams ){	HRESULT      hr;	VARIANT      varg;	IPropertyBag *pPropertyBag = NULL;	if( NULL == pDMO || NULL == pParams )	{		return ( E_INVALIDARG );	}	do	{		//		// Get the IPropertyBag IF and set the appropriate params		//		hr = pDMO->QueryInterface(IID_IPropertyBag, (void**)&pPropertyBag);		if( FAILED( hr ) )		{			break;		}		//		//set the encoder in VBR mode if required		//		if( pParams->fIsVBR == TRUE )		{			::VariantInit(&varg);			varg.vt      = VT_BOOL;			varg.boolVal = TRUE;			hr = pPropertyBag->Write( g_wszWMVCVBREnabled, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_VBR_NOT_SUPPORTED;				break;			}			//			// if it is 1 pass VBR set the Quality param			//			if( pParams->nPasses == 1 )			{				::VariantInit(&varg);				varg.vt = VT_I4;				varg.lVal = pParams->nVBRQuality;				hr = pPropertyBag->Write( g_wszWMVCVBRQuality, &varg );				if( FAILED( hr ) )				{					hr = E_VBR_QUALITY_REJECTED;					break;				}			}		}		//		//set the number of passes		//		if( pParams->nPasses > 1 )		{			::VariantInit(&varg);			varg.vt   = VT_I4;			varg.lVal = pParams->nPasses;			hr = pPropertyBag->Write( g_wszWMVCPassesUsed, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_NPASS_NOT_SUPPORTED;				break;			}		}		//		// set the bitrate for all the modes except 1 pass VBR		//		if( !( pParams->fIsVBR == TRUE && pParams->nPasses == 1 ) )		{			::VariantInit(&varg);			varg.vt = VT_I4;			varg.lVal = pParams->nBitrate;			hr = pPropertyBag->Write( g_wszWMVCAvgBitrate, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_BITRATE_REJECTED;				break;			}		}		//		// set the buffer window		//		::VariantInit(&varg);		varg.vt = VT_I4;		varg.lVal = pParams->nBufferDelay;		hr = pPropertyBag->Write( g_wszWMVCVideoWindow, &varg );		if( FAILED( hr ) )		{			hr = E_VIDEO_BUFFER_REJECTED;			break;		}		if( pParams->fIsConstrained == TRUE )		{			::VariantInit(&varg);			varg.vt   = VT_I4;			varg.lVal = pParams->nPeakBitrate;			hr = pPropertyBag->Write( g_wszWMVCMaxBitrate, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_PEAK_BITRATE_REJECTED;				break;			}			::VariantInit(&varg);			varg.vt   = VT_I4;			varg.lVal = pParams->nPeakBuffer;			hr = pPropertyBag->Write( g_wszWMVCBMax, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_PEAK_BUFFER_REJECTED;				break;			}		}		//		// set the profile for WMV# only		//		hr = S_OK;		BSTR bstrIn=NULL;		if( pParams->dwTag == WMCFOURCC_WMV3 )		{			switch( pParams->nProfile )			{			case P_MAIN:				bstrIn = ::SysAllocString(L"MP");				break;			case P_SIMPLE:				bstrIn = ::SysAllocString(L"SP");				break;			case P_COMPLEX:				bstrIn = ::SysAllocString(L"CP");				break;			default:				hr = E_VIDEO_INVALID_PROFILE;				break;			}			if( FAILED( hr ) ) break;			::VariantInit(&varg);			varg.vt      = VT_BSTR;			varg.bstrVal = bstrIn;			hr = pPropertyBag->Write( g_wszWMVCDecoderComplexityRequested, &varg );			::SysFreeString( bstrIn );			if( FAILED( hr ) )			{				hr = E_VIDEO_PROFILE_REJECTED;				break;			}		}		//		// set the complexity param		//		::VariantInit(&varg);		varg.vt = VT_I4;		varg.lVal = pParams->nComplexity;		hr = pPropertyBag->Write( g_wszWMVCComplexityEx, &varg );		if( FAILED( hr ) )		{			hr = E_VIDEO_KEYDIST_REJECTED;			break;		}		//		// set the max distance between the key frames		//		::VariantInit(&varg);		varg.vt = VT_I4;		varg.lVal = pParams->nKeyDist;		hr = pPropertyBag->Write( g_wszWMVCKeyframeDistance, &varg );		if( FAILED( hr ) )		{			hr = E_VIDEO_KEYDIST_REJECTED;			break;		}		//		// set the crispness params for WMV# only		//		if( pParams->dwTag == WMCFOURCC_WMV3 || pParams->dwTag == WMCFOURCC_WMV2 || pParams->dwTag == WMCFOURCC_WMV1 )		{			::VariantInit(&varg);			varg.vt = VT_I4;			varg.lVal = pParams->nCrisp;			hr = pPropertyBag->Write( g_wszWMVCCrisp, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_CRISPNESS_REJECTED;				break;			}		}		if ( pParams->fIsVBR)		{			::VariantInit(&varg);			varg.vt = VT_I4;			varg.lVal = pParams->nQuality;			hr = pPropertyBag->Write( g_wszWMVCVBRQuality, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_QUALITY_REJECTED;				break;			}		}  #ifdef SUPPORT_INTERLACE		//		// set the interlace mode for WMV# only		//		if( pParams->dwTag == WMCFOURCC_WMV3 && pParams->fIsInterlaced)		{			::VariantInit(&varg);			varg.vt = VT_BOOL;			varg.boolVal = TRUE;			hr = pPropertyBag->Write( g_wszWMVCInterlacedCodingEnabled, &varg );			if( FAILED( hr ) )			{				hr = E_VIDEO_INTERLACE_REJECTED;				break;			}		}#endif //SUPPORT_INTERLACE	}	while( FALSE );	SAFERELEASE( pPropertyBag );	return ( hr );}//////////////////////////////////////////////////////////////////////////////// a decent guess would be 0.4 bits per pixelHRESULT DefaultVideoBitrate( AM_MEDIA_TYPE *pmt, double dFramesPerSec, int *pBitrate ){	if( NULL == pmt || NULL == pBitrate )	{		return ( E_INVALIDARG );	}	if( NULL == pmt->pbFormat || pmt->cbFormat <= 0 )	{		return ( E_INVALIDARG );	}	if( FORMAT_VideoInfo == pmt->formattype )	{		VIDEOINFOHEADER *pvih = (VIDEOINFOHEADER*)pmt->pbFormat;		*pBitrate = ( pvih->bmiHeader.biWidth * pvih->bmiHeader.biHeight * 2 ) / 5;		if( dFramesPerSec == 0 )		{ // use the input rate			if( pvih->AvgTimePerFrame > 0 )			{				dFramesPerSec = 10000000.0 / pvih->AvgTimePerFrame;			}			else			{				dFramesPerSec = 29.97;   // 30 frames per sec			}		}	}	else if( FORMAT_VideoInfo2 == pmt->formattype  )	{		VIDEOINFOHEADER2 *pvih = (VIDEOINFOHEADER2*)pmt->pbFormat;		*pBitrate = ( pvih->bmiHeader.biWidth * pvih->bmiHeader.biHeight * 2 ) / 5;		if( dFramesPerSec == 0 )		{ // use the input rate			if( pvih->AvgTimePerFrame > 0 )			{				dFramesPerSec = 10000000.0 / pvih->AvgTimePerFrame;			}			else			{				dFramesPerSec = 29.97;   // 30 frames per sec			}		}	}	else	{		return ( E_VIDEO_INVALID_INPUT_TYPE );	}	*pBitrate = (int)( *pBitrate * dFramesPerSec );	return ( S_OK );}//////////////////////////////////////////////////////////////////////////////HRESULT InitializeVideoEncoder(  AM_MEDIA_TYPE      *pmtInput,							   VideoEncParams       *pParams,							   IMediaObject         **ppDMO,							   AM_MEDIA_TYPE        *pmtOutput,							   CHandlingMediaBuffer *pMediaBuffer ){	HRESULT       hr             = S_OK;	DWORD         cbInputBuffer  = 0;	DWORD         cbOutputBuffer = 0;	if( NULL == pmtInput || NULL == pParams || NULL == ppDMO )	{		return ( E_INVALIDARG );	}#ifdef SUPPORT_INTERLACE	//	// Interlace encoding using IYUV or I420 at the input is not supported	//	if( NULL == pmtInput->pbFormat )	{		return ( E_INVALIDARG );	}	if( WMCFOURCC_IYUV == ((VIDEOINFOHEADER*)pmtInput->pbFormat)->bmiHeader.biCompression ||		WMCFOURCC_I420 == ((VIDEOINFOHEADER*)pmtInput->pbFormat)->bmiHeader.biCompression )	{		if( TRUE == pParams->fIsInterlaced )		{			return ( E_VIDEO_INTERLACE_REJECTED );		}	}#endif //SUPPORT_INTERLACE	*ppDMO = NULL;	//	//check to see if the video bitrate has been set; if not calculate the default	//	if( pParams->nBitrate <= 0 )	{		hr = DefaultVideoBitrate( pmtInput, pParams->dFrameRate, &pParams->nBitrate );		if( FAILED( hr ) )		{			return ( hr );		}		if( pParams->nPeakBitrate <= 0 )		{			pParams->nPeakBitrate = 3 * pParams->nBitrate;		}	}	do	{		//		// Create the DMO Encoder		//		CLSID clsid=CLSID_NULL;		char fcc[]="1234";memcpy(fcc,&pParams->dwTag,4);		switch (pParams->dwTag)		{		case WMCFOURCC_MSS1:		case WMCFOURCC_MSS2:			clsid=CLSID_CMSSCEncMediaObject2;			break;		case WMCFOURCC_WMVA:		case WMCFOURCC_WVP2:			clsid=CLSID_CWMV9EncMediaObject;			break;		case WMCFOURCC_WMV1:		case WMCFOURCC_WMV2:		case WMCFOURCC_WMV3:		case WMCFOURCC_WMVP:		case WMCFOURCC_MP4S:		case WMCFOURCC_MP43:		default:			clsid=CLSID_CWMVEncMediaObject2;			break;		}  		hr = CoCreateInstance( clsid,			NULL,			CLSCTX_INPROC_SERVER,			IID_IMediaObject,			(void**)ppDMO);		if( FAILED( hr ) )		{			break;		}		hr = SetVideoParams( *ppDMO, pParams );		if( FAILED( hr ) )		{			break;		}		hr = SetVideoTypes( *ppDMO, pmtInput, pParams, pmtOutput, &cbInputBuffer, &cbOutputBuffer );		if( FAILED( hr ) )		{			break;		}#ifdef SUPPORT_INTERLACE		if( pParams->dwTag == WMCFOURCC_WMV3 && pParams->fIsInterlaced)		{			INSSBuffer3 *pINSSBuffer3 = NULL;			BYTE        bType         = WM_CT_INTERLACED;			hr = pMediaBuffer->QueryInterface( IID_INSSBuffer3, (void**)&pINSSBuffer3 );			if( FAILED( hr ) )			{				break;			}			pINSSBuffer3->SetProperty( WM_SampleExtension_ContentType,				&bType,				1 );			SAFERELEASE( pINSSBuffer3 );		}#endif //SUPPORT_INTERLACE	}	while ( FALSE );	if( S_OK != hr )	{		SAFERELEASE( *ppDMO );	}	return ( hr );}

⌨️ 快捷键说明

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