安卓Unity3d 可以使用ReadPixels从当前Render Target读取图像,音频可以从AudioClip读取,具体调用GetData接口,读取到的可能是float类型,有些音频编码器可能需要sint16格式,这需要做一个转换。 读图像先用StartCoroutine创建协程,等待WaitForEndOfFrame, 之后调用ReadPixels就好,调用之前要创建一个和Camera一样的大小Texture2D, 创建代码如下:
Texture2D image_texture = new Texture2D(w, h, texture_format_, false);
启动停止协程,捕获图像代码如下:
// Github: https://github.com/daniulive/SmarterStreaming
// Copyright (C) 1130758427@qq.com
public class TestCameraCapture: MonoBehaviour
{
Coroutine coroutine_ = null;
void OnDisable()
{
coroutine_ = StartCoroutine(captureImage());
}
void OnEnable()
{
StopCoroutine(coroutine_);
coroutine_ = null;
}
IEnumerator captureImage()
{
yield return new WaitForEndOfFrame();
image_texture.ReadPixels(new Rect(0, 0, w, h), 0, 0, false);
// 编码图像
}
}
这个是Unity3D官方给出的代码:
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;
}
}
上面代码是读取图像后保存成PNG图片,只要把读取的纹理传给我写的C接口即可:
// Github: https://github.com/daniulive/SmarterStreaming
// Copyright (C) 1130758427@qq.com
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", 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);
}
private int postLayerImageRGBX8888Native(long handle, int index, int left, int top,
long rgbx_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>("OnPostLayerImageRGBX8888Native", handle, index, left, top,
rgbx_plane, offset, row_stride, width, height,
is_vertical_flip, is_horizontal_flip,
scale_width, scale_height, scale_filter_mode, rotation_degree);
}
读Camera和读Screen差不多,在我自己手机上硬编码视频可以跑到60帧,有些眼镜性能较弱,帧率稍微低些,不过基本都能满足需求, 实际开发中遇到不少问题,经验就是多看Unity3D官方文档,基本都能找到解决方案.