Recently I'm working with VC and DirectShow, the problem is that the dynamic format changes did not work out to me.
I customized a CBaseFilter as my SouceFilter. It get, fill and deliver a MediaSample(Sample for short) to downstream filter which is a VMR precisely.The SourceFilter get the Sample through CBaseOutputPin::GetDeliveryBuffer, and deliver the Sample through CBaseOutputPin::Deliver.
For reasons, the resolution of frames may change any time. So I attach a new MediaType with width and height changed in its pbFormat bmiHeader every time the resolution changed.
According ot MSDN Dynamic Format Changes, I wrote codes as below:
// YUV420 frame got
// now try to get Sample buffer
if(pvi.bmiHeader.biWidth != width || pvi.bmiHeader.biHeight != height){
// if resolution changed
// generate new MediaType with new resolution
SetMediaType(width, height);
if(S_OK == pRenderInPin->QueryAccept(&mediaType)){
// if the input Pin of render accept the new MediaType
if(pSourceFilter){
/*
* In function GetSampleBufferOfMediaType,
* I ask for a Sample, attach a MediaType to it,
* and get its buffer for future use
*/
while(S_OK != pSourceFilter->GetSampleBufferOfMediaType(&mediaType, &pSampleBuffer)
&& isActive){
Sleep(8);
}
}
}else{
DEBUG_INFO("ERROR - failed on QueryAccept\n");
}
}else{
// in function GetSampleBuffer, just ask for a Sample buffer
while (S_OK != pSourceFilter->GetSampleBuffer(&pSampleBuffer)
&& isActive){
Sleep(8);
}
}
// fill buffer and deliver it
I considered that once RenderFilter get the Sample with new MediaType attached, it will call IMediaSample::GetMediaType, and adopt the new MediaType. But I found onece resolution changed, the GetSampleBufferOfMediaType will execute, unfortunately the pictures did not properly show on the screen.
I wonder why it does not work as I expected, and how should I modify my program.
Any hint will be highly appreciate.
-----[Extra Information]-----
In condition which has no format changes, my MediaType works with 720P and 1080P well, but it is not lucky with CIF(352*288). Maybe here's something wrong with my function SetMediaType()?
void CReadBufController::SetMediaType(short _width, short _height){
mMediaType.subtype = MEDIASUBTYPE_YV12;
mMediaType.majortype = MEDIATYPE_Video;
mMediaType.formattype = FORMAT_VideoInfo;
mMediaType.bFixedSizeSamples = FALSE;
mMediaType.bTemporalCompression = TRUE;
mMediaType.lSampleSize = 0;
mMediaType.pUnk = 0;
mMediaType.cbFormat = sizeof(VIDEOINFOHEADER);
pvi.bmiHeader.biBitCount = 12;
pvi.bmiHeader.biWidth = _width;
pvi.bmiHeader.biHeight = _height;
pvi.bmiHeader.biSizeImage = GetBitmapSize(&pvi.bmiHeader);
pvi.bmiHeader.biPlanes = 1;
pvi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi.bmiHeader.biCompression = MAKEFOURCC('Y', 'V', '1', '2');
mMediaType.pbFormat = (BYTE *)(&pvi);
}
-----[UPDATE]-----
According to comment of @Roman_R, here's my code of GetSampleBufferOfMediaType:
// here CReadBufferFilter is the SourceFilter I mentioned
HRESULT CReadBufferFilter::GetSampleBufferOfMediaType(AM_MEDIA_TYPE *_pMediaType, PBYTE *_pBuffer){
SAFE_RELEASE(mSample);
// get a Sample from output Pin
mOutputPin->GetDeliveryBuffer(&mSample, NULL, NULL, 0);
// attach the new MediaType to the Sample
if(mSample && (S_OK == mSample->SetMediaType(_pMediaType) )){
mSample->GetPointer(_pBuffer); // get the Sample buffer
return S_OK;
}
return E_FAIL;
}
'the pictures did not properly show on the screen' means its gray and overlapped with its multiple image copy, just act like when you assigned improper width and height to the MediaType it will.
GetSampleBufferOfMediaTypedoes exactly, and then what do you mean by "the pictures did not properly show on the screen". It is unclear whether you see at all new media type attached to media sample at any time. - Roman R.