WM_GRAPHNOTIFY,它是特定于它的filtergraph

时间:2018-05-08 07:46:56

标签: c# directshow

我们有一个应用程序,它使用带有两个滤镜图的directshow来实现无缝视频播放。 每个“面板”用filtergraph初始化 new QuartzTypeLib.FilgraphManager()后来使用WndProcMediaEventEx.SetNotifyWindow分配到同一窗口但使用不同的LParam(面板ID 0或1)

文档说明在有新事件时发送WM_GRAPHNOTIFY,但队列中可能有多个事件,或者队列可能为空。此外,每个事件不会发送一次WM_GRAPHNOTIFY,但如果队列中有一个或多个事件,则可以发送一次。

由于我使用相同的窗口来处理来自两个过滤器图的通知,我可以确定如果它们同时发生,我会从两个队列中获取事件,或者我是否需要在每个WM_GRAPHNOTIFY消息上解析两个队列,或者我是否可以安全地处理从lParam排队?

以下是我的代码的非常剥离版本。

private const int WM_APP = 0x8000;
private const int WM_GRAPHNOTIFY = WM_APP + 1;
private const int EC_COMPLETE = 0x01;
private const int EC_USERABORT = 0x02;
private const int EC_ERRORABORT = 0x03;

void InitializePanels()
{
    for (int panel = 0; panel <= 1; panel++)
    {
        PlaybackPanels[panel].FilterGraph = new QuartzTypeLib.FilgraphManager();
        PlaybackPanels[panel].MediaEventEx = PlaybackPanels[(panel].FilterGraph as IMediaEventEx;
        PlaybackPanels[panel].MediaEventEx.SetNotifyWindow((int)this.Handle, WM_GRAPHNOTIFY, panel);
        PlaybackPanels[panel].MediaControl = PlaybackPanels[panel].FilterGraph as IMediaControl;
        // Additional code to load media files here...
        PlaybackPanels[panel].MediaControl.Pause();
    }
    PlaybackPanels[0].MediaControl.Run();
}

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_GRAPHNOTIFY)
    {
        int lEventCode;
        int lParam1, lParam2;

        int playerPanelID = m.LParam.ToInt32();

        int _while = 0;
        while (_while < 100)
        {
            try
            {

                PlaybackPanels[playerPanelID].MediaEventEx.GetEvent(out lEventCode, out lParam1, out lParam2, 0);
                PlaybackPanels[playerPanelID].MediaEventEx.FreeEventParams(lEventCode, lParam1, lParam2);
                if (lEventCode == EC_COMPLETE)
                {
                    int nextPanel = 1 - playerPanelID;
                    PlaybackPanels[nextPanel].MediaControl.Run();
                }
                else if (lEventCode == EC_USERABORT || lEventCode == EC_ERRORABORT)
                {
                    /// Handle error...
                }
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {

                // REMARKS: When the window receives the message, it should call the IMediaEvent::GetEvent method to retrieve the event. 
                //          Events are asynchronous, so the queue might contain several events (or none). 
                //          Call GetEvent repeatedly, until it returns an error code.

                if ((uint)ex.ErrorCode == 0x80004004) //Operation Aborted (E_ABORT)
                {

                    // We are done processing the event queue. *Resume event loop*
                    break;

                }
                else
                {
                    throw;
                }
            }

            _while++;
        }
    }

    base.WndProc(ref m);
}

1 个答案:

答案 0 :(得分:0)

图表会发出有关新事件可用性的通知,因此没有冲突或问题,否则多个图表会发送相同的窗口消息。已经无关,如果您发送邮件GetEvent两个图表(包括不是首先发出通知的图表),也没有问题。

区分发件人的另一种方法是分别发送WM_GRAPHNOTIFY + 0WM_GRAPHNOTIFY + 1并处理。您可以拥有更多标识信息,LPARAM以及消息偏移。