一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - WPF下YUV播放的D3D解決方案

WPF下YUV播放的D3D解決方案

2020-05-01 14:22yangyy9611 ASP.NET教程

這篇文章主要介紹了WPF下YUV播放的D3D解決方案,需要的朋友可以參考下

在視頻媒體播放,監控系統的構建當中,經常會涉及到YUV數據的顯示問題。一般的播放控件以及SDK都是通過使用Window句柄,利用DirectDraw直接在窗口上渲染。但是,如果用戶界面是使用WPF開發的時候,通常只能通過WinFormHost在WPF界面中嵌入WinForm來完成。但這么做會遇到AeroSpace的問題,即winform的控件永遠浮在WPF的最上層,任何WPF元素都會被蓋住,同時縮放和拖動的時候都會造成很差的用戶體驗。原因是由于WPF和Winform使用了不同的渲染技術。

要在WPF中完美的支持YUV數據的顯示,通常的解決方式是使用先把YUV數據轉換成WPF可以支持的RGB數據,然后利用類似于WriteableBitmap的控件,把他展現在WPF上。這么做的主要問題是在做RGB轉換的時候,需要消耗大量的CPU, 效率比較低。一種優化方式是使用FFMPEG里的SwScale或者Intel的IPP庫,這些庫經過了一定的優化,可以有限度的使用硬件加速。下面為一個使用WritableBitmap的例子。

?
1
2
3
4
5
6
7
8
9
10
11
12
WriteableBitmap imageSource = new WriteableBitmap(videoWidth, videoHeight,
 DPI_X, DPI_Y, System.Windows.Media.PixelFormats.Bgr32, null);
...
int rgbSize = width * height * 4; // bgr32
IntPtr rgbPtr = Marshal.AllocHGlobal(rgbSize);
YV12ToRgb(yv12Ptr, rgbPtr, width, height);
// 更新圖像
imageSource.Lock();
Interop.Memcpy(this.imageSource.BackBuffer, rgbPtr, rgbSize);
imageSource.AddDirtyRect(this.imageSourceRect);
imageSource.Unlock();
Marshal.FreeHGlobal(rgbPtr);

另一種解決方法是使用D3DImage作為WPF與顯卡的橋梁。我們可以借助D3DImage,直接將D3D渲染過后的部分送到WPF中顯示。一個參考就是VMR9在WPF中的應用。VMR9是微軟提供的DirectShow的Render。經過仔細參考了WpfMediaTookit中VMR9相關的代碼后,其核心的思想就是在初始化DirectShow構建VMR9渲染器時,讓其輸出一個D3D9Surface,D3DImage將使用該Surface作為BackBuffer。當有新的視頻幀在該Surface渲染完成后,VMR9將發送一個事件通知。收到通知后,D3DImage刷新一下BackBuffer即可。下面代碼展現了核心思想部分。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private VideoMixingRenderer9 CreateRenderer() {
 var result = new VideoMixingRenderer9();
 var cfg = result as IVMRFilterConfig9;
 cfg.SetNumberOfStreams(1);
 cfg.SetRenderingMode(VMR9Mode.Renderless);
 var notify = result as IVMRSurfaceAllocatorNotify9;
 var allocator = new Vmr9Allocator();
 notify.AdviseSurfaceAllocator(m_userId, allocator);
 allocator.AdviseNotify(notify);
 // 在構建VMR9 Render時,注冊新視頻幀渲染完成事件
 allocator.NewAllocatorFrame += new Action(allocator_NewAllocatorFrame);
 // 注冊接收新D3DSurface被創建的事件
 allocator.NewAllocatorSurface += new NewAllocatorSurfaceDelegate(allocator_NewAllocatorSurface);
 return result;
 }
 void allocator_NewAllocatorSurface(object sender, IntPtr pSurface)
 {
  // 為了方便理解,只保留核心部分。省略改寫了其他部分
  ...
  // 將pSurface設置為D3DImage的BackBuffer
  this.m_d3dImage.Lock();
  this.m_d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, pSurface);
  this.m_d3dImage.Unlock();
  ...
 }
 void allocator_NewAllocatorFrame()
 {
  ...
  // 重繪
  this.m_d3dImage.Lock();
  this.m_d3dImage.AddDirtyRect(new Int32Rect(0, /* Left */
    0, /* Top */
    this.m_d3dImage.PixelWidth, /* Width */
    this.m_d3dImage.PixelHeight /* Height */));
  this.m_d3dImage.Unlock();
  ...
 }

由此,只要是使用DirectShow的視頻播放就可以借助VMR9在WPF上完美顯示。但很多時候,DirectShow不能解決所有問題。例如在做交互式視頻優化處理或是視頻疊加的時候, 采用固定濾鏡流水線的DirectShow很難滿足要求。有的時候還是需要便捷的直接渲染的方式。

由VMR9的例子我們可以看出,產生出一個D3D9Surface并在上面渲染是其中的關鍵。那么剩下的問題就是如何把YUV數據渲染到D3D9Surface。

D3D沒有直接支持YUV圖像格式。因此需要我們想辦法讓D3D能夠渲染YUV數據。在用C#改寫的過程當中,我突然發現D3D已經提供了更簡單的方法幫助我們實現YUV到RGB顏色空間的轉換,而且是通過顯卡硬件直接支持。效率相當的高。主要原理就是借助D3DDevice的StrentchRectangle方法。

?
1
2
3
4
5
6
7
public void StretchRectangle(
 Surface sourceSurface,
 Rectangle sourceRectangle,
 Surface destSurface,
 Rectangle destRectangle,
 TextureFilter filter
);

StrentchRectangle方法的主要功能是將一個Surface上的某個區域的內容拷貝到另一個Surface的指定區域中。在Copy的過程當中,只要是顯卡直接支持的格式,如YV12,YUY2等等, 都會自動的進行D3D PixelFormat的轉換!因此,我們只需要創建一個指定好PixelFormat的D3D OffscreenPlainSurface, 把原始數據填充進去,調用StrentchRectangle向目標Surface拷貝,我們就得到了想要的Surface。剩下的事情就交給D3DImage了。下面是例子代碼的核心部分

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void Render(IntPtr imgBuffer)
{
 lock (this.renderLock)
 {
  // 將圖像數據填充進offscreen surface
  this.FillBuffer(imgBuffer);
  // 調用StrentchRectangle把原始圖像數據Copy到TextureSurface中        
  this.StretchSurface();
  // 執行渲染操作
  this.CreateScene();
 }
 // 通知D3DImage刷新圖像
 this.InvalidateImage();
}

以上所述是小編給大家介紹的WPF下YUV播放的D3D解決方案,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

原文鏈接:http://blog.csdn.net/yangyy9611/article/details/17464133

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精品在线观看一区 | 冰漪丰满大乳人体图片欣赏 | 国产真实偷乱视频在线观看 | 三级无删减高清在线影院 | 免费看1级伦理 | 色悠久久久久综合欧美99 | 99国产精品免费视频 | 国产麻豆精品原创 | 亚洲欧美精品一区二区 | bt天堂在线观看国产 | 成人aqq | xxxx18日本视频xxxxx | 男人的天堂久久精品激情 | 艹出白浆| 操极品女神 | 偷拍自拍校园春色 | 青青草在线观看 | 香蕉久久高清国产精品免费 | 暖暖 免费 高清 日本 中文 | 欧美a在线| 免费久久久久 | 精品视频在线观看 | 亚洲国产区中文在线观看 | 久久综合给合久久狠狠狠… | 欧美一级免费看 | 五月色综合婷婷综合俺来也 | 痴mu动漫成年动漫在线观看 | 国产aaaaa一级毛片 | 无限资源在线观看高清 | 成人午夜视频一区二区国语 | 国内精品久久久久久不卡影院 | 黄色a | 毛片免费全部免费观看 | 国产免费小视频在线观看 | 欧美一级欧美一级高清 | 169pp美女 | 丝袜足液精子免费视频 | 精品一区视频 | 狠狠干2016| 欧美一级在线视频 | 熟睡中的麻麻大白屁股小说 |