How to do dynamic format change from the Decoder Filter?...
Scenario:
-------------
Assume that we reading video data from the RTP or from real media file.
we will receive the video with 320x240 resolution. In the middle of the stream, it might give you video data with 640x480
resolution. How will u handle the situation ? we can do it with Dynamic format change.
what needs to be done at decoder level:
---------------------------------------
For getting width and height, we will refer the config data from the Source filter's VIDEOINFOHEADER config data or from
the video frame itself have the config information .
We have the Create the Decoder with current width and height( 320x240) resolution.
DecodeFrame() fn itself must have the ability to detect new config. if some new config arrived, the DecodeFrame () returns
E_NEW_CONFIG;
when the new width and height found, we have to delete/release the decoder ( Not a decoder filter) and we have to
create the new decoder with new resolution and then try to decode the frame.
Here we need to change Decoder filter's output pin media type as well as the reallocate renderer's allocator with new
resolution.
Logic is as follows:
if( DecodeFrame() == E_NEW_CONFIG)
{
DeleteDecoder();
hr =CreateDecoder(newWidth,newHeight);
//Change the output pin's media type resolution
//Rellocate the renderer's allocator with new resolution (640x480)
//DecodeFrame() once again and give it out.
}
if we want the dynamic format change, we have to use upstream filter's(video renderer) allocator .
For Windows mobile:
-------------------
Microsoft video renderer doesnt have the dynamic format change support.
So we can develop the new video renderer.
if( DecodeFrame() == E_NEW_CONFIG)
{
DeleteDecoder();
hr =CreateDecoder(newWidth,newHeight);
//Change the output pin's media type resolution
//Rellocate the renderer's allocator with new resolution (640x480)
hr = m_pInput->ReceiveConnection(m_pOutput,mediatypeWithNewRes); // m_pInput is just a pointer to upstream
filter's // input pin ( video renderer input pin
DecodeFrame();
Deliver(pSample);
}
In Video renderer:
-------------------
upstream filter input pin (Renderer input Pin):
we have to override the ReceiveConnection() fn;
HRESULT ReceiveConnection(IPin* m_Connected, AM_MEDIA_TYPE* mtWithNewRes)
{
if( m_Connected)
{
// this condition will be satisfied if ReceiveConnection() called from the Decoder manually (while // the graph was running
int Width = getWidth(mtwithNewRes);
int height = getHeight(mtWithNewRes);
if( CheckMediaType(mtWithNewRes) != S_OK)
{
return E_FAIL;
}
SetMediaType(mtWithNewRes);
m_pAllocator->Decommit();
m_pAllocator->SetProperties(Width,height);
m_pAllocator->Commit();
}
else
{
return CBasePin::ReceiveConnection();
}
}
For PC:
----------
For PC, Video renderer has the support for dynamic format change.
we will do as follows:
within Decoder:
if( DecodeFrame() == E_NEW_CONFIG)
{
DeleteDecoder();
hr =CreateDecoder(newWidth,newHeight);
//Change the output pin's media type resolution
//Rellocate the renderer's allocator with new resolution (640x480)
hr = m_pInput->ReceiveConnection(mediatypeWithNewRes);
m_pInput->m_pAllocator->Decommit();
m_pInput->m_pAllocator->SetProperties(new Resolution Size);
m_pInput->m_pAllocator->Commit();
DecodeFrame();
Deliver(pSample);
}
Renderer have the ability to change to new allocated buffer;;