Unity下RTMP直播背景方面不再赘述,今天主要讨论的是,Unity环境下,如何实现Camera高帧率RTMP推送,这里提到的高帧率,不再局限于常规环境下的30帧,以VR头显为例,更高的帧率(比如50帧),体验会更好。
Android平台Unity推送Camera
Windows平台Unity推送Camera
之前,我们老早实现了Unity环境下的RTMP低延迟推送,原生环境下,比如windows下,可轻松实现50帧+的编码和RTMP推送(需要播放端也有高帧率播放的能力)。
好多开发者对这块比较感兴趣,今天分享几个点,权当抛砖引玉:
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推送一点抛砖引玉的介绍,实际开发过程中,可能还需要考虑多实例、异常网络环境处理等各种情况,如果原生开发这块,有很好的积累,这块都不难。