Поделиться через


Настройка свойств сжатия видео

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

Фильтры сжатия видео могут поддерживать интерфейс IAMVideoCompression на выходных контактах. Используйте этот интерфейс для задания свойств сжатия, таких как частота ключевых кадров, число прогнозируемых (P) кадров на ключевой кадр и относительное качество сжатия.

Сначала вызовите метод IBaseFilter::EnumPins , чтобы найти выходной контакт фильтра и запросить контакт для интерфейса. Некоторые фильтры могут вообще не поддерживать интерфейс. Другие могут предоставлять интерфейс, но не поддерживают все свойства сжатия. Чтобы определить, какие свойства поддерживаются, вызовите IAMVideoCompression::GetInfo. Этот метод возвращает несколько фрагментов информации:

  • Набор флагов возможностей
  • Описательная строка и строка номера версии
  • Значения по умолчанию для ключевой частоты кадров, частоты кадров P и качества (если это поддерживается)

Метод имеет следующий синтаксис:

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

Параметры pszVersion и pszDesc — это буферы расширенных символов, которые получают строку версии и строку описания. Параметры cbVersion и cbDesc получают требуемые размеры буфера в байтах (не символах). Параметры lKeyFrame, lPFrame и dblQuality получают значения по умолчанию для ключевой частоты кадров, частоты кадров P и качества. Качество выражается в виде числа с плавающей запятой от 0,0 до 1,0. Параметр lCap получает побитовое ИЛИ флагов возможностей, которые определяются перечисленным типом CompressionCaps .

Любой из этих параметров может иметь значение NULL, и в этом случае метод игнорирует этот параметр. Например, чтобы выделить буферы для строк версии и описания, сначала вызовите метод со значением NULL в первом и третьем параметрах. Используйте возвращаемые значения для cbVersion и cbDesc , чтобы выделить буферы, а затем снова вызовите метод :

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);
}

Значение lCap указывает, какой из других методов IAMVideoCompression поддерживает фильтр. Например, если lCap содержит флаг CompressionCaps_CanKeyFrame, можно вызвать IAMVideoCompression::get_KeyFrameRate для получения ключевой частоты кадров и IAMVideoCompression::p ut_KeyFrameRate , чтобы задать частоту кадров. Отрицательное значение указывает, что фильтр будет использовать значение по умолчанию, полученное из IAMVideoCompression::GetInfo. Пример:

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

В следующем примере кода пытается найти интерфейс IAMVideoCompression в выходном контакте. В случае успешного выполнения извлекаются значения по умолчанию и фактические значения для свойств сжатия:

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;
        }
    }
}

Примечание

Если для построения графа используется интерфейс ICaptureGraphBuilder2 , интерфейс IAMVideoCompression можно получить, вызвав ICaptureGraphBuilder2::FindInterface вместо использования IBaseFilter::EnumPins. Метод FindInterface — это вспомогательный метод, который выполняет поиск указанного интерфейса в фильтрах и закреплениях на графе.