Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
[Funkcja skojarzona z tą stroną, DirectShow, jest starszą funkcją. Został zastąpiony przez MediaPlayer, IMFMediaEnginei Audio/Video Capture w Media Foundation. Te funkcje zostały zoptymalizowane pod kątem systemów Windows 10 i Windows 11. Firma Microsoft zdecydowanie zaleca, aby nowy kod używał MediaPlayer, IMFMediaEngine i Audio/Video Capture w programie Media Foundation zamiast DirectShow, jeśli to możliwe. Firma Microsoft sugeruje, że istniejący kod, który używa starszych interfejsów API, należy przepisać go do korzystania z nowych interfejsów API, jeśli to możliwe.]
Ten mechanizm umożliwia wprowadzenie numeru PIN do zaproponowania zmiany formatu na nadrzędną elementy równorzędne. Filtr podrzędny musi dołączyć typ nośnika do próbki, który filtr nadrzędny uzyska w następnym wywołaniu do IMemAllocator::GetBuffer. Aby to zrobić, filtr podrzędny musi jednak podać niestandardowy alokator dla połączenia. Ten alokator musi zaimplementować metodę prywatną, za pomocą którego filtr podrzędny może ustawić typ nośnika w następnym przykładzie.
Są wykonywane następujące czynności:
- Filtr podrzędny sprawdza, czy połączenie pin używa niestandardowego alokatora filtru. Jeśli filtr nadrzędny jest właścicielem alokatora, filtr podrzędny nie może zmienić formatu.
- Filtr podrzędny wywołuje IPin::QueryAccept na wyprowadzeniu wyjściowym nadrzędnym (zobacz ilustrację, krok A).
- Jeśli
QueryAcceptzwraca S_OK, filtr podrzędny wywołuje metodę prywatną na alokatorze, aby ustawić typ nośnika. W ramach tej metody prywatnej alokator wywołuje IMediaSample::SetMediaType w następnym dostępnym przykładzie (B). - Nadrzędne wywołania filtru GetBuffer, aby pobrać nowy przykład (C) i IMediaSample::GetMediaType, aby pobrać typ nośnika (D).
- Gdy filtr nadrzędny dostarcza przykład, powinien pozostawić typ nośnika dołączony do tej próbki. Dzięki temu filtr podrzędny może potwierdzić, że typ nośnika uległ zmianie (E).
Jeśli filtr nadrzędny akceptuje zmianę formatu, musi być również w stanie przełączyć się z powrotem do oryginalnego typu nośnika, jak pokazano na poniższym diagramie.
queryaccept (nadrzędne)
Główne przykłady tego rodzaju zmiany formatu obejmują programy renderujące wideo DirectShow.
- Oryginalny filtr Video Renderer może przełączać się między typami RGB i YUV podczas przesyłania strumieniowego. Po nawiązaniu połączenia z filtrem wymagany jest format RGB zgodny z bieżącymi ustawieniami wyświetlania. Gwarantuje to, że może wrócić do GDI, jeśli jest to konieczne. Po rozpoczęciu przesyłania strumieniowego, jeśli tryb DirectDraw jest dostępny, program renderowania wideo żąda zmiany formatu na typ YUV. Później może przełączyć się z powrotem do RGB, jeśli utraci powierzchnię DirectDraw z jakiegokolwiek powodu.
- Nowszy filtr renderatora mieszania wideo (VMR) będzie łączyć się z dowolnym formatem obsługiwanym przez sprzęt graficzny, w tym typy YUV. Jednak sprzęt graficzny może zmienić krok bazowej powierzchni DirectDraw w celu optymalizacji wydajności. Filtr VMR używa
QueryAcceptdo raportowania nowego kroku określonego w biWidth elementu członkowskiego BITMAPINFOHEADER. Prostokąty źródłowe i docelowe w VIDEOINFOHEADER lub VIDEOINFOHEADER2 strukturze identyfikują region, w którym ma zostać zdekodowane wideo.
implementacji
Jest mało prawdopodobne, że napiszesz filtr, który musi zażądać zmian formatu nadrzędnego, ponieważ jest to głównie funkcja renderatorów wideo. Jeśli jednak napiszesz filtr przekształcenia wideo lub dekoder wideo, filtr musi odpowiadać poprawnie na żądania z modułu renderowania wideo.
Filtr trans-in-place, który znajduje się między modułem renderowania wideo a dekoderem, powinien przekazać wszystkie QueryAccept wywołania nadrzędne. Przechowuj nowe informacje o formacie po nadejściu.
Filtr przekształcenia kopiowania (czyli filtr nieuwzwiązany z trans- w miejscu) powinien implementować jedno z następujących zachowań:
- Przekaż zmiany formatu nadrzędnego i zapisz nowe informacje o formacie po ich nadejściu. Filtr musi używać niestandardowego alokatora, aby można było dołączyć format do próbki nadrzędnej.
- Przeprowadź konwersję formatu wewnątrz filtru. Jest to prawdopodobnie łatwiejsze niż przekazywanie zmiany formatu nadrzędnego. Jednak może to być mniej wydajne niż umożliwienie dekodowania filtru dekodowania w poprawnym formacie.
- W ostateczności po prostu odrzuć zmianę formatu. (Aby uzyskać więcej informacji, zapoznaj się z kodem źródłowym CTransInPlaceOutputPin::CheckMediaType metody w bibliotece klas bazowych DirectShow. Odrzucenie zmiany formatu może jednak zmniejszyć wydajność, ponieważ uniemożliwia renderowanie wideo przy użyciu najbardziej wydajnego formatu.
Poniższy pseudokod pokazuje, jak można zaimplementować filtr przekształcenia kopiowania (pochodzący z CTransformFilter), który może przełączać się między typami wyjściowymi YUV i RGB. W tym przykładzie przyjęto założenie, że filtr wykonuje samą konwersję, a nie przekazuje zmiany formatu nadrzędnego.
HRESULT CMyTransform::CheckInputType(const CMediaType *pmt)
{
if (pmt is a YUV type that you support) {
return S_OK;
}
else {
return VFW_E_TYPE_NOT_ACCEPTED;
}
}
HRESULT CMyTransform::CheckTransform(
const CMediaType *mtIn, const CMediaType *mtOut)
{
if (mtOut is a YUV or RGB type that you support)
{
if ((mtIn has the same video dimensions as mtOut) &&
(you support the mtIn-to-mtOut transform))
{
return S_OK;
}
}
// otherwise
return VFW_E_TYPE_NOT_ACCEPTED;
}
// GetMediaType: Return a preferred output type.
HRESULT CMyTransform::GetMediaType(int iPosition, CMediaType *pMediaType)
{
if (iPosition < 0) {
return E_INVALIDARG;
}
switch (iPosition)
{
case 0:
Copy the input type (YUV) to pMediaType
return S_OK;
case 1:
Construct an RGB type that matches the input type.
return S_OK;
default:
return VFW_S_NO_MORE_ITEMS;
}
}
// SetMediaType: Override from CTransformFilter.
HRESULT CMyTransform::SetMediaType(
PIN_DIRECTION direction, const CMediaType *pmt)
{
// Capture this information...
if (direction == PINDIR_OUTPUT)
{
m_bYuv = (pmt->subtype == MEDIASUBTYPE_UYVY);
}
return S_OK;
}
HRESULT CMyTransform::Transform(
IMediaSample *pSource, IMediaSample *pDest)
{
// Look for format changes from downstream.
CMediaType *pMT = NULL;
HRESULT hr = pDest->GetMediaType((AM_MEDIA_TYPE**)&pMT);
if (hr == S_OK)
{
hr = m_pOutput->CheckMediaType(pMT);
if(FAILED(hr))
{
DeleteMediaType(pMT);
return E_FAIL;
}
// Notify our own output pin about the new type.
m_pOutput->SetMediaType(pMT);
DeleteMediaType(pMT);
}
// Process the buffers
if (m_bYuv) {
return ProcessFrameYUV(pSource, pDest);
}
else {
return ProcessFrameRGB(pSource, pDest);
}
}