使用 h264 解码 得到的 一般是 yuv420 格式的数据
我解码 1920*1080分辨率 的 h264 得到的数据格式如下
Y[0,1,2,...,1920*1080-1] UV[0,1,1920*1080/2-1]
使用 unity 的shader 进行渲染 定义了 两个 TEX
一个用来 保存 Y 变量 一个 用来 保存 uv 变量
Shader "Custom/YUV420ToRGB"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
//_UTex ("U", 2D) = "white" {}
//_VTex ("V", 2D) = "white" {}
_UVTex("U", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
//sampler2D _UTex;
//sampler2D _VTex;
sampler2D _UVTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//如果需要翻转画面,把下面的 进行对应的 1- 即可,例如(翻转左右则 1- i.uv.x)
fixed2 uv = fixed2(i.uv.x, i.uv.y);
fixed4 ycol = tex2D(_MainTex, uv);
//fixed4 ucol = tex2D(_UTex, uv);
//fixed4 vcol = tex2D(_VTex, uv);
fixed4 uvcol = tex2D(_UVTex, uv);
//如果是使用 Alpha8 的纹理格式写入各分量的值,各分量的值就可以直接取a通道的值
//float r = ycol.a + 1.4022 * vcol.a - 0.7011;
//float g = ycol.a - 0.3456 * ucol.a - 0.7145 * vcol.a + 0.53005;
//float b = ycol.a + 1.771 * ucol.a - 0.8855;
float r = ycol.a + 1.4022 * uvcol.g - 0.7011;
float g = ycol.a - 0.3456 * uvcol.r - 0.7145 * uvcol.g + 0.53005;
float b = ycol.a + 1.771 * uvcol.r - 0.8855;
return fixed4(r,g,b,1);
}
ENDCG
}
}
FallBack "diffuse"
}
添加更新 tex 数据的函数 在 update 定时调用 YUV420ToRGB 代码如下 如下
using UnityEngine;
/// <summary>
/// 把 YUV byte[] 转为 RGB 格式的封装类
/// </summary>
public static class YUV420ToRGBWrapper
{
static Texture2D texY = new Texture2D(1920, 1080, TextureFormat.Alpha8, false);
static Texture2D texUV = new Texture2D(1920 >> 1, 1080 >> 1, TextureFormat.RG16, false);
/// <summary>
/// YUV 转为 RGB 的对外接口
/// </summary>
/// <param name="dataY">数据流</param>
/// <param name="dataUV">数据流</param>
/// <param name="width">yuv 宽</param>
/// <param name="height">yuv 高</param>
/// <param name="renderer">要渲染的 Renderer</param>
public static void YUV420ToRGB(byte[] dataY, byte[] dataUV, Renderer renderer)
{
// 把数据下载到对应 YUV 贴图中
texY.LoadRawTextureData(dataY);
texUV.LoadRawTextureData(dataUV);
texY.Apply();
texUV.Apply();
// 把 YUV 贴图中 数据传给 shader 进行 RGB 解析显示
renderer.sharedMaterial.SetTexture("_MainTex", texY);
renderer.sharedMaterial.SetTexture("_UVTex", texUV);
}
}