Impostazione delle proprietà di compressione video

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

I filtri di compressione video possono supportare l'interfaccia IAMVideoCompression nei pin di output. Usare questa interfaccia per impostare le proprietà di compressione, ad esempio la frequenza dei fotogrammi chiave, il numero di fotogrammi stimati (P) per fotogrammi chiave e la qualità di compressione relativa.

Prima di tutto, chiamare il metodo IBaseFilter::EnumPins per trovare il pin di output del filtro e eseguire una query sul pin per l'interfaccia. Alcuni filtri potrebbero non supportare l'interfaccia. Altri possono esporre l'interfaccia, ma non supportare ogni proprietà di compressione. Per determinare quali proprietà sono supportate, chiamare IAMVideoCompression::GetInfo. Questo metodo restituisce diverse informazioni:

  • Set di flag di funzionalità
  • Stringa descrittiva e stringa numero di versione
  • Valori predefiniti per la frequenza dei fotogrammi chiave, la frequenza dei fotogrammi P e la qualità (se supportata)

Il metodo ha la sintassi seguente:

hr = pCompress->GetInfo(pszVersion, &cbVersion, pszDesc, &cbDesc, 
         &lKeyFrame, &lPFrame, &dblQuality, &lCap);

I parametri pszVersion e pszDesc sono buffer a caratteri wide che ricevono la stringa di versione e la stringa di descrizione. I parametri cbVersion e cbDesc ricevono le dimensioni del buffer necessarie in byte (non caratteri). I parametri lKeyFrame, lPFrame e dblQuality ricevono i valori predefiniti per la frequenza dei fotogrammi chiave, la frequenza dei fotogrammi P e la qualità. La qualità viene espressa come numero a virgola mobile da 0,0 a 1,0. Il parametro lCap riceve un or bit per bit dei flag di funzionalità, definiti dal tipo enumerato CompressionCaps.

Uno di questi parametri può essere NULL, nel qual caso il metodo ignora tale parametro. Ad esempio, per allocare buffer per le stringhe di versione e descrizione, chiamare prima il metodo con NULL nei primi e nel terzo parametro. Usare i valori restituiti per cbVersion e cbDesc per allocare i buffer e quindi chiamare di nuovo il metodo:

int cbVersion, cbDesc; // Size in bytes, not characters!
hr = pCompress->GetInfo(0, &cbVersion, 0, &cbDesc, 0, 0, 0, 0);
if (SUCCEEDED(hr))
{
    WCHAR *pszVersion = new WCHAR[cbVersion/2]; // Wide character = 2 bytes
    WCHAR *pszDesc = new WCHAR[cbDesc/2];
    hr = pCompress->GetInfo(pszVersion, 0, pszDesc, 0, 0, 0, 0, 0);
}

Il valore di lCap indica quale degli altri metodi IAMVideoCompression supporta il filtro. Ad esempio, se lCap contiene il flag CompressionCaps_CanKeyFrame, è possibile chiamare IAMVideoCompression::get_KeyFrameRate per ottenere la frequenza dei fotogrammi chiave e IAMVideoCompression::p ut_KeyFrameRate per impostare la frequenza dei fotogrammi chiave. Un valore negativo indica che il filtro userà il valore predefinito, come ottenuto da IAMVideoCompression::GetInfo. Ad esempio:

if (lCap & CompressionCaps_CanKeyFrame)
{
    hr = pCompress->get_KeyFrameRate(&lKeyFrame);
    if (FAILED(hr) || lKeyFrame < 0)
    {
        lKeyFrame = lDefaultKeyFrame; // From GetInfo.
    }
}

L'esempio di codice seguente tenta di trovare l'interfaccia IAMVideoCompression nel pin di output. Se ha esito positivo, recupera i valori predefiniti e effettivi per le proprietà di compressione:

HRESULT hr = E_FAIL;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
IAMVideoCompression *pCompress = NULL;

// Find the pin that supports IAMVideoCompression (if any).
pFilter->EnumPins(&pEnum);
while (S_OK == pEnum->Next(1, &pPin, NULL))
{
    hr = pPin->QueryInterface(IID_IAMVideoCompression, (void**)&pCompress);
    pPin->Release();
    if (SUCCEEDED(hr)) // Found the interface.
    {
        break;
    }
}
if (SUCCEEDED(hr)) 
{
    long lCap;                     // Capability flags
    long lKeyFrame, lPFrame;       // Real values
    double m_Quality;
    long lKeyFrameDef, lPFrameDef; // Default values
    double QualityDef;
    
    // Get default values and capabilities.
    hr = pCompress->GetInfo(0, 0, 0, 0, &KeyFrameDef, &lPFrameDef,
             &QualityDef, &lCap);
    if (SUCCEEDED(hr))
    {
        // Get actual values where possible.
        if (lCap & CompressionCaps_CanKeyFrame)
        {
            hr = pCompress->get_KeyFrameRate(&lKeyFrame);
            if (FAILED(hr) || lKeyFrame < 0)
                lKeyFrame = lKeyFrameDef;
        }
        if (lCap & CompressionCaps_CanBFrame)
        {
            hr = pCompress->get_PFramesPerKeyFrame(&lPFrame);
            if (FAILED(hr) || lPFrame < 0)
                lPFrame = lPFrameDef;
        }
        if (lCap & CompressionCaps_CanQuality)
        {
            hr = pCompress->get_Quality(&Quality);
            if (FAILED(hr) || Quality < 0)
                Quality = QualityDef;
        }
    }
}

Nota

Se si usa l'interfaccia ICaptureGraphBuilder2 per compilare il grafico, è possibile ottenere l'interfaccia IAMVideoCompression chiamando ICaptureGraphBuilder2::FindInterface, anziché usare IBaseFilter::EnumPins. Il metodo FindInterface è un metodo helper che cerca filtri e pin nel grafico per un'interfaccia specificata.