/// <summary> /// Creates a new instance of the <see cref="MMALResizerComponent"/> class that can be used to change the size /// and the pixel format of resulting frames. /// </summary> /// <param name="handler">The capture handler associated with this component.</param> public unsafe MMALResizerComponent(ICaptureHandler handler) : base(MMAL_COMPONENT_DEFAULT_RESIZER) { // Default to use still image port behaviour. this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, PortType.Input, Guid.NewGuid())); this.Outputs.Add(new StillPort((IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); }
/// <summary> /// Creates a new instance of <see cref="MMALVideoEncoder"/>. /// </summary> /// <param name="handler">The capture handler.</param> /// <param name="split">Configure this component to split into multiple files.</param> public MMALVideoEncoder(ICaptureHandler handler, Split split = null) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER) { this.Split = split; this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, PortType.Input, Guid.NewGuid())); this.Outputs.Add(new VideoPort((IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); }
/// <summary> /// Self-contained method for capturing a continual images from the camera still port for a specified period of time. /// An MMALImageEncoder component will be created and attached to the still port. /// </summary> /// <param name="handler">The image capture handler to apply to the encoder component.</param> /// <param name="encodingType">The image encoding type e.g. JPEG, BMP.</param> /// <param name="pixelFormat">The pixel format to use with the encoder e.g. I420 (YUV420).</param> /// <param name="cancellationToken">A cancellationToken to trigger stop capturing.</param> /// <param name="burstMode">When enabled, burst mode will increase the rate at which images are taken, at the expense of quality.</param> /// <returns>The awaitable Task.</returns> public async Task TakePictureTimeout(ICaptureHandler handler, MMALEncoding encodingType, MMALEncoding pixelFormat, CancellationToken cancellationToken, bool burstMode = false) { if (burstMode) { this.Camera.StillPort.SetParameter(MMALParametersCamera.MMAL_PARAMETER_CAMERA_BURST_CAPTURE, true); } using (var imgEncoder = new MMALImageEncoder(handler)) using (var renderer = new MMALNullSinkComponent()) { this.ConfigureCameraSettings(); var portConfig = new MMALPortConfig(encodingType, pixelFormat, 90); imgEncoder.ConfigureOutputPort(portConfig); // Create our component pipeline. this.Camera.StillPort.ConnectTo(imgEncoder); this.Camera.PreviewPort.ConnectTo(renderer); // Camera warm up time await Task.Delay(2000).ConfigureAwait(false); while (!cancellationToken.IsCancellationRequested) { await this.ProcessAsync(this.Camera.StillPort).ConfigureAwait(false); } } }
/// <summary> /// Self-contained method for capturing a single image from the camera still port. /// An MMALImageEncoder component will be created and attached to the still port. /// </summary> /// <param name="handler">The image capture handler to apply to the encoder component.</param> /// <param name="encodingType">The image encoding type e.g. JPEG, BMP.</param> /// <param name="pixelFormat">The pixel format to use with the encoder e.g. I420 (YUV420).</param> /// <returns>The awaitable Task.</returns> public async Task TakePicture(ICaptureHandler handler, MMALEncoding encodingType, MMALEncoding pixelFormat) { using (var imgEncoder = new MMALImageEncoder(handler)) using (var renderer = new MMALNullSinkComponent()) { this.ConfigureCameraSettings(); var portConfig = new MMALPortConfig(encodingType, pixelFormat, 90); imgEncoder.ConfigureOutputPort(portConfig); // Create our component pipeline. this.Camera.StillPort.ConnectTo(imgEncoder); this.Camera.PreviewPort.ConnectTo(renderer); // Enable the image encoder output port. MMALLog.Logger.Info($"Preparing to take picture. Resolution: {this.Camera.StillPort.Resolution.Width} x {this.Camera.StillPort.Resolution.Height}. " + $"Encoder: {encodingType.EncodingName}. Pixel Format: {pixelFormat.EncodingName}."); // Camera warm up time await Task.Delay(2000).ConfigureAwait(false); await this.ProcessAsync(this.Camera.StillPort).ConfigureAwait(false); } }
/// <summary> /// Self-contained method for recording H.264 video for a specified amount of time. Records at 30fps, 25Mb/s at the highest quality. /// </summary> /// <param name="handler">The video capture handler to apply to the encoder.</param> /// <param name="cancellationToken">A cancellationToken to signal when to stop video capture.</param> /// <param name="split">Used for Segmented video mode.</param> /// <returns>The awaitable Task.</returns> public async Task TakeVideo(ICaptureHandler handler, CancellationToken cancellationToken, Split split = null) { if (split != null && !MMALCameraConfig.InlineHeaders) { MMALLog.Logger.Warn("Inline headers not enabled. Split mode not supported when this is disabled."); split = null; } using (var vidEncoder = new MMALVideoEncoder(handler, split)) using (var renderer = new MMALVideoRenderer()) { this.ConfigureCameraSettings(); var portConfig = new MMALPortConfig(MMALEncoding.H264, MMALEncoding.I420, 10, MMALVideoEncoder.MaxBitrateLevel4, null); vidEncoder.ConfigureOutputPort(portConfig); // Create our component pipeline. this.Camera.VideoPort.ConnectTo(vidEncoder); this.Camera.PreviewPort.ConnectTo(renderer); MMALLog.Logger.Info($"Preparing to take video. Resolution: {this.Camera.VideoPort.Resolution.Width} x {this.Camera.VideoPort.Resolution.Height}. " + $"Encoder: {vidEncoder.Outputs[0].EncodingType.EncodingName}. Pixel Format: {vidEncoder.Outputs[0].PixelFormat.EncodingName}."); // Camera warm up time await Task.Delay(2000).ConfigureAwait(false); await this.ProcessAsync(this.Camera.VideoPort, cancellationToken).ConfigureAwait(false); } }
/// <summary> /// Self-contained method for capturing timelapse images. /// An MMALImageEncoder component will be created and attached to the still port. /// </summary> /// <param name="handler">The image capture handler to apply to the encoder component.</param> /// <param name="encodingType">The image encoding type e.g. JPEG, BMP.</param> /// <param name="pixelFormat">The pixel format to use with the encoder e.g. I420 (YUV420).</param> /// <param name="timelapse">A Timelapse object which specifies the timeout and rate at which images should be taken.</param> /// <returns>The awaitable Task.</returns> /// <exception cref="ArgumentNullException"/> public async Task TakePictureTimelapse(ICaptureHandler handler, MMALEncoding encodingType, MMALEncoding pixelFormat, Timelapse timelapse) { int interval = 0; if (timelapse == null) { throw new ArgumentNullException(nameof(timelapse), "Timelapse object null. This must be initialized for Timelapse mode"); } using (var imgEncoder = new MMALImageEncoder(handler)) using (var renderer = new MMALNullSinkComponent()) { this.ConfigureCameraSettings(); var portConfig = new MMALPortConfig(encodingType, pixelFormat, 90); imgEncoder.ConfigureOutputPort(portConfig); // Create our component pipeline. this.Camera.StillPort.ConnectTo(imgEncoder); this.Camera.PreviewPort.ConnectTo(renderer); // Camera warm up time await Task.Delay(2000).ConfigureAwait(false); while (!timelapse.CancellationToken.IsCancellationRequested) { switch (timelapse.Mode) { case TimelapseMode.Millisecond: interval = timelapse.Value; break; case TimelapseMode.Second: interval = timelapse.Value * 1000; break; case TimelapseMode.Minute: interval = (timelapse.Value * 60) * 1000; break; } await Task.Delay(interval).ConfigureAwait(false); MMALLog.Logger.Info($"Preparing to take picture. Resolution: {imgEncoder.Outputs[0].Resolution.Width} x {imgEncoder.Outputs[0].Resolution.Height}. " + $"Encoder: {encodingType.EncodingName}. Pixel Format: {pixelFormat.EncodingName}."); await this.ProcessAsync(this.Camera.StillPort).ConfigureAwait(false); } } }
/// <summary> /// Self-contained method to capture raw image data directly from the Camera component - this method does not use an Image encoder. /// </summary> /// <returns>The awaitable Task</returns> public async Task TakeRawPicture(ICaptureHandler handler) { if (this.Camera.StillPort.ConnectedReference != null) { throw new PiCameraError("A connection was found to the Camera still port. No encoder should be connected to the Camera's still port for raw capture."); } if (handler == null) { throw new PiCameraError("No handler specified"); } this.Camera.Handler = handler; this.CheckPreviewComponentStatus(); //Enable the image encoder output port. try { MMALLog.Logger.Info($"Preparing to take raw picture - Resolution: {MMALCameraConfig.StillResolution.Width} x {MMALCameraConfig.StillResolution.Height}. " + $"Encoder: {MMALCameraConfig.StillEncoding.EncodingName}. Pixel Format: {MMALCameraConfig.StillSubFormat.EncodingName}."); //Camera warm up time await Task.Delay(2000); //Enable processing on the camera still port. this.Camera.EnableConnections(); this.Camera.Start(this.Camera.StillPort, new Action <MMALBufferImpl, MMALPortBase>(this.Camera.ManagedOutputCallback)); this.Camera.StillPort.Trigger = new Nito.AsyncEx.AsyncCountdownEvent(1); this.StartCapture(this.Camera.StillPort); //Wait until the process is complete. await this.Camera.StillPort.Trigger.WaitAsync(); //Stop capturing on the camera still port. this.StopCapture(this.Camera.StillPort); this.Camera.Stop(MMALCameraComponent.MMALCameraStillPort); //Close open connections and clean port pools. this.Camera.DisableConnections(); this.Camera.CleanPortPools(); } finally { this.Camera.Handler.Dispose(); } }
/// <summary> /// Self-contained method to capture raw image data directly from the Camera component - this method does not use an Image encoder. /// Note: We cannot use the OPAQUE encoding format with this helper method, the capture will not fail, but will not produce valid data. For reference, RaspiStillYUV uses YUV420. /// </summary> /// <param name="handler">The image capture handler to use to save image.</param> /// <returns>The awaitable Task.</returns> /// <exception cref="ArgumentNullException"/> /// <exception cref="PiCameraError"/> public async Task TakeRawPicture(ICaptureHandler handler) { if (this.Camera.StillPort.ConnectedReference != null) { throw new PiCameraError("A connection was found to the Camera still port. No encoder should be connected to the Camera's still port for raw capture."); } this.Camera.Handler = handler ?? throw new ArgumentNullException(nameof(handler)); using (var renderer = new MMALNullSinkComponent()) { this.ConfigureCameraSettings(); this.Camera.PreviewPort.ConnectTo(renderer); // Enable the image encoder output port. try { MMALLog.Logger.Info($"Preparing to take raw picture - Resolution: {MMALCameraConfig.StillResolution.Width} x {MMALCameraConfig.StillResolution.Height}. " + $"Encoder: {MMALCameraConfig.StillEncoding.EncodingName}. Pixel Format: {MMALCameraConfig.StillSubFormat.EncodingName}."); // Camera warm up time await Task.Delay(2000); this.Camera.Start(this.Camera.StillPort); this.Camera.StillPort.Trigger = new Nito.AsyncEx.AsyncCountdownEvent(1); this.StartCapture(this.Camera.StillPort); // Wait until the process is complete. await this.Camera.StillPort.Trigger.WaitAsync(); // Stop capturing on the camera still port. this.StopCapture(this.Camera.StillPort); this.Camera.Stop(MMALCameraComponent.MMALCameraStillPort); // Close open connections and clean port pools. this.Camera.DisableConnections(); this.Camera.CleanPortPools(); } finally { this.Camera.Handler.PostProcess(); this.Camera.Handler.Dispose(); this.Camera.Handler = null; } } }
/// <summary> /// Creates a new instance of the <see cref="MMALImageEncoder"/> class with the specified handler. /// </summary> /// <param name="handler">A handler to receive the encoded image data.</param> /// <param name="rawBayer">Specifies whether to include raw bayer image data.</param> /// <param name="useExif">Specifies whether any EXIF tags should be used.</param> /// <param name="continuousCapture">Configure component for rapid capture mode.</param> /// <param name="thumbnailConfig">Configures the embedded JPEG thumbnail.</param> /// <param name="exifTags">A collection of custom EXIF tags.</param> public MMALImageEncoder(ICaptureHandler handler, bool rawBayer = false, bool useExif = true, bool continuousCapture = false, JpegThumbnail thumbnailConfig = null, params ExifTag[] exifTags) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER) { this.RawBayer = rawBayer; this.UseExif = useExif; this.ExifTags = exifTags; this.ContinuousCapture = continuousCapture; this.JpegThumbnailConfig = thumbnailConfig; this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, PortType.Input, Guid.NewGuid())); if (this.ContinuousCapture) { this.Outputs.Add(new FastStillPort((IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); } else { this.Outputs.Add(new StillPort((IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); } }
/// <summary> /// Self-contained method to capture raw image data directly from the Camera component - this method does not use an Image encoder. /// Note: We cannot use the OPAQUE encoding format with this helper method, the capture will not fail, but will not produce valid data. For reference, RaspiStillYUV uses YUV420. /// </summary> /// <param name="handler">The image capture handler to use to save image.</param> /// <returns>The awaitable Task.</returns> /// <exception cref="ArgumentNullException"/> /// <exception cref="PiCameraError"/> public async Task TakeRawPicture(ICaptureHandler handler) { if (this.Camera.StillPort.ConnectedReference != null) { throw new PiCameraError("A connection was found to the Camera still port. No encoder should be connected to the Camera's still port for raw capture."); } this.Camera.StillPort.Handler = handler ?? throw new ArgumentNullException(nameof(handler)); using (var renderer = new MMALNullSinkComponent()) { this.ConfigureCameraSettings(); this.Camera.PreviewPort.ConnectTo(renderer); // Enable the image encoder output port. MMALLog.Logger.Info($"Preparing to take raw picture - Resolution: {this.Camera.StillPort.Resolution.Width} x {this.Camera.StillPort.Resolution.Height}. " + $"Encoder: {MMALCameraConfig.StillEncoding.EncodingName}. Pixel Format: {MMALCameraConfig.StillSubFormat.EncodingName}."); // Camera warm up time await Task.Delay(2000).ConfigureAwait(false); await this.ProcessAsync(this.Camera.StillPort).ConfigureAwait(false); } }
public override void Configure(IMmalPortConfig config, IInputPort copyFrom, ICaptureHandler handler) { CallbackHandler = new VideoOutputCallbackHandler(this, handler); if (config == null) { return; } PortConfig = config; copyFrom?.ShallowCopy(this); if (config.EncodingType != null) { NativeEncodingType = config.EncodingType.EncodingVal; } if (config.PixelFormat != null) { NativeEncodingSubformat = config.PixelFormat.EncodingVal; } var tempVid = Ptr->Format->Es->Video; try { Commit(); } catch { // If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MmalLog.Logger.LogWarning($"{Name}: Commit of output port failed. Attempting to reset values."); Ptr->Format->Es->Video = tempVid; Commit(); } if (config.ZeroCopy) { ZeroCopy = true; this.SetParameter(MmalParametersCommon.MmalParameterZeroCopy, true); } if (CameraConfig.VideoColorSpace != null && CameraConfig.VideoColorSpace.EncType == MmalEncoding.EncodingType.ColorSpace) { VideoColorSpace = CameraConfig.VideoColorSpace; } if (config.Bitrate > 0) { Bitrate = config.Bitrate; } EncodingType = config.EncodingType; PixelFormat = config.PixelFormat; BufferNum = Math.Max(BufferNumMin, config.BufferNum > 0 ? config.BufferNum : BufferNumRecommended); BufferSize = Math.Max(BufferSizeMin, config.BufferSize > 0 ? config.BufferSize : BufferSizeRecommended); Commit(); }
/// <summary> /// Creates a new instance of <see cref="VideoFileEncodeOutputPort"/>. /// </summary> /// <param name="ptr">The native pointer.</param> /// <param name="comp">The component this port is associated with.</param> /// <param name="type">The type of port.</param> /// <param name="guid">Managed unique identifier for this port.</param> /// <param name="handler">The capture handler for this port.</param> public VideoFileEncodeOutputPort(IntPtr ptr, MMALComponentBase comp, PortType type, Guid guid, ICaptureHandler handler) : base(ptr, comp, type, guid, handler) { }
protected MMALDownstreamHandlerComponent(string name, ICaptureHandler handler) : base(name) { this.Handler = handler; }
/// <summary> /// Creates a new instance of <see cref="MMALImageFileDecoder"/>. /// </summary> /// <param name="handler">The capture handle to use.</param> public unsafe MMALImageFileDecoder(ICaptureHandler handler) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_IMAGE_DECODER) { this.Inputs.Add(new ImageFileDecodeInputPort((IntPtr)(&(*this.Ptr->Input[0])), this, PortType.Input, Guid.NewGuid(), handler)); this.Outputs.Add(new ImageFileDecodeOutputPort((IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); }
/// <summary> /// Creates a new instance of <see cref="FastStillPort"/>. /// </summary> /// <param name="ptr">The native pointer.</param> /// <param name="comp">The component this port is associated with.</param> /// <param name="type">The type of port.</param> /// <param name="guid">Managed unique identifier for this port.</param> /// <param name="handler">The capture handler for the output port.</param> public FastStillPort(IntPtr ptr, MMALComponentBase comp, PortType type, Guid guid, ICaptureHandler handler) : base(ptr, comp, type, guid, handler) { }
public virtual unsafe IDownstreamComponent ConfigureOutputPort <TPort>(int outputPort, IMmalPortConfig config, ICaptureHandler handler) where TPort : IOutputPort { Outputs[outputPort] = (IOutputPort)Activator.CreateInstance(typeof(TPort), (IntPtr)(&(*Ptr->Output[outputPort])), this, Guid.NewGuid()); return(ConfigureOutputPort(outputPort, config, handler)); }
public virtual IDownstreamComponent ConfigureOutputPort(int outputPort, IMmalPortConfig config, ICaptureHandler handler) { if (ProcessingPorts.ContainsKey(outputPort)) { ProcessingPorts.Remove(outputPort); } ProcessingPorts.Add(outputPort, Outputs[outputPort]); Outputs[outputPort].Configure(config, Inputs[0], handler); return(this); }
protected MMALEncoderBase(string encoderName, ICaptureHandler handler) : base(encoderName, handler) { }
public MMALImageEncoder(ICaptureHandler handler, bool rawBayer = false, bool useExif = true, params ExifTag[] exifTags) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, handler) { this.RawBayer = rawBayer; this.UseExif = useExif; this.ExifTags = exifTags; }
public MMALResizerComponent(int width, int height, ICaptureHandler handler) : base(MMAL_COMPONENT_DEFAULT_RESIZER, handler) { this.Width = width; this.Height = height; }
public MMALVideoEncoder(ICaptureHandler handler, DateTime?timeout = null, Split split = null) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, handler) { this.Split = split; this.Timeout = timeout; }
public MMALVideoDecoder(ICaptureHandler handler) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, handler) { }
public MMALVideoEncoder(ICaptureHandler handler, MMAL_RATIONAL_T framerate, DateTime?timeout = null, Split split = null) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, handler) { this.Framerate = framerate.Num / framerate.Den; this.Split = split; this.Timeout = timeout; }
public MMALSplitterComponent(ICaptureHandler handler) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER, handler) { }
/// <summary> /// Creates a new instance of the <see cref="MMALResizerComponent"/> class that can be used to change the size /// and the pixel format of resulting frames. /// </summary> /// <param name="handler">The capture handler associated with this component.</param> /// <param name="outputPortType">The user defined output port type.</param> public unsafe MMALResizerComponent(ICaptureHandler handler, Type outputPortType) : base(MMAL_COMPONENT_DEFAULT_RESIZER) { this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, PortType.Input, Guid.NewGuid())); this.Outputs.Add((OutputPortBase)Activator.CreateInstance(outputPortType, (IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); }
public MMALImageDecoder(ICaptureHandler handler) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_IMAGE_DECODER, handler) { }
/// <summary> /// Creates a new instance of <see cref="ImageFileDecodeInputPort"/>. /// </summary> /// <param name="ptr">The native pointer.</param> /// <param name="comp">The component this port is associated with.</param> /// <param name="type">The type of port.</param> /// <param name="guid">Managed unique identifier for this port.</param> /// <param name="handler">The capture handler for this port.</param> public ImageFileDecodeInputPort(IntPtr ptr, MMALComponentBase comp, PortType type, Guid guid, ICaptureHandler handler) : base(ptr, comp, type, guid, handler) { }
public virtual IDownstreamComponent ConfigureOutputPort(IMmalPortConfig config, ICaptureHandler handler) => ConfigureOutputPort(0, config, handler);
public override IDownstreamComponent ConfigureOutputPort(int outputPort, IMmalPortConfig config, ICaptureHandler handler) { var bufferSize = Math.Max(Outputs[outputPort].Ptr->BufferSizeRecommended, Outputs[outputPort].Ptr->BufferSizeMin); var bitrate = GetValidBitrate(config); // Force framerate to be 0 in case it was provided by user. config = new MmalPortConfig( config.EncodingType, config.PixelFormat, config.Quality, bitrate, config.Timeout, config.Split, config.StoreMotionVectors, config.Width, config.Height, config.Framerate, config.ZeroCopy, config.BufferNum, bufferSize, config.Crop); base.ConfigureOutputPort(outputPort, config, handler); ConfigureIntraPeriod(outputPort); ConfigureVideoProfile(outputPort); ConfigureInlineHeaderFlag(outputPort); ConfigureInlineVectorsFlag(outputPort); ConfigureIntraRefresh(outputPort); ConfigureQuantisationParameter(outputPort, config.Quality); ConfigureImmutableInput(); return(this); }
/// <summary> /// Creates a new instance of <see cref="MMALImageFileEncoder"/>. /// </summary> /// <param name="handler">The capture handler.</param> public unsafe MMALVideoFileEncoder(ICaptureHandler handler) : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER) { this.Inputs.Add(new VideoFileEncodeInputPort((IntPtr)(&(*this.Ptr->Input[0])), this, PortType.Input, Guid.NewGuid(), handler)); this.Outputs.Add(new VideoFileEncodeOutputPort((IntPtr)(&(*this.Ptr->Output[0])), this, PortType.Output, Guid.NewGuid(), handler)); }