private Uri DetermineRealUri()
        {
            // The VideoXpert system does some non-standard RTSP redirecting so that it can determine the intent of
            // the client (intent being live or playback).  It stats off by creating a spoofed SDP and then will
            // redirect on play.  What we will do it write a wrapper that does some of the RTSP calls to first
            // determine what the actual live RTSP uri is.

            using (RtspClient client = new RtspClient(_uri))
            {
                try
                {
                    var method = RtspRequest.RtspMethod.OPTIONS;
                    CheckResponse(client.Send(RtspRequest.CreateBuilder()
                                              .Method(method)
                                              .Uri(_uri)
                                              .Build()), method);

                    method = RtspRequest.RtspMethod.DESCRIBE;
                    var res = CheckResponse(client.Send(RtspRequest.CreateBuilder()
                                                        .Method(method)
                                                        .Uri(_uri)
                                                        .Build()), method);

                    var sdp = res.GetBodyAsSdp();
                    if (!sdp.SessionName.Contains("Spoofed session"))
                    {
                        // We are not working with a spoofed session just return
                        // the current uri.
                        return(_uri);
                    }

                    Uri controlUri = null;
                    var tracks     = MediaTracks.FromSdp(sdp, _uri);
                    foreach (var track in tracks)
                    {
                        if (track.Type.Is(MimeType.ANY_VIDEO))
                        {
                            if (GetRedirectUri(client, track, out controlUri))
                            {
                                return(controlUri);
                            }
                        }
                    }

                    throw new RtspClientException($"Unable to retrieve usable uri from server at endpoint '{_uri}'");
                }
                catch (Exception e)
                {
                    LOG.Error(e, $"Failed while communicating with RTSP server at '{_uri}'");
                    throw e;
                }
            }
        }
        private bool GetRedirectUri(RtspClient client, MediaTrack track, out Uri uri)
        {
            var transport = TransportHeader.CreateBuilder()
                            .Type(TransportType.RtspInterleaved)
                            .InterleavedChannels(0, 1)
                            .Build();

            var method = RtspRequest.RtspMethod.SETUP;
            var res    = CheckResponse(client.Send(RtspRequest.CreateBuilder()
                                                   .Method(method)
                                                   .Uri(track.ControlUri)
                                                   .AddHeader(RtspHeaders.Names.TRANSPORT, transport.ToString())
                                                   .Build()), method);

            if (!res.Headers.ContainsKey(RtspHeaders.Names.SESSION))
            {
                uri = null;
                return(false);
            }
            var rtspSession = Session.Parse(res.Headers[RtspHeaders.Names.SESSION]);

            method = RtspRequest.RtspMethod.PLAY;
            res    = CheckResponse(client.Send(RtspRequest.CreateBuilder()
                                               .Method(method)
                                               .Uri(track.ControlUri)
                                               .AddHeader(RtspHeaders.Names.SESSION, rtspSession.ID)
                                               .Build()), method);

            var status = res.ResponseStatus;

            if (status.Is(RtspResponse.Status.MovedPermanently) || status.Is(RtspResponse.Status.MovedTemporarily))
            {
                // We received a redirect lets get the uri and return it.

                if (res.Headers.ContainsKey(RtspHeaders.Names.LOCATION))
                {
                    var value = res.Headers[RtspHeaders.Names.LOCATION];

                    return(Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out uri));
                }
            }

            uri = null;
            return(false);
        }