private bool Initialize(uint connectionHandle)
        {
            bool returnResult = false;

            if (connectionHandle != PluginUtils.InvalidHandle)
            {
                this.Handle = connectionHandle;
                this.State  = ConnectionState.Connected;

                thisObject = GCHandle.Alloc(this, GCHandleType.Normal);
                IntPtr thisObjectPtr = GCHandle.ToIntPtr(this.thisObject);

                this.disconnectedHandler = new PluginCallbackHandler(Connection_PluginCallbackWrapper.OnDisconnected_Callback);
                PluginUtils.CheckHResult(
                    Wrapper.exAddDisconnected(this.Handle, this.disconnectedHandler, thisObjectPtr, ref this.disconnectedToken),
                    "Connection.AddDisconnected");

                this.dataReceivedHandler = new Wrapper.DataReceivedHandler(Connection_PluginCallbackWrapper.OnDataReceived_Callback);
                PluginUtils.CheckHResult(
                    Wrapper.exAddReceived(this.Handle, this.dataReceivedHandler, thisObjectPtr, ref this.dataReceivedToken),
                    "Connection.AddRecevied");

                returnResult = true;
            }

            return(returnResult);
        }
예제 #2
0
        private void OnConnected(uint handle, long result, string message)
        {
            bool failed = true;

            if (handle != PluginUtils.InvalidHandle)
            {
                // create Connection and pass ownership to it
                var connection = Connection.CreateConnection(handle);

                if (connection != null)
                {
                    failed = false;
                    this.Connected?.Invoke(this, connection);
                }
            }

            if (failed)
            {
                if (this.Failed != null)
                {
                    this.Failed(this,
                                new FailedEventArgs(result,
                                                    string.Format("NetworkComponent.Connected(): result: 0x{0} - {1}",
                                                                  result.ToString("X", NumberFormatInfo.InvariantInfo), message)));
                }
                else
                {
                    PluginUtils.CheckHResult(result, "NetworkComponent.Connected()");
                }
            }
        }
예제 #3
0
 protected virtual void OnStarted(int result)
 {
     if (result != 0)
     {
         if (this.Failed != null)
         {
             this.Failed(this,
                         new FailedEventArgs(result,
                                             string.Format("NetworkComponent.Started(): result: 0x{0}",
                                                           result.ToString("X", NumberFormatInfo.InvariantInfo))));
         }
         else
         {
             PluginUtils.CheckHResult(result, "NetworkComponent.Connected()");
         }
         return;
     }
     else
     {
         // success send the started event
         if (this.Started != null)
         {
             this.Started(this, EventArgs.Empty);
         }
     }
 }
        private void OnStateChanged(PlayerPlugin.PLAYBACK_STATE args)
        {
            this.plugin.QueueAction(() =>
            {
                var stateType = (PlayerPlugin.StateType)Enum.ToObject(typeof(PlayerPlugin.StateType), args.type);

                // TODO: Update player state based on this*

                switch (stateType)
                {
                case PlayerPlugin.StateType.StateChanged:
                    //this.PlayerState = (PlaybackState)Enum.ToObject(typeof(PlaybackState), args.state);
                    Debug.Log("Playback State: " + stateType.ToString() + " - " + this.PlayerState.ToString());
                    break;

                case PlayerPlugin.StateType.Opened:
                    PlayerPlugin.MEDIA_DESCRIPTION description = args.description;
                    Debug.Log("Media Opened: " + description.ToString());
                    break;

                case PlayerPlugin.StateType.Failed:
                    PluginUtils.CheckHResult(args.hresult, "RealtimeVideoPlayer::OnStateChanged");
                    break;

                default:
                    break;
                }
            });
        }
        private void CreateRealTimePlayer()
        {
            Debug.Log("RealtimeVideoPlayer::CreateRealTimePlayer");

            // Only initialize if we have a connection and don't already have a player
            if (this.networkConnection == null || isPlayerCreated)
            {
                Debug.Log("RealtimeVideoPlayer::CreateRealTimePlayer - Connection=null or isPlayerCreated");
                return;
            }

            this.onCreatedCallback      = new PlayerPlugin.PlayerCreatedCallback(Player_PluginCallbackWrapper.OnCreated_Callback);
            this.onStateChangedCallback = new PlayerPlugin.StateChangedCallback(Player_PluginCallbackWrapper.OnStateChanged_Callback);

            IntPtr thisObjectPtr = GCHandle.ToIntPtr(this.thisObject);

            // Create our RealtimePlayer at the Plugin C++ layer
            PluginUtils.CheckHResult(PlayerPlugin.exCreatePlayer(
                                         this.networkConnection.Handle,
                                         this.onStateChangedCallback,
                                         this.onCreatedCallback,
                                         thisObjectPtr,
                                         ref this.playerHandle
                                         ), "RealtimeVideoPlayer::exCreatePlayer()");

            if (!isPlayerCreated)
            {
                Shutdown();
                return;
            }
        }
예제 #6
0
        public void StartAsync()
        {
            IntPtr thisObjectPtr = GCHandle.ToIntPtr(this.thisObject);
            var    result        = Wrapper.exStartListener(this.Port, ref this.handle, this.connectedHandler, thisObjectPtr);

            PluginUtils.CheckHResult(result, "Listener.StartAsync()");

            base.OnStarted(result);
        }
예제 #7
0
        public void DiscoverAsync()
        {
            IntPtr thisObjectPtr = GCHandle.ToIntPtr(this.thisObject);
            var    result        = Wrapper.exDiscoverConnection(ref this.handle, this.connectedHandler, thisObjectPtr);

            PluginUtils.CheckHResult(result, "Connector.DiscoverAsync()");

            base.OnStarted(result);
        }
예제 #8
0
        public void ConnectAsync(string connectionUrl)
        {
            IntPtr thisObjectPtr = GCHandle.ToIntPtr(this.thisObject);
            var    result        = Wrapper.exOpenConnection(connectionUrl, ref this.handle, this.connectedHandler, thisObjectPtr);

            PluginUtils.CheckHResult(result, "Connector.ConnectAsync()");

            base.OnStarted(result);
        }
        public void SendData(DataType messageType, byte[] buf, int length)
        {
            if (this.Handle == PluginUtils.InvalidHandle)
            {
                return;
            }

            PluginUtils.CheckHResult(
                Wrapper.exSendRawMessage(this.Handle, messageType, buf, length),
                "Connection.SendNetworkMessage");
        }
        /// <summary>
        /// Callback from the Native plugin when a realtime player has been created at the c++ level
        /// </summary>
        /// <param name="result">HRESULT from creation</param>
        /// <param name="width">streaming texture width</param>
        /// <param name="height">streaming texture height</param>
        private void OnCreated(long result, uint width, uint height)
        {
            this.plugin.QueueAction(() =>
            {
                Debug.Log("RealtimeVideoPlayer::OnCreated");
                PluginUtils.CheckHResult(result, "RealtimeVideoPlayer::OnCreated");

                // Weird bug seen on ARM. width/height parameters passed into this function are invalid values
                PluginUtils.CheckHResult(PlayerPlugin.exGetStreamResolution(this.playerHandle, ref width, ref height),
                                         "RealtimeVideoPlayer::exGetStreamResolution");

                if (!IsValidResolution(width, height))
                {
                    Debug.LogError("RealtimeVideoPlayer::OnCreated() Invalid streaming resolution width=" + width + " - height=" + height);
                    Shutdown();
                    return;
                }

                this.TextureWidth          = width;
                this.TextureHeight         = height;
                IntPtr nativeTexturePtr_L  = IntPtr.Zero;
                IntPtr nativeTexturePtr_UV = IntPtr.Zero;

                // It is more performant to utilize YUV texture for video streaming/rendering
                // https://docs.microsoft.com/en-us/windows/desktop/medfound/recommended-8-bit-yuv-formats-for-video-rendering

                // Get pointers to the Luma/Chroma textures being used by MediaFoundation in the native plugin
                PluginUtils.CheckHResult(PlayerPlugin.exCreateExternalTexture(this.playerHandle,
                                                                              this.TextureWidth, this.TextureHeight,
                                                                              out nativeTexturePtr_L, out nativeTexturePtr_UV),
                                         "RealtimeVideoPlayer::exCreateExternalTexture");

                this.Texture_Luma = Texture2D.CreateExternalTexture((int)this.TextureWidth,
                                                                    (int)this.TextureHeight,
                                                                    TextureFormat.RG16,
                                                                    false,
                                                                    true,
                                                                    nativeTexturePtr_L);

                this.Texture_Chroma = Texture2D.CreateExternalTexture((int)this.TextureWidth,
                                                                      (int)this.TextureHeight,
                                                                      TextureFormat.R8,
                                                                      false,
                                                                      true,
                                                                      nativeTexturePtr_UV);

                if (AutoPlay)
                {
                    Play();
                }
            });
        }
        public void Close()
        {
            if (this.Handle != PluginUtils.InvalidHandle)
            {
                PluginUtils.CheckHResult(Wrapper.exRemoveDisconnected(this.Handle, this.disconnectedToken), "Connection.Close() - RemoveDisconnected - Handle= " + this.Handle);

                PluginUtils.CheckHResult(Wrapper.exRemoveReceived(this.Handle, this.dataReceivedToken), "Connection.Close() - RemoveReceived - Handle= " + this.Handle);

                PluginUtils.CheckHResult(Wrapper.exClose(this.Handle), "Connection.Close() - CloseConnection - Handle= " + this.Handle);
            }

            this.State = ConnectionState.Closed;
            this.Closed?.Invoke(this, EventArgs.Empty);
            this.Handle = PluginUtils.InvalidHandle;
        }
예제 #12
0
        private bool DestroyServer()
        {
            if (isServerRunning)
            {
                Debug.Log("Cannot StopServer() - server not active");
                return(false);
            }

            var hr = VideoServerWrapper.exShutdown(this.serverHandle);

            PluginUtils.CheckHResult(hr, "RealtimeVideoServer::StopServer");

            // Invalidate our handle
            this.serverHandle = PluginUtils.InvalidHandle;

            return(hr == PluginUtils.S_OK);
        }
        public void Stop()
        {
            if (!this.isPlayerCreated)
            {
                return;
            }

            Debug.Log("RealTimePlayer::Stop");

            // Run plugin command on background thread and not UI thread. Weird bug where MF locks the thread
            Task task = new Task(() =>
            {
                PluginUtils.CheckHResult(PlayerPlugin.exStop(this.playerHandle), "RealTimePlayer::exStop");
                this.plugin.QueueAction(() => this.PlayerState = PlaybackState.Ended);
            });

            task.Start();
        }
예제 #14
0
        public bool WriteFrame(byte[] data)
        {
            if (data == null || data.Length <= 0)
            {
                Debug.LogError("RealtimeVideoServer::WriteFrame - byte[] data cannot be null");
                return(false);
            }

            if (!isServerRunning)
            {
                Debug.LogError("Cannot WriteFrame() - server not active");
                return(false);
            }

            var hr = VideoServerWrapper.exWrite(this.serverHandle, data, (uint)data.Length);

            PluginUtils.CheckHResult(hr, "RealtimeVideoServer::WriteFrame");

            return(hr == PluginUtils.S_OK);
        }
예제 #15
0
        private bool CreateServer(Connection connection)
        {
            Debug.Log("RealtimeVideoServer::InitializeServer()");

            if (connection == null)
            {
                Debug.LogError("RealtimeVideoServer.Initialize() - requires a valid connection component to start.");
                return(false);
            }

            if (isServerRunning)
            {
                Debug.LogError("RealtimeVideoServer.Initialize() - cannot start until previous instance is stopped.");
                return(false);
            }

            this.networkConnection = connection;
            this.networkConnection.Disconnected += this.OnDisconnected;
            this.networkConnection.Closed       += this.OnConnectionClosed;

            uint handle  = PluginUtils.InvalidHandle;
            bool useHEVC = this.OutputEncoding == Encoding.H265;
            var  hr      = VideoServerWrapper.exCreate(this.networkConnection.Handle, useHEVC, this.OutputWidth, this.OutputHeight, ref handle);

            PluginUtils.CheckHResult(hr, "RealtimeVideoServer::exCreate");

            if (handle == PluginUtils.InvalidHandle || hr != PluginUtils.S_OK)
            {
                Debug.Log("VideoServerWrapper.exCreate - Failed");
                Shutdown();
                return(false);
            }

            this.serverHandle = handle;
            this.CurrentState = ServerState.Ready;

            return(true);
        }
        public void Shutdown()
        {
            Debug.Log("RealtimeVideoPlayer::Shutdown");

            if (this.connector != null)
            {
                this.StopConnector();
            }

            if (this.isPlayerCreated)
            {
                Stop();

                CloseNetworkConnection();

                PluginUtils.CheckHResult(PlayerPlugin.exReleasePlayer(this.playerHandle), "RealtimeVideoPlayer::exReleasePlayer()");
                this.Texture_Luma           = this.Texture_Chroma = null;
                this.onCreatedCallback      = null;
                this.onStateChangedCallback = null;
                this.playerHandle           = PluginUtils.InvalidHandle;

                PlayerState = PlaybackState.None;
            }
        }