protected override void ProcessEntry(long position, Frame entry) { if (!allocated) { return; } long then = stopwatch.ElapsedMilliseconds; // We don't move back this call to the UI thread. // During recording we extract frames from the delayer on that very same thread, // and for the display it's not critical that the images be broken. (less critical than switching context each frame). // As this mode is tailored for delay scenario, in all likelihood the display is not going to be reading the frame we are writing to. bool pushed = delayer.Push(entry); if (!pushed) { // Very critical error. Most likely cross thread access to the same frame. // Let's deactivate to avoid looping on the error. log.ErrorFormat("Critical error while trying to push frame to delayer."); DoStopRecord(); Deactivate(); } if (stopRecordAsked) { DoStopRecord(); } else if (recording) { // Extract a bitmap from delayer at right delay and convert it into a frame for the writer. // Note that we do not go through the delay compositer. We only support "normal" delay here. // Compositers (e.g: quadrants with different ages) are only supported in display. bool copied = delayer.GetStrong(age, delayedFrame); if (copied) { writer.SaveFrame(delayerImageDescriptor.Format, delayedFrame.Buffer, delayedFrame.PayloadLength, delayerImageDescriptor.TopDown); } } Ellapsed = stopwatch.ElapsedMilliseconds - then; }
private void GrabFrame() { // 1. Consume a frame for display purposes (= push to delay buffer). // 2. Get a frame to display (= pull from delay buffer). // // This can be synchronized with the camera frame signals or it can be on an independant timer. // The consumer display never blocks and always get the latest frame from the ring buffer. // This means that it may miss some frames, especially if it is on a lower frequency timer. // It is considered acceptable for display purposes, the recorder consumer works differently. if (!cameraConnected) { return; } consumerDisplay.ConsumeOne(); Bitmap fresh = consumerDisplay.Bitmap; if (fresh == null) { return; } delayer.Push(fresh); if (imageProcessor.Active) { imageProcessor.Update(fresh); } if (recording && recordingThumbnail == null) { recordingThumbnail = BitmapHelper.Copy(fresh); } // Get the image to display. Bitmap delayed = delayCompositer.Get(delay); viewportController.Bitmap = delayed; }