Unity实现Camera和Audio数据的低延迟RTMP推送技术探讨

Posted 音视频牛哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity实现Camera和Audio数据的低延迟RTMP推送技术探讨相关的知识,希望对你有一定的参考价值。

关于Unity实现RTMP直播推送技术方案,之前零散的写过几篇介绍,得到了好多开发者的关注。以android平台为例,目前视频这块,我们demo实现的是Camera数据的采集,然后编码投递到底层,如果设备没有性能瓶颈,可达到高帧率(60帧)均匀的RTMP推送效果。

视频采集这块,不再是难题,用ReadPixels从当前Render Target读取到图像数据即可,视频编码的话,我们分软编码、硬编码两块,硬编码,我们又实现了native层的硬编(5.0+以上版本),效率更高,native层我们做的可圈可点的一个地方是,armv7a也可以支持。

视频采集这块,需要考虑的是,如果场景分辨率发送变化,需要自动适配,帧与帧之间的连贯问题。

数据的采集,也可以参考官方给出来的示例:

using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
 
public class ExampleClass : MonoBehaviour

    // Take a shot immediately
    IEnumerator Start()
    
        UploadPNG();
        yield return null;
    
 
    IEnumerator UploadPNG()
    
        // We should only read the screen buffer after rendering is complete
        yield return new WaitForEndOfFrame();
 
        // Create a texture the size of the screen, RGB24 format
        int width = Screen.width;
        int height = Screen.height;
        Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
 
        // Read screen contents into the texture
        tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        tex.Apply();
 
        // Encode texture into PNG
        byte[] bytes = tex.EncodeToPNG();
        Destroy(tex);
 
        // For testing purposes, also write to a file in the project folder
        // File.WriteAllBytes(Application.dataPath + "/../SavedScreen.png", bytes);
 
 
        // Create a Web Form
        WWWForm form = new WWWForm();
        form.AddField("frameCount", Time.frameCount.ToString());
        form.AddBinaryData("fileUpload", bytes);
 
        // Upload to a cgi script
        var w = UnityWebRequest.Post("http://localhost/cgi-bin/env.cgi?post", form);
        yield return w.SendWebRequest();
        if (w.result != UnityWebRequest.Result.Success)
            print(w.error);
        else
            print("Finished Uploading Screenshot");
        yield return null;
    

有人说官方示例太简单,实际上官方示例,拿到数据,直接投递到底层即可,底层接口设计如下:


/*
 * Github: https://github.com/daniulive/SmarterStreaming
 */

private const String OnPostLayerImageRGBA8888Native_MethodName = "OnPostLayerImageRGBA8888Native";
        
        private int postLayerImageRGBA8888Native(long handle, int index, int left, int top,
                                            long 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)

            return obj_.Call<int>(OnPostLayerImageRGBA8888Native_MethodName, handle, index, left, top,
                rgba_plane, offset, row_stride, width, height,
                is_vertical_flip, is_horizontal_flip,
                scale_width, scale_height, scale_filter_mode, rotation_degree);
        

音频的话,我们支持了几种模式:

    /*定义Audio源选项*/
    public enum PB_AUDIO_OPTION : uint
    
        AUDIO_OPTION_CAPTURE_MIC = 0x0,             /*采集麦克风音频*/
        AUDIO_OPTION_EXTERNAL_PCM_DATA = 0x1,       /*外部PCM数据*/
        AUDIO_OPTION_MIC_EXTERNAL_PCM_MIXER = 0x2,  /*麦克风+外部PCM数据混音*/
        AUDIO_OPTION_TWO_EXTERNAL_PCM_MIXER = 0x3,  /* 两路外部PCM数据混音*/
    

分别是采集麦克风、外部PCM、麦克风和外部PCM混音、两路外部PCM的混音,几种模式。

麦克风的数据采集,我们是直接基于原生的Android,通过Unity调用Android实现数据采集推送,外部PCM数据,我们以AudioClip为例,读取到数据,每隔10ms传下去,两路外部PCM也就是两路AudioClip数据投递,JNI层做混音。麦克风和外部PCM数据混音,实际上是为了达到类似授课或者讲解过程中,自带背景音的效果,需要注意的是,AudioClip读到的是float类型的数据,有些音频编码器需要sint16格式,也可以在上层或者底层做下转换。

音频这块,如果是读取文件,还需要考虑的是,如果audio source读过之后,是从头读,还是后面静音?当然不管哪种实现都不难。

数据有了,实现RTMP推送这块,小菜一碟了,由于我们有多年的RTMP推送方面的技术积累,对我们来说,无非就是多一种类型的数据源而已。

经过实际测试,配合我们自研的RTMP播放器,轻松实现超过50帧的RTMP毫秒级延迟的体验,足够应对大多数行业场景了。

HDFS,Hadoop中的低延迟数据访问

【中文标题】HDFS,Hadoop中的低延迟数据访问【英文标题】:Low Latency data access in HDFS ,Hadoop 【发布时间】:2017-09-22 05:47:46 【问题描述】:

我正在阅读有关大数据和 Hadoop 的教程,我在 HDFS 上找到了这两点

流式数据访问:读取整个数据集的时间比读取第一个数据集的延迟更重要。 HDFS 建立在一次写入和多次读取的模式之上。

&

低延迟数据访问:访问第一个数据所需时间非常短的应用程序不应使用 HDFS,因为它更重视整个数据而不是获取第一个记录的时间。

我很困惑,因为第一个说读取整个数据集的时间更重要,第二个说...不应该使用 HDFS,因为它重视整个数据

我不明白预期是什么?我是 Hadoop 新手。

【问题讨论】:

【参考方案1】:

流式数据访问:

HDFS 基于“一次写入,多次读取”的原则。 主要关注点是以尽可能快的方式读取完整的数据集,这比花时间从数据集中获取单个记录更重要。

根据 Hadoop:权威指南

MapReduce 本质上是一个批处理系统,不适合交互式分析。您无法在几秒钟或更短的时间内运行查询并获得结果。查询通常需要几分钟或更长时间,因此最适合离线使用,因为没有人坐在处理循环中等待结果。

MapReduce 非常适合需要以批处理方式分析整个数据集的问题。 RDBMS 适用于点查询或更新,其中数据集已被索引以提供相对少量数据的低延迟检索和更新时间。 MapReduce 适用于数据写入一次多次读取的应用程序,而关系数据库则适用于不断更新的数据集。

延迟:请参考下面这个What is low latency access of data?

【讨论】:

以上是关于Unity实现Camera和Audio数据的低延迟RTMP推送技术探讨的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D Camera透视相机到正交相机插值

Linux 上的低延迟串行通信

HDFS,Hadoop中的低延迟数据访问

Windows平台Unity Camera场景实现轻量级RTSP服务和RTMP推送

Unity的延迟渲染(一)

反应原生:上传 apk 后,Play 商店有权限问题(CAMERA,RECORD_AUDIO,...)