1

我创建了一个自定义分配器/演示器,可以正常播放普通媒体文件。但是,当我使用以下代码尝试播放 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->Run() 后立即发生。这让我发疯,因为我确信我只是忘记了一些非常简单的事情。

谢谢。

4

3 回答 3

1

您的图表应如下所示。确保您的图表中没有任何错误的过滤器。

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

我的开源项目中有一个自定义分配器,还有一个 DVD 播放器。您可以查看它以供参考,尽管由于我需要在其中破解一些东西以实现 WPF 兼容性,因此其中存在很多代码噪音。 http://wpfmediakit.codeplex.com

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

替代文字 http://img29.imageshack.us/img29/7798/capturelu.jpg

于 2009-09-25T11:07:16.190 回答
0

它可能是一种 DRM 保护形式吗?DVD 图表中的解码器通常会尝试阻止您构建可以访问未压缩数据的图表,就像您在此处所做的那样。通常他们通过更简洁的方法来做到这一点,例如拒绝连接到未经授权的渲染器,但这可能是由类似的事情引起的——当然有 mpeg-2 解码器使用故意崩溃来防止逆向工程。

G

于 2009-09-21T08:41:54.353 回答
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;
}
于 2009-10-22T01:04:08.503 回答