用dshow解码多媒体文件并将音频存成wav的代码,求改错
dwing吧
全部回复
仅看楼主
level 4
newjunwei 楼主
class CDshowDecode
{
private:
AM_MEDIA_TYPE destMt;
double filelen;
int gsample;//采样率 (传进值)
int gchannel;//声道数 (传出值)
//directshow 接口定义
IGraphBuilder *pGraphall;
//函数声明
//int CopyFileWave(char * filename,char * openfilename,double start,double end,int t_sample,int channel_t);
HRESULT GetUnconnectedPin(IBaseFilter *pFilter,PIN_DIRECTION PinDir,IPin **ppPin);
HRESULT ConnectFilters(IGraphBuilder *pGraph,IBaseFilter *pSrc,IBaseFilter *pDest,int tag);
HRESULT ConnectFilters(IGraphBuilder *pGraph, IPin *pOut,IBaseFilter *pDest,int tag); HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);
void RemoveGraphFromRot(DWORD pdwRegister);
public:
CDshowDecode()
{
pGraphall = NULL;
}
//解码并通过channel_t返回声道数
int DecodeDShow(char * srcfile,char * destfile,int sample_t,int &channel_t);
};
//释放接口
//文件截取保存函数
//int DecodeDShow(char * filename,char * openfilename,double start,double end,int t_sample,int channel_t)
int CDshowDecode ::DecodeDShow(char * srcfile,char * destfile,int sample_t,int &channel_t)
{
HRESULT hr;
IEnumFilters *pEnum1 = NULL;
IBaseFilter *pFilter=NULL;
IPin* pRpin=NULL;
IEnumPins *pEnum=NULL,*pEnum2=NULL;
IPin* pPin=NULL,*pPin2=NULL;
IPin*pDPin=NULL;
IBaseFilter * pFilter1=NULL;
IBaseFilter * VideoFilter[10]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
IBaseFilter *pWaveDest = NULL;
IBaseFilter *pFileWriter = NULL;
IBaseFilter *pAcmWrapper = NULL;
IFileSinkFilter *pSink=NULL;
IPin* pin2=NULL;
IMediaEvent *pEvent=NULL;
IMediaControl *pMediaControl=NULL;
IMediaFilter * pMediaFilter=NULL;
int re=1,i=0;
gsample=sample_t;
try
{
hr=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&pGraphall);
if (FAILED(hr))throw"ERROR--could not create filter graph manager\n"; BSTR bstrText=CComBSTR(srcfile);
hr=pGraphall->RenderFile(bstrText,NULL);
if(FAILED(hr))throw"RenderFile failed "; //显示媒体文件为音频或者视频
FILTER_INFO FilterInfo;
hr = pGraphall->EnumFilters(&pEnum1);
if (FAILED(hr))throw"EnumFilters failed\n"; int VideoFilterNum=0;
while(pEnum1->Next(1, &pFilter, NULL) == S_OK)
{
hr = pFilter->QueryFilterInfo(&FilterInfo);
printf("%ws\n",FilterInfo.achName);
if (FAILED(hr))
{
pFilter->Release();
pFilter=NULL;
continue; // Maybe the next one will work.
}
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
{
pEnum->Release();
pEnum=NULL;
pFilter->Release();
pFilter=NULL;
continue; // Maybe the next one will work.
}
int PinCount=0;
AM_MEDIA_TYPE pmt;
bool bHasAudio=false;
while(pEnum->Next(1, &pPin, 0) == S_OK)
{
PinCount++;
pPin->ConnectionMediaType(&pmt);

2011年12月30日 08点12分 1
level 4
newjunwei 楼主
if(pmt.majortype==MEDIATYPE_Audio||pmt.majortype==MEDIATYPE_Stream)bHasAudio=true;
pPin->Release();
pPin=NULL;
}
if (pmt.majortype==MEDIATYPE_Audio&&PinCount==1)
{
pFilter->EnumPins(&pEnum2);
pEnum2->Next(1,&pPin2,0);
pEnum2->Release();
pEnum2=NULL;
pPin2->ConnectedTo(&pRpin);
pPin2->Release();
pPin2=NULL;
memcpy((char*)&destMt,(char*)&pmt,sizeof(AM_MEDIA_TYPE));
pFilter->Release();
pFilter=NULL;
}
else
{
if(!bHasAudio)
{
VideoFilter[VideoFilterNum++]=pFilter;
}
else
{
pFilter->Release();
pFilter=NULL;
}
}
SAFERELEASE(pEnum);//for while
SAFERELEASE(pPin);
}
SAFERELEASE(pFilter);//for while
SAFERELEASE(pEnum1); for(i=0;i<VideoFilterNum;i++)
{
pGraphall->RemoveFilter(VideoFilter[i]);
VideoFilter[i]->Release();
VideoFilter[i]=NULL;
}
/////////////////////////////clear
if(!pRpin)throw("Find pRpin failed\n"); pRpin->ConnectedTo(&pDPin);
PIN_INFO pinInfo1;
pDPin->QueryPinInfo(&pinInfo1);
pFilter1=pinInfo1.pFilter;
hr=pGraphall->RemoveFilter(pFilter1);
if(FAILED(hr))throw("fail remove pFilter\n");
SAFERELEASE(pDPin);
SAFERELEASE(pFilter1);
///////////////////////////////////////// //创建所需的Filter hr = CoCreateInstance(CLSID_ACMWrapper, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAcmWrapper);
if (FAILED(hr)) throw("创建AcmWrapper失败!");
hr = pGraphall->AddFilter(pAcmWrapper, L"ACMWrapper");
if (FAILED(hr)) throw("添加AcmWrapper失败!");
hr = CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pWaveDest);
if (FAILED(hr)) throw"创建wavdest失败!";
hr = pGraphall->AddFilter(pWaveDest, L"WAVDest");
if (FAILED(hr)) throw"添加WaVDest失败!";
hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pFileWriter);
if (FAILED(hr)) throw"创建FileWriter失败!";
hr = pGraphall->AddFilter((IBaseFilter *)pFileWriter, L"FileWriter");
if (FAILED(hr)) throw"添加FileWriter失败!";
pFileWriter->QueryInterface(IID_IFileSinkFilter,(void**)&pSink); BSTR pPath=CComBSTR(destfile);
hr=pSink->SetFileName(pPath,NULL);
if (FAILED(hr))throw"设置文件名称失败!";
hr = GetUnconnectedPin(pAcmWrapper, PINDIR_INPUT, &pin2);
if(FAILED(hr))throw"获得ACMWRAPPER inputpin失败!";
/* PIN_INFO pininfor;
pRpin->QueryPinInfo(&pininfor);
IBaseFilter * pUpFilter=pininfor.pFilter;
FILTER_INFO filterInfo;
pUpFilter->QueryFilterInfo(&filterInfo);
printf("%ws\n",filterInfo.achName);*/
hr = pGraphall->ConnectDirect(pRpin,pin2,NULL); if(FAILED(hr))throw"连接失败-error1!"; hr=ConnectFilters(pGraphall,pAcmWrapper,pWaveDest,1);//tag 是否为一 表示是否进行格式转换

2011年12月30日 08点12分 2
level 4
newjunwei 楼主
if(FAILED(hr))throw"连接失败-error2!";
hr=ConnectFilters(pGraphall,pWaveDest,pFileWriter,0);
if(FAILED(hr))throw"连接失败-error3!";
hr=pGraphall->QueryInterface(IID_IMediaFilter,(void**)&pMediaFilter);
hr=pGraphall->QueryInterface(IID_IMediaControl,(void**)&pMediaControl);
pMediaFilter->SetSyncSource(NULL);//通过这种设置,可以使文件尽快解码完成 2011-08-17
hr=pMediaControl->Run(); Sleep(500);
hr = pGraphall->QueryInterface(IID_IMediaEvent,(void**)&pEvent);
long EventCode ;
hr = pEvent->WaitForCompletion(1000,&EventCode);
//if(EventCode==EC_COMPLETE )printf(" complete\n");
hr=pMediaControl->Stop();
if(FAILED(hr))throw("fail stop\n");
/*DWORD g_dwGraphRegister=0;
hr = AddGraphToRot(pGraphall, &g_dwGraphRegister);
if(FAILED(hr))
{
printf("fail add to rot\n");
}*/
//各种接口释放
}
catch(char *strError)
{
printf(strError);
re=-1;
goto over;
}
catch(...)
{
re=-1;
goto over;
}
over:
printf("-------over----------------\n");
SAFERELEASE(pEnum1);
SAFERELEASE(pFilter);
SAFERELEASE(pRpin);
SAFERELEASE(pEnum);
SAFERELEASE(pEnum2);
SAFERELEASE(pPin);
SAFERELEASE(pPin2);
SAFERELEASE(pDPin);
SAFERELEASE(pFilter1);
SAFERELEASE(pWaveDest);
SAFERELEASE(pFileWriter);
SAFERELEASE(pAcmWrapper);
SAFERELEASE(pSink);
SAFERELEASE(pin2);
SAFERELEASE(pEvent);
SAFERELEASE(pMediaControl);
SAFERELEASE(pMediaFilter);
for(i=0;i<10;i++)
{
SAFERELEASE(VideoFilter[i]);
}
channel_t=gchannel;
return re;
}
//获取Filter中未连接的Pin
HRESULT CDshowDecode ::GetUnconnectedPin(IBaseFilter *pFilter,PIN_DIRECTION PinDir,IPin**ppPin)
{
*ppPin = 0;
IEnumPins *pEnum = 0;
IPin*pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
{
return hr;
}
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
PIN_DIRECTION ThisPinDir;
pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PinDir)
{
IPin* pTmp = 0;
hr = pPin->ConnectedTo(&pTmp);
if (SUCCEEDED(hr))
{
pTmp->Release();
}
else
{
pEnum->Release();
*ppPin = pPin;
return S_OK;
}
}
pPin->Release();
}
pEnum->Release();
return E_FAIL;
}
//连接Filter
HRESULT CDshowDecode ::ConnectFilters(IGraphBuilder *pGraph,IBaseFilter *pSrc,IBaseFilter *pDest,int tag)
{
if ((pGraph == NULL) || (pSrc == NULL) || (pDest == NULL))
{
return E_POINTER;
}
IPin*pOut = NULL;
HRESULT hr = GetUnconnectedPin(pSrc, PINDIR_OUTPUT, &pOut);
if (FAILED(hr))
{
return hr;
}
hr = ConnectFilters(pGraph, pOut, pDest,tag);
pOut->Release();
return hr;
}
//真正连接Filter
HRESULT CDshowDecode ::ConnectFilters(IGraphBuilder *pGraph, IPin* pOut,IBaseFilter *pDest,int tag)
{
if ((pGraph == NULL) || (pOut == NULL) || (pDest == NULL))
{
return E_POINTER;
}
IPin*pIn = 0;
HRESULT hr = GetUnconnectedPin(pDest, PINDIR_INPUT, &pIn);
if (FAILED(hr))
{
pIn->Release();
return hr;
}
if (tag==1)
{
// AM_MEDIA_TYPE destMt1;
destMt.majortype=MEDIATYPE_Audio;
destMt.subtype=MEDIASUBTYPE_PCM;
destMt.formattype=FORMAT_WaveFormatEx;
WAVEFORMATEX *pWF=(WAVEFORMATEX *)(destMt.pbFormat);
pWF->wFormatTag=WAVE_FORMAT_PCM;
gchannel=pWF->nChannels; //顺路获得声道数
pWF->nSamplesPerSec=gsample; //1111111111111
pWF->wBitsPerSample=16;
pWF->nBlockAlign=pWF->wBitsPerSample*pWF->nChannels/8;
pWF->nAvgBytesPerSec=pWF->nSamplesPerSec*pWF->nBlockAlign;
pWF->cbSize=0;
hr = pGraph->ConnectDirect(pOut,pIn,&destMt);
}
else
{
hr = pGraph->ConnectDirect(pOut, pIn,NULL);
}
pIn->Release();
return hr;
}
2011年12月30日 08点12分 3
level 4
newjunwei 楼主
主要思路:去掉音频render,连上AcmWrapper、WAVDest、FileWriter三个filter,并去掉所有关于视频的filter。
主要问题:1、内存泄露 2、需要用到声卡,再没有声卡的机器没法运行
2011年12月30日 08点12分 4
level 9
建议自己写个filter接收音频数据。wav可以自己写。
如果没有声卡,直接render音频文件会失败,但手动加入可以接收音频的filter后再render就会自动连上。
内存泄露的原因不太清楚,不过我的方法是没有的。
2011年12月30日 12点12分 5
level 4
newjunwei 楼主
内存泄露会不会是因为连续render而同时上次的没有彻底释放的原因呢?
2012年01月01日 01点01分 6
level 4
newjunwei 楼主
有没有更好的方法让render时没有视频filter的加入呢
2012年01月01日 02点01分 7
level 4
newjunwei 楼主
如果智能连接sourse跟ffdshow Audio decoder ,然后再在后面添加相应filter,会不会更简单
2012年01月01日 02点01分 8
level 9
不太好弄,只能连接后去掉
2012年01月01日 02点01分 9
level 9
可以参考我direct264里dump.ax的代码
2012年01月01日 03点01分 10
1