/// <summary> /// Initialises the camera's video port using the width, height and encoding as specified by the user /// </summary> internal void InitialiseVideo() { if (MMALCameraConfig.VideoResolution.Width == 0 || MMALCameraConfig.VideoResolution.Width > this.CameraInfo.MaxWidth) { MMALCameraConfig.VideoResolution.Width = this.CameraInfo.MaxWidth; } if (MMALCameraConfig.VideoResolution.Height == 0 || MMALCameraConfig.VideoResolution.Height > this.CameraInfo.MaxHeight) { MMALCameraConfig.VideoResolution.Height = this.CameraInfo.MaxHeight; } var vFormat = new MMAL_VIDEO_FORMAT_T( MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.VideoResolution.Width, 32), MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.VideoResolution.Height, 16), new MMAL_RECT_T(0, 0, MMALCameraConfig.VideoResolution.Width, MMALCameraConfig.VideoResolution.Height), MMALCameraConfig.VideoFramerate, this.VideoPort.Ptr->Format->es->video.par, this.VideoPort.Ptr->Format->es->video.colorSpace ); this.VideoPort.Ptr->Format->encoding = MMALCameraConfig.VideoEncoding.EncodingVal; this.VideoPort.Ptr->Format->encodingVariant = MMALCameraConfig.VideoSubformat.EncodingVal; this.VideoPort.Ptr->Format->es->video = vFormat; MMALLog.Logger.Debug("Commit video"); this.VideoPort.Commit(); this.VideoPort.Ptr->BufferNum = Math.Max(this.VideoPort.BufferNumRecommended, this.VideoPort.BufferNumMin); this.VideoPort.Ptr->BufferSize = Math.Max(this.VideoPort.BufferSizeRecommended, this.VideoPort.BufferSizeMin); }
/// <summary> /// Initialises the camera's preview component using the user defined width/height for the video port /// </summary> internal void InitialisePreview() { var vFormat = new MMAL_VIDEO_FORMAT_T( MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.VideoResolution.Width, 32), MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.VideoResolution.Height, 16), new MMAL_RECT_T(0, 0, MMALCameraConfig.VideoResolution.Width, MMALCameraConfig.VideoResolution.Height), new MMAL_RATIONAL_T(0, 1), this.PreviewPort.Ptr->Format->es->video.par, this.PreviewPort.Ptr->Format->es->video.colorSpace ); this.PreviewPort.Ptr->Format->encoding = MMALCameraConfig.PreviewEncoding.EncodingVal; this.PreviewPort.Ptr->Format->encodingVariant = MMALCameraConfig.PreviewSubformat.EncodingVal; this.PreviewPort.Ptr->Format->es->video = vFormat; MMALLog.Logger.Debug("Commit preview"); this.PreviewPort.Commit(); this.PreviewPort.Ptr->BufferNum = Math.Max(this.PreviewPort.BufferNumRecommended, this.PreviewPort.BufferNumMin); this.PreviewPort.Ptr->BufferSize = Math.Max(this.PreviewPort.BufferSizeRecommended, this.PreviewPort.BufferSizeMin); }
/// <summary> /// Call to configure changes on an Downstream component output port. /// </summary> /// <param name="outputPort">The output port we are configuring.</param> /// <param name="encodingType">The encoding type this output port will send data in.</param> /// <param name="pixelFormat">The pixel format this output port will send data in.</param> /// <param name="quality">The quality of our outputted data.</param> /// <param name="bitrate">The bitrate we are sending data at.</param> /// <param name="zeroCopy">Instruct MMAL to not copy buffers to ARM memory (useful for large buffers and handling raw data).</param> public virtual unsafe void ConfigureOutputPort(int outputPort, MMALEncoding encodingType, MMALEncoding pixelFormat, int quality, int bitrate = 0, bool zeroCopy = false) { this.InitialiseOutputPort(outputPort); this.ProcessingPorts.Add(outputPort); this.Inputs[0].ShallowCopy(this.Outputs[outputPort]); if (encodingType != null) { this.Outputs[outputPort].NativeEncodingType = encodingType.EncodingVal; } if (pixelFormat != null) { this.Outputs[outputPort].NativeEncodingSubformat = pixelFormat.EncodingVal; } MMAL_VIDEO_FORMAT_T tempVid = this.Outputs[outputPort].Ptr->Format->Es->Video; try { this.Outputs[outputPort].Commit(); } catch { // If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MMALLog.Logger.Warn("Commit of output port failed. Attempting to reset values."); this.Outputs[outputPort].Ptr->Format->Es->Video = tempVid; this.Outputs[outputPort].Commit(); } if (encodingType == MMALEncoding.JPEG) { this.Outputs[outputPort].SetParameter(MMALParametersCamera.MMAL_PARAMETER_JPEG_Q_FACTOR, quality); } if (zeroCopy) { this.Outputs[outputPort].ZeroCopy = true; this.Outputs[outputPort].SetParameter(MMALParametersCommon.MMAL_PARAMETER_ZERO_COPY, true); } this.Outputs[outputPort].EncodingType = encodingType; this.Outputs[outputPort].PixelFormat = pixelFormat; this.Outputs[outputPort].Resolution = new Resolution(this.Width, this.Height).Pad(); this.Outputs[outputPort].Crop = new Rectangle(0, 0, this.Width, this.Height); // It is important to re-commit changes to width and height. this.Outputs[outputPort].Commit(); this.Outputs[outputPort].BufferNum = Math.Max(this.Outputs[outputPort].Ptr->BufferNumRecommended, this.Outputs[outputPort].Ptr->BufferNumMin); this.Outputs[outputPort].BufferSize = Math.Max(this.Outputs[outputPort].Ptr->BufferSizeRecommended, this.Outputs[outputPort].Ptr->BufferSizeMin); this.Outputs[outputPort].ManagedOutputCallback = OutputCallbackProvider.FindCallback(this.Outputs[outputPort]); }
/// <summary> /// Call to configure changes on an Downstream component output port. /// </summary> /// <param name="outputPort">The output port we are configuring</param> /// <param name="encodingType">The encoding type this output port will send data in</param> /// <param name="pixelFormat">The pixel format this output port will send data in</param> /// <param name="quality">The quality of our outputted data</param> /// <param name="bitrate">The bitrate we are sending data at</param> public virtual unsafe void ConfigureOutputPort(int outputPort, MMALEncoding encodingType, MMALEncoding pixelFormat, int quality, int bitrate = 0) { this.InitialiseOutputPort(outputPort); this.ProcessingPorts.Add(outputPort); this.Inputs[0].ShallowCopy(this.Outputs[outputPort]); if (encodingType != null) { this.Outputs[outputPort].Ptr->Format->encoding = encodingType.EncodingVal; } if (pixelFormat != null) { this.Outputs[outputPort].Ptr->Format->encodingVariant = pixelFormat.EncodingVal; } MMAL_VIDEO_FORMAT_T tempVid = this.Outputs[outputPort].Ptr->Format->es->video; //this.OutputPort.Ptr->Format->es->video.frameRate = new MMAL_RATIONAL_T(0, 1); //this.OutputPort.Ptr->Format->bitrate = bitrate; try { this.Outputs[outputPort].Commit(); } catch { //If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MMALLog.Logger.Warn("Commit of output port failed. Attempting to reset values."); this.Outputs[outputPort].Ptr->Format->es->video = tempVid; this.Outputs[outputPort].Commit(); } if (encodingType == MMALEncoding.JPEG) { this.Outputs[outputPort].SetParameter(MMALParametersCamera.MMAL_PARAMETER_JPEG_Q_FACTOR, quality); } this.Outputs[outputPort].EncodingType = encodingType; this.Outputs[outputPort].PixelFormat = pixelFormat; this.Outputs[outputPort].Ptr->Format->es->video.height = MMALUtil.VCOS_ALIGN_UP(this.Height, 32); this.Outputs[outputPort].Ptr->Format->es->video.width = MMALUtil.VCOS_ALIGN_UP(this.Width, 32); this.Outputs[outputPort].Ptr->Format->es->video.crop = new MMAL_RECT_T(0, 0, this.Width, this.Height); this.Outputs[outputPort].Ptr->BufferNum = Math.Max(this.Outputs[outputPort].Ptr->BufferNumRecommended, this.Outputs[outputPort].Ptr->BufferNumMin); this.Outputs[outputPort].Ptr->BufferSize = Math.Max(this.Outputs[outputPort].Ptr->BufferSizeRecommended, this.Outputs[outputPort].Ptr->BufferSizeMin); //It is important to re-commit changes to width and height. this.Outputs[outputPort].Commit(); }
/// <summary> /// Call to configure changes on a downstream component output port. /// </summary> /// <param name="outputPort">The output port number to configure.</param> /// <param name="config">User provided port configuration object.</param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual unsafe MMALDownstreamComponent ConfigureOutputPort(int outputPort, MMALPortConfig config) { this.Outputs[outputPort].PortConfig = config; if (this.ProcessingPorts.ContainsKey(outputPort)) { this.ProcessingPorts.Remove(outputPort); } this.ProcessingPorts.Add(outputPort, this.Outputs[outputPort]); this.Inputs[0].ShallowCopy(this.Outputs[outputPort]); if (config.EncodingType != null) { this.Outputs[outputPort].NativeEncodingType = config.EncodingType.EncodingVal; } if (config.PixelFormat != null) { this.Outputs[outputPort].NativeEncodingSubformat = config.PixelFormat.EncodingVal; } MMAL_VIDEO_FORMAT_T tempVid = this.Outputs[outputPort].Ptr->Format->Es->Video; try { this.Outputs[outputPort].Commit(); } catch { // If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MMALLog.Logger.Warn("Commit of output port failed. Attempting to reset values."); this.Outputs[outputPort].Ptr->Format->Es->Video = tempVid; this.Outputs[outputPort].Commit(); } if (config.EncodingType == MMALEncoding.JPEG) { this.Outputs[outputPort].SetParameter(MMALParametersCamera.MMAL_PARAMETER_JPEG_Q_FACTOR, config.Quality); } if (config.ZeroCopy) { this.Outputs[outputPort].ZeroCopy = true; this.Outputs[outputPort].SetParameter(MMALParametersCommon.MMAL_PARAMETER_ZERO_COPY, true); } if (MMALCameraConfig.VideoColorSpace != null && MMALCameraConfig.VideoColorSpace.EncType == MMALEncoding.EncodingType.ColorSpace) { this.Outputs[outputPort].VideoColorSpace = MMALCameraConfig.VideoColorSpace; } if (config.Bitrate > 0) { this.Outputs[outputPort].Bitrate = config.Bitrate; } this.Outputs[outputPort].EncodingType = config.EncodingType; this.Outputs[outputPort].PixelFormat = config.PixelFormat; if (config.Width > 0 && config.Height > 0) { this.Outputs[outputPort].Resolution = new Resolution(config.Width, config.Height).Pad(); this.Outputs[outputPort].Crop = new Rectangle(0, 0, this.Outputs[outputPort].Resolution.Width, this.Outputs[outputPort].Resolution.Height); } else { // Use config or don't set depending on port type. this.Outputs[outputPort].Resolution = new Resolution(0, 0); if (this.Outputs[outputPort].Resolution.Width > 0 && this.Outputs[outputPort].Resolution.Height > 0) { this.Outputs[outputPort].Crop = new Rectangle(0, 0, this.Outputs[outputPort].Resolution.Width, this.Outputs[outputPort].Resolution.Height); } } // It is important to re-commit changes to width and height. this.Outputs[outputPort].Commit(); this.Outputs[outputPort].BufferNum = Math.Max(this.Outputs[outputPort].Ptr->BufferNumRecommended, this.Outputs[outputPort].Ptr->BufferNumMin); this.Outputs[outputPort].BufferSize = Math.Max(this.Outputs[outputPort].Ptr->BufferSizeRecommended, this.Outputs[outputPort].Ptr->BufferSizeMin); this.Outputs[outputPort].ManagedOutputCallback = OutputCallbackProvider.FindCallback(this.Outputs[outputPort]); return(this); }
/// <inheritdoc /> public override unsafe MMALDownstreamComponent ConfigureOutputPort(int outputPort, MMALPortConfig config) { // The splitter component should not have its resolution set on the output port so override method accordingly. this.Outputs[outputPort].PortConfig = config; if (this.ProcessingPorts.ContainsKey(outputPort)) { this.ProcessingPorts.Remove(outputPort); } this.ProcessingPorts.Add(outputPort, this.Outputs[outputPort]); this.Inputs[0].ShallowCopy(this.Outputs[outputPort]); if (config.EncodingType != null) { this.Outputs[outputPort].NativeEncodingType = config.EncodingType.EncodingVal; } if (config.PixelFormat != null) { this.Outputs[outputPort].NativeEncodingSubformat = config.PixelFormat.EncodingVal; } MMAL_VIDEO_FORMAT_T tempVid = this.Outputs[outputPort].Ptr->Format->Es->Video; try { this.Outputs[outputPort].Commit(); } catch { // If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MMALLog.Logger.Warn("Commit of output port failed. Attempting to reset values."); this.Outputs[outputPort].Ptr->Format->Es->Video = tempVid; this.Outputs[outputPort].Commit(); } if (config.EncodingType == MMALEncoding.JPEG) { this.Outputs[outputPort].SetParameter(MMALParametersCamera.MMAL_PARAMETER_JPEG_Q_FACTOR, config.Quality); } if (config.ZeroCopy) { this.Outputs[outputPort].ZeroCopy = true; this.Outputs[outputPort].SetParameter(MMALParametersCommon.MMAL_PARAMETER_ZERO_COPY, true); } if (MMALCameraConfig.VideoColorSpace != null && MMALCameraConfig.VideoColorSpace.EncType == MMALEncoding.EncodingType.ColorSpace) { this.Outputs[outputPort].VideoColorSpace = MMALCameraConfig.VideoColorSpace; } this.Outputs[outputPort].EncodingType = config.EncodingType; this.Outputs[outputPort].PixelFormat = config.PixelFormat; // It is important to re-commit changes to width and height. this.Outputs[outputPort].Commit(); this.Outputs[outputPort].BufferNum = Math.Max(this.Outputs[outputPort].Ptr->BufferNumRecommended, this.Outputs[outputPort].Ptr->BufferNumMin); this.Outputs[outputPort].BufferSize = Math.Max(this.Outputs[outputPort].Ptr->BufferSizeRecommended, this.Outputs[outputPort].Ptr->BufferSizeMin); this.Outputs[outputPort].ManagedOutputCallback = OutputCallbackProvider.FindCallback(this.Outputs[outputPort]); return(this); }
/// <summary> /// Call to configure an output port. /// </summary> /// <param name="config">The port configuration object.</param> /// <param name="copyFrom">The port to copy from.</param> /// <param name="handler">The capture handler to assign to this port.</param> public virtual void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) { if (config != null) { this.PortConfig = config; copyFrom?.ShallowCopy(this); if (config.EncodingType != null) { this.NativeEncodingType = config.EncodingType.EncodingVal; } if (config.PixelFormat != null) { this.NativeEncodingSubformat = config.PixelFormat.EncodingVal; } this.Par = new MMAL_RATIONAL_T(1, 1); MMAL_VIDEO_FORMAT_T tempVid = this.Ptr->Format->Es->Video; try { this.Commit(); } catch { // If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MMALLog.Logger.LogWarning($"{this.Name}: Commit of output port failed. Attempting to reset values."); this.Ptr->Format->Es->Video = tempVid; this.Commit(); } if (config.ZeroCopy) { this.ZeroCopy = true; this.SetParameter(MMALParametersCommon.MMAL_PARAMETER_ZERO_COPY, true); } if (MMALCameraConfig.VideoColorSpace != null && MMALCameraConfig.VideoColorSpace.EncType == MMALEncoding.EncodingType.ColorSpace) { this.VideoColorSpace = MMALCameraConfig.VideoColorSpace; } if (config.Framerate > 0) { this.FrameRate = config.Framerate; } if (config.Bitrate > 0) { this.Bitrate = config.Bitrate; } this.EncodingType = config.EncodingType; this.PixelFormat = config.PixelFormat; if (config.Width > 0 && config.Height > 0) { if (config.Crop.HasValue) { this.Crop = config.Crop.Value; } else { this.Crop = new Rectangle(0, 0, config.Width, config.Height); } this.Resolution = new Resolution(config.Width, config.Height); } else { // Use config or don't set depending on port type. this.Resolution = new Resolution(0, 0); // Certain resolution overrides set to global config Video/Still resolutions so check here if the width and height are greater than 0. if (this.Resolution.Width > 0 && this.Resolution.Height > 0) { this.Crop = new Rectangle(0, 0, this.Resolution.Width, this.Resolution.Height); } } this.BufferNum = Math.Max(this.BufferNumMin, config.BufferNum > 0 ? config.BufferNum : this.BufferNumRecommended); this.BufferSize = Math.Max(this.BufferSizeMin, config.BufferSize > 0 ? config.BufferSize : this.BufferSizeRecommended); // It is important to re-commit changes to width and height. this.Commit(); } this.CallbackHandler = new DefaultOutputPortCallbackHandler(this, handler); }
/// <summary> /// Initialises the camera's still port using the width, height and encoding as specified by the user /// </summary> internal void InitialiseStill() { if (MMALCameraConfig.StillResolution.Width == 0 || MMALCameraConfig.StillResolution.Width > this.CameraInfo.MaxWidth) { MMALCameraConfig.StillResolution.Width = this.CameraInfo.MaxWidth; } if (MMALCameraConfig.StillResolution.Height == 0 || MMALCameraConfig.StillResolution.Height > this.CameraInfo.MaxHeight) { MMALCameraConfig.StillResolution.Height = this.CameraInfo.MaxHeight; } var vFormat = new MMAL_VIDEO_FORMAT_T(); if (MMALCameraConfig.StillEncoding == MMALEncoding.RGB32 || MMALCameraConfig.StillEncoding == MMALEncoding.RGB24 || MMALCameraConfig.StillEncoding == MMALEncoding.RGB16) { MMALLog.Logger.Warn("Encoding set to RGB. Setting width padding to multiple of 16."); vFormat = new MMAL_VIDEO_FORMAT_T( MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.StillResolution.Width, 16), MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.StillResolution.Height, 16), new MMAL_RECT_T(0, 0, MMALCameraConfig.StillResolution.Width, MMALCameraConfig.StillResolution.Height), new MMAL_RATIONAL_T(0, 1), this.StillPort.Ptr->Format->es->video.par, this.StillPort.Ptr->Format->es->video.colorSpace ); try { if (!this.StillPort.RgbOrderFixed()) { MMALLog.Logger.Warn("Using old firmware. Setting encoding to BGR24"); this.StillPort.Ptr->Format->encoding = MMALEncoding.BGR24.EncodingVal; } } catch { MMALLog.Logger.Warn("Using old firmware. Setting encoding to BGR24"); this.StillPort.Ptr->Format->encoding = MMALEncoding.BGR24.EncodingVal; } this.StillPort.Ptr->Format->encodingVariant = 0; } else { vFormat = new MMAL_VIDEO_FORMAT_T( MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.StillResolution.Width, 32), MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.StillResolution.Height, 16), new MMAL_RECT_T(0, 0, MMALCameraConfig.StillResolution.Width, MMALCameraConfig.StillResolution.Height), MMALCameraConfig.StillFramerate, this.StillPort.Ptr->Format->es->video.par, this.StillPort.Ptr->Format->es->video.colorSpace ); this.StillPort.Ptr->Format->encoding = MMALCameraConfig.StillEncoding.EncodingVal; this.StillPort.Ptr->Format->encodingVariant = MMALCameraConfig.StillSubFormat.EncodingVal; } this.StillPort.Ptr->Format->es->video = vFormat; MMALLog.Logger.Debug("Commit still"); this.StillPort.Commit(); this.StillPort.Ptr->BufferNum = Math.Max(this.StillPort.BufferNumRecommended, this.StillPort.BufferNumMin); this.StillPort.Ptr->BufferSize = Math.Max(this.StillPort.BufferSizeRecommended, this.StillPort.BufferSizeMin); }
/// <inheritdoc /> public override void Configure(MMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) { // The splitter component should not have its resolution set on the output port so override method accordingly. if (config != null) { this.PortConfig = config; copyFrom?.ShallowCopy(this); if (config.EncodingType != null) { this.NativeEncodingType = config.EncodingType.EncodingVal; } if (config.PixelFormat != null) { this.NativeEncodingSubformat = config.PixelFormat.EncodingVal; } MMAL_VIDEO_FORMAT_T tempVid = this.Ptr->Format->Es->Video; try { this.Commit(); } catch { // If commit fails using new settings, attempt to reset using old temp MMAL_VIDEO_FORMAT_T. MMALLog.Logger.LogWarning("Commit of output port failed. Attempting to reset values."); this.Ptr->Format->Es->Video = tempVid; this.Commit(); } if (config.ZeroCopy) { this.ZeroCopy = true; this.SetParameter(MMALParametersCommon.MMAL_PARAMETER_ZERO_COPY, true); } if (MMALCameraConfig.VideoColorSpace != null && MMALCameraConfig.VideoColorSpace.EncType == MMALEncoding.EncodingType.ColorSpace) { this.VideoColorSpace = MMALCameraConfig.VideoColorSpace; } if (config.Bitrate > 0) { this.Bitrate = config.Bitrate; } this.EncodingType = config.EncodingType; this.PixelFormat = config.PixelFormat; this.Commit(); this.BufferNum = Math.Max(this.BufferNumMin, config.BufferNum > 0 ? config.BufferNum : this.BufferNumRecommended); this.BufferSize = Math.Max(this.BufferSizeMin, config.BufferSize > 0 ? config.BufferSize : this.BufferSizeRecommended); } this.CallbackHandler = new VideoOutputCallbackHandler(this, (IVideoCaptureHandler)handler, null); }