VLC的音视频编解码是对ffmpeg的封装,用FFmpeg可以开发视频播放器,推拉流,同样用VLC也可以,某些时候可能比ffmpeg还要简单点。本篇博客介绍VLC Qt视频播放器开发的预备工作。
开发环境:VS2017, Qt5.12_x64, win10
首先需要获取VLC的SDK, 3.0版本的VLC安装后只有dll, 没有头文件,lib库,直接用源码编译还是有一定难度的。2.x版本的安装包会有sdk, 下载链接:http://download.videolan.org/pub/videolan/vlc/ 下载后,将include, lib,dll, plugins等文件放到一块儿,方便在vs中引用,如下图:
sdk也可以直接编译 vlc 2.x 的源码得到,可以看我的这篇博客:VS2013编译vlc源码
运行的时候,dll和plugins要放到exe所在的路径。
VS2017项目属性包含include, lib,项目依赖项添加 libvlc.lib,libvlccore.lib
播放器界面如下:
视频显示用的是QWidget, 界面用qss做了美化,
代码不太难,下面全部贴出来,有兴趣的可以参考。
界面qss
QMainWindow
{
background-color: rgb(53, 53, 53);
}
QPushButton
{
background-color:rgb(128, 138, 135);
color:white;
font:16px;
border-radius:6px;
}
QPushButton:hover
{
color:#0000ff;
background-color:rgb(210, 205, 205); /*改变背景色*/
border-style:inset;/*改变边框风格*/
padding-left:1px;
padding-top:1px;
}
QSlider::groove:horizontal {
border: 1px solid #4A708B;
background: #C0C0C0;
height: 5px;
border-radius: 1px;
padding-left:-1px;
padding-right:-1px;
}
QSlider::sub-page:horizontal {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #B1B1B1, stop:1 #c4c4c4);
background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,
stop: 0 #5DCCFF, stop: 1 #1874CD);
border: 1px solid #4A708B;
height: 10px;
border-radius: 2px;
}
QSlider::add-page:horizontal {
background: #575757;
border: 0px solid #777;
height: 10px;
border-radius: 2px;
}
QSlider::handle:horizontal
{
background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,
stop:0.6 #45ADED, stop:0.778409 rgba(255, 255, 255, 255));
width: 11px;
margin-top: -5px;
margin-bottom: -5px;
border-radius: 5px;
}
QSlider::handle:horizontal:hover
{
background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0.6 #2A8BDA,
stop:0.778409 rgba(255, 255, 255, 255));
width: 11px;
margin-top: -5px;
margin-bottom: -5px;
border-radius: 5px;
}
头文件
#pragma once
#include
#include "ui_MyVLCPlayer.h"
#include "vlc/vlc.h"
class MyVLCPlayer : public QMainWindow
{
Q_OBJECT
public:
MyVLCPlayer(QWidget *parent = Q_NULLPTR);
~MyVLCPlayer();
void stopPlay();
private slots:
void on_btnLoadVideo_clicked();
void on_btnStart_clicked();
void on_btnStop_clicked();
int changeVolume(int vol);
void changePosition(int pos);
void updateInterface();
void on_btnMute_clicked();
private:
Ui::MyVLCPlayerClass ui;
libvlc_instance_t *m_vlcInstance;
libvlc_media_player_t *m_vlcPlayer;
};
cpp文件
#pragma execution_character_set("utf-8")
#include "MyVLCPlayer.h"
#include
#include
#include
MyVLCPlayer::MyVLCPlayer(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
#ifdef _DEBUG
setWindowTitle("MyVLCPlayer_d");
#else
setWindowTitle("MyVLCPlayer");
#endif
m_vlcPlayer = NULL;
//创建vlc实例
m_vlcInstance = libvlc_new(0, NULL);
//判断vlc实例化是否ok
if (m_vlcInstance == NULL)
{
QMessageBox::critical(this, "Qt libVLC player", "Could not init libVLC");
exit(1);
}
//音量进度条
connect(ui.volumeSlider, SIGNAL(sliderMoved(int)), this, SLOT(changeVolume(int)));
ui.volumeSlider->setValue(50);
//时间进度条
ui.timeSlider->setMaximum(1000);
connect(ui.timeSlider, SIGNAL(sliderMoved(int)), this, SLOT(changePosition(int)));
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateInterface()));
timer->start(100);
}
MyVLCPlayer::~MyVLCPlayer()
{
if (m_vlcInstance)
{
libvlc_release(m_vlcInstance);
}
stopPlay();
}
void MyVLCPlayer::on_btnLoadVideo_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("请选择视频文件"),
tr("D:\\TestVideo"),
tr("视频文件 (*.flv *.rmvb *.avi *.mp4);; 所有文件 (*.*);; "));
fileName.replace(":/", ":\\");
setWindowTitle(fileName);
//如果视频正在播放,先停止播放
if (m_vlcPlayer && libvlc_media_player_is_playing(m_vlcPlayer))
{
stopPlay();
}
libvlc_media_t *vlcMedia = libvlc_media_new_path(m_vlcInstance, fileName.toStdString().c_str());
if (!vlcMedia)
{
return;
}
m_vlcPlayer = libvlc_media_player_new_from_media(vlcMedia);
libvlc_media_release(vlcMedia);
//vlcplayer和Qt控件关联
libvlc_media_player_set_hwnd(m_vlcPlayer, (void*)(ui.widget->winId()));
libvlc_media_player_play(m_vlcPlayer);
ui.btnStart->setText(tr("暂停"));
}
void MyVLCPlayer::on_btnStart_clicked()
{
if (!m_vlcPlayer)
return;
if (libvlc_media_player_is_playing(m_vlcPlayer))
{
libvlc_media_player_pause(m_vlcPlayer);
ui.btnStart->setText(tr("开始播放"));
}
else
{
libvlc_media_player_play(m_vlcPlayer);
ui.btnStart->setText(tr("暂停"));
}
}
void MyVLCPlayer::on_btnStop_clicked()
{
stopPlay();
}
void MyVLCPlayer::stopPlay()
{
if (m_vlcPlayer)
{
libvlc_media_player_stop(m_vlcPlayer);
libvlc_media_player_release(m_vlcPlayer);
m_vlcPlayer = NULL;
ui.timeSlider->setValue(0);
ui.btnStart->setText(tr("开始播放"));
}
}
int MyVLCPlayer::changeVolume(int vol)
{
if (m_vlcPlayer)
{
return libvlc_audio_set_volume(m_vlcPlayer, vol);
}
return 0;
}
void MyVLCPlayer::changePosition(int pos)
{
if (m_vlcPlayer)
{
libvlc_media_player_set_position(m_vlcPlayer, (float)pos / 1000.0);
}
}
void MyVLCPlayer::updateInterface()
{
if (!m_vlcPlayer)
{
return;
}
float pos = libvlc_media_player_get_position(m_vlcPlayer);
ui.timeSlider->setValue((int)(pos*1000.0));
if (libvlc_media_player_get_state(m_vlcPlayer) == libvlc_Ended)
{
this->stopPlay();
}
}
void MyVLCPlayer::on_btnMute_clicked()
{
if (m_vlcPlayer)
{
if (ui.volumeSlider->value() == 0)
{
this->changeVolume(80);
ui.volumeSlider->setValue(80);
}
else
{
this->changeVolume(0);
ui.volumeSlider->setValue(0);
}
}
}
音量处理这块儿有问题,声音曲线是log函数类型的,目前简单的处理了。视频其它功能基本ok.
以后有时间再写写vlc推拉流。