操作系統: win10 64位
QT版本: QT5.12.6
編譯器: MinGW 32
QMediaPlayer是Qt提供的一個跨平臺媒體播放器類,它沒有自帶解碼庫,而是對平臺相關的播放器框架做了封裝,提供了平臺無關的API。所以使用QMediaPlayer播放視頻,需要提前安裝解碼庫。 在win系統下可以下載K-Lite_Codec_Pack或者LAVFilters解碼庫安裝。
下載地址:https://download.csdn.net/download/xiaolong1126626497/15702561
工程完整源碼下載: https://download.csdn.net/download/xiaolong1126626497/15804157
1. 支持命令行傳入視頻播放
2. 支持圖像旋轉播放
3. 支持查看媒體信息
4. 支持選擇GPU加速解碼
5. 支持快進、快退
6. 支持預覽畫面(鼠標放在進度條上查看畫面縮略圖)
7. 支持單幀播放,就是一幀一幀的點擊切換畫面
8. 支持畫面拍照、截圖
9. 支持復位到視頻首頁
10. 支持音量調整
11. 支持拖拽文件到窗口播放
12. 默認打開視頻不會自動播放。 自動顯示在第一幀,視頻放完停留在最后一幀。
為了更加方便處理視頻幀,代碼里重寫了QAbstractVideoSurface 類,接收解碼的視頻幀,自己完成繪制。
頭文件:
#ifndef MEDIAVIDEOFRAME_H#define MEDIAVIDEOFRAME_H#include <QAbstractVideoSurface>class MediaVideoFrame : public QAbstractVideoSurface{ Q_OBJECTpublic: explicit MediaVideoFrame(QObject *parent = nullptr);signals: void SendOneFrame(QImage img);public slots: // QAbstractVideoSurface interfacepublic: QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const; bool present(const QVideoFrame &frame);};#endif // MEDIAVIDEOFRAME_H
源文件:
#include "MediaVideoFrame.h"MediaVideoFrame::MediaVideoFrame(QObject *parent) : QAbstractVideoSurface(parent){}QList<QVideoFrame::PixelFormat> MediaVideoFrame::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const{ QList<QVideoFrame::PixelFormat> list; list<<QVideoFrame::Format_RGB32; //支持的格式 return list;}bool MediaVideoFrame::present(const QVideoFrame &frame){ if(frame.isValid()) { QVideoFrame cloneFrame(frame); cloneFrame.map(QAbstractVideoBuffer::ReadOnly); QImage img(cloneFrame.bits(),cloneFrame.width(),cloneFrame.height(),QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat())); cloneFrame.unmap(); emit SendOneFrame(img); return true; } return false;}
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QFile>#include <QFileDialog>#include <QActionGroup>#include <QMenu>#include <QApplication>#include <QClipboard>#include <QStyle>#include <QToolTip>#include <QDragEnterEvent>#include <QDropEvent>#include <QMimeData>#include <QMouseEvent>#include "work_thread.h"#include "dialog_waitcomplete.h"#include <QDesktopWidget>#include <QMessageBox>#include <QMediaPlayer>#include "MediaVideoFrame.h"QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEenum MENU_ITEM{ MENU_COPY_CLIPBOARD = 0, MENU_SAVE_FILE_SYSTEM, MENU_EDIT_SUBTITLE, MENU_SHOW_SUBTITLE, MENU_PLAY_NARRATOR, MENU_TO_KeyFrame, //轉為關鍵幀 MENU_APP_INFO,//APP信息介紹};enum MEDIA_STATE{ MEDIA_NOLOAD,//視頻未加載 MEDIA_LOAD,//視頻加載};//媒體狀態信息struct MediaStateInfo{ MEDIA_STATE state; QString mediaName;};//配置文件名稱#define ConfigFile "cofnig.ini"class Widget : public QWidget{ Q_OBJECTpublic: Widget(QString filename=nullptr,QWidget *parent = nullptr); ~Widget(); //加載樣式表 void SetStyle(const QString &qssFile); //UI界面初始化 void UI_InitConfig(); //加載視頻文件 bool load_video_file(bool flag, QString file_path); //保存配置 void SaveConfig(); //讀取配置 void ReadConfig(); //播放器初始化 void MediaPlayer_InitConfig(void); signals: void s_pause_state(bool pause_state,qint64 current_time); void s_PlayPosTime(qint64 pos_time);protected: bool eventFilter(QObject *obj, QEvent *event); void dragEnterEvent(QDragEnterEvent *e); void dropEvent(QDropEvent *e);private slots: void slot_stateChanged(QMediaPlayer::State); void slot_PlayError(QMediaPlayer::Error); void slot_wheelEvent(bool type); void seek(); void seek(int); void onTimeSliderHover(int pos, int value); void onTimeSliderLeave(); void slot_onMediaSnapshot(QAction *action); void slot_onConfigurationFunction(QAction *action); void slot_onMediaRotate(QAction *action); void slot_onSetTimeSpeed(QAction *action); void updateSliderPosition(qint64 value); void media_durationChanged(qint64); void on_toolButton_load_clicked(); void on_toolButton_init_load_clicked(); void on_MediaPauseBtn_clicked(); void on_MediaResetBtn_clicked(); void on_MediaPrevBtn_clicked(); void on_MediaPlayBtn_clicked(); void on_ReverseFrameBtn_clicked(); void on_ForwardFrameBtn_clicked(); void on_VolumeBtn_clicked(); void on_horizontalSlider_AudioValue_valueChanged(int value); void on_MediaSpeedBtn_clicked(); void on_MediaRotateBtn_clicked(); void on_MediaSnapshotBtn_clicked(); void on_toolButton_set_clicked(); void on_toolButton_media_info_clicked(); void on_checkBox_gpu_set_clicked(bool checked);private: Ui::Widget *ui; struct MediaStateInfo MediaInfo; QActionGroup *m_TimeSpeedGrp; QMenum_SpeedMenu; QActionGroup*m_RotateGrp; QMenum_RotateMenu; QActionGroup*m_SnapshotGrp; QMenum_SnapshotMenu; QActionGroup*m_ConfigurationFunctionGrp; QMenum_ConfigurationFunctionMenu; //視頻名稱 char video_name[1024]; //視頻名稱 //工作線程 CWorkThread *work_thread; QMediaPlayer *MeadiaPlayer; MediaVideoFrame *VideoFrame;};#endif // WIDGET_H
#include "widget.h"#include "ui_widget.h"Widget::Widget(QString filename,QWidget *parent) : QWidget(parent) , ui(new Ui::Widget){ ui->setupUi(this); //設置窗口的標題名稱 this->setWindowTitle("視頻播放器-K-Lite_Codec_Pack"); //加載樣式表 SetStyle(":/resource/ECRS_VideoPlayer.qss"); //讀取配置文件 ReadConfig(); //播放器初始化 MediaPlayer_InitConfig(); //UI界面相關初始化 UI_InitConfig(); //如果構造函數傳入的視頻文件就直接加載 if(!filename.isempty()) { load_video_file(0,filename); }}Widget::~Widget(){ delete ui;}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 加載樣式表*/void Widget::SetStyle(const QString &qssFile){ QFile file(qssFile); if (file.open(QFile::ReadOnly)) { QByteArray qss=file.readAll(); qApp->setStyleSheet(qss); file.close(); }}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: UI界面初始化*/void Widget::UI_InitConfig(){ //音量滑塊范圍設置 ui->horizontalSlider_AudioValue->setMaximum(10); ui->horizontalSlider_AudioValue->setMinimum(0); //播放速度設置 ui->MediaSpeedBtn->setCheckable(true); m_TimeSpeedGrp = new QActionGroup(this); QStringList strSpeedItems; strSpeedItems << tr("0.03X") << tr("0.06X") << tr("0.1X") << tr("0.15X") << tr("0.2X") << tr("0.3X") << tr("0.4X") << tr("0.5X") << tr("0.6X") << tr("0.8X") << tr("1.0X") << tr("1.25X") << tr("1.5X") << tr("2.0X") << tr("4.0X") << tr("8.0X"); float speeds[] = { 0.03, 0.06, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5,0.6,0.8,1.0,1.25,1.5,2.0,4.0,8.0}; for (int i = 0; i < strSpeedItems.size(); i++) { QAction *pSpeedItem = m_SpeedMenu.addAction(strSpeedItems.at(i)); pSpeedItem->setData(QVariant::fromValue(speeds[i])); pSpeedItem->setCheckable(true); m_TimeSpeedGrp->addAction(pSpeedItem); if (i == 10) { pSpeedItem->setChecked(true); } } connect(m_TimeSpeedGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onSetTimeSpeed(QAction *))); //圖像的旋轉方向 m_RotateGrp = new QActionGroup(this); QStringList strDegrees; strDegrees << tr("0~") << tr("90~") << tr("180~") << tr("270~"); int Degrees[] = {0, 90, 180, 270 }; for (int i = 0; i < strDegrees.size(); i++) { QAction *pItem = m_RotateMenu.addAction(strDegrees.at(i)); pItem->setData(QVariant::fromValue(Degrees[i])); pItem->setCheckable(true); m_RotateGrp->addAction(pItem); } connect(m_RotateGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onMediaRotate(QAction *))); //功能設置 // ui->toolButton_set->setCheckable(true); m_ConfigurationFunctionGrp = new QActionGroup(this); QAction *pToKeyFrame = m_ConfigurationFunctionMenu.addAction(tr("轉為關鍵幀")); QAction *pAppInfo = m_ConfigurationFunctionMenu.addAction(tr("功能說明")); pToKeyFrame->setData(MENU_TO_KeyFrame); //保存到剪切板 pAppInfo->setData(MENU_APP_INFO); //保存到文件 m_ConfigurationFunctionGrp->addAction(pToKeyFrame); //添加到分組 m_ConfigurationFunctionGrp->addAction(pAppInfo); //添加到分組 connect(m_ConfigurationFunctionGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onConfigurationFunction(QAction *))); //截圖保存 // ui->MediaSnapshotBtn->setCheckable(true); m_SnapshotGrp = new QActionGroup(this); QAction *pClipboard = m_SnapshotMenu.addAction(tr("保存到剪切板")); QAction *pFileDirectory = m_SnapshotMenu.addAction(tr("保存到文件")); pClipboard->setData(MENU_COPY_CLIPBOARD); //保存到剪切板 pFileDirectory->setData(MENU_SAVE_FILE_SYSTEM); //保存到文件 m_SnapshotGrp->addAction(pClipboard); //添加到分組 m_SnapshotGrp->addAction(pFileDirectory); //添加到分組 connect(m_SnapshotGrp, SIGNAL(triggered(QAction *)), this, SLOT(slot_onMediaSnapshot(QAction *))); //安裝事件監聽器 事件篩選器是接收發送到此對象的所有事件的對象 ui->horizontalSlider_PlayPosition->installEventFilter(this); ui->widget_videoDisplay->installEventFilter(this); //狀態信息初始化 MediaInfo.state=MEDIA_NOLOAD; //工具提示信息 ui->toolButton_init_load->setToolTip(tr("加載視頻,也可以直接將視頻文件拖拽到窗口")); ui->toolButton_load->setToolTip(tr("加載視頻,也可以直接將視頻文件拖拽到窗口")); ui->toolButton_media_info->setToolTip(tr("媒體信息")); ui->MediaPrevBtn->setToolTip(tr("快退")); ui->MediaPlayBtn->setToolTip(tr("快進")); ui->MediaPauseBtn->setToolTip(tr("暫停/繼續")); ui->MediaSpeedBtn->setToolTip(tr("倍速選擇")); ui->MediaResetBtn->setToolTip(tr("復位")); ui->MediaSnapshotBtn->setToolTip(tr("截圖")); ui->MediaRotateBtn->setToolTip(tr("畫面旋轉")); ui->ReverseFrameBtn->setToolTip(tr("左一幀")); ui->ForwardFrameBtn->setToolTip(tr("右一幀")); ui->VolumeBtn->setToolTip(tr("靜音切換")); ui->checkBox_gpu_set->setToolTip(tr("GPU硬件解碼支持(需要重啟軟件才能生效)")); //播放進度條滑塊初始化 connect(ui->horizontalSlider_PlayPosition, SIGNAL(onLeave()), SLOT(onTimeSliderLeave())); connect(ui->horizontalSlider_PlayPosition, SIGNAL(onHover(int,int)), SLOT(onTimeSliderHover(int,int))); connect(ui->horizontalSlider_PlayPosition, SIGNAL(sliderMoved(int)), SLOT(seek(int))); connect(ui->horizontalSlider_PlayPosition, SIGNAL(sliderPressed()), SLOT(seek())); this->setMouseTracking(true); connect(this, SIGNAL(s_pause_state(bool,qint64)),ui->widget_videoDisplay,SLOT(slot_pause_state(bool,qint64))); connect(this, SIGNAL(s_PlayPosTime(qint64)),ui->widget_videoDisplay,SLOT(slot_PlayPosTime(qint64))); //工作線程 work_thread =new CWorkThread;}/*工程: ECRS_VideoPlayer日期: 2021-03-15作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: MediaPlayer初始化*/void Widget::MediaPlayer_InitConfig(void){ /*多媒體類*/ MeadiaPlayer = new QMediaPlayer(this); VideoFrame = new MediaVideoFrame; /*設置視頻解碼輸出的位置*/ MeadiaPlayer->setVideoOutput(VideoFrame); //關聯播放器的視頻幀顯示 connect(VideoFrame, SIGNAL(SendOneFrame(QImage)),ui->widget_videoDisplay,SLOT(slotGetOneFrame(QImage))); //添加播放進度的信號 connect(MeadiaPlayer, SIGNAL(positionChanged(qint64)),this, SLOT(updateSliderPosition(qint64))); //添加獲取播放總時間的信號 connect(MeadiaPlayer, SIGNAL(durationChanged(qint64)),this, SLOT(media_durationChanged(qint64))); //關聯鼠標事件 connect(ui->widget_videoDisplay, SIGNAL(s_wheelEvent(bool)),this,SLOT(slot_wheelEvent(bool))); //關聯錯誤提示信號 connect(MeadiaPlayer, SIGNAL(error(QMediaPlayer::Error)),this,SLOT(slot_PlayError(QMediaPlayer::Error))); //狀態發生改變 connect(MeadiaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)),this,SLOT(slot_stateChanged(QMediaPlayer::State))); //設置更新間隔 MeadiaPlayer->setNotifyInterval(100);}/*工程: ECRS_VideoPlayer日期: 2021-03-15作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 設置播放器*/void Widget::slot_PlayError(QMediaPlayer::Error error){ QString text; if(QMediaPlayer::NoError==error) { text="正常解碼!"; } else if(QMediaPlayer::ResourceError==error) { text="媒體資源無法解析。"; } else if(QMediaPlayer::FormatError==error) { text="不支持該媒體資源的格式,沒有解碼器!"; } else if(QMediaPlayer::NetworkError==error) { text="發生網絡錯誤。"; } else if(QMediaPlayer::AccessDeniedError==error) { text="沒有適當的權限來播放媒體資源。"; } else if(QMediaPlayer::ServiceMissingError==error) { text="沒有找到有效的播放服務,播放無法繼續。"; } QMessageBox::critical(this,"播放器提示",text,QMessageBox::Ok,QMessageBox::Ok);}/*工程: ECRS_VideoPlayer日期: 2021-03-15作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 狀態發生改變*/void Widget::slot_stateChanged(QMediaPlayer::State state){ switch (state) { case QMediaPlayer::StoppedState: qDebug()<<"視頻停止播放"; break; case QMediaPlayer::PlayingState: qDebug()<<"視頻繼續播放"; ui->MediaPauseBtn->setChecked(false); break; case QMediaPlayer::PausedState: qDebug()<<"視頻暫停播放"; ui->MediaPauseBtn->setChecked(true); break; }}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 更新播放進度*/void Widget::updateSliderPosition(qint64 value){ //設置進度條的時間 ui->horizontalSlider_PlayPosition->setValue(int(value)); //通知播放器顯示窗體 emit s_PlayPosTime(value); //設置右上角的時間 ui->label_current_Time->setText(QTime(0, 0, 0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss")));}/*工程: ECRS_VideoPlayer日期: 2021-03-15作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 媒體總時間*/void Widget::media_durationChanged(qint64 value){ //最大值最小值 ui->horizontalSlider_PlayPosition->setMinimum(int(0)); ui->horizontalSlider_PlayPosition->setMaximum(int(value)); ui->label_Total_Time->setText(QTime(0, 0, 0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss")));}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 加載視頻文件 flag=0 重新加載文件 flag=1 重新開始播放QString file_path 這參數可以傳入文件名稱,因為窗口支持拖放文件進來返回值: true 成功 false 失敗*/bool Widget::load_video_file(bool flag,QString file_path){ if(flag==false) { QString filename=file_path; if(filename.isEmpty()) { filename=QFileDialog::getOpenFileName(this,"選擇播放的視頻","D:/",tr("*.mp4 *.wmv *.*")); } strncpy(video_name,filename.toUtf8().data(),sizeof(video_name)); ui->toolButton_init_load->setVisible(false); } //判斷文件是否存在 if(QFileInfo::exists(video_name)==false) { return false; } else { MediaInfo.state=MEDIA_LOAD; MediaInfo.mediaName=video_name; } //每次加載新文件設置播放進度條為0 ui->horizontalSlider_PlayPosition->setValue(0); qDebug()<<"停止原視頻"; //停止播放 MeadiaPlayer->stop(); //播放視頻 MeadiaPlayer->setMedia(QUrl::fromLocalFile(video_name)); MeadiaPlayer->pause(); qDebug()<<"當期播放視頻:"<<video_name; //設置當前播放的視頻名稱 QFileInfo info(video_name); ui->label_FileName->setText(QString("%1").arg(info.fileName())); return true;}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 加載視頻文件*/void Widget::on_toolButton_load_clicked(){ qDebug()<<"加載視頻文件狀態:"<<load_video_file(0,"");}void Widget::on_toolButton_init_load_clicked(){ load_video_file(0,"");}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 暫停播放*/void Widget::on_MediaPauseBtn_clicked(){ //暫停狀態 if (MeadiaPlayer->state()==QMediaPlayer::PausedState) { //通知播放器 s_pause_state(true,ui->horizontalSlider_PlayPosition->value()); //繼續播放 MeadiaPlayer->play(); return; } else { //暫停播放 MeadiaPlayer->pause(); }}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 重新開始播放*/void Widget::on_MediaResetBtn_clicked(){ //加重新開始播放 load_video_file(true,"");}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 快退播放*/void Widget::on_MediaPrevBtn_clicked(){ //得到播放進度的當前位置 int value=ui->horizontalSlider_PlayPosition->value(); int m_unit = MeadiaPlayer->notifyInterval();//獲取更新間隔時間 //設置每次點擊快退的距離 MeadiaPlayer->setPosition(value-m_unit*10);}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 快進播放*/void Widget::on_MediaPlayBtn_clicked(){ //得到播放進度的當前位置 int value=ui->horizontalSlider_PlayPosition->value(); int m_unit = MeadiaPlayer->notifyInterval();//獲取更新間隔時間 //設置每次點擊快退的距離 MeadiaPlayer->setPosition(value+m_unit*10);}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 向左一幀*/void Widget::on_ReverseFrameBtn_clicked(){ //得到播放進度的當前位置 int value=ui->horizontalSlider_PlayPosition->value(); int m_unit = MeadiaPlayer->notifyInterval();//獲取更新間隔時間 //設置每次點擊快退的距離 MeadiaPlayer->setPosition(value-m_unit);}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 向右一幀*/void Widget::on_ForwardFrameBtn_clicked(){ //得到播放進度的當前位置 int value=ui->horizontalSlider_PlayPosition->value(); int m_unit = MeadiaPlayer->notifyInterval();//獲取更新間隔時間 //設置每次點擊快退的距離 MeadiaPlayer->setPosition(value+m_unit);}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 音量設置*/void Widget::on_VolumeBtn_clicked(){ bool checked=ui->VolumeBtn->isChecked(); if(checked) { //靜音 //音量設置 MeadiaPlayer->setVolume(0); } else { //設置正常音量 int volume_val=ui->horizontalSlider_AudioValue->value(); //音量設置 MeadiaPlayer->setVolume(int(volume_val)); }}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 音量設置*/void Widget::on_horizontalSlider_AudioValue_valueChanged(int value){ //音量設置 MeadiaPlayer->setVolume(value);}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 播放速度設置菜單選擇*/void Widget::slot_onSetTimeSpeed(QAction *action){ action->setChecked(true); ui->MediaSpeedBtn->setToolTip(action->text()); ui->MediaSpeedBtn->setText(action->text()); //設置速度 正常速度是1.0 MeadiaPlayer->setPlaybackRate(qreal(action->data().toFloat()));}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了速度設置按鈕*/void Widget::on_MediaSpeedBtn_clicked(){ QPoint ptWgt = ui->MediaSpeedBtn->mapToGlobal(QPoint(0, 0)); ptWgt -= QPoint(10, 180); QAction *pSelect = m_SpeedMenu.exec(ptWgt); if (pSelect == nullptr) return;}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了旋轉選擇菜單*/void Widget::slot_onMediaRotate(QAction *action){ action->setChecked(true); ui->MediaRotateBtn->setToolTip(action->text()); ui->widget_videoDisplay->Set_Rotate(action->data().toInt());}/*工程: ECRS_VideoPlayer日期: 2021-02-23作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了畫面旋轉菜單*/void Widget::on_MediaRotateBtn_clicked(){ QPoint ptWgt = ui->MediaRotateBtn->mapToGlobal(QPoint(0, 0)); ptWgt -= QPoint(10, 94); QAction *pSelect = m_RotateMenu.exec(ptWgt); if (pSelect == nullptr) return;}/*工程: ECRS_VideoPlayer日期: 2021-03-08作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了功能設置菜單*/void Widget::slot_onConfigurationFunction(QAction *action){ if (action == nullptr) return; //得到按下的序號 MENU_ITEM item = MENU_ITEM(action->data().toInt()); //轉視頻為關鍵幀 if (item == MENU_TO_KeyFrame) { qDebug()<<"轉視頻為關鍵幀"; //創建窗口,顯示導出的過程信息,并綁定信號. Dialog_WaitComplete wait; connect(work_thread, &CWorkThread::exit_close,&wait, &Dialog_WaitComplete::dialog_close); QString video_file=QFileDialog::getOpenFileName(this,"選擇打開的視頻文件","D:/",tr("*.*")); //filename==選擇文件的絕對路徑 if(video_file.isEmpty())return; QFileInfo info(video_file); QString output_video=info.absolutePath()+info.baseName()+"_KeyFrame"+"."+info.suffix(); qDebug()<<"output_video:"<<output_video; //拼接命令 QString strCmd=QCoreApplication::applicationDirPath(); //得到程序的執行路徑 strCmd += QString("/ffmpeg_422.exe -i %1 -strict -2 -qscale 0 -intra %2") .arg(video_file) //輸入視頻文件路徑 .arg(output_video); //輸出的文件名稱 qDebug()<<"strCmd:"<<strCmd; //判斷輸出文件是否已經存在 QFileInfo out_file(output_video); if(out_file.exists()) //文件存在就不需要轉換 { QFile::remove(output_video); //return; } //先退出線程 work_thread->quit(); work_thread->wait(); work_thread->SetRunCmd(strCmd); work_thread->start(); //執行線程 //設置遮罩窗口 QWidget mask_window(this); //設置窗體的背景色,這里的百分比就是透明度 mask_window.setStyleSheet(QString("background-color: rgba(0, 0, 0, 50%);")); mask_window.setGeometry(this->rect()); //設置當前窗口 mask_window.show(); //顯示狀態窗口 wait.SetText("請等待..."); wait.show(); wait.exec(); //關閉遮罩窗口 mask_window.close(); } //APP功能介紹 else if(item==MENU_APP_INFO) { qDebug()<<"APP功能介紹"; QString text= "Bug提交: QQ1126626497n" "1. 支持命令行傳入視頻播放n" "2. 支持圖像旋轉播放n" "3. 支持查看媒體信息n" "4. 支持選擇GPU加速解碼n" "5. 支持快進、快退n" "6. 支持預覽畫面(鼠標放在進度條上查看畫面縮略圖)n" " 7. 支持單幀播放,就是一幀一幀的點擊切換畫面n" " 8. 支持畫面拍照、截圖n" " 9. 支持復位到視頻首頁n" "10. 支持音量調整n" "11. 支持拖拽文件到窗口播放n" "12. 默認打開視頻不會自動播放。自動顯示在第一幀,視頻放完停留在最后一幀。n" "13. 支持視頻轉關鍵幀輸出.方便鼠標滾輪單幀跳轉n"; QMessageBox::about(this,"播放器功能介紹",text); }}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了截圖菜單*/void Widget::slot_onMediaSnapshot(QAction *action){ if (action == nullptr) return; //得到按下的序號 MENU_ITEM item = MENU_ITEM(action->data().toInt()); QImage Pic=ui->widget_videoDisplay->GetImage(); if (Pic.isNull() || Pic.height() <= 0)return; //保存到剪切板 if (item == MENU_COPY_CLIPBOARD) { QApplication::clipboard()->setImage(Pic); } //保存到文件 else if (item == MENU_SAVE_FILE_SYSTEM) { QString strFile = QDateTime::currentDateTime().toString("yyyyMMddHHmmss") + ".png"; QString strFileName = QFileDialog::getSaveFileName(nullptr, "保存圖片", strFile, "PNG(*.png);;BMP(*.bmp);;JPEG(*.jpg *.jpeg)"); if (!strFileName.isEmpty()) { strFileName = QDir::toNativeSeparators(strFileName); QFileInfo fInfo(strFileName); Pic.save(strFileName, fInfo.completeSuffix().toStdString().c_str(), 80); } }}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了截圖按鈕*/void Widget::on_MediaSnapshotBtn_clicked(){ QPoint ptWgt = ui->MediaSnapshotBtn->mapToGlobal(QPoint(0, 0)); ptWgt -= QPoint(10, 48); QAction *pSelect = m_SnapshotMenu.exec(ptWgt); if (pSelect == nullptr) return;}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 攔截事件*/bool Widget::eventFilter(QObject *obj, QEvent *event){ //判斷是否在視頻窗口范圍內按下的鼠標 if(obj==ui->widget_videoDisplay) { //視頻加載成功才能進行下面的操作 if(MediaInfo.state==MEDIA_LOAD) { //判斷是否是鼠標事件 if (event->type()==QEvent::MouseButtonPress) { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); //如果按下的是左鍵 if(mouseEvent->button() == Qt::LeftButton) { //如果是暫停狀態 if(MeadiaPlayer->state()==QMediaPlayer::PausedState) { //繼續播放 MeadiaPlayer->play(); //通知播放器 s_pause_state(true,ui->horizontalSlider_PlayPosition->value()); } else { //暫停播放 MeadiaPlayer->pause(); } } } } } return QObject::eventFilter(obj,event);}/*工程: ECRS_VideoPlayer日期: 2021-03-08作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 點擊了設置按鈕*/void Widget::on_toolButton_set_clicked(){ QPoint ptWgt = ui->toolButton_set->mapToGlobal(QPoint(0, 0)); ptWgt -= QPoint(10, 48); QAction *pSelect = m_ConfigurationFunctionMenu.exec(ptWgt); if (pSelect == nullptr) return;}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 查看媒體信息*/void Widget::on_toolButton_media_info_clicked(){}void Widget::onTimeSliderHover(int pos, int value){}void Widget::onTimeSliderLeave(){}void Widget::seek(int value){ MeadiaPlayer->setPosition(qint64(value));}void Widget::seek(){ seek(ui->horizontalSlider_PlayPosition->value());}void Widget::dragEnterEvent(QDragEnterEvent *e){ if (e->mimeData()->hasUrls()) { e->acceptProposedAction(); }}void Widget::dropEvent(QDropEvent *e){ foreach (const QUrl &url, e->mimeData()->urls()) { QString fileName = url.toLocalFile(); qDebug() << "拖入的文件名稱:" << fileName; //加載視頻文件 load_video_file(false,fileName); }}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 保存配置*/void Widget::SaveConfig(){ //從UI界面獲取用戶的個性化配置參數 bool val=ui->checkBox_gpu_set->isChecked(); /*保存數據到文件,方便下次加載*/ QString text; text=QCoreApplication::applicationDirPath()+"/"+ConfigFile; QFile filesrc(text); filesrc.open(QIODevice::WriteOnly); QDataStream out(&filesrc); out << val; //序列化 filesrc.flush(); filesrc.close();}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 讀取配置*/void Widget::ReadConfig(){// //讀取配置文件// QString text;// text=QCoreApplication::applicationDirPath()+"/"+ConfigFile;// bool val;// //判斷文件是否存在// if(QFile::exists(text))// {// QFile filenew(text);// filenew.open(QIODevice::ReadOnly);// QDataStream in(&filenew); // 從文件讀取序列化數據// in >> val; //提取寫入的數據// filenew.close();// //設置界面值// ui->checkBox_gpu_set->setChecked(val);// } //因為使用的系統接口,默認就是使用GPU ui->checkBox_gpu_set->setChecked(true);}/*工程: ECRS_VideoPlayer日期: 2021-02-24作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: GPU支持選擇*/void Widget::on_checkBox_gpu_set_clicked(bool checked){ SaveConfig();}/*工程: ECRS_VideoPlayer日期: 2021-03-07作者: DS小龍哥環境: win10 QT5.12.6 MinGW32功能: 鼠標滾輪事件true 向前false 向后*/void Widget::slot_wheelEvent(bool type){ //鼠標滾輪向前 if(type) { on_ForwardFrameBtn_clicked(); } //鼠標滾輪向后 else { on_ReverseFrameBtn_clicked(); }}
注意: 運行的時候,需要把QT安裝目錄下的“mediaservice” 目錄拷貝到程序運行目錄下。
比如我的目錄路徑:C:QtQt5.12.65.12.6mingw73_32pluginsmediaservice
解碼器安裝之后的目錄如下:
最后程序打包的時候,可以把解碼庫一起打包放在程序執行目錄下,注冊3個ax文件即可。
可以將以下代碼寫入到xxx.bat文件中,直接運行。 注意: 要用管理員身份運行。
cd /d %~dp0@regsvr32 LAVAudio.ax@regsvr32 LAVSplitter.ax@regsvr32 LAVVideo.ax@exit
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
正常一套窗簾要多少錢?這取決于窗簾的尺寸。一般窗簾長三米,寬三米。也就是9個正方形的面積。如果是每平方50元,那就是450元左右。不同材質的窗簾價格也不同。如果是紗窗,大概200元。如果是棉質的雙層紗窗,大概要450~500元。如果是真絲的,應該要1000~1200元。正常一套窗簾要多少錢?窗簾的價格主要看材質,不同材質的價格自然不同。以下是不同材質窗簾的大概價格,僅供參考:1.化纖面料:化纖面料...
Mom、Dad、Grandma和Grandpa在什么時候字母需要大寫?您好,首先,在正常情況下,長者的地址不需要大寫。第二,以地址的大小寫作為強調。第三,無線首字母大寫的情況是在句首。我希望我能幫助你。印度的首字母大寫?印度,英語,大寫I。斗羅大陸的大寫首字母?豆洛大陸拼音大寫豆洛大路第三音第二音第四音第四音大寫豆洛大路...
泰和烏雞的作用與功效 你知道泰和烏雞嗎?烏雞的品種? 泰和烏雞起源于泰和縣武山,又稱武山雞。它與其他雞有八個不同的特點:紫色鳳冠、綠耳、五爪、胡須、白絲毛、藍流蘇頭、烏皮、烏肉。因此,有些地方以其部分特點命名為絲毛烏骨、羊毛雞、絲絲雞、竹絲雞、松花雞、墨腳雞等。它已經飼養了1300多年。清朝乾隆年間,乾隆皇帝見泰和烏雞,不僅外表出眾,而且肉質細嫩,味道鮮美。它被認為是一種奇怪的珍品,被命名為武...