Как заставить фильтр DirectShow VideoRender реагировать на изменения MediaType на своем входном контакте? - PullRequest
0 голосов
/ 17 марта 2010

Ниже приведен фрагмент кода из моего фильтра преобразования декодера, который принимает данные из моего исходного фильтра, который получает данные сети 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;
}

1 Ответ

0 голосов
/ 17 марта 2010

Какую ошибку вы получаете при сбое? Вероятно, вам нужно убедиться, что нет ожидающих буферов - все сэмплы должны быть возвращены распределителю, прежде чем это удастся. Вы сравнили свой код с версией в www.gdcl.co.uk/gmfbridge?

...