基于RTMP实现Linux

2023-11-01

背景

Windows操作系统自问世以来,以其简单易用的图形化界面操作受到大众追捧,为计算机的普及、科技的发展做出了不可磨灭的功绩,也慢慢的成为人们最依赖的操作系统。在中国,90%以上的办公环境都是Windows,学校和各种培训班的培训内容也都是Windows,Windows操作系统已经渗入到各行各业,人们已经习惯了Windows的界面和操作习惯,IT计算机和Windows已经被习以为常的画上了等号。

但是,我们使用的软件真的安全吗?黑屏事件和棱镜门事件让很多乐观看待或尚未意识到信息安全问题的人们警醒,我们所使用的国外软件并不是安全的,我们的数据完全掌握在别人手中。随着信息安全上升到了国家战略的高度,推行自主可控的国产操作系统势在必行。国产操作系统作为自主可控的基础,市场迅速升温,受到了社会各界的高度关注。

我们有别的选择吗?

其实基于开源软件Linux二次开发的操作系统,近年来的发展趋势非常迅猛。Linux已经有20年历史,尤其近十年经过突飞猛进的发展,Linux桌面操作系统已经远远摆脱了“具备与主流桌面操作系统的可比性”阶段,基于拥有众多优秀的开源应用软件的基础,在软件多样性、硬件兼容性、用户体验等各方面做了大量的改进,现在已经可以满足日常办公的需求。在欧美,我们不时听到一些政府部门将采用Linux桌面办公:慕尼黑市政府用十年的时间,成功的“赶走”了微软;伯明翰市政府、法国国会、瑞士、挪威和南非政府部门也都采用了Linux桌面办公。

国产操作系统|Linux下RTMP同屏推送

在发布国产操作系统|Linux平台的RTMP直播推送SDK之前,大牛直播SDK(官方)的RTMP推送模块已稳定运行在Windows、Android和iOS平台几年了。

相对Windows、Android和iOS平台,Linux在桌面采集等方面,资料非常少,数据采集可以采用调用XLib相关接口实现,本Demo实现的是Linux上实现桌面和系统声音采集,然后使用RTMP协议推出去的一个SDK. 集成调用非常简单。

相关实现

int main(int argc, char *argv[])
{
	signal(SIGINT, &OnSigIntHandler);

	//printf("sizeof(NT_SmartPublisherSDKAPI)=%d\n", sizeof(NT_SmartPublisherSDKAPI));

	LogInit();

	NT_SmartPublisherSDKAPI push_api;
	if (!PushSDKInit(push_api))
	{
		return 0;
	}

	auto push_handle = StartPush(&push_api, "rtmp://192.168.0.154:1935/live/test1", 30);
	if (!push_handle)
	{
		fprintf(stderr, "start push failed.\n");
		push_api.UnInit();
		return 0;
	}

	while (!g_is_exit)
	{
		sleep(2);
	}

	fprintf(stdout, "Skip run loop, is_exit:%d\n", g_is_exit);

	push_api.StopPublisher(push_handle);

	push_api.Close(push_handle);

	push_handle = nullptr;
	
	push_api.UnInit();

	fprintf(stdout, "SDK UnInit..\n");
	
	return 0;
}

相关初始化

	void OnSigIntHandler(int sig)
	{
		if (SIGINT == sig)
		{
			g_is_exit = true;
		}
	}
	
	void LogInit()
	{
		SmartLogAPI log_api;
		memset(&log_api, 0, sizeof(log_api));
		GetSmartLogAPI(&log_api);

		log_api.SetLevel(SL_INFO_LEVEL);
		log_api.SetPath((NT_PVOID)"./");
	}

	bool PushSDKInit(NT_SmartPublisherSDKAPI& push_api)
	{
		memset(&push_api, 0, sizeof(push_api));
		NT_GetSmartPublisherSDKAPI(&push_api);

		auto ret = push_api.Init(0, nullptr);
		if (NT_ERC_OK != ret)
		{
			fprintf(stderr, "push_api.Init failed!\n");
			return false;
		}
		else
		{
			fprintf(stdout, "push_api.Init ok!\n");
		}

		return true;
	}

推送接口封装

	NT_HANDLE StartPush(NT_SmartPublisherSDKAPI* push_api, const std::string& rtmp_url, int dst_fps)
	{
		NT_INT32 pulse_device_number = 0;
		if (NT_ERC_OK == push_api->GetAuidoInputDeviceNumber(2, &pulse_device_number))
		{
			fprintf(stdout, "Pulse device num:%d\n", pulse_device_number);
			char device_name[512];

			for (auto i = 0; i < pulse_device_number; ++i)
			{
				if (NT_ERC_OK == push_api->GetAuidoInputDeviceName(2, i, device_name, 512))
				{
					fprintf(stdout, "index:%d name:%s\n", i, device_name);
				}
			}
		}

		NT_INT32 alsa_device_number = 0;
		if (pulse_device_number < 1)
		{
			if (NT_ERC_OK == push_api->GetAuidoInputDeviceNumber(1, &alsa_device_number))
			{
				fprintf(stdout, "Alsa device num:%d\n", alsa_device_number);
				char device_name[512];
				for (auto i = 0; i < alsa_device_number; ++i)
				{
					if (NT_ERC_OK == push_api->GetAuidoInputDeviceName(1, i, device_name, 512))
					{
						fprintf(stdout, "index:%d name:%s\n", i, device_name);
					}
				}
			}
		}

		NT_INT32 capture_speaker_flag = 0;
		if ( NT_ERC_OK == push_api->IsCanCaptureSpeaker(2, &capture_speaker_flag) )
		{
			if (capture_speaker_flag)
				fprintf(stdout, "Support speaker capture\n");
			else
				fprintf(stdout, "UnSupport speaker capture\n");
		}

		NT_INT32 is_support_window_capture = 0;
		if (NT_ERC_OK == push_api->IsCaptureWindowSupported(NULL, &is_support_window_capture))
		{
			if (is_support_window_capture)
				fprintf(stdout, "Support window capture\n");
			else
				fprintf(stdout, "UnSupport window capture\n");
		}

		NT_HANDLE push_handle = nullptr;

		// if (NT_ERC_OK != push_api->Open(&push_handle, NT_PB_E_VIDEO_OPTION_LAYER, NT_PB_E_AUDIO_OPTION_CAPTURE_SPEAKER, 0, NULL))
		if (NT_ERC_OK != push_api->Open(&push_handle, NT_PB_E_VIDEO_OPTION_SCREEN, NT_PB_E_AUDIO_OPTION_CAPTURE_SPEAKER, 0, NULL))
		{
			return nullptr;
		}

		//push_api->SetXDisplayName(push_handle, ":0");
		//push_api->SetXDisplayName(push_handle, NULL);
		
		// 视频层配置方式

		//std::vector<std::shared_ptr<nt_pb_sdk::layer_conf_wrapper_base> > layer_confs;

		//auto index = 0;

		 第0层填充RGBA矩形, 目的是保证帧率, 颜色就填充全黑
		//auto rgba_layer_c0 = std::make_shared<nt_pb_sdk::RGBARectangleLayerConfigWrapper>(index++, true, 0, 0, 1280, 720);

		//rgba_layer_c0->conf_.red_ = 0;
		//rgba_layer_c0->conf_.green_ = 0;
		//rgba_layer_c0->conf_.blue_ = 0;
		//rgba_layer_c0->conf_.alpha_ = 255;

		//layer_confs.push_back(rgba_layer_c0);

		 第一层为桌面层
		//auto screen_layer_c1 = std::make_shared<nt_pb_sdk::ScreenLayerConfigWrapper>(index++, true, 0, 0, 1280, 720);
		//
		//screen_layer_c1->conf_.scale_filter_mode_ = 3;

		//layer_confs.push_back(screen_layer_c1);

		//std::vector<const NT_PB_LayerBaseConfig* > layer_base_confs;

		//for (const auto& i : layer_confs)
		//{
		//	layer_base_confs.push_back(i->getBase());
		//}

		//if (NT_ERC_OK != push_api->SetLayersConfig(push_handle, 0, layer_base_confs.data(),
		//	layer_base_confs.size(), 0, nullptr))
		//{
		//	push_api->Close(push_handle);
		//	push_handle = nullptr;
		//	return nullptr;
		//}

		// push_api->SetScreenClip(push_handle, 0, 0, 1280, 720);

		push_api->SetFrameRate(push_handle, dst_fps); // 帧率设置
			
		push_api->SetVideoBitRate(push_handle, 2000);  // 平均码率2000kbps
		push_api->SetVideoQualityV2(push_handle, 26); 
		push_api->SetVideoMaxBitRate(push_handle, 4000); // 最大码率4000kbps
		push_api->SetVideoKeyFrameInterval(push_handle, dst_fps*2); // 关键帧间隔
		push_api->SetVideoEncoderProfile(push_handle, 3); // h264 baseline
		push_api->SetVideoEncoderSpeed(push_handle, 3); // 编码速度设置到3

		if (pulse_device_number > 0)
		{
			push_api->SetAudioInputLayer(push_handle, 2);
			push_api->SetAuidoInputDeviceId(push_handle, 0);
		}
		else if (alsa_device_number > 0)
		{
			push_api->SetAudioInputLayer(push_handle, 1);
			push_api->SetAuidoInputDeviceId(push_handle, 0);
		}

		// 音频配置
		push_api->SetPublisherAudioCodecType(push_handle, 1);
		//push_api->SetMute(push_handle, 1);

		if ( NT_ERC_OK != push_api->SetURL(push_handle, rtmp_url.c_str(), NULL) )
		{
			push_api->Close(push_handle);
			push_handle = nullptr;
			return nullptr;
		}

		if ( NT_ERC_OK != push_api->StartPublisher(push_handle, NULL) )
		{
			push_api->Close(push_handle);
			push_handle = nullptr;
			return nullptr;
		}

		return push_handle;
	}

相关界面

总结

实际测试下来,以RTMP推送和RTMP播放为例,整体测试时延都在毫秒级,可满足像内网无纸化、教育同屏等场景需求。

Linux的RTMP推送接口,和Windows平台的相差无几,通用接口四个平台几乎一致,不存在集成难度。

国产操作系统替代windows,也许并不像你想象的那么遥远,使用习惯上也并不像想象中那么难,相信在不久的将来,国产操作系统会真正被市场广泛使用。

国产操作系统下的应用生态的创建,需要国人一点点建立。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于RTMP实现Linux 的相关文章

  • 可用的公开 RTSP/ RTMP 在线视频流资源地址(亲测可行)

    可用的公开 RTSP RTMP 在线视频流资源地址 亲测可行 时间节点 2023 01 23 rtsp rtsp wowzaec2demo streamlock net vod mp4 BigBuckBunny 115k mp4 rtmp
  • H264码流RTP封装方式详解

    H264码流RTP封装方式详解 文章目录 H264码流RTP封装方式详解 1 H264基本概念 2 NALU Header介绍 3 RTP封装H264码流 3 1 单一NALU模式 3 2 组合帧封装模式 3 3 分片封装模式 4 代码解析
  • 基于libVLC的视频播放器(支持RTSP协议)

    VLC Media Player是一款优秀的播放器 大多数多媒体开发人员都使用过 VLC是一款开源的 跨平台的 可扩展的 多媒体播放器 流媒体服务器及框架 可播放大多数多媒体文件 以及DVD 音频CD VCD及各类流媒体协议 现更名为VLC
  • 将websocket通信端口代理到TCP通信端口的方法记录

    websocketproxy代理服务基于go语言实现 功能描述 Proxy of gateway Websockt transfer TCP protocol Websocket gt TCP TCP gt Websocket 即 实现将w
  • Android GB28181设备接入端语音广播和语音对讲技术实现探究

    上篇文章提到Android端GB28181接入端的语音广播和语音对讲的实现 从spec角度大概介绍了下流程和简单的接口设计 好多开发者私信我 希望展开说一下 其实这块难度不大 只是广播和对讲涉及到双向实现 如果之前没有相关的积累 从头实现麻
  • GB/T28181-2022协议版本标识X-GB-Ver解读

    GB28181 2022相对2016 其中有个变化是 报文中携带协议版本标识 X GB Ver 3 0 3 0 2022 2 0 2016 为便于联网设备或服务器之间互相识别对方支持的协议版本 在SIP注册及其响应消息 无论是成功或失败 头
  • 海康rtsp抓包分析

    海康h264 rtp rtsp rtcp包分析 1 DESCRIBE rtsp 192 168 0 186 554 mpeg4 ch01 main av stream RTSP 1 0 CSeq 0 Accept application s
  • VLC相关参数中文说明!

    用法 vlc 选项 流 您可以在命令行中指定多个流 它们将被加入播放列表队列 指定的首个项目将被首先播放 选项样式 选项 用于设置程序执行期间的全局选项 选项 单字母版本的全局 选项 选项 一个仅在流之前应用的选项 且将覆盖先前的设置 流
  • 运动估计与运动补偿

    运动估计与运动补 偿 改正 2010 11 17 10 29 29 运动补偿是通过先前的局部图像来预测 补偿当前的局部图像 它是减少帧序列冗余信息的有效方法 运动估计是从视频序列中抽取运动信息的一整套技术 运动估计与运动补偿技术 MPEG
  • NV21、NV12、YV12、RGB565、YUV等颜色编码格式区别和接口设计探讨

    NV21 NV12 YV12 RGB565 YUV扫盲 NV21 NV12 YV12 RGB565 YUV分别是不同的颜色编码格式 这些颜色编码格式各有特点 适用于不同的应用场景 选择合适的颜色编码格式取决于具体的需求和环境 NV21 NV
  • Android平台GB28181接入端如何对接UVC摄像头?

    我们在对接Android平台GB28181接入的时候 有公司提出这样的需求 除了采集执法记录仪摄像头自带的数据外 还想通过执法记录仪采集外接UVC摄像头 实际上 这块对我们来说有点炒冷饭了 不算新的诉求 大牛直播SDK 在2016年对接RT
  • FFmpeg入门详解之92:Live555学习之(一)-------Live555的基本介绍

    Live555学习之 一 Live555的基本介绍 前一阵子 因为项目需要 研究了一下Live555开源框架 研究的不是很深入 基本上把Live555当做API用了一下 但是毕竟也是本人看的第一个开源框架 在此记录总结一下 Live555是
  • librtmp ssl 1.0.0 到 ssl 1.1.1

    openssl 版本更新了 导致 librtmp 库不能使用 于是查查资料 Compiler errors dereferencing pointer to incomplete type DH aka struct dh st 根据上面的
  • Red5应用开发(二)直播串流与录制

    环境 操作系统 win10 1803 Eclipse版本 4 7 3a Oxygen J2EE版本 Red5 Server版本 1 0 8 Release 环境搭建参考前一篇文章 Red5应用开发 一 开发环境搭建 后续不再涉及red5 f
  • GB28181媒体保活机制探究与实现

    规范解读 GB28181 2016和GB28181 2022关于媒体保活机制这块 并无调整 平台 设备媒体流保活机制规定如下 a 链路建立后 码流经过的各级平台应具备媒体流丢失监测能力 若监测到媒体流丢失 应释放该条媒体链路 并通过会话内B
  • RTP和RTCP详解

    1 RTP和RTCP详解 文章目录 1 RTP和RTCP详解 1 1 概述 1 2 RTP协议详解 1 3 RTCP协议详解 1 1 概述 在流媒体相关的领域 我们进场会看到RTP RTCP 其用于流式传输的最常见的码流传输协议 位于传输层
  • Android平台一对一音视频通话方案对比:WebRTC VS RTMP VS RTSP

    一对一音视频通话使用场景 一对一音视频通话都需要稳定 清晰和流畅 以确保良好的用户体验 常用的使用场景如下 社交应用 社交应用是一种常见的使用场景 用户可以通过音视频通话进行面对面的交流 在线教育 老师和学生可以通过音视频通话功能进行实时互
  • 深入理解Google Cast(三)探寻原理

    如何开发一个receiver application 先来简单说一下这个话题 Receiver本质就是一个网页 由html CSS和jacascript开发 如果要自定义receiver application 需要在 Google Cas
  • 公网可用的RTMP、RTSP测试地址(更新于2021年3月)

    好多博客提到的公网可测试的RTSP和RTMP URL大多都不用了 以下是大牛直播SDK Github 于2021年3月亲测可用的几个URL 有其他可用的URL 也欢迎大家在评论区回复 RTMP流地址 湖南卫视 rtmp 58 200 131
  • RTP/RTCP/RTSP负载H264的一些问题小结

    以下内容都是基于rfc3984 RTP负载H264时的参数配置 1 在TCP传输时 Transport头中的interleaved参数必须设置 比如0 1 或者2 3 海康的流中出现了4 但是没有配置 所以wireshark也无法解析cha

随机推荐

  • Linux修改虚拟内存

    Linux机器默认swap空间 虚拟内存 为2G或更小 在运行一些大型程序如深度神经网络程序时 物理内存往往无法满足需求 可以扩大swap空间以达到正常运行的目的 主要分为6个步骤 1 创建swap文件夹 sudo mkdir usr sw
  • ospf小总结

    Ospf 开放式最短路径优先协议 Open Shortest Path First OSPF 无类别链路状态igp协议 周期更新 30min 触发更新 链路状态协议的更新量随着网络范围的扩展指数性的上升 因此ospf协议为了在中大型网络中工
  • 【cpolar、PHPStudy— 搭建企业论坛】

    公司内部搭建企业论坛 并实现在外也可以访问 文章目录 公司内部搭建企业论坛 并实现在外也可以访问 前言 1 cpolar PHPStudy 2 Discuz 3 打开PHPStudy 安装网页论坛所需软件 4 进行网页运行环境的构建 5 运
  • 关于ADMM的研究(二)

    4 Consensus and Sharing 本节讲述的两个优化问题 是非常常见的优化问题 也非常重要 我认为是ADMM算法通往并行和分布式计算的一个途径 consensus和sharing 即一致性优化问题与共享优化问题 Consens
  • Servlet的生命周期

    目录 1 Servlet的一生有这么几个阶段 2 一个Servlet从开始到消亡 1 Servlet的一生有这么几个阶段 调用构造方法进行实例化 1 构造方法 在第一次发起请求时 调用一次 public HomeServlet System
  • 61850协议服务器端开发,IEC61850中报告服务端开发

    实战的方式介绍IEC61850报告服务端的开发 本文讲述的是IEC61850中最常用的报告功能服务端的实现方法 内容包含了CID建模 编码实现 还包括后面的运行效果 MMS报文等 一 CID建模 1 通讯部分 1 1 9999 1 12 0
  • 【ReactiveX】介绍(译)

    更多内容 欢迎关注作者博客 http www china10s com blog p 465 ReactiveX 是通过使用 Observable 序列用来合成异步的和事件响应式的程序上的库文件 它扩展了通知者模式来支持数据和 或事件的响应
  • 8款超级好用的3D建模软件上下篇

    只要有水平 做出好作品 完全没问题 非也非也 做出一个好作品 不但要靠自身的技巧水平 选择适合自己的3D建模软件也是一个很重要的因素 所以小编今天就给大家安利8款好用的3D建模软件 无论你是一个0基础的初阶学者 还是想提升自己水平的进阶从业
  • 第3章-数组

    1 数组的概述 数组 Array 是多个相同类型数据按一定顺序排列 的集合 并使用一个名字命名 并通过编号的方式 对这些数据进行统一管理 数组的常见概念 数组名 下标 或索引 元素 数组的长度 数组本身是引用数据类型 而数组中的元素可以是任
  • 解决 Xshell 连接 centOs7 的Could not connect to '192.168.119.129' (port 22): Connection failed.

    在用Xshell 连接centos7的时候会遇到Could not connect to 192 168 119 129 port 22 Connection failed 这个问题 我的解决办法如下 Step1 获取 centos7 的I
  • 刷题-Leetcode-39. 组合总和(回溯-组合)

    39 组合总和 题目链接 来源 力扣 LeetCode 链接 https leetcode cn com problems combination sum submissions 著作权归领扣网络所有 商业转载请联系官方授权 非商业转载请注
  • 【手撕代码系列】JS手写实现防抖函数

    公众号 Code程序人生 分享互联网所见所闻 防抖是一种前端常见的性能优化技术 可以避免在高频触发的情况下频繁地执行函数 从而减少资源的消耗 本文将介绍如何手写实现一个防抖函数 防抖的原理 防抖的原理是当事件被触发后 计时器会被重置 如果在
  • 计算两个旋转矩形的交集——Python

    转自 https blog csdn net sda42342342423 article details 79746736 知识准备 cv2 rotatedRectangleIntersection rect1 rect2 计算两个旋转矩
  • 【C++】类和对象

    面向对象和面向过程 举个例子 淘宝这个软件 我要买一个东西 就应该有以下几步 上架商品 下单 送快递 收快递 评价 C语言关注的就是这个过程 而C 关注的更多是对象 平台 快递 用户 这就是面向对象 将上面繁琐的过程总结为三个对象 这样再来
  • Merkle树介绍

    默克尔树 Merkle树 又叫哈希树 是区块链数据存储运用到的一个重要的技术算法 简单来说 哈希树 默克尔树 中 每个节点都标有一个数据块的加密哈希值 哈希树可以用来验证任何一种在计算机中和计算机之间存储 处理和传输的数据 它们可以确保在点
  • linux ss命令详解

    ss 是 Socket Statistics 的缩写 ss 命令可以用来获取 socket 统计信息 它显示的内容和 netstat 类似 但 ss 的优势在于它能够显示更多更详细的有关 TCP 和连接状态的信息 而且比 netstat 更
  • DispatcherServlet是如何进行初始化的呢?

    转自 DispatcherServlet是如何进行初始化的呢 下文笔者讲述DispatcherServlet的初始化顺序 如下所示 Web容器启动时将调用HttpServletBean的init方法 public abstract clas
  • 蓝桥杯真题:乘积尾零

    题目描述 本题为填空题 只需要算出结果后 在代码中使用输出语句将所填结果输出即可 如下的 10 行数据 每行有 10 个整数 请你求出它们的乘积的末尾有多少个零 5650 4542 3554 473 946 4114 3871 9073 9
  • java 通过url取得文件返回InputStream类型数据的工具类

    通过url取得文件返回InputStream类型数据 author gugf public class HttpUtils 通过图片url返回图片Bitmap param url return public static InputStre
  • 基于RTMP实现Linux

    背景 Windows操作系统自问世以来 以其简单易用的图形化界面操作受到大众追捧 为计算机的普及 科技的发展做出了不可磨灭的功绩 也慢慢的成为人们最依赖的操作系统 在中国 90 以上的办公环境都是Windows 学校和各种培训班的培训内容也