音视频学习(二十二)——rtmp发流(tcp方式)

前言

本文主要介绍自研的RtmpStreamSender.dll,rtmp库提供接口接收裸流数据,支持将裸流数据封装为flv格式并通过rtmp协议发流。

关于rtmp协议基础介绍可查看:https://blog.csdn.net/www_dong/article/details/131026072

关于rtmp收流介绍可查看:https://blog.csdn.net/www_dong/article/details/135073488

设计

主要流程:

  1. rtmp服务端启动tcp(端口:1935)监听,创建rtmp server对象;
  2. rtmp客户端发起tcp连接,连接成功后等到收流;
  3. rtmp服务端以动态库的形式呈现,提供SendData接口,有上层应用调用时塞入数据;
  4. rtmp服务端接收数据,将数据封装为flv格式;
  5. rtmp服务端将flv格式的流发送给rtmp客户端;
  6. rtmp客户端将数据解复用、解码和播放;

流程

  • 创建tcp、启动端口监听;
c++ 复制代码
int RtmpServerThread(void* param)
{
	assert(param);
	CRtmpStreamSender* receiver = (CRtmpStreamSender*)param;
	receiver->RtmpServerWorker();
	return 0;
}

int CRtmpStreamSender::InitRtmpSession_()
{
	if (0 != ParseUrl_())
	{
		printf("parse url failed\n");
		return -1;
	}

	do
	{
		m_tcpServer = std::make_shared<ZDTcpServer>(nullptr, this);
		if (!m_tcpServer.get()
			|| 0 != m_tcpServer->TcpCreate()
			|| 0 != m_tcpServer->TcpBind(m_rtmpPort)
			|| 0 != m_tcpServer->TcpListen(5))
		{
			break;
		}
			
		m_command = std::make_shared<CRtmpServerCommand>(m_tcpServer);
		if (!m_command.get()
			|| 0 != m_command->Create())
		{
			break;
		}

		m_thread = std::thread(RtmpServerThread, this);
		return 0;
	} while (0);
	
	Stop();
	return 0;
}

// 在线程中等待连接
void CRtmpStreamSender::RtmpServerWorker()
{
	bool bAccept = false;
	while (m_running)
	{
		if (!bAccept)
		{
			if (0 == m_tcpServer->TcpAccept())
			{
				bAccept = true;
			}

			continue;
		}

		std::this_thread::sleep_for(std::chrono::seconds(5));
	}
}
  • 创建rtmp server
c++ 复制代码
// CRtmpServerCommand:librtmp封装类
m_command = std::make_shared<CRtmpServerCommand>(m_tcpServer);
if (!m_command.get()
    || 0 != m_command->Create())
{
    break;
}

// 创建rtmp server
int CRtmpServerCommand::Create()
{
    // 创建flv复用对象
	m_flvMuxer = flv_muxer_create(SendRtmpDataMutexFLV, this);
	if (!m_flvMuxer)
		return -1;

	struct rtmp_server_handler_t handler;
	memset(&handler, 0, sizeof(handler));
	handler.send = SendCallback;

    // 创建rtmp server
	m_rtmp = rtmp_server_create(this, &handler);
	if (!m_rtmp)
		return -1;

	return 0;
}
  • 数据封装
c++ 复制代码
// 上层通过SendData塞数据
int CRtmpStreamSender::SendData(void* data, int len, char* codec)
{
	if (!m_command.get())
		return -1;

	return m_command->InputData(data, len, codec);
}

// 数据做flv封装
int CRtmpServerCommand::InputData(void* data, int len, const std::string& codec)
{
	if (!m_flvMuxer || !data || len <= 0 || codec.empty())
		return -1;

	int ret = -1;
	if (0 == codec.compare("H264"))
	{
		ret = flv_muxer_avc(m_flvMuxer, data, len, 0, 0);
	}
	else if (0 == codec.compare("H265"))
	{
		ret = flv_muxer_hevc(m_flvMuxer, data, len, 0, 0);
	}
	else if (0 == codec.compare("AAC"))
	{
		ret = flv_muxer_aac(m_flvMuxer, data, len, 0, 0);
	}

	return 0;
}
  • 发送数据
c++ 复制代码
int CRtmpServerCommand::Package(int type, const void* data, size_t bytes, uint32_t timestamp)
{
	if (!m_rtmp || !data || bytes <= 0)
		return -1;

	int ret = -1;
	if (FLV_TYPE_AUDIO == type)
	{
		ret = rtmp_server_send_audio(m_rtmp, data, bytes, timestamp);
	}
	else if (FLV_TYPE_VIDEO == type)
	{
		ret = rtmp_server_send_video(m_rtmp, data, bytes, timestamp);
	}
	else if (FLV_TYPE_SCRIPT == type)
	{
		ret = rtmp_server_send_script(m_rtmp, data, bytes, timestamp);
	}

	if (0 != ret)
		return ret;

	return 0;
}
  • 资源销毁
c++ 复制代码
void CRtmpServerCommand::Destroy()
{
	if (m_rtmp)
	{
		rtmp_server_destroy(m_rtmp);
		m_rtmp = nullptr;
	}

	if (m_flvMuxer)
	{
		flv_muxer_destroy(m_flvMuxer);
		m_flvMuxer = nullptr;
	}
}
相关推荐
我命由我1234516 小时前
SVG - SVG 引入(SVG 概述、SVG 基本使用、SVG 使用 CSS、SVG 使用 JavaScript、SVG 实例实操)
开发语言·前端·javascript·css·学习·ecmascript·学习方法
老蒋新思维17 小时前
知识IP的长期主义:当AI成为跨越增长曲线的“第二曲线引擎”|创客匠人
大数据·人工智能·tcp/ip·机器学习·创始人ip·创客匠人·知识变现
Fern_blog18 小时前
鸿蒙学习之路
学习
小智RE0-走在路上19 小时前
Python学习笔记(11) --数据可视化
笔记·python·学习
誰能久伴不乏20 小时前
epoll 学习踩坑:`fcntl` 设置非阻塞到底用 `F_SETFL` 还是 `F_SETFD`?
linux·服务器·网络·c++·tcp/ip
cver12320 小时前
足球视频检测数据集介绍-160张图片-智能体育转播 运动数据分析 自动化视频剪辑 裁判辅助系统 青训技术分析 虚拟现实体验
数据分析·自动化·音视频
来鸟 鸣间21 小时前
MIPI D-PHY 理解
linux·音视频·sensor·mipi
Asus.Blogs21 小时前
SSE + Resty + Goroutine + Channel 完整学习笔记
笔记·学习·golang
charlie1145141911 天前
Git团队协作完全入门指南(上)
笔记·git·学习·教程·工程