Unity_利用Shader使YUV420p转为RGB,以此渲染出视频

 

由于项目需求,讨论如何做个播放器,能够实现流畅播放高码率高分辨率的视频。。。
    >>>因此决定从共享内存里入手,C++获取本地视频文件写到windows的共享内存

    >>>unity则从共享内存里读取YUV420p数据贴图到画面

本文只涉及到获取YUV420P数据后实现播放,至于这数据怎么来的以及相关C++的DLL不进行详细讨论,俺也不清楚

代码大致流程:初始化DLL,并开始从DLL获取数据,存进Queue,在FixedUpdate()取出Queue图像并贴图

Shader下载地址http://download.csdn.net/download/le_sam/9980147

相关Inspector如下:(把下载的Shander绑定到player)

Unity_利用Shader使YUV420p转为RGB,以此渲染出视频_第1张图片

 

 

public class Player : MonoBehaviour
{

        public static string SHARE_MEMORY_NAME = "user-defined";
        public static int SHARE_MEM_SIZE = "user-defined";
        private bool isRead = true;
        public Material mShareMaterial;
        private Texture2D texY, texU, texV;
        private Queue ListQueue = new Queue();
    private void Awake()
    {
        gameObject.GetComponent().sharedMaterial = mShareMaterial;
        shareMemRead();
    }
    private void shareMemRead()
    {
        //Application.targetFrameRate = AppFps;
        Sharemem.hLib = Sharemem.pisoft_share_mem_create();
        int ret = Sharemem.pisoft_share_mem_init(1, 0, SHARE_MEM_SIZE, SHARE_MEMORY_NAME, Sharemem.hLib);


        if (ret < 0)
        {


        }
        Debug.LogFormat("SHARE_MEM_SIZE:{0}", SHARE_MEM_SIZE);
        Debug.LogFormat("SHARE_MEMORY_NAME:{0}", SHARE_MEMORY_NAME);


        StartCoroutine(readFrames());
    }
    private IEnumerator readFrames()
    {
        int len = 0;
        int isVideo = 0;
        byte[] data = new byte[Width * Height * 3 / 2];


        //dataY = new byte[Width * Height];
        //dataU = new byte[Width * Height / 4];
        //dataV = new byte[Width * Height / 4];


        texY = new Texture2D(Width, Height, TextureFormat.Alpha8, false);
        texU = new Texture2D(Width / 2, Height / 2, TextureFormat.Alpha8, false);
        texV = new Texture2D(Width / 2, Height / 2, TextureFormat.Alpha8, false);


        //float lastTiem = Time.deltaTime;
        while (isRead)
        {
            yield return new WaitForEndOfFrame();
            if (Sharemem.pisoft_share_mem_is_exit(Sharemem.hLib) == 1)//quit
            {
                Debug.LogFormat("SharedMemory quit...");
                break;
            }
            //从dll里获取YUV420__byte[] 
            Sharemem.pisoft_share_mem_read(ref isVideo, ref len, data, Sharemem.hLib);
            if (len > 0)
            {
                len = 0;
                ListQueue.Enqueue(data);
                //Buffer.BlockCopy(data, 0, dataY, 0, Width * Height);
                //Buffer.BlockCopy(data, Width * Height, dataU, 0, Width * Height / 4);
                //Buffer.BlockCopy(data, Width * Height * 5 / 4, dataV, 0, Width * Height / 4);


            }
        }


        Sharemem.pisoft_share_mem_deinit(Sharemem.hLib);
    }
    void FixedUpdate() {


        if (ListQueue.Count > 0)
        {


            byte[] data = ListQueue.Dequeue();
            MemoryStream ms = new MemoryStream(data);
            BinaryReader reader = new BinaryReader(ms);


            byte[] dataY = reader.ReadBytes(Width * Height);
            byte[] dataU = reader.ReadBytes(Width * Height / 4);
            byte[] dataV = reader.ReadBytes(Width * Height / 4);
            StickTexture(Width, Height, dataY, dataU, dataV);
        }
    }

    private void StickTexture(int width, int height, byte[] dataY, byte[] dataU, byte[] dataV)
    {
        //if (width == mLastWidth && height == mLastHeight)
        //{
        //    return;
        //}


        //if (width == 0 || height == 0)
        //{
        //    return;
        //}


        //mLastWidth = width;
        //mLastHeight = height;


        //Color32[] grayColors = new Color32[width * height];
        //for (int i = 0; i < grayColors.Length; ++i)
        //{
        //    grayColors[i].a = 0;
        //}


        //Y
        //if (texY)
        //{
        //    Destroy(texY);
        //}


        //texY.filterMode = FilterMode.Bilinear;
        //texY.wrapMode = TextureWrapMode.Clamp;
        //texY.SetPixels32(grayColors);
        texY.LoadRawTextureData(dataY);
        texY.Apply();


        //grayColors = new Color32[(width / 2) * (height / 2)];
        //for (int i = 0; i < grayColors.Length; ++i)
        //{
        //    grayColors[i].a = 128;
        //}


        //U
        //if (texU)
        //{
        //    Destroy(texU);
        //}


        //texU.filterMode = FilterMode.Point;
        //texU.wrapMode = TextureWrapMode.Clamp;
        //texU.SetPixels32(grayColors);
        texU.LoadRawTextureData(dataU);
        texU.Apply();


        //V
        //if (texV)
        //{
        //    Destroy(texV);
        //}


        //texV.filterMode = FilterMode.Point;
        //texV.wrapMode = TextureWrapMode.Clamp;
        //texV.SetPixels32(grayColors);
        texV.LoadRawTextureData(dataV);
        texV.Apply();


        mShareMaterial.mainTexture = texY;
        mShareMaterial.SetTexture("_MainTexU", texU);
        mShareMaterial.SetTexture("_MainTexV", texV);
    }  

    void OnApplicationQuit()
    {
        isRead = false;
        StartCoroutine(DelayedStart());
        Debug.Log("app quit");
    }


    private IEnumerator DelayedStart()
    {
        yield return new WaitForSeconds(1f);
        Sharemem.pisoft_share_mem_set_exit(1, Sharemem.hLib);

    }
}
public class Sharemem : MonoBehaviour{ //Dll

    public static IntPtr hLib = new IntPtr(0);

    [DllImport("pisoft_share_mem")]
    public static extern IntPtr pisoft_share_mem_create();

    [DllImport("pisoft_share_mem")]
    public static extern int pisoft_share_mem_init(int is_read, int wait_ms, int mem_size, string name, IntPtr handle);

    [DllImport("pisoft_share_mem")]
    public static extern int pisoft_share_mem_deinit(IntPtr handle);

    [DllImport("pisoft_share_mem")]
    public static extern int pisoft_share_mem_read(ref int stream_type, ref int len, [MarshalAs(UnmanagedType.LPArray)] byte[] data, IntPtr handle);

    [DllImport("pisoft_share_mem")]
    public static extern int pisoft_share_mem_write(int is_video, int len, [MarshalAs(UnmanagedType.LPArray)] byte[] data, IntPtr handle);

    [DllImport("pisoft_share_mem")]
    public static extern int pisoft_share_mem_set_exit(int is_exit, IntPtr handle);

    [DllImport("pisoft_share_mem")]
    public static extern int pisoft_share_mem_is_exit(IntPtr handle);


}

 

 

 

 

 

你可能感兴趣的:(Unity,经验总结)