在優麒麟上使用MPV編寫自己的播放器

發布時間:2019-09-10 08:00:08 點擊次數:598
0

上一期,小編給大家簡要介紹了MPV的配置和使用方法,雖然MPV功能強大,但默認情況下,MPV無GUI圖形界面,用戶需要通過命令行或者手動修改其配置文件達到配置MPV的目的,這樣就給普通用戶帶來了諸多不便。為此,本文將介紹如何在優麒麟系統上使用Qt編寫帶UI圖形的MPV播放器,使用戶對快速定制具有圖形界面的MPV播放器有一個大致的了解。安裝編程開發依賴包:$ sudo apt install qtb

上一期,小編給大家簡要介紹了MPV的配置和使用方法,雖然MPV功能強大,但默認情況下,MPV無GUI圖形界面,用戶需要通過命令行或者手動修改其配置文件達到配置MPV的目的,這樣就給普通用戶帶來了諸多不便。為此,本文將介紹如何在優麒麟系統上使用Qt編寫帶UI圖形的MPV播放器,使用戶對快速定制具有圖形界面的MPV播放器有一個大致的了解。

安裝編程開發依賴包:

$ sudo apt install qtbase5-dev qt5-qmake qtscript5-dev qttools5-dev-tools

1、QProcess類

為了實現一個既可以在Qt程序中控制MPV,又可以讓Qt程序得到MPV的輸出信息的播放器,這里重點介紹Qt的QProcess類。QProcess類可用來調用外部程序,并與外部程序進行通信。其把外部程序的進程當作一個有序的I/O設備,通過對I/O設備的讀寫來完成進程間的通信,即:write()函數實現對進程標準輸入的寫操作,通過read(),readLine()和getChar()函數實現對標準輸出的讀操作。

在正常渠道模式下,QProcess的無名管道stdinChannelpipe,stdoutChannelpipe和stderrChannelpipe分別與標準輸入、標準輸出和標準容錯進行綁定,實現與外部程序的通信;而在融合模式下,沒有容錯管道,此時,標準容錯端和標準輸出端將共同掛接到子進程的stdoutChannelpipe的寫端來實現內外進程的通信,即標準輸出和標準容錯綁定到同一個管道的寫端。

本文介紹通過QProcess類調用MPV,并設置一系列播放參數,如視頻驅動、音頻驅動、軟解/硬解、緩存等。至于Qt圖形和MPV視頻窗口的關聯,則是使用“--wid widget->winId()”進行綁定,通過winId()可以獲得一個數字,其中widget是一個QWidget對象,這樣將界面上一個窗口的句柄給了MPV,即視頻輸出定位到了widget窗體部件中(wid為MPV指定了輸入窗口,-wid參數只在X11、directX和OpenGL中適用)。本文推薦使用融合模式,代碼為:setProcessChannelMode(QProcess::MergedChannels)。

2、Qt對MPV的控制

前面詳細介紹了Qt的QProcess類,這里描述下該類是如何設置MPV的參數和啟動MPV的,即如何使用給標準輸入控制MPV。MPV自動從標準輸入中讀取信息并執行,該類指令信息都需要以“\n”結尾。管道的讀端描述符stdinChannelpipe[0]復制給了標準輸入,即標準輸入的描述符也為stdinChannelpipe[0],隱藏按照標準輸入的描述符去讀信息就是到stdinChannelpipe所對應的管道中讀取信息。QProcess的start()函數將開啟進程,第一個參數即為MPV二進制,第二個參數為給MPV的參數列表,執行start()函數后,將完成內核中管道以及通信環境的建立。QProcess的成員函數write()向stdinChannelpipe[1]端寫入信息,比如想讓MPV退出,則通過write函數寫入“quit \n”即可(write()函數將向stdinChannelpipe[1]端寫入命令)。參考代碼如下:

QString mpvCmd = "/usr/bin/mpv";  

QStringList args;

args << "-- no-quiet";

args << "--wid=100663330";

args << xxx.avi;

process->start(mpvCmd, args);//啟動播放

waitForStarted();

QString cmd = "set pause yes";

process->write(cmd.toLocal8Bit() + "\n");//設置暫停

3、Qt獲取MPV的信息

使用QProcess的融合模式,從標準輸出和標準容錯得到MPV 的信息。綁定QProcess的信號readyReadStandardOutput,當該信號出發時,再通過QProcess的readAllStandardOutput()函數獲取信息(當然,這里也可以while循環來判斷是否可以讀取一行數據:while(process->canReadLine()),如果可以,則讀取一行:QString line(process->readLine());),readAllStandardOutput獲取的數據類型為QByteArray,對數據進行解析時通過“\n” 和“\r” 切分后一行一行解析,通過對每行的QByteArray數據進行詳細解析可以得出MPV的狀態信息,并將一些狀態在Qt的圖形程序上動態展示處理,比如MPV播放成功,則根據播放成功的信息將Qt圖形的播放按鈕設置為可暫停狀態,此時點擊該按鈕給MPV發送的指令應該是暫停而非啟動。另外,可以綁定QProcess的信號finished(int, QProcess::ExitStatus),當該信號被觸發時,通過判斷QProcess的bytesAvailable()值,如果>0,則通過QProcess的readAllStandardOutput()函數獲取信息。

獲取MPV的信息進行解析的難點是對繁雜冗余的信息進行過濾,針對關鍵字定位信息表示的意思。這里可以使用Qt的對獲取的QRegExp來進行匹配。

下述正則表達式可用于分析出正在啟動中:

QRegExp rx_playing;

rx_playing.setPattern("^Playing:.*|^\\[ytdl_hook\\].*");

下述正則表達式可可解析出暫停、緩存中等各種狀態信息:

QRegExp rx_av;

rx_av.setPattern("^STATUS: ([0-9\\.-]+) / ([0-9\\.-]+) P: (yes|no) B: (yes|no) I: (yes|no) VB: ([0-9\\.-]+) AB: ([0-9\\.-]+)");

4、編程示例

使用Qt Creator創建一個新工程,模板中選擇"QApplication -> Qt Widgets Application",以下示例取名為mympvplayer,如下圖所示:

優麒麟(Ubuntu Kylin)

優麒麟(Ubuntu Kylin)

優麒麟(Ubuntu Kylin)

至此,一個最基本的UI圖形框架已經成功搭建完畢了,編譯和運行則會彈出一個最基本的QMainWindow圖形界面。接下來我們要做的就是在此基礎上豐富播放器的界面和完成最基本的功能邏輯處理,示例支持基本的文件播放(包括拖動文件到播放器進行播放和通過鼠標右鍵菜單選擇文件播放)、暫停、停止、進度控制(包括鼠標拖動進度條進行控制和鼠標滾輪上下滾動控制)、音量調節。下面將對部分代碼模塊進行簡單的說明,具體說明和示例代碼請查看:https://github.com/eightplus/examples/tree/master/code/Qt/mympvplayer 或 https://eightplus.github.io/2019/08/19/2019-08-19-qt-mpv-player/。

1)增加播放控制欄

這里在主界面的最下方增加一個播放控制欄區域,包括播放/暫停、停止、進度條、音量控制以及時長顯示等,如下圖所示:

優麒麟(Ubuntu Kylin)

在實例中,圖形界面相關的模塊主要有兩個,一個是類Mainwindow(mainwindow.cpp和mainwindow.h),另一個是類BottomWidget(bottomwidget.cpp和bottomwidget.h)。Mainwindow是主體,負責各個模塊對象的創建,圖形和數據的交互處理等。BottomWidget創建了三個按鈕(播放/暫停、停止、靜音),兩個滑動條(播放進度條、音量控制條),一個文字顯示區域(視頻時長和播放時長)。具體代碼見:https://github.com/eightplus/examples/blob/master/code/Qt/mympvplayer/bottomwidget.cpp。

2)增加顯示模塊類

類VideoWindow(videowindow.cpp和videowindow.h)中包含了一個QWidget對象,通過將QWidget對象的wid傳遞給MPV播放引擎用來顯示視頻。示例將視頻的顯示長寬比固定為了4/3。具體代碼見:https://github.com/eightplus/examples/blob/master/code/Qt/mympvplayer/videowindow.cpp。

3)增加進程控制類

類MyProcess(myprocess.cpp和myprocess.h)繼承于QProcess,使用上面接收QProcess時提到的QProcess::MergedChannels融合模式。該模塊的主要功能有兩點:一是負責向MPV發送指令,如播放、暫停等(通過write函數 ,每一條指令需要以"\n"結尾);而是接收MPV反饋的各類數據信息,并通過QRegExp設置正則表達式進行匹配和解析,從而顯示一些用戶可以識別和理解的信息,并實時根據一些狀態信息修改界面狀態或更改播放控制等。具體代碼見:https://github.com/eightplus/examples/blob/master/code/Qt/mympvplayer/myprocess.cpp。 

4)增加交互類

類Core(core.cpp和core.h)相當于一個管家,負責播放器圖形端和控制端的通信和交互。如圖形上的指令通過該類調用進程控制類的方法去給MPV發送指令,MPV的信息通過該類給圖形端去顯示。具體代碼見:https://github.com/eightplus/examples/blob/master/code/Qt/mympvplayer/core.cpp。

5)增加其他模塊類

上面提交的4個模塊,已經將播放器需要的圖形顯示、數據管理和指令處理描述完畢,接下來還需要增加一些輔助類,讓自定義的播放器功能更完善,如配置項類Preferences、視頻文件數據結構類MediaData、視頻文件各類數據設置類MediaSettings、MPV各類數據獲取類InfoReader和輔助功能模塊類Utils。

參考文檔和項目:

https://github.com/ukui/kylin-video/

https://mpv.io/manual/master/#configuration-files

https://mpv.io/manual/stable/

https://github.com/mpv-player/mpv/blob/master/etc/mpv.conf

https://github.com/mpv-player/mpv/blob/master/etc/input.conf



时时彩九码稳赚视频教程