示例#1
0
        public override RtspResponse SetUp(RtspRequest request)
        {
            var builder = RtspResponse.CreateBuilder().Status(RtspResponse.Status.Ok);

            var transport = request.Transport;

            if (transport == null)
            {
                return(builder.Status(RtspResponse.Status.BadRequest).Build());
            }
            else if (transport.Type != TransportType.RtspInterleaved)
            {
                return(builder.Status(RtspResponse.Status.UnsupportedTransport).Build());
            }

            lock (this)
            {
                PortPair channels = new PortPair(_currentChannel, _currentChannel + 1);
                _currentChannel += 2;

                var session = new InterleavedTestSession(request.Context, _spy, channels, PAYLOAD_TYPE);
                _sessionManager.RegisterSession(session);

                transport = TransportHeader.CreateBuilder()
                            .Type(TransportType.RtspInterleaved)
                            .InterleavedChannels(channels)
                            .Build();

                return(builder.AddHeader(RtspHeaders.Names.TRANSPORT, transport.ToString())
                       .AddHeader(RtspHeaders.Names.SESSION, session.Id)
                       .Build());
            }
        }
示例#2
0
        public override RtspResponse SetUp(RtspRequest request)
        {
            var builder = RtspResponse.CreateBuilder();

            var queryParams = HttpUtility.ParseQueryString(request.URI.Query);
            var sourceId    = queryParams["sourceId"];

            if (sourceId == null || !_sourceMgr.ContainsSource(sourceId))
            {
                return(builder.Status(RtspResponse.Status.NotFound).Build());
            }

            var transport = request.Transport;

            if (transport == null)
            {
                return(builder.Status(RtspResponse.Status.BadRequest).Build());
            }

            if (transport.Type != Pelco.Media.RTSP.TransportType.UdpUnicast)
            {
                return(builder.Status(RtspResponse.Status.UnsupportedTransport).Build());
            }

            if (transport.ClientPorts == null || !transport.ClientPorts.IsSet)
            {
                return(builder.Status(RtspResponse.Status.BadRequest).Build());
            }

            var rtpPort = transport.ClientPorts.RtpPort;
            var address = transport.Destination != null?Dns.GetHostAddresses(transport.Destination)[0]
                          : request.RemoteEndpoint.Address;

            var rtspSession = new RtspSession(_sourceMgr.GetSource(sourceId).GetPipelineSource(),
                                              PAYLOAD_TYPE,
                                              new IPEndPoint(address, rtpPort));

            if (!_sessionMgr.RegisterSession(rtspSession))
            {
                return(builder.Status(RtspResponse.Status.InternalServerError)
                       .AddHeader(RtspHeaders.Names.CONTENT_TYPE, "text/plain")
                       .Body("Unable to register Rtsp session with system")
                       .Build());
            }

            var session = Session.FromParts(rtspSession.Id, RtspSession.RTSP_SESSION_TIMEOUT);

            transport = TransportHeader.CreateBuilder()
                        .Type(Pelco.Media.RTSP.TransportType.UdpUnicast)
                        .ClientPorts(transport.ClientPorts)
                        .ServerPorts(rtpPort + 3, rtpPort + 4)                // Just create dummy ports.
                        .Build();

            return(builder.Status(RtspResponse.Status.Ok)
                   .AddHeader(RtspHeaders.Names.TRANSPORT, transport.ToString())
                   .AddHeader(RtspHeaders.Names.SESSION, session.ToString())
                   .Build());
        }
        public void TestInterleaved()
        {
            var transport = TransportHeader.CreateBuilder()
                            .Type(TransportType.RtspInterleaved)
                            .InterleavedChannels(0, 1)
                            .Build();

            var response = _fixture.Client.Request().Transport(transport).SetUp();

            Assert.True(response.ResponseStatus.Is(RtspResponse.Status.Ok));

            transport = response.Transport;
            Assert.NotNull(transport);
            Assert.Equal(TransportType.RtspInterleaved, transport.Type);
            Assert.Equal(0, transport.InterleavedChannels.RtpPort);
            Assert.Equal(1, transport.InterleavedChannels.RtcpPort);

            var session = response.Session;

            Assert.NotNull(session);
            Assert.NotEmpty(session.ID);
            Assert.Equal(60u, session.Timeout);

            var sink     = new Sink();
            var pipeline = MediaPipeline.CreateBuilder()
                           .Source(_fixture.Client.GetChannelSource(transport.InterleavedChannels.RtpPort))
                           .Transform(new DefaultRtpDepacketizer())
                           .Sink(sink)
                           .Build();

            pipeline.Start();

            _fixture.Client.Request().Session(session.ID).PlayAsync((res) =>
            {
                Assert.True(res.ResponseStatus.Is(RtspResponse.Status.Ok));
            });

            sink.WaitForCompletion(TimeSpan.FromSeconds(20));

            _fixture.Client.Request().Session(session.ID).TeardownAsync((res) => { });

            pipeline.Stop();

            var sessData = _spy.GetData(session.ID);

            Assert.Equal(sessData.Buffers.Count, sink.ReceivedBuffers.Count);
            Assert.True(Enumerable.SequenceEqual(sessData.Buffers, sink.ReceivedBuffers));
        }
        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);
        }
示例#5
0
        private RtpSession Setup(MediaTrack track, RtpChannelSink sink, bool interleaved)
        {
            lock (SourceLock)
            {
                IRtpSource rtpSource = null;
                try
                {
                    TransportHeader transport = null;
                    if (interleaved)
                    {
                        transport = TransportHeader.CreateBuilder()
                                    .Type(Media.RTSP.TransportType.RtspInterleaved)
                                    .InterleavedChannels(0, 1)
                                    .Build();
                    }
                    else
                    {
                        // TODO(frank.lamar): Add multicast support.
                        rtpSource = new RtpUdpSource(track.Address);
                        transport = TransportHeader.CreateBuilder()
                                    .Type(Media.RTSP.TransportType.UdpUnicast)
                                    .ClientPorts(rtpSource.RtpPort, rtpSource.RtcpPort)
                                    .Build();
                    }

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

                    if (!response.Headers.ContainsKey(RtspHeaders.Names.SESSION))
                    {
                        throw new RtspClientException("Rtsp SETUP response does not contain a session id");
                    }
                    var rtspSession = Session.Parse(response.Headers[RtspHeaders.Names.SESSION]);

                    transport = response.Transport;
                    if (interleaved)
                    {
                        if (transport.Type != Media.RTSP.TransportType.RtspInterleaved)
                        {
                            throw new RtspClientException($"Server does not support interleaved. Response Transport='{transport}'");
                        }

                        var channels = transport.InterleavedChannels != null ? transport.InterleavedChannels : new PortPair(0, 1);
                        sink.Channel = channels.RtpPort; // Ensure that the sink contains the correct Interleaved channel id.

                        rtpSource = new RtpInterleavedSource(_client.GetChannelSource(channels.RtpPort),
                                                             _client.GetChannelSource(channels.RtcpPort));
                    }

                    var pipeline = MediaPipeline.CreateBuilder()
                                   .Source(rtpSource.RtpSource)
                                   .TransformIf(transport.SSRC != null, new SsrcFilter(transport.SSRC))
                                   .Sink(sink)
                                   .Build();

                    var session = new RtpSession(track, rtspSession, rtpSource);
                    session.Pipelines.Add(pipeline);
                    session.Start();

                    CheckAndStartRefreshTimer(session.Session.Timeout);

                    return(session);
                }
                catch (Exception e)
                {
                    if (rtpSource != null)
                    {
                        rtpSource?.Stop();
                    }

                    if (e is RtspClientException)
                    {
                        throw e;
                    }

                    throw new RtspClientException($"Unable to set up media track {track.ID}", e);
                }
            }
        }