/// <summary> /// This acquires a new CameraFrame from the pool and copies the pixel data through the internal IBuffer. /// </summary> /// <param name="bmpFrame">The software bitmap from the camera</param> /// <returns>The camera frame (with the pixel data copied already)</returns> public CameraFrameInternal AcquireFrame(SoftwareBitmap bmpFrame, PixelFormat desiredPixelFormat) { lock (frameLock) { CameraFrameInternal frame = null; // convert the data format and get the data size - PixelFormat pixelFormat = PixelHelpers.ConvertFormat(bmpFrame.BitmapPixelFormat); if (pixelFormat != desiredPixelFormat) { BitmapPixelFormat bitmapPixelFormat = PixelHelpers.ConvertFormat(desiredPixelFormat); bmpFrame = SoftwareBitmap.Convert(bmpFrame, PixelHelpers.ConvertFormat(desiredPixelFormat)); } int dataSize = PixelHelpers.GetDataSize(bmpFrame.PixelWidth, bmpFrame.PixelHeight, desiredPixelFormat); if (freeCameraFrames.Count > 0) { // find a frame with the required size buffer for (LinkedListNode <CameraFrameInternal> node = freeCameraFrames.First; node != null; node = node.Next) { // check if the pixel data array is the correct length if (node.Value != null && node.Value?.PixelData?.Length == dataSize) { // remove the frame from the free list freeCameraFrames.Remove(node); // add the frame to the used list (need to create a new node) frame = node.Value; usedCameraFrames.AddFirst(frame); } } } // if there were no free frames, create a new one if (frame == null) { frame = new CameraFrameInternal(this); frame.PixelData = new byte[dataSize]; frame.PixelDataBuffer = frame.PixelData.AsBuffer(); // add the new frame to the used camera frames list usedCameraFrames.AddFirst(frame); } // copy the pixel data to the frame through the internal IBuffer bmpFrame.CopyToBuffer(frame.PixelDataBuffer); return(frame); } }
private void OnMediaFrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args) { bool getFrame = false; lock (stateLock) { getFrame = (State == CameraState.CapturingContinuous || State == CameraState.CapturingSingle); // quickly handle state changes here (only changes if we're capturing a single image) if (State == CameraState.CapturingSingle) { State = CameraState.Ready; } } CameraFrameInternal frame = null; if (getFrame) { frame = GetFrameFromMediaFrameReader(sender); } if (frame != null) { // clean up state after frame if (CaptureMode == CaptureMode.SingleLowLatency) { // release previous frame and addref current frame if (latestFrame != null) { latestFrame.Release(); } // add ref for the camera frame.AddRef(); latestFrame = frame; } // callback any registered listeners OnFrameCaptured?.Invoke(this, frame); } }
public void ReleaseFrame(CameraFrameInternal frame) { lock (frameLock) { // remove the frame from the used list and add to the free list if (frame != null) { LinkedListNode <CameraFrameInternal> frameNode = usedCameraFrames.Find(frame); // if the frame was found, add to the free pile and remove from the used list if (frameNode != null) { // need to create a new node as nodes don't swap between linked lists freeCameraFrames.AddFirst(frameNode.Value); // remove from the current list usedCameraFrames.Remove(frameNode); } } } }
private CameraFrameInternal GetFrameFromMediaFrameReader(MediaFrameReader frameReader) { // get the latest frame MediaFrameReference frameReference = frameReader?.TryAcquireLatestFrame(); VideoMediaFrame videoFrame = frameReference?.VideoMediaFrame; SoftwareBitmap frameBmp = videoFrame?.SoftwareBitmap; CameraFrameInternal frame = null; if (frameBmp != null) { // get a camera frame and populate with the correct data for this frame - acquire copies the bitmap to the frame frame = framePool.AcquireFrame(frameBmp, desiredPixelFormat); frame.PixelFormat = desiredPixelFormat; frame.Resolution = Resolution; frame.FrameTime = frameReference.SystemRelativeTime.HasValue ? frameReference.SystemRelativeTime.Value.TotalSeconds : 0.0; frame.Exposure = frameReference.Duration.TotalSeconds; frame.Gain = Gain; if (KeepSoftwareBitmap) { frame.SoftwareBitmap = frameBmp; } else { frameBmp.Dispose(); } // extrinsics and intrinsics frame.Extrinsics = GetExtrinsics(frameReference.CoordinateSystem); frame.Intrinsics = ConvertIntrinsics(frameReference.VideoMediaFrame.CameraIntrinsics); } frameReference?.Dispose(); return(frame); }