Zmiana formatu pinu wyjściowego

Podczas tworzenia filtru nieraz istnieje potrzeba zmiany formatu pinu wyjściowego. Zmianę formatu pinu wyjściowego rozważymy na przykładzie filtru Transform. Chcemy zmienić obraz wyjściowy w taki sposób aby był 2 razy wyższy.

Pierwszym krokiem jest fizyczna modyfikacje formaty wyjściowego. W celu należy zmodyfikować funkcję GetMediaType w filtrze Transform.

HRESULT CFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
{
  // Funkcja jest wywolywana przez menadzer grafu w celu sprawdzenia
  // jakie typy danych wyjsciowych jest wstanie wyprodukowac nasz filtr.
  // Nie podlaczony
  if(!m_pInput->IsConnected())
    return E_UNEXPECTED;

  // Parametr
  CheckPointer(pMediaType,E_POINTER);

  // Tylko jeden typ
  if(iPosition < 0)	return E_INVALIDARG;
  if(iPosition > 0)	return VFW_S_NO_MORE_ITEMS;
	
  // Pobierz typ wejsciowy
   CMediaType	mt_in;
   m_pInput->ConnectionMediaType((AM_MEDIA_TYPE*)&mt_in);
   // Zmien typ wyjściowy
   // Ustaw dwa razy wiekszą wysokość
   ((VIDEOINFOHEADER*)mt_in.pbFormat)->bmiHeader.biHeight = 2*abs(((VIDEOINFOHEADER*)mt_in.pbFormat)->bmiHeader.biHeight);
 
  //Wprzypisz nowy typ do pinu wyjściowego
  (*pMediaType) = mt_in;
    return S_OK;
}

Dodatkowo nalezy zmienić funkcje DecideBufferSize odpowiadającą za alokację bufora pinu wyjściowego. Modyfikacja polega na zmianie pobieranie formatu pinu wyjściowego zamiast wejściowego.

HRESULT CFilter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
  // W tym miejscu filtr alokuje pamiec na obraz wyjsciowy, w DirectShow bufory danych
  // znajduja sie zawsze na wyjsciach filtrow.

  CheckPointer(pAlloc,E_POINTER);
  CheckPointer(pProperties,E_POINTER);

  // Wejscie nie podlaczone
  if(!m_pInput->IsConnected())
    return E_UNEXPECTED;

  // Pobierz format wejsciowy
  HRESULT		hr = S_OK;
  AM_MEDIA_TYPE	mt;
  DWORD		dwSize;

  //m_pInput->ConnectionMediaType(&mt);
  //Pobranie formatu pinu wyjściowego
  m_pOutput->ConnectionMediaType(&mt); 
  
  // Pobierz rozmiar obrazu w bajtach
  dwSize = GetBitmapSize( &((VIDEOINFOHEADER* )mt.pbFormat)->bmiHeader );

  // Ustaw rozmiar i liczbe buforow
  pProperties->cBuffers = 1;
  pProperties->cbBuffer = dwSize;

  ALLOCATOR_PROPERTIES Actual;
  hr = pAlloc->SetProperties(pProperties, &Actual);
  if(FAILED(hr)) return hr;

  if(Actual.cBuffers != 1)	return E_FAIL;
  if(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer)
    return E_FAIL;

  return S_OK;
}

Aby przestestować modyfikacje należy jeszcze zmodyfikować funkcje Transform. W głównej pętli przetwarzającej należy dodać dodatkowe kopiowanie danych.

//Główna pętla filtru kopiująca próbki z obraz wejściowego do wyjściowego
for(int y = 0; y

W wyniku powyższych modyfikacji filtr powinien podwajać wprowadzony na wejście obraz.

Podwojony obraz wejściowy
Rezultat modyfikacji filtru Transform