Stöd för DXVA 2.0 i DirectShow
Det här avsnittet beskriver hur du stöder DirectX Video Acceleration (DXVA) 2.0 i ett DirectShow-avkodarfilter. Mer specifikt beskriver den kommunikationen mellan avkodaren och videoåtergivningen. Det här avsnittet beskriver inte hur du implementerar DXVA-avkodning.
- Förutsättningar
- Migreringsanteckningar
- Hitta en konfiguration av avkodare
- Aviserar Video Renderer
- Allokera okomprimerade buffertar
- avkodning
- Relaterade ämnen
Förutsättningar
Det här avsnittet förutsätter att du är bekant med att skriva DirectShow-filter. Mer information finns i avsnittet Skriva DirectShow-filter i DirectShow SDK-dokumentationen. Kodexemplen i det här avsnittet förutsätter att avkodarfiltret härleds från klassen CTransformFilter med följande klassdefinition:
class CDecoder : public CTransformFilter
{
public:
static CUnknown* WINAPI CreateInstance(IUnknown *pUnk, HRESULT *pHr);
HRESULT CompleteConnect(PIN_DIRECTION direction, IPin *pPin);
HRESULT InitAllocator(IMemAllocator **ppAlloc);
HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp);
// TODO: The implementations of these methods depend on the specific decoder.
HRESULT CheckInputType(const CMediaType *mtIn);
HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);
HRESULT CTransformFilter::GetMediaType(int,CMediaType *);
private:
CDecoder(HRESULT *pHr);
~CDecoder();
CBasePin * GetPin(int n);
HRESULT ConfigureDXVA2(IPin *pPin);
HRESULT SetEVRForDXVA2(IPin *pPin);
HRESULT FindDecoderConfiguration(
/* [in] */ IDirectXVideoDecoderService *pDecoderService,
/* [in] */ const GUID& guidDecoder,
/* [out] */ DXVA2_ConfigPictureDecode *pSelectedConfig,
/* [out] */ BOOL *pbFoundDXVA2Configuration
);
private:
IDirectXVideoDecoderService *m_pDecoderService;
DXVA2_ConfigPictureDecode m_DecoderConfig;
GUID m_DecoderGuid;
HANDLE m_hDevice;
FOURCC m_fccOutputFormat;
};
I resten av det här avsnittet refererar termen avkodare till avkodarfiltret, som tar emot komprimerad video och matar ut okomprimerad video. Termen avkodarenhet refererar till en maskinvaruvideoaccelerator som implementeras av grafikdrivrutinen.
Här är de grundläggande stegen som ett avkodarfilter måste utföra för att stödja DXVA 2.0:
- Förhandla om en medietyp.
- Hitta en DXVA-avkodarkonfiguration.
- Meddela videoåtergivningen att avkodaren använder DXVA-avkodning.
- Ange en anpassad allokerare som allokerar Direct3D-ytor.
De här stegen beskrivs mer detaljerat i resten av det här avsnittet.
Migreringsanteckningar
Om du migrerar från DXVA 1.0 bör du vara medveten om några betydande skillnader mellan de två versionerna:
- DXVA 2.0 använder inte IAMVideoAccelerator och IAMVideoAcceleratorNotify-gränssnitt, eftersom avkodaren kan komma åt DXVA 2.0-API:erna direkt via IDirectXVideoDecoder-gränssnittet.
- Under förhandling av medietyp använder avkodaren inte en GUID för videoacceleration som undertyp. I stället är undertypen bara det okomprimerade videoformatet (till exempel NV12), som med avkodning av programvara.
- Proceduren för att konfigurera acceleratorn har ändrats. I DXVA 1.0 anropar avkodaren Kör med en DXVA_ConfigPictureDecode struktur för att konfigurera accerlatorn. I DXVA 2.0 använder avkodaren gränssnittet IDirectXVideoDecoderService, enligt beskrivningen i nästa avsnitt.
- Avkodaren allokerar de okomprimerade buffertarna. Videorenderaren allokerar dem inte längre.
- I stället för att anropa IAMVideoAccelerator::D isplayFrame för att visa den avkodade ramen, levererar avkodaren ramen till renderaren genom att anropa IMemInputPin::Ta emot, precis som med programavkodning.
- Avkodaren ansvarar inte längre för att kontrollera när databuffertar är säkra för uppdateringar. DXVA 2.0 har därför ingen metod som motsvarar IAMVideoAccelerator::QueryRenderStatus.
- Blandning av underbilder görs av videorenderaren med hjälp av DXVA2.0-videoprocessor-API:erna. Avkodare som levererar underbilder (till exempel DVD-avkodare) bör skicka underbildsdata på ett separat utgångsstift.
För avkodningsåtgärder använder DXVA 2.0 samma datastrukturer som DXVA 1.0.
Det förbättrade filtret för videoåtergivning (EVR) stöder DXVA 2.0. Filter för videomixningsåtergivning (VMR-7 och VMR-9) stöder endast DXVA 1.0.
Hitta en avkodarkonfiguration
När avkodaren har förhandlat om utdatamedietypen måste den hitta en kompatibel konfiguration för DXVA-avkodarens enhet. Du kan utföra det här steget i utgångsstiftets CBaseOutputPin::CompleteConnect metod. Det här steget säkerställer att grafikdrivrutinen stöder de funktioner som krävs av avkodaren innan avkodaren förbinder sig att använda DXVA.
Gör följande för att hitta en konfiguration för avkodarens enhet:
Fråga renderarens ingångsstift efter IMFGetService--gränssnittet.
Anropa IMFGetService::GetService för att få en pekare till gränssnittet IDirect3DDeviceManager9. Tjänstens GUID är MR_VIDEO_ACCELERATION_SERVICE.
Anropa IDirect3DDeviceManager9::OpenDeviceHandle för att få ett handtag till renderarens Direct3D-enhet.
Anropa IDirect3DDeviceManager9::GetVideoService och skicka in enhetshandtaget. Den här metoden returnerar en pekare till gränssnittet IDirectXVideoDecoderService.
Anropa IDirectXVideoDecoderService::GetDecoderDeviceGuids. Den här metoden returnerar en matris med dekodarenhets-GUID:er.
Gå igenom matrisen med dekodar-GUID:er för att hitta de som avkodarfiltret stöder. För en MPEG-2-avkodare letar du till exempel efter DXVA2_ModeMPEG2_MOCOMP, DXVA2_ModeMPEG2_IDCTeller DXVA2_ModeMPEG2_VLD.
När du hittar en GUID för en kandidatdekoderenhet, passerar du GUID till IDirectXVideoDecoderService::GetDecoderRenderTargets-metoden. Den här metoden returnerar en matris med återgivningsmålformat som anges som D3DFORMAT värden.
Loopa igenom målformaten för återgivning och leta efter ett som matchar utdataformatet. Normalt stöder en dekoderenhet ett enda målformat för återgivning. Avkodarfiltret bör ansluta till renderaren med hjälp av den här undertypen. I det första anropet till CompleteConnectkan avkodaren fastställa målformatet för återgivningen och sedan returnera det här formatet som en önskad utdatatyp.
Anropa IDirectXVideoDecoderService::GetDecoderConfigurations. Skicka in samma dekodarenhets-GUID tillsammans med en DXVA2_VideoDesc struktur som beskriver det föreslagna formatet. Metoden returnerar en matris med DXVA2_ConfigPictureDecode strukturer. Varje struktur beskriver en möjlig konfiguration för avkodarenheten.
Förutsatt att de föregående stegen lyckas, lagra Direct3D-enhetshandtaget, avkodarens enhetsGUID och konfigurationsstrukturen. Filtret använder den här informationen för att skapa avkodarenheten.
Följande kod visar hur du hittar en avkodarkonfiguration.
HRESULT CDecoder::ConfigureDXVA2(IPin *pPin)
{
UINT cDecoderGuids = 0;
BOOL bFoundDXVA2Configuration = FALSE;
GUID guidDecoder = GUID_NULL;
DXVA2_ConfigPictureDecode config;
ZeroMemory(&config, sizeof(config));
// Variables that follow must be cleaned up at the end.
IMFGetService *pGetService = NULL;
IDirect3DDeviceManager9 *pDeviceManager = NULL;
IDirectXVideoDecoderService *pDecoderService = NULL;
GUID *pDecoderGuids = NULL; // size = cDecoderGuids
HANDLE hDevice = INVALID_HANDLE_VALUE;
// Query the pin for IMFGetService.
HRESULT hr = pPin->QueryInterface(IID_PPV_ARGS(&pGetService));
// Get the Direct3D device manager.
if (SUCCEEDED(hr))
{
hr = pGetService->GetService(
MR_VIDEO_ACCELERATION_SERVICE,
IID_PPV_ARGS(&pDeviceManager)
);
}
// Open a new device handle.
if (SUCCEEDED(hr))
{
hr = pDeviceManager->OpenDeviceHandle(&hDevice);
}
// Get the video decoder service.
if (SUCCEEDED(hr))
{
hr = pDeviceManager->GetVideoService(
hDevice, IID_PPV_ARGS(&pDecoderService));
}
// Get the decoder GUIDs.
if (SUCCEEDED(hr))
{
hr = pDecoderService->GetDecoderDeviceGuids(
&cDecoderGuids, &pDecoderGuids);
}
if (SUCCEEDED(hr))
{
// Look for the decoder GUIDs we want.
for (UINT iGuid = 0; iGuid < cDecoderGuids; iGuid++)
{
// Do we support this mode?
if (!IsSupportedDecoderMode(pDecoderGuids[iGuid]))
{
continue;
}
// Find a configuration that we support.
hr = FindDecoderConfiguration(pDecoderService, pDecoderGuids[iGuid],
&config, &bFoundDXVA2Configuration);
if (FAILED(hr))
{
break;
}
if (bFoundDXVA2Configuration)
{
// Found a good configuration. Save the GUID and exit the loop.
guidDecoder = pDecoderGuids[iGuid];
break;
}
}
}
if (!bFoundDXVA2Configuration)
{
hr = E_FAIL; // Unable to find a configuration.
}
if (SUCCEEDED(hr))
{
// Store the things we will need later.
SafeRelease(&m_pDecoderService);
m_pDecoderService = pDecoderService;
m_pDecoderService->AddRef();
m_DecoderConfig = config;
m_DecoderGuid = guidDecoder;
m_hDevice = hDevice;
}
if (FAILED(hr))
{
if (hDevice != INVALID_HANDLE_VALUE)
{
pDeviceManager->CloseDeviceHandle(hDevice);
}
}
SafeRelease(&pGetService);
SafeRelease(&pDeviceManager);
SafeRelease(&pDecoderService);
return hr;
}
HRESULT CDecoder::FindDecoderConfiguration(
/* [in] */ IDirectXVideoDecoderService *pDecoderService,
/* [in] */ const GUID& guidDecoder,
/* [out] */ DXVA2_ConfigPictureDecode *pSelectedConfig,
/* [out] */ BOOL *pbFoundDXVA2Configuration
)
{
HRESULT hr = S_OK;
UINT cFormats = 0;
UINT cConfigurations = 0;
D3DFORMAT *pFormats = NULL; // size = cFormats
DXVA2_ConfigPictureDecode *pConfig = NULL; // size = cConfigurations
// Find the valid render target formats for this decoder GUID.
hr = pDecoderService->GetDecoderRenderTargets(
guidDecoder,
&cFormats,
&pFormats
);
if (SUCCEEDED(hr))
{
// Look for a format that matches our output format.
for (UINT iFormat = 0; iFormat < cFormats; iFormat++)
{
if (pFormats[iFormat] != (D3DFORMAT)m_fccOutputFormat)
{
continue;
}
// Fill in the video description. Set the width, height, format,
// and frame rate.
DXVA2_VideoDesc videoDesc = {0};
FillInVideoDescription(&videoDesc); // Private helper function.
videoDesc.Format = pFormats[iFormat];
// Get the available configurations.
hr = pDecoderService->GetDecoderConfigurations(
guidDecoder,
&videoDesc,
NULL, // Reserved.
&cConfigurations,
&pConfig
);
if (FAILED(hr))
{
break;
}
// Find a supported configuration.
for (UINT iConfig = 0; iConfig < cConfigurations; iConfig++)
{
if (IsSupportedDecoderConfig(pConfig[iConfig]))
{
// This configuration is good.
*pbFoundDXVA2Configuration = TRUE;
*pSelectedConfig = pConfig[iConfig];
break;
}
}
CoTaskMemFree(pConfig);
break;
} // End of formats loop.
}
CoTaskMemFree(pFormats);
// Note: It is possible to return S_OK without finding a configuration.
return hr;
}
Eftersom det här exemplet är allmänt har en del av logiken placerats i hjälpfunktioner som skulle behöva implementeras av avkodaren. Följande kod visar deklarationerna för dessa funktioner:
// Returns TRUE if the decoder supports a given decoding mode.
BOOL IsSupportedDecoderMode(const GUID& mode);
// Returns TRUE if the decoder supports a given decoding configuration.
BOOL IsSupportedDecoderConfig(const DXVA2_ConfigPictureDecode& config);
// Fills in a DXVA2_VideoDesc structure based on the input format.
void FillInVideoDescription(DXVA2_VideoDesc *pDesc);
Meddelar videoåtergivaren
Om avkodaren hittar en avkodarkonfiguration är nästa steg att meddela videoåtergivningen att avkodaren använder maskinvaruacceleration. Du kan utföra det här steget i metoden CompleteConnect. Det här steget måste utföras innan allokeraren väljs, eftersom det påverkar hur allokeraren väljs.
- Fråga renderarens inmatningsstift om IMFGetService--gränssnittet.
- Anropa IMFGetService::GetService för att få en pekare till gränssnittet IDirectXVideoMemoryConfiguration. Tjänstens GUID är MR_VIDEO_ACCELERATION_SERVICE.
- Anropa IDirectXVideoMemoryConfiguration::GetAvailableSurfaceTypeByIndex inom en loop, för att öka variabeln dwTypeIndex från noll. Stoppa när metoden returnerar värdet DXVA2_SurfaceType_DecoderRenderTarget i parametern pdwType. Det här steget säkerställer att videoåtergivningen stöder maskinvaruaccelererad avkodning. Det här steget lyckas alltid för EVR-filtret.
- Om föregående steg lyckades anropar du IDirectXVideoMemoryConfiguration::SetSurfaceType med värdet DXVA2_SurfaceType_DecoderRenderTarget. Genom att anropa SetSurfaceType med det här värdet försätts videoåtergivningen i DXVA-läge. När videoåtergivningen är i det här läget måste avkodaren ange en egen allokerare.
Följande kod visar hur du underrättar videorenderaren.
HRESULT CDecoder::SetEVRForDXVA2(IPin *pPin)
{
HRESULT hr = S_OK;
IMFGetService *pGetService = NULL;
IDirectXVideoMemoryConfiguration *pVideoConfig = NULL;
// Query the pin for IMFGetService.
hr = pPin->QueryInterface(__uuidof(IMFGetService), (void**)&pGetService);
// Get the IDirectXVideoMemoryConfiguration interface.
if (SUCCEEDED(hr))
{
hr = pGetService->GetService(
MR_VIDEO_ACCELERATION_SERVICE, IID_PPV_ARGS(&pVideoConfig));
}
// Notify the EVR.
if (SUCCEEDED(hr))
{
DXVA2_SurfaceType surfaceType;
for (DWORD iTypeIndex = 0; ; iTypeIndex++)
{
hr = pVideoConfig->GetAvailableSurfaceTypeByIndex(iTypeIndex, &surfaceType);
if (FAILED(hr))
{
break;
}
if (surfaceType == DXVA2_SurfaceType_DecoderRenderTarget)
{
hr = pVideoConfig->SetSurfaceType(DXVA2_SurfaceType_DecoderRenderTarget);
break;
}
}
}
SafeRelease(&pGetService);
SafeRelease(&pVideoConfig);
return hr;
}
Om avkodaren hittar en giltig konfiguration och lyckas meddela videorenderaren, kan avkodaren använda DXVA för avkodning. Avkodaren måste implementera en anpassad allokerare för utdatastiftet enligt beskrivningen i nästa avsnitt.
Allokera okomprimerade buffertar
I DXVA 2.0 ansvarar avkodaren för allokering av Direct3D-ytor som ska användas som okomprimerade videobuffertar. Därför måste avkodaren implementera en anpassad allokerare som skapar ytorna. Medieexemplen som tillhandahålls av den här allokeraren innehåller pekare till Direct3D-ytorna. EVR hämtar en pekare till ytan genom att anropa IMFGetService::GetService i medieexemplet. Tjänstidentifieraren är MR_BUFFER_SERVICE.
Utför följande steg för att tillhandahålla den anpassade allokeraren:
- Definiera en klass för medieexemplen. Den här klassen kan härledas från klassen CMediaSample. Gör följande i den här klassen:
- Lagra en pekare på Direct3D-ytan.
- Implementera gränssnittet IMFGetService. Om tjänstens GUID är MR_BUFFER_SERVICEi metoden GetService frågar du Direct3D-ytan efter det begärda gränssnittet. Annars kan GetService returnera MF_E_UNSUPPORTED_SERVICE.
- Åsidosätt metoden CMediaSample::GetPointer för att returnera E_NOTIMPL.
- Definiera en klass för allokeraren. Allokeraren kan härledas från klassen CBaseAllocator. Gör följande i den här klassen.
- Åsidosätt metoden CBaseAllocator::Alloc. I den här metoden anropar du IDirectXVideoAccelerationService::CreateSurface för att skapa ytorna. (Gränssnittet IDirectXVideoDecoderService ärver den här metoden från IDirectXVideoAccelerationService.)
- Åsidosätt metoden CBaseAllocator::Free för att frigöra ytorna.
- I filtrets utmatningsstift ska du åsidosätta metoden CBaseOutputPin::InitAllocator. I den här metoden skapar du en instans av din anpassade allokerare.
- I ditt filter implementerar du metoden CTransformFilter::DecideBufferSize. Parametern pProperties anger antalet ytor som krävs för EVR. Lägg detta värde till antalet ytor som din avkodare kräver, och anropa IMemAllocator::SetProperties på allokeraren.
Följande kod visar hur du implementerar medieexempelklassen:
class CDecoderSample : public CMediaSample, public IMFGetService
{
friend class CDecoderAllocator;
public:
CDecoderSample(CDecoderAllocator *pAlloc, HRESULT *phr)
: CMediaSample(NAME("DecoderSample"), (CBaseAllocator*)pAlloc, phr, NULL, 0),
m_pSurface(NULL),
m_dwSurfaceId(0)
{
}
// Note: CMediaSample does not derive from CUnknown, so we cannot use the
// DECLARE_IUNKNOWN macro that is used by most of the filter classes.
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv, E_POINTER);
if (riid == IID_IMFGetService)
{
*ppv = static_cast<IMFGetService*>(this);
AddRef();
return S_OK;
}
else
{
return CMediaSample::QueryInterface(riid, ppv);
}
}
STDMETHODIMP_(ULONG) AddRef()
{
return CMediaSample::AddRef();
}
STDMETHODIMP_(ULONG) Release()
{
// Return a temporary variable for thread safety.
ULONG cRef = CMediaSample::Release();
return cRef;
}
// IMFGetService::GetService
STDMETHODIMP GetService(REFGUID guidService, REFIID riid, LPVOID *ppv)
{
if (guidService != MR_BUFFER_SERVICE)
{
return MF_E_UNSUPPORTED_SERVICE;
}
else if (m_pSurface == NULL)
{
return E_NOINTERFACE;
}
else
{
return m_pSurface->QueryInterface(riid, ppv);
}
}
// Override GetPointer because this class does not manage a system memory buffer.
// The EVR uses the MR_BUFFER_SERVICE service to get the Direct3D surface.
STDMETHODIMP GetPointer(BYTE ** ppBuffer)
{
return E_NOTIMPL;
}
private:
// Sets the pointer to the Direct3D surface.
void SetSurface(DWORD surfaceId, IDirect3DSurface9 *pSurf)
{
SafeRelease(&m_pSurface);
m_pSurface = pSurf;
if (m_pSurface)
{
m_pSurface->AddRef();
}
m_dwSurfaceId = surfaceId;
}
IDirect3DSurface9 *m_pSurface;
DWORD m_dwSurfaceId;
};
Följande kod visar hur du implementerar metoden Alloc på allokeringsgivaren.
HRESULT CDecoderAllocator::Alloc()
{
CAutoLock lock(this);
HRESULT hr = S_OK;
if (m_pDXVA2Service == NULL)
{
return E_UNEXPECTED;
}
hr = CBaseAllocator::Alloc();
// If the requirements have not changed, do not reallocate.
if (hr == S_FALSE)
{
return S_OK;
}
if (SUCCEEDED(hr))
{
// Free the old resources.
Free();
// Allocate a new array of pointers.
m_ppRTSurfaceArray = new (std::nothrow) IDirect3DSurface9*[m_lCount];
if (m_ppRTSurfaceArray == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
ZeroMemory(m_ppRTSurfaceArray, sizeof(IDirect3DSurface9*) * m_lCount);
}
}
// Allocate the surfaces.
if (SUCCEEDED(hr))
{
hr = m_pDXVA2Service->CreateSurface(
m_dwWidth,
m_dwHeight,
m_lCount - 1,
(D3DFORMAT)m_dwFormat,
D3DPOOL_DEFAULT,
0,
DXVA2_VideoDecoderRenderTarget,
m_ppRTSurfaceArray,
NULL
);
}
if (SUCCEEDED(hr))
{
for (m_lAllocated = 0; m_lAllocated < m_lCount; m_lAllocated++)
{
CDecoderSample *pSample = new (std::nothrow) CDecoderSample(this, &hr);
if (pSample == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
if (FAILED(hr))
{
break;
}
// Assign the Direct3D surface pointer and the index.
pSample->SetSurface(m_lAllocated, m_ppRTSurfaceArray[m_lAllocated]);
// Add to the sample list.
m_lFree.Add(pSample);
}
}
if (SUCCEEDED(hr))
{
m_bChanged = FALSE;
}
return hr;
}
Här är koden för metoden Kostnadsfri:
void CDecoderAllocator::Free()
{
CMediaSample *pSample = NULL;
do
{
pSample = m_lFree.RemoveHead();
if (pSample)
{
delete pSample;
}
} while (pSample);
if (m_ppRTSurfaceArray)
{
for (long i = 0; i < m_lAllocated; i++)
{
SafeRelease(&m_ppRTSurfaceArray[i]);
}
delete [] m_ppRTSurfaceArray;
}
m_lAllocated = 0;
}
Mer information om hur du implementerar anpassade allokerare finns i avsnittet Tillhandahålla en anpassad allokeringsnyckel i DirectShow SDK-dokumentationen.
Avkodning
Om du vill skapa avkodarenheten anropar du IDirectXVideoDecoderService::CreateVideoDecoder. Metoden returnerar en pekare till IDirectXVideoDecoder gränssnitt för avkodarens enhet.
På varje bildruta, anropa IDirect3DDeviceManager9::TestDevice för att testa enhetshandtaget. Om enheten har ändrats returnerar metoden DXVA2_E_NEW_VIDEO_DEVICE. Om detta inträffar gör du följande:
- Stäng enhetens handtag genom att anropa IDirect3DDeviceManager9::CloseDeviceHandle.
- Släpp pekarna IDirectXVideoDecoderService och IDirectXVideoDecoder.
- Öppna ett nytt enhetshandtag.
- Förhandla fram en ny konfiguration av avkodaren enligt beskrivningen i avsnittet Hitta en avkodarkonfiguration.
- Skapa en ny avkodare.
Förutsatt att enhetshandtaget är giltigt fungerar avkodningsprocessen på följande sätt:
- Anropa IDirectXVideoDecoder::BeginFrame.
- Gör följande en eller flera gånger:
- Anropa IDirectXVideoDecoder::GetBuffer för att hämta en DXVA-avkodarbuffert.
- Fyll bufferten.
- Anropa IDirectXVideoDecoder::ReleaseBuffer.
- Anropa IDirectXVideoDecoder::Utför för att utföra avkodningsåtgärderna i ramen.
DXVA 2.0 använder samma datastrukturer som DXVA 1.0 för avkodningsåtgärder. För den ursprungliga uppsättningen DXVA-profiler (för H.261, H.263 och MPEG-2) beskrivs dessa datastrukturer i DXVA 1.0-specifikationen.
Inom varje par BeginFrame-/Execute--anrop kan du anropa GetBuffer flera gånger, men bara en gång för varje typ av DXVA-buffert. Om du anropar den två gånger med samma bufferttyp skriver du över data.
När du har anropat Kör, anropar du IMemInputPin::Ta emot för att leverera bilden till videorenderaren, precis som vid programvaruavkodning. Metoden Ta emot är asynkron. när den har returnerats kan avkodaren fortsätta avkoda nästa bildruta. Visningsdrivrutinen förhindrar att avkodningskommandon skriver över bufferten medan bufferten används. Avkodaren bör inte återanvända en yta för att avkoda en annan bildruta förrän renderaren har släppt provet. När renderaren släpper exemplet placerar allokeraren tillbaka exemplet i sin pool med tillgängliga exempel. Om du vill hämta nästa tillgängliga prov anropar du CBaseOutputPin::GetDeliveryBuffer, som i sin tur anropar IMemAllocator::GetBuffer. Mer information finns i avsnittet Översikt över dataflöde i DirectShow i DirectShow-dokumentationen.
Relaterade ämnen