DirectShow DVD播放

时间:2009-09-20 20:18:56

标签: c++ directx stack-overflow directshow

我创建了一个自定义分配器/演示器,可以正常播放普通媒体文件。但是,当我使用以下代码尝试播放DVD时,它会因堆栈溢出异常而失败。

    vmr9_ap = new vmr9ap();

HMONITOR monitor = MonitorFromWindow(hwnd, NULL);

IGraphBuilder *graph;
IBaseFilter *filter;

IDvdGraphBuilder *builder;

CoCreateInstance(CLSID_DvdGraphBuilder, NULL, CLSCTX_INPROC_SERVER, IID_IDvdGraphBuilder, reinterpret_cast<void**>(&builder));

CoCreateInstance(::CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void**>(&filter));


builder->GetDvdInterface(IID_IVMRFilterConfig9, (void**)&vmr9_config);

vmr9_ap->Initialize(g_pd3dDevice, monitor, vmr9_config);

HRESULT hr = builder->RenderDvdVideoVolume(L"G:\\VIDEO_TS", AM_DVD_SWDEC_PREFER | AM_DVD_VMR9_ONLY, &status);

builder->GetFiltergraph(&graph);

IDvdControl2 *dvdControl;

builder->GetDvdInterface(::IID_IDvdControl2, (void**)&dvdControl);

graph->QueryInterface(::IID_IMediaControl, (void**)&control);

HRESULT h = control->Run();

在调用control-&gt; Run()之后立即发生堆栈溢出。这让我疯狂,因为我确信我只是忘记了一些非常简单的事情。

感谢。

3 个答案:

答案 0 :(得分:1)

您的图表看起来应该是这样的。确保图表中没有任何错误过滤器。

因为您正在使用自定义分配器,所以我会查找该问题并在那里设置一些断点。您粘贴的代码可能不完整,因为我没有看到您使用自定义分配器配置VMR9,也没有看到它被添加到图表中。我避免使用DVDGraphBuilder,因为我很难用我的VMR9 + Allocator正确地获取RenderVolume。我会手动构建图表。

我的开源项目中有一个自定义分配器,带有DVD播放器。您可以查看它以供参考,但由于我需要在WPF兼容性中破解一些内容,因此存在大量代码噪音。 http://wpfmediakit.codeplex.com

您所看到的不应该是DRM问题。

alt text http://img29.imageshack.us/img29/7798/capturelu.jpg

答案 1 :(得分:0)

它可能是DRM保护的一种形式吗? DVD图中的解码器通常会尝试阻止您构建可以像访问这里一样访问未压缩数据的图形。通常他们通过更干净的方法来做到这一点,例如拒绝连接到未经授权的渲染器,但这可能是由于类似的原因造成的 - 当然有mpeg-2解码器使用故意崩溃来防止逆向工程。

答案 2 :(得分:0)

感谢Jeremiah Morrill指出的代码,我设法让回放大部分都在工作。 它工作正常,只要你不试图调整它所使用的D3DImage的大小。我猜想魔鬼的细节。

感谢所有答案。 DVD播放不适用于附带的调试器,根据谷歌的说法,它不是DRM,而是一种反向逆向工程措施。可能特别适合我正在使用的DVD编解码器。

extern "C" __declspec(dllexport) LPDIRECT3DSURFACE9 InitializeDvd(HWND hWnd)
{
    CoInitialize(NULL);

    IPin *dvdVideoOut;
    IPin *vmr9VideoIn;

    HRESULT hr = S_OK;

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

    if(graph)
    {
        hr = CoCreateInstance(CLSID_DVDNavigator, NULL, CLSCTX_INPROC_SERVER, 
                IID_IBaseFilter, (void **)&dvdNavigator);

        if(dvdNavigator)
        {
            hr = graph->AddFilter(dvdNavigator, L"DVD Navigator");

            if(SUCCEEDED(hr))
            {
                hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IBaseFilter, (void **)&vmr9);

                if(vmr9)
                {
                    hr = vmr9->QueryInterface(IID_IVMRFilterConfig9, reinterpret_cast<void**>(&p_fConfig));

                    p_Ap = new VMR9AllocatorPresenter();
                    p_Dh = new DeviceHandler();
                    p_device = p_Dh->Initialize(hWnd);
                    p_fConfig->SetRenderingMode(VMR9Mode_Renderless);
                    p_fConfig->SetNumberOfStreams(1);

                    p_Ap->Initialize(hWnd, p_device, p_fConfig);

                    if(SUCCEEDED(hr))
                    {
                        hr = graph->AddFilter(vmr9, L"Video Mixing Renderer 9");

                        if(p_fConfig)
                        {
                            dvdNavigator->FindPin(L"Video", &dvdVideoOut);
                            if(dvdVideoOut)
                            {
                                hr = graph->Render(dvdVideoOut);
                            }
                            hr = graph->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&control));

                            if(control)
                            {
                                control->Run();
                            }
                        }
                    }
                }   
            }
        }
    }

    return p_Dh->g_surface9;
}