/// <inheritdoc /> public override IDownstreamComponent ConfigureOutputPort(int outputPort, IMMALPortConfig config, IOutputCaptureHandler handler) { base.ConfigureOutputPort(outputPort, config, handler); if (this.RawBayer) { MMALCamera.Instance.Camera.StillPort.SetRawCapture(true); } if (this.UseExif) { this.AddExifTags(this.ExifTags); } if (this.JpegThumbnailConfig != null) { var str = new MMAL_PARAMETER_THUMBNAIL_CONFIG_T( new MMAL_PARAMETER_HEADER_T( MMALParametersCamera.MMAL_PARAMETER_THUMBNAIL_CONFIGURATION, Marshal.SizeOf <MMAL_PARAMETER_THUMBNAIL_CONFIG_T>()), this.JpegThumbnailConfig.Enable, this.JpegThumbnailConfig.Width, this.JpegThumbnailConfig.Height, this.JpegThumbnailConfig.Quality); MMALCheck(MMALPort.mmal_port_parameter_set(this.Control.Ptr, &str.Hdr), "Unable to set JPEG thumbnail config."); } return(this); }
/// <summary> /// Call to configure changes on a downstream component input port. /// </summary> /// <typeparam name="TPort">Input port type.</typeparam> /// <param name="config">User provided port configuration object.</param> /// <param name="handler">The input port capture handler.</param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual unsafe IDownstreamComponent ConfigureInputPort <TPort>(IMMALPortConfig config, IInputCaptureHandler handler) where TPort : IInputPort { this.Inputs[0] = (IInputPort)Activator.CreateInstance(typeof(TPort), (IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid()); return(this.ConfigureInputPort(config, null, handler)); }
/// <inheritdoc /> public override void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) { base.Configure(config, copyFrom, handler); if (config != null && config.EncodingType == MMALEncoding.JPEG) { this.SetParameter(MMALParametersCamera.MMAL_PARAMETER_JPEG_Q_FACTOR, config.Quality); } }
/// <inheritdoc /> public override IDownstreamComponent ConfigureOutputPort(int outputPort, IMMALPortConfig config, IOutputCaptureHandler handler) { this.Quality = config.Quality; var bufferSize = 0; if (config.EncodingType == MMALEncoding.H264) { bufferSize = Math.Max(this.Outputs[outputPort].Ptr->BufferSizeRecommended, this.Outputs[outputPort].Ptr->BufferSizeMin); } else { // Follow raspivid logic. bufferSize = Math.Max(this.Outputs[outputPort].Ptr->BufferSizeRecommended, 256 << 10); } var bitrate = this.GetValidBitrate(outputPort, 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); if (this.Outputs[outputPort].EncodingType == MMALEncoding.H264) { this.ConfigureIntraPeriod(outputPort); this.ConfigureVideoProfile(outputPort); this.ConfigureInlineHeaderFlag(outputPort); this.ConfigureInlineVectorsFlag(outputPort); this.ConfigureIntraRefresh(outputPort); this.ConfigureQuantisationParameter(outputPort); } this.ConfigureImmutableInput(outputPort); return(this); }
/// <summary> /// Configures a specific input port on a downstream component. This method will perform a shallow copy of the output /// port it is to be connected to. /// </summary> /// <param name="config">User provided port configuration object.</param> /// <param name="copyPort">The output port we are copying format data from.</param> /// <param name="handler">The input port capture handler. This will be non-null if this port's component is the 1st component in the /// pipeline and you are feeding data to it directly from a <see cref="IInputCaptureHandler"/>. If this port is connected to by another component then leave this parameter null. /// </param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual unsafe IDownstreamComponent ConfigureInputPort(IMMALPortConfig config, IPort copyPort, IInputCaptureHandler handler) { this.Inputs[0].Configure(config, copyPort, handler); if (this.Outputs.Count > 0 && this.Outputs[0].Ptr->Format->Type == MMALFormat.MMAL_ES_TYPE_T.MMAL_ES_TYPE_UNKNOWN) { throw new PiCameraError("Unable to determine settings for output port."); } return(this); }
/// <inheritdoc /> public override IDownstreamComponent ConfigureInputPort(IMMALPortConfig config, IInputCaptureHandler handler) { var bufferNum = Math.Max(this.Inputs[0].BufferNumRecommended, 3); config = new MMALPortConfig(config.EncodingType, config.PixelFormat, config.Width, config.Height, config.Framerate, config.Quality, config.Bitrate, config.ZeroCopy, config.Timeout, bufferNum, config.BufferSize, config.Crop, config.StoreMotionVectors); base.ConfigureInputPort(config, handler); return(this); }
/// <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> /// <param name="handler">The output port capture handler.</param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual IDownstreamComponent ConfigureOutputPort(int outputPort, IMMALPortConfig config, IOutputCaptureHandler handler) { if (this.ProcessingPorts.ContainsKey(outputPort)) { this.ProcessingPorts.Remove(outputPort); } this.ProcessingPorts.Add(outputPort, this.Outputs[outputPort]); this.Outputs[outputPort].Configure(config, this.Inputs[0], handler); return(this); }
private int GetValidBitrate(int outputPort, IMMALPortConfig config) { var bitrate = config.Bitrate; if (this.Outputs[outputPort].EncodingType == MMALEncoding.H264) { List <VideoLevel> levelList = null; if (MMALCameraConfig.VideoProfile == MMALParametersVideo.MMAL_VIDEO_PROFILE_T.MMAL_VIDEO_PROFILE_H264_HIGH) { levelList = GetHighLevelLimits(); } else if (MMALCameraConfig.VideoProfile == MMALParametersVideo.MMAL_VIDEO_PROFILE_T.MMAL_VIDEO_PROFILE_H264_HIGH10) { levelList = GetHigh10LevelLimits(); } else { levelList = GetNormalLevelLimits(); } var level = levelList.First(c => c.Level == MMALCameraConfig.VideoLevel); if (config.Bitrate > level.Maxbitrate) { throw new PiCameraError("Bitrate requested exceeds maximum for selected Video Level and Profile"); } } else if (this.Outputs[outputPort].EncodingType == MMALEncoding.MJPEG) { if (this.Outputs[outputPort].Bitrate > MaxBitrateMJPEG) { MMALLog.Logger.LogWarning("Bitrate too high: Reducing to 25MBit/s"); bitrate = MaxBitrateMJPEG; } } return(bitrate); }
/// <inheritdoc /> public override void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) { base.Configure(config, copyFrom, handler); this.CallbackHandler = new VideoOutputCallbackHandler(this, (IVideoCaptureHandler)handler, config.Split); }
/// <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> /// Call to configure an input port. /// </summary> /// <param name="config">The port configuration object.</param> /// <param name="copyPort">The port to copy from.</param> /// <param name="handler">The capture handler to assign to this port.</param> public virtual void Configure(IMMALPortConfig config, IPort copyPort, IInputCaptureHandler handler) { copyPort?.ShallowCopy(this); if (config != null) { this.PortConfig = config; if (config.EncodingType != null) { this.NativeEncodingType = config.EncodingType.EncodingVal; } if (config.PixelFormat != null) { this.NativeEncodingSubformat = config.PixelFormat.EncodingVal; } 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); } } if (config.Framerate > 0) { this.FrameRate = config.Framerate; } if (config.Bitrate > 0) { this.Bitrate = config.Bitrate; } this.EncodingType = config.EncodingType; if (config.ZeroCopy) { this.ZeroCopy = true; this.SetParameter(MMALParametersCommon.MMAL_PARAMETER_ZERO_COPY, true); } 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.Commit(); this.CallbackHandler = new DefaultInputPortCallbackHandler(this, handler); } }
/// <inheritdoc /> public override void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) { base.Configure(config, copyFrom, handler); this.CallbackHandler = new FastImageOutputCallbackHandler(this, handler); }
/// <summary> /// Call to configure changes on the first downstream component output port. /// </summary> /// <param name="config">User provided port configuration object.</param> /// <param name="handler">The output port capture handler.</param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual IDownstreamComponent ConfigureOutputPort(IMMALPortConfig config, IOutputCaptureHandler handler) { return(this.ConfigureOutputPort(0, config, handler)); }
/// <summary> /// Call to configure changes on a downstream component input port. /// </summary> /// <param name="config">User provided port configuration object.</param> /// <param name="handler">The input port capture handler. This will be non-null if this port's component is the 1st component in the /// pipeline and you are feeding data to it directly from a <see cref="IInputCaptureHandler"/>. If this port is connected to by another component then leave this parameter null. /// </param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual IDownstreamComponent ConfigureInputPort(IMMALPortConfig config, IInputCaptureHandler handler) { return(this.ConfigureInputPort(config, null, handler)); }
/// <summary> /// Call to configure changes on a downstream component output port. /// </summary> /// <typeparam name="TPort">Output port type.</typeparam> /// <param name="outputPort">The output port number to configure.</param> /// <param name="config">User provided port configuration object.</param> /// <param name="handler">The output port capture handler.</param> /// <returns>This <see cref="MMALDownstreamComponent"/>.</returns> public virtual unsafe IDownstreamComponent ConfigureOutputPort <TPort>(int outputPort, IMMALPortConfig config, IOutputCaptureHandler handler) where TPort : IOutputPort { this.Outputs[outputPort] = (IOutputPort)Activator.CreateInstance(typeof(TPort), (IntPtr)(&(*this.Ptr->Output[outputPort])), this, Guid.NewGuid()); return(this.ConfigureOutputPort(outputPort, config, handler)); }
/// <inheritdoc /> public override void Configure(IMMALPortConfig 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); }