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()); }
public ActionResult Player(WebMediaType type, string itemId, int fileindex = 0) { PlayerViewModel model = new PlayerViewModel(); model.MediaType = type; model.MediaId = itemId; model.ContinuationId = randomGenerator.Next(100000, 999999).ToString(); // get profile var profile = GetProfile(GetStreamControl(type), GetDefaultProfile(type)); // get size if (type == WebMediaType.TV) { // TODO: we should start the timeshifting through an AJAX call, and then load the player based upon the results // from that call. Also avoids timeouts of the player when initiating the timeshifting takes a long time. // HACK: currently there is no method in WSS to get the aspect ratio for streams with a fixed aspect ratio. model.Size = GetStreamControl(type).GetStreamSize(type, null, "", 0, profile.Name); } else if (!StreamTarget.GetAllTargets().First(t => profile.Targets.Contains(t.Name)).HasVideo) { model.Size = new WebResolution() { Width = 600, Height = 100 }; } else { model.Size = GetStreamControl(type).GetStreamSize(type, GetProvider(type), itemId, 0, profile.Name); } // generate url RouteValueDictionary parameters = new RouteValueDictionary(); parameters["item"] = itemId; parameters["fileindex"] = fileindex; parameters["transcoder"] = profile.Name; parameters["continuationId"] = model.ContinuationId; model.URL = Url.Action(Enum.GetName(typeof(WebMediaType), type), parameters); // generic part var targets = type == WebMediaType.MusicTrack ? StreamTarget.GetAllTargets() : StreamTarget.GetVideoTargets(); return(CreatePlayer(GetStreamControl(type), model, targets, profile, false)); }
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 })); }