Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
[De functie die is gekoppeld aan deze pagina, DirectShow, is een verouderde functie. Het is vervangen door MediaPlayer, IMFMediaEngineen Audio/Video Capture in Media Foundation. Deze functies zijn geoptimaliseerd voor Windows 10 en Windows 11. Microsoft raadt ten zeerste aan om nieuwe code te gebruiken MediaPlayer, IMFMediaEngine en Audio/Video Capture in Media Foundation in plaats van DirectShow, indien mogelijk. Microsoft stelt voor dat bestaande code die gebruikmaakt van de verouderde API's, indien mogelijk opnieuw worden geschreven om de nieuwe API's te gebruiken.]
Met dit mechanisme kan een invoerpin een opmaakwijziging voorstellen in de upstream-peer. Het downstreamfilter moet een mediatype koppelen aan het voorbeeld dat het upstream-filter in de volgende aanroep van IMemAllocator::GetBuffer. Hiervoor moet het downstreamfilter echter een aangepaste allocator voor de verbinding bieden. Deze allocator moet een privémethode implementeren die het downstreamfilter kan gebruiken om het mediatype in te stellen op het volgende voorbeeld.
De volgende stappen worden uitgevoerd:
- Het downstreamfilter controleert of de pinverbinding gebruikmaakt van de aangepaste allocator van het filter. Als het upstream-filter eigenaar is van de allocator, kan het downstreamfilter de indeling niet wijzigen.
- Het downstreamfilter roept IPin::QueryAccept- aan op de upstream-uitvoerpin (zie afbeelding, stap A).
- Als
QueryAcceptS_OK retourneert, roept het downstreamfilter de privémethode aan op de bijbehorende allocator om het mediatype in te stellen. Binnen deze privémethode roept de allocator IMediaSample::SetMediaType aan op het volgende beschikbare voorbeeld (B). - Met het upstream-filter worden GetBuffer- een nieuw voorbeeld (C) en IMediaSample::GetMediaType om het mediatype (D) op te halen.
- Wanneer het upstream-filter het voorbeeld levert, moet het mediatype aan dat voorbeeld worden gekoppeld. Op die manier kan het downstreamfilter bevestigen dat het mediatype is gewijzigd (E).
Als het upstream-filter de indelingswijziging accepteert, moet het ook kunnen terugkeren naar het oorspronkelijke mediatype, zoals wordt weergegeven in het volgende diagram.
De belangrijkste voorbeelden van dit soort indelingswijziging zijn de DirectShow-video-renderers.
- De oorspronkelijke Video Renderer filter kan schakelen tussen RGB- en YUV-typen tijdens het streamen. Wanneer het filter verbinding maakt, is een RGB-indeling vereist die overeenkomt met de huidige weergave-instellingen. Dit garandeert dat het kan terugvallen op GDI als dat nodig is. Als DirectDraw beschikbaar is nadat het streamen is gestart, vraagt de Video Renderer een indeling aan voor een YUV-type. Later kan het weer overschakelen naar RGB als het DirectDraw-oppervlak om welke reden dan ook verloren gaat.
- Het nieuwere videomixerfilter (VMR) maakt verbinding met elke indeling die wordt ondersteund door de grafische hardware, inclusief YUV-typen. De grafische hardware kan echter de onderdrukking van het onderliggende DirectDraw-oppervlak wijzigen om de prestaties te optimaliseren. Het VMR-filter gebruikt
QueryAcceptvoor het rapporteren van de nieuwe stride, die is opgegeven in de biWidth lid van de BITMAPINFOHEADER structuur. De bron- en doelrechthoeken in de VIDEOINFOHEADER of VIDEOINFOHEADER2 structuur identificeren de regio waar de video moet worden gedecodeerd.
implementatienotitie
Het is onwaarschijnlijk dat u een filter schrijft dat wijzigingen in upstream-indeling moet aanvragen, omdat dit voornamelijk een functie van video-renderers is. Als u echter een videotransformatiefilter of een videodecoder schrijft, moet uw filter correct reageren op aanvragen van de video-renderer.
Een trans-in-place filter dat zich tussen de video renderer en de decoder bevindt, moet alle QueryAccept oproepen upstream doorgeven. Sla de nieuwe indelingsgegevens op wanneer deze binnenkomen.
Een filter voor kopiëren/transformeren (een niet-trans-in-place filter) moet een van de volgende gedragingen implementeren:
- De indeling wordt upstream gewijzigd en de nieuwe indelingsgegevens worden opgeslagen wanneer deze binnenkomt. Uw filter moet een aangepaste allocator gebruiken, zodat deze de indeling aan het upstream-voorbeeld kan koppelen.
- Voer de indelingsconversie in het filter uit. Dit is waarschijnlijk eenvoudiger dan het doorgeven van de opmaakwijziging upstream. Het kan echter minder efficiënt zijn dan de decoder te laten decoderen in de juiste indeling.
- Als laatste redmiddel negeert u de opmaakwijziging. (Raadpleeg de broncode voor de CTransInPlaceOutputPin::CheckMediaType methode in de directShow-basisklassebibliotheek voor meer informatie.) Het weigeren van een indelingswijziging kan echter de prestaties verminderen, omdat hiermee wordt voorkomen dat de video-renderer de meest efficiënte indeling gebruikt.
De volgende pseudocode laat zien hoe u een kopieertransformatiefilter (afgeleid van CTransformFilter) kunt implementeren die kan schakelen tussen YUV- en RGB-uitvoertypen. In dit voorbeeld wordt ervan uitgegaan dat het filter de conversie zelf uitvoert, in plaats van de notatie upstream door te geven.
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);
}
}