From 9bd97ecbc788ae1666c02d396a16d8a5909595bd Mon Sep 17 00:00:00 2001 From: Davide Galli Date: Mon, 28 Sep 2026 09:49:58 +0200 Subject: [PATCH] Changed way Rtsp send messages. Can be necessary to queue messages, if sever is slow to connect. --- RtspClientExample/RTSPClient.cs | 153 ++++++++++++++++---------------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/RtspClientExample/RTSPClient.cs b/RtspClientExample/RTSPClient.cs index 9b8730f..53187af 100644 --- a/RtspClientExample/RTSPClient.cs +++ b/RtspClientExample/RTSPClient.cs @@ -7,6 +7,7 @@ using Rtsp.Rtp; using Rtsp.Sdp; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -15,6 +16,7 @@ using System.Net; using System.Net.Security; using System.Text; +using System.Threading; namespace RtspClientExample; @@ -134,6 +136,20 @@ private enum RTSP_STATUS // setup messages still to send readonly Queue setupMessages = new(); + + /// + /// Working thread for queue messages management + /// + Thread? _queueRequestThread = null; + /// + /// AutoResetEvent for quit. + /// + AutoResetEvent _queueRequestEvent = new(false); + /// + /// Queue for request to send to rtsp channel. + /// + readonly ConcurrentQueue _queueRequests = []; + /// /// Called when the Setup command are completed, so we can start the right Play message (with or without playback informations) /// @@ -345,50 +361,21 @@ public void Connect( public bool Pause() { - if (rtspSocket is null || _uri is null) - { - _logger.LogInformation("Not connected"); - return false; - } - if (!_ready) { return false; } - // Send PAUSE - RtspRequest pauseMessage = new RtspRequestPause - { - RtspUri = _uri, - Session = session - }; - pauseMessage.AddAuthorization(_authentication, _uri, rtspSocket.NextCommandIndex()); - rtspClient?.SendMessage(pauseMessage); + RtspRequestPause pauseMessage = new(); + CheckQueueRequest(pauseMessage); return true; } public bool Play() { - if (rtspSocket is null || _uri is null) - { - _logger.LogInformation("Not connected"); - return false; - } - if (!_ready) { return false; } - // Send PLAY - var playMessage = new RtspRequestPlay - { - RtspUri = _uri, - Session = session - }; - playMessage.AddAuthorization(_authentication, _uri, rtspSocket.NextCommandIndex()); - + RtspRequestPlay playMessage = new(); //// Need for old sony camera SNC-CS20 playMessage.Headers.Add("range", "npt=0.000-"); - if (_playbackSession) - { - playMessage.AddRequireOnvifRequest(); - playMessage.AddRateControlOnvifRequest(false); - } - rtspClient?.SendMessage(playMessage); + CheckQueueRequest(playMessage); + return true; } @@ -399,30 +386,11 @@ public bool Play() /// Speed information (1.0 means normal speed, -1.0 backward speed), other values >1.0 and <-1.0 allow a different speed public bool Play(DateTime seekTime, double speed = 1.0) { - if (rtspSocket is null || _uri is null) - { - _logger.LogInformation("Not connected"); - return false; - } - if (!_ready) - { - return false; - } - - var playMessage = new RtspRequestPlay - { - RtspUri = _uri, - Session = session, - }; - playMessage.AddAuthorization(_authentication, _uri, rtspSocket.NextCommandIndex()); + RtspRequestPlay playMessage = new(); playMessage.AddPlayback(seekTime, speed); - if (_playbackSession) - { - playMessage.AddRequireOnvifRequest(); - playMessage.AddRateControlOnvifRequest(false); - } - rtspClient?.SendMessage(playMessage); + CheckQueueRequest(playMessage); + return true; } @@ -435,34 +403,17 @@ public bool Play(DateTime seekTime, double speed = 1.0) /// public bool Play(DateTime seekTimeFrom, DateTime seekTimeTo, double speed = 1.0) { - if (rtspSocket is null || _uri is null) - { - _logger.LogInformation("Not connected"); - return false; - } - if (_ready) { return false; } - if (seekTimeFrom > seekTimeTo) { throw new ArgumentOutOfRangeException(nameof(seekTimeFrom), "Starting seek cannot be major than ending seek."); } - var playMessage = new RtspRequestPlay - { - RtspUri = _uri, - Session = session, - }; - - playMessage.AddAuthorization(_authentication, _uri, rtspSocket.NextCommandIndex()); + RtspRequestPlay playMessage = new(); playMessage.AddPlayback(seekTimeFrom, seekTimeTo, speed); - if (_playbackSession) - { - playMessage.AddRequireOnvifRequest(); - playMessage.AddRateControlOnvifRequest(false); - } - rtspClient?.SendMessage(playMessage); + CheckQueueRequest(playMessage); + return true; } @@ -1291,4 +1242,54 @@ private void SendKeepAlive(object? sender, System.Timers.ElapsedEventArgs e) keepAliveMessage.AddAuthorization(_authentication, _uri!, rtspSocket!.NextCommandIndex()); rtspClient?.SendMessage(keepAliveMessage); } + + + private void CheckQueueRequest(RtspRequest request) + { + if (_queueRequestThread is null) + { + _queueRequestEvent = new(false); + _queueRequestThread = new(QueueRequestMethod) + { + Name = nameof(QueueRequestMethod), + }; + _queueRequestThread.Start(); + } + // add request to queue. + _queueRequests.Enqueue(request); + } + + /// + /// This is the main method for sending requests.
+ /// Since the rtsp can use some times to connect, in an "async" scenario, the requests would be lost, since we check + /// and url connection.
+ /// We avoid to lost messages in this way. + ///
+ private void QueueRequestMethod() + { + // we check every second (avoid sending messages too close togheter, some rtsp implementation does not work correctly if so) + while (!_queueRequestEvent.WaitOne(1000)) + { + // If we have not completed the Setup process, continue. + if (!_ready) { continue; } + + if (_queueRequests.TryDequeue(out RtspRequest? request)) + { + request.RtspUri = _uri; + request.Session = session; + // we are sure uri and socket are setup. + request.AddAuthorization(_authentication, _uri!, rtspSocket!.NextCommandIndex()); + + if (_playbackSession && request is RtspRequestPlay) + { + // only on play requests. + request.AddRequireOnvifRequest(); + request.AddRateControlOnvifRequest(true); + } + + // we are sure client is online, but, since we dispose it, use compound request. + rtspClient?.SendMessage(request); + } + } + } } \ No newline at end of file