DirectShow 采集摄像头图像为AVI文件 但是用播放器无法播放这个AVI文件

season030441 2013-01-04 09:13:59
以下为我的源码,可以看到预览的摄像头画面,test2.avi可以生成,文件大小也正确,但是用QQ影音等播放器却无法播放这个test2.avi文件,提示信息“文件无法渲染”。分数过少可以继续追加!

HRESULT hr;
IGraphBuilder *pGB=NULL;
ICaptureGraphBuilder2* pCGB2=NULL;
IMediaControl *pMediaControl = NULL;
IBaseFilter *pMux =NULL;
IBaseFilter *pWriter=NULL;
IBaseFilter *pCompress=NULL;
IFileSinkFilter2 *pSink=NULL;
IBaseFilter *pSrcFilter =NULL;

hr=CoInitialize(NULL);
if( FAILED(hr))
AfxMessageBox("Initializing COM library failed!");

// 创建IGraphBuilder接口
hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB);
if( FAILED(hr))
{
AfxMessageBox("IGraphBuilder failed");
return ;
}
// 创建ICaptureGraphBuilder2接口
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 ,NULL,CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **) &pCGB2);
if( FAILED(hr))
{
AfxMessageBox("IID_ICaptureGraphBuilder2 failed");
return ;
}
pCGB2->SetFiltergraph(pGB);


hr = pGB->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
if( FAILED(hr))
{
AfxMessageBox("IID_IMediaControl failed");
return ;
}

BindFilter(0,&pSrcFilter);//该函数可以正确运行
pGB->AddFilter(pSrcFilter, L"Capture Filter");



hr=pCGB2->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,pSrcFilter,NULL,NULL);
if( FAILED(hr))
{
AfxMessageBox("RenderStream PIN_CATEGORY_PREVIEW failed");
hr = pCGB2->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pSrcFilter,NULL,NULL);
if( FAILED(hr))
{
AfxMessageBox("RenderStream PIN_CATEGORY_CAPTURE failed");
return ;
}

}
else
{
AfxMessageBox("预览");
}

hr=pCGB2->SetOutputFileName(&MEDIASUBTYPE_Avi,L"e:\\test2.avi",&pMux,NULL);//生成Avi pMux

if( FAILED(hr))
{
AfxMessageBox("SetOutputFileName failed");
return ;
}
IConfigAviMux *pConfigMux=NULL;
hr=pMux->QueryInterface(IID_IConfigAviMux,(void **)&pConfigMux);
if( FAILED(hr))
{
AfxMessageBox("IID_IConfigAviMux failed");
return ;
}
pConfigMux->SetMasterStream(0);
pConfigMux->Release();


hr=pCGB2->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pSrcFilter,NULL,pMux);//不带压缩

if( FAILED(hr))
{
AfxMessageBox("记录 PIN_CATEGORY_CAPTURE failed");
return ;
}
pMux->Release();


pMediaControl->Run();
...全文
394 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
season030441 2013-01-10
  • 打赏
  • 举报
回复
感谢 “gdstx” 确实好使了!多谢。
gdstx 2013-01-06
  • 打赏
  • 举报
回复
使用pMediaControl->Stop()后, AVI文件就正常了
season030441 2013-01-05
  • 打赏
  • 举报
回复
除了BindFilter代码没贴出来,全部代码都在这了。我用了graphedt 这个建图过程是可以正常保存avi视频,并可以用播放器正常播放的,但是我这个代码就不行。 BindFilter代码如下: bool CMyCaptureDlg::BindFilter(int nCamID, IBaseFilter **pFilter) { if (nCamID < 0) return false; // enumerate all video capture devices CComPtr<ICreateDevEnum> pCreateDevEnum; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum); if (hr != NOERROR) { return false; } CComPtr<IEnumMoniker> pEm; hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0); if (hr != NOERROR) { return false; } pEm->Reset(); ULONG cFetched; IMoniker *pM; int index = 0; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= nCamID) { IPropertyBag *pBag; hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(SUCCEEDED(hr)) { VARIANT var; var.vt = VT_BSTR; hr = pBag->Read(L"FriendlyName", &var, NULL); if (hr == NOERROR) { if (index == nCamID) { pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter); } char sName[1024]; WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,sName, 1024 ,"",NULL); CString strTemp; strTemp.Format("%s",sName); AfxMessageBox(strTemp); SysFreeString(var.bstrVal); } pBag->Release(); } pM->Release(); index++; } pCreateDevEnum = NULL; return true; }
mangshe0 2013-01-04
  • 打赏
  • 举报
回复
代码 我好久没写了 都忘记了 刚才翻了一下 以前写的工程, 我建议你这样 先使用directshow 的filter 那个工具 叫 :graphedt 用它先把模型搭建好,然后测试好 测试出来的文件 没有问题能看 最后在编码实现 ds很好玩的 你可以加预览之类的 争取后期自己写filter
银点 2013-01-04
  • 打赏
  • 举报
回复

//创建File Writer
	hr = ::CoCreateInstance(CLSID_FileWriter,NULL,CLSCTX_INPROC,
									IID_IFileSinkFilter2,(LPVOID*)&FileSink);
	if(FAILED(hr))
		return hr;

	if(FAILED(hr = FileSink->QueryInterface(IID_IBaseFilter,(void**)&FileWriter)))
		return E_NOINTERFACE;

	if(FAILED(hr =Graph->AddFilter(FileWriter,L"File Writer")))
		return hr;

	hr = CaptureGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
						VideoSourceFilter, VideoEncoder, AviMux);
	if(FAILED(hr))
	{
		MESSAGEBOX("创建视频压缩链路失败");
		return hr;
	}
	CaptureGraph->RenderStream(NULL, &MEDIATYPE_Audio,AudioSourceFilter,
											AudioEncoder, AviMux);
    if(FAILED(hr))
	{
		MESSAGEBOX("创建音频压缩链路失败");
		return hr;
	}
	if(FAILED(hr = ConnectPin(AviMux,FileWriter)))
	{
		MESSAGEBOX("创建文件输出链路失败");
		return hr;
	}
我这个顺序创建的graph 启动采集时这样写的:
HRESULT TCaptureGraph::StartCapture(FileName)
{
	HRESULT hr = FileSink->SetMode(1);  //AM_FILE_OVERRITE
    if(FAILED(hr))
		return hr;
	
	if(FAILED(hr = FileSink->SetFileName(FileName,NULL)))
        return hr;
	hr = MediaControl->Run();
	if(SUCCEEDED(hr))
		this->CaptureState = RUNNING;
	return hr;

}
银点 2013-01-04
  • 打赏
  • 举报
回复
把源代码发给我,我帮你调一下

3,248

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧