Ниже приведен фрагмент кода из моего фильтра преобразования декодера, который принимает данные из моего исходного фильтра, который получает данные сети RTP с IP-камеры. Исходный фильтр, фильтр декодирования может динамически реагировать на изменения размеров изображения камеры, поскольку мне нужно обрабатывать изменения разрешения в библиотеке декодирования.
Я использовал метод ReceiveConnection, как описано в справке DirectShow, передавая новые данные MediaType в следующем примере. Однако я не могу заставить рендерер микширования видео динамически принимать изменения разрешения, даже если рендерер будет отображать другое разрешение, если график остановлен и перезапущен.
Может ли кто-нибудь указать, что мне нужно сделать, чтобы средство визуализации обрабатывало динамические изменения разрешения?
HRESULT CDecoder::Receive(IMediaSample* pIn)
{
//Input data does not necessarily correspond one-to-one
//with output frames, so we must override Receive instead
//of Transform.
HRESULT hr = S_OK;
//Deliver input to library
long cBytes = pIn->GetActualDataLength();
BYTE* pSrc;
pIn->GetPointer(&pSrc);
try
{
hr = m_codec.Decode(pSrc, cBytes, (hr == S_OK)?&tStart : NULL);
}
catch (...)
{
hr = E_UNEXPECTED;
}
if (FAILED(hr))
{
if (theLog.enabled()){theLog.strm() << "Decoder Error " << hex << hr << dec << " - resetting input"; theLog.write();}
//Force reset of decoder
m_bReset = true;
m_codec.ResetInput();
//We have handled the error -- don't pass upstream or the source may stop.
return S_OK;
}
//Extract and deliver any decoded frames
hr = DeliverDecodedFrames();
return hr;
}
HRESULT CDecoder::DeliverDecodedFrames()
{
HRESULT hr = S_OK;
for (;;)
{
DecodedFrame frame;
bool bFrame = m_codec.GetDecodedFrame(frame);
if (!bFrame)
{
break;
}
CMediaType mtIn;
CMediaType mtOut;
GetMediaType( PINDIR_INPUT, &mtIn);
GetMediaType( PINDIR_OUTPUT, &mtOut);
//Get the output pin's current image resolution
VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)mtOut.Format();
if( pvi->bmiHeader.biWidth != m_cxInput ||
pvi->bmiHeader.biHeight != m_cyInput)
{
HRESULT hr = GetPin(PINDIR_OUTPUT)->GetConnected()->ReceiveConnection(GetPin(PINDIR_OUTPUT), &mtIn);
if(SUCCEEDED(hr))
{
SetMediaType(PINDIR_OUTPUT, &mtIn);
}
}
IMediaSamplePtr pOut;
hr = m_pOutput->GetDeliveryBuffer(&pOut, 0, 0, NULL);
if (FAILED(hr))
{
break;
}
AM_MEDIA_TYPE* pmt;
if (pOut->GetMediaType(&pmt) == S_OK)
{
CMediaType mt(*pmt);
DeleteMediaType(pmt);
SetMediaType(PINDIR_OUTPUT, &mt);
pOut->SetMediaType(&mt);
}
// crop, tramslate and deliver
BYTE* pDest;
pOut->GetPointer(&pDest);
m_pConverter->Convert(frame.Width(), frame.Height(), frame.GetY(), frame.GetU(), frame.GetV(), pDest);
pOut->SetActualDataLength(m_pOutput->CurrentMediaType().GetSampleSize());
pOut->SetSyncPoint(true);
if (frame.HasTimestamp())
{
REFERENCE_TIME tStart = frame.Timestamp();
REFERENCE_TIME tStop = tStart+1;
pOut->SetTime(&tStart, &tStop);
}
m_pOutput->Deliver(pOut);
}
return hr;
}