国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

WPF下YUV播放的D3D解決方案

2024-07-10 12:49:13
字體:
來源:轉載
供稿:網友

在視頻媒體播放,監控系統的構建當中,經常會涉及到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的例子。

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即可。下面代碼展現了核心思想部分。

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();   ...  }             
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 漾濞| 颍上县| 澎湖县| 聂拉木县| 和田县| 宁阳县| 泾川县| 屏边| 且末县| 老河口市| 陇西县| 莎车县| 田林县| 正阳县| 綦江县| 游戏| 阿克| 洛南县| 阳谷县| 天气| 年辖:市辖区| 达州市| 饶平县| 南丹县| 彭水| 隆尧县| 石泉县| 阳原县| 镇远县| 朝阳市| 资阳市| 平昌县| 温泉县| 安西县| 绥江县| 名山县| 南京市| 临沭县| 榆社县| 锦州市| 康平县|