/// <summary> /// Stop the encoding process /// </summary> public void Stop() { if (cam != null) { cam.Pause(); } if (mic != null) { mic.Pause(); } EncoderRunning = false; if (coreloops != null) { foreach (var loop in coreloops) { loop.Join(); // wait for the encoder to get the message and actually stop. Easier than screwing it's state data. } } try { cam.Dispose(); } catch { } try { mic.Dispose(); } catch { } foreach (var pkg in Packages) { try { EncoderBridge.CloseEncoderJob(ref pkg.Job); } catch { } } if (outputRouter != null) { outputRouter.Close(); } }
/// <summary> /// This loop does the actual work of reading caches into the encoder and firing actions. /// This loop controls Multiple-bit-rate encoding /// </summary> private void EncoderCoreLoop(object Package) { EncoderPackage pkg = Package as EncoderPackage; try { #region Start up if (pkg == null) { throw new Exception("Encoder core loop package was lost"); } double lastVideoTime = 0.0; // used for Adaptive frame rate if (cam != null) { lastVideoTime = cam.TimecodeStart; } int loop_frame_incr = 0; if (pkg.Specification.HasVideo) { loop_frame_incr = 1; videoJobs++; } #endregion while (!EncoderRunning) // wait for the signal! { System.Threading.Thread.Sleep(1000); } WaitForSyncFlag(); start = DateTime.Now; while (EncoderRunning) // Encode frames until stopped { #region Frame availability checks // Wait for buffers to be populated while (pkg.BuffersEmpty(MinimumBufferPopulation) && EncoderRunning) { foreach (var buf in pkg.Buffers) { buf.RebufferCapturedFrames(); } if (pkg.BuffersEmpty(MinimumBufferPopulation)) { System.Threading.Thread.Sleep(frameSleep); } } if (DryRun) { System.Threading.Thread.Sleep(frameSleep); continue; // don't encode } #endregion pkg.LoadAllBuffers(); EncoderBridge.EncodeFrame(ref pkg.Job, ref pkg.Frame); pkg.UnloadAllBuffers(); if (!pkg.Job.IsValid) { throw new Exception("Job became invalid. Possible memory or filesystem error"); } #region Segment switching if (pkg.Job.SegmentNumber != pkg.Job.OldSegmentNumber) { double real_chunk_duration = pkg.Frame.VideoSampleTime - lastVideoTime; lock (outputRouter) { outputRouter.NewChunkAvailable(pkg.Job.OldSegmentNumber, pkg.JobIndex, real_chunk_duration); } lastVideoTime = pkg.Frame.VideoSampleTime; pkg.Job.OldSegmentNumber = pkg.Job.SegmentNumber; } FrameCount += loop_frame_incr; #endregion } } catch (Exception ex) { System.Diagnostics.Debug.Fail("EncoderController.cs: Core loop fault.", ex.Message + "\r\n" + ex.StackTrace); File.WriteAllText(config.EncoderSettings.LocalSystemOutputFolder + @"/error.txt", "Main loop: " + ex.Message + "\r\n" + ex.StackTrace); } finally { if (pkg != null) { EncoderBridge.CloseEncoderJob(ref pkg.Job); // NEVER FORGET THIS!! } if (EncoderRunning) { Halt(); // Don't use 'Stop()' in the core loop, or the system will freeze! } System.Threading.Thread.CurrentThread.Abort(); } }