Unity 解析视频流数据

首先在AndroidStudio中将数据转换为yuv图片数据,然后传到Unity,Unity解析Yuv图片数据并显示

MediaCodec mCodec = MediaCodec.createDecoderByType("video/avc");
final MediaFormat mediaformat = MediaFormat.createVideoFormat("video/avc", VIDEO_WIDTH, VIDEO_HEIGHT);
mediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
mCodec.configure(mediaformat, null,null, 0);

初始化MediaCodec,然后启动一个线程获取数据,保证数据是一帧的完整数据

然后调用queueInputBuffer,把数据传给MediaCodec。

MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
long timeoutUs = 1000;
int outIndex = mCodec.dequeueOutputBuffer(info, timeoutUs);

if (outIndex >= 0) {
    Image image = mCodec.getOutputImage(outIndex);
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    ByteBuffer buffer1 = image.getPlanes()[1].getBuffer();
    byte[] arr = new byte[buffer.remaining()];
    byte[] arr1 = new byte[buffer1.remaining()];

    buffer.get(arr);
    buffer1.get(arr1);
    image.close();
    mCodec.releaseOutputBuffer(outIndex, 0);
    _callBack.JavaObjectCallBack(new _byteArrydata(arr, arr1));
}

获取MediaCodec输出数据,获取输出Image,Image有3个plane,存放了Yuv的数据,根据不同格式解析不一样。

我这里第二个和第三个plane数据是相同的,只是有一个错位,就是uv数据交叉储存的。所有直需要传给Unity2个数据

  Texture2D texture_image = new Texture2D(1920, 1080, TextureFormat.Alpha8, false);
  Texture2D  texture_imageuv = new Texture2D(1920 / 2, 1080 / 2, TextureFormat.RGBA4444, false);

Unity获取到数据,初始化两个Texture2D,Y的图片的尺寸就是屏幕尺寸,uv的是它的1/4.

Y的数据是一个byte储存一个像素,uv数据是两个byte储存一个像素。

然后通过LoadRawTextureData加载数据,然后把图片赋值给材质球。

需要在shader中解析两张图片,获取到yuv分别的值,然后在转成rgb,显示

    half2 uv = i.uv;

                uv.y = 1 - uv.y;

                fixed4 color1 = tex2D(_MainTex, uv);

                fixed4 color2 = tex2D(_MainTexUV, uv);

                float y = 1.1643 * (color1.a - 0.0625);
                float u = (color2.r * 15 * 16 + color2.g * 15) / 255 - 0.5;
                float v = (color2.b * 15 * 16 + color2.a * 15) / 255 - 0.5;

                float r = y + 1.403 * v;
                float g = y - 0.344  * u - 0.714 * v;
                float b = y + 1.770  * u;

                return float4(b, g, r, 1);

因为没去理解具体的计算,所以我只是在网上找了一个计算公式,但是最后结果通过rgb显示不对,所以我改成了bgr。uv要改一下,因为图片是反的。

发布了31 篇原创文章 · 获赞 2 · 访问量 2793

猜你喜欢

转载自blog.csdn.net/BDDNH/article/details/99594155