libvlc视频播放器: 播放rtsp/rtmp视频流
【摘要】 libvlc播发器引擎除了能播放本地视频外,也支持播放各种协议的流媒体视频,比如: 常见的RTMP、RTSP、HTTP、RTP格式等等。这篇文章就介绍如何使用libvlc打开协议格式,播放rtsp流。
一、功能介绍
libvlc播发器引擎除了能播放本地视频外,也支持播放各种协议的流媒体视频,比如常见的RTMP、RTSP格式视频。
在前面几篇文章里陆陆续续介绍了libvlc的常用的使用方法,这篇文章继续介绍libvlc的知识点: 播放指定协议的视频
。
libvlc提供了两种直接打开视频的方法:
/**
* Create a media with a certain given media resource location,
* for instance a valid URL.
*
* \note To refer to a local file with this function,
* the file://... URI syntax <b>must</b> be used (see IETF RFC3986).
* We recommend using libvlc_media_new_path() instead when dealing with
* local files.
*
* \see libvlc_media_release
*
* \param p_instance the instance
* \param psz_mrl the media location
* \return the newly created media or NULL on error
*/
LIBVLC_API libvlc_media_t *libvlc_media_new_location(
libvlc_instance_t *p_instance,
const char * psz_mrl );
/**
* Create a media for a certain file path.
*
* \see libvlc_media_release
*
* \param p_instance the instance
* \param path local filesystem path
* \return the newly created media or NULL on error
*/
LIBVLC_API libvlc_media_t *libvlc_media_new_path(
libvlc_instance_t *p_instance,
const char *path );
其中 libvlc_media_new_path
用于打开本地视频文件,可以直接传入本地磁盘路径。
例如:
libvlc_media_new_path(vlc_base,"D:\\work\\test.mp4");
注意: windows下使用libvlc_media_new_path
函数传入的路径要注意斜杠问题,必须保证传入的是双右斜杠,如果默认选择的路径是左斜杠,可以使用std::replace
函数转换一下。
filename="D:/work/test.mp4";
std::replace(filename.begin(), filename.end(), QChar('/'), QChar('\\'));
另一个libvlc_media_new_location
函数用于打开协议,这个函数更加强大,可以支持很多协议,本地视频也可以使用该函数打开,更加通用一点,而且使用该函数时,路径斜杠使用常规左斜杠就行(linux风格),不需要进行转换。
下面介绍几个常用的使用示例:
打开本地文件: libvlc_media_new_location (inst, "file:///D:/work/test.mp4");
打开RTSP流媒体:libvlc_media_new_location (inst, "rtsp://10.0.0.4:554/cam");
打开RTMP流媒体:libvlc_media_new_location (inst, "rtmp://10.0.0.4:554/cam");
播放当前桌面屏幕: libvlc_media_new_location (inst, "screen://");
注意: 使用 libvlc_media_new_location
函数打开路径之后不要使用std::replace
转换路径。
播放桌面屏幕的效果:
libvlc_media_new_location (inst, "screen://")
播放rtmp流效果
libvlc_media_new_location (inst, "rtmp://media3.scctv.net/live/scctv_800")
二、完整代码示例
#include "widget.h"
#include "ui_widget.h"
Widget* Widget::pThis = nullptr;
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
pThis=this;
ui->setupUi(this);
//创建并初始化libvlc实例
vlc_base=libvlc_new(0,nullptr);
this->setWindowTitle("libvlc设计的视频播放器");
}
Widget::~Widget()
{
delete ui;
}
//选择视频
void Widget::on_pushButton_open_clicked()
{
/*选择文件*/
filename=QFileDialog::getOpenFileName(this,"选择打开的文件","D:/",tr("*.*"));
filename="file:///"+filename;
/*停止媒体文件*/
if(vlc_mediaPlayer)libvlc_media_player_stop(vlc_mediaPlayer);
//QThread::msleep(5000);
/*为特定文件路径创建媒体*/
if(vlc_media)libvlc_media_release(vlc_media);
// vlc_media=libvlc_media_new_path(vlc_base,filename.toUtf8().data());
vlc_media=libvlc_media_new_location (vlc_base,filename.toUtf8().data());
if(vlc_media==nullptr)
{
qDebug()<<"libvlc_media_new_path 执行错误.";
return;
}
/*根据给定的媒体对象创建一个播放器对象*/
if(vlc_mediaPlayer)libvlc_media_player_release(vlc_mediaPlayer);
vlc_mediaPlayer=libvlc_media_player_new_from_media(vlc_media);
//忽略事件处理(这样libvlc就捕获不到鼠标和键盘事件了)
if (vlc_mediaPlayer)libvlc_video_set_mouse_input(vlc_mediaPlayer, false);
if (vlc_mediaPlayer)libvlc_video_set_key_input(vlc_mediaPlayer, false);
//创建事件管理器
eventManager = libvlc_media_player_event_manager(vlc_mediaPlayer);
//订阅事件
attachEvents(eventManager);
/*设置给予媒体播放器媒体输出的win32/win64窗口句柄*/
libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui->widget->winId());
/*播放媒体文件*/
if(vlc_mediaPlayer)libvlc_media_player_play(vlc_mediaPlayer);
//等待VLC解析文件.否则下面的时间获取不成功
QThread::msleep(500);
//获取媒体文件总长度 ms
libvlc_time_t length = libvlc_media_player_get_length(vlc_mediaPlayer);
qDebug()<<"媒体文件总长度:"<<length;
ui->label_t2->setText(QTime(0, 0, 0,0).addMSecs(int(length)).toString(QString::fromLatin1("HH:mm:ss:zzz")));
ui->horizontalSlider_pos->setMaximum(length);
ui->horizontalSlider_pos->setMinimum(0);
}
//暂停与继续
void Widget::on_pushButton_pause_clicked()
{
if(vlc_mediaPlayer)libvlc_media_player_pause(vlc_mediaPlayer);
}
//停止
void Widget::on_pushButton_stop_clicked()
{
if(vlc_mediaPlayer)libvlc_media_player_stop(vlc_mediaPlayer);
}
//订阅事件
void Widget::attachEvents(libvlc_event_manager_t *eventManager)
{
// 事件列表
QList<libvlc_event_e> events = {
libvlc_MediaPlayerPositionChanged,
libvlc_MediaPlayerTimeChanged,
libvlc_MediaPlayerLengthChanged,
libvlc_MediaPlayerPaused,
libvlc_MediaPlayerPlaying,
libvlc_MediaPlayerStopped,
libvlc_MediaPlayerEndReached,
libvlc_MediaParsedChanged
};
// 订阅事件
for (const libvlc_event_e &e : events)
{
libvlc_event_attach(eventManager, e, vlcEvents, nullptr);
}
}
void Widget::vlcEvents(const libvlc_event_t *event, void *param)
{
qint64 pos=0;
switch (event->type){
case libvlc_MediaPlayerTimeChanged:
//获取当前媒体播放的位置
pos=event->u.media_player_time_changed.new_time;
pThis->ui->label_t1->setText(QTime(0, 0, 0,0).addMSecs(int(pos)).toString(QString::fromLatin1("HH:mm:ss:zzz")));
pThis->ui->horizontalSlider_pos->setValue(pos);
qDebug()<<"pos:"<<pos;
break;
case libvlc_MediaPlayerPositionChanged:
//qDebug() << "Position: " << event->u.media_player_position_changed.new_position << endl;
break;
case libvlc_MediaPlayerLengthChanged:
qDebug() << "Length:"<< event->u.media_player_length_changed.new_length;
break;
case libvlc_MediaPlayerEndReached:
qDebug() << "VLC播放完毕.";
break;
case libvlc_MediaPlayerStopped:
qDebug() << "VLC停止播放";
break;
case libvlc_MediaPlayerPlaying:
qDebug() << "VLC开始播放";
break;
case libvlc_MediaPlayerPaused:
qDebug() << "VLC暂停播放";
break;
case libvlc_MediaParsedChanged: //获取媒体信息
qDebug() << "获取媒体信息";
break;
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)