一、前言
在研究Qt+vlc的过程中,就想直接做个播放器用于独立的项目,尽管Qt自带了mediaplayer,但是那个依赖本地的解码器,除了MP4以外,非常鸡肋,还要求用户电脑先要安装解码器才行,这个肯定不大符合要求,于是决定采用vlc内核,vlc还支持硬件加速,不过部分电脑硬件不支持除外。用vlc的内核写播放器就是快,直接调用api就行,逻辑处理和ui展示基本上分分钟的事情,最好加点美化那就更加完美了,市面上很多播放器是vlc内核写的,或者ffmpeg写的。其实vlc也封装了ffmpeg的库,ffmpeg真的是一个非常强大的视频处理开源项目。
二、实现的功能
1:多线程实时播放rtsp视频流
2:支持windows+linux+mac
3:多线程显示图像,不卡主界面
4:自动重连网络摄像头
5:可设置边框大小即偏移量和边框颜色
6:可设置是否绘制OSD标签即标签文本或图片和标签位置
7:可设置两种OSD位置和风格
8:可设置是否保存到文件以及文件名
9:可播放本地视频文件,支持设置帧率
10:支持h265视频流+rtmp等常见视频流
11:可暂停播放和继续播放
12:支持回调模式和句柄两种模式
13:自动将当前播放位置和音量大小是否静音以信号发出去
14:提供接口设置播放位置和音量及设置静音
三、效果图
四、核心代码
void VlcThread::run()
{
while(!stopped) {
//开始播放
if (isPlayVideo) {
playVideo();
isPlayVideo = false;
}
//暂停播放
if (isPauseVideo) {
pauseVideo();
isPauseVideo = false;
}
//停止播放
if (isStopVideo) {
stopVideo();
isStopVideo = false;
}
//读取当前播放位置数据
if (isReadPosition) {
readPosition();
msleep(300);
}
msleep(1);
}
stopped = false;
}
QString VlcThread::getFileName() const
{
return fileName;
}
QString VlcThread::getSuffix() const
{
return suffix;
}
void VlcThread::readLength()
{
//定义长度变量用于存储文件时长
uint length = getLength();
//定义变量存储声音大小,默认值1
int volume = getVolumn();
//定义变量存储是否静音
bool mute = getMute();
//发送文件时长信号
emit fileLengthReceive(length);
//发送当前音量值信号
emit fileVolumeReceive(volume, mute);
isReadPosition = true;
}
void VlcThread::readPosition()
{
//获取播放进度位置
int position = getPosition();
//获取是否播放结束
bool isPlay = (getStatus() != VlcThread::VlcState_Ended);
if (position > 0) {
emit filePositionReceive(position, isPlay);
}
}
void VlcThread::playVideo()
{
//先停止上一次播放
stopVideo();
//延时一点时间让界面切换按钮状态,否则太快了人眼看不到效果
msleep(200);
bool isRtsp = ("rtsp") || ("rtmp") || ("http"));
QFileInfo info(fileName);
suffix = in();
//设置拓展名
if ("dshow://")) {
suffix = "dshow";
} else if ("rtsp")) {
suffix = "rtsp";
} else if ("rtmp")) {
suffix = "rtmp";
} else if ("http")) {
suffix = "http";
}
const char *tempArg = "";
if (suffix == "h264") {
tempArg = "–demux=h264";
} else if (suffix == "h265") {
tempArg = "–demux=h265";
}
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};
vlcInst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
if (vlcInst == NULL) {
return;
}
if (isRtsp || suffix == "dshow") {
vlcMedia = libvlc_media_new_location(vlcInst, ().constData());
} else {
//windows上需要替换文件路径
QString fileName = this->fileName;
#ifdef Q_OS_WIN
fileName = ("/", "\");
#endif
vlcMedia = libvlc_media_new_path(vlcInst, ().constData());
}
if (vlcMedia == NULL) {
return;
}
vlcPlayer = libvlc_media_player_new_from_media(vlcMedia);
if (vlcPlayer == NULL) {
return;
}
//设置播放句柄
#if defined(Q_OS_WIN)
libvlc_media_player_set_hwnd(vlcPlayer, (void *)lab->winId());
#elif defined(Q_OS_UNIX)
libvlc_media_player_set_xwindow(vlcPlayer, lab->winId());
#elif defined(Q_OS_MAC)
libvlc_media_player_set_nsobject(vlcPlayer, (void *)lab->winId());
#endif
//开启硬件加速
//setOption(":avcodec-hw=any");//any d3d11va dxva2
//设置缓存时间
setOption(QString(":network-caching=%1").arg(500));
//设置宽度高度,本地USB摄像头需要单独设置
if (suffix == "dshow") {
setOption(QString(":dshow-size=%1*%2").arg(640).arg(480));
}
libvlc_media_player_play(vlcPlayer);
//发送开始播放信号
emit playStart();
//延时获取,否则获取不到
if (!isRtsp) {
QTimer::singleShot(1000, this, SLOT(readLength()));
}
}
void VlcThread::pauseVideo()
{
if (vlcPlayer != 0) {
VlcState state = (VlcState)libvlc_media_player_get_state(vlcPlayer);
bool isPause = (state == VlcState_Paused);
if (libvlc_media_player_can_pause(vlcPlayer)) {
libvlc_media_player_pause(vlcPlayer);
}
if (isPause) {
isReadPosition = true;
emit playStart();
} else {
isReadPosition = false;
emit playPause();
}
} else {
playVideo();
}
}
void VlcThread::stopVideo()
{
if (vlcPlayer != 0) {
libvlc_media_player_stop(vlcPlayer);
vlcPlayer = 0;
isReadPosition = false;
emit playStop();
}
}
void VlcThread::setFileName(const QString &fileName)
{
this->fileName = fileName;
}
void VlcThread::setWidget(QLabel *lab)
{
if (this->lab != lab) {
this->lab = lab;
}
}
void VlcThread::setOption(const QString &args)
{
QByteArray ba = args.toUtf8();
const char *arg = ba.constData();
if (vlcMedia != 0) {
libvlc_media_add_option(vlcMedia, arg);
}
}
void VlcThread::setDelayTime(int delayTime)
{
setOption(QString(":network-caching=%1").arg(delayTime));
}
void VlcThread::save(const QString &videoFilePath)
{
setOption(QString(":sout=#duplicate{dst=display,dst=std{access=file,mux=ts,dst=%1}}")
.arg(videoFilePath));
}
1.文章《qt怎么播放本地视频》援引自互联网,为网友投稿收集整理,仅供学习和研究使用,内容仅代表作者本人观点,与本网站无关,侵删请点击页脚联系方式。
2.文章《qt怎么播放本地视频》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
相关推荐
- . 现代买票为什么带上携程保险
- . 潮阳怎么去广州南站
- . 湖南马拉河怎么样
- . 烧纸为什么到三岔路口
- . 百色为什么这么热
- . 神州租车怎么样
- . 芜湖方特哪个适合儿童
- . 护肤品保养液是什么类目
- . 早晚的护肤保养有哪些项目
- . 女孩护肤品怎么保养的最好