📄 ddgrab.cpp
字号:
if (SUCCEEDED(hr))
{
VideoCBs.add(grabberCB);
_RPT0(_CRT_WARN,"Added a VideoCapture.\n");
// if the subtype was changed on us... complain.
if (mt.subtype != MEDIASUBTYPE_RGB24) return E_NOTIMPL;
//set the rate and bytes per WORD info
int width, height, dummy;
double dummyd;
int currentCB = VideoCBs.size()-1;
getVideoInfo(currentCB, &width, &height, &(VideoCBs.at(currentCB)->rate), &dummy, &dummy, &dummyd);
VideoCBs.at(currentCB)->bytesPerWORD = width*height*3;
}
MyFreeMediaType(mt);
return hr;
}
HRESULT DDGrabber::insertAudioCapture(IGraphBuilder* pGraphBuilder, IBaseFilter* pRenderer)
{
AM_MEDIA_TYPE mt = {0};
CSampleGrabberCB* grabberCB;
if (!pGraphBuilder || !pRenderer) return E_POINTER;
mt.majortype = MEDIATYPE_Audio;
mt.subtype = MEDIASUBTYPE_PCM;
mt.formattype = FORMAT_WaveFormatEx;
_RPT0(_CRT_WARN,"Trying to add an AudioCapture.\n");
_RPT0(_CRT_WARN,"Trying MEDIASUBTYPE_PCM\n");
HRESULT hr = insertCapture(pGraphBuilder, pRenderer, &mt, &grabberCB);
if (FAILED(hr))
{
mt.subtype = MEDIASUBTYPE_IEEE_FLOAT;
_RPT0(_CRT_WARN,"Trying MEDIASUBTYPE_IEEE_FLOAT\n");
hr = insertCapture(pGraphBuilder, pRenderer, &mt, &grabberCB);
if (FAILED(hr))
{
GUID null = {0};
mt.subtype = null;
_RPT0(_CRT_WARN,"Trying NULL\n");
hr = insertCapture(pGraphBuilder, pRenderer, &mt, &grabberCB);
}
}
if (SUCCEEDED(hr))
{
grabberCB->isAudio = true;
grabberCB->subtype = mt.subtype;
AudioCBs.add(grabberCB);
_RPT0(_CRT_WARN,"Added an AudioCapture.\n");
//set the rate and bytes per WORD info
int nrChannels, bits, dummy;
double dummyd;
GUID subtype;
int currentCB = AudioCBs.size()-1;
getAudioInfo(currentCB, &nrChannels, &(AudioCBs.at(currentCB)->rate), &bits, &dummy, &dummy, &subtype, &dummyd);
AudioCBs.at(currentCB)->bytesPerWORD = bits/8.0*nrChannels;
// an unsupported bit depth, nrChannels combination; should only be for 4bit.
if (AudioCBs.at(currentCB)->bytesPerWORD != bits/8.0*nrChannels) hr = E_NOTIMPL;
}
MyFreeMediaType(mt);
return hr;
}
HRESULT DDGrabber::mangleGraph(IGraphBuilder* pGraphBuilder)
{
if (!pGraphBuilder) return E_POINTER;
IEnumFilters* filterList;
IBaseFilter* filt;
vector<IBaseFilter*> renderers; // if there is an audio and a video stream then we could have two renderers
ULONG tmp;
HRESULT hr;
if (FAILED(hr = pGraphBuilder->EnumFilters(&filterList))) return hr;
filterList->Reset();
while (filterList->Next(1, &filt, &tmp) == S_OK)
{
if (isRenderer(filt))
{
renderers.add(filt);
}
else filt->Release();
}
filterList->Release();
for (int i=0; i<renderers.size(); i++)
{
if (MEDIATYPE_Video == getMajorType(renderers.at(i)))
{
_RPT0(_CRT_WARN,"Inserting Video Capture...\n");
if (FAILED(hr = insertVideoCapture(pGraphBuilder,renderers.at(i)))) return hr;
_RPT0(_CRT_WARN,"Inserted Video Capture\n");
} else if (MEDIATYPE_Audio == getMajorType(renderers.at(i))) {
_RPT0(_CRT_WARN,"Inserting Audio Capture...\n");
if (FAILED(hr = insertAudioCapture(pGraphBuilder,renderers.at(i)))) return hr;
_RPT0(_CRT_WARN,"Inserted Audio Capture\n");
} else {
_RPT0(_CRT_WARN,"Renderer type not recognized.\n");
}
_RPT0(_CRT_WARN,"Changing to Null...\n");
if (FAILED(hr = changeToNull(pGraphBuilder,(IBaseFilter*)renderers.at(i)))) return hr;
_RPT0(_CRT_WARN,"Changed to Null\n");
}
return S_OK;
}
HRESULT DDGrabber::buildGraph(char* filename)
{
if (!filename) return E_POINTER;
WCHAR uniFilename[MAX_PATH];
HRESULT hr;
MultiByteToWideChar(CP_ACP, 0, filename, -1, uniFilename, MAX_PATH);
// Create the graph builder
pGraphBuilder = NULL;
if (FAILED(hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraphBuilder))) return hr;
// make sure everything is back to "normal"; cleanUp() also releases the current pGraphBuilder, so we need to make a new one
cleanUp();
if (FAILED(hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraphBuilder))) return hr;
// Add some Null Renderers to the graph so that we don't have weird hardware dependences.
IBaseFilter *pNull1, *pNull2;
if (FAILED(hr = ::CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter, (void**)&pNull1))) return hr;
if (FAILED(hr = pGraphBuilder->AddFilter(pNull1, L"NullRender"))) return hr;
if (FAILED(hr = ::CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter, (void**)&pNull2))) return hr;
if (FAILED(hr = pGraphBuilder->AddFilter(pNull2, L"NullRender"))) return hr;
_RPT0(_CRT_WARN,"Rendering File...\n");
if (FAILED(hr = pGraphBuilder->RenderFile(uniFilename,NULL))) return hr;
_RPT0(_CRT_WARN,"Rendered File\n");
IPin* nullPin, *tmpPin;
nullPin = getInputPin(pNull1);
if (nullPin->ConnectedTo(&tmpPin) == VFW_E_NOT_CONNECTED)
{
pGraphBuilder->RemoveFilter(pNull1);
pNull1->Release();
} else tmpPin->Release();
nullPin->Release();
nullPin = getInputPin(pNull2);
if (nullPin->ConnectedTo(&tmpPin) == VFW_E_NOT_CONNECTED)
{
pGraphBuilder->RemoveFilter(pNull2);
pNull2->Release();
} else tmpPin->Release();
nullPin->Release();
_RPT0(_CRT_WARN,"Mangling graph...\n");
// insert the Capture CBs, and change the Renderers to Null
if (FAILED(hr = mangleGraph(pGraphBuilder))) return hr;
_RPT0(_CRT_WARN,"Mangled graph...\n");
return hr;
}
#ifdef MATLAB_MEX_FILE
void DDGrabber::runMatlabCommand()
{
if (matlabCommand)
{
IMediaControl* pMediaControl;
pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
int dims[] = {1,1};
int width=0, height = 0;
mxArray* plhs[] = {NULL};
mxArray* prhs[5];
int ExitCode;
OAFilterState fs;
int f;
prhs[0] = NULL;
mexSetTrapFlag(0);
pMediaControl->GetState(100,&fs);
if (fs != State_Stopped) pMediaControl->Pause(); // pause rendering so that we can process what we have so far...
for (int i=0; i < VideoCBs.size(); i++)
{
CSampleGrabberCB* CB = VideoCBs.at(i);
if (CB)
{
if (CB->pbFormat)
{
VIDEOINFOHEADER * h = (VIDEOINFOHEADER*) CB->pbFormat;
width = h->bmiHeader.biWidth;
height = h->bmiHeader.biHeight;
}
prhs[1] = mxCreateDoubleMatrix(1,1,mxREAL); mxGetPr(prhs[1])[0] = width;
prhs[2] = mxCreateDoubleMatrix(1,1,mxREAL); mxGetPr(prhs[2])[0] = height;
prhs[3] = mxCreateDoubleMatrix(1,1,mxREAL);
prhs[4] = mxCreateDoubleMatrix(1,1,mxREAL);
for (f = lastFrames.at(i); f < CB->frames.size(); f++)
{
if (CB->frames.at(f))
{
dims[0] = CB->frameBytes.at(f);
// only if the array is changing sizes do we allocate a new one
if (prhs[0] == NULL || mxGetM(prhs[0]) != dims[0])
{
if (prhs[0] != NULL) mxDestroyArray(prhs[0]);
//make matrices to pass to the matlab function
prhs[0] = mxCreateNumericArray(2, dims, mxUINT8_CLASS, mxREAL); // empty 2d matrix
}
memcpy(mxGetPr(prhs[0]),(BYTE*)CB->frames.at(f),dims[0]);
mxGetPr(prhs[3])[0] = CB->frameNrs.size()==0?f+1:CB->frameNrs.at(f);
mxGetPr(prhs[4])[0] = CB->frameTimes.size()==0?f+1:CB->frameTimes.at(f);
//free the frame memory
free((BYTE*)CB->frames.at(f));
CB->frames.assign(f,NULL);
CB->frameBytes.assign(f,0);
_RPT3(_CRT_WARN,"mexCallMATLAB %s f# %d #fs %d\n",matlabCommand,f,CB->frames.size());
//call Matlab
ExitCode = mexCallMATLAB(0,plhs,5,prhs,matlabCommand);
_RPT1(_CRT_WARN,"ErrorCode = %d\n",ExitCode);
}
}
lastFrames.assign(i,f);
//free memory
mxDestroyArray(prhs[0]);
prhs[0] = NULL;
mxDestroyArray(prhs[1]);
mxDestroyArray(prhs[2]);
mxDestroyArray(prhs[3]);
mxDestroyArray(prhs[4]);
}
}
pMediaControl->GetState(100,&fs);
if (fs != State_Stopped) pMediaControl->Run(); // restart rendering...
pMediaControl->Release();
}
}
#endif
HRESULT DDGrabber::doCapture()
{
HRESULT hr;
IMediaControl* pMediaControl;
IMediaEvent* pMediaEventEx;
IMediaFilter* pMediaFilter;
IMediaSeeking* pMediaSeeking;
pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEventEx);
pGraphBuilder->QueryInterface(IID_IMediaFilter, (void **)&pMediaFilter);
pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking);
if (pMediaControl == NULL || pMediaEventEx == NULL || pMediaFilter == NULL || pMediaSeeking == NULL) return E_NOINTERFACE;
_RPT1(_CRT_WARN,"tryseeking: %d\n",tryseeking);
if (tryseeking)
{
_RPT2(_CRT_WARN,"frameNrs.size(): %d stopTime: %f\n",tryseeking,(float)stopTime);
if (frameNrs.size() > 0)
{
LONGLONG firstFrame = frameNrs.at(0);
_RPT0(_CRT_WARN,"Trying SetTimeFormat TIME_FORMAT_FRAME\n");
if (SUCCEEDED(pMediaSeeking->SetTimeFormat(&TIME_FORMAT_FRAME)) &&
SUCCEEDED(pMediaSeeking->SetPositions(&firstFrame, AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning )))
{
_RPT0(_CRT_WARN,"SetTimeFormat SUCCEEDED\n");
for (int i=0; i < VideoCBs.size(); i++)
{
CSampleGrabberCB* CB = VideoCBs.at(i);
for (int j=0; j<frameNrs.size(); j++) CB->frameNrs.assign(j,frameNrs.at(j)-firstFrame+1);
}
} else {_RPT0(_CRT_WARN,"SetTimeFormat FAILED\n");}
} else if (stopTime) {
REFERENCE_TIME llstartTime = startTime*10000000;
_RPT0(_CRT_WARN,"Trying SetTimeFormat TIME_FORMAT_MEDIA_TIME\n");
if (SUCCEEDED(pMediaSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME)))
{
_RPT0(_CRT_WARN,"SetTimeFormat SUCCEEDED\n");
if (SUCCEEDED(pMediaSeeking->SetPositions(&llstartTime, AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning ))) {_RPT0(_CRT_WARN,"SetPositions SUCCEEDED\n");}
} else {_RPT0(_CRT_WARN,"SetTimeFormat FAILED\n");}
}
}
//turn off the clock, so that it will run as fast as possible
pMediaFilter->SetSyncSource(NULL);
InitializeCriticalSection(&CriticalSection);
// Run the graph and wait for completion.
if (FAILED(hr = pMediaControl->Run())) return hr;
long evCode = 0;
bool allDone = false;
stopForced = false;
#ifdef MATLAB_MEX_FILE
// initialize the lastFrames vector
lastFrames.clear();
for (int i=0; i < VideoCBs.size(); i++) lastFrames.add(0);
#endif
while (pMediaEventEx->WaitForCompletion(1000, &evCode) == E_ABORT)
{
allDone = true;
for (int i=0; i < VideoCBs.size(); i++)
{
if (VideoCBs.at(i) && !VideoCBs.at(i)->disabled && !VideoCBs.at(i)->done) allDone = false;
_RPT2(_CRT_WARN,"Testing VideoCB: %d allDone: %d \n",i,allDone);
}
for (int i=0; i < AudioCBs.size(); i++)
{
if (AudioCBs.at(i) && !AudioCBs.at(i)->disabled && !AudioCBs.at(i)->done) allDone = false;
_RPT2(_CRT_WARN,"Testing AudioCBs: %d allDone: %d \n",i,allDone);
}
if (allDone)
{
_RPT0(_CRT_WARN,"STOP!!! \n");
// if all of the video streams are done, then force a stop
if (FAILED(hr = pMediaControl->Stop())) return hr;
stopForced = true;
}
#ifdef MATLAB_MEX_FILE
runMatlabCommand();
#endif
}
DeleteCriticalSection(&CriticalSection);
// make sure everything has really stopped before returning.
if (FAILED(hr = pMediaControl->Stop())) return hr;
#ifdef MATLAB_MEX_FILE
runMatlabCommand();
#endif
pMediaEventEx->Release();
pMediaControl->Release();
pMediaFilter->Release();
pMediaSeeking->Release();
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -