一、环境介绍
操作系统: win10 64位
QT版本: QT5.12.6
编译器: MinGW 32
libvlc版本: 3.0.12
完整工程下载地址(下载即可编译运行): VLC_Core_VideoPlayer.zip-QT文档类资源-CSDN下载
二、播放器运行效果与功能介绍
播放器的功能介绍:
1. 图像旋转播放(90°、0°、180°、360°)
2. 视频画面截图保存到本地
3. 倍速切换、速度切换不会改变声音音色
4. 音量调整,静音切换
5. 快进、快退支持
6. 点击按钮加载文件、鼠标拖拽文件进行播放
7. 重播按钮支持
8. 暂停与继续切换
9. 单帧切换、前一帧、后一帧
10. 流媒体播放,输入流媒体链接
11. 进度条显示,支持鼠标点击任意跳转到点击位置
12. 播放时间实时更新显示
其他功能可自己增加.....
三、libVLC介绍
3.1 下载VLC的SDK文件
VLC官网地址: VLC: Official site - Free multimedia solutions for all OS! - VideoLAN
所有的VLC版本下载地址: http://ftp.heanet.ie/pub/videolan/vlc
3.0.12的SDK下载地址: Index of /pub/videolan/vlc/last/win32
3.2 libvlc介绍
来至官网的介绍:
libVLC是核心引擎,也是VLC 媒体播放器所基于的多媒体框架的接口。
libVLC被模块化为数百个插件,可以在运行时加载。这种架构为开发人员(VLC 开发人员和使用该库的开发人员)提供了极大的灵活性。它允许开发人员使用VLC功能创建范围广泛的多媒体应用程序。
播放每种媒体文件格式、每种编解码器和每种流媒体协议。
在各种平台上运行,从桌面(Windows、Linux、Mac)到移动设备(Android、iOS)和电视。
每个平台上的硬件和高效解码,高达 8K。
远程文件系统(SMB、FTP、SFTP、NFS...)和服务器(UPnP、DLNA)的网络浏览。
使用菜单导航播放音频 CD、DVD 和蓝光。
支持 HDR,包括 SDR 流的色调映射。
具有 SPDIF 和 HDMI 的音频直通,包括音频高清编解码器,如 DD+、TrueHD 或 DTS-HD。
支持视频和音频过滤器。
支持 360 度视频和 3D 音频播放,包括 Ambisonics。
能够投射和流式传输到远程渲染器,如 Chromecast 和 UPnP 渲染器。
libVLC是一个 C 库,可以嵌入到您自己的应用程序中。它适用于大多数流行的操作系统平台,包括移动设备和桌面设备。它在LGPL2.1 许可下。
libVLC版本控制本质上与 VLC 应用程序版本控制相关联。libVLC 当前稳定的主要版本是 version 3,预览/开发版本是 version 4。
libVLC 的各种编程语言绑定可用于在您选择的生态系统中无缝使用该库。
VideoLAN 绑定
用于 C++ 的libvlcpp
用于 Apple 平台的VLCKit,使用 Objective-C/Swift。
用于 Android 平台的libvlcjni,使用 Java/Kotlin。
LibVLCSharp适用于大多数操作系统平台,使用 .NET/Mono。
社区绑定
vlcj用于使用 Java 的桌面平台。
python-vlc用于使用 Python 的桌面平台。
vlc-rs使用 Rust 编程语言。
libvlc-go使用 Go 编程语言。
四、播放器程序设计
#include "widget.h" #include "ui_widget.h" Widget* Widget::pThis = nullptr; Widget::Widget(QString filename,QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); pThis=this; //设置窗口的标题名称 this->setWindowTitle("VLC内核视频播放器"); //获取VLC版本号 qDebug()<<"VLC内核版本:"<<libvlc_get_version(); qDebug()<<"编译LIBVLC的编译器版本:"<<libvlc_get_compiler(); //加载样式表 SetStyle(":/resource/VideoPlayer.qss"); //读取配置文件 ReadConfig(); //播放器初始化 VLC_InitConfig(); //UI界面相关初始化 UI_InitConfig(); //如果构造函数传入的视频文件就直接加载 if(!filename.isEmpty()) { load_video_file(0,filename); } //拖放文件需要使用 setAcceptDrops(true); } Widget::~Widget() { delete ui; libvlc_release(vlc_base); //减少libvlc实例的引用计数,并销毁它 } /* 工程: 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(100); ui->horizontalSlider_AudioValue->setMinimum(0); //安装事件过滤器 ui->horizontalSlider_AudioValue->installEventFilter(this); //播放速度设置 ui->MediaSpeedBtn->setCheckable(true); m_TimeSpeedGrp = new QActionGroup(this); QStringList strSpeedItems; strSpeedItems << tr("0.5X") << tr("1.0X") << tr("1.5X") << tr("2.0X") << tr("4.0X"); float speeds[] = {0.5,1.0,1.5,2.0,4.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 == 1) { 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); if (i == 0) { pItem->setChecked(true); } } 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("保留1")); QAction *pAppInfo = m_ConfigurationFunctionMenu.addAction(tr("保留2")); 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_load->setToolTip(tr("加载视频,也可以直接将视频文件拖拽到窗口")); ui->MediaPrevBtn->setToolTip(tr("快退5秒")); ui->MediaPlayBtn->setToolTip(tr("快进5秒")); 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->toolButton_link->setToolTip(tr("流媒体链接")); //播放进度条滑块初始化 connect(ui->horizontalSlider_PlayPosition, SIGNAL(sliderMoved(int)), SLOT(seek(int))); connect(ui->horizontalSlider_PlayPosition, SIGNAL(sliderPressed()), SLOT(seek())); this->setMouseTracking(true); } /* 工程: ECRS_VideoPlayer 日期: 2021-03-15 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: MediaPlayer初始化 */ void Widget::VLC_InitConfig(void) { const char *tempArg = ""; // tempArg = "--demux=h264"; const char *vlc_args[9] = {"-I", "dummy", "--no-osd", "--no-stats", "--ignore-config", "--no-video-on-top", "--no-video-title-show", "--no-snapshot-preview", tempArg}; //VLC相关的初始化 //vlc_base=libvlc_new(0, nullptr); //创建并初始化libvlc实例 vlc_base=libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); if(!vlc_base) { qDebug()<<"libvlc_new 执行错误."; } //图像缓冲区申请空间 ctx.pixels = new uchar[MAX_WIDTH * MAX_HEIGHT * 4]; } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 更新播放进度 */ void Widget::updateSliderPosition(qint64 value) { //设置进度条的时间 ui->horizontalSlider_PlayPosition->setValue(int(value)); //设置右上角的时间 ui->label_current_Time->setText(QTime(0, 0, 0,0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); } /* 工程: 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,0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); } /* 工程: QtVLC_Player 日期: 2021-03-24 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: VLC的事件回调 */ void Widget::vlcEvents(const libvlc_event_t *ev, void *param) { libvlc_time_t play_ms_pos=0; switch (ev->type){ case libvlc_MediaPlayerTimeChanged: //获取当前视频的播放位置 play_ms_pos=libvlc_media_player_get_time(pThis->vlc_mediaPlayer); //设置右上角的时间 pThis->ui->label_current_Time->setText(QTime(0, 0, 0,0).addMSecs(int(play_ms_pos)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); //设置进度条 pThis->ui->horizontalSlider_PlayPosition->setValue(int(play_ms_pos)); break; case libvlc_MediaPlayerEndReached: qDebug() << "VLC播放完毕."; break; case libvlc_MediaPlayerStopped: qDebug() << "VLC停止播放"; //获取当前视频的播放位置 play_ms_pos=libvlc_media_player_get_time(pThis->vlc_mediaPlayer); //设置右上角的时间 pThis->ui->label_current_Time->setText(QTime(0, 0, 0,0).addMSecs(int(play_ms_pos)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); //设置进度条 pThis->ui->horizontalSlider_PlayPosition->setValue(int( pThis->ui->horizontalSlider_PlayPosition->maximum())); break; case libvlc_MediaPlayerPlaying: qDebug() << "VLC开始播放"; break; case libvlc_MediaPlayerPaused: qDebug() << "VLC暂停播放"; break; case libvlc_MediaParsedChanged: qDebug() << "获取到元数据"; int state=ev->u.media_parsed_changed.new_status; if(libvlc_media_parsed_status_done==state) { qDebug()<<"媒体元数据:"<<libvlc_media_get_meta(pThis->vlc_media,libvlc_meta_Date); } break; } } void Widget::display(void *opaque, void *picture) { (void)opaque; } void *Widget::vlc_lock(void *opaque, void **planes) { struct Context *ctx = (struct Context *)opaque; ctx->mutex.lock(); // 告诉 VLC 将解码的数据放到缓冲区中 *planes = ctx->pixels; return nullptr; } //获取 argb 帧 void Widget::vlc_unlock(void *opaque, void *picture, void *const *planes) { struct Context *ctx = (struct Context *)opaque; unsigned char *data = static_cast<unsigned char *>(*planes); quint32 w=pThis->video_width; quint32 h=pThis->video_height; if(w>0 && h>0 && data!=nullptr) { QImage image(data, int(w),int(h), QImage::Format_RGB32); if(!image.isNull()) { pThis->ui->widget_videoDisplay->slotGetOneFrame(image.copy()); } } ctx->mutex.unlock(); } /* 工程: 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()) { //获取路径,如果没有默认路径,就使用当前C盘根目录 if(open_dir_path.isEmpty()) { open_dir_path="C:/"; } filename=QFileDialog::getOpenFileName(this,"选择播放的视频",open_dir_path,tr("*.mkv *.flv *.mp4 *.wmv *.*")); if(filename.isEmpty())return false; open_dir_path=QFileInfo(filename).path(); qDebug()<<"路径:"<<open_dir_path; } media_filename=filename; } //判断文件是否存在 if(QFileInfo::exists(media_filename)==false) { if(media_filename.contains("rtsp:", Qt::CaseInsensitive)==false&& media_filename.contains("rtmp:", Qt::CaseInsensitive)==false) { return false; } else { qDebug()<<"播放的流媒体:"<<media_filename; } } else { /* 将 / 转为windows下的右斜杆 */ std::replace(media_filename.begin(), media_filename.end(), QChar('/'), QChar('\\')); qDebug()<<"播放的本地媒体:"<<media_filename; } MediaInfo.state=MEDIA_LOAD; MediaInfo.mediaName=media_filename; //设置当前播放的视频名称 QFileInfo info(media_filename); ui->label_FileName->setText(QString("%1").arg(info.fileName())); //宽高清0 video_width=0; video_height=0; /*为特定文件路径创建媒体*/ if(vlc_media)libvlc_media_release(vlc_media); vlc_media=libvlc_media_new_path(vlc_base,media_filename.toUtf8()); if(vlc_media==nullptr) { qDebug()<<"libvlc_media_new_path 执行错误."; return false; } /*根据给定的媒体对象创建一个播放器对象*/ if(vlc_mediaPlayer)libvlc_media_player_release(vlc_mediaPlayer); vlc_mediaPlayer=libvlc_media_player_new_from_media(vlc_media); //设置回调,用于提取帧或者在界面上显示。 libvlc_video_set_callbacks(vlc_mediaPlayer, vlc_lock, vlc_unlock, display, &ctx); /*获取媒体播放器事件管理器*/ libvlc_event_manager_t *em = libvlc_media_player_event_manager(vlc_mediaPlayer); libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this); //进度改变 libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this); //播放完毕 libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this); //停止 libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this); //开始播放 libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this); //暂停 libvlc_event_attach(em, libvlc_MediaParsedChanged, vlcEvents, this); //获取到元数据 /*播放媒体文件*/ if(vlc_mediaPlayer)libvlc_media_player_play(vlc_mediaPlayer); //等待VLC解析文件.否则下面的时间获取不成功 QThread::msleep(100); //获取媒体文件总长度 ms libvlc_time_t length = libvlc_media_player_get_length(vlc_mediaPlayer); qDebug()<<"媒体文件总长度:"<<length; ui->label_Total_Time->setText(QTime(0, 0, 0,0).addMSecs(int(length)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); //每次加载新文件设置播放进度条为0 ui->horizontalSlider_PlayPosition->setValue(0); //设置进度条的范围 ui->horizontalSlider_PlayPosition->setMaximum(int(length)); ui->horizontalSlider_PlayPosition->setMinimum(0); //获取当前媒体播放的位置 libvlc_time_t current_movie_time=libvlc_media_player_get_time(vlc_mediaPlayer); qDebug()<<"获取当前媒体播放的位置:"<<current_movie_time; libvlc_video_get_size(vlc_mediaPlayer,0,&video_width,&video_height); qDebug()<<"视频尺寸:"<<"width:"<<video_width<<"height:"<<video_height; memset(ctx.pixels, 0, MAX_WIDTH * MAX_HEIGHT * 4); //设置图像颜色格式 libvlc_video_set_format(vlc_mediaPlayer, "RV32", video_width, video_height, video_width * 4); libvlc_media_add_option(vlc_media, ":rtsp=tcp"); //连接方式 libvlc_media_add_option(vlc_media, ":network-caching=200"); //缓存 //设置按钮状态为播放状态 ui->MediaPauseBtn->setChecked(false); //隐藏标签控件 ui->label->setVisible(false); //获取媒体的元数据信息--异步方式 libvlc_media_parse_with_options(vlc_media,libvlc_media_parse_local,1000); qDebug()<<"媒体元数据获取---媒体标题:"<<libvlc_media_get_meta(vlc_media,libvlc_meta_Title); //获取媒体描述符的基本流描述 libvlc_media_track_t **tracks; //正常的视频获取的流的数量是2. 一个视频流 一个音频流 if(libvlc_media_tracks_get(vlc_media,&tracks)) { qDebug()<<"视频宽:"<<tracks[0]->video->i_width; qDebug()<<"视频高:"<<tracks[0]->video->i_height; //手机拍的视频是翻转(宽高反过来的),电脑上播放需要翻转回去 qDebug()<<"旋转度数:"<<tracks[0]->video->i_orientation; //逆时针旋转90° if(tracks[0]->video->i_orientation==libvlc_video_orient_right_top) { // video_width=tracks[0]->video->i_height; // video_height=tracks[0]->video->i_width; //ui->widget_videoDisplay->Set_Rotate(90); //libvlc_media_add_option(vlc_media, ":transform-type=90"); } // libvlc_video_set_scale(vlc_mediaPlayer,1); } /* libvlc_media_add_option(vlc_media, ":rtsp=tcp"); //连接方式 libvlc_media_add_option(vlc_media, ":codec=ffmpeg"); libvlc_media_add_option(vlc_media, ":avcodec-threads=1"); libvlc_media_add_option(vlc_media, ":avcodec-hw=any"); //硬件解码 libvlc_media_add_option(vlc_media, ":network-caching=200"); //缓存 libvlc_media_add_option(vlc_media, ":prefetch-buffer-size=1024"); //预装取缓冲大小512K libvlc_media_add_option(vlc_media, ":prefetch-read-size=65535"); //预装取读取大小64K */ return true; } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 加载视频文件 */ void Widget::on_toolButton_load_clicked() { qDebug()<<"加载视频文件状态:"<<load_video_file(0,""); } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 暂停播放 */ void Widget::on_MediaPauseBtn_clicked() { //暂停与继续 if(vlc_mediaPlayer)libvlc_media_player_pause(vlc_mediaPlayer); } /* 工程: 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(); seek(value-1000*5); } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 快进播放 */ void Widget::on_MediaPlayBtn_clicked() { //得到播放进度的当前位置 int value=ui->horizontalSlider_PlayPosition->value(); seek(value+1000*5); } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 向左一帧 */ void Widget::on_ReverseFrameBtn_clicked() { //得到播放进度的当前位置 int value=ui->horizontalSlider_PlayPosition->value(); value+=100; if(value<=ui->horizontalSlider_PlayPosition->maximum()) { ui->horizontalSlider_PlayPosition->setValue(value); ui->label_current_Time->setText(QTime(0, 0, 0,0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); //跳转播放器 float f_value=(float)value/(float)ui->horizontalSlider_PlayPosition->maximum(); qDebug()<<"f_value:"<<f_value; libvlc_media_player_set_position(vlc_mediaPlayer,f_value); } } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 向右一帧 */ void Widget::on_ForwardFrameBtn_clicked() { //得到播放进度的当前位置 int value=ui->horizontalSlider_PlayPosition->value(); value-=100; if(value>=0) { ui->horizontalSlider_PlayPosition->setValue(value); ui->label_current_Time->setText(QTime(0, 0, 0,0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); //跳转播放器 float f_value=(float)value/(float)ui->horizontalSlider_PlayPosition->maximum(); qDebug()<<"f_value:"<<f_value; libvlc_media_player_set_position(vlc_mediaPlayer,f_value); } } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 音量设置 */ void Widget::on_VolumeBtn_clicked() { bool checked=ui->VolumeBtn->isChecked(); if(checked) { //静音 if(vlc_mediaPlayer)libvlc_audio_set_volume(vlc_mediaPlayer,0); } else { //设置正常音量 int volume_val=ui->horizontalSlider_AudioValue->value(); //音量设置 if(vlc_mediaPlayer)libvlc_audio_set_volume(vlc_mediaPlayer,volume_val); } } /* 工程: ECRS_VideoPlayer 日期: 2021-02-23 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 音量设置 */ void Widget::on_horizontalSlider_AudioValue_valueChanged(int value) { //音量设置 if(vlc_mediaPlayer)libvlc_audio_set_volume(vlc_mediaPlayer,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()); /*设置播放速率*/ if(vlc_mediaPlayer)libvlc_media_player_set_rate(vlc_mediaPlayer,float(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, 94); 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) { } //APP功能介绍 else if(item==MENU_APP_INFO) { } } /* 工程: 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) { } //点击的是音量滑块 else if(obj==ui->horizontalSlider_AudioValue) { if (event->type()==QEvent::MouseButtonPress) //判断类型 { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if (mouseEvent->button() == Qt::LeftButton) //判断左键 { int value = QStyle::sliderValueFromPosition(ui->horizontalSlider_AudioValue->minimum(), ui->horizontalSlider_AudioValue->maximum(), mouseEvent->pos().x(), ui->horizontalSlider_AudioValue->width()); ui->horizontalSlider_AudioValue->setValue(value); } } } return QObject::eventFilter(obj,event); } /* 工程: ASS_SubtitleVideoPlayer 日期: 2021-06-15 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 按键事件 */ void Widget::keyPressEvent(QKeyEvent *event) { switch(event->key()) { case Qt::Key_Space: //视频加载成功才能进行下面的操作 if(MediaInfo.state==MEDIA_LOAD) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); if (keyEvent->key() == Qt::Key_Space) { if(vlc_mediaPlayer) { //暂停与继续切换 libvlc_media_player_pause(vlc_mediaPlayer); //4表示暂停 3表示继续 5表示停止 int state=libvlc_media_player_get_state(vlc_mediaPlayer); if(state==4 || state==5) { //设置按钮状态 ui->MediaPauseBtn->setChecked(false); } else if(state==3) { //设置按钮状态 ui->MediaPauseBtn->setChecked(true); } } } } break; } } /* 工程: 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; } void Widget::seek(int value) { if(vlc_mediaPlayer) { float pos=value*1.0/ui->horizontalSlider_PlayPosition->maximum(); libvlc_media_player_set_position(vlc_mediaPlayer,pos); qDebug()<<"跳转的位置:"<<pos; ui->horizontalSlider_PlayPosition->setValue(value); ui->label_current_Time->setText(QTime(0, 0, 0,0).addMSecs(int(value)).toString(QString::fromLatin1("HH:mm:ss:zzz"))); //跳转播放器 float f_value=(float)value/(float)ui->horizontalSlider_PlayPosition->maximum(); qDebug()<<"f_value:"<<f_value; libvlc_media_player_set_position(vlc_mediaPlayer,f_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界面获取用户的个性化配置参数 /*保存数据到文件,方便下次加载*/ QString text; text=QCoreApplication::applicationDirPath()+"/"+ConfigFile; QFile filesrc(text); filesrc.open(QIODevice::WriteOnly); QDataStream out(&filesrc); out << open_dir_path; //序列化 filesrc.flush(); filesrc.close(); } /* 工程: ECRS_VideoPlayer 日期: 2021-02-24 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 读取配置 */ void Widget::ReadConfig() { //读取配置文件 QString text; text=QCoreApplication::applicationDirPath()+"/"+ConfigFile; //判断文件是否存在 if(QFile::exists(text)) { QFile filenew(text); filenew.open(QIODevice::ReadOnly); QDataStream in(&filenew); // 从文件读取序列化数据 in >>open_dir_path; //提取写入的数据 filenew.close(); } } /* 工程: ASS_SubtitleVideoPlayer 日期: 2021-06-16 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 窗口关闭事件 */ void Widget::closeEvent(QCloseEvent *event) //窗口关闭事件 { int ret = QMessageBox::question(this, tr("重要提示"), tr("是否退出播放器?"), QMessageBox::Yes | QMessageBox::No); if(ret==QMessageBox::Yes) { SaveConfig(); event->accept(); //接受事件 } else { event->ignore(); //清除事件 } } /* 工程: VLC_Core_VideoPlayer 日期: 2021-07-26 作者: DS小龙哥 环境: win10 QT5.12.6 MinGW32 功能: 打开链接 */ void Widget::on_toolButton_link_clicked() { bool ok; QString text = QInputDialog::getText(this, tr("流媒体播放"),tr("请输入流媒体地址:"), QLineEdit::Normal, tr("rtmp://58.200.131.2:1935/livetv/cctv14"),&ok); if (ok && !text.isEmpty()) { //load_video_file(0,text); //打开RTMP流媒体:libvlc_media_new_location (inst, "rtmp://10.0.0.4:554/cam"); } }