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. Rezultat modyfikacji filtru Transform