/// <summary> /// Creates a new instance of a Overlay renderer component. This component is identical to the <see cref="MMALVideoRenderer"/> class, however it provides /// the ability to overlay a static source onto the render overlay. /// </summary> /// <param name="parent">The parent renderer which is being used to overlay onto the display.</param> /// <param name="config">The configuration for rendering a static preview overlay.</param> /// <param name="source">A reference to the current stream being used in the overlay.</param> public MMALOverlayRenderer(MMALVideoRenderer parent, PreviewOverlayConfiguration config, byte[] source) : base(config) { this.Source = source; this.ParentRenderer = parent; this.OverlayConfiguration = config; parent.Overlays.Add(this); this.Inputs[0] = new OverlayPort(this.Inputs[0]); if (config != null) { if (config.Resolution.Width > 0 && config.Resolution.Height > 0) { this.Inputs[0].Resolution = config.Resolution; this.Inputs[0].Crop = new Rectangle(0, 0, config.Resolution.Width, config.Resolution.Height); } else { this.Inputs[0].Resolution = parent.Inputs[0].Resolution; this.Inputs[0].Crop = new Rectangle(0, 0, parent.Inputs[0].Resolution.Width, parent.Inputs[0].Resolution.Height); } this.Inputs[0].FrameRate = new MMAL_RATIONAL_T(0, 0); if (config.Encoding == null) { var sourceLength = source.Length; var planeSize = this.Inputs[0].Resolution.Pad(); var planeLength = Math.Floor((double)planeSize.Width * planeSize.Height); if (Math.Floor(sourceLength / planeLength) == 3) { config.Encoding = MMALEncoding.RGB24; } else if (Math.Floor(sourceLength / planeLength) == 4) { config.Encoding = MMALEncoding.RGBA; } else { throw new PiCameraError("Unable to determine encoding from image size."); } } this.Inputs[0].NativeEncodingType = config.Encoding.EncodingVal; } if (!this.AllowedEncodings.Any(c => c.EncodingVal == this.Inputs[0].NativeEncodingType)) { throw new PiCameraError($"Incompatible encoding type for use with Preview Render overlay {MMALEncodingHelpers.ParseEncoding(this.Inputs[0].NativeEncodingType).EncodingName}."); } this.Inputs[0].Commit(); this.Control.Start(); this.Inputs[0].Start(); }
/// <summary> /// Creates a new instance of a Overlay renderer component. This component is identical to the <see cref="MMALVideoRenderer"/> class, however it provides /// the ability to overlay a static source onto the render overlay. /// </summary> /// <param name="parent">The parent renderer which is being used to overlay onto the display.</param> /// <param name="config">The configuration for rendering a static preview overlay.</param> /// <param name="source">A reference to the current stream being used in the overlay.</param> public MMALOverlayRenderer(MMALVideoRenderer parent, PreviewOverlayConfiguration config, byte[] source) : base(config) { this.Source = source; this.ParentRenderer = parent; this.OverlayConfiguration = config; parent.Overlays.Add(this); if (config != null) { var width = 0; var height = 0; if (config.Resolution.Width > 0 && config.Resolution.Height > 0) { width = config.Resolution.Width; height = config.Resolution.Height; } else { width = parent.Inputs[0].Resolution.Width; height = parent.Inputs[0].Resolution.Height; } if (config.Encoding == null) { var sourceLength = source.Length; var planeSize = this.Inputs[0].Resolution.Pad(); var planeLength = Math.Floor((double)planeSize.Width * planeSize.Height); if (Math.Floor(sourceLength / planeLength) == 3) { config.Encoding = MMALEncoding.RGB24; } else if (Math.Floor(sourceLength / planeLength) == 4) { config.Encoding = MMALEncoding.RGBA; } else { throw new PiCameraError("Unable to determine encoding from image size."); } } if (!this.AllowedEncodings.Any(c => c.EncodingVal == this.Inputs[0].NativeEncodingType)) { throw new PiCameraError($"Incompatible encoding type for use with Preview Render overlay {this.Inputs[0].NativeEncodingType.ParseEncoding().EncodingName}."); } var portConfig = new MMALPortConfig(config.Encoding, null, width, height, 0, 0, 0, false, null, 0, 0); this.ConfigureInputPort(portConfig, null); this.Control.Start(); this.Inputs[0].Start(); } }
public void StaticOverlay() { TestHelper.BeginTest("StaticOverlay"); TestHelper.SetConfigurationDefaults(); MMALCameraConfig.StillResolution = Resolution.As03MPixel; MMALCameraConfig.StillEncoding = MMALEncoding.I420; MMALCameraConfig.StillSubFormat = MMALEncoding.I420; AsyncContext.Run(async() => { var filename = string.Empty; using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/tests/staticoverlay", "raw")) { TestHelper.CleanDirectory("/home/pi/images/tests"); TestHelper.CleanDirectory("/home/pi/images/tests/staticoverlay"); await _fixture.MMALCamera.TakeRawPicture(imgCaptureHandler); filename = imgCaptureHandler.GetFilepath(); } PreviewConfiguration previewConfig = new PreviewConfiguration { FullScreen = false, PreviewWindow = new Rectangle(160, 0, 640, 480), Layer = 2, Opacity = 1 }; MMALCameraConfig.StillResolution = Resolution.As1080p; MMALCameraConfig.StillEncoding = MMALEncoding.OPAQUE; using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/tests", "jpg")) using (var imgEncoder = new MMALImageEncoder(imgCaptureHandler)) using (var video = new MMALVideoRenderer(previewConfig)) { _fixture.MMALCamera.ConfigureCameraSettings(); video.ConfigureRenderer(); PreviewOverlayConfiguration overlayConfig = new PreviewOverlayConfiguration { FullScreen = true, PreviewWindow = new Rectangle(50, 0, 640, 480), Layer = 1, Resolution = new Resolution(640, 480), Encoding = MMALEncoding.I420, Opacity = 255 }; var overlay = _fixture.MMALCamera.AddOverlay(video, overlayConfig, File.ReadAllBytes(filename)); overlay.ConfigureRenderer(); overlay.UpdateOverlay(); // Create our component pipeline. imgEncoder.ConfigureOutputPort(0, MMALEncoding.JPEG, MMALEncoding.I420, 90); _fixture.MMALCamera.Camera.StillPort.ConnectTo(imgEncoder); _fixture.MMALCamera.Camera.PreviewPort.ConnectTo(video); _fixture.MMALCamera.PrintPipeline(); await _fixture.MMALCamera.ProcessAsync(_fixture.MMALCamera.Camera.StillPort); if (System.IO.File.Exists(imgCaptureHandler.GetFilepath())) { var length = new System.IO.FileInfo(imgCaptureHandler.GetFilepath()).Length; Assert.True(length > 0); } else { Assert.True(false, $"File {imgCaptureHandler.GetFilepath()} was not created"); } } }); }