wpf實(shí)現(xiàn)超低延遲的RTMP或RTSP播放
?技術(shù)背景
我們?cè)谧鯳indows平臺(tái)RTMP和RTSP播放模塊對(duì)接的時(shí)候,有開(kāi)發(fā)者需要在wpf下調(diào)用,如果要在wpf下使用,只需要參考C#的對(duì)接demo即可,唯一不同的是,視頻流數(shù)據(jù)顯示的話,要么通過(guò)控件模式,要么可以讓RTMP、RTSP播放模塊回調(diào)rgb數(shù)據(jù)上來(lái),在wpf直接繪制即可。
技術(shù)實(shí)現(xiàn)
本文以大牛直播SDK的Windows平臺(tái)SmartPlayer為例,回調(diào)數(shù)據(jù)的模式,其他不再說(shuō)明,只要處理好上來(lái)的數(shù)據(jù)就好:
播放之前,設(shè)置回調(diào),選擇NT_SP_E_VIDEO_FRAME_FORMAT_RGB32:
video_frame_call_back_ = new SP_SDKVideoFrameCallBack(SetVideoFrameCallBack); NTSmartPlayerSDK.NT_SP_SetVideoFrameCallBack(player_handle_, (Int32)NT.NTSmartPlayerDefine.NT_SP_E_VIDEO_FRAME_FORMAT.NT_SP_E_VIDEO_FRAME_FORMAT_RGB32, IntPtr.Zero, video_frame_call_back_);
處理rgb數(shù)據(jù)回調(diào):
/* * nt_player_wrapper.cs * Author: daniusdk.com */ public void SetVideoFrameCallBack(IntPtr handle, IntPtr userData, UInt32 status, IntPtr frame) { if (frame == IntPtr.Zero) { return; } //如需直接處理RGB數(shù)據(jù),請(qǐng)參考以下流程 NT_SP_VideoFrame video_frame = (NT_SP_VideoFrame)Marshal.PtrToStructure(frame, typeof(NT_SP_VideoFrame)); if (video_frame.format_ != (Int32)NT.NTSmartPlayerDefine.NT_SP_E_VIDEO_FRAME_FORMAT.NT_SP_E_VIDEO_FRAME_FORMAT_RGB32) return; NT_SP_VideoFrame pVideoFrame = new NT_SP_VideoFrame(); pVideoFrame.format_ = video_frame.format_; pVideoFrame.width_ = video_frame.width_; pVideoFrame.height_ = video_frame.height_; pVideoFrame.timestamp_ = video_frame.timestamp_; pVideoFrame.stride0_ = video_frame.stride0_; pVideoFrame.stride1_ = video_frame.stride1_; pVideoFrame.stride2_ = video_frame.stride2_; pVideoFrame.stride3_ = video_frame.stride3_; Int32 argb_size = video_frame.stride0_ * video_frame.height_; pVideoFrame.plane0_ = Marshal.AllocHGlobal(argb_size); CopyMemory(pVideoFrame.plane0_, video_frame.plane0_, (UInt32)argb_size); }
另外一種,可以用picturebox,在MainWindow.xaml 做以下設(shè)置:
<WindowsFormsHost HorizontalAlignment="Left" Height="338" Margin="10,10,0,0" VerticalAlignment="Top" Width="480" Background="Black"> <wf:PictureBox x:Name="RealPlayWnd"></wf:PictureBox> </WindowsFormsHost>
為了便于多實(shí)例集成參考,以播放2路為例(一路2560*1440,一路1920*1080):
具體實(shí)現(xiàn)如下:
/* * MainWindow.xaml.cs * Author: daniusdk.com */ public MainWindow() { InitializeComponent(); if (!InitSDK()) return; UIDispatcher = Dispatcher.CurrentDispatcher; player1_ = new nt_player_wrapper(RealPlayWnd, UIDispatcher); player1_.EventGetPlayerEventMsg += new DelGetPlayerEventMsg(GetPlayerEventMsgInfo); player1_.EventGetVideoSize += new DelGetVideoSize(GetVideoSize); player2_ = new nt_player_wrapper(RealPlayWnd1, UIDispatcher); player2_.EventGetPlayerEventMsg += new DelGetPlayerEventMsg(GetPlayerEventMsgInfo); player2_.EventGetVideoSize += new DelGetVideoSize(GetVideoSize); } private void GetPlayerEventMsgInfo(IntPtr handle, String msg) { this.Dispatcher.Invoke((Action)delegate() { event_label.Content = msg; }); } private void GetVideoSize(IntPtr handle, String size) { this.Dispatcher.Invoke((Action)delegate() { video_size.Content = size; }); } private bool InitSDK() { if (!is_player_sdk_init_) { UInt32 isPlayerInited = NT.NTSmartPlayerSDK.NT_SP_Init(0, IntPtr.Zero); if (isPlayerInited != 0) { MessageBox.Show("調(diào)用NT_SP_Init失敗.."); return false; } is_player_sdk_init_ = true; } return true; } private void Button_Click_1(object sender, RoutedEventArgs e) { if (!player1_.IsPlaying()) { player1_.SetBuffer(0); bool is_mute = true; if (!player1_.StartPlay("rtsp://admin:daniulive12345@192.168.0.120:554/h264/ch1/main/av_stream", false, is_mute)) return; btn_playback1.Content = "停止播放"; } else { player1_.StopPlay(); btn_playback1.Content = "開(kāi)始播放"; } } private void Button_Click_2(object sender, RoutedEventArgs e) { if (!player2_.IsPlaying()) { player2_.SetBuffer(0); bool is_mute = true; if (!player2_.StartPlay("rtsp://admin:admin123456@192.168.0.121:554/cam/realmonitor?channel=1&subtype=0", false, is_mute)) return; btn_playback2.Content = "停止播放"; } else { player2_.StopPlay(); btn_playback2.Content = "開(kāi)始播放"; } } protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { if (MessageBox.Show("確定要關(guān)閉窗口嗎?", "確認(rèn)", MessageBoxButton.YesNo) != MessageBoxResult.Yes) { // 如果用戶選擇“否”,取消關(guān)閉 e.Cancel = true; } if (player1_.IsPlaying()) { player1_.StopPlay(); } player1_.Dispose(); if (player2_.IsPlaying()) { player2_.StopPlay(); } player2_.Dispose(); if (is_player_sdk_init_) { NTSmartPlayerSDK.NT_SP_UnInit(); is_player_sdk_init_ = false; } base.OnClosing(e); }
延遲依舊毫秒級(jí),CPU占用如下,如果用硬解碼,體驗(yàn)會(huì)更好:
SmartPlayer以跨平臺(tái)的RTSP播放器為例,我們實(shí)現(xiàn)的功能如下,如不單獨(dú)說(shuō)明,系Windows、Linux、Android、iOS全平臺(tái)支持:
- [支持播放協(xié)議]高穩(wěn)定、超低延遲、業(yè)內(nèi)首屈一指的RTSP直播播放器SDK;
- [多實(shí)例播放]支持多實(shí)例播放;
- [事件回調(diào)]支持網(wǎng)絡(luò)狀態(tài)、buffer狀態(tài)等回調(diào);
- [視頻格式]支持H.265、H.264,此外,還支持RTSP MJPEG播放;
- [音頻格式]支持AAC/PCMA/PCMU;
- [H.264/H.265軟解碼]支持H.264/H.265軟解;
- [H.264硬解碼]Windows/Android/iOS支持特定機(jī)型H.264硬解;
- [H.265硬解]Windows/Android/iOS支持特定機(jī)型H.265硬解;
- [H.264/H.265硬解碼]Android支持設(shè)置Surface模式硬解和普通模式硬解碼;
- [RTSP模式設(shè)置]支持RTSP TCP/UDP模式設(shè)置;
- [RTSP TCP/UDP自動(dòng)切換]支持RTSP TCP、UDP模式自動(dòng)切換;
- [RTSP超時(shí)設(shè)置]支持RTSP超時(shí)時(shí)間設(shè)置,單位:秒;
- [RTSP 401認(rèn)證處理]支持上報(bào)RTSP 401事件,如URL攜帶鑒權(quán)信息,會(huì)自動(dòng)處理;
- [緩沖時(shí)間設(shè)置]支持buffer time設(shè)置;
- [首屏秒開(kāi)]支持首屏秒開(kāi)模式;
- [復(fù)雜網(wǎng)絡(luò)處理]支持?jǐn)嗑W(wǎng)重連等各種網(wǎng)絡(luò)環(huán)境自動(dòng)適配;
- [快速切換URL]支持播放過(guò)程中,快速切換其他URL,內(nèi)容切換更快;
- [音視頻多種render機(jī)制]Android平臺(tái),視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
- [實(shí)時(shí)靜音]支持播放過(guò)程中,實(shí)時(shí)靜音/取消靜音;
- [實(shí)時(shí)音量調(diào)節(jié)]支持播放過(guò)程中實(shí)時(shí)調(diào)節(jié)音量;
- [實(shí)時(shí)快照]支持播放過(guò)程中截取當(dāng)前播放畫(huà)面;
- [只播關(guān)鍵幀]Windows平臺(tái)支持實(shí)時(shí)設(shè)置是否只播放關(guān)鍵幀;
- [渲染角度]支持0°,90°,180°和270°四個(gè)視頻畫(huà)面渲染角度設(shè)置;
- [渲染鏡像]支持水平反轉(zhuǎn)、垂直反轉(zhuǎn)模式設(shè)置;
- [等比例縮放]支持圖像等比例縮放繪制(Android設(shè)置surface模式硬解模式不支持);
- [實(shí)時(shí)下載速度更新]支持當(dāng)前下載速度實(shí)時(shí)回調(diào)(支持設(shè)置回調(diào)時(shí)間間隔);
- [解碼前視頻數(shù)據(jù)回調(diào)]支持H.264/H.265數(shù)據(jù)回調(diào);
- [解碼后視頻數(shù)據(jù)回調(diào)]支持解碼后YUV/RGB數(shù)據(jù)回調(diào);
- [解碼前音頻數(shù)據(jù)回調(diào)]支持AAC/PCMA/PCMU數(shù)據(jù)回調(diào);
- [音視頻自適應(yīng)]支持播放過(guò)程中,音視頻信息改變后自適應(yīng);
- [擴(kuò)展錄像功能]完美支持和錄像模塊組合使用。
總結(jié)
Windows平臺(tái)下如果需要wpf播放,如果需要更靈活,可以采用回調(diào)rgb數(shù)據(jù)的模式,上層直接繪制,只是低延遲的播放出來(lái)畫(huà)面,采用上述控件模式亦可,除了wpf外,我們提供了C++和C#的接口和demo,感興趣的開(kāi)發(fā)者,可以嘗試看看,有問(wèn)題可以單獨(dú)跟我溝通。
到此這篇關(guān)于wpf實(shí)現(xiàn)超低延遲的RTMP或RTSP播放的文章就介紹到這了,更多相關(guān)wpf延遲播放內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#判斷代碼是否執(zhí)行超時(shí)的幾種方式總結(jié)
這篇文章主要介紹了c#判斷代碼是否執(zhí)行超時(shí)的幾種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01C#中幾個(gè)未知的Visual Studio編碼技巧分享
用了多年的Visual Studio,今天才發(fā)現(xiàn)這個(gè)編碼技巧,真是慚愧,分享出來(lái),算是拋磚引玉吧,需要的朋友可以參考下2012-11-11C# menuStrip控件實(shí)現(xiàn)鼠標(biāo)滑過(guò)自動(dòng)彈出功能
MenuStrip 控件是 Visual Studio 和 .NET Framework 中的功能。使用該控件,可以輕松創(chuàng)建 Microsoft Office 中那樣的菜單。本文給大家分享menuStrip鼠標(biāo)滑過(guò)自動(dòng)彈出效果2021-07-07算法證明每一位都相同十進(jìn)制數(shù)不是完全平方數(shù)
這篇文章主要為大家介紹了算法證明每一位都相同十進(jìn)制數(shù)不是完全平方數(shù)的過(guò)程論述,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05C# Winform使用log4net進(jìn)行日志記錄
Log4Net是從Java的log4j移植過(guò)來(lái)的,功能也與log4j類似,可以把日志信息輸出到文件、數(shù)據(jù)庫(kù)等不同的介質(zhì)或目標(biāo),下面我們就來(lái)學(xué)習(xí)一下如何使用log4net進(jìn)行日志記錄吧2023-11-11詳解C#設(shè)置Excel數(shù)據(jù)自適應(yīng)行高、列寬的2種情況
這篇文章主要介紹了C#設(shè)置Excel數(shù)據(jù)自適應(yīng)行高、列寬的2種情況,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04