protected virtual void onBlackScreen(BlackScreenEventArgs e) { if (frameBuffer[0] == null) { return; } BlackScreen?.Invoke(this, e); for (int i = 0; i < frameBuffer.Length; i++) { frameBuffer[i]?.Dispose(); frameBuffer[i] = null; } }
/// <summary> /// Main video processing loop /// </summary> public void processingLoop() { while (true) { try { initializeCaptureDevice(deviceId, resolution); //Initalize the currentFrame mat with a byte[] pointer so we can access its data directly without a conversion to Image<> byte[] data = new byte[frameSize.Width * frameSize.Height * 3]; GCHandle dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); Mat currentFrame = new Mat(frameSize, DepthType.Cv8U, 3, dataHandle.AddrOfPinnedObject(), frameSize.Width * 3); WasBlack = false; bool WasClear = false; bool WaitForClearStats = false; int skip = frameSize.Width / 50; DateTime blackStart = DateTime.Now; while (true) { if (shouldStop) { return; } cap.Retrieve(currentFrame); Dictionary <int, int> hues = getHues(data, frameSize, skip); if (WasBlack) { WasBlack = isBlackFrame(hues); if (!WasBlack) { BlackScreenEventArgs args = new BlackScreenEventArgs(); args.frameBuffer = copyFrameBuffer(); args.currentFrame = getLevelScreenImageFromBuffer(args.frameBuffer); args.seconds = DateTime.Now.Subtract(blackStart).TotalMilliseconds / 1000; onBlackScreen(args); } } else if (WasClear) { WasClear = isClearFrame(hues); if (!WasClear) { WaitForClearStats = true; } } else if (WaitForClearStats && isClearWithStatsScreen(hues)) { // HACK: Apart from taking up more CPU to do a comparision like the Level Select screen this is the best solution imo // Match happens during transition, so 500ms is long enough to get to the screen, but not long enough to exit and miss it. Thread.Sleep(593); cap.Retrieve(currentFrame); ClearScreenEventArgs args = new ClearScreenEventArgs(); args.currentFrame = currentFrame.Clone().ToImage <Bgr, Byte>(); // Check to see if this is the clear screen with comments on - things are positioned differently. // Top of screen is yellow if comments are on Size topOfScreen = new Size(frameSize.Width, frameSize.Height / 6); Dictionary <int, int> topHues = getHues(data, topOfScreen, skip); if (isMostlyYellow(topHues)) { args.commentsEnabled = true; } onClearScreen(args); } else if (isBlackFrame(hues)) { WasBlack = true; WaitForClearStats = false; // XXX: If we get a black screen and this is true, something weird is going on blackStart = DateTime.Now; } else if (isClearFrame(hues)) { WasClear = true; } } } catch (Exception ex) { log.Debug("Exception in main procesisng loop"); log.Error(ex); Thread.Sleep(5000); } } }