Bagikan melalui


Menanggapi Peristiwa

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Tangkapan Audio/Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Audio/Video Capture di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

Artikel ini menjelaskan cara menanggapi peristiwa yang terjadi dalam grafik filter.

Cara Kerja Pemberitahuan Peristiwa

Saat aplikasi DirectShow berjalan, peristiwa dapat terjadi dalam grafik filter. Misalnya, filter mungkin mengalami kesalahan streaming. Filter memperingatkan Filter Graph Manager dengan mengirim peristiwa, yang terdiri dari kode peristiwa dan dua parameter peristiwa. Kode peristiwa menunjukkan jenis peristiwa, dan parameter peristiwa menyediakan informasi tambahan. Arti parameter tergantung pada kode peristiwa. Untuk daftar lengkap kode peristiwa, lihat Kode Pemberitahuan Peristiwa.

Beberapa peristiwa ditangani secara diam-diam oleh Filter Graph Manager, tanpa aplikasi diberi tahu. Peristiwa lain ditempatkan pada antrean untuk aplikasi. Tergantung pada aplikasinya, ada berbagai peristiwa yang mungkin perlu Anda tangani. Artikel ini berfokus pada tiga peristiwa yang sangat umum:

  • Peristiwa EC_COMPLETE menunjukkan bahwa pemutaran telah selesai secara normal.
  • Peristiwa EC_USERABORT menunjukkan bahwa pengguna telah mengganggu pemutaran. Perender video mengirim kejadian ini jika pengguna menutup jendela video.
  • Peristiwa EC_ERRORABORT menunjukkan bahwa kesalahan telah menyebabkan pemutaran dihentikan.

Menggunakan Pemberitahuan Peristiwa

Aplikasi dapat menginstruksikan Filter Graph Manager untuk mengirim pesan Windows ke jendela yang ditunjuk setiap kali peristiwa baru terjadi. Ini memungkinkan aplikasi untuk merespons di dalam perulangan pesan jendela. Pertama, tentukan pesan yang akan dikirim ke jendela aplikasi. Aplikasi dapat menggunakan nomor pesan dalam rentang dari WM_APP hingga 0xBFFF sebagai pesan privat:

#define WM_GRAPHNOTIFY  WM_APP + 1

Selanjutnya, kueri Filter Graph Manager untuk antarmuka IMediaEventEx dan panggil metode IMediaEventEx::SetNotifyWindow :

IMediaEventEx *g_pEvent = NULL;
g_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent);
g_pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

Metode ini menunjuk jendela yang ditentukan (g_hwnd) sebagai penerima pesan. Panggil metode setelah Anda membuat grafik filter, tetapi sebelum menjalankan grafik.

WM_GRAPHNOTIFY adalah pesan Windows biasa. Setiap kali Filter Graph Manager menempatkan peristiwa baru pada antrean peristiwa, Filter Graph Manager memposting pesan WM_GRAPHNOTIFY ke jendela aplikasi yang ditunjuk. Parameter lParam pesan sama dengan parameter ketiga di SetNotifyWindow. Parameter ini memungkinkan Anda mengirim data instans dengan pesan. Parameter wParam pesan jendela selalu nol.

Dalam fungsi WindowProc aplikasi Anda, tambahkan pernyataan kasus untuk pesan WM_GRAPHNOTIFY:

case WM_GRAPHNOTIFY:
    HandleGraphEvent();
    break;

Dalam fungsi penanganan aktivitas, panggil metode IMediaEvent::GetEvent untuk mengambil peristiwa dari antrean:

void HandleGraphEvent()
{
    // Disregard if we don't have an IMediaEventEx pointer.
    if (g_pEvent == NULL)
    {
        return;
    }
    // Get all the events
    long evCode;
    LONG_PTR param1, param2;
    HRESULT hr;
    while (SUCCEEDED(g_pEvent->GetEvent(&evCode, &param1, &param2, 0)))
    {
        g_pEvent->FreeEventParams(evCode, param1, param2);
        switch (evCode)
        {
        case EC_COMPLETE:  // Fall through.
        case EC_USERABORT: // Fall through.
        case EC_ERRORABORT:
            CleanUp();
            PostQuitMessage(0);
            return;
        }
    } 
}

Metode GetEvent mengambil kode peristiwa dan dua parameter peristiwa. Parameter GetEvent keempat menentukan lamanya waktu untuk menunggu peristiwa, dalam milidetik. Karena aplikasi memanggil metode ini sebagai respons terhadap pesan WM_GRAPHNOTIFY, peristiwa sudah diantrekan. Oleh karena itu, kami menetapkan nilai waktu habis ke nol.

Pemberitahuan peristiwa dan perulangan pesan keduanya asinkron, sehingga antrean mungkin menyimpan lebih dari satu peristiwa pada saat aplikasi Anda merespons pesan. Selain itu, Filter Graph Manager dapat menghapus peristiwa tertentu dari antrean, jika menjadi tidak valid. Oleh karena itu, Anda harus memanggil GetEvent sampai mengembalikan kode kegagalan, yang menunjukkan antrean kosong.

Dalam contoh ini, aplikasi merespons EC_COMPLETE, EC_USERABORT, dan EC_ERRORABORT dengan memanggil fungsi CleanUp yang ditentukan aplikasi, yang menyebabkan aplikasi berhenti dengan baik. Contoh mengabaikan dua parameter peristiwa. Setelah Anda mengambil peristiwa, panggil IMediaEvent::FreeEventParams ke sumber daya gratis apa pun yang terkait dengan parameter peristiwa.

Perhatikan bahwa peristiwa EC_COMPLETE tidak menyebabkan grafik filter berhenti. Aplikasi dapat menghentikan atau menjeda grafik. Jika Anda menghentikan grafik, filter merilis sumber daya apa pun yang dipegangnya. Jika Anda menjeda grafik, filter terus menyimpan sumber daya. Selain itu, saat perender video dijeda, perender video menampilkan gambar statis dari bingkai terbaru.

Sebelum Anda merilis pointer IMediaEventEx , batalkan pemberitahuan peristiwa dengan memanggil SetNotifyWindow dengan handel jendela NULL :

// Disable event notification before releasing the graph.
g_pEvent->SetNotifyWindow(NULL, 0, 0);
g_pEvent->Release();
g_pEvent = NULL;

Di handler pesan WM_GRAPHNOTIFY, periksa pointer IMediaEventEx sebelum memanggil GetEvent:

if (g_pEvent == NULL) return;

Ini mencegah kemungkinan kesalahan yang dapat terjadi jika aplikasi menerima pemberitahuan peristiwa setelah merilis pointer.

Tugas DirectShow Dasar

Pemberitahuan Peristiwa di DirectShow