GB28181学习(六)——实时视音频点播(数据传输部分)

GB28181系列文章:

总述:https://blog.csdn.net/www_dong/article/details/132515446

注册与注销:https://blog.csdn.net/www_dong/article/details/132654525

心跳保活:https://blog.csdn.net/www_dong/article/details/132796612

网络设备信息查询:https://blog.csdn.net/www_dong/article/details/132912085

视音频点播(信令传输部分):https://blog.csdn.net/www_dong/article/details/132950064

媒体服务器

提供媒体流的转发、媒体存储、历史媒体信息的检索和点播服务的服务器。

设计方案

  • jrtplib+jthread:监听、视频数据接收与转发;
  • libmpeg:对ps流解复用;
  • ffmpeg:数据解码;
  • Qt(QOpenGLWidget):视频播放;

数据接收

jrtplib

jrtplib是一个面向对象的RTP封装库。

特点:

  • 该库使用户能够发送和接收数据使用RTP,无需担心SSRC冲突、调度和传输RTCP数据等。用户只需提供库通过发送有效负载数据,库为用户提供访问权限输入RTP和RTCP数据;
  • 该库提供了几个类,这些类有助于创建RTP应用程序。大多数用户可能只需要RTPSession类来构建应用程序,或者从RTPSecureSession派生一个类来支持SRTP。这些类提供了发送RTP数据的必要功能,并在内部处理RTCP部分;

jthread

jrtplib的使用依赖于jthread,使用方式用两种:

  1. 用 jthread 库提供的线程自动在后台执行对数据的接收;
  2. 用户自己调用 RTPSession 中的 Poll 方法;

下载

下载地址:https://research.edm.uhasselt.be/jori/page/Cs/JrtplibOld.html

该项目目前使用的是jrtplib-3.11.2.zip+jthread-1.3.3.zip 。下载完成后使用cmake生成windows下.sln工程编译生成静态库使用。

流程

  • 数据接收流程,该流程目前在线程中处理。
c++ 复制代码
uint8_t payload;
while (m_running)
{
	Poll();
	BeginDataAccess();

	if (GotoFirstSourceWithData())
	{
		do
		{
			RTPPacket* packet = nullptr;
			while (nullptr != (packet = GetNextPacket()))
			{
				payload = packet->GetPayloadType();
				if (0 == payload)
				{
					DeletePacket(packet);
					continue;
				}

				// ...
				// rtp载荷数据处理流程

				DeletePacket(packet);
			}

		} while (GotoNextSourceWithData());
	}

	EndDataAccess();
	Sleep(30);
}

Destroy();

数据解复用

该流程使用的是libmpeg库,下载地址:https://github.com/ireader/media-server.git

由于国标流是ps封装,故需要将ps流解复用获取原始数据。

解复用代码流程:

c++ 复制代码
static void* Alloc(void* /*param*/, size_t bytes)
{
	return malloc(bytes);
}

static void Free(void* /*param*/, void* packet)
{
	free(packet);
}

static int Write(void* param, int avtype, void* pes, size_t bytes)
{
	assert(param);
	CPSParse* parse = (CPSParse*)param;
	return parse->Package(avtype, pes, bytes);
}

CPSParse::CPSParse()
{
	struct ps_muxer_func_t func;
	func.alloc = Alloc;
	func.free = Free;
	func.write = Write;
	m_ps = ps_muxer_create(&func, this);
	m_ps_stream = ps_muxer_add_stream(m_ps, STREAM_VIDEO_H264, nullptr, 0);
}

CPSParse::~CPSParse()
{
	if (m_ps)
		ps_muxer_destroy(m_ps);
}

int CPSParse::InputData(void* data, int len)
{
	if (nullptr == m_ps || nullptr == data || len <= 0)
		return -1;

	uint64_t clock = time64_now();
	if (0 == m_ps_clock)
		m_ps_clock = clock;
	ps_muxer_input(m_ps, m_ps_stream, 0, (clock - m_ps_clock) * 90, (clock - m_ps_clock) * 90, data, len);
	return 0;
}

int CPSParse::Package(int avtype, void* payload, size_t bytes)
{
	// 数据处理
    
	return 0;
}

数据解码

通过对ps数据流解复用获取原始数据,本项目通过ffmpeg对原始数据进行解码获取yuv数据。

关于ffmpeg的使用,可以查看:

音视频播放器设计(一)------环境配置https://blog.csdn.net/www_dong/article/details/124459467

音视频播放器设计(二)------ffmpeg视频处理流程https://blog.csdn.net/www_dong/article/details/124561444

音视频播放器设计(三)------OpenGL绘制视频https://blog.csdn.net/www_dong/article/details/124638515

音视频播放器设计(四)------ffmpeg音频处理流程https://blog.csdn.net/www_dong/article/details/125323635

视频播放

通过ffmpeg解码获取yuv数据,本项目通过qt的QOpenGLWidget对yuv数据进行渲染达到播放的目的。

  • 使用方法:
    • 新建一个PlayWidget类继承于QOpenGLWidget;
    • 将ffmpeg解码后的yuv数据传入PlayWidget类,保存并调用update函数;
    • update()被调用后,QOpenGLWidget::paintGL()会自动被调用,在里面进行显示;
    • 使用QOpenGLFunctions::glTexImage2D传入一帧数据进行显示;
c++ 复制代码
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>

class PlayWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    public:
	PlayWidget(QWidget *parent = nullptr);
	virtual ~PlayWidget();
    
    // ...
};

效果展示

相关推荐
冷眼看人间恩怨25 分钟前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
红龙创客34 分钟前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin37 分钟前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
yuanbenshidiaos2 小时前
c++---------数据类型
java·jvm·c++
十年一梦实验室3 小时前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
taoyong0013 小时前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
这是我583 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
fpcc3 小时前
跟我学c++中级篇——C++中的缓存利用
c++·缓存
呆萌很3 小时前
C++ 集合 list 使用
c++
诚丞成4 小时前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++