共用方式為


在 DMO 上設定媒體類型

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

在 DMO 可以處理任何資料之前,用戶端必須為每個資料流程設定媒體類型。 (此規則有一個次要例外狀況;請參閱 選擇性 Streams.) 若要尋找資料流程數目,請呼叫 IMediaObject::GetStreamCount 方法:

DWORD cInput = 0, cOutput = 0;
pDMO->GetStreamCount(&cInput, &cOutput);

這個方法會傳回兩個值:輸入數目和輸出數目。 這些值在 DMO 的存留期內是固定的。

慣用類型

針對每個資料流程,DMO 會依喜好設定順序指派可能媒體類型的清單。 例如,慣用的類型可能是 32-RGB、24 位 RGB 和 16 位 RGB,依該順序。 當用戶端設定媒體類型時,可以使用這些清單作為提示。 若要擷取資料流程的慣用類型,請呼叫 IMediaObject::GetInputType 方法或 IMediaObject::GetOutputType 方法。 指定從零) 開始 (類型的資料流程編號和索引值。 例如,下列程式碼會從第一個輸入資料流程擷取第一個慣用的類型:

DMO_MEDIA_TYPE mt
hr = pDMO->GetInputType(0, 0, &mt)
if (SUCCEEDED(hr))
{
    // Examine this media type (not shown).
    /* ... */

    // Free the format block.
    MoFreeMediaType(&mt);
}

若要列舉指定資料流程上所有慣用的媒體類型,請使用迴圈來遞增類型索引,直到方法傳回DMO_E_NO_MORE_ITEMS為止,如下列範例所示:

DMO_MEDIA_TYPE mt;
DWORD dwType = 0;
while (hr = pDMO->GetInputType(0, dwType, &mt), SUCCEEDED(hr))
{
    // Examine this media type (not shown).
    /* ... */

    // Free the format block.
    MoFreeMediaType(&mt);
    ++dwType;
}

您應該注意關於慣用類型的下列幾點:

  • DMO 可能會傳回沒有格式區塊的類型。 例如,DMO 可以指定視訊類型,例如 24 位 RGB,而不需要提供影像的寬度和高度。 不過,當您設定類型時,必須提供完整的格式區塊。 (某些媒體類型,例如 MIDI,絕對不需要格式區塊,在此情況下,此備註不適用。)
  • DMO 不需要支援傳回的每個慣用型別組合。 例如,如果 DMO 有兩個數據流,而且每個資料流程都有四個慣用類型,則有 16 個可能的組合,但並非所有類型都保證有效。
  • 當用戶端設定一個資料流程的媒體類型時,DMO 可能會更新其他資料流程的慣用類型,以反映新的狀態。 不過,不需要這麼做。
  • 對於某些資料流程,DMO 可能不會提供任何慣用的類型。 一般而言,DMO 應該在某些資料流程上至少提供一些慣用的類型。
  • DMO 不需要提供可接受之媒體類型的完整清單。 DMO 可能支援的「非反轉」類型,但不提供慣用的類型。

簡單來說,用戶端應該只將慣用的類型視為指導方針。 特定支援類型的唯一方法是測試它們,如下一節所述。

在資料流程上設定媒體類型

使用 IMediaObject::SetInputTypeIMediaObject::SetOutputType 方法來設定每個資料流程的類型。 您必須提供包含媒體類型完整描述 的DMO_MEDIA_TYPE 結構。 下列範例會使用 44.1-kHz 16 位的立體 PCM 音訊,在輸入資料流程 0 上設定媒體類型:

DMO_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(DMO_MEDIA_TYPE));
// Allocate memory for the format block.
HRESULT hr = MoInitMediaType(&mt, sizeof(WAVEFORMATEX));
if (SUCCEEDED(hr))
{
    // Set the type GUIDs.
    mt.majortype  = MEDIATYPE_Audio;
    mt.subtype    = MEDIASUBTYPE_PCM;
    mt.formattype = FORMAT_WaveFormatEx;

    // Initialize the format block.
    WAVEFORMATEX *pWave = reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat);
    pWave->wFormatTag = WAVE_FORMAT_PCM;
    pWave->nChannels = 2;
    pWave->nSamplesPerSec = 44100;
    pWave->wBitsPerSample = 16;
    pWave->nBlockAlign = (pWave->nChannels * pWave->wBitsPerSample) / 8;
    pWave->nAvgBytesPerSec = pWave->nSamplesPerSec * pWave->nBlockAlign;
    pWave->cbSize = 0;

    // Set the media type.
    hr = pDMO->SetInputType(0, &mt, 0); 

    // Release the format block.
    MoFreeMediaType(&mt);
}

若要測試媒體類型而不進行設定,請使用 DMO_SET_TYPEF_TEST_ONLY 旗標呼叫 SetInputTypeSetOutputType 。 如果類型可接受,則方法會傳回S_OK,否則會傳回S_FALSE:

if (S_OK == pDMO->SetInputType(0, &mt, DMO_SET_TYPEF_TEST_ONLY)
{
    // Media type is OK.
}

由於某個資料流程上的設定可能會影響另一個資料流程,因此您可能需要清除資料流程的媒體類型。 若要這樣做,請使用 DMO_SET_TYPEF_CLEAR 旗標呼叫 SetInputTypeSetOutputType

針對解碼器 DMO,用戶端通常會先設定輸入類型,然後選擇輸出類型。 針對編碼器 DMO,用戶端會先設定輸出類型,然後再設定輸入類型。

直接裝載 DMO