コード例 #1
0
        public async Task ConnectAsync(DateTime initialTimeStamp, CancellationToken token)
        {
            IRtspTransportClient rtspTransportClient = _transportClientProvider();

            Volatile.Write(ref _rtspTransportClient, rtspTransportClient);

            await _rtspTransportClient.ConnectAsync(token);

            RtspRequestMessage  optionsRequest  = _requestMessageFactory.CreateOptionsRequest();
            RtspResponseMessage optionsResponse = await _rtspTransportClient.ExecuteRequest(optionsRequest, token);

            if (optionsResponse.StatusCode == RtspStatusCode.Ok)
            {
                ParsePublicHeader(optionsResponse.Headers[WellKnownHeaders.Public]);
            }

            RtspRequestMessage  describeRequest  = _requestMessageFactory.CreateDescribeRequest();
            RtspResponseMessage describeResponse =
                await _rtspTransportClient.EnsureExecuteRequest(describeRequest, token);

            string contentBaseHeader = describeResponse.Headers[WellKnownHeaders.ContentBase];

            if (!string.IsNullOrEmpty(contentBaseHeader))
            {
                _requestMessageFactory.ContentBase = new Uri(contentBaseHeader);
            }

            var parser = new SdpParser();
            IEnumerable <RtspTrackInfo> tracks = parser.Parse(describeResponse.ResponseBody);

            bool anyTrackRequested = false;

            foreach (RtspMediaTrackInfo track in GetTracksToSetup(tracks))
            {
                await SetupTrackAsync(initialTimeStamp, track, token);

                anyTrackRequested = true;
            }

            if (!anyTrackRequested)
            {
                throw new RtspClientException("Any suitable track is not found");
            }

            RtspRequestMessage  playRequest  = (initialTimeStamp != default(DateTime) ? _requestMessageFactory.CreatePlayRequest(initialTimeStamp) : _requestMessageFactory.CreatePlayRequest());
            RtspResponseMessage playResponse =
                await _rtspTransportClient.EnsureExecuteRequest(playRequest, token, 1);

            // TODO : Create a specific parse to convert the clock values
            Regex clockRegex = new Regex(@"clock=(?<startTime>\d{8}T\d{6}Z)\-(?<endTime>\d{8}T\d{6}Z)", RegexOptions.Singleline);

            foreach (string playResponseHeader in playResponse.Headers.GetValues("Range"))
            {
                Match clockMatches = clockRegex.Match(playResponseHeader);
                if (clockMatches.Success)
                {
                    _mediaPayloadParser.BaseTime = DateTime.ParseExact(clockMatches.Groups["startTime"].Value, "yyyyMMddTHHmmssZ", CultureInfo.InvariantCulture, DateTimeStyles.None);
                }
            }
        }
コード例 #2
0
        public async Task <RtspResponseMessage> EnsureExecuteRequest(RtspRequestMessage requestMessage,
                                                                     CancellationToken token, int responseReadPortionSize = 0)
        {
            RtspResponseMessage responseMessage = await ExecuteRequest(requestMessage, token, responseReadPortionSize);

            if (responseMessage.StatusCode != RtspStatusCode.Ok)
            {
                throw new RtspBadResponseCodeException(responseMessage.StatusCode);
            }

            return(responseMessage);
        }
コード例 #3
0
        private async Task <RtspResponseMessage> GetResponseAsync(int responseReadPortionSize = 0)
        {
            int totalRead = await ReadUntilEndOfHeadersAsync(responseReadPortionSize);

            int startOfResponse = ArrayUtils.IndexOfBytes(_buffer, Constants.RtspProtocolNameBytes, 0, totalRead);

            if (startOfResponse == -1)
            {
                throw new RtspBadResponseException("\"RTSP\" start signature is not found");
            }

            int endOfResponseHeaders = ArrayUtils.LastIndexOfBytes(_buffer, Constants.DoubleCrlfBytes, 0, totalRead) +
                                       Constants.DoubleCrlfBytes.Length;

            if (endOfResponseHeaders == -1)
            {
                throw new RtspBadResponseException("End of response headers is not found");
            }

            var headersByteSegment =
                new ArraySegment <byte>(_buffer, startOfResponse, endOfResponseHeaders - startOfResponse);
            RtspResponseMessage rtspResponseMessage = RtspResponseMessage.Parse(headersByteSegment);

            string contentLengthString = rtspResponseMessage.Headers[WellKnownHeaders.ContentLength];

            if (string.IsNullOrEmpty(contentLengthString))
            {
                return(rtspResponseMessage);
            }

            if (!uint.TryParse(contentLengthString, out uint contentLength))
            {
                throw new RtspParseResponseException($"Invalid content-length header: {contentLengthString}");
            }

            if (contentLength == 0)
            {
                return(rtspResponseMessage);
            }

            if (contentLength > Constants.MaxResponseHeadersSize)
            {
                throw new RtspBadResponseException($"Response content is too large: {contentLength}");
            }

            int dataPartSize = totalRead - headersByteSegment.Count;

            Buffer.BlockCopy(_buffer, endOfResponseHeaders, _buffer, 0, dataPartSize);
            await ReadExactAsync(_buffer, dataPartSize, (int)(contentLength - dataPartSize));

            rtspResponseMessage.ResponseBody = new ArraySegment <byte>(_buffer, 0, (int)contentLength);
            return(rtspResponseMessage);
        }
コード例 #4
0
        public async Task ConnectAsync(CancellationToken token)
        {
            IRtspTransportClient rtspTransportClient = _transportClientProvider();

            Volatile.Write(ref _rtspTransportClient, rtspTransportClient);

            await _rtspTransportClient.ConnectAsync(token);

            RtspRequestMessage  optionsRequest  = _requestMessageFactory.CreateOptionsRequest();
            RtspResponseMessage optionsResponse = await _rtspTransportClient.ExecuteRequest(optionsRequest, token);

            if (optionsResponse.StatusCode == RtspStatusCode.Ok)
            {
                ParsePublicHeader(optionsResponse.Headers[WellKnownHeaders.Public]);
            }

            RtspRequestMessage  describeRequest  = _requestMessageFactory.CreateDescribeRequest();
            RtspResponseMessage describeResponse =
                await _rtspTransportClient.EnsureExecuteRequest(describeRequest, token);

            string contentBaseHeader = describeResponse.Headers[WellKnownHeaders.ContentBase];

            if (!string.IsNullOrEmpty(contentBaseHeader))
            {
                _requestMessageFactory.ContentBase = new Uri(contentBaseHeader);
            }

            var parser = new SdpParser();
            IEnumerable <RtspTrackInfo> tracks = parser.Parse(describeResponse.ResponseBody);

            bool anyTrackRequested = false;

            foreach (RtspMediaTrackInfo track in GetTracksToSetup(tracks))
            {
                await SetupTrackAsync(track, token);

                Codec             = track.Codec;
                anyTrackRequested = true;
            }

            if (!anyTrackRequested)
            {
                throw new RtspClientException("Any suitable track is not found");
            }

            RtspRequestMessage playRequest = _requestMessageFactory.CreatePlayRequest();
            await _rtspTransportClient.EnsureExecuteRequest(playRequest, token, 1);
        }
コード例 #5
0
        public async Task <RtspResponseMessage> ExecuteRequest(RtspRequestMessage requestMessage,
                                                               CancellationToken token, int responseReadPortionSize = 0)
        {
            token.ThrowIfCancellationRequested();

            await SendRequestAsync(requestMessage, token);

            RtspResponseMessage responseMessage = await GetResponseAsync(responseReadPortionSize);

            if (responseMessage.StatusCode != RtspStatusCode.Unauthorized)
            {
                return(responseMessage);
            }

            if (ConnectionParameters.Credentials.IsEmpty() || _authenticator != null)
            {
                throw new RtspBadResponseCodeException(responseMessage.StatusCode);
            }

            string authenticateHeader = responseMessage.Headers[WellKnownHeaders.WwwAuthenticate];

            if (string.IsNullOrEmpty(authenticateHeader))
            {
                throw new RtspBadResponseCodeException(responseMessage.StatusCode);
            }

            _authenticator = Authenticator.Create(ConnectionParameters.Credentials, authenticateHeader);
            requestMessage.UpdateSequenceNumber();

            await SendRequestAsync(requestMessage, token);

            responseMessage = await GetResponseAsync();

            if (responseMessage.StatusCode == RtspStatusCode.Unauthorized)
            {
                throw new RtspBadResponseCodeException(responseMessage.StatusCode);
            }

            return(responseMessage);
        }