DirectShow使用C ++无限循环视频

时间:2013-09-28 12:09:41

标签: c++ video delay directshow infinite-loop

我有这个小C ++代码播放带有 DirectShow 的视频片段。我想要的是视频永远不会停止所以一旦它到达结束我再次将位置设置为0。问题是在新循环的结束和开始之间有一个小的延迟,我想删除。我的代码如下所示:

#define WM_GRAPHNOTIFY  WM_USER

// Global vars
IGraphBuilder*      g_pGraphBuilder;
IMediaControl*      g_pMediaCtrl;
IMediaPosition*     g_pMediaPos;
IMediaEventEx*      g_pMediaEvent;

HWND                h_MainWindow;

// PlayVideo() - I removed the errors checking lines (irrelevant right now)
RECT grc;
IVideoWindow *pVidWin = NULL;
HRESULT hr = CoInitialize(NULL);

hr = CoCreateInstance(
    CLSID_FilterGraph, 
    NULL, 
    CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder,
    (void**)&g_pGraphBuilder
);

hr = g_pGraphBuilder->RenderFile(L"Clip.mpeg", NULL);
hr = g_pGraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
hr = pVidWin->put_Owner((OAHWND)h_MainWindow);
hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);

GetClientRect(h_MainWindow, &grc);
pVidWin->SetWindowPosition(0, 0, grc.right, grc.bottom);

hr = g_pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&g_pMediaEvent);
hr = g_pGraphBuilder->QueryInterface(IID_IMediaPosition, (void**)&g_pMediaPos);
hr = g_pMediaEvent->SetNotifyWindow((OAHWND)h_MainWindow, WM_GRAPHNOTIFY, 0);
g_pMediaEvent->SetNotifyFlags(0);

hr = g_pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&g_pMediaCtrl);
g_pMediaCtrl->Run();

// WndPrc of the main window, the WM_GRAPHNOTIFY message
long EventCode, Param1, Param2;
// ...
case WM_GRAPHNOTIFY:
    while (g_pMediaEvent->GetEvent(&EventCode, &Param1, &Param2, 0)!=E_ABORT) {
        switch (EventCode) {
            case EC_COMPLETE:
                // Going back to the start of the clip
                g_pMediaPos->put_CurrentPosition(0);
            break;
            default:
            break;
        }   
        g_pMediaEvent->FreeEventParams(EventCode, Param1, Param2);
    }
break;
// ...

正如我所说,这里的问题是当视频停止并再次启动时会出现明显的延迟。看起来EC_COMPLETE并不是在视频停止时发送的,也可能不是,但是put_CurrentPosition()需要一些时间才能将位置设置回0.无论如何,问题在于我想知道是否有解决方案。< / p>

1 个答案:

答案 0 :(得分:3)

没有标准的循环播放解决方案,但任务并非不可能,并且可以通过合理的努力来实现。

错误的方法是使用标准图形/管道实现期望的行为,期望在图形的上游部分执行无缝搜索操作。该图以非常有效的方式流式传输数据并预加载管道以准确地播放数据。但是,一旦到达文件的末尾,就会出现不可避免的搜索和状态转换,这会导致延迟

您需要两者中的任何一种(两种方法都需要开发工作):

  1. 智能自定义过滤器,它拦截完成(流结束)消息并寻找上游部分,或者在小流的情况下,完全缓冲数据并从内部缓冲区无缝继续(适用于小流)
  2. 一个双图设计,其中一个部分从文件读取并将数据发送到另一个图形以进行回放,另一个图形处理来自注入数据的无限回放;你可以正常地寻找第一张图,而不会延迟传播到另一张图
  3. 更新。由于媒体文件很短(可能是某种动画),因此上面的第1项看起来很合适。目标是缓冲过滤器接受所有内容直到完成,将其保留在内部缓冲区,并从内部缓冲区进一步流。

    • 来源 - &gt; ...(解复用器等) - &gt; 缓冲区 - &gt;解压缩器 - &gt;视频渲染器
    • 来源 - &gt; ...(解复用器等) - &gt;解压缩器 - &gt; 缓冲区 - &gt;视频渲染器

    这两个选项都可以实现目标,您可以根据内存/速度要求和偏好在两者之间进行选择。

    缓冲区过滤器的最佳基础是CBaseFilter