概述

DirectShow提供了几种渲染视频的滤镜:

·Video Renderer filter:此过滤器适用于支持DirectX的所有平台,并且没有特定的系统要求。 Video Renderer尽可能使用DirectDraw来呈现视频; 否则,它使用GDI。 此筛选器是比Windows XP早的平台上的默认视频渲染器。

·Video Mixing Renderer Filter 7 (VMR-7):VMR-7在Windows XP上可用,它是默认的视频渲染器。 VMR-7总是使用DirectDraw 7进行渲染。 它提供了旧版Video Renderer过滤器中没有的许多强大功能,包括应用程序控制用于渲染的DirectDraw表面的插件模型。

·Video Mixing Render Filter 9 (VMR-9):VMR-9是使用Direct3D 9进行渲染的视频混合渲染器的更新版本。 它适用于支持DirectX的所有平台。 但它不是默认的渲染器,因为它比Video Renderer过滤器具有更高的系统要求。

·Overlay Mixer滤镜专为DVD播放和广播视频而设计。 它还支持视频端口扩展(VPE),使其能够与硬件MPEG-2解码器或将视频直接发送到图形卡的模拟电视调谐器。

·增强视频渲染器(EVR)过滤器在Windows Vista中可用。 与早期的视频渲染器相比,它提供了改进的视频性能,尤其是在启用Windows Vista桌面组合时

DirectShow视频渲染器可以在窗口模式或无窗口模式下运行:

·在窗口模式下,渲染器创建自己的窗口来显示视频。 通常,您将使此窗口成为应用程序窗口的子项。

·在无窗口模式下,渲染器将视频直接拖到应用程序窗口上。 它不创建它自己的窗口

Video Renderer过滤器仅支持窗口模式。 VMR-7和VMR-9过滤器支持这两种模式。 它们默认为窗口模式以实现向后兼容,但无窗口模式是首选。 EVR仅支持无窗口模式。

Choosing the Right Video Renderer

主要使用哪个渲染器取决于您需要支持哪些版本的Windows

·在Windows Vista及更高版本中,如果硬件支持,则应用程序应使用EVR。 否则,回到VMR-9或VMR-7。 EVR提供比以前的渲染器更好的性能和更好的视频质量。 此外,它旨在与桌面窗口管理器(DWM)一起使用。

·在Windows Vista之前,如果硬件支持它并且不需要视频端口功能,请使用VMR-9。 否则,请使用VMR-7。

·在较旧的系统上,您可能需要使用Overlay Mixer(用于视频端口或硬件叠加支持)或旧式Video Renderer过滤器。

IGraphBuilder :: Render和RenderFile方法默认使用VMR-7。 如果硬件不支持VMR-7,这些方法将回退到传统的Video Renderer过滤器。 EVR和VMR-9绝不是默认的渲染器。

窗口模式

在窗口模式下,视频渲染器创建自己的窗口,在该窗口绘制视频帧。 除非另有说明,否则此窗口是具有自己的边框和标题栏的顶层窗口。 但是,大多数情况下,您会将视频窗口附加到应用程序窗口,以便将视频集成到应用程序UI中。 这需要以下步骤:

1.查询IVideoWindow。

2.设置父窗口。

3.设置新的窗口样式。

4.将视频窗口放置在所有者窗口内。

5.通知WM_MOVE消息的视频窗口。

Query for IVideoWindow

在开始播放之前,请在Filter Graph Manager中查询IVideoWindow接口

IVideoWindow *pVidWin = NULL;
pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);

Set the Parent Window

要设置父窗口,请调用带有应用程序窗口句柄的IVideoWindow :: put_Owner方法。 这个方法接受一个OAHWND类型的变量,所以把句柄转换为这种类型:

pVidWin->put_Owner((OAHWND)hwnd);

Set New Window Styles

通过调用IVideoWindow :: put_WindowStyle方法来更改视频窗口的样式:

pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);

WS_CHILD标志将窗口设置为子窗口,并且WS_CLIPSIBLINGS标志防止窗口在另一个子窗口的客户区域内绘制。

Position the Video Window

要设置视频相对于应用程序窗口客户区的位置,请调用IVideoWindow :: SetWindowPosition方法。 此方法采用指定视频窗口的左边缘,顶边缘,宽度和高度的矩形。 例如,以下代码将视频窗口拉伸到适合父窗口的整个客户区:

RECT rc;
GetClientRect(hwnd, &rc);
pVidWin->SetWindowPosition(0, 0, rc.right, rc.bottom);

要获得视频的原始大小,请在Filter Graph Manager上调用IBasicVideo :: GetVideoSize方法。 您可以使用该信息来缩放视频并保持正确的宽高比。

Respond to WM_MOVE Messages

为了获得最佳性能,每当窗口在图形暂停时移动时,都应通知视频渲染器。 调用IVideoWindow :: NotifyOwnerMessage方法来转发WM_MOVE消息:

// (Inside your WindowProc)
case WM_MOVE:pVidWin->NotifyOwnerMessage((OAHWND)hWnd, msg, wParam, lParam);break;

如果渲染器正在使用硬件叠加层,则此通知将导致渲染器更新叠加层位置。 (VMR-9不使用叠加层,因此如果您使用VMR-9,则无需调用此方法。)

Cleap Up

在应用程序退出之前,停止图形并将视频窗口的所有者重置为NULL。 否则,窗口消息可能被发送到错误的窗口,这可能会导致错误。 此外,隐藏视频窗口,否则您可能会在屏幕上瞬间看到视频图像闪烁:

pControl->Stop();
pVidWin->put_Visible(OAFALSE);
pVidWin->put_Owner(NULL);  

无窗口模式

Configure the VMR for Windowless Mode

·VMR-7

1.创建过滤器图形管理器。

2.创建VMR-7并将其添加到过滤器图形中。

3.使用VMRMode_Windowless标志在VMR-7上调用IVMRFilterConfig :: SetRenderingMode。

4.查询IVMRWindowlessControl接口的VMR-7。

5.在VMR-7上调用IVMRWindowlessControl :: SetVideoClippingWindow。指定视频应该出现的窗口的句柄。

·VMR-9

1.创建过滤器图形管理器。

2.创建VMR-9并将其添加到过滤器图形中。

3.使用VMR9Mode_Windowless标志调用VMR-9上的IVMRFilterConfig9 :: SetRenderingMode。

4.查询IVMRWindowlessControl9界面的VMR-9。

5.在VMR-9上调用IVMRWindowlessControl9 :: SetVideoClippingWindow。 指定视频应该出现的窗口的句柄。

以下代码显示了一个辅助函数,它可以创建VMR-7,将其添加到图形中,并设置无窗口模式。

HRESULT InitWindowlessVMR( HWND hwndApp,                  // Window to hold the video. IGraphBuilder* pGraph,         // Pointer to the Filter Graph Manager. IVMRWindowlessControl** ppWc   // Receives a pointer to the VMR.)
{ if (!pGraph || !ppWc) {return E_POINTER;}IBaseFilter* pVmr = NULL; IVMRWindowlessControl* pWc = NULL; // Create the VMR. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (FAILED(hr)){return hr;}// Add the VMR to the filter graph.hr = pGraph->AddFilter(pVmr, L"Video Mixing Renderer"); if (FAILED(hr)) {pVmr->Release();return hr;}// Set the rendering mode.  IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if (SUCCEEDED(hr)) { hr = pConfig->SetRenderingMode(VMRMode_Windowless); pConfig->Release(); }if (SUCCEEDED(hr)){// Set the window. hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);if( SUCCEEDED(hr)) { hr = pWc->SetVideoClippingWindow(hwndApp); if (SUCCEEDED(hr)){*ppWc = pWc; // Return this as an AddRef'd pointer. }else{// An error occurred, so release the interface.pWc->Release();}} } pVmr->Release(); return hr;
} 

此功能假定仅显示一个视频流,而不是在视频上混合静态位图。你可以这样调用这个函数:

IVMRWindowlessControl *pWc = NULL;
hr = InitWindowlessVMR(hwnd, pGraph, &g_pWc);
if (SUCCEEDED(hr))
{// Build the graph. For example:pGraph->RenderFile(wszMyFileName, 0);// Release the VMR interface when you are done.pWc->Release();
}

Positon the Video

·VMR-7

1.调用IVMRWindowlessControl :: SetVideoPosition方法来指定两个矩形。

2.源矩形必须等于或小于原始视频大小; 您可以使用IVMRWindowlessControl :: GetNativeVideoSize方法获取原生视频大小。

·VMR-9

1.调用IVMRWindowlessControl9 :: SetVideoPosition方法来指定两个矩形。

2.源矩形必须等于或小于原始视频大小; 您可以使用IVMRWindowlessControl9 :: GetNativeVideoSize方法来获取原生视频大小。

例如,以下代码设置VMR-7的源矩形和目标矩形。 它将源矩形设置为等于整个视频图像,目标矩形等于整个窗口客户区:

// Find the native video size.
long lWidth, lHeight;
HRESULT hr = g_pWc->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
if (SUCCEEDED(hr))
{RECT rcSrc, rcDest; // Set the source rectangle.SetRect(&rcSrc, 0, 0, lWidth, lHeight); // Get the window client area.GetClientRect(hwnd, &rcDest); // Set the destination rectangle.SetRect(&rcDest, 0, 0, rcDest.right, rcDest.bottom); // Set the video position.hr = g_pWc->SetVideoPosition(&rcSrc, &rcDest);
}

Handle Window Messages

·VMR-7

1.WM_PAINT。 调用IVMRWindowlessControl :: RepaintVideo。 此方法会导致VMR-7重新绘制最近的视频帧。                 2.WM_DISPLAYCHANGE:调用IVMRWindowlessControl :: DisplayModeChanged。 此方法通知VMR-7必须以新的分辨率或颜色深度显示视频。

3.WM_SIZE或WM_WINDOWPOSCHANGED:重新计算视频的位置并在需要时调用IVMRWindowlessControl :: SetVideoPosition更新位置。

·VMR-9

1.WM_PAINT。 调用IVMRWindowlessControl9 :: RepaintVideo。 此方法会导致VMR-9重新绘制最近的视频帧。                2.WM_DISPLAYCHANGE:调用IVMRWindowlessControl9 :: DisplayModeChanged。 此方法通知VMR-9必须以新的分辨率或颜色深度显示视频。

3.WM_SIZE或WM_WINDOWPOSCHANGED:重新计算视频的位置并在需要时调用IVMRWindowlessControl9 :: SetVideoPosition更新位置。

以下示例显示了一个WM_PAINT消息处理程序。 它绘制由客户矩形减去视频矩形定义的区域。 不要在视频矩形上绘制,因为VMR会覆盖它,导致闪烁。 出于同样的原因,不要在窗口类中设置背景画笔。

void OnPaint(HWND hwnd)
{ PAINTSTRUCT ps; HDC         hdc; RECT        rcClient; GetClientRect(hwnd, &rcClient); hdc = BeginPaint(hwnd, &ps); if (g_pWc != NULL) { // Find the region where the application can paint by subtracting // the video destination rectangle from the client area.// (Assume that g_rcDest was calculated previously.)HRGN rgnClient = CreateRectRgnIndirect(&rcClient); HRGN rgnVideo  = CreateRectRgnIndirect(&g_rcDest);  CombineRgn(rgnClient, rgnClient, rgnVideo, RGN_DIFF);  // Paint on window.HBRUSH hbr = GetSysColorBrush(COLOR_BTNFACE); FillRgn(hdc, rgnClient, hbr); // Clean up.DeleteObject(hbr); DeleteObject(rgnClient); DeleteObject(rgnVideo); // Request the VMR to paint the video.HRESULT hr = g_pWc->RepaintVideo(hwnd, hdc);  } else  // There is no video, so paint the whole client area. { FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1)); } EndPaint(hwnd, &ps);
} 

参考:

https://www.yuque.com/docs/share/6c6329ba-62e6-4b66-8d01-0c57d47828de

DirectShow之视频渲染相关推荐

  1. madVR(视频渲染器)免费版 v0.92.17

    madVR是一款高品质的DirectShow视频渲染器.该软件非常实用,能够兼容非常多的视频播放器,在播放器播放视频时,你可以通过该软件得到高质量的图像,madVR可以和绝大部分的播放器一起使用,像M ...

  2. webrtc 渲染_WebRTC 开发(六)摄像头采集与视频渲染分析

    在上一篇文章 WebRTC 开发(五)编译与运行 Mac 工程 中,我们编译了 WebRTC 的工程 AppRTCMobile,也看到了 App 启动后的初始界面.本文基于 WebRTC M76 ,将 ...

  3. 在iOS端使用AVSampleBufferDisplayLayer进行视频渲染

    原文在这里:http://blog.csdn.net/fernandowei/article/details/52179631 目前大多数iOS端的视频渲染都使用OpenGLES,但如果仅仅为了渲染而 ...

  4. 将 libVLC 视频渲染到 QWidget 中

    作者:一去.二三里 个人微信号:iwaleon 微信公众号:高效程序员 在用 libVLC 播放视频时,会默认显示一个 Direct3D output 窗口.这个窗口不太美观,而且也没办法做一些定制, ...

  5. Android OpenGL ES视频渲染(一)GLSurfaceView

    相关文章:Android OpenGL ES视频渲染(二)EGL+OpenGL Android中视频渲染有几种方式,之前的文章使用的是nativewindow(包括softwareRender).今天 ...

  6. webrtc视频引擎之video_render(视频渲染)介绍

    此部分为webrtc视频渲染显示,代码结构如下: 其实此部分代码与<webrtc视频引擎之vedio_capture_module介绍>的代码结构一样 1,图中能够直接看到的.h和.cc文 ...

  7. Qt WA_TranslucentBackground 导致视频渲染不了的问题

    使用QT5.7 + VS2015做的试验,视频渲染使用D3D9.发现的规律是: 顶层窗口(指父窗口为NULL的窗口)如果设置了 this->setWindowFlags( Qt::Framele ...

  8. SDL2音视频渲染入门

    SDL, "Simple DirectMedia Layer",它是一套开放源代码的跨平台多媒体开发库,使用C语言写成.其主要用于游戏开发中的多媒体处理,如视频渲染,音频播放,鼠标 ...

  9. c++封装webrtc sdk(二):在sdk端实现webrtc视频渲染

      如果你用过其它厂商的rtc sdk,比如声网,在渲染视频时,只需要传入窗口句柄,即可进行渲染,接口如下: 初始化本地视图 virtual int setupLocalVideo(const Vid ...

  10. iOS音视频开发十三:视频渲染,用 Metal 渲染

    本系列文章通过拆解采集 → 编码 → 封装 → 解封装 → 解码 → 渲染流程并实现 Demo 来向大家介绍如何在 iOS/Android 平台上手音视频开发. 这里是第十三篇:iOS 视频渲染 De ...

最新文章

  1. 【BZOJ】1726 [Usaco2006 Nov]Roadblocks第二短路
  2. Android:面试官死亡问答,如何优化一个网络请求?大牛多个网络优化方案帮你解决!
  3. linux下free命令详解
  4. crontab -e 运行python的脚本的坑
  5. frida 安装特定版本
  6. 【今晚七点半】:主编对话李宇翔——我所经历的“前端”开发
  7. 图解 ElasticSearch 原理,太牛了
  8. Android 雪花飘落动画效果 自定义View
  9. 3D slicer的教程网站
  10. java判断小数点后是否为0,是的话则取整,不是的话则保留
  11. 谈谈对象和XML文件的转换
  12. 尚学堂马士兵Linux视频教程笔记
  13. 《python 计算机视觉编程》教程+图片+代码
  14. 扩展Redux——Store Enhancer
  15. 【原创】彻底解决2440触摸屏跳点以及抖动问题
  16. 多台计算机虚拟化方案,虚拟化建设解决方案
  17. 计算机毕业设计之java+ssm基于个人需求的外卖订餐推荐系统
  18. SYSTEM大法好!!!
  19. android 应用性能监控软件,App性能监控工具
  20. Linux小白想成为007,先会用“John the Ripper工具”

热门文章

  1. vivado快速下载及解压安装教程
  2. 试用华为3D建模服务
  3. matlab求边界点,MATLAB Delaunay算法提取离散点边界的方法
  4. 最新高德地图使用——申请key、显示地图
  5. 关于4442卡的读密码问题
  6. [工具] multidesk
  7. scipy回归分析_业余时间学数据分析,如何快速上手
  8. 电子厂计算机维修周记,关于电子厂实习周记范文
  9. DELMIA软件:机器人固定点焊仿真
  10. Linux tar命令无法执行,Linux执行tar解压报错tar: Error is not recoverable: exiting now