Ejemplo n.º 1
0
        public string CloseAndGetOutput()
        {
            // Terminate the subthreads.
            _terminate = true;

            _copyPing.Set();
            _pipePing.Set();

            _copyThread.Join();
            _pipeThread.Join();

            // Close FFmpeg subprocess.
            _subprocess.StandardInput.Close();
            _subprocess.WaitForExit();

            var outputReader = _subprocess.StandardError;
            var error        = outputReader.ReadToEnd();

            _subprocess.Close();
            _subprocess.Dispose();

            outputReader.Close();
            outputReader.Dispose();

            // Nullify members (just for ease of debugging).
            _subprocess = null;
            _copyThread = null;
            _pipeThread = null;
            _copyQueue  = null;
            _pipeQueue  = _freeBuffer = null;

            //Kill server
            RTSPServerLoader.GetInstance().Kill();

            return(error);
        }
Ejemplo n.º 2
0
        protected void PushToPipe(Texture texture, string url, int width, int height)
        {
            RTSPServerLoader loader = RTSPServerLoader.GetInstance();

            if (!loader.CoroutineStarted)
            {
                StartCoroutine(loader.WaitForServerToStart());
            }
            // Lazy initialization
            if (_session == null && loader.RTSPServerloaded)
            {
                Debug.Log("Creating Session: " + url);
                // Give a newly created temporary render texture to the camera
                // if it's set to render to a screen. Also create a blitter
                // object to keep frames presented on the screen.
                if (texture == null)
                {
                    Debug.LogError("Texture is null");
                }

                // Start an FFmpeg session.
                _session = FFmpegSession.Create(
                    url,
                    width,
                    height,
                    _frameRate, preset,
                    _crfValue,
                    _maxBitrate
                    );

                _startTime      = Time.time;
                _frameCount     = 0;
                _frameDropCount = 0;
            }

            if (_session == null)
            {
                return;
            }

            var gap   = Time.time - FrameTime;
            var delta = 1 / _frameRate;

            if (gap < 0)
            {
                // Update without frame data.
                _session.PushFrame(null);
            }
            else if (gap < delta)
            {
                // Single-frame behind from the current time:
                // Push the current frame to FFmpeg.
                _session.PushFrame(texture);
                _frameCount++;
            }
            else if (gap < delta * 2)
            {
                // Two-frame behind from the current time:
                // Push the current frame twice to FFmpeg. Actually this is not
                // an efficient way to catch up. We should think about
                // implementing frame duplication in a more proper way. #fixme
                _session.PushFrame(texture);
                _session.PushFrame(texture);
                _frameCount += 2;
            }
            else
            {
                // Show a warning message about the situation.
                WarnFrameDrop();

                // Push the current frame to FFmpeg.
                _session.PushFrame(texture);

                // Compensate the time delay.
                _frameCount += Mathf.FloorToInt(gap * _frameRate);
            }
        }