public unsafe int RunVideo(int gap_h, int gap_w, int width, int height)
    {
        Produce_data p = new Produce_data();

        p.gap_h         = gap_h;
        p.gap_w         = gap_w;
        p.target_height = height;
        p.target_width  = width;
        IsRun           = true;
        exit_thread     = false;
        pause_thread    = false;
        Thread produce = new Thread(() => ProduceFrame(ref p));

        produce.Start();
        produce.IsBackground = true;
        return(0);
    }
예제 #2
0
        public unsafe int RunVideo(int gap_h, int gap_w, int width, int height, SDLHelper sdlVideo)  //这个是用来渲染整个大画面的
        {
            int          frame_count = 0;
            Produce_data p           = new Produce_data();

            fq              = new FrameQueue();
            p.gap_h         = gap_h;
            p.gap_w         = gap_w;
            p.target_height = height;
            p.target_width  = width;
            IsRun           = true;
            exit_thread     = false;
            pause_thread    = false;
            threadVideo     = Thread.CurrentThread;
            SDL.SDL_Event even    = new SDL.SDL_Event();
            Thread        refresh = new Thread(() => sfp_refresh_thread());
            Thread        produce = new Thread(() => ProduceFrame(ref p));

            refresh.Start();
            produce.Start();
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            try
            {
                for (; ;)
                {
                    //Wait
                    SDL.SDL_WaitEvent(out even);
                    if (even.type == SFM_REFRESH_EVENT)
                    {
                        FrameBuffer fb;
                        // 退出线程
                        if (exit_thread)
                        {
                            break;
                        }
                        // 暂停解析
                        if (pause_thread)
                        {
                            while (pause_thread)
                            {
                                Thread.Sleep(1);
                            }
                        }

                        while (true)
                        {
                            GetFrame(out fb);
                            if (fb == null)
                            {
                                Thread.Sleep(1);
                            }
                            else
                            {
                                fq.Pop();
                                break;
                            }
                            // Console.WriteLine("尚味获取到帧");
                        }
                        frame_count++;
                        //SDL播放YUV数据
                        //var data = fb.outbuffer;


                        int     out_buffer_size = fb.outbuffersize;
                        AVFrame pFrameYUV       = fb.av;
                        sdlVideo.SDL_Display(width * gap_w, height * gap_h, (IntPtr)(pFrameYUV.data[0]), out_buffer_size, pFrameYUV.linesize[0]);


                        //  Console.WriteLine("渲染第" + frame_count.ToString() + "帧");
                        if (frame_count == 1)
                        {
                            stopwatch.Start();
                        }
                        if (frame_count == 1000)
                        {
                            stopwatch.Stop();
                            TimeSpan timespan = stopwatch.Elapsed;
                            Console.WriteLine(timespan.TotalSeconds.ToString());
                            Thread.Sleep(100000);
                        }
                    }
                    else if (even.type == SDL.SDL_EventType.SDL_KEYDOWN)
                    {
                        //Pause
                        if (even.key.keysym.sym == SDL.SDL_Keycode.SDLK_SPACE)
                        {
                            thread_pause = 1 - thread_pause;
                        }
                    }
                    else if (even.type == SDL.SDL_EventType.SDL_QUIT)
                    {
                        thread_exit = 1;
                    }
                    else if (even.type == SFM_BREAK_EVENT)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
            }
            IsRun = false;
            return(0);
        }
예제 #3
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);
            }
        }
    }
예제 #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 = 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() + "帧");
        }
    }