/// <summary> /// Stop rendering video. /// Note, this method may be called multiple times in a row. /// </summary> public void Stop() { Deployment.Current.Dispatcher.BeginInvoke(() => { if (!this.isRendering) return; // Nothing more to be done Debug.WriteLine("[VoIP Background Process] Video rendering stopped."); mediaStreamSource.Shutdown(); mediaStreamSource.Dispose(); mediaStreamSource = null; mediaStreamer.Dispose(); mediaStreamer = null; this.isRendering = false; }); }
/// <summary> /// Stop a streamer and remove it from the local list of streamers /// </summary> /// <param name="streamerID"></param> /// <returns></returns> public bool StopStreamer(int streamerID) { if (Settings.Default.DebugStreaming) { Functions.WriteLineToLogFile("StreamingManager: Received stop command for streamer " + streamerID.ToString()); } try { MediaStreamer mediaStreamer = GetStreamerByID(streamerID); if (mediaStreamer == null) { return(false); } // Abort streamer (on a different thread) AbortMediaStreamerAndDeleteFiles((object)mediaStreamer); /* * System.Threading.ParameterizedThreadStart ts = new System.Threading.ParameterizedThreadStart(AbortMediaStreamerAndDeleteFiles); * System.Threading.Thread t_abortStreamer = new System.Threading.Thread(ts); * t_abortStreamer.Start(mediaStreamer); */ // Remove from streamers RemoveStreamer(streamerID); return(true); } catch (Exception ex) { Functions.WriteExceptionToLogFileIfAdvanced(ex); } return(false); }
public MainForm() { InitializeComponent(); mediaStreamer = new MediaStreamer(); mediaStreamer.StateChanged += MediaStreamer_StateChanged; //Validate session... currentSession = Config.Data.Session; usbManager = new UsbDeviceManager(); usbManager.Init(UsbCategory.VideoCamera); usbManager.UsbDeviceArrival += UsbManager_UsbDeviceArrival; usbManager.UsbDeviceMoveComplete += UsbManager_UsbDeviceMoveComplete; syncContext = SynchronizationContext.Current; InitControls(); var startupParams = Program.StartupParams; if (startupParams.IsSystem) { var caption = this.Text; caption = caption + " (" + startupParams.UserName + ")"; this.Text = caption; } }
void AddNewStreamer(MediaStreamer newStreamer) { mediaStreamers.Add(newStreamer.ID, newStreamer); // Power options SetPowerOptions(); }
void AddNewStreamer(MediaStreamer newStreamer) { mediaStreamers.Add(newStreamer.ID, newStreamer); if (newStreamer.Request.OnlyTranscodeOnServer) { List <MediaStreamingRequest> msrlist = MediaStreamer.DeserializeTranscodedMSRFromXML(); List <MediaStreamingRequest> msrlist2 = new List <MediaStreamingRequest>(); for (int i = 0; i < msrlist.Count; i++) { MediaStreamingRequest msr = msrlist[i]; if (msr.InputFile.Equals(newStreamer.Request.InputFile) && msr.UniekClientID.Equals(newStreamer.Request.UniekClientID)) { } else { msrlist2.Add(msr); } } msrlist2.Add(newStreamer.Request); MediaStreamer.SerializeTranscodedMSRToXML(msrlist2); } // Power options SetPowerOptions(); }
/// <summary> /// Raised by a streamer after around 10 minutes of inactivity when it auto dies /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void mediaStreamer_AutoDied(object sender, EventArgs e) { MediaStreamer ms = (MediaStreamer)sender; if (Settings.Default.DebugStreaming) { Functions.WriteLineToLogFile("StreamingManager: Received notification that streamer " + ms.ID.ToString() + " auto-died."); } RemoveStreamer(ms.ID); }
public bool SegmentFromStreamer(int streamerID, int segmentNumber, ref byte[] Data, ref string txtError) { MediaStreamer ms = GetStreamerByID(streamerID); if (ms == null) { txtError = "No such streamer."; return(false); } return(ms.GetSegment(segmentNumber, ref Data, ref txtError)); }
/// <summary> /// Legacy for older iOS clients /// </summary> /// <param name="streamerID"></param> /// <returns></returns> public string KeepStreamerAliveAndReturnStatus(int streamerID) { MediaStreamer mediaStreamer = GetStreamerByID(streamerID); if (mediaStreamer == null) { return("disposed"); } return("streamavailable"); // stream is always available now }
void AbortMediaStreamerAndDeleteFiles(object obj) { try { MediaStreamer ms = (MediaStreamer)obj; ms.AbortStreaming(true); } catch (Exception ex) { // Must catch exceptions on other threads Functions.WriteExceptionToLogFileIfAdvanced(ex); } }
private void MaakInitialM3U8ForNewLiveTV(string WorkingDirectory, int StreamerID) { MediaStreamer ms = GetStreamerByID(StreamerID); int msSegmentDuration = ms.Request.ActualSegmentDuration; StringBuilder sbIndexFile = new StringBuilder(1000); sbIndexFile.AppendLine("#EXTM3U"); sbIndexFile.AppendLine("#EXT-X-VERSION:3"); sbIndexFile.AppendLine("#EXT-X-TARGETDURATION:" + (msSegmentDuration * 3)); // maximum duration of any one file, in seconds, the ffmpeg segmenter rather fluctuates // I don't think mx player likes this changing ext-duration, so we set it at 3 times initially sbIndexFile.AppendLine("#EXT-X-MEDIA-SEQUENCE:1"); sbIndexFile.AppendLine("#EXT-X-ALLOW-CACHE:YES"); // allow client to cache files sbIndexFile.AppendLine("start here"); //sbIndexFile.AppendLine(TSFilesinM3U8(StreamerID, msSegmentDuration, 0)); //sbIndexFile.AppendLine("#EXT-X-ENDLIST"); using (StreamWriter sw = new StreamWriter(WorkingDirectory + "\\CurrentIndex.m3u8")) sw.Write(sbIndexFile.ToString()); return; }
public string IndexFileForStreamer(int StreamerID) { MediaStreamer ms = GetStreamerByID(StreamerID); TimeSpan mediaDuration = FileBrowseExporter.DurationOfMediaFile_OSSpecific(ms.Request.InputFile); int msSegmentDuration = ms.Request.ActualSegmentDuration; StringBuilder sbIndexFile = new StringBuilder(1000); sbIndexFile.AppendLine("#EXTM3U"); sbIndexFile.AppendLine("#EXT-X-TARGETDURATION:" + msSegmentDuration.ToString()); // maximum duration of any one file, in seconds sbIndexFile.AppendLine("#EXT-X-ALLOW-CACHE:YES"); // allow client to cache files double dNumberSegments = mediaDuration.TotalSeconds / Convert.ToDouble(msSegmentDuration); int WholeNumberSegments = Convert.ToInt32(Math.Floor(dNumberSegments)); int i; for (i = 0; i < WholeNumberSegments; i++) { sbIndexFile.AppendLine("#EXTINF:" + msSegmentDuration.ToString() + ","); string strSegID = "seg-" + i.ToString() + ".ts"; sbIndexFile.AppendLine(strSegID); } // Duration of final segment? double dFinalSegTime = mediaDuration.TotalSeconds % Convert.ToDouble(msSegmentDuration); int iFinalSegTime = Convert.ToInt32(dFinalSegTime); sbIndexFile.AppendLine("#EXTINF:" + iFinalSegTime.ToString() + ","); string strFinalSegID = "seg-" + i.ToString() + ".ts"; sbIndexFile.AppendLine(strFinalSegID); sbIndexFile.AppendLine("#EXT-X-ENDLIST"); return(sbIndexFile.ToString()); }
void RemoveStreamer(int id) { MediaStreamer ms = GetStreamerByID(id); if (ms != null) { mediaStreamers.Remove(id); } // Power options SetPowerOptions(); #if !DEBUG // Delete the streaming files. If there are no streamers left, delete all streaming files if (mediaStreamers.Count > 0) { DeleteStreamingFiles(id); } else { DeleteAllStreamingFiles(); } #endif }
public MediaStreamModel() { mediaStreamer = new MediaStreamer(); mediaStreamer.StateChanged += MediaStreamer_StateChanged; }
private void StartMediaStreamer() { if (mediaStreamer == null) { mediaStreamer = MediaStreamerFactory.CreateMediaStreamer(123); } // Using default resolution of 640x480 mediaStreamSource = new VideoMediaStreamSource(null, 640, 480); mediaStreamer.SetSource(mediaStreamSource); }
public MediaStreamingResult StartStreamer(MediaStreamingRequest request, string HostName) { int newStreamerID = newUniqueID(); // Universal workaround: can be removed once new iOS app introduced that sets the Client Device to 'iphone3g' // (desirable to remove it since this will also affect silverlive streaming) if (string.IsNullOrEmpty(request.ClientID)) { request.ClientID = "ios"; request.ClientDevice = "iphone3g"; } try { // Legacy clients (e.g. iOS client) don't have any custom parameters - set them now based on 'Quality' if (!request.UseCustomParameters) // if there are no custom parameters { // Create/update video encoding parameters (also transfers Aspect Ratio into child 'encoding parameters' object) MediaStreamingRequest.AddVideoEncodingParametersUsingiOSQuality(ref request); } /* ************************************************************ * // Override any video encoding parameters from server settings ************************************************************ */ // 1. Audio Volume if (Settings.Default.StreamingVolumePercent != 100) { request.CustomParameters.AudioVolumePercent = Convert.ToInt32(Settings.Default.StreamingVolumePercent); } // 2. Custom FFMPEG template if ((Settings.Default.UseCustomFFMpegTemplate) & (!string.IsNullOrWhiteSpace(Settings.Default.CustomFFMpegTemplate))) { request.CustomParameters.CustomFFMpegTemplate = Settings.Default.CustomFFMpegTemplate.Trim(); } // 3. iPhone 3G requires profile constraints if (request.ClientDevice.ToLowerInvariant() == "iphone3g") { request.CustomParameters.X264Level = 30; request.CustomParameters.X264Profile = "baseline"; } // 4. Deinterlace obvious WMC video if ( (request.InputFile.ToUpper().EndsWith("WTV")) || (request.InputFile.ToUpper().EndsWith("DVR-MS")) ) { request.CustomParameters.DeInterlace = true; } // Create the streamer MediaStreamer mediaStreamer = new MediaStreamer(newStreamerID, request, Functions.ToolkitFolder, Settings.Default.MediaStreamerSecondsToKeepAlive, Settings.Default.DebugAdvancedStreaming); mediaStreamer.DebugMessage += new EventHandler <FatAttitude.GenericEventArgs <string> >(mediaStreamer_DebugMessage); mediaStreamer.AutoDied += new EventHandler(mediaStreamer_AutoDied); AddNewStreamer(mediaStreamer); Functions.WriteLineToLogFile("MediaStreamer: mediaStreamer object created."); // Try streaming MediaStreamingResult result = mediaStreamer.Configure(); // this does actually begin transcoding result.LiveStreamingIndexPath = "/httplivestream/" + newStreamerID.ToString() + "/index.m3u8"; // Add streamer ID to result result.StreamerID = newStreamerID; // Return return(result); } catch (Exception e) { Functions.WriteLineToLogFile("Exception setting up mediaStreaming object:"); Functions.WriteExceptionToLogFile(e); return(new MediaStreamingResult(MediaStreamingResultCodes.NamedError, e.Message)); } }
public string IndexFileForStreamer(int StreamerID, bool background) { MediaStreamer ms = GetStreamerByID(StreamerID); ms.Request.InputFile = HttpUtility.HtmlDecode(ms.Request.InputFile); TimeSpan mediaDuration = (!(ms.Request.LiveTV || ms.Request.NewLiveTV) ? FileBrowseExporter.DurationOfMediaFile_OSSpecific(ms.Request.InputFile) : new TimeSpan(0, ms.Request.DurationLiveTVBlocks, 0)); int msSegmentDuration = ms.Request.ActualSegmentDuration; StringBuilder sbIndexFile = new StringBuilder(1000); string WorkingDirectory = "c:\\"; if (background) { // StopStreamer(StreamerID, 99); } if (ms.Request.NewLiveTV) { if (LiveTVParts.usingVLCWithsegmenter || LiveTVParts.UseVLCHLSsegmenter || LiveTVParts.dontUsePipe) { // do it the old style } else { //if (Settings.Default.DebugStreaming) // Functions.WriteLineToLogFile2("StreamingManager: client asks to generate new m3u8, resistance is futile"); string rpPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "RemotePotato"); WorkingDirectory = Path.Combine(rpPath, "static\\mediastreams\\" + StreamerID.ToString()); if (!Directory.Exists(WorkingDirectory)) { Directory.CreateDirectory(WorkingDirectory); } if (!File.Exists(WorkingDirectory + "\\livetvtemp0.m3u8")) { return(""); } var fs = File.Open(WorkingDirectory + "\\livetvtemp0.m3u8", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); var sr2 = new StreamReader(fs); string m3u8File = sr2.ReadToEnd(); return(m3u8File); } } sbIndexFile.AppendLine("#EXTM3U"); if (ms.Request.UseNewerFFMPEG) { sbIndexFile.AppendLine("#EXT-X-TARGETDURATION:" + (msSegmentDuration + 1)); // maximum duration of any one file, in seconds } else { sbIndexFile.AppendLine("#EXT-X-TARGETDURATION:" + msSegmentDuration.ToString()); // maximum duration of any one file, in seconds } sbIndexFile.AppendLine("#EXT-X-ALLOW-CACHE:YES"); // allow client to cache files double dNumberSegments; if (ms.Request.LiveTV)// || ms.Request.NewLiveTV) { int q = ms.Request.InitialWaitTimeBeforeLiveTVStarts; int r = ms.Request.SegmentIncreasingStepsLiveTV; double StartAtSegmentWhereCalculatedSegmentDurationIsMax = (msSegmentDuration - q) / r; double StartAtSecondsWhereCalculatedSegmentDurationIsMax = (Math.Min(q + (int)StartAtSegmentWhereCalculatedSegmentDurationIsMax * r, msSegmentDuration) - q) * (Math.Min(q + (int)StartAtSegmentWhereCalculatedSegmentDurationIsMax * r, msSegmentDuration) + q - r) / (2 * r); dNumberSegments = (mediaDuration.TotalSeconds - StartAtSecondsWhereCalculatedSegmentDurationIsMax) / msSegmentDuration + StartAtSegmentWhereCalculatedSegmentDurationIsMax; } else //never change a winning team: { dNumberSegments = mediaDuration.TotalSeconds / Convert.ToDouble(msSegmentDuration); } int WholeNumberSegments = Convert.ToInt32(Math.Floor(dNumberSegments)); int i; // int OldSegmentDuration = 2; int SegmentDuration; string strSegID = ""; int from = (ms.Request.NewLiveTV?1:0); for (i = from; i < WholeNumberSegments; i++) // TODO: for newlivetv: have to cheang wholenumbersegments to differrent nr (higher) cuz now also segmnent<4sec { if (ms.Request.LiveTV) // || ms.Request.NewLiveTV) { SegmentDuration = Math.Min(msSegmentDuration, ms.Request.InitialWaitTimeBeforeLiveTVStarts + i * ms.Request.SegmentIncreasingStepsLiveTV); //make segments q second bigger untill 60 seconds reached // start with 4 seconds first then gradually increase up to 1 minute of segmentlength sbIndexFile.AppendLine("#EXTINF:" + SegmentDuration.ToString() + ","); // sbIndexFile.AppendLine("#EXTINF:4,"); } else { if (ms.Request.UseNewerFFMPEG) { sbIndexFile.AppendLine("#EXTINF:" + msSegmentDuration.ToString() + ".0,"); } else { sbIndexFile.AppendLine("#EXTINF:" + msSegmentDuration.ToString() + ","); } } if (!ms.Request.NewLiveTV) { if (background) { strSegID = "segbackground-" + i.ToString() + ".ts"; } else { strSegID = "seg-" + i.ToString() + ".ts"; } } else { strSegID = "liveseg-" + i + ".ts"; } sbIndexFile.AppendLine(strSegID); } // Duration of final segment? TODO for NEWLIVETV double dFinalSegTime; if (ms.Request.LiveTV) //|| ms.Request.NewLiveTV) { dFinalSegTime = (dNumberSegments - WholeNumberSegments) * msSegmentDuration; // TODO: should also take inot account special case where totalduration smalller than when mssegmentduration segments appear } else { dFinalSegTime = mediaDuration.TotalSeconds % Convert.ToDouble(msSegmentDuration); } int iFinalSegTime = Convert.ToInt32(dFinalSegTime); if (iFinalSegTime > 0) // adding this prevents stream from freezing at end { sbIndexFile.AppendLine("#EXTINF:" + iFinalSegTime.ToString() + ","); string strFinalSegID = ""; if (!ms.Request.NewLiveTV) { if (background) { strFinalSegID = "segbackground-" + i.ToString() + ".ts"; } else { strFinalSegID = "seg-" + i.ToString() + ".ts"; } } else { strFinalSegID = "liveseg-" + i + ".ts"; } sbIndexFile.AppendLine(strFinalSegID); } sbIndexFile.AppendLine("#EXT-X-ENDLIST"); TextWriter tw = new StreamWriter(Functions.AppDataFolder + "\\static\\mediastreams\\" + StreamerID + "\\index.m3u8"); tw.Write(sbIndexFile.ToString()); tw.Close(); return(sbIndexFile.ToString()); }