Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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));
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <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);
        }
Beispiel #10
0
        /// <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);
        }
Beispiel #11
0
        /// <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);
        }
Beispiel #13
0
 /// <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));
 }
Beispiel #14
0
 /// <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));
 }
Beispiel #15
0
        /// <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);
        }