QT实现低延迟的RTSP、RTMP播放器

 

好多开发者在QT环境下实现RTMP或RTSP播放时,首先考虑到的是集成VLC,集成后,却发现VLC在延迟、断网重连、稳定性等各个方面不尽人意,无法满足上线环境需求。本文以调用大牛直播SDK(官方)的Windows平台播放端SDK为例,介绍下如何在QT下实现低延迟的RTMP|RTSP播放器,废话不多说,先上图:

大牛直播SDK有MFC的demo,所以在QT上实现播放轻车熟路,如果需要多窗口播放,也可以参考转发的demo,转发的那个4窗口预览的demo做了二次封装,调用更方便。

窗体布局不再赘述,就是个普通的6窗口布局,不得不说,QT在窗体布局这块,相对MFC真的太方便了。

考虑到大多场景下,开发者有多路播放诉求,针对这种情况,我们对player做个简单的封装:

开始播放:

bool player_wrapper::StartPlay(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute)
{if (is_playing_)return false;if (!OpenPlayerHandle(url, is_rtsp_tcp_mode, is_mute))return false;player_api_->SetBuffer(player_handle_, 100);player_api_->SetMute(player_handle_, is_mute ? 1 : 0);player_api_->SetRtspAutoSwitchTcpUdp(player_handle_, true);player_api_->SetRtspTimeout(player_handle_, 10);player_api_->SetRenderWindow(player_handle_, render_wnd_);player_api_->SetRenderScaleMode(player_handle_, 1);auto ret = player_api_->StartPlay(player_handle_);if (NT_ERC_OK != ret){if (!is_recording_){player_api_->Close(player_handle_);player_handle_ = NULL;}return false;}is_playing_ = true;return true;
}

开始播放封装,调用了OpenPlayerHandle(),检查系统是不是支持特定机型硬解码,通过调用Open()接口,获取播放实例,然后进行播放前的参数设置,比如网络状态event回调、视频宽高回调、设置buffer time、RTSP的TCP-UDP模式,默认播放音量等,具体实现如下:

bool player_wrapper::OpenPlayerHandle(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute)
{if (player_handle_ != NULL)return true;if (url.empty())return false;bool is_support_h264_hardware_decoder_ = NT_ERC_OK == player_api_->IsSupportH264HardwareDecoder();bool is_support_h265_hardware_decoder_ = NT_ERC_OK == player_api_->IsSupportH265HardwareDecoder();NT_HANDLE player_handle = NULL;Q_ASSERT(player_api_ != NULL);if (NT_ERC_OK != player_api_->Open(&player_handle, render_wnd_, 0, NULL)){return false;}Q_ASSERT(player_handle != NULL);player_api_->SetEventCallBack(player_handle, this, &NT_Player_SDKEventHandle);player_api_->SetVideoSizeCallBack(player_handle, this, SP_SDKVideoSizeHandle);player_api_->SetH264HardwareDecoder(player_handle, is_support_h264_hardware_decoder_ ? 1 : 0, 0);player_api_->SetH265HardwareDecoder(player_handle, is_support_h265_hardware_decoder_ ? 1 : 0, 0);player_api_->SetBuffer(player_handle, 0);player_api_->SetFastStartup(player_handle, 1);player_api_->SetRTSPTcpMode(player_handle, is_rtsp_tcp_mode ? 1 : 0);player_api_->SetMute(player_handle, is_mute ? 1 : 0);int audio_volume = 100;player_api_->SetAudioVolume(player_handle, audio_volume);if (NT_ERC_OK != player_api_->SetURL(player_handle, url.c_str())){if (!is_recording_){player_api_->Close(player_handle_);player_handle_ = NULL;}return false;}player_handle_ = player_handle;return true;
}

停止播放:

void player_wrapper::StopPlay()
{if (!is_playing_)return;player_api_->StopPlay(player_handle_);if (!is_recording_){player_api_->Close(player_handle_);player_handle_ = NULL;}is_playing_ = false;
}

Event回调:

extern "C" NT_VOID NT_CALLBACK NT_Player_SDKEventHandle(NT_HANDLE handle, NT_PVOID user_data,NT_UINT32 event_id,NT_INT64  param1,NT_INT64  param2,NT_UINT64 param3,NT_PCSTR  param4,NT_PCSTR  param5,NT_PVOID  param6)
{if (user_data == NULL)return;auto wrapper = reinterpret_cast<player_wrapper*>(user_data);if (wrapper == NULL)return;wrapper->OnPlayerStatus(event_id, param1);
}
void player_wrapper::OnPlayerStatus(NT_UINT32 event_id, NT_INT64 param1)
{if (player_handle_ == NULL)return;if (!is_playing_ && !is_recording_){return;}if (NT_SP_E_EVENT_ID_RTSP_STATUS_CODE == event_id){int status_code = (int)param1;if (401 == status_code){//HandleVerification();}return;}if (NT_SP_E_EVENT_ID_CONNECTING == event_id|| NT_SP_E_EVENT_ID_CONNECTION_FAILED == event_id|| NT_SP_E_EVENT_ID_CONNECTED == event_id|| NT_SP_E_EVENT_ID_DISCONNECTED == event_id|| NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED == event_id){if (NT_SP_E_EVENT_ID_CONNECTING == event_id){OutputDebugStringA("connection status: connecting\r\n");}else if (NT_SP_E_EVENT_ID_CONNECTION_FAILED == event_id){OutputDebugStringA("connection status: connection failed\r\n");}else if (NT_SP_E_EVENT_ID_CONNECTED == event_id){OutputDebugStringA("connection status: connected\r\n");}else if (NT_SP_E_EVENT_ID_DISCONNECTED == event_id){OutputDebugStringA("connection status: disconnected\r\n");}else if (NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED == event_id){OutputDebugStringA("connection status: no mediadata received\r\n");}}std::unique_lock<std::recursive_mutex> lock(player_handle_mutex_);player_status_ = event_id;
}

调用封装后的播放接口,记得多实例播放环境下,Init()和UnInit()接口仅需要调用一次,测试URL可自行设置。

void frmMain::startplay()
{for (int i = 0; i < widgets.size(); ++i){if (!plays[i]){plays[i] = std::make_shared<player_wrapper>(&player_api_, (HWND)NULL,(HWND)widgets.at(i)->winId());}auto& play = plays[i];if (!play->IsPlaying()){QString play_url = "rtsp://admin:admin123456@192.168.0.121:554/cam/realmonitor?channel=1&subtype=0";if (!play->StartPlay(play_url.toStdString(), true, false)){QMessageBox::information(NULL, "播放失败!", play_url);}}}
}
void frmMain::stopplay()
{for (int i = 0; i < widgets.size(); ++i){if (!plays[i]){plays[i] = std::make_shared<player_wrapper>(&player_api_, (HWND)NULL,(HWND)widgets.at(i)->winId());}auto& play = plays[i];if (play->IsPlaying()){play->StopPlay();}widgets.at(i)->setText(QString("通道 %1").arg(i + 1));widgets.at(i)->update();}
}

窗体大小发生改变时:


void frmMain::resizeEvent(QResizeEvent* event)
{for (int i = 0; i < widgets.size(); ++i){if (!plays[i]){plays[i] = std::make_shared<player_wrapper>(&player_api_, (HWND)NULL,(HWND)widgets.at(i)->winId());}auto& play = plays[i];if (play->IsPlaying()){play->OnWindowSize(widgets.at(i)->width(), widgets.at(i)->height());}}
}

以上是QT环境下集成个低延迟的RTMP、RTSP播放的基本流程,感兴趣的开发者可酌情参考。相对MFC,QT环境下在实现更酷炫和实用的逻辑显然体验更好一些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/553054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android对接实现内网无纸化会议|智慧教室|实时同屏功能

背景 本文主要讲的是基于Android平台实现RTMP的技术方案设计&#xff0c;基础架构图如下&#xff1a; 组网注意事项 1. 组网&#xff1a;无线组网&#xff0c;需要好的AP模块才能撑得住大的并发流量&#xff0c;推送端到AP&#xff0c;最好是有线网链接&#xff1b; 2. 服务…

bilibili里的硬币有什么用 硬币的作用详细介绍

很多bilibili中的用户发现自己的账户中拥有很多的硬币&#xff0c;却不知道这些硬币有什么用&#xff0c;下面小编就为大家带来硬币的作用介绍。 bilibili里的硬币有什么用 硬币的作用详细介绍 1、视频评分。向喜欢的视频投硬币以示鼓励(一个视频收到的硬币多了就会被推荐) …

Windows平台RTMP推送|轻量级RTSP服务实现本地摄像头|屏幕|叠加数据预览

背景 大家在做Windows平台RTMP推送或轻量级RTSP服务的时候&#xff0c;不管是采集屏幕还是采集摄像头&#xff0c;亦或屏幕摄像头的叠加模式&#xff0c;总会有这样的诉求&#xff0c;采集到的数据&#xff0c;希望能本地看看具体采集的数据或者图像实际效果&#xff0c;也就是…

Outlook2016怎么修改默认数据库

Outlook2016中想要修改默认数据库&#xff0c;该怎么修改呢?下面我们就来看看详细的教程。 Outlook2016怎么修改默认数据库? 1、下载安装outlook软件。 Outlook2016怎么修改默认数据库? 2、双击打开outlook软件。 Outlook2016怎么修改默认数据库? 3、点击“文件”——…

Windows平台RTMP|RTSP播放器为什么要兼容GDI绘制

为什么要支持GDI 先说结论&#xff0c;Windows平台播放渲染这块&#xff0c;一般来说99%以上的机器都是支持D3D的&#xff0c;实现GDI模式绘制&#xff0c;除了为了好的兼容性外&#xff0c;在远程连接的场景下&#xff0c;D3D创建不成功&#xff0c;需要使用GDI模式。 简单来…

Windows平台RTMP|RTSP播放器实现画面全屏功能

我们在Windows平台实现RTSP或者RTMP播放的时候&#xff0c;有个功能是绕不开的&#xff0c;那就是播放窗口全屏。本文就以大牛直播SDK&#xff08;官方&#xff09;的Windows播放器为例&#xff0c;大概讲下大概实现&#xff1a; 全屏播放需要考虑的点不多&#xff1a; 第一&…

tim怎么设置检测到新版本自动安装 tim安全自动更新的开启方法

TIM想要开启自动检测新版本并下载安装&#xff0c;该怎么设置呢?下面我们就来看看详细的教程。 1、首先&#xff0c;在你的 电脑中找到TIM; tim怎么设置检测到新版本自动安装?tim安全自动更新的开启方法 2、打开TIM&#xff0c;登录你的个人账号&#xff0c;登陆之后&…

Android平台实现Unity3D下RTMP推送

像Unity3D下的RTMP或RTSP播放器一样&#xff0c;好多开发者苦于在Unity环境下&#xff0c;如何高效率低延迟的把数据采集并编码实时推送到流媒体服务器&#xff0c;实现Unity场景下的低延迟推拉流方案。 关于屏幕采集&#xff0c;有两种方案&#xff1a; 1. 直接封装Android原…

Windows平台实现Unity下窗体|摄像头|屏幕采集推送

技术背景 随着Unity3D的应用范围越来越广&#xff0c;越来越多的行业开始基于Unity3D开发产品&#xff0c;如传统行业中虚拟仿真教育、航空工业、室内设计、城市规划、工业仿真等领域。 基于此&#xff0c;好多开发者苦于在Unity环境下&#xff0c;没有低延迟的推拉流解决方案…

钉钉调岗申请单怎么写 钉钉申请调岗的教程

钉钉中想要申请调岗申请单&#xff0c;调岗申请单在哪&#xff0c;该怎么填写呢?下面我们就来看看详细的教程。 1、首先打开钉钉客户端&#xff0c;点击下方的工作。 钉钉调岗申请单怎么写? 钉钉申请调岗的教程 2、向下滑动找到并打开调岗申请单应用。 钉钉调岗申请单怎么…

Android平台RTMP推送端实现外部数据对接推送和录像

背景 好多开发者在做Android平台RTMP推送对接的同时&#xff0c;除了编码前的数据外&#xff0c;还有些外部编码数据推送诉求&#xff0c;他们希望外部的编码音视频数据不止可以实现RTMP推送&#xff0c;还可以同时在推送端实时录制下来&#xff0c;本文以我们&#xff08;官方…

excel怎么删除浏览记录 方法介绍

Excel 2013工作表删除浏览记录的步骤&#xff1a; 1、鼠标左键双击计算机桌面Excel2013程序图标&#xff0c;将其打开运行。在打开的Excel2013程序窗口&#xff0c;点击“空白工作薄”选项&#xff0c;新建一个空白Excel工作薄。如图所示; excel怎么删除浏览记录&#xff1f;…

爱奇艺怎么开启数据流量自动播放

1、打开手机&#xff0c;点击爱奇艺 爱奇艺怎么开启数据流量自动播放 2、进入爱奇艺&#xff0c;点击我的 爱奇艺怎么开启数据流量自动播放 3、然后在我的界面&#xff0c;点击设置 爱奇艺怎么开启数据流量自动播放 4、进入设置界面&#xff0c;点击播放与下载 爱奇艺怎…

Win7系统账户被禁用的解决方法

我们都知道Win7系统中可以建立多个账户来进行不同的登录使用&#xff0c;十分的方便&#xff0c;但是有的用户建立了多个账户&#xff0c;却发现所有的账号都被禁用&#xff0c;那遇到这个问题应该怎么解决呢&#xff0c;下面就为小伙伴们带来 了Win7系统账户被禁用的解决方法&…

Win11系统如何隐藏快速搜索

近日网络中已经出现了很多Windows 11的泄露版本&#xff0c;意味着Win11版本正式确定&#xff0c;现在只是等待微软正式发布了。Windows系统中菜单栏都会默认放一个快速搜索的图标&#xff0c;快速搜索一直是Windows系统中的一个重要功能&#xff0c;那么在Win11系统中该如何隐…

网易邮箱广告标签怎么关 163邮箱去广告标签的教程

1、打开百度输入网易邮箱 网易邮箱广告标签怎么关? 163邮箱去广告标签的教程 网易邮箱广告标签怎么关? 163邮箱去广告标签的教程 2、输入账号和密码&#xff0c;进入邮箱主页&#xff0c;在标签栏看到广告标签 网易邮箱广告标签怎么关? 163邮箱去广告标签的教程 3、选中…

Linux|麒麟操作系统实现多路RTMP|RTSP播放

技术背景 无论是Windows平台还是Linux&#xff0c;多路播放诉求非常普遍&#xff0c;比如针对智慧工地、展馆、教育等宏观场景下的摄像头展示&#xff0c;关于RTSP或RTMP直播播放器开发需要注意的点&#xff0c;可参考之前博客&#xff0c;总的来说有以下一些点&#xff1a; …

TIM提示“个人文件夹被占用,请稍候再登录”怎么解决

在登录TIM的时候&#xff0c;弹出提示“个人文件夹被占用&#xff0c;请稍后再登录”的提示&#xff0c;无法正常登录TIM TIM提示“个人文件夹被占用&#xff0c;请稍候再登录”怎么解决&#xff1f; 这个时候&#xff0c;我们可以直接关闭上面的登录窗口&#xff0c;然后过一…

数据推送选择GB28181、RTSP还是RTMP?

GB/T28181 国标GB/T28181协议全称《安全防范视频监控联网系统信息传输、交换、控制技术要求》&#xff0c;是一个定义视频联网传输和设备控制标准的白皮书&#xff0c;由公安部科技信息化局提出&#xff0c;该标准规定了城市监控报警联网系统中信息传输、交换、控制的互联结构…

Windows平台RTMP推送摄像头对接介绍

背景 好多开发者在对接大牛直播SDK&#xff08;官方&#xff09;的Windows平台RTMP推送时&#xff0c;不熟悉摄像头调用&#xff0c;实际上&#xff0c;摄像头调用逻辑并不复杂&#xff0c;以下是大概流程&#xff1a; 首先调用我们sdk接口获取摄像头个数&#xff0c;调用接口…