简单的多屏播放器示例(vlc+qt)

FutaAlice FutaAlice     2022-10-16     127

关键词:

简单的多屏播放器示例(vlc+qt)

介绍

  • 简单的多屏播放器
  • 最多同时播放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;
        }
    }
}






最新libvlc4.0+qt设计视频播放器

...件的好处他都有,而且是为数不多开源并长期更新维护的播放器,兼容性等各个方面都很好。VLC提供了libvlc库,可以很方便进行二次开发。稳定版本,3.0版本官网:VLC:Officialsite-FreemultimediasolutionsforallOS!-VideoLAN目前VLC已经推出了... 查看详情

最新libvlc4.0+qt设计视频播放器

...件的好处他都有,而且是为数不多开源并长期更新维护的播放器,兼容性等各个方面都很好。VLC提供了libvlc库,可以很方便进行二次开发。稳定版本,3.0版本官网:VLC:Officialsite-FreemultimediasolutionsforallOS!-VideoLAN目前VLC已经推出了... 查看详情

最新libvlc4.0+qt设计视频播放器

...件的好处他都有,而且是为数不多开源并长期更新维护的播放器,兼容性等各个方面都很好。VLC提供了libvlc库,可以很方便进行二次开发。稳定版本,3.0版本官网:VLC:Officialsite-FreemultimediasolutionsforallOS!-VideoLAN目前VLC已经推出了... 查看详情

qt音视频开发17-vlc内核回调拿图片进行绘制(代码片段)

一、前言在众多播放器中,支持的种类格式众多,并支持DVD影音光盘,VCD影音光盘及各类流式协议,提供了sdk进行开发,这点是至关重要的,尽管很多优秀的播放器很牛逼,由于没有提供sdk第三方开发&... 查看详情

基于vlc-qt的视频播放器(支持添加视频列表单曲循环等)(代码片段)

    基于libvlc和Qt实现了一个视频播放器,可实现列表循环播放,单曲播放等,效果好于Qt自带的视频播放库。网上已有诸多基于vlc库的视频播放器,但设计列表播放的资源较少,基于vlc实现列表播放主要利... 查看详情

在 VLC 播放器中播放 RTSP 流

】在VLC播放器中播放RTSP流【英文标题】:PlayingRTSPstreaminVLCplayer【发布时间】:2011-08-1808:29:37【问题描述】:我正在尝试用java制作一个简单的rtsp流服务器。服务器能够将视频正确地流式传输到自定义写入的播放器。我无法在vlc... 查看详情

系列分享|《最全面最细致的vlc教程》

...程,你将可以快速打造一个属于自己的跨平台多媒体播放器。毫不夸张地说,这是市面上最全面、最细致的libVLC教程,有理论、有基础、有实战。赶紧行动起来,和亮哥一起进阶音视频/多媒体开发!专栏目录... 查看详情

qt音视频开发19-vlc内核各种事件通知(代码片段)

...,还希望通过事件机制拿到消息通知,比如当前播放进度、音量值变化、静音变化、文件长度、播放结束等,有了这些才是完整的播放功能,在vlc中要拿到各种事件需要先通过libvlc_event_attach订阅事件,不需要... 查看详情

在 VLC 上播放 MPEG-DASH

...示例媒体还是我自己编码的视频。我已经在基于浏览器的播放器中成功测试了这些视频清单,但我需要流式传输视频并从没有显示器的计算机收集带宽数据。当我尝试从命令行流式传输清单时,看 查看详情

qt编写安防视频监控系统2-视频播放(代码片段)

一、前言视频播放功能是核心功能之一,为了统一管理接口,统一封装成一个控件,对外提供seturlopenclose方法即可,不用去管内部的具体处理,这样就可以提供多种接口来实现统一的管理,比如vlc内核+ffmpeg内核+海康sdk内核等,... 查看详情

使用 Qt 播放实时视频流

...来自IP摄像机的实时视频流。另一种方法是在Qt中嵌入VLC播放器,并提供该项目的链接here。问题是我不知道如何在Qt中包含播放器。那么我该如何进行呢?#include<QApplication>#incl 查看详情

在 Qt 中移动图像(作为动画)的简单示例?

】在Qt中移动图像(作为动画)的简单示例?【英文标题】:Simpleexampleofmovinganimage(asananimation)inQt?【发布时间】:2021-11-0101:24:27【问题描述】:我想在Qt中加载一个图像,并在动画中沿x轴移动它。就是这样。我四处搜索,但大多... 查看详情

qt学习笔记——实现简单的视频播放器(代码片段)

一、配置文件更改用到多媒体的话,需要修改配置文件的第一行,后面加一句sqlmultimediamultimediawidgets修改后的配置文件前3行如下QT+=coreguisqlmultimediamultimediawidgets//下面都不用改greaterThan(QT_MAJOR_VERSION,4):QT+=widgetsC 查看详情

百行代码实现vlc简易视频播放器vlc环境配置过程+可执行源码注释完整(代码片段)

...系统+vs2017+win64】🍎VLC库的基本使用🎂视频播放器实现⭐自定义函数Unicode2Utf8讲解🏠总结❓什么是VLCVLC是VideoLanClient的缩写,原先是几个法国的大学生做的项目,后来他们把VLC作为了一个开源的项目࿰... 查看详情

qt实现一个简单的播放器

ui界面设计如下:2、代码结构3、dialog.cpp#include"dialog.h"#include"ui_dialog.h"#include<QStringList>#include<QDebug>Dialog::Dialog(QWidget*parent):QDialog(parent),ui(newUi::Dialog){ui->setupUi(this) 查看详情

QT (C++) 中的简单声音 (.wav) 播放应用程序

】QT(C++)中的简单声音(.wav)播放应用程序【英文标题】:Simplesound(.wav)playingapplicationinQT(C++)【发布时间】:2012-03-3118:52:11【问题描述】:我是Qt新手,正在尝试编写一个可以规划wav文件的简单qt类。经过一番阅读和环顾后,我编写... 查看详情

如何使用python创建一个自定义视频播放器(代码片段)

...问题,解决方式如下:这个例子使用VLC作为视频播放器,并且使用tkinter创建了一个简单的GUI界面,其中包括一个Canvas用于播放视频,几个按钮用于控制视频播放,以及一个滑动条用于控制音量。你可以根... 查看详情

qt5中的seekslider实现

...020:49:53【问题描述】:大家。我正在用qt5重写我的qt4音乐播放器。而且我无法制作正确的搜索滑块,就像在声子中一样。你有实现这部分UI的简单示例吗?更新:这是我的方法://mainwindow.cppconnect(ui->seekSlider,SIGNAL(sliderMoved(int 查看详情