DirectShow 切割视频保存到本地

DES对于视频的拼接和拼接后视频的预览书上都有讲到,但是对于拼接后视频保存到本地的代码却是哪也找不到(自己搜索过很久)

保存到本地的关键一段代码就是找到压缩器,这段代码书上只说了大概的思路,如果你不使用压缩器直接用书上的代码的话,截取下来的视频画面将严重失真。

void CXunLeiPlayDlg::WriteFile(IAMTimeline *pTL)
{
	IRenderEngine *pRenderEngine=NULL;
	CoCreateInstance(CLSID_RenderEngine,NULL,CLSCTX_INPROC_SERVER,IID_IRenderEngine ,(void**)&pRenderEngine);
	IMediaControl   *pMC=NULL; 
	IMediaEvent     *pEvent=NULL; 
	IGraphBuilder   *pGraph; 
	ICaptureGraphBuilder2   *pBuilder=NULL;
	HRESULT hr=pRenderEngine->SetTimelineObject(pTL);
	hr=pRenderEngine->ConnectFrontEnd();
	hr=pRenderEngine->GetFilterGraph(&pGraph);
	hr=CoCreateInstance(CLSID_CaptureGraphBuilder2, 
		NULL, 
		CLSCTX_INPROC, 
		IID_ICaptureGraphBuilder2, 
		(void   **)&pBuilder); 
	ASSERT(SUCCEEDED(hr)); 
	hr=pBuilder->SetFiltergraph(pGraph); 
	ASSERT(SUCCEEDED(hr)); 
	IBaseFilter *pMux; 
	hr=pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi,L"流年逝水.avi",&pMux,NULL); 
	ASSERT(SUCCEEDED(hr)); 
	long NumGroups; 

	
	pTL->GetGroupCount(&NumGroups); 
	for   (int i=0;i<NumGroups;i++) 
	{ 
		IPin  *pPin=NULL; 
		if   (pRenderEngine->GetGroupOutputPin(i,&pPin)==S_OK) 
		{ 
			IBaseFilter *pCompressor=NULL;
			pCompressor=GetCompressor(CLSID_VideoCompressorCategory,"Microsoft Video 1"); //获取压缩器
			pGraph->AddFilter(pCompressor,L"com");//加入过滤器

			hr=pBuilder->RenderStream(NULL,NULL,pPin,pCompressor,pMux); 
			ASSERT(SUCCEEDED(hr));
			pPin->Release(); 
		} 
	} 

	pGraph->QueryInterface(IID_IMediaEvent,(void**)&pEvent); 
	pGraph->QueryInterface(IID_IMediaControl,(void**)&pMC); 
	pMC->Run(); 
	long evCode;
	pEvent->WaitForCompletion(INFINITE,&evCode);
	pMC->Stop();

}

IBaseFilter* CXunLeiPlayDlg::GetCompressor(GUID inCategory, const char *inFriendlyName)
{
	ICreateDevEnum * enumHardware = NULL;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_ALL,
		IID_ICreateDevEnum, (void**)&enumHardware);
	if (FAILED(hr))
	{
		return NULL;
	}

	IBaseFilter * hardwareFilter = NULL;
	IEnumMoniker * enumMoniker   = NULL;
	hr = enumHardware->CreateClassEnumerator(inCategory,&enumMoniker,0);
	if (enumMoniker)
	{
		enumMoniker->Reset();
		ULONG      fetched = 0;
		IMoniker * moniker = NULL;
		char friendlyName[256];
		while (!hardwareFilter &&SUCCEEDED(enumMoniker->Next(1,&moniker,&fetched))&&fetched)
		{
			if (moniker)
			{
				IPropertyBag * propertyBag = NULL;
				VARIANT        name;
				friendlyName[0] = 0;
				hr = moniker->BindToStorage(0,0,IID_IPropertyBag,(void **)&propertyBag);
				if (SUCCEEDED(hr))
				{					
					name.vt=VT_BSTR;
					hr = propertyBag->Read(L"FriendlyName",&name,NULL);
				}
				if (SUCCEEDED(hr))
				{
					WideCharToMultiByte(CP_ACP, 0, name.bstrVal, -1,
						friendlyName, 256, NULL, NULL);
					if (strcmp(friendlyName,inFriendlyName) == 0) 
					{
						moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&hardwareFilter);
					}
				}
				if (propertyBag)
				{
					propertyBag->Release();
					propertyBag = NULL;
				}
				moniker->Release();
			}			
		}
		enumMoniker->Release();
	}
	enumHardware->Release();
	return hardwareFilter;
}


你可能感兴趣的:(DirectShow 切割视频保存到本地)