介绍

  • 简单的多屏播放器
  • 最多同时播放16个视频
  • 支持本地文件和rtsp、rtmp等流媒体播放
  • VS2015工程,依赖Qt+VLC
  • 练手作品

截图


下载

程序:download.csdn.net/detail/u014755412/9908787

源码:github.com/FutaAlice/QtPlayer


代码分析

IMediaPlayer是为规定接口的基类
提供了播放和控制的几个常用函数
其中打开媒体部分拆分为了OpenURL和OpenFile,并在cpp中实现
若为Windows环境,则对QFileDialog获取的路径进行替换

/*******************************************************************
IMediaPlayer.h(接口类)
构造时传入QWidget*
调用OpenFile或OpenURL或Open打开文件并渲染窗体
*******************************************************************/ #ifndef IMEDIAPLAYER_H
#define IMEDIAPLAYER_H class QWidget;
class IMediaPlayer
{
public:
IMediaPlayer(QWidget* pWidget);
virtual ~IMediaPlayer(); virtual bool OpenFile();
virtual bool OpenURL(const char* url); virtual bool Open(const char* url) = 0;
virtual bool Play() = 0;
virtual void Pause() = 0;
virtual void Stop() = 0;
virtual void ChangeVolume(int vol) = 0; protected:
QWidget* m_pWidget;
}; #endif // IMEDIAPLAYER_H
/*******************************************************************
IMediaPlayer.cpp(接口类)
*******************************************************************/
#include "IMediaPlayer.h"
#include <QtWidgets/QWidget>
#include <QtWidgets/qfiledialog.h> // Windows环境下进行字符替换
static void StrReplace(QString& str)
{
#if defined(Q_OS_MAC) // Mac
#elif defined(Q_OS_UNIX) // Linux
#elif defined(Q_OS_WIN) // Windows
str = str.replace(QRegExp("/"), "\\");
#endif
} IMediaPlayer::IMediaPlayer(QWidget* pWidget)
: m_pWidget(pWidget)
{
} IMediaPlayer::~IMediaPlayer()
{
} bool IMediaPlayer::OpenFile()
{
QString fileOpen = QFileDialog::getOpenFileName(NULL, "Load a file", "~");
if (!fileOpen.isEmpty())
{
StrReplace(fileOpen);
return Open(fileOpen.toUtf8().constData());
}
else
return false;
} bool IMediaPlayer::OpenURL(const char * url)
{
return Open(url);
}

之后新建一个派生自IMediaPlayer的类:VlcMediaPlayer,
并使用libvlc实现其基类中的纯虚函数实现视频的播放

/*******************************************************************
VlcMediaPlayer.h
使用libvlc实现的IMediaPlayer
构造时传入QWidget*
调用OpenFile或OpenURL或Open打开文件并渲染窗体
例如:
QWidget* pWidget = new QOpenGLWidget();
pWidget->show();
auto player = new VlcMediaPlayer(pWidget);
player->Open("test.hevc");
*******************************************************************/ #ifndef VLCMEDIAPLAYER_H
#define VLCMEDIAPLAYER_H #include "IMediaPlayer.h" struct libvlc_media_player_t;
struct libvlc_instance_t;
class VlcMediaPlayer :
public IMediaPlayer
{
public:
VlcMediaPlayer(QWidget* pWidget);
~VlcMediaPlayer(); // 禁用拷贝构造和赋值
VlcMediaPlayer(const VlcMediaPlayer&) = delete;
VlcMediaPlayer& operator=(VlcMediaPlayer&) = delete; // Control
virtual bool Open(const char* url);
virtual bool Play();
virtual void Pause();
virtual void Stop();
virtual void ChangeVolume(int vol) ; private:
// 播放器对象
libvlc_media_player_t *m_pVlcPlayer; private:
// libvlc实例,所有窗体的渲染共用一个
static libvlc_instance_t *s_pVlcInstance;
static unsigned int s_ref;
}; #endif // VLCMEDIAPLAYER_H
/*******************************************************************
VlcMediaPlayer.cpp
libvlc播放视频的实现
*******************************************************************/
#include "VlcMediaPlayer.h"
#include <assert.h>
#include <QtWidgets/QWidget> # ifdef __cplusplus
extern "C" {
# endif
#include <vlc/vlc.h>
# ifdef __cplusplus
}
# endif #if defined(Q_OS_MAC) // Mac
// TODO
#elif defined(Q_OS_UNIX) // Linux
#pragma comment(lib, "libvlc.a")
#elif defined(Q_OS_WIN) // Windows
#pragma comment(lib, "libvlc.lib")
#endif unsigned int VlcMediaPlayer::s_ref = 0;
libvlc_instance_t *VlcMediaPlayer::s_pVlcInstance = NULL; VlcMediaPlayer::VlcMediaPlayer(QWidget* pWidget)
: IMediaPlayer(pWidget)
, m_pVlcPlayer(NULL)
{
/* Initialize libVLC */
if (0 == s_ref++)
{
s_pVlcInstance = libvlc_new(0, NULL);
if (NULL == s_pVlcInstance)
{
assert(false);
}
}
} VlcMediaPlayer::~VlcMediaPlayer()
{
if (0 == --s_ref)
{
libvlc_release(s_pVlcInstance);
}
} bool VlcMediaPlayer::Open(const char *url)
{
/* Stop if something is playing */
Stop(); auto funcOpen = libvlc_media_new_path;
if (QString(url).startsWith("rtsp://") ||
QString(url).startsWith("rtmp://") ||
QString(url).startsWith("rtp://") ||
QString(url).startsWith("tcp://") ||
QString(url).startsWith("udp://") ||
QString(url).startsWith("ftp://") ||
QString(url).startsWith("http://") ||
QString(url).startsWith("https://"))
{
funcOpen = libvlc_media_new_location;
} /* Create a new Media */
libvlc_media_t *vlcMedia = funcOpen(s_pVlcInstance, url);
/* Fail to open url*/
if (!vlcMedia)
{
return false;
} if (QString(url).endsWith(".hevc"))
libvlc_media_add_option(vlcMedia, ":demux=hevc");
else if (QString(url).endsWith("rtsp"))
libvlc_media_add_option(vlcMedia, ":rtsp-tcp"); /* Create a new libvlc player */
m_pVlcPlayer = libvlc_media_player_new_from_media(vlcMedia); /* Release the media */
libvlc_media_release(vlcMedia); return Play();
} bool VlcMediaPlayer::Play()
{
/* Integrate the video in the interface */
#if defined(Q_OS_MAC)
libvlc_media_player_set_nsobject(m_pVlcPlayer, (void*)m_pWidget->winId());
#elif defined(Q_OS_UNIX)
libvlc_media_player_set_xwindow(m_pVlcPlayer, m_pWidget->winId());
#elif defined(Q_OS_WIN)
libvlc_media_player_set_hwnd(m_pVlcPlayer, (void*)m_pWidget->winId());
#endif /* And start playback */
int vlc_ret = libvlc_media_player_play(m_pVlcPlayer);
if (0 == vlc_ret)
return true;
else
return false;
} void VlcMediaPlayer::Pause()
{
if (m_pVlcPlayer && libvlc_media_player_is_playing(m_pVlcPlayer))
{
libvlc_media_player_pause(m_pVlcPlayer);
}
} void VlcMediaPlayer::Stop()
{
if (m_pVlcPlayer)
{
/* stop the media player */
libvlc_media_player_stop(m_pVlcPlayer); /* release the media player */
libvlc_media_player_release(m_pVlcPlayer); /* Reset application values */
m_pVlcPlayer = NULL;
}
} void VlcMediaPlayer::ChangeVolume(int vol)
{
if (m_pVlcPlayer)
{
libvlc_audio_set_volume(m_pVlcPlayer, vol);
}
}

界面部分,
响应界面按钮点击的消息和调整窗体大小的消息,
并且调用VlcMediaPlayer添加播放视频的小窗口

/*******************************************************************
QtPlayer.h
*******************************************************************/
#pragma once #include <QtWidgets/QWidget>
#include "ui_QtPlayer.h" struct libvlc_media_player_t;
class QtPlayer : public QWidget
{
Q_OBJECT
public:
QtPlayer(QWidget *parent = Q_NULLPTR);
void resizeEvent(QResizeEvent* e); private slots:
void openFile();
void openURL(); private:
Ui::QtPlayerClass ui;
QWidget* m_pSubWidgets[16];
};
/*******************************************************************
QtPlayer.cpp
*******************************************************************/
#include "QtPlayer.h"
#include "VlcMediaPlayer.h" QtPlayer::QtPlayer(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this); memset(m_pSubWidgets, NULL, sizeof(m_pSubWidgets));
} void QtPlayer::openFile()
{
int w = width() / 4, h = (height() - 24) / 4;
for (int i = 0; i < 16; ++i)
{
if (m_pSubWidgets[i] == NULL)
{
m_pSubWidgets[i] = new QWidget(this);
auto player = new VlcMediaPlayer(m_pSubWidgets[i]); // 打开成功
if (player->OpenFile())
{
resizeEvent(NULL);
m_pSubWidgets[i]->show();
}
else
{
delete player;
delete m_pSubWidgets[i];
m_pSubWidgets[i] = NULL;
}
break;
}
}
} void QtPlayer::resizeEvent(QResizeEvent *e)
{
int w = width() / 4, h = (height() - 24) / 4;
for (int i = 0; i < 16; ++i)
{
if (NULL == m_pSubWidgets[i])
continue;
m_pSubWidgets[i]->resize(QSize(w, h));
m_pSubWidgets[i]->move(QPoint((i % 4) * w, (i / 4) * h));
}
QPoint pos = ui.btnOpenFile->pos();
pos.setY(height() - 24);
ui.btnOpenFile->move(pos); pos = ui.btnOpenURL->pos();
pos.setY(height() - 24);
ui.btnOpenURL->move(pos); pos = ui.lineEdit->pos();
pos.setY(height() - 24);
ui.lineEdit->move(pos);
} void QtPlayer::openURL()
{
int w = width() / 4, h = height() / 4;
for (int i = 0; i < 16; ++i)
{
if (m_pSubWidgets[i] == NULL)
{
m_pSubWidgets[i] = new QWidget(this);
auto player = new VlcMediaPlayer(m_pSubWidgets[i]);
// 打开成功
if (player->OpenURL(ui.lineEdit->text().toUtf8().constData()))
{
resizeEvent(NULL);
m_pSubWidgets[i]->show();
}
else
{
delete player;
delete m_pSubWidgets[i];
m_pSubWidgets[i] = NULL;
}
break;
}
}
}

简单的多屏播放器示例(vlc+qt)的更多相关文章

  1. 一款非常简单的android音乐播放器源码分享给大家

    一款非常简单的android音乐播放器源码分享给大家,该应用虽然很小,大家常用的播放器功能基本实现了,可能有点还不够完善,大家也可以自己完善一下,源码在源码天堂那里已经有了,大家可以到那里下载学习吧. ...

  2. 【源码分享】mui实现简单的手机音乐播放器

    mui实现简单的手机音乐播放器 最近先来无事,我用mui写了一个可以跨页面控制的音乐播放器.主要功能有上一曲,下一曲,播放,暂停,感兴趣的可以继续看下去. 说的总是不实在,直接上源码,有兴趣的可以读下 ...

  3. Go笔记之二:一个完整的播放器示例

    Go笔记之二:一个完整的播放器示例 该示例从命令行运行一个播放器示例,可进行添加.删除.浏览和模拟播放,其内容是对 Go 语言接口使用的良好展示 源码及可执行文件 参考书籍<Go语言编程> ...

  4. h5-自定义视屏播放器

    1.html代码 <h3 class="playerTitle">视屏播放器</h3> <div class="player"&g ...

  5. Java利用VLC开发简易视屏播放器

    1.环境配置 (1)下载VLC  VlC官网http://www.videolan.org/    各个版本的下载地址http://download.videolan.org/pub/videolan ...

  6. Android中使用SurfaceView+MediaPlayer+自定义的MediaController实现自定义的视屏播放器

    效果图如下: (PS本来是要给大家穿gif动态图的,无奈太大了,没法上传) 功能实现:暂停,播放,快进,快退,全屏,退出全屏,等基本功能 实现的思路: 在主布局中放置一个SurfaceView,在Su ...

  7. 超简单解决linux音乐播放器乱码问题

    问题 中文MP3的tag信息有些因为采用了GBK编码, 导致linux下的大多播放器(Rhythmbox, Audacious)无法正确识别而显示乱码. 如下图Audacious的乱码情况. 网上的常 ...

  8. android快捷简单的实现音乐播放器

    自己做了一个相对完整的音乐播放器,现在把播放模块提取出来,分享给大家.音乐播放器基本功能都实现了的,可能有些BUG,希望谅解. 播放器功能如下: 1.暂停,播放 2.拖动条实现,快进,快退 3.歌词同 ...

  9. 一个简单的ipfs音乐播放器的实现

    IPFS音乐播放器 IPFS相关 IPFS第一次亲密接触 什么是IPFS IPFS对比HTTP/FTP等协议的优势 IPFS应用场景 -移动数据 交易 路由 网络 定义数据 命名 使用数据 具体场景; ...

随机推荐

  1. JavaScript使用纯函数避免bug

    纯函数 一.纯函数 定义:纯函数是指不依赖并且不修改其作用域之外的函数.通过以下几个示例来认识纯函数: var a = 10; //纯函数 function foo(num){ return num ...

  2. parseInt()、Number()区别

    parseInt从头解析string为整数,在遇到不能解析的字符时就返回已经解析的整数部分,如果第一个字符就不能解析,就直接返回NaN. Number如果无法转换为数字,就返回NaN.像“123a”, ...

  3. Databus&canal对比

    Databus和canal都能够提供实时从数据库获取变更,并提供给下游的实时消费流的功能. 本文针对两个系统实现和应用上的不同点,做了一个简单的对比: 对比项 Databus canal 结论 支持的 ...

  4. Java学习笔记【八、数据结构】

    参考资料: http://www.cnblogs.com/janneystory/p/5758958.html array arraylist list linklist的区别 http://www. ...

  5. 第四篇.python的基础

    目录 第四篇.python基础01 1. 变量 2. 常量 3. python变量内存管理 4. 变量的三个特征 5. 花式赋值 6. 注释 7. 数据类型基础 8. 数字类型 9. 字符串类型 10 ...

  6. java_day11_IO流

    第十一章:IO流 1.流的概念 流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行.设备可以是文件,网络,内存等 流具有方向性 ...

  7. 寒武纪C++日常实习生面经(其他人面试题)

    1.C++继承方式? 答:public,protected,private三种继承方式和虚继承一共四种. 派生类可以继承定义在基类中的成员,但是派生类的成员函数不一定有权访问从基类继承而来的成员. 派 ...

  8. ubuntu学习笔记-sudo/gedit

    1.sudo命令 sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用户的登录 和管理时间 ...

  9. Liux chmod 给文件夹赋权限

    777 最高权限 给文件夹及子文件夹赋权限 chmod -R 777 * 给单独文件赋权限 chmod -R 777 ./startup.sh

  10. [Ahoi2009]self 同类分布

    1799: [Ahoi2009]self 同类分布 Time Limit: 50 Sec  Memory Limit: 64 MBSubmit: 2357  Solved: 1079[Submit][ ...