/// <summary> /// Initializes a new instance of the <see cref="Irseny.Core.Sensors.VideoCapture.VideoFrame"/> class. /// </summary> /// <param name="width">Width.</param> /// <param name="height">Height.</param> /// <param name="format">Pixel format.</param> /// <param name="data">Pixel data.</param> /// <param name="metadata">Associated metadata.</param> public VideoFrame(int width, int height, RasterImagePixelFormat format, byte[] data, VideoFrameMetadata metadata) { if (width < 0 || width > 16384) { throw new ArgumentOutOfRangeException("width"); } if (height < 0 || height > 16884) { throw new ArgumentOutOfRangeException("height"); } if (data == null) { throw new ArgumentNullException("data"); } if (metadata.FrameRate < 0) { throw new ArgumentOutOfRangeException("metadata.FrameRate"); } if (metadata.FrameTime < 0) { throw new ArgumentOutOfRangeException("metadata.FrameTime"); } if (metadata.FrameTimeDeviation < 0) { throw new ArgumentOutOfRangeException("metadata.FrameTimeVariance"); } Width = width; Height = height; PixelFormat = format; PixelData = data; Metadata = metadata; }
/// <inheritdoc/> public SensorDataPacket Process(long timestamp) { lock (captureSync) { if (!Capturing) { return(null); } long startTime = rateAnalyzer.GetTimeStamp(); // TODO implrement prediction service and divide split multiple calls into grab begin/end // get image and metadata from the backend if (!VideoCaptureBackend.BeginVideoCaptureFrameGrab(videoCapture)) { return(null); } if (!VideoCaptureBackend.EndVideoCaptureFrameGrab(videoCapture)) { return(null); } long endTime = rateAnalyzer.GetTimeStamp(); if (endTime - startTime > 0) { Console.WriteLine("waited additional " + (endTime - startTime) + "ms for the next frame"); } rateAnalyzer.Tick(); int width = VideoCaptureBackend.GetVideoCaptureFrameProperty(videoFrame, VideoFrameProperty.Width); int height = VideoCaptureBackend.GetVideoCaptureFrameProperty(videoFrame, VideoFrameProperty.Height); RasterImagePixelFormat format = (RasterImagePixelFormat)VideoCaptureBackend.GetVideoCaptureFrameProperty( videoFrame, VideoFrameProperty.PixelFormat); int pixelSize = VideoFrame.GetPixelSize(format); // construct a data packet as result if (width < 0 || width >= 16384 || height < 0 || height >= 16384 || pixelSize < 1 || pixelSize > 16) { return(null); } int imageSize = width * height * pixelSize; byte[] image = new byte[imageSize]; GCHandle imageBuffer = GCHandle.Alloc(image, GCHandleType.Pinned); if (!VideoCaptureBackend.CopyVideoCaptureFrame(videoFrame, imageBuffer.AddrOfPinnedObject(), imageSize)) { imageBuffer.Free(); return(null); } imageBuffer.Free(); var metadata = new VideoFrameMetadata() { FrameRate = rateAnalyzer.AverageFrameRate, FrameTime = rateAnalyzer.AverageFrameTime, FrameTimeDeviation = rateAnalyzer.StandardFrameTimeDeviation }; var frame = new VideoFrame(width, height, format, image, metadata); // TODO generate packet id return(new SensorDataPacket(this, SensorDataType.Video, frame, 0)); } }
/// <summary> /// Gets the size of a single hypothetical pixel in memory. /// </summary> /// <returns>The pixel size.</returns> /// <param name="format">Format of the pixel.</param> public static int GetPixelSize(RasterImagePixelFormat format) { switch (format) { case RasterImagePixelFormat.Gray8: return(sizeof(byte) * 1); case RasterImagePixelFormat.Gray16: return(sizeof(byte) * 2); case RasterImagePixelFormat.RGB24: return(sizeof(byte) * 3); case RasterImagePixelFormat.ARGB32: return(sizeof(byte) * 4); default: return(-1); } }
/// <summary> /// Gets the bitmap format that corresponds to the given video frame format. /// </summary> /// <returns>The target format.</returns> /// <param name="format">Source format.</param> public static BitmapPixelFormat GetBitmapFormat(RasterImagePixelFormat format) { switch (format) { case RasterImagePixelFormat.Gray8: return(BitmapPixelFormat.Alpha); case RasterImagePixelFormat.Gray16: return(BitmapPixelFormat.Format16bppGrayScale); case RasterImagePixelFormat.RGB24: return(BitmapPixelFormat.Format24bppRgb); case RasterImagePixelFormat.ARGB32: return(BitmapPixelFormat.Format32bppArgb); default: throw new ArgumentException("No complementary format found", "format"); } }