音视频学习(二十二)——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、启动端口监听;
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
// 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 serverm_rtmp = rtmp_server_create(this, &handler);if (!m_rtmp)return -1;return 0;
}
  • 数据封装
// 上层通过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;
}
  • 发送数据
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;
}
  • 资源销毁
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;}
}

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

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

相关文章

django的gunicorn的异步任务执行

gunicorn 本身是一个WSGI HTTP服务器&#xff0c;用于运行Python的web应用&#xff0c;如Django项目。它并不直接提供执行异步任务的功能。异步任务通常是指那些你想要在web请求之外执行的后台任务&#xff0c;如发送电子邮件、处理长时间运行的计算或与外部API交互等。 在Dja…

可视化云监控/安防监控系统EasyCVR视频管理平台播流失败的原因(端口篇)

安防视频监控EasyCVR平台兼容性强&#xff0c;可支持的接入协议众多&#xff0c;包括国标GB28181、RTSP/Onvif、RTMP&#xff0c;以及厂家的私有协议与SDK&#xff0c;如&#xff1a;海康ehome、海康sdk、大华sdk、宇视sdk、华为sdk、萤石云sdk、乐橙sdk等。平台能将接入的视频…

C++ list的模拟实现

一 定义节点类 list相当于带头节点的双向链表&#xff0c;我们定义节点时要用类模板参数&#xff0c;同时定义_next、_prev指针和数据_data&#xff0c;使用struct定义节点类&#xff0c;因为节点类要能够被访问&#xff0c;而struct的默认访问权限就是public&#xff08;当然手…

XIAO ESP32S3之物体检测加入视频流

一、前言 由于XIAO ESP32S3开发套件没有显示屏配件&#xff0c;因此加入http视频流功能&#xff0c;可通过浏览器请求ESP32S3上的视频流。 二、思路 1、XIAO ESP32S3启动后通过wifi连接到AP&#xff1b; 2、启动http服务器&#xff0c;注册get_mjpeg处理函数&#xff1b; 3…

GPT Zero 是什么?

from https://openaigptguide.com/gptzero/ 在人工智能技术飞速发展的今天&#xff0c;人们对于文字内容的准确性和可信度要求越来越高。例如在学术研究领域&#xff0c;防止抄袭和造假是非常重要的。而对于普通用户而言&#xff0c;辨别哪些内容是由人工智能生成的&#xff0…

ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

目录 ​专题一 开启大模型 专题二 基于ChatGPT大模型提问框架 专题三 基于ChatGPT大模型的数据清洗 专题四 基于ChatGPT大模型的统计分析 专题五 基于ChatGPT大模型的机器学习 专题六 基于ChatGPT大模型的科研绘图 专题七 基于ChatGPT大模型的GIS应用 专题八 基于基于C…

redis如何批量删除key

在redis-cli或者rdm可视化工具中删除 执行命令行&#xff1a;DEL keyword1:keyword2:Id:7316* 表示删除形如 keyword1:keyword2:Id:7316123222,keyword1:keyword2:Id:7316123223的key&#xff0c;在redis中存储的key一般是前面都相同的&#xff0c;后面为变量 lua脚本删除 如…

FTP原理与配置

FTP是用来传送文件的协议。使用FTP实现远程文件传输的同时&#xff0c;还可以保证数据传输的可靠性和高效性。 FTP的应用 FTP 提供了一种在服务器和客户机之间上传和下载文件的有效方式。在企业网络中部署一台FTP服务器&#xff0c;将网络设备配置为FTP客户端&#xff0c;则可…

在Java中,list集合拆分

在Java中&#xff0c;list集合中有1000行student类的数据&#xff0c;循环遍历如何优化拆分集合&#xff0c;效率变快&#xff0c;请详细的写出代码并把注释写上在Java中&#xff0c;可以使用多线程来优化循环遍历list集合的效率。以下是一个示例代码&#xff1a;java import j…

在Ubuntu20.04配置PX4环境

目录 1.下载PX4源码2.安装PX4所有工具链3.编译PX4工程1.下载PX4源码 打开Ubuntu,Ctrl+Alt+T打开终端输入下面代码: git clone https://github.com/PX4/PX4-Autopilot.git --recursive出现上图中出现“Command ‘git’ not found, but can be installed with”,使用以下代码…

蓝桥杯嵌入式KEY

1.按键原理图 2.按键GPIO引脚设置成输入&#xff0c;上拉模式 3.设置TIM4时钟源为外部时钟源 PSC为80-1 Period为10000-1 打开NVIC 中断时间为10ms 4.在bsp文件中添加interrupt.c文件 5.按键单击代码 6.长按键 7.按键过程和显示过程

c语言结构体(初阶)

1. 结构体的声明 1.1 结构体的基础知识 结构是一些值的集合&#xff0c;这些值被称为成员变量。结构的每个成员可以是不同类型的变量。 1.2 结构的声明 struct tag {member - list; }variable-list; 例&#xff1a;描述一个人的信息&#xff1a;名字电话性别身高 //声明的…

深入浅出:分布式、CAP 和 BASE 理论(荣耀典藏版)

大家好&#xff0c;我是月夜枫&#xff0c;一个漂泊江湖多年的 985 非科班程序员&#xff0c;曾混迹于国企、互联网大厂和创业公司的后台开发攻城狮。 在计算机科学领域&#xff0c;分布式系统是一门极具挑战性的研究方向&#xff0c;也是互联网应用中必不可少的优化实践&…

LabVIEW利用视觉引导机开发器人精准抓取

LabVIEW利用视觉引导机开发器人精准抓取 本项目利用单目视觉技术指导多关节机器人精确抓取三维物体的技术。通过改进传统的相机标定方法&#xff0c;结合LabVIEW平台的Vision Development和Vision Builder forAutomated Inspection组件&#xff0c;优化了摄像系统的标定过程&a…

LeetCode第8题 - 字符串转换整数 (atoi)

题目 请你来实现一个 atoi 函数&#xff0c;使其能将字符串转换成整数。 首先&#xff0c;该函数会根据需要丢弃无用的开头空格字符&#xff0c;直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时&#xff0c;则将该符号与之后面尽可能多的连续数…

ROS学习记录:如何在Github上寻找并安装软件包

一、打开网页输入www.github.com 二、进入github界面 三、打开一个终端&#xff0c;输入mkdir catkin_ws1建立一个工作空间 四、使用cd catkin_ws1进入工作空间 五、使用mkdir src创建一个子目录src就是source&#xff0c;原始资料的意思,指的就是程序源代码这类资源材料&#…

小机器人,电子锁,牙刷,表类开关,磁阀开关等一些安防直流驱动的选型介绍分析

安防监控是一门被人们日益重视的新兴行业&#xff0c;就目前发展来看&#xff0c;应用普及程度越来越广&#xff0c;科技含量也越来越高&#xff0c;几乎所有高新科技都可促进其发展&#xff0c;尤其是信息时代的来临&#xff0c;更为该行业的发展提供契机。其中安防领域最为典…

electron 菜单栏打开指定url页面菜单实现方法

electron 菜单栏打开指定url页面菜单 可以是本地URL也可以是远程的URL 自动判断跳转 以下代码可以在主进程main.js里面也可以是在独立的模块文件里面 const { BrowserWindow } require(electron);//定义窗口加载URL export const winURL process.env.NODE_ENV development …

Android原生实现单选

六年前写的一个控件&#xff0c;一直没有时间总结&#xff0c;趁年底不怎么忙&#xff0c;整理一下之前写过的组件。供大家一起参考学习。废话不多说&#xff0c;先上图。 一、效果图 实现思路使用的是radioGroup加radiobutton组合方式。原理就是通过修改RadioButton 的backgr…

企业私有云容器化架构运维实战

企业私有云容器化架构运维实战 了解 什么是虚拟化: 虚拟化&#xff08;Virtualization&#xff09;技术最早出现在 20 世纪 60 年代的 IBM 大型机系统&#xff0c;在70年代的 System 370 系列中逐渐流行起来&#xff0c;这些机器通过一种叫虚拟机监控器&#xff08;Virtual M…