D3D下使用VMR9播放视频文件

随着DX开发包的不断升级,其提供给媒体程序开发人员的接口功能也空前强大起来。本文就D3D下使用VMR9播放视频向初学者谈谈心得。高手请止步(不想让你看了吐血^_^)。
       早在DX8时代,SDK中就提供了VMR的功能,但是不幸的是,有不少功能只限于WINXP下使用。现在好了,DX9中VMR升级了,提供了VMR9。VMR全称为Video Mixing Renderer,顾名思义就是可以使用它来进行视频渲染。那么它到底有多强大呢?我可以告诉你,他十分强大,从SDK的SAMPLE中大家就能看到,VMR9可以进行多部视频文件的混合播放,画中画播放,更酷的是只要是能支持DirectX9的系统都能使用它在3维物体的表面上进行视频渲染。那么这到底是什么样的效果呢?我可以设想这样一个效果来告诉你。(注意:这目前只是一个设想,本人还没有完全掌握这项技术)大家都知道“水晶球”有预知未来的能力吧,当法师操纵水晶球时,球体表面就会出现未来世界的一些情景。如果要把这个效果反映的程序里去,我们就可以使用VMR9了。我们可以首先建立一个球体,并进行水晶化效果处理,然后再使用VMR9将一个关于未来的视频片断渲染到球体表面,这样就形成了刚才所设想的效果了。
VMR9可以使用3种工作模式,分别为windowed, windowless, renderless模式。后两种模式多用于游戏中。本文将只谈及windowless模式。下面我们进入正题。
使用过DSHOW的朋友应该会对下面的流程有似曾相识的感觉。
 
使用VMR9前我们必须先初始化COM库!因为它是一个COM对象。
 
//关于D3D的设备初始化我就不在此讲述了
 
CoInitialize(NULL);       //初始化COM库
 
程序中需要如下变量:
IGraphBuilder*                           g_graph;        //FILTER管理器
IBaseFilter*                                g_filter;         //用于创建VMR9
IBaseFilter*                                g_source;        //用于流媒体数据处理
IEnumPins*                                g_enumpins;     //用于获取PIN
IFilterGraph2*                            g_Graph2;             //用于视频流渲染操作
IMediaControl*                           g_mediaControl;   //媒体控制
IVMRFilterConfig9*                    g_filterConfig;     //VMR9配置
IVMRWindowlessControl9*         g_VMR;         //VMR9的WINDOWED模式控制
HWND                                      hWnd;           //程序主窗口句柄
 
首先我们要创建FilterGraphManager来管理处理视频音频信息的Filter(过滤器)
//创建FilterGraphManager
 
if(FAILED(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&g_graph)))
{
       //错误处理
}
 
然后我们就要创建VMR9对象并将其功能接口返回给g_filter
 
//创建FilterGraph(VMR9)
if(FAILED(CoCreateInstance(CLSID_VideoMixingRenderer9,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void **)&g_filter)))
{
              //ERROR
}
 
创建完毕后将其加入到FILTER管理器以便使用VMR9的功能处理视频流.
 
//add the VMR-9 to the filter graph
if(FAILED(g_graph->AddFilter(g_filter, L"VMR9")))
{
              //ERROR
}
 
现在第一步完成。我们接下来该对VMR9进行属性配置,以便我们按照自己的目的使用它。
 
//创建VMRFilterConfig9
if(FAILED(g_filter->QueryInterface(IID_IVMRFilterConfig9, reinterpret_cast<void**>(&g_filterConfig))))
{
              //ERROR;
}
 
g_filterConfig->SetRenderingMode(VMR9Mode_Windowless);  //将其配置为WINDOWLESS模式
 
现在我们需要VMRWindowlessControl9来对渲染区进行描述
 
//创建VMRWindowlessControl9
if(FAILED(g_filter->QueryInterface(IID_IVMRWindowlessControl9, reinterpret_cast<void**>(&g_VMR))))
{
              //error
}
 
g_VMR->SetVideoClippingWindow(hWnd);    //指定要渲染的窗口为我们的应用程序
                                                                      //主窗口
//下面的三行描述我们的渲染窗口为整个应用程序客户区(整个配置过程适用于窗口模//式和全屏模式)
RECT *clientRect = new RECT;
::GetClientRect(hWnd, clientRect );
g_VMR->SetVideoPosition( NULL, clientRect );
 
最后,我们需要加载资源并控制播放
 
g_graph->AddSourceFilter(“你的资源路径”, L"source", &g_source);  //将资源载入
 
//创建IFilterGrahp2处理媒体流
if(FAILED(g_graph->QueryInterface(IID_IFilterGraph2,reinterpret_cast<void**>(&g_Graph2))))
{
              //error
}
 
//指定RENDER渲染设备对上流设备的数据进行处理
g_Graph2->RenderEx(GetPin(g_source,PINDIR_OUTPUT),AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL);
 
这里对GetPin()方法进行一下说明:
IPin* PowerVideo::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{
       BOOL       bFound = FALSE;
    IEnumPins  *pEnum;
    IPin       *pPin;
    HRESULT hr = pFilter->EnumPins(&pEnum);  //搜索上流设备的PIN
    if (FAILED(hr))
    {
        return NULL;
    }
    while(pEnum->Next(1, &pPin, 0) == S_OK)
    {
        PIN_DIRECTION PinDirThis;
        pPin->QueryDirection(&PinDirThis);
        if (bFound = (PinDir == PinDirThis))   //找到上流设备的输出PIN
            break;
        pPin->Release();
    }
    pEnum->Release();
       if(!bFound)MessageBox(NULL,"Pin连接失败","PowerVideo",MB_OK);
    return (bFound ? pPin : NULL); 
}//该方法主要就是帮助g_Graph2->RenderEx方法和上流设备的媒体输出PIN进行对连
//以便将上流设备解码后的媒体信息流出到RENDER(应用程序创建的渲染器)
 
//创建MediaControl控制播放
if(FAILED(g_graph->QueryInterface(IID_IMediaControl,reinterpret_cast<void**>(&g_mediaControl))))
{
              //error
}
 
g_mediaControl->Run();   //播放
 
至此,所部过程完毕,再次复述一下流程:
1、创建FILTER管理器
2、创建VMR9
3、将VMR9加入管理器
4、设置VMR9
5、加载资源
6、将资源与VMR9连接,让VMR9对其进行解码
7、播放
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值