Pengambilan Audio/Video di Media Foundation

Microsoft Media Foundation mendukung pengambilan audio dan video. Perangkat pengambilan video didukung melalui driver kelas UVC dan harus kompatibel dengan UVC 1.1. Perangkat pengambilan audio didukung melalui Windows Audio Session API (WASAPI).

Perangkat penangkapan diwakili dalam Media Foundation oleh objek sumber media, yang mengekspos antarmuka IMFMediaSource . Dalam kebanyakan kasus, aplikasi tidak akan menggunakan antarmuka ini secara langsung, tetapi akan menggunakan API tingkat yang lebih tinggi seperti Pembaca Sumber untuk mengontrol perangkat penangkapan.

Menghitung Perangkat Pengambilan

Untuk menghitung perangkat pengambilan pada sistem, lakukan langkah-langkah berikut:

  1. Panggil fungsi MFCreateAttributes untuk membuat penyimpanan atribut.

  2. Atur atribut MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE ke salah satu nilai berikut:

    Nilai Deskripsi
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID Menghitung perangkat pengambilan audio.
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID Menghitung perangkat pengambilan video.

     

  3. Panggil fungsi MFEnumDeviceSources. Fungsi ini mengalokasikan array penunjuk IMFActivate. Setiap penunjuk mewakili objek aktivasi untuk satu perangkat pada sistem.

  4. Panggil metode IMFActivate::ActivateObject untuk membuat instans sumber media dari salah satu objek aktivasi.

Contoh berikut membuat sumber media untuk perangkat pengambilan video pertama dalam daftar enumerasi:

HRESULT CreateVideoCaptureDevice(IMFMediaSource **ppSource)
{
    *ppSource = NULL;

    UINT32 count = 0;

    IMFAttributes *pConfig = NULL;
    IMFActivate **ppDevices = NULL;

    // Create an attribute store to hold the search criteria.
    HRESULT hr = MFCreateAttributes(&pConfig, 1);

    // Request video capture devices.
    if (SUCCEEDED(hr))
    {
        hr = pConfig->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
            );
    }

    // Enumerate the devices,
    if (SUCCEEDED(hr))
    {
        hr = MFEnumDeviceSources(pConfig, &ppDevices, &count);
    }

    // Create a media source for the first device in the list.
    if (SUCCEEDED(hr))
    {
        if (count > 0)
        {
            hr = ppDevices[0]->ActivateObject(IID_PPV_ARGS(ppSource));
        }
        else
        {
            hr = MF_E_NOT_FOUND;
        }
    }

    for (DWORD i = 0; i < count; i++)
    {
        ppDevices[i]->Release();
    }
    CoTaskMemFree(ppDevices);
    return hr;
}

Anda bisa mengkueri objek aktivasi untuk berbagai atribut, termasuk yang berikut ini:

Contoh berikut mengambil array penunjuk IMFActivate dan mencetak nama tampilan setiap perangkat ke jendela debug:

void DebugShowDeviceNames(IMFActivate **ppDevices, UINT count)
{
    for (DWORD i = 0; i < count; i++)
    {
        HRESULT hr = S_OK;
        WCHAR *szFriendlyName = NULL;
    
        // Try to get the display name.
        UINT32 cchName;
        hr = ppDevices[i]->GetAllocatedString(
            MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
            &szFriendlyName, &cchName);

        if (SUCCEEDED(hr))
        {
            OutputDebugString(szFriendlyName);
            OutputDebugString(L"\n");
        }
        CoTaskMemFree(szFriendlyName);
    }
}

Jika Anda sudah mengetahui tautan simbolis untuk perangkat video, ada cara lain untuk membuat sumber media untuk perangkat:

  1. Panggil MFCreateAttributes untuk membuat penyimpanan atribut.
  2. Atur atribut MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE ke MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID.
  3. Atur atribut MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK ke tautan simbolis.
  4. Panggil fungsi MFCreateDeviceSource atau MFCreateDeviceSourceActivate. Yang pertama mengembalikan pointer IMFMediaSource. Yang terakhir mengembalikan penunjuk IMFActivate ke objek aktivasi. Anda dapat menggunakan objek aktivasi untuk membuat sumber. (Objek aktivasi dapat di-marshal ke proses lain, sehingga berguna jika Anda ingin membuat sumber dalam proses lain. Untuk informasi selengkapnya, lihat Objek Aktivasi.)

Contoh berikut mengambil tautan simbolis perangkat video dan membuat sumber media.

HRESULT CreateVideoCaptureDevice(PCWSTR *pszSymbolicLink, IMFMediaSource **ppSource)
{
    *ppSource = NULL;
    
    IMFAttributes *pAttributes = NULL;
    IMFMediaSource *pSource = NULL;

    HRESULT hr = MFCreateAttributes(&pAttributes, 2);

    // Set the device type to video.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
            );
    }


    // Set the symbolic link.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetString(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
            (LPCWSTR)pszSymbolicLink
            );            
    }

    if (SUCCEEDED(hr))
    {
        hr = MFCreateDeviceSource(pAttributes, ppSource);
    }

    SafeRelease(&pAttributes);
    return hr;    
}

Ada cara yang setara untuk membuat perangkat audio dari ID titik akhir audio:

  1. Panggil MFCreateAttributes untuk membuat penyimpanan atribut.
  2. Atur atribut MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE ke MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID.
  3. Atur atribut MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID ke ID titik akhir.
  4. Panggil fungsi MFCreateDeviceSource atau MFCreateDeviceSourceActivate.

Contoh berikut mengambil ID titik akhir audio dan membuat sumber media.

HRESULT CreateAudioCaptureDevice(PCWSTR *pszEndPointID, IMFMediaSource **ppSource)
{
    *ppSource = NULL;
    
    IMFAttributes *pAttributes = NULL;
    IMFMediaSource *pSource = NULL;

    HRESULT hr = MFCreateAttributes(&pAttributes, 2);

    // Set the device type to audio.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
            );
    }

    // Set the endpoint ID.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetString(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID,
            (LPCWSTR)pszEndPointID
            ); 
    }

    if (SUCCEEDED(hr))
    {
        hr = MFCreateDeviceSource(pAttributes, ppSource);
    }

    SafeRelease(&pAttributes);
    return hr;    
}

Menggunakan perangkat penangkapan

Setelah Anda membuat sumber media untuk perangkat pengambilan, gunakan Pembaca Sumber untuk mendapatkan data dari perangkat. Pembaca Sumber mengirimkan sampel media yang berisi data audio tangkap atau bingkai video. Langkah selanjutnya tergantung pada skenario aplikasi Anda:

  • Pratinjau video: Gunakan Microsoft Direct3D atau Direct2D untuk menampilkan video.
  • Pengambilan file: Gunakan Sink Writer untuk mengodekan file.
  • Pratinjau audio: Gunakan WASAPI.

Jika Anda ingin menggabungkan pengambilan audio dengan pengambilan video, gunakan sumber media agregat. Sumber media agregat berisi kumpulan sumber media dan menggabungkan semua alirannya ke dalam satu objek sumber media. Untuk membuat instans sumber media agregat, panggil fungsi MFCreateAggregateSource.

Mematikan perangkat pengambilan

Ketika perangkat pengambilan tidak lagi diperlukan, Anda harus mematikan perangkat dengan memanggil Matikan pada objek IMFMediaSource yang Anda peroleh dengan memanggil MFCreateDeviceSource atau IMFActivate::ActivateObject. Kegagalan untuk memanggil Matikan dapat mengakibatkan kebocoran memori karena sistem dapat menyimpan referensi ke sumber daya IMFMediaSource hingga Matikan dipanggil.

if (g_pSource)
{
    g_pSource->Shutdown();
    g_pSource->Release();
    g_pSource = NULL;
}

Jika Anda mengalokasikan string yang berisi tautan simbolis ke perangkat pengambilan, Anda juga harus merilis objek ini.

    CoTaskMemFree(g_pwszSymbolicLink);
    g_pwszSymbolicLink = NULL;

    g_cchSymbolicLink = 0;

Pengambilan Audio/Video