Exemplo n.º 1
0
        public ActionResult MusicPlayer(string albumId)
        {
            AlbumPlayerViewModel model = new AlbumPlayerViewModel();

            model.MediaId = albumId;
            WebTranscoderProfile profile = GetProfile(Connections.Current.MASStreamControl, Settings.ActiveSettings.DefaultAudioProfile);

            model.Tracks = Connections.Current.MAS.GetMusicTracksDetailedForAlbum(Settings.ActiveSettings.MusicProvider, albumId);
            return(CreatePlayer(Connections.Current.MASStreamControl, model, StreamTarget.GetAudioTargets(), profile, true));
        }
Exemplo n.º 2
0
        public ActionResult MusicPlayer(string albumId)
        {
            AlbumPlayerViewModel model = new AlbumPlayerViewModel();

            model.MediaId        = albumId;
            model.ContinuationId = "playlist-" + randomGenerator.Next(100000, 999999).ToString();
            WebTranscoderProfile profile = GetProfile(Connections.Current.MASStreamControl,
                                                      Configuration.StreamingPlatforms.GetDefaultProfileForUserAgent(StreamingProfileType.Audio, Request.UserAgent));

            model.Tracks = Connections.Current.MAS.GetMusicTracksDetailedForAlbum(Settings.ActiveSettings.MusicProvider, albumId);
            return(CreatePlayer(Connections.Current.MASStreamControl, model, StreamTarget.GetAudioTargets(), profile, true));
        }
Exemplo n.º 3
0
        private string ActuallyStartHttpLiveStream(WebMediaType type, string itemId, WebTranscoderProfile profile, int starttime, string continuationId)
        {
            // Get identifier and continuationId
            continuationId = continuationId ?? "hls-" + randomGenerator.Next(10000, 99999).ToString();
            bool   alreadyRunning = RunningStreams.ContainsKey(continuationId);
            string identifier     = alreadyRunning ? RunningStreams[continuationId] : "webmediaportal-" + randomGenerator.Next(10000, 99999);

            Log.Debug("Requested HLS file for continuationId={0}; running={1}; identifier={2}", continuationId, alreadyRunning, identifier);

            // We only need to start the stream if this is the first request for this file
            string url;

            if (!alreadyRunning)
            {
                Log.Debug("Starting HLS stream type={0}; itemId={1}; profile={2}; starttime={3}; continuationId={4}; identifier={5}",
                          type, itemId, profile.Name, starttime, continuationId, identifier);
                Log.Debug("Stream is for user {0} from host {1}, has identifier {2} and timeout {3}s",
                          HttpContext.User.Identity.Name, Request.UserHostAddress, identifier, STREAM_TIMEOUT_HTTPLIVE);

                // Start the stream
                string clientDescription = String.Format("WebMediaPortal (user {0})", HttpContext.User.Identity.Name);
                using (var scope = WCFClient.EnterOperationScope(GetStreamControl(type)))
                {
                    WCFClient.SetHeader("forwardedFor", HttpContext.Request.UserHostAddress);
                    if (!GetStreamControl(type).InitStream((WebMediaType)type, GetProvider(type), itemId, clientDescription, identifier, STREAM_TIMEOUT_HTTPLIVE))
                    {
                        Log.Error("InitStream for HLS failed");
                        return(null);
                    }
                }

                // Get stream URL
                url = GetStreamControl(type).StartStream(identifier, profile.Name, starttime);
                if (String.IsNullOrEmpty(url))
                {
                    Log.Error("StartStream for HLS failed");
                    return(null);
                }
                Log.Debug("Started HLS stream successfully at {0}", url);
                RunningStreams[continuationId] = identifier;
                HttpLiveUrls[identifier]       = url;
            }

            return(identifier);
        }
Exemplo n.º 4
0
        //
        // Player
        protected ActionResult CreatePlayer(IWebStreamingService streamControl, PlayerViewModel model, List <StreamTarget> targets, WebTranscoderProfile profile, bool album)
        {
            // save stream request
            if (!PlayerOpenedBy.Contains(Request.UserHostAddress))
            {
                PlayerOpenedBy.Add(Request.UserHostAddress);
            }

            // get view properties
            VideoPlayer player   = targets.First(x => profile.Targets.Contains(x.Name)).Player;
            string      viewName = Enum.GetName(typeof(VideoPlayer), player) + (album ? "Album" : "") + "Player";

            // generate view
            var supportedTargets = Configuration.StreamingPlatforms.GetValidTargetsForUserAgent(Request.UserAgent).Intersect(targets.Select(x => x.Name));

            model.Transcoders       = ProfileModel.GetProfilesForTargets(streamControl, supportedTargets).Select(x => x.Name);
            model.Transcoder        = profile.Name;
            model.TranscoderProfile = profile;
            model.Player            = player;
            model.PlayerViewName    = viewName;
            Log.Debug("Created player with size={0} view={1} transcoder={2} url={3}", model.Size, viewName, profile.Name, model.URL);
            return(PartialView("Player", model));
        }
Exemplo n.º 5
0
        private ActionResult GenerateHttpLiveStream(WebMediaType type, string itemId, int fileindex, WebTranscoderProfile profile, int starttime, string continuationId)
        {
            string identifier = ActuallyStartHttpLiveStream(type, itemId, fileindex, profile, starttime, continuationId);

            if (identifier == null)
            {
                return(new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError));
            }

            // Return the actual file contents
            GetStreamControl(type).AuthorizeRemoteHostForStreaming(HttpContext.Request.UserHostAddress);
            if (GetStreamMode() == StreamType.Direct)
            {
                Log.Debug("HLS: Using Direct streaming mode and redirecting to playlist at {0}", HttpLiveUrls[identifier]);
                return(Redirect(HttpLiveUrls[identifier]));
            }
            else
            {
                ProxyHttpLiveIndex(identifier, HttpLiveUrls[identifier]);
                return(new EmptyResult());
            }
        }
Exemplo n.º 6
0
        private ActionResult GenerateStream(WebMediaType type, string itemId, int fileindex, string transcoder, int starttime, string continuationId)
        {
            // Check if there is actually a player requested for this stream
            if (!IsUserAuthenticated())
            {
                Log.Warn("User {0} (host {1}) requested a stream but isn't authenticated - denying access to stream", HttpContext.User.Identity.Name, Request.UserHostAddress);
                return(new HttpUnauthorizedResult());
            }

            // Load and validate profile
            WebTranscoderProfile profile = GetStreamControl(type).GetTranscoderProfileByName(transcoder);

            if (profile == null)
            {
                Log.Error("Requested stream for non-existing profile '{0}', other parameters type={1}; itemId={2}; starttime={3}; continuationId={4}", transcoder, type, itemId, starttime, continuationId);
                return(new HttpNotFoundResult());
            }

            // Delegate to HLS streaming if needed
            if (profile.HasVideoStream && StreamTarget.GetVideoTargets().First(x => profile.Targets.Contains(x.Name)).Player == VideoPlayer.HLS)
            {
                return(GenerateHttpLiveStream(type, itemId, fileindex, profile, starttime, continuationId));
            }

            // Generate random identifier, and continuationId if needed
            string identifier = "webmediaportal-" + randomGenerator.Next(10000, 99999);

            continuationId = continuationId ?? "none-provided-" + randomGenerator.Next(10000, 99999).ToString();

            // Kill previous stream, but only if we expect it to be still running (avoid useless calls in non-seek and proxied cases)
            if (RunningStreams.ContainsKey(continuationId))
            {
                Log.Debug("Killing off old stream for continuationId {0} with identifier {1} first", continuationId, RunningStreams[continuationId]);
                GetStreamControl(type).FinishStream(RunningStreams[continuationId]);
            }

            // Check stream mode, generate timeout setting and dump all info we got
            StreamType streamMode = GetStreamMode();
            int        timeout    = streamMode == StreamType.Direct ? STREAM_TIMEOUT_DIRECT : STREAM_TIMEOUT_PROXY;

            Log.Debug("Starting stream type={0}; itemId={1}; index={2}; transcoder={3}; starttime={4}; continuationId={5}",
                      type, itemId, fileindex, transcoder, starttime, continuationId);
            Log.Debug("Stream is for user {0} from host {1}, has identifier {2} and is using mode {3} with timeout {4}s",
                      HttpContext.User.Identity.Name, Request.UserHostAddress, identifier, streamMode, timeout);

            // Start the stream
            string clientDescription = String.Format("WebMediaPortal (user {0})", HttpContext.User.Identity.Name);

            using (var scope = WCFClient.EnterOperationScope(GetStreamControl(type)))
            {
                WCFClient.SetHeader("forwardedFor", HttpContext.Request.UserHostAddress);
                if (!GetStreamControl(type).InitStream((WebMediaType)type, GetProvider(type), itemId, fileindex, clientDescription, identifier, timeout))
                {
                    Log.Error("InitStream failed");
                    return(new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError));
                }
            }

            // Save stream
            RunningStreams[continuationId] = identifier;
            string url = GetStreamControl(type).StartStream(identifier, transcoder, starttime);

            if (String.IsNullOrEmpty(url))
            {
                Log.Error("StartStream failed");
                return(new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError));
            }
            Log.Debug("Stream started successfully and is at {0}", url);

            // Do the actual streaming
            if (streamMode == StreamType.Proxied)
            {
                GetStreamControl(type).AuthorizeStreaming();
                ProxyStream(url);
            }
            else if (streamMode == StreamType.Direct)
            {
                GetStreamControl(type).AuthorizeRemoteHostForStreaming(HttpContext.Request.UserHostAddress);
                return(Redirect(url));
            }

            // Kill stream (doesn't matter much if this doesn't happen, WSS kills streams automatically nowadays)
            Log.Debug("Finished stream {0}", identifier);
            RunningStreams.Remove(continuationId);
            if (!GetStreamControl(type).FinishStream(identifier))
            {
                Log.Error("FinishStream failed");
            }
            return(new EmptyResult());
        }
Exemplo n.º 7
0
        //
        // Player
        protected ActionResult CreatePlayer(IWebStreamingService streamControl, PlayerViewModel model, List <StreamTarget> targets, WebTranscoderProfile profile, bool album)
        {
            // save stream request
            if (!PlayerOpenedBy.Contains(Request.UserHostAddress))
            {
                PlayerOpenedBy.Add(Request.UserHostAddress);
            }

            // get all transcoder profiles
            List <string> profiles = new List <string>();

            foreach (StreamTarget target in targets)
            {
                profiles = profiles.Concat(streamControl.GetTranscoderProfilesForTarget(target.Name).Select(x => x.Name)).Distinct().ToList();
            }

            // get view properties
            VideoPlayer player   = targets.First(x => profile.Targets.Contains(x.Name)).Player;
            string      viewName = Enum.GetName(typeof(VideoPlayer), player) + (album ? "Album" : "") + "Player";

            // generate view
            model.Transcoders       = profiles;
            model.Transcoder        = profile.Name;
            model.TranscoderProfile = profile;
            model.Player            = player;
            model.PlayerViewName    = viewName;
            Log.Debug("Created player with size={0} view={1} transcoder={2} url={3}", model.Size, viewName, profile.Name, model.URL);
            return(PartialView("Player", model));
        }
Exemplo n.º 8
0
        public ActionResult Player(WebStreamMediaType type, string itemId, bool video = true)
        {
            // get transcoding profile
            IWebStreamingService streamControl = GetStreamControl(type);
            WebTranscoderProfile profile       = null;

            if (Request.QueryString["transcoder"] != null)
            {
                profile = GetStreamControl(type).GetTranscoderProfileByName(Request.QueryString["transcoder"]);
            }
            if (Request.Form["transcoder"] != null)
            {
                profile = GetStreamControl(type).GetTranscoderProfileByName(Request.Form["transcoder"]);
            }
            if (profile == null)
            {
                string defaultName = "";
                if (type == WebStreamMediaType.TV || type == WebStreamMediaType.Recording)
                {
                    defaultName = Settings.ActiveSettings.DefaultTVProfile;
                }
                else if (video)
                {
                    defaultName = Settings.ActiveSettings.DefaultMediaProfile;
                }
                else
                {
                    defaultName = Settings.ActiveSettings.DefaultAudioProfile;
                }
                profile = GetStreamControl(type).GetTranscoderProfileByName(defaultName);
            }

            // get all transcoder profiles
            List <StreamTarget> targets  = video ? StreamTarget.GetVideoTargets() : StreamTarget.GetAudioTargets();
            List <string>       profiles = new List <string>();

            foreach (StreamTarget target in targets)
            {
                profiles = profiles.Concat(GetStreamControl(type).GetTranscoderProfilesForTarget(target.Name).Select(x => x.Name)).ToList();
            }

            // get view properties
            VideoPlayer player   = targets.First(x => x.Name == profile.Target).Player;
            string      viewName = Enum.GetName(typeof(VideoPlayer), player) + "Player";

            // player size
            WebResolution playerSize;

            if (!video)
            {
                playerSize = new WebResolution()
                {
                    Width = 300, Height = 150
                };
            }
            else
            {
                playerSize = GetStreamControl(type).GetStreamSize(type, GetProvider(type), itemId, profile.Name);
            }

            // generate url
            RouteValueDictionary parameters = new RouteValueDictionary();

            parameters["item"]       = itemId;
            parameters["transcoder"] = profile.Name;

            // generate view
            return(PartialView(new PlayerViewModel
            {
                Transcoders = profiles,
                Transcoder = profile.Name,
                Player = player,
                PlayerViewName = viewName,
                URL = Url.Action(Enum.GetName(typeof(WebStreamMediaType), type), parameters),
                Size = playerSize
            }));
        }
        internal static WebTranscoderProfile TranscoderProfile(KeyValuePair <string, EndPointProfile> profile)
        {
            int    bandwith     = 0;
            string mime         = "video/MP2T";
            int    maxHeight    = profile.Value?.MediaTranscoding?.VideoSettings?.MaxHeight ?? 0;
            int    maxWidth     = Convert.ToInt32((double)maxHeight * (16.0 / 9.0));
            string transport    = "http";
            long   audioBitrate = 512;
            long   videoBitRate = 10000;

            if (profile.Value?.MediaTranscoding?.VideoTargets?.Count > 0)
            {
                var video = profile.Value.MediaTranscoding.VideoTargets.First();
                if (video.Target.MaxVideoBitrate > 0)
                {
                    videoBitRate = video.Target.MaxVideoBitrate;
                }
                if (video.Target.AudioBitrate > 0)
                {
                    audioBitrate = video.Target.AudioBitrate;
                }
                if (videoBitRate > 0 && audioBitrate > 0)
                {
                    bandwith = Convert.ToInt32(videoBitRate + audioBitrate);
                }
                if (video.Target.MaxVideoHeight > maxHeight)
                {
                    maxHeight = video.Target.MaxVideoHeight;
                }

                if (video.Target.AspectRatio > 0)
                {
                    maxWidth = Convert.ToInt32((float)maxHeight * video.Target.AspectRatio);
                }
                else
                {
                    maxWidth = Convert.ToInt32((double)maxHeight * (16.0 / 9.0));
                }

                if (video.Target.VideoContainerType == VideoContainer.Hls)
                {
                    transport = "httplive";
                    mime      = "application/x-mpegURL";
                }

                //Impossible to guess the right MIME without knowing source. Could be a live stream or direct profile f.ex.
                //List<string> profiles = ProfileMime.ResolveVideoProfile(profile.Value.MediaTranscoding.Video[0].Target.VideoContainerType, profile.Value.MediaTranscoding.Video[0].Target.VideoCodecType,
                //  profile.Value.MediaTranscoding.Video[0].Target.AudioCodecType, profile.Value.MediaTranscoding.Video[0].Target.EncodingProfileType, profile.Value.MediaTranscoding.Video[0].Target.LevelMinimum,
                //   0, maxWidth, maxHeight, profile.Value.MediaTranscoding.Video[0].Target.MaxVideoBitrate, profile.Value.MediaTranscoding.Video[0].Target.AudioBitrate, Transcoding.Service.Timestamp.None);
                //ProfileMime.FindCompatibleMime(profile.Value, profiles, ref mime);
            }

            WebTranscoderProfile webTranscoderProfile = new WebTranscoderProfile
            {
                Bandwidth       = bandwith,
                Description     = profile.Value.Name,
                HasVideoStream  = true,
                MIME            = mime,
                MaxOutputHeight = maxHeight,
                MaxOutputWidth  = maxWidth,
                Name            = profile.Value.Name,
                Targets         = profile.Value.Targets,
                Transport       = transport
            };

            return(webTranscoderProfile);
        }