Unity环境下实现Camera高帧率RTMP推送

Unity下RTMP直播背景方面不再赘述,今天主要讨论的是,Unity环境下,如何实现Camera高帧率RTMP推送,这里提到的高帧率,不再局限于常规环境下的30帧,以VR头显为例,更高的帧率(比如50帧),体验会更好。

Android平台Unity推送Camera

Windows平台Unity推送Camera

之前,我们老早实现了Unity环境下的RTMP低延迟推送,原生环境下,比如windows下,可轻松实现50帧+的编码和RTMP推送(需要播放端也有高帧率播放的能力)。

好多开发者对这块比较感兴趣,今天分享几个点,权当抛砖引玉:

  1. 数据源:拿到期望的高帧率数据是基础,以Android或Windows的Unity环境为例,如果你想推50帧,起码camera能每秒读到超过50帧的数据,这个在好多开发者看来,可能觉得不是难事,实际你会发现,在复杂场景下,ReadPixel()耗时还是比较大的,特别是Android端;
  2. 数据读取和数据投递、编码等拆分,确保不至于因为数据投递、编码等,彼此相互影响;
  3. 针对横竖屏或camera分辨率实时变化的处理;
  4. 编码瓶颈:高帧率环境下,如果是windows还好,android端,编超过30帧,特别是分辨率比较大的话还是吃力的,这时候需要酌情考虑硬编或高效的软编方案,一般来说,建议H.264;
  5. 帧率控制:帧率控制这块,好多开发者可能会忽略,比如,我每秒需要编45帧,实际可以拿到60帧数据,如何用合理的算法处理数据,确保投递60帧数据,编码45帧(drop 15帧)的情况下,还能流畅无卡顿感,在设备无性能瓶颈的情况下,如何实现设置45帧,实际编码出来45帧数据;
  6. 音频方面:一般来说,常用的无非几种组合模式:麦克风、Unity内部音频、麦克风+unity内部音频混音或Unity下2路内部音频混音,麦克风的话,可以原生实现,然后直接调用即可,Unity内部音频可以通过AudioClip读取数据,编码的话,考虑到通用性,一般建议AAC;

Frame的构建,可以参考一下设计:

/*
* FrameTexture构建
* WebSite: https://github.com/daniulive/SmarterStreaming
*/
public class FrameTexture {public FrameTexture(Texture2D texture, int is_vertical_flip, int is_horizontal_flip, int scale_width, int scale_height) {texture_ = texture;is_vertical_flip_ = is_vertical_flip;is_horizontal_flip_ = is_horizontal_flip;scale_width_ = scale_width;scale_height_ = scale_height;}public Texture2D texture_ ;public int is_vertical_flip_ ;public int is_horizontal_flip_;public int scale_width_;public int scale_height_;
}

数据投递接口设计(Android):

/*** 投递层RGBA8888图像,如果不需要Aplpha通道的话, 请使用RGBX8888接口, 效率高** @param index: 层索引, 必须大于等于0, 注意:如果index是0的话,将忽略Alpha通道** @param left: 层叠加的左上角坐标, 对于第0层的话传0** @param top: 层叠加的左上角坐标, 对于第0层的话传0** @param rgba_plane: rgba 图像数据** @param offset: 图像偏移, 这个主要目的是用来做clip的, 一般传0** @param row_stride: stride information** @param width: width, 必须大于1, 如果是奇数, 将减1** @param height: height, 必须大于1, 如果是奇数, 将减1** @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转** @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转** @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放** @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放** @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢** @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序** @return {0} if successful*/public native int PostLayerImageRGBA8888ByteBuffer(long handle, int index, int left, int top,ByteBuffer rgba_plane, int offset, int row_stride, int width, int height,int is_vertical_flip,  int is_horizontal_flip,int scale_width,  int scale_height, int scale_filter_mode,int rotation_degree);/*** 投递层RGBA8888图像, 详细说明请参考PostLayerImageRGBA8888ByteBuffer** @return {0} if successful*/public native int PostLayerImageRGBA8888ByteArray(long handle, int index, int left, int top,byte[] rgba_plane, int offset, int row_stride, int width, int height,int is_vertical_flip,  int is_horizontal_flip,int scale_width,  int scale_height, int scale_filter_mode,int rotation_degree);

Windows的话,构建图层:

NT_PB_ExternalVideoFrameLayerConfig external_layer_c1 = new NT_PB_ExternalVideoFrameLayerConfig();external_layer_c1.base_.type_ = (Int32)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_EXTERNAL_VIDEO_FRAME;
external_layer_c1.base_.index_ = 0;
external_layer_c1.base_.enable_ = 1;
external_layer_c1.base_.region_.x_ = 0;
external_layer_c1.base_.region_.y_ = 0;
external_layer_c1.base_.region_.width_ = video_width_;
external_layer_c1.base_.region_.height_ = video_height_;external_layer_c1.base_.offset_ = Marshal.OffsetOf(external_layer_c1.GetType(), "base_").ToInt32();
external_layer_c1.base_.cb_size_ = (uint)Marshal.SizeOf(external_layer_c1);IntPtr external_layer_conf = Marshal.AllocHGlobal(Marshal.SizeOf(external_layer_c1));Marshal.StructureToPtr(external_layer_c1, external_layer_conf, true);UInt32 external_r = NTSmartPublisherSDK.NT_PB_AddLayerConfig(publisher_handle_, 0,external_layer_conf, (int)NTSmartPublisherDefine.NT_PB_E_LAYER_TYPE.NT_PB_E_LAYER_TYPE_EXTERNAL_VIDEO_FRAME,0, IntPtr.Zero);Marshal.FreeHGlobal(external_layer_conf);

然后通过NT_PB_PostLayerImage()给图层投递数据即可:

/** 给index层投递Image数据,目前主要是用来把rgb和yuv视频数据传给相关层* reserve: 保留字段,请传0* index: 层索引* image: 图像* flag: 请传0* pReserve: 保留字段,请传0* * 成功返回 NT_ERC_OK*/
[DllImport("SmartPublisherSDK", EntryPoint = "NT_PB_PostLayerImage", CallingConvention = CallingConvention.StdCall)]public static extern UInt32 NT_PB_PostLayerImage(IntPtr handle, Int32 reserve,Int32 index, IntPtr image,UInt32 flag, IntPtr pReserve);

以上是Unity环境下高帧率RTMP推送一点抛砖引玉的介绍,实际开发过程中,可能还需要考虑多实例、异常网络环境处理等各种情况,如果原生开发这块,有很好的积累,这块都不难。

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

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

相关文章

如何在Android平台GB28181接入终端实现语音广播和语音对讲

技术背景 在之前的blog,我们以Android平台国标接入终端为例,分别介绍了一些常规的功能,比如REGISTER、CATALOG、INVITE、Keepalive、SUBSCRIBE、NOTIFY等常规操作,今天主要介绍下语音广播和语音对讲这部分。 GB28181平台广播和对…

Android GB28181设备接入端语音广播和语音对讲技术实现探究

上篇文章提到Android端GB28181接入端的语音广播和语音对讲的实现,从spec角度大概介绍了下流程和简单的接口设计,好多开发者私信我,希望展开说一下。其实这块难度不大,只是广播和对讲涉及到双向实现,如果之前没有相关的…

Android native层实现MediaCodec编码H264/HEVC

Android平台在上层实现mediacodec的编码,资料泛滥,已经不再是难事,今天给大家介绍下,如何在Android native层实现MediaCodec编码H264/HEVC,网上千篇一律的接口说明,这里不再赘述,本文主要介绍下…

GB/T 28181联网系统通信协议结构和技术实现

技术回顾 在本文开头,我们先一起回顾下GB/T28181联网系统通信协议结构: 联网系统在进行视音频传输及控制时应建立两个传输通道:会话通道和媒体流通道。 会话通道用于在设备之间建立会话并传输系统控制命令;媒体流通道用于传输视…

Android平台GB28181设备接入端对接编码前后音视频源类型浅析

前言 今天主要对Android平台GB28181设备接入模块支持的接入数据类型,做个简单的汇总: 编码前数据(目前支持的有YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等数据类型),其中,Android平台前后摄像头数据&…

C++学习之-析构函数必须为虚函数吗?

今天讨论个比较有意思的话题:析构函数是不是必须要为虚函数? 先说答案: 析构函数可以是虚函数,也可以不是虚函数。 再说原因: 析构函数为虚函数的情况:继承 当父类指针释放子类对象时,如果…

如何实现RTMP或RTSP播放端回调YUV/RGB数据?

今天某乎收到个问题推荐,如何实现RTSP回调YUV数据,用于二次处理? 正好前些年我们做RTSP和RTMP直播播放的时候,实现过相关的需求,本文就以Android为例,大概说说具体实现吧。 先说回调yuv或rgb这块意义吧&a…

GB28181控制、传输流程和协议接口之注册|注销和技术实现

注册和注销基本要求 SIP客户端、网关、SIP设备、联网系统等 SIP代理(SIP UA)使用IETFRFC3261中定义的方法 15 GB/T28181—2016Register进行注册和注销。 注册和注销时应进行认证,认证方式应支持数字摘要认证方式,高安全级别的宜支持数字证书的认证方式&…

GB28181状态信息报送解读及Android端国标设备接入技术实现

今天主要聊聊GB/T28181状态信息报送这块,先回顾下协议规范相关细节,然后再针对代码实现,做个简单的说明。 状态消息报送基本要求 当源设备(包括网关、SIP设备、SIP客户端或联网系统)发现工作异常时,应立即向本 SIP监控域 的SIP服务器发送状…

GB28181设备接入端如何实现校时?

在探讨这个问题之前,我们先看看GB/T28181-2016官方文档怎么说的,9.10.1章节校时基本要求提到: 联网内设备支持基于SIP方式或 NTP方式的网络校时功能,标准时间为北京时间。 SIP方式校时见本节具体描述;NTP(见IETFRFC2…

如何在Unity下采集音视频实现轻量级RTSP服务(类似于IPC)

好多开发者在做虚拟仿真、VR教育等场景的时候,遇到个问题,想把头显里面的画面在内网环境下低延迟的同步出来,又不想单独部署流媒体服务器。为此,我们在Unity下,添加了轻量级RTSP服务模块,通过头显端启动个轻…

【Datawhale 大模型基础】第十一章 环境影响

第十一章 环境影响 This blog is based on datawhale files and a paper. The initial consideration revolves around the potential positive or negative direct impact on the environment. Other transformative technological advancements, like the metaverse, are li…

Android GB28181接入端实时位置订阅和上报之-如何获取当前经纬度

我们在做Android平台GB28181的时候,其中实时位置(MobilePosition)订阅和上报这块,涉及到实时经纬度的获取,特别是执法记录、车载系统的那个等场景,几乎就是标配。 今天主要是分享一段实时获取位置的代码: /** Camera…

如何实现Android平台GB28181设备对接Camera2数据

技术背景 在写如何实现Android平台GB28181设备对接Camera2数据说明之前,我在前两年的blog就有针对camera2的RTMP直播推送模块做过技术分享: 在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用…

Android平台GB28181设备接入端本地SIP端口被占用或屏蔽怎么办?

好多开发者或厂商,对Android平台GB28181接入模块的定位,大多是IPC国标流程打通模拟,基于这个目的,很难按照标准SPEC规范实现Android平台GB28181设备接入,我们在跟第三方国标平台厂商对接时发现,部分公司&am…

Android平台GB28181设备接入端如何实现本地录像?

实现Android平台GB28181设备接入的时候,有个功能点不可避免,那就是本地录像,实际上,在实现GB28181设备接入模块之前,我们前些年做RTMP推送和轻量级RTSP服务的时候,早已经实现了本地录像功能。 本地录像功能…

国网B接口注册(REGISTER)接口描述和消息示例

技术背景 电网视频监控系统是智能电网的一个重要组成部分,广泛应用于电网的建设、生产、运行、经营等方面。由于视频监控系统在不同的建设时期选用了不同的技术和不同厂家的产品,导致了标准不统一、技术路线不一致。目前国家电网公司智能电网建设&#…

国网B接口资源上报(Push_Resourse)接口描述和消息示例

上篇blog,梳理了国网B接口的REGISTER接口描述和消息示例,前端系统加电启动并初次注册成功后,向平台上报前端系统的设备资源信息(包括:视频服务器、DVR/DVS、摄像机、告警设备、环境量采集设备等模拟或数字信号采集设备…

Android平台GB28181设备接入端语音广播如何实现实时音量调节

Android平台GB28181设备接入,语音广播功能非常重要,本文要介绍的,不是语音广播的流程,语音广播流程,之前的blog也有非常详细的分享,感兴趣的可以参考官方规范书的交互流程: 语音广播这块&#x…

GB28181基于TCP协议的视音频媒体传输探究及实现

我们先看看官方规范针对TCP协议的视音频传输描述: 实时视频点播、历史视频回放与下载的 TCP媒体传输应支持基于RTP封装的视音频PS流,封装格式参照IETFRFC4571。 流媒体服务器宜同时支持作为TCP媒体流传输服务端和客户端。默认情况下,前端设…