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); }
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()"); } } }
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; } }
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); }
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); }
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; }
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(); }
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); }
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; } }