Beispiel #1
0
        public static ImmutableList <MediaTrack> FromSdp(SessionDescription sdp, Uri baseUri, MimeType filter = null)
        {
            var builder = ImmutableList.CreateBuilder <MediaTrack>();

            string sdpConnectionAddr = baseUri.Host;

            if (sdp.Connection != null && IsAddressSet(sdp.Connection.Address))
            {
                sdpConnectionAddr = sdp.Connection.Address;
            }

            sdp.MediaDescriptions.ForEach(md =>
            {
                Uri controlUri = baseUri;
                string type    = md.Media.ToString().ToLower();
                string subType = "unknown";

                // Prefer the media description's connection address over the sdp connection address.
                var connectionAddr = md.Connection != null && !string.IsNullOrEmpty(md.Connection.Address)
                        ? md.Connection.Address
                        : sdpConnectionAddr;

                var rtmpmaps = md.GetRtpMaps();

                // Via spec there can be multiple types and rtpmaps, but
                // we will assume a single one since all cameras/encoders
                // appear to only provide one per Media Description.
                var rtpmap = rtmpmaps.IsEmpty ? FromPayloadType(md.MediaFormats[0]) : rtmpmaps.First();
                subType    = rtpmap.EncodingName;

                var control = md.Attributes.Where(a => "control" == a.Name).DefaultIfEmpty(null).First();
                if (control != null)
                {
                    controlUri = ResolveUri(baseUri, new Uri(control.Value, UriKind.RelativeOrAbsolute));
                }

                var mimeType = MimeType.Create(type, rtpmap.EncodingName);

                if (mimeType.Is(APPLICATION_SPOOFED))
                {
                    // The MediaGateway and Vxpro us spoofing to determine the client's intentions of
                    // either playing live or recorded data.  Because of the current design they do not
                    // have a way to know the client's intentions until a play call is issued that contains
                    // and RTSP Range header with an absolute start-time.
                    //
                    // To handle metadata, in a pretty hacky way, a new media description is added to the SDP
                    // of type application/vnd.pelco.spoofed to indicate to a client that the data is bogus
                    // The client should continue processing up until the play call is made.  At this point the
                    // MediaGateway or VxPro will issues a redirect to the actual source.
                    //
                    // We will make a bogus metadata track to allow the client to continue processing.
                    builder.Add(MediaTrack.CreateBuilder()
                                .Address(Dns.GetHostAddresses(baseUri.Host)[0])
                                .Port(md.Port)
                                .Type(mimeType)
                                .Uri(controlUri)
                                .Build());
                }
                else if ((filter != null && mimeType.Is(filter)) || (filter == null))
                {
                    // If a filter is defined only return tracks that match the
                    // defined filter type; otherwise, return all tracks.

                    if (IsAddressSet(connectionAddr))
                    {
                        // If defined as 0.0.0.0 or ::0 then replace with the SDP connection address.
                        connectionAddr = sdpConnectionAddr;
                    }

                    var addrs = Dns.GetHostAddresses(connectionAddr);

                    builder.Add(MediaTrack.CreateBuilder()
                                .Address(Dns.GetHostAddresses(connectionAddr)[0])
                                .Port(md.Port)
                                .RtpMap(rtpmap)
                                .Type(mimeType)
                                .Uri(controlUri)
                                .Build());
                }
            });

            return(builder.ToImmutable());
        }