Stream Player Control-流播放器控制元件
介紹
這篇文章是我前一篇文章的一個延續,它展示了一個網路攝像頭控制元件的實現。 最近我建立了另一個控制元件,並希望與社群分享我的經驗。 這是一個基於FFmpeg的流播放器控制元件,可以執行以下操作:該控制元件沒有額外的依賴和一個簡約的介面。
必要條件
- 該控制元件的WinForms版本是使用.NET Framework 2.0實現的
- 該控制元件的WPF版本是使用.NET Framework 4 Client Profile實現的
背景
現在通過網際網路流式傳輸音訊,視訊和資料是非常平常的事情。 但是,當我試圖找到一個.NET控制元件來播放通過網路傳送的視訊流時,我幾乎找不到任何東西。 這個專案試圖填補這個空白。
實現細節
如果你對實現細節不感興趣,那麼你可以跳過這一節。
實施分為三層。
- 底層被實現為本地DLL模組,它將我們的呼叫轉發給FFmpeg框架。
- 為了便於分發,原生DLL模組作為資源嵌入到控制元件的程式集中。 在執行時階段,DLL模組將被提取到磁碟上的臨時檔案,並通過後期繫結技術使用。 一旦控制權被處置,臨時檔案將被刪除。 換句話說,該控制元件是作為一個單獨的檔案分發的。 所有這些操作都是由中間層來實現的。
- 頂層實現控制類本身。
只有頂層應該被客戶使用。
底層
底層使用facade模式來為FFmpeg框架提供一個簡化的介面。 門面由三個類組成:StreamPlayer類,它實現了流播放功能
/// <summary> /// The StreamPlayer class implements a stream playback functionality. /// </summary> class StreamPlayer : private boost::noncopyable { public: /// <summary> /// Initializes a new instance of the StreamPlayer class. /// </summary> StreamPlayer(); /// <summary>Stream類將視訊流轉換為一系列幀/// Initializes the player. /// </summary> /// <paramname="playerParams">The StreamPlayerParams object that contains the information that is used to initialize the player.</param> void Initialize(StreamPlayerParams playerParams); /// <summary> /// Asynchronously plays a stream. /// </summary> /// <paramname="streamUrl">The url of a stream to play.</param> void StartPlay(std::string const& streamUrl); /// <summary> /// Retrieves the current frame being displayed by the player. /// </summary> /// <paramname="bmpPtr">Address of a pointer to a byte that will receive the DIB.</param> void GetCurrentFrame(uint8_t **bmpPtr); /// <summary> /// Retrieves the unstretched frame size, in pixels. /// </summary> /// <paramname="widthPtr">A pointer to an int that will receive the width.</param> /// <paramname="heightPtr">A pointer to an int that will receive the height.</param> void GetFrameSize(uint32_t *widthPtr, uint32_t *heightPtr); /// <summary> /// Uninitializes the player. /// </summary> void Uninitialize(); };
/// <summary> /// A Stream class converts a stream into series of frames. /// </summary> class Stream : private boost::noncopyable { public: /// <summary> /// Initializes a new instance of the Stream class. /// </summary> /// <paramname="streamUrl">The url of a stream to decode.</param> Stream(std::string const& streamUrl); /// <summary> /// Gets the next frame in the stream. /// </summary> /// <returns>The next frame in the stream.</returns> std::unique_ptr<Frame> GetNextFrame(); /// <summary> /// Gets an interframe delay, in milliseconds. /// </summary> int32_t InterframeDelayInMilliseconds() const; /// <summary> /// Releases all resources used by the stream. /// </summary> ~Stream(); };Frame類,它是一組框架相關的工具。
/// <summary> /// The Frame class implements a set of frame-related utilities. /// </summary> class Frame : private boost::noncopyable { public: /// <summary> /// Initializes a new instance of the Frame class. /// </summary> Frame(uint32_t width, uint32_t height, AVPicture &avPicture); /// <summary> /// Gets the width, in pixels, of the frame. /// </summary> uint32_t Width() const { return width_; } /// <summary> /// Gets the height, in pixels, of the frame. /// </summary> uint32_t Height() const { return height_; } /// <summary> /// Draws the frame. /// </summary> /// <paramname="window">A container window that frame should be drawn on.</param> void Draw(HWND window); /// <summary> /// Converts the frame to a bitmap. /// </summary> /// <paramname="bmpPtr">Address of a pointer to a byte that will receive the DIB.</param> void ToBmp(uint8_t **bmpPtr); /// <summary> /// Releases all resources used by the frame. /// </summary> ~Frame(); };這些樹類是FFmpeg Facade DLL模組的核心。
中間層
中間層由StreamPlayerProxy類實現,該類用作FFmpeg Facade DLL模組的代理。
首先,我們應該從資源中提取FFmpeg Facade DLL模組並將其儲存到一個臨時檔案中。
_dllFile = Path.GetTempFileName();
using (FileStream stream = new FileStream(_dllFile, FileMode.Create, FileAccess.Write))
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(Resources.StreamPlayer);
}
}
然後我們將DLL模組載入到呼叫程序的地址空間中。_hDll = LoadLibrary(_dllFile);
if (_hDll == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
並將DLL模組函式繫結到類例項方法。private delegate Int32 StopDelegate();
private StopDelegate _stop;
// ...
IntPtr procPtr = GetProcAddress(_hDll, "Stop");
_stop =
(StopDelegate)Marshal.GetDelegateForFunctionPointer(procPtr,
typeof(StopDelegate));
在處理控制元件時,我們解除安裝DLL模組並將其刪除。private void Dispose()
{
if (_hDll != IntPtr.Zero)
{
FreeLibrary(_hDll);
_hDll = IntPtr.Zero;
}
if (File.Exists(_dllFile))
{
File.Delete(_dllFile);
}
}
頂層
頂層由具有以下介面的StreamPlayerControl類實現。
/// <summary>
/// Asynchronously plays a stream.
/// </summary>
/// <paramname="uri">The url of a stream to play.</param>
/// <exceptioncref="ArgumentException">An invalid string is passed as an argument.</exception>
/// <exceptioncref="Win32Exception">Failed to load the FFmpeg facade dll.</exception>
/// <exceptioncref="StreamPlayerException">Failed to play the stream.</exception>
public void StartPlay(Uri uri)
/// <summary>
/// Retrieves the image being played.
/// </summary>
/// <returns>The current image.</returns>
/// <exceptioncref="InvalidOperationException">The control is not playing a video stream.</exception>
/// <exceptioncref="StreamPlayerException">Failed to get the current image.</exception>
public Bitmap GetCurrentFrame();
/// <summary>
/// Stops a stream.
/// </summary>
/// <exceptioncref="InvalidOperationException">The control is not playing a stream.</exception>
/// <exceptioncref="StreamPlayerException">Failed to stop a stream.</exception>
public void Stop();
/// <summary>
/// Gets a value indicating whether the control is playing a video stream.
/// </summary>
public Boolean IsPlaying { get; }
/// <summary>
/// Gets the unstretched frame size, in pixels.
/// </summary>
public Size VideoSize { get; }
/// <summary>
/// Occurs when the first frame is read from a stream.
/// </summary>
public event EventHandler StreamStarted;
/// <summary>
/// Occurs when there are no more frames to read from a stream.
/// </summary>
public event EventHandler StreamStopped;
/// <summary>
/// Occurs when the player fails to play a stream.
/// </summary>
public event EventHandler StreamFailed;
使用
開啟程式包管理器控制檯,並將Nuget程式包新增到您的專案中:
Install-Package WebEye.Controls.WinForms.StreamPlayerControl首先,我們需要將控制元件新增到Visual Studio Designer工具箱,使用右鍵單擊,然後選擇“選擇專案...”選單項。 然後,我們將控制元件放置在所需的位置並具有所需的大小。 控制元件例項變數的預設名稱將是streamPlayerControl1。
以下程式碼使用提供的地址非同步播放流。
streamPlayerControl1.StartPlay(new Uri("rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov"));
還有一個選項可以指定連線超時和底層傳輸協議。
streamPlayerControl1.StartPlay(new Uri("rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov"),
TimeSpan.FromSeconds(15), RtspTransport.UdpMulticast);
要獲得正在播放的幀,只需呼叫GetCurrentFrame()方法即可。 幀的解析度和質量取決於流的質量。using (Bitmap image = streamPlayerControl1.GetCurrentFrame())
{
// image processing...
}
要停止流,使用Stop()方法。streamPlayerControl1.Stop();
您可以隨時使用以下程式碼檢查播放狀態。if (streamPlayerControl1.IsPlaying)
{
streamPlayerControl1.Stop();
}
此外,StreamStarted,StreamStopped和StreamFailed事件可用於監視播放狀態。要報告錯誤,使用異常,所以不要忘記將程式碼包裝在try / catch塊中。 這就是使用它。 要檢視完整的示例,請檢視演示應用程式來源。
WPF版本
FFmpeg外觀需要一個WinAPI視窗控制代碼(HWND)才能將其用作渲染目標。 問題是,在WPF世界的窗戶不再有處理。 VideoWindow類解決了這個問題。
<UserControlx:Class="WebEye.StreamPlayerControl"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"mc:Ignorable="d"d:DesignHeight="300"d:DesignWidth="300"xmlns:local="clr-namespace:WebEye">
<local:VideoWindowx:Name="_videoWindow"HorizontalAlignment="Stretch"VerticalAlignment="
相關推薦
Stream Player Control-流播放器控制元件
在本文中,您將會找到一個流播放器控制元件的實現。介紹這篇文章是我前一篇文章的一個延續,它展示了一個網路攝像頭控制元件的實現。 最近我建立了另一個控制元件,並希望與社群分享我的經驗。 這是一個基於FFmpeg的流播放器控制元件,可以執行以下操作:播放RTSP/RTMP視訊流或本
VS2010/MFC對話方塊程式呼叫Windows Media Player播放器控制元件
MFC對話方塊程式呼叫Windows Media Player播放器控制元件播放開啟的avi格式的檔案,具體步驟如下:
1.根據MFC嚮導提示,建立一個預設的對話方塊專案TestMediaPlayer.
2.開啟資源,在主對話方塊上點選右鍵,在右鍵選單中選擇“插入Activ
h5+js視訊播放器控制元件
由於h5相容性問題,很多瀏覽器對於插入視訊播放的支援都大不相同。火狐支援的比較完整,谷歌則支援的不是很好,很多功能都不能實現,這就需要我們去自制一個播放介面,去相容不同的瀏覽器。
只插入一個視訊時,瀏覽器中只會出現這樣一個畫面。只有單擊右鍵才可以彈出選單欄顯示播放或者顯示控制元件;
下
一個強悍而優美的Android視訊播放器控制元件JieCaoVideoPlayer
本文為轉載文章,原文作者:魑魅魍魎9527 原文連結:https://blog.csdn.net/qq_28934205/article/details/52944383?utm_source=copy
效果圖:
視訊可以全屏 顯示 旋轉螢幕也可以
xml程
Android上定義播放器控制元件UniversalVideoView
在Android上播放視訊最簡單的方法是使用SDK中內建的VideoView,然後加上MediaController來控制視訊播放暫停等,但是這樣有一個缺點是無法定製自己的控制UI,所以這裡提供一個自定義播放控制元件,它可以設定多種自定義屬性(如loading樣式,錯誤視訊
零基礎讀懂視頻播放器控制原理: ffplay 播放器源代碼分析
5.4 編碼方式 是否播放 都對 enum 其中 mat 源碼 開始 https://www.qcloud.com/community/article/535574001486630869
視頻播放器原理其實大抵相同,都是對音視頻幀序列的控制。只是一些播放器在音視頻同步上可
關於Timer計時器控制元件的java.lang.IllegalStateException: TimerTask is scheduled already問題分析
博主最近在改被人的專案,準備寫一個類似今日頭條的載入完成提示,就寫了個計時器讓它顯示幾秒,於是就用到了timer這個計時器控制元件,簡單的正常程式碼如下,因為博主的載入需要多次,當timer二次呼叫的時候就出現了java.lang.IllegalStateException: TimerTask i
iOS學習十二之選擇器控制元件UIPickerView
UIPickerView是一個簡易的列表控制元件,用於提供有限個數的選項供使用者選擇。
它是通過代理和資料來源的方法對其進行設定和資料來源填充的,這種控制元件的設計模式也是代理模式的應用之一。
新增下面的程式碼即可實現基本功能。
class ViewController: UIViewControlle
零基礎讀懂視訊播放器控制原理——ffplay播放器原始碼分析(二)
圖7音視訊解碼分析
圖7為輸出的音訊幀和視訊幀序列,每一幀都有PTS和DTS標籤,這兩個標籤究竟是什麼意思呢?
DTS(Decode Time Stamp)和PTS(Presentation Time Stamp)都是時間戳,前者是解碼時間,後者是顯示時間,都是為視訊幀、音訊幀打上的時間標籤,以更
ABAP 使用嚮導建立TABLE CONTROL (TC 表控制元件)
使用嚮導建立TC,主要有以下步驟,
1.定義你要在TC上顯示的列為一個數據結構,並用該結構定義內表和工作區。在建立TC前一定要啟用程式,這樣TC才能獲得定義的內表和工作區。
2.建立螢幕,轉到格式佈局
MFC 主對話方塊獲得tab control子對話方塊控制元件的值
1.建立兩個對話方塊程式,用來當做Tab Control控制元件的兩個頁。別忘了把Style改為Child,Border改為None。然後就可以在上面加其他控制元件了。
接著分別為這兩個對話方塊建立兩個類,比如CPage1和CPage2。
然後在對話方塊類標頭檔案中,加入這
WPF Control Development Unleashed(wpf控制元件開發揭祕) 章節一 WPF的設計理念
章節一 WPF的設計理念
想像你是一個技術相當成熟的設計師,你被要求在空地上蓋一座房子.你看看附近的建築物確保你使用的外部的顏色不與鄰居的衝突.當你完成你的新房子大作之後,你退後一步,被你完成的東西驚呆了.房子擁有輝煌的四層結構和巨大的開放式玻璃幕牆,周圍的美
axure rp 中繼器 控制元件 預設資料
我們使用中繼器來操作表格的初始化(頁面載入時展示預設的一部分資料)、增(增加一行)、刪(刪除一行)。首先來看效果:表格裡面放的是控制元件,不是純文字。不管做什麼,最重要的是思路。我的實現思路是:首先要設定一個預設的資料集,然後一行一行的讀取這個預設的資料集,在讀取資料時再根據
iOS:選擇器控制元件UIPickerView的詳解和演示
#import "ViewController.h"
2
3 @interface ViewController ()
4 @property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
5
6 @end
java Swing 時間選擇器控制元件
效果圖:
中的 flowlayout_v.jar 檔案
示例程式碼:
HongYeLingGuDate類
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Flow
WPF播放GIF控制元件完整程式碼
WPF擁有很強的介面設計能力,可以很方便的做出非常漂亮的介面。但有個問題,WPF沒有自己的播放GIF的控制元件。這讓很多想在介面播放動態動畫的人不得不使用視訊來代替。WPF就真的不能播放GIF動圖了嗎?當然是可以播放的,只是我們需要寫一些程式碼。下面是我總結後寫的一個WPF
介紹一個基於QT的原始碼編輯器控制元件QScintilla
轉 :
pc的部落格
什麼是QScintilla?
QScintilla is a port to Qt of Neil Hodgson’s Scintilla C++ editor control.
QScintilla是Scintilla在QT上的移植,Scintil
那些年我們熬夜打造一可收縮流式標籤控制元件
一、前言
時間匆匆,一眨眼來廈門已經一個多月了。似乎已經適應了這邊的生活,喜歡這邊的風,溫和而舒適,還有淡淡海的味道 。。。
還在再次跟大家致個歉意,部落格的更新又延期了。新的環境,新的工作加上專案大改版,基本每天都有大量的事情,週末也不得空閒。
非常感謝
RN開源播放器Video元件(react-native-video)
一.
專案介紹
該元件進行封裝成React Native平臺播放器Video元件,大家可以使用該元件進行播放視訊啦~不過支援React Native的版本最低0.19版本。
二.
1.1. 執行命令進行安裝
npm instal
Android基礎控制元件Chronometer計時器控制元件
Chronometer→計時器控制元件
java.lang.Object
android.view.View
android.widget.TextView
android.widget.Chronometer
main.xml佈局
<?xm