示例#1
0
        /// <summary>
        /// Call to configure changes on an Image Encoder input port. Used when providing an image file directly
        /// to the component.
        /// </summary>
        /// <param name="encodingType">The encoding type the input port will expect data in</param>
        /// <param name="width">The width of the incoming frame</param>
        /// <param name="height">The height of the incoming frame</param>
        public virtual unsafe void ConfigureInputPort(MMALEncoding encodingType, int width, int height)
        {
            this.InitialiseInputPort(0);

            if (encodingType != null)
            {
                this.Inputs[0].Ptr->Format->encoding = encodingType.EncodingVal;
            }

            this.Inputs[0].Ptr->Format->es->video.height = MMALUtil.VCOS_ALIGN_UP(height, 32);
            this.Inputs[0].Ptr->Format->es->video.width  = MMALUtil.VCOS_ALIGN_UP(width, 32);
            this.Inputs[0].Ptr->Format->es->video.crop   = new MMAL_RECT_T(0, 0, width, height);

            this.Inputs[0].Commit();

            if (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.");
            }

            this.Inputs[0].Ptr->BufferNum  = Math.Max(this.Inputs[0].Ptr->BufferNumRecommended, this.Inputs[0].Ptr->BufferNumMin);
            this.Inputs[0].Ptr->BufferSize = Math.Max(this.Inputs[0].Ptr->BufferSizeRecommended, this.Inputs[0].Ptr->BufferSizeMin);

            this.Inputs[0].EncodingType = encodingType;
        }
示例#2
0
        /// <summary>
        /// Creates a new instance of <see cref="MMALPoolImpl"/> based on a port.
        /// </summary>
        /// <param name="port">The port.</param>
        public MMALPoolImpl(PortBase port)
        {
            MMALLog.Logger.Debug($"Creating buffer pool with {port.BufferNum} buffers of size {port.BufferSize}");

            this.Ptr   = MMALUtil.mmal_port_pool_create(port.Ptr, port.BufferNum, port.BufferSize);
            this.Queue = new MMALQueueImpl((*this.Ptr).Queue);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        /// <summary>
        /// Provides a facility to get data from the port using the native helper functions.
        /// </summary>
        /// <param name="port">The port to get the parameter from.</param>
        /// <param name="key">The unique key for the parameter.</param>
        /// <returns>Dynamic parameter based on key parameter.</returns>
        public static unsafe dynamic GetParameter(this IPort port, int key)
        {
            var t = MMALParameterHelpers.ParameterHelper.Where(c => c.ParamValue == key).FirstOrDefault();

            if (t == null)
            {
                throw new PiCameraError($"Could not find parameter {key}");
            }

            MMALLog.Logger.LogDebug($"Getting parameter {t.ParamName}");

            try
            {
                switch (t.ParamType.Name)
                {
                case "MMAL_PARAMETER_BOOLEAN_T":
                    int boolVal = 0;
                    MMALCheck(MMALUtil.mmal_port_parameter_get_boolean(port.Ptr, (uint)key, ref boolVal), "Unable to get boolean value");
                    return(boolVal == 1);

                case "MMAL_PARAMETER_UINT64_T":
                    ulong ulongVal = 0UL;
                    MMALCheck(MMALUtil.mmal_port_parameter_get_uint64(port.Ptr, (uint)key, ref ulongVal), "Unable to get ulong value");
                    return(ulongVal);

                case "MMAL_PARAMETER_INT64_T":
                    long longVal = 0U;
                    MMALCheck(MMALUtil.mmal_port_parameter_get_int64(port.Ptr, (uint)key, ref longVal), "Unable to get long value");
                    return(longVal);

                case "MMAL_PARAMETER_UINT32_T":
                    uint uintVal = 0U;
                    MMALCheck(MMALUtil.mmal_port_parameter_get_uint32(port.Ptr, (uint)key, ref uintVal), "Unable to get uint value");
                    return(uintVal);

                case "MMAL_PARAMETER_INT32_T":
                    int intVal = 0;
                    MMALCheck(MMALUtil.mmal_port_parameter_get_int32(port.Ptr, (uint)key, ref intVal), "Unable to get int value");
                    return(intVal);

                case "MMAL_PARAMETER_RATIONAL_T":
                    MMAL_RATIONAL_T ratVal = default(MMAL_RATIONAL_T);
                    MMALCheck(MMALUtil.mmal_port_parameter_get_rational(port.Ptr, (uint)key, ref ratVal), "Unable to get rational value");
                    return((double)ratVal.Num / ratVal.Den);

                default:
                    throw new NotSupportedException();
                }
            }
            catch
            {
                MMALLog.Logger.LogWarning($"Unable to get port parameter {t.ParamName}");
                throw;
            }
        }
        /// <summary>
        /// Provides a facility to set data on the port using the native helper functions
        /// </summary>
        /// <param name="port">The port we want to set the parameter on</param>
        /// <param name="key">The unique key of the parameter</param>
        /// <param name="value">The value of the parameter</param>
        public static unsafe void SetParameter(this MMALPortBase port, int key, dynamic value)
        {
            var t = MMALParameterHelpers.ParameterHelper.Where(c => c.ParamValue == key).FirstOrDefault();

            if (t == null)
            {
                throw new PiCameraError($"Could not find parameter {key}");
            }

            MMALLog.Logger.Debug($"Setting parameter {t.ParamName}");

            try
            {
                switch (t.ParamType.Name)
                {
                case "MMAL_PARAMETER_BOOLEAN_T":
                    int i = (bool)value ? 1 : 0;
                    MMALCheck(MMALUtil.mmal_port_parameter_set_boolean(port.Ptr, (uint)key, i), "Unable to set boolean value");
                    break;

                case "MMAL_PARAMETER_UINT64_T":
                    MMALCheck(MMALUtil.mmal_port_parameter_set_uint64(port.Ptr, (uint)key, (ulong)value), "Unable to set ulong value");
                    break;

                case "MMAL_PARAMETER_INT64_T":
                    MMALCheck(MMALUtil.mmal_port_parameter_set_int64(port.Ptr, (uint)key, (long)value), "Unable to set long value");
                    break;

                case "MMAL_PARAMETER_UINT32_T":
                    MMALCheck(MMALUtil.mmal_port_parameter_set_uint32(port.Ptr, (uint)key, (uint)value), "Unable to set uint value");
                    break;

                case "MMAL_PARAMETER_INT32_T":
                    MMALCheck(MMALUtil.mmal_port_parameter_set_int32(port.Ptr, (uint)key, (int)value), "Unable to set int value");
                    break;

                case "MMAL_PARAMETER_RATIONAL_T":
                    MMALCheck(MMALUtil.mmal_port_parameter_set_rational(port.Ptr, (uint)key, (MMAL_RATIONAL_T)value), "Unable to set rational value");
                    break;

                case "MMAL_PARAMETER_STRING_T":
                    MMALCheck(MMALUtil.mmal_port_parameter_set_string(port.Ptr, (uint)key, (string)value), "Unable to set rational value");
                    break;

                default:
                    throw new NotSupportedException();
                }
            }
            catch
            {
                MMALLog.Logger.Warn($"Unable to set port parameter {t.ParamName}");
                throw;
            }
        }
示例#7
0
        /// <summary>
        /// Destroy a pool of MMAL_BUFFER_HEADER_T associated with a specific port. This will also deallocate all of the memory
        /// which was allocated when creating or resizing the pool.
        /// </summary>
        internal void DestroyPortPool()
        {
            if (this.BufferPool != null)
            {
                if (this.Enabled)
                {
                    this.DisablePort();
                }

                MMALUtil.mmal_port_pool_destroy(this.Ptr, this.BufferPool.Ptr);
            }
        }
示例#8
0
        /// <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();
        }
        /// <inheritdoc />
        public virtual void Callback(IBuffer buffer)
        {
            if (MMALCameraConfig.Debug)
            {
                MMALLog.Logger.LogDebug($"In managed {this.WorkingPort.PortType.GetPortType()} callback");
            }

            long?pts = null;

            var data           = buffer.GetBufferData();
            var eos            = buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_FRAME_END) || buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS);
            var containsIFrame = buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_CONFIG);

            if (this is IVideoOutputCallbackHandler &&
                !buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_CONFIG) &&
                buffer.Pts != MMALUtil.MMAL_TIME_UNKNOWN &&
                (buffer.Pts != _ptsLastTime || !_ptsLastTime.HasValue))
            {
                if (!_ptsStartTime.HasValue)
                {
                    _ptsStartTime = buffer.Pts;
                }

                _ptsLastTime = buffer.Pts;
                pts          = buffer.Pts - _ptsStartTime.Value;
            }

            if (MMALCameraConfig.Debug)
            {
                MMALLog.Logger.LogDebug("Attempting to process data.");
            }

            this.CaptureHandler?.Process(new ImageContext
            {
                Data        = data,
                Eos         = eos,
                IFrame      = containsIFrame,
                Resolution  = this.WorkingPort.Resolution,
                Encoding    = this.WorkingPort.EncodingType,
                PixelFormat = this.WorkingPort.PixelFormat,
                Raw         = this.WorkingPort.EncodingType.EncType == MMALEncoding.EncodingType.PixelFormat,
                Pts         = pts,
                Stride      = MMALUtil.mmal_encoding_width_to_stride(WorkingPort.PixelFormat?.EncodingVal ?? this.WorkingPort.EncodingType.EncodingVal, this.WorkingPort.Resolution.Width)
            });

            if (eos)
            {
                // Once we have a full frame, perform any post processing as required.
                this.CaptureHandler?.PostProcess();
            }
        }
        internal static bool RgbOrderFixed(this MMALPortImpl port)
        {
            int newFirmware = 0;
            var encodings   = port.GetSupportedEncodings();

            foreach (int enc in encodings)
            {
                if (enc == MMALUtil.MMAL_FOURCC("BGR3"))
                {
                    break;
                }
                if (enc == MMALUtil.MMAL_FOURCC("RGB3"))
                {
                    newFirmware = 1;
                }
            }

            return(newFirmware == 1);
        }
示例#11
0
 /// <summary>
 /// Pads a <see cref="Resolution"/> object to the desired width/height.
 /// </summary>
 /// <param name="width">The width to be padded to.</param>
 /// <param name="height">The height to be padded to.</param>
 /// <returns>A new <see cref="Resolution"/> struct, padded to the required width/height.</returns>
 public Resolution Pad(int width = 32, int height = 16)
 {
     return(new Resolution(MMALUtil.VCOS_ALIGN_UP(this.Width, width),
                           MMALUtil.VCOS_ALIGN_UP(this.Height, height)));
 }
示例#12
0
        /// <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);
        }