示例#1
0
    public void OnI420RemoteFrameReady(int id,
                                       IntPtr dataY, IntPtr dataU, IntPtr dataV, IntPtr dataA,
                                       int strideY, int strideU, int strideV, int strideA,
                                       uint width, uint height)
    {
        /* if (  (++sFrameCount % 25) == 0)
         * {
         *   Debug.Log("OnI420RemoteFrameReady clientID" +  id);
         * }
         */

        //Debug.Log("OnI420RemoteFrameReady called! w=" + width + " h=" + height + " thread:" + Thread.CurrentThread.ManagedThreadId);

        //Debug.Log("OnI420RemoteFrameReady called! w=" + width + " h=" + height + " thread:" + Thread.CurrentThread.ManagedThreadId);
        FramePacket packet = frameQueueRemote.GetDataBufferWithoutContents((int)(width * height * 4));

        if (packet == null)
        {
            Debug.LogError("OnI420RemoteFrameReady: FramePacket is null!");
            return;
        }
        CopyYuvToBuffer(dataY, dataU, dataV, strideY, strideU, strideV, width, height, packet.Buffer);
        packet.width  = (int)width;
        packet.height = (int)height;
        frameQueueRemote.Push(packet);
    }
示例#2
0
        private void Peer_RemoteI420FrameReady(IntPtr dataY, IntPtr dataU, IntPtr dataV, IntPtr dataA, int strideY, int strideU, int strideV, int strideA, uint width, uint height)
        {
            FramePacket packet = remoteFrameQueue.GetDataBufferWithoutContents((int)(width * height * 4));

            if (packet == null)
            {
                return;
            }
            CopyYuvToBuffer(dataY, dataU, dataV, strideY, strideU, strideV, width, height, packet.Buffer);
            packet.width  = (int)width;
            packet.height = (int)height;
            remoteFrameQueue.Push(packet);
        }
    public void OnI420LocalFrameReady(int id,
                                      IntPtr dataY, IntPtr dataU, IntPtr dataV, IntPtr dataA,
                                      int strideY, int strideU, int strideV, int strideA,
                                      uint width, uint height)
    {
        //Debug.Log("OnI420LocalFrameReady called! w=" + width + " h=" + height+" thread:"+ Thread.CurrentThread.ManagedThreadId + ":" + Thread.CurrentThread.Name);
        FramePacket packet = frameQueueLocal.GetDataBufferWithoutContents((int)(width * height * 4));

        if (packet == null)
        {
            //Debug.LogError("OnI420LocalFrameReady: FramePacket is null!");
            return;
        }
        CopyYuvToBuffer(dataY, dataU, dataV, strideY, strideU, strideV, width, height, packet.Buffer);
        packet.width  = (int)width;
        packet.height = (int)height;
        frameQueueLocal.Push(packet);
    }
示例#4
0
    public void             OnPixels(byte[] Pixels, Vector2 Size, int Channels)
    {
        var Frame = new PixelFrame();

        Frame.Pixels   = Pixels;
        Frame.Size     = Size;
        Frame.Channels = Channels;
        Frame.Rgb      = true;

        var TimeSinceLastSend = Time_time - LastSendTime;

        if (TimeSinceLastSend < SendDelayMs)
        {
            return;
        }

        JpegQueue.Push(Frame);
        LastSendTime = Time_time;
    }
示例#5
0
        //当前线程获取tile数量,以及具体tile的位置
        public unsafe void ProduceFrame(ref Produce_data p)   //不停的往队列里添加帧,到时间就自动切换
        {
            //初始创建一批decoder

            int height = p.target_height;
            int width  = p.target_width;
            int gap_h  = p.gap_h;
            int gap_w  = p.gap_w;

            int tileNumber = gap_w * gap_h;

            tileNumber = tileNumber + 1;
            //暂时这么写
            int i, j;

            Tile [] tile = new Tile[72]; //暂时使用方格
            for (i = 0; i < gap_h; i++)
            {
                for (j = 0; j < gap_w; j++)
                {
                    tile[i * gap_w + j + 1] = new Tile(j * width, i * height, j * width + width, i * height + height);
                }
            }
            tile[0] = new Tile(0, 0, 2880, 1440);
            //tile[0] = new Tile(0, 0, 480, 480);
            //tile[1] = new Tile(0, 480, 480,960);


            int T = 0;  //每隔30帧重新启动decoder

            AVFrame * [] pDstFrameBuffer = new AVFrame *[3];
            byte * []    distBuffer      = new byte *[3];

            for (i = 0; i < 3; i++)
            {
                AVFrame *ptempDstFrame;
                int      target_width = width, target_height = height;
                int      nDstSize = ffmpeg.avpicture_get_size(AVPixelFormat.AV_PIX_FMT_YUV420P, target_width * gap_w, target_height * gap_h);
                byte[]   buf      = new byte[nDstSize];
                fixed(byte *dsttempbuf = buf)
                {
                    ptempDstFrame = ffmpeg.av_frame_alloc();
                    ffmpeg.avpicture_fill((AVPicture *)ptempDstFrame, dsttempbuf, AVPixelFormat.AV_PIX_FMT_YUV420P, target_width * gap_w, target_height * gap_h);
                    ptempDstFrame->width  = target_width * gap_w;
                    ptempDstFrame->height = target_height * gap_h;
                    ptempDstFrame->format = (int)AVPixelFormat.AV_PIX_FMT_YUV420P;
                    memset(ptempDstFrame->data[0], 0, (uint)(target_height * target_width * gap_w * gap_h));
                    memset(ptempDstFrame->data[1], 0x80, (uint)(target_height * target_width * gap_w * gap_h / 4));
                    memset(ptempDstFrame->data[2], 0x80, (uint)(target_height * target_width * gap_w * gap_h / 4));
                    pDstFrameBuffer[i] = ptempDstFrame;
                    distBuffer[i]      = dsttempbuf;
                }
            }

            for (i = 0; i < tileNumber; i++)
            {
                semaphore[i] = new Semaphore(0, 1);
            }
            while (true)  //不停的向前进行decode,每一次循环产生一帧
            {
                FrameBuffer fb;
                AVFrame *   tempFrame;
                //如果当前已经解完了就换个文件读,重新给decoder赋予新的文件名
                T = T + 1;
                if (T % (changeFrame - 1) == 1)
                {
                    //每隔30帧自动的去更换一个文件去读
                    //v.clear();
                    //这里要获取新的tilenumber和tile方式
                    //
                    //this_thread::sleep_for(chrono::milliseconds(500));
                    T = 1;
                    for (i = 0; i < tileNumber; i++)
                    {
                        isTrue[i] = false;
                        string temp1;
                        if (i == 0)
                        {
                            temp1 = "base.mp4"; // i.ToString()+".mp4";
                            //temp1 = i.ToString() + ".mp4";
                            //temp1 = "0.mp4";
                        }
                        else
                        {
                            // temp1 = i.ToString() + ".mp4";
                            temp1 = "0.mp4";
                        }


                        int    tn = i;
                        Thread t  = new Thread(() => Decoder(temp1, tn));
                        t.Start();
                    }

                    //重新启动一堆解码器
                }
                tempFrame = pDstFrameBuffer[(T - 1) % 3];
                //告诉所有decoder可以进行解码了

                for (i = 0; i < tileNumber; i++)
                {
                    isTrue[i] = true;  //当所有Istrue都是false 的时候代表所有块都已经渲染完了
                    semaphore[i].Release();
                }

                //第一帧让他渲染,渲染完之后他进入等待,等我放入队列后,再让他继续走!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //
                int pass = 1;
                while (true)
                {
                    pass = 1;
                    for (i = 0; i < tileNumber; i++)
                    {
                        if (isTrue[i] == true)
                        {
                            pass = 0;
                        }
                    }
                    if (pass == 1)
                    {
                        break;
                    }

                    Thread.Sleep(1);
                }

                //渲染完了就进行拼接,update函数其实是拼接函数

                Update_Tile(tempFrame, ref cur, ref tile, tileNumber, width * gap_w, height * gap_h);
                fb           = new FrameBuffer();
                fb.av        = *tempFrame;
                fb.outbuffer = distBuffer[(T - 1) % 3];
                //完成拼接放入队列
                while (true)
                {
                    if (fq.Push(ref fb) == 1)  //代表成功放入队列了
                    {
                        break;
                    }
                    Thread.Sleep(1);
                }

                //Console.WriteLine("拼接第" + T.ToString() + "帧");
            }
        }
    public unsafe void ProduceFrame(ref Produce_data p)
    {
        //decoder

        int height = p.target_height;
        int width  = p.target_width;
        int gap_h  = p.gap_h;
        int gap_w  = p.gap_w;

        int tileNumber = 1;

        int i, j;



        int T = 0;  //decoder

        AVFrame[] pDstFrameBuffer = new AVFrame[3];
        byte *[]  distBuffer      = new byte *[3];
        AVFrame * ptempDstFrame;
        int       target_width = width, target_height = height;
        int       nDstSize = ffmpeg.avpicture_get_size(AVPixelFormat.AV_PIX_FMT_YUV420P, target_width * gap_w, target_height * gap_h);

        byte[] buf;

        show_flag = 1;
        for (i = 0; i < 3; i++)
        {
            buf = new byte[nDstSize];
            //fixed (byte* dsttempbuf = buf)
            {
                IntPtr dsttempbuf = Marshal.AllocHGlobal(buf.Length);
                Marshal.Copy(buf, 0, dsttempbuf, buf.Length);
                ptempDstFrame = ffmpeg.av_frame_alloc();
                ffmpeg.avpicture_fill((AVPicture *)ptempDstFrame, (byte *)dsttempbuf, AVPixelFormat.AV_PIX_FMT_YUV420P, target_width * gap_w, target_height * gap_h);
                ptempDstFrame->width  = target_width * gap_w;
                ptempDstFrame->height = target_height * gap_h;
                ptempDstFrame->format = (int)AVPixelFormat.AV_PIX_FMT_YUV420P;
                memset(ptempDstFrame->data[0], 0, (uint)(target_height * target_width * gap_w * gap_h));
                memset(ptempDstFrame->data[1], 0x80, (uint)(target_height * target_width * gap_w * gap_h / 4));
                memset(ptempDstFrame->data[2], 0x80, (uint)(target_height * target_width * gap_w * gap_h / 4));
                pDstFrameBuffer[i] = *ptempDstFrame;
                distBuffer[i]      = (byte *)dsttempbuf;
            }
        }

        FrameBuffer fb;
        AVFrame     tempFrame;
        int         pts = 0;

        while (true)
        {
            T = T + 1;
            Debug.Log("开始拼接第" + T.ToString() + "帧");
            if (T % changeFrame == 1)
            {
                T = 1;
                int       videoid = 6;
                int       offset  = 70;
                string    path    = currentPath + "/StreamingAssets/" + videoid + "" + "_trace/VRJND/" + "" + (int)(pts + offset) + "" + ".txt";
                String [] lines   = File.ReadAllLines(path, Encoding.Default);
                tileNumber = lines.Length + 1;
                for (i = 0; i < tileNumber; i++)
                {
                    semaphore[i] = new Semaphore(0, 1);
                }
                for (i = 0; i < tileNumber; i++)
                {
                    if (i == 0)
                    {
                        tile[i]    = new Tile(0, 0, 2879, 1439);
                        tileIdx[i] = 0;
                        qp[i]      = 42;
                    }
                    else
                    {
                        string[] temp = lines[i - 1].Split(' ');
                        tile[i]    = new Tile(int.Parse(temp[2]), int.Parse(temp[1]), int.Parse(temp[4]) + 120 - 1, int.Parse(temp[3]) + 120 - 1);
                        tileIdx[i] = int.Parse(temp[0]);
                        qp[i]      = ((int)((int.Parse(temp[5]) - 22) / 5)) * 5 + 22;
                    }
                }
                for (i = 0; i < tileNumber; i++)
                {
                    isTrue[i] = false;
                    string filepath;
                    filepath = currentPath + "/StreamingAssets/" + videoid + "" + "_seg/" + (int)(pts + offset) + "" + "/" + tileIdx[i] + "" + "_" + qp[i] + "" + ".mp4";
                    string temp1 = filepath;// i.ToString()+".mp4";
                    int    tn    = i;
                    Thread t     = new Thread(() => Decoder(temp1, tn));
                    t.Start();
                    t.IsBackground = true;
                }
                pts = pts + 1;
            }
            tempFrame = pDstFrameBuffer[(T - 1) % 3];


            for (i = 0; i < tileNumber; i++)
            {
                isTrue[i] = true;
                semaphore[i].Release();
            }

            int pass = 1;
            while (true)
            {
                pass = 1;
                for (i = 0; i < tileNumber; i++)
                {
                    if (isTrue[i] == true)
                    {
                        pass = 0;
                    }
                }
                if (pass == 1)
                {
                    break;
                }
                Thread.Sleep(1);
            }


            Update_Tile(ref tempFrame, cur, tile, tileNumber, width * gap_w, height * gap_h);
            fb    = new FrameBuffer();
            fb.av = tempFrame;

            while (true)
            {
                if (fq.Push(ref fb) == 1)
                {
                    break;
                }
                Thread.Sleep(1);
            }
        }
    }
示例#7
0
    //当前线程获取tile数量,以及具体tile的位置
    public unsafe void ProduceFrame(ref Produce_data p)   //不停的往队列里添加帧,到时间就自动切换
    {
        //初始创建一批decoder

        int height = p.target_height;
        int width  = p.target_width;
        int gap_h  = p.gap_h;
        int gap_w  = p.gap_w;

        int tileNumber = 1;
        //暂时这么写
        int i, j;

        Debug.Log("启动帧生成!");

        int T = 0;  //每隔30帧重新启动decoder

        AVFrame[] pDstFrameBuffer = new AVFrame[3];
        byte *[]  distBuffer      = new byte *[3];
        AVFrame * ptempDstFrame;
        int       target_width = width, target_height = height;
        int       nDstSize = ffmpeg.avpicture_get_size(AVPixelFormat.AV_PIX_FMT_YUV420P, target_width * gap_w, target_height * gap_h);

        byte[] buf;

        show_flag = 1;
        for (i = 0; i < 3; i++)
        {
            buf = new byte[nDstSize];
            //fixed (byte* dsttempbuf = buf)
            {
                IntPtr dsttempbuf = Marshal.AllocHGlobal(buf.Length);
                Marshal.Copy(buf, 0, dsttempbuf, buf.Length);
                ptempDstFrame = ffmpeg.av_frame_alloc();
                ffmpeg.avpicture_fill((AVPicture *)ptempDstFrame, (byte *)dsttempbuf, AVPixelFormat.AV_PIX_FMT_YUV420P, target_width * gap_w, target_height * gap_h);
                ptempDstFrame->width  = target_width * gap_w;
                ptempDstFrame->height = target_height * gap_h;
                ptempDstFrame->format = (int)AVPixelFormat.AV_PIX_FMT_YUV420P;
                memset(ptempDstFrame->data[0], 0, (uint)(target_height * target_width * gap_w * gap_h));
                memset(ptempDstFrame->data[1], 0x80, (uint)(target_height * target_width * gap_w * gap_h / 4));
                memset(ptempDstFrame->data[2], 0x80, (uint)(target_height * target_width * gap_w * gap_h / 4));
                pDstFrameBuffer[i] = *ptempDstFrame;
                distBuffer[i]      = (byte *)dsttempbuf;
            }
        }

        FrameBuffer fb;
        AVFrame     tempFrame;
        int         pts = 0;

        while (true)  //不停的向前进行decode,每一次循环产生一帧
        {
            //如果当前已经解完了就换个文件读,重新给decoder赋予新的文件名
            T = T + 1;
            Debug.Log("拼接第" + T.ToString() + "帧");
            if (T % (changeFrame - 1) == 1)
            {
                //每隔30帧自动的去更换一个文件去读
                //v.clear();
                //这里要获取新的tilenumber和tile方式
                //0号tile是背景tile,其他1-X号是中间的
                //segment命名方式为 秒数_tile_Qp
                T = 1;
                int       videoid = 6;
                int       offset  = 70;
                string    path    = currentPath + "/StreamingAssets/" + videoid + "" + "_trace/VRJND/" + "" + (int)(pts + offset) + "" + ".txt";
                String [] lines   = File.ReadAllLines(path, Encoding.Default);
                tileNumber = lines.Length + 1;
                for (i = 0; i < tileNumber; i++)
                {
                    semaphore[i] = new Semaphore(0, 1);
                }
                for (i = 0; i < tileNumber; i++)
                {
                    if (i == 0)
                    {
                        tile[i]    = new Tile(0, 0, 2879, 1439);
                        tileIdx[i] = 0;
                        qp[i]      = 42;
                    }
                    else
                    {
                        string[] temp = lines[i - 1].Split(' ');
                        tile[i]    = new Tile(int.Parse(temp[2]), int.Parse(temp[1]), int.Parse(temp[4]) + 120 - 1, int.Parse(temp[3]) + 120 - 1);
                        tileIdx[i] = int.Parse(temp[0]);
                        qp[i]      = ((int)((int.Parse(temp[5]) - 22) / 5)) * 5 + 22;
                    }
                }
                for (i = 0; i < tileNumber; i++)
                {
                    isTrue[i] = false;
                    string filepath;
                    filepath = currentPath + "/StreamingAssets/" + videoid + "" + "_seg/" + (int)(pts + offset) + "" + "/" + tileIdx[i] + "" + "_" + qp[i] + "" + ".mp4";
                    string temp1 = filepath;// i.ToString()+".mp4";
                    int    tn    = i;
                    Thread t     = new Thread(() => Decoder(temp1, tn));
                    t.Start();
                    t.IsBackground = true;
                }
                pts = pts + 1;
                //重新启动一堆解码器
            }
            tempFrame = pDstFrameBuffer[(T - 1) % 3];

            //告诉所有decoder可以进行解码了
            for (i = 0; i < tileNumber; i++)
            {
                isTrue[i] = true;  //当所有Istrue都是false 的时候代表所有块都已经渲染完了
                semaphore[i].Release();
            }
            //第一帧让他渲染,渲染完之后他进入等待,等我放入队列后,再让他继续走!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //
            int pass = 1;
            while (true)
            {
                pass = 1;
                for (i = 0; i < tileNumber; i++)
                {
                    if (isTrue[i] == true)
                    {
                        pass = 0;
                    }
                }
                if (pass == 1)
                {
                    break;
                }

                Thread.Sleep(10);
            }

            //渲染完了就进行拼接,update函数其实是拼接函数
            Update_Tile(ref tempFrame, cur, tile, tileNumber, width * gap_w, height * gap_h);
            fb    = new FrameBuffer();
            fb.av = tempFrame;
            //完成拼接放入队列
            while (true)
            {
                if (fq.Push(ref fb) == 1)  //代表成功放入队列了
                {
                    break;
                }
                Thread.Sleep(10);
            }
            //Debug.Log("拼接第" + T.ToString() + "帧");
        }
    }