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

📄 ff_wmv9.cpp

📁 mpeg4 video codec mpeg4 video codec
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"#include "ff_wmv9.h"#include "GenProfile_lib.h"#include "writerSink.h"#include "Twmv9dll.h"#include <strmif.h>#include <mediaobj.h>#include "encode.h"#include "encappErr.h"#include "videoenc.h"#include <uuids.h>#include <amvideo.h>#include "../imgFilters/ffImgfmt.h"#include <initguid.h>#include "ffdshow_mediaguids.h"#ifdef __GNUC__#include "strmiids.cpp"#elseDEFINE_GUID(IID_IMediaObject,0xd8ad0f58,0x5494,0x4102,0x97,0xc5,0xec,0x79,0x8e,0x59,0xbc,0xf4);DEFINE_GUID(MEDIASUBTYPE_IYUV,0x56555949,0x0,0x10,0x80,0x0,0x0,0xAA,0x0,0x38,0x9B,0x71);#endif#if DEBUG#define DEBUGS(s) OutputDebugString(s)#else#define DEBUGS(s)#endif#if defined(_DEBUG)#include <stdio.h>	/* vsprintf */#define DPRINTF_BUF_SZ  1024static __inline void DPRINTF(char *fmt, ...){	va_list args;	char buf[DPRINTF_BUF_SZ];	va_start(args, fmt);	vsprintf(buf, fmt, args);	OutputDebugString(buf);}#elsestatic __inline void DPRINTF(char *fmt, ...) { }#endifusing namespace std;bool operator <(const Tff_wmv9codecInfo &c1,const Tff_wmv9codecInfo &c2){	return stricmp(c1.name,c2.name)<0;}struct Tff_wmv9 :public Iff_wmv9{private:	Tff_wmv9cfg cfg;	IWMProfile *pProfile;	IWMCodecInfo3 *m_pCodecInfo;	IWMWriter *pWMWriter;	IWMWriterAdvanced *pWMWriterA;	IWMWriterFileSink *filesink;	TmyWriterSink *mysink;	int wrinputnum;	bool ok,writing;	std::vector<Tff_wmv9codecInfo> codecs;	Twmv9dll *wmv9dll;public:	Tff_wmv9(void) 	{		ok=false;		pProfile=NULL;m_pCodecInfo=NULL;		pWMWriter=NULL;pWMWriterA=NULL;		mysink=NULL;filesink=NULL;		memset(&cfg,0,sizeof(cfg));		wmv9dll=new Twmv9dll;		if (!wmv9dll->ok) return;#define JIF(x) if (FAILED(hr=(x))) {DEBUGS(_l("FAILED in ")_l(#x)_l("\n"));return;}		HRESULT hr;		JIF(EnsureIWMCodecInfo3(wmv9dll,&m_pCodecInfo)); 		DWORD codecCount;		m_pCodecInfo->GetCodecInfoCount(WMMEDIATYPE_Video,&codecCount);		for (DWORD i=0;i<codecCount;i++)		{			WCHAR codecName[1024];			DWORD codecNameLength=1024;			if (SUCCEEDED(m_pCodecInfo->GetCodecName(WMMEDIATYPE_Video,i,codecName,&codecNameLength)))			{				codecName[codecNameLength]=L'\0'; // terminate the codec name, just in case				Tff_wmv9codecInfo info;memset(&info,0,sizeof(info));				info.index=i;				//WideCharToMultiByte(CP_ACP,0,codecName,-1,info.name,256,NULL,NULL);				strcpy(info.name,text<char_t>(codecName));				WMT_ATTR_DATATYPE type;				BOOL isVBR;DWORD isVBRsize=sizeof(isVBR);				if (SUCCEEDED(m_pCodecInfo->GetCodecProp(WMMEDIATYPE_Video,i,g_wszIsVBRSupported,&type,(BYTE*)&isVBR,&isVBRsize)))					info.vbr=isVBR;				DWORD cmplxMax,cmplxMaxSize=sizeof(cmplxMax);				if (SUCCEEDED(m_pCodecInfo->GetCodecProp(WMMEDIATYPE_Video,i,g_wszComplexityMax,&type,(BYTE*)&cmplxMax,&cmplxMaxSize)))					info.cmplxMax=cmplxMax;				DWORD codecformatcount=0;				m_pCodecInfo->GetCodecFormatCount(WMMEDIATYPE_Video,i,&codecformatcount);				for (unsigned int j=0;j<min(DWORD(1),codecformatcount);j++)				{					IWMStreamConfig *wsc=NULL;					WCHAR desc[256];DWORD desclen=256;					if (SUCCEEDED(m_pCodecInfo->GetCodecFormatDesc(WMMEDIATYPE_Video,i,j,&wsc,desc,&desclen)))					{						IWMMediaProps *mp=NULL;						if (SUCCEEDED(wsc->QueryInterface(IID_IWMMediaProps,(void**)&mp)))						{							DWORD typelen=0;							if (SUCCEEDED(mp->GetMediaType(NULL,&typelen)) && typelen!=0)							{								WM_MEDIA_TYPE *type=(WM_MEDIA_TYPE*)malloc(typelen);								mp->GetMediaType(type,&typelen);								info.mediatype=type->subtype;								info.fcc=type->subtype.Data1;								DWORD dwFcc = info.fcc;								DPRINTF("mmioFOURCC('%c', '%c', '%c', '%c'); // %u %s\n", BYTE(dwFcc), BYTE(dwFcc >> 8), BYTE(dwFcc >> 16), BYTE(dwFcc >> 24), info.fcc, info.name);								codecs.push_back(info);								free(type);							} 							mp->Release();						} 						wsc->Release();					} 				}			}		}		sort(codecs.begin(),codecs.end());		ok=true;	}	virtual ~Tff_wmv9()	{		end();		delete wmv9dll;	}	virtual bool __stdcall getOk(void) {return ok;} 	virtual size_t  __stdcall getCodecCount(void) {return codecs.size();}	virtual bool __stdcall getCodecInfo(size_t i,const Tff_wmv9codecInfo* *info) 	{		if (i>=codecs.size() || !info) return false;		*info=&codecs[i];		return true;	}	virtual bool __stdcall start(const Tff_wmv9cfg &Icfg) 	{		cfg=Icfg;		if (cfg.avioutput) return startAVI();		writing=false;#undef JIF#define JIF(x) if (FAILED(hr=(x))) {DEBUGS(_l("FAILED in ")_l(#x)_l("\n"));return false;}		HRESULT hr;		IWMProfileManager *pProfileManager=NULL;		JIF(wmv9dll->WMCreateProfileManager(&pProfileManager));		JIF(pProfileManager->CreateEmptyProfile(WMT_VER_9_0,&pProfile));		IWMProfile3 *pProfile3=NULL;		JIF(pProfile->QueryInterface(IID_IWMProfile3,(void**)&pProfile3));		JIF(pProfile->SetName(L"ff_wmv9 profile"));		JIF(pProfile->SetDescription(L"ff_wmv9 description"));		IWMStreamConfig *pNewStreamConfig=NULL;		JIF(CreateVideoStream(wmv9dll,			&pNewStreamConfig,			m_pCodecInfo,			pProfile,			cfg.codecIndex,  // codec index			cfg.bitrate,       // bitrate			3000, // buffer window			cfg.width, // width			cfg.height, // height			cfg.fps,  // fps			cfg.quality, // video quality			cfg.seckf,  // seconds per keyframes			cfg.bUseVBR, // video is VBR			cfg.vbr_mode, // VBR mode ( VIDEO_VBR_MODE )			cfg.vbrquality, // VBR Quality			cfg.maxbitrate, // Max Bitrate (VBR)			10000,      // Max VBR Video Buffer 			GetSystemDefaultLCID()));		JIF(pNewStreamConfig->SetStreamNumber(1));		JIF(pNewStreamConfig->SetStreamName(L"Video"));#define CONN_NAME L"VideoConnect"		JIF(pNewStreamConfig->SetConnectionName(CONN_NAME));		JIF(pNewStreamConfig->SetBufferWindow(3000));		IWMPropertyVault *strprops=NULL;		if (SUCCEEDED(pNewStreamConfig->QueryInterface(IID_IWMPropertyVault,(void**)&strprops)))		{			WORD cplx=(WORD)cfg.cplx;if (cplx>codecs[cfg.codecIndex].cmplxMax) cplx=WORD(codecs[cfg.codecIndex].cmplxMax);			strprops->SetProperty(g_wszComplexity,WMT_TYPE_WORD,(BYTE*)&cplx,sizeof(cplx));			strprops->Release();		}		JIF(pProfile->AddStream(pNewStreamConfig));		pNewStreamConfig->Release();pNewStreamConfig=NULL;		pProfile3->Release();pProfile3=NULL;		pProfileManager->Release();pProfileManager=NULL;		JIF(wmv9dll->WMCreateWriter(NULL,&pWMWriter));		JIF(pWMWriter->QueryInterface(IID_IWMWriterAdvanced,(void**)&pWMWriterA));		JIF(pWMWriter->SetProfile(pProfile));		DWORD inpcnt=0;		pWMWriter->GetInputCount(&inpcnt);		wrinputnum=-1;		for (DWORD i=0;i<inpcnt && wrinputnum==-1;i++)		{			IWMInputMediaProps *props=NULL;			JIF(pWMWriter->GetInputProps(i,&props));			WCHAR connNameW[256];WORD connNameLen=256;			props->GetConnectionName(connNameW,&connNameLen);			if (wcscmp(connNameW,CONN_NAME)==0)				wrinputnum=i;			props->Release();		}		if (wrinputnum==-1) return false;		DWORD fmtcnt=0;		pWMWriter->GetInputFormatCount(wrinputnum,&fmtcnt);		WM_MEDIA_TYPE *mediatype=NULL;		IWMInputMediaProps *props=NULL;		for (DWORD fmti=0;fmti<fmtcnt && !mediatype;fmti++)		{			JIF(pWMWriter->GetInputFormat(wrinputnum,fmti,&props));			DWORD mtsize;			JIF(props->GetMediaType(NULL,&mtsize));			mediatype=(WM_MEDIA_TYPE*)malloc(mtsize);			JIF(props->GetMediaType(mediatype,&mtsize));			if (mediatype->subtype==WMMEDIASUBTYPE_YV12) break;			free(mediatype);mediatype=NULL;			props->Release();props=NULL;		}		if (!mediatype) return false;		//here we could modify input type settings, but they seem to be OK already		//WMVIDEOINFOHEADER *wvih=(WMVIDEOINFOHEADER*)mediatype->pbFormat;		// BITMAPINFOHEADER &bih=wvih->bmiHeader;		pWMWriter->SetInputProps(wrinputnum,props);		free(mediatype);		props->Release();		IWMWriterAdvanced2 *writerA2=NULL;		if (SUCCEEDED(pWMWriter->QueryInterface(IID_IWMWriterAdvanced2,(void**)&writerA2)))		{			if (cfg.ivtc)			{				DWORD a=WM_DM_DEINTERLACE_INVERSETELECINE;				hr=writerA2->SetInputSetting(wrinputnum,g_wszDeinterlaceMode,WMT_TYPE_DWORD,(const unsigned char *)&a,sizeof(DWORD));			}			if (cfg.deint)			{				DWORD a=WM_DM_DEINTERLACE_NORMAL;				hr=writerA2->SetInputSetting(wrinputnum,g_wszDeinterlaceMode,WMT_TYPE_DWORD,(const unsigned char *)&a,sizeof(DWORD));			} 			writerA2->Release();		}		if (0) 		{			mysink=new TmyWriterSink(NULL,&hr);			pWMWriterA->AddSink((IWMWriterSink*)mysink);		} 		if (cfg.flnm) 		{			wmv9dll->WMCreateWriterFileSink(&filesink);			//WCHAR flnmW[MAX_PATH];			//MultiByteToWideChar(CP_ACP,0,cfg.flnm,(int)strlen(cfg.flnm)+1,flnmW,MAX_PATH);			filesink->Open(text<wchar_t>(cfg.flnm));			pWMWriterA->AddSink(filesink);		} 		JIF(pWMWriter->BeginWriting());		writing=true;		return true;	}	virtual int __stdcall write(unsigned int framenum,int csp,const unsigned char * const src[4],const int srcStride[4],void *dst)	{		if (!writing) return 0;		if (cfg.avioutput) return writeAVI(framenum,csp,src,srcStride,dst);		INSSBuffer *buf=NULL;		if (SUCCEEDED(pWMWriter->AllocateSample(3*cfg.width*cfg.height/2,&buf)))		{			BYTE *bufptr=NULL;			buf->GetBuffer(&bufptr);			DWORD buflen=3*cfg.width*cfg.height/2;			memcpy(bufptr,src[0],buflen); //always XVID_CSP_YV12			buf->SetLength(buflen);			HRESULT res=pWMWriter->WriteSample(wrinputnum,QWORD(framenum*int64_t(10000000)/cfg.fps),0,buf);			buf->Release();			return 1;		}		else 			return 0; 	}	virtual void __stdcall end(void)	{		if (cfg.avioutput)		{			endAVI();			return;		}		if (pWMWriter)		{			if (writing) pWMWriter->EndWriting();writing=false;			if (filesink) filesink->Release();filesink=NULL;			if (mysink) mysink->Release();mysink=NULL;			if (pWMWriterA) pWMWriterA->Release();pWMWriterA=NULL;			if (pWMWriter) pWMWriter->Release();pWMWriter=NULL;		}		if (pProfile) pProfile->Release();pProfile=NULL;		if (m_pCodecInfo) m_pCodecInfo->Release();m_pCodecInfo=NULL;	}private:	struct Tcontext	{		Tcontext(void)		{			memset(this,0,sizeof(*this));		}		IMediaObject *pDMO;		AM_MEDIA_TYPE mtIn;		AM_MEDIA_TYPE mtOut;		CHandlingMediaBuffer *pInputBuffer;		CHandlingMediaBuffer *pOutputBuffer;		REFERENCE_TIME       rtDecimatorTimeStamp;		REFERENCE_TIME       rtDecimatorDuration;		REFERENCE_TIME       rtMaxJitter;		REFERENCE_TIME       rtFrameDuration;		REFERENCE_TIME       rtTimeStamp;		unsigned char *input;unsigned int inputSize;		unsigned char *output;unsigned int outputSize;	} pContext;	VideoEncParams pParams;	int nOutFrames;	DWORD cbVideoOut;	HRESULT InitializeEncoder(IMediaObject  **ppDMO,		AM_MEDIA_TYPE *pmtIn, 		AM_MEDIA_TYPE *pmtOut,		CHandlingMediaBuffer *pMediaBuffer)	{		HRESULT hr=S_OK;		if (!ppDMO ||!pmtIn || !pmtOut) return E_INVALIDARG;		hr=InitializeVideoEncoder(pmtIn,			&pParams,			ppDMO,			pmtOut,			pMediaBuffer);		return ( hr );	}	bool startAVI(void)	{		cbVideoOut = max(128 * 128 * 2,			(((cfg.width  + 15) & ~15) *			((cfg.height + 15) & ~15) * 3));		HRESULT  hr=S_OK;		DWORD dwFlags;		VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));		vih->rcSource.left=0;vih->rcSource.top=0;vih->rcSource.right=cfg.width;vih->rcSource.bottom=cfg.height;		vih->rcTarget=vih->rcSource;		vih->dwBitRate=DWORD(3*cfg.fps*cfg.width*cfg.height/2);		vih->dwBitErrorRate=0;		vih->AvgTimePerFrame=REFERENCE_TIME(10000000.0/cfg.fps);		vih->bmiHeader.biSize=sizeof(vih->bmiHeader);		vih->bmiHeader.biWidth=cfg.width;		vih->bmiHeader.biHeight=cfg.height;		vih->bmiHeader.biPlanes=1;		const TcspInfo *cspInfo=csp_getInfo(cfg.csp);		vih->bmiHeader.biBitCount=WORD(cspInfo->bpp);		vih->bmiHeader.biCompression=cspInfo->fcc;		vih->bmiHeader.biSizeImage=cspInfo->bpp*cfg.width*cfg.height/8;		pContext.mtIn.subtype=*cspInfo->subtype;		vih->bmiHeader.biXPelsPerMeter=0;		vih->bmiHeader.biYPelsPerMeter=0;		vih->bmiHeader.biClrUsed=0;		vih->bmiHeader.biClrImportant=0;		pContext.pDMO=NULL;		pContext.pInputBuffer=new CHandlingMediaBuffer;		pContext.mtIn.majortype=MEDIATYPE_Video;		pContext.mtIn.bFixedSizeSamples=TRUE;		pContext.mtIn.bTemporalCompression=FALSE;		pContext.mtIn.formattype=FORMAT_VideoInfo;		pContext.mtIn.lSampleSize=vih->bmiHeader.biSizeImage;		pContext.mtIn.pUnk=NULL;		pContext.mtIn.cbFormat=sizeof(VIDEOINFOHEADER);		pContext.mtIn.pbFormat=(unsigned char*)vih;		pContext.input=(unsigned char*)malloc(pContext.inputSize=pContext.mtIn.lSampleSize);		pContext.pOutputBuffer=new CHandlingMediaBuffer;		memset(&pContext.mtOut,0,sizeof(pContext.mtOut));		pParams.nBitrate=cfg.bitrate;		pParams.nWidth=cfg.width;		pParams.nHeight=cfg.height;		pParams.dFrameRate=cfg.fps;		pParams.nKeyDist=cfg.seckf*1000;		pParams.nBufferDelay=5000;		pParams.nCrisp=cfg.crisp;		pParams.nQuality=cfg.quality;		pParams.nPeakBuffer=5000;		pParams.nPeakBitrate=cfg.maxbitrate;		pParams.nComplexity=cfg.cplx;		pParams.nProfile=P_MAIN;		pParams.fIsVBR=cfg.bUseVBR;		pParams.fIsConstrained=FALSE;		pParams.fIsInterlaced=cfg.deint;		pParams.nPasses=1;		for (vector<Tff_wmv9codecInfo>::const_iterator c=codecs.begin();c!=codecs.end();c++)			if (c->index==cfg.codecIndex)			{				pParams.dwTag=c->fcc;				break;			} 			hr=InitializeEncoder(&pContext.pDMO,				&pContext.mtIn,

⌨️ 快捷键说明

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