/// <summary> /// Send any queued outputs inclusively inside the specified range. /// Queued outputs less than the minimum will be dropped. /// Setting the maximum to -1 will re-enable output (same as 'EnableOutput = true') and /// send all queued outputs. /// </summary> /// <param name="MinimumChunkIndex">Inclusive minimum chunk to send</param> /// <param name="MaximumChunkIndex">Inclusive maximum chunk to send</param> /// <remarks>To enable output while clearing all queued outputs, call as 'SendOutput(Job.SegmentNumber, -1)'</remarks> public void SendOutput(int MinimumChunkIndex, int MaximumChunkIndex) { lock (SyncLock) { int max = (MaximumChunkIndex >= 0) ? (MaximumChunkIndex) : (int.MaxValue); int jobs_to_run = 0; // number of output workers to start. List <ChunkDetail> chunks_waiting = ChunksCompleted.ToList(); chunks_waiting.Sort((a, b) => a.ChunkIndex.CompareTo(b.ChunkIndex)); ChunksCompleted.Clear(); foreach (var chunk in chunks_waiting) { if (chunk.ChunkIndex > max) { ChunksCompleted.Enqueue(chunk); continue; } if (chunk.ChunkIndex >= MinimumChunkIndex) { jobs_to_run++; // note another job to be run. ChunksCompleted.Enqueue(chunk); } else { // drop this file. FilesCompleted.Enqueue(new FileInfo(chunk.SourceFilePath)); } } // run jobs that are waiting and not removed. for (int i = 0; i < jobs_to_run; i++) { System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ChunkAction)); } if (MaximumChunkIndex < 0) { EnableOutput = true; } } }
/// <summary> /// Close this output path and clean up any connections /// </summary> public void Close() { if (SelectedHandler != null) { SelectedHandler.FileConsumed -= SelectedHandler_FileConsumed; SelectedHandler.Close(); } while (FilesCompleted.Count > 0) { FilesCompleted.Dequeue().Delete(); } // clean up leftovers: if (ShouldCleanup) { while (ChunksCompleted.Count > 0) { new FileInfo(ChunksCompleted.Dequeue().SourceFilePath).Delete(); } } }
/// <summary> /// Signal the output to consume the given chunk. /// Should only be called by the encoder. /// </summary> public void NewChunkAvailable(int ChunkIndex, int StreamIndex, double CaptureDuration) { if (SelectedHandler == null) { throw new Exception("Output handler was not initialised"); } string joined = Path.Combine(Config.EncoderSettings.LocalSystemOutputFolder, Config.EncoderSettings.LocalSystemFilePrefix); string chunk_path = joined + "_" + StreamIndex + "-" + ChunkIndex.ToString("00000") + ".ts"; ChunkDetail chunk = new ChunkDetail(chunk_path, ChunkIndex, StreamIndex, CaptureDuration); lock (ChunksCompleted) { ChunksCompleted.Enqueue(chunk); } if (EnableOutput) { // Force work on a seperate thread, to prevent any interference with encoding. // Encoder output to local system SHOULD be unaffected by delays in output handler. // Final output MAY be delayed, but SHOULD be correct. System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ChunkAction)); } }