Aracılığıyla paylaş


Olaylara Yanıt Verme

Bu sayfayla ilişkilendirilmiş DirectShowözelliği, eski bir özelliktir. Yerine MediaPlayer, IMFMediaEngineve Media Foundation 'de Ses/Video Yakalamaalmıştır. Bu özellikler Windows 10 ve Windows 11 için iyileştirilmiştir. Microsoft, mümkün olduğunda, yeni kodun DirectShowyerine MediaPlayer, IMFMediaEngine ve Media Foundation üzerindeki Audio/Video Capture kullanmasını kesinlikle önerir. Microsoft, mümkünse yeni API'leri kullanmak için eski API'leri kullanan mevcut kodun yeniden yazılmasını önerir.]

Bu makalede, filtre grafında gerçekleşen olaylara nasıl yanıt verleneceği açıklanmaktadır.

Olay Bildirimi Nasıl Çalışır?

DirectShow uygulaması çalışırken, olaylar filtre grafı içinde gerçekleşebilir. Örneğin, bir filtre akış hatasıyla karşılaşabilir. Filtreler, bir olay kodu ve iki olay parametresinden oluşan olayları göndererek Filter Graph Manager'ı uyarır. Olay kodu olayın türünü gösterir ve olay parametreleri ek bilgi sağlar. Parametrelerin anlamı olay koduna bağlıdır. Olay kodlarının tam listesi için bkz. Olay Bildirim Kodları.

Bazı olaylar, uygulamaya bildirilmeden Filtre Graf Yöneticisi tarafından sessizce işlenir. Diğer olaylar uygulama için bir kuyruğa yerleştirilir. Uygulamaya bağlı olarak, işlemeniz gerekebilecek çeşitli olaylar vardır. Bu makale, çok yaygın olan üç olaya odaklanır:

  • EC_COMPLETE olayı, oynatmanın normal şekilde tamamlandığını gösterir.
  • EC_USERABORT olayı, kullanıcının kayıttan yürütmeyi kesintiye uğrattığını gösterir. Kullanıcı video penceresini kapatırsa video işleyicileri bu olayı gönderir.
  • EC_ERRORABORT olayı, bir hatanın kayıttan yürütmenin durmasına neden olduğunu işaret eder.

Olay Bildirimi'ni kullanma

Bir uygulama, Filtre Grafı Yöneticisi'ne yeni bir olay gerçekleştiğinde belirlenen bir pencereye Windows iletisi göndermesini bildirir. Bu, uygulamanın pencerenin ileti döngüsü içinde yanıt vermesini sağlar. İlk olarak, uygulama penceresine gönderilecek iletiyi tanımlayın. Uygulamalar, WM_APP ile 0xBFFF arasında özel iletiler olarak ileti numaralarını kullanabilir:

#define WM_GRAPHNOTIFY  WM_APP + 1

Ardından, IMediaEventEx arabirimi için Filter Graph Manager'ı sorgulayıp IMediaEventEx::SetNotifyWindow yöntemini çağırın:

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

Bu yöntem, belirtilen pencereyi (g_hwnd) iletinin alıcısı olarak belirler. Filtre grafiğini oluşturduktan sonra ancak grafiği çalıştırmadan önce yöntemini çağırın.

WM_GRAPHNOTIFY sıradan bir Windows iletisidir. Filter Graph Manager olay kuyruğuna yeni bir olay yerleştirdiği her durumda, belirlenen uygulama penceresine WM_GRAPHNOTIFY bir ileti gönderir. İletinin lParam parametresi, SetNotifyWindowiçindeki üçüncü parametreye eşittir. Bu parametre, iletiyle örnek verileri göndermenizi sağlar. Pencere iletisinin wParam parametresi her zaman sıfırdır.

Uygulamanızın WindowProc işlevine WM_GRAPHNOTIFY iletisi için bir durum deyimi ekleyin.

case WM_GRAPHNOTIFY:
    HandleGraphEvent();
    break;

Olay işleyici işlevinde, kuyruktan olay almak için IMediaEvent::GetEvent yöntemini çağırın:

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

GetEvent yöntemi olay kodunu ve iki olay parametresini alır. GetEvent parametresinin dördüncü, bir olayı bekleme süresini milisaniye cinsinden belirtir. Uygulama bir WM_GRAPHNOTIFY iletisine yanıt olarak bu yöntemi çağırdığından olay zaten kuyruğa alınmış durumdadır. Bu nedenle, zaman aşımı değerini sıfır olarak ayarlarız.

Olay bildirimi ve ileti döngüsü zaman uyumsuz olduğundan, uygulamanız iletiye yanıt verene kadar kuyruk birden fazla olay tutabilir. Ayrıca, Filtre Grafı Yöneticisi bazı olayları geçersiz hale gelirse kuyruktan kaldırabilir. Bu nedenle, kuyruğun boş olduğunu belirten bir hata kodu döndürene kadar GetEvent çağırmalısınız.

Bu örnekte, uygulama EC_COMPLETE, EC_USERABORTve EC_ERRORABORT olaylarına yanıt vererek, uygulamanın düzgün bir şekilde çıkmasına olanak tanıyan, uygulama tanımlı CleanUp işlevini çağırır. Örnek, iki olay parametresini yoksayar. Bir olayı aldıktan sonra, olay parametreleriyle ilişkili tüm ücretsiz kaynaklaraIMediaEvent::FreeEventParams'ı çağırın.

EC_COMPLETE olayının filtre grafiğinin durmasına neden olmadığını unutmayın. Uygulama grafiği durdurabilir veya duraklatabilir. Grafiği durdurursanız filtreler, tuttukları kaynakları serbest bırakır. Grafiği duraklatırsanız filtreler kaynakları tutmaya devam eder. Ayrıca, bir video işleyici duraklatıldığında en son karenin statik görüntüsünü görüntüler.

IMediaEventEx işaretçisini serbest bırakmadan önce, NULL pencere tutamacı ile SetNotifyWindow çağırarak olay bildirimini iptal edin:

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

WM_GRAPHNOTIFY ileti işleyicisinde GetEventçağırmadan önce IMediaEventExişaretçisini denetleyin:

if (g_pEvent == NULL) return;

Bu, uygulama işaretçiyi serbest bıraktıktan sonra olay bildirimini aldığında oluşabilecek olası bir hatayı önler.

Temel DirectShow Görevleri

DirectShow 'da Olay Bildirimi