private void ProcessFormatChangedEvent(MMALBufferImpl buffer, int outputPort = 0) { MMALLog.Logger.Info("Received MMAL_EVENT_FORMAT_CHANGED event"); var ev = MMALEventFormat.GetEventFormat(buffer); MMALLog.Logger.Info("-- Event format changed from -- "); this.LogFormat(new MMALEventFormat(this.Outputs[outputPort].Format), this.Outputs[outputPort]); MMALLog.Logger.Info("-- To -- "); this.LogFormat(ev, null); buffer.Release(); this.Outputs[outputPort].DisablePort(); while (this.Outputs[outputPort].BufferPool.Queue.QueueLength() < this.Outputs[outputPort].BufferPool.HeadersNum) { MMALLog.Logger.Debug("Queue length less than buffer pool num"); MMALLog.Logger.Debug("Getting buffer via Queue.Wait"); var tempBuf = WorkingQueue.Wait(); tempBuf.Release(); } this.Outputs[outputPort].BufferPool.Dispose(); this.Outputs[outputPort].FullCopy(ev); this.ConfigureOutputPortWithoutInit(0, this.Outputs[outputPort].EncodingType); this.Outputs[outputPort].EnableOutputPort(false); }
/// <inheritdoc /> internal override void ReleaseOutputBuffer(MMALBufferImpl bufferImpl) { bufferImpl.Release(); try { if (!this.Enabled) { MMALLog.Logger.Warn("Port not enabled."); } if (this.BufferPool == null) { MMALLog.Logger.Warn("Buffer pool null."); } if (this.Enabled && this.BufferPool != null) { var newBuffer = MMALQueueImpl.GetBuffer(this.BufferPool.Queue.Ptr); if (newBuffer != null) { this.SendBuffer(newBuffer); } else { MMALLog.Logger.Warn("Buffer null. Continuing."); } } } catch (Exception e) { MMALLog.Logger.Warn($"Unable to send buffer header. {e.Message}"); } }
/// <summary> /// The callback function to carry out. /// </summary> /// <param name="buffer">The working buffer header.</param> public override void Callback(MMALBufferImpl buffer) { if (this.WorkingPort.ComponentReference.GetType() != typeof(MMALVideoEncoder)) { throw new ArgumentException($"Working port component is not of type {nameof(MMALVideoEncoder)}"); } MMALLog.Logger.Debug("In video output callback"); var component = (MMALVideoEncoder)this.WorkingPort.ComponentReference; if (component.PrepareSplit && buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_CONFIG)) { ((VideoStreamCaptureHandler)this.WorkingPort.Handler).Split(); component.LastSplit = DateTime.Now; component.PrepareSplit = false; } // Ensure that if we need to split then this is done before processing the buffer data. if (component.Split != null) { if (!component.LastSplit.HasValue) { component.LastSplit = DateTime.Now; } if (DateTime.Now.CompareTo(component.CalculateSplit()) > 0) { component.PrepareSplit = true; this.WorkingPort.SetParameter(MMALParametersVideo.MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, true); } } base.Callback(buffer); }
/// <summary> /// This is the camera's control port callback function. The callback is used if /// MMALCameraConfig.SetChangeEventRequest is set to true. /// </summary> /// <seealso cref="MMALCameraConfig.SetChangeEventRequest" /> /// <param name="buffer">The buffer header being sent from MMAL.</param> /// <param name="port">The managed control port instance.</param> internal unsafe void CameraControlCallback(MMALBufferImpl buffer, MMALPortBase port) { if (buffer.Cmd == MMALEvents.MMAL_EVENT_PARAMETER_CHANGED) { var data = (MMAL_EVENT_PARAMETER_CHANGED_T *)buffer.Data; if (data->Hdr.Id == MMALParametersCamera.MMAL_PARAMETER_CAMERA_SETTINGS) { var settings = (MMAL_PARAMETER_CAMERA_SETTINGS_T *)data; MMALLog.Logger.Debug($"Analog gain num {settings->AnalogGain.Num}"); MMALLog.Logger.Debug($"Analog gain den {settings->AnalogGain.Den}"); MMALLog.Logger.Debug($"Exposure {settings->Exposure}"); MMALLog.Logger.Debug($"Focus position {settings->FocusPosition}"); } } else if (buffer.Cmd == MMALEvents.MMAL_EVENT_ERROR) { MMALLog.Logger.Info("No data received from sensor. Check all connections, including the Sunny one on the camera board"); } else { MMALLog.Logger.Info("Received unexpected camera control callback event"); } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { var bufferImpl = new MMALBufferImpl(buffer); if (bufferImpl.CheckState() && MMALVideoFileDecoder.WorkingQueue != null) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug($"Putting output port buffer back into queue {((IntPtr)MMALVideoFileDecoder.WorkingQueue.Ptr).ToString()}"); } bufferImpl.PrintProperties(); MMALVideoFileDecoder.WorkingQueue.Put(bufferImpl); } else { MMALLog.Logger.Debug($"Invalid output buffer received"); } if (port->IsEnabled == 1 && !this.Trigger) { this.Trigger = true; } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.LogDebug($"{this.Name}: In native {nameof(VideoPort)} output callback"); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.PrintProperties(); var eos = (this.PortConfig.Timeout.HasValue && DateTime.Now.CompareTo(this.PortConfig.Timeout.Value) > 0) || this.ComponentReference.ForceStopProcessing; if (bufferImpl.CheckState() && bufferImpl.Length > 0 && !eos && !this.Trigger.Task.IsCompleted) { this.CallbackHandler.Callback(bufferImpl); } // Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. this.ReleaseBuffer(bufferImpl, eos); if (eos && !this.Trigger.Task.IsCompleted) { MMALLog.Logger.LogDebug($"{this.Name}: Timeout exceeded, triggering signal."); Task.Run(() => { this.Trigger.SetResult(true); }); } }
/// <inheritdoc /> public virtual void OutputCallback(MMALBufferImpl buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("Inside Managed output port connection callback"); } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.LogDebug($"{this.Name}: In native {nameof(FastStillPort)} output callback."); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.PrintProperties(); var failed = bufferImpl.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED); if ((bufferImpl.CheckState() && bufferImpl.Length > 0 && !this.ComponentReference.ForceStopProcessing && !failed && !this.Trigger.Task.IsCompleted) || (this.ComponentReference.ForceStopProcessing && !this.Trigger.Task.IsCompleted)) { this.CallbackHandler.Callback(bufferImpl); } // Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. this.ReleaseBuffer(bufferImpl, this.ComponentReference.ForceStopProcessing || failed); // If this buffer signals the end of data stream, allow waiting thread to continue. if (this.ComponentReference.ForceStopProcessing || failed) { MMALLog.Logger.LogDebug($"{this.Name}: Signaling completion of continuous still frame capture..."); Task.Run(() => { this.Trigger.SetResult(true); }); } }
/// <summary> /// The native callback MMAL passes buffer headers to /// </summary> /// <param name="port">The port the buffer is sent to</param> /// <param name="buffer">The buffer header</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { lock (MMALPortBase.OutputLock) { var bufferImpl = new MMALBufferImpl(buffer); if (MMALCameraConfig.Debug) { bufferImpl.PrintProperties(); } if (bufferImpl.Length > 0) { this.ManagedOutputCallback(bufferImpl, this); } //Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. this.ReleaseOutputBuffer(bufferImpl); if (this.Timeout.HasValue && DateTime.Now.CompareTo(this.Timeout.Value) > 0) { if (this.Trigger != null && this.Trigger.CurrentCount > 0) { this.Trigger.Signal(); } } } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { lock (MMALPortBase.OutputLock) { var bufferImpl = new MMALBufferImpl(buffer); if (bufferImpl.CheckState()) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug($"Putting output port buffer back into queue {((IntPtr)MMALImageFileDecoder.WorkingQueue.Ptr).ToString()}"); } bufferImpl.PrintProperties(); MMALImageFileDecoder.WorkingQueue.Put(bufferImpl); } else { MMALLog.Logger.Debug($"Invalid output buffer received"); } if (this.Trigger != null && this.Trigger.CurrentCount > 0) { this.Trigger.Signal(); } } }
/// <summary> /// The native callback MMAL passes buffer headers to /// </summary> /// <param name="port">The port the buffer is sent to</param> /// <param name="buffer">The buffer header</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { lock (MMALPortBase.OutputLock) { var bufferImpl = new MMALBufferImpl(buffer); if (MMALCameraConfig.Debug) { bufferImpl.PrintProperties(); } if (bufferImpl.Length > 0) { this.ManagedOutputCallback(bufferImpl, this); } //Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. this.ReleaseOutputBuffer(bufferImpl); //If this buffer signals the end of data stream, allow waiting thread to continue. if (bufferImpl.Properties.Any(c => c == MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS || c == MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)) { MMALLog.Logger.Debug("End of stream. Signaling completion..."); if (this.Trigger != null && this.Trigger.CurrentCount > 0) { this.Trigger.Signal(); } } } }
/// <inheritdoc /> public virtual void Callback(MMALBufferImpl buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug($"In managed {this.WorkingPort.PortType.GetPortType()} callback"); } }
/// <summary> /// Delegate to process the buffer header containing image data /// </summary> /// <param name="buffer">The buffer header we're currently processing</param> /// <param name="port">The port we're currently processing on</param> public override void ManagedOutputCallback(MMALBufferImpl buffer, MMALPortBase port) { if (this.PrepareSplit && buffer.Properties.Any(c => c == MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_CONFIG)) { ((VideoStreamCaptureHandler)this.Handler).Split(); this.LastSplit = DateTime.Now; this.PrepareSplit = false; } //Ensure that if we need to split then this is done before processing the buffer data. if (this.Split != null) { if (!this.LastSplit.HasValue) { this.LastSplit = DateTime.Now; } if (DateTime.Now.CompareTo(this.CalculateSplit()) > 0) { this.PrepareSplit = true; port.SetParameter(MMALParametersVideo.MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, true); } } base.ManagedOutputCallback(buffer, port); }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeControlPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { lock (MMALControlPort.ControlLock) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("In native control callback."); } var bufferImpl = new MMALBufferImpl(buffer); if (bufferImpl.CheckState()) { if (MMALCameraConfig.Debug) { bufferImpl.ParseEvents(); bufferImpl.PrintProperties(); } this.ManagedControlCallback.Callback(bufferImpl); if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("Releasing buffer."); } bufferImpl.Release(); } else { MMALLog.Logger.Warn("Received null control buffer."); } } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal virtual void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("In native output callback"); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.PrintProperties(); var failed = bufferImpl.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED); var eos = bufferImpl.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_FRAME_END) || bufferImpl.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS) || this.ComponentReference.ForceStopProcessing; if ((bufferImpl.CheckState() && bufferImpl.Length > 0 && !eos && !failed && !this.Trigger) || (eos && !this.Trigger)) { this.ManagedOutputCallback.Callback(bufferImpl); } // Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. this.ReleaseOutputBuffer(bufferImpl); // If this buffer signals the end of data stream, allow waiting thread to continue. if (eos || failed) { MMALLog.Logger.Debug($"{this.ComponentReference.Name} {this.Name} End of stream. Signaling completion..."); this.Trigger = true; } }
/// <inheritdoc /> public override void Callback(MMALBufferImpl buffer) { base.Callback(buffer); var data = buffer.GetBufferData(); this.WorkingPort.Handler?.Process(data); }
/// <summary> /// The native callback MMAL passes buffer headers to /// </summary> /// <param name="port">The port the buffer is sent to</param> /// <param name="buffer">The buffer header</param> internal override void NativeControlPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { var bufferImpl = new MMALBufferImpl(buffer); this.ManagedOutputCallback(bufferImpl, this); MMALLog.Logger.Debug("Releasing buffer"); bufferImpl.Release(); }
/// <summary> /// The callback function to carry out. /// </summary> /// <param name="buffer">The working buffer header.</param> public virtual void Callback(MMALBufferImpl buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug($"In managed {this.WorkingPort.PortType.GetPortType()} callback"); } if (this.EncodingType != null && this.WorkingPort.EncodingType != this.EncodingType) { throw new ArgumentException("Port Encoding Type not supported for this handler."); } }
private void GetAndSendInputBuffer() { // Get buffer from input port pool MMALBufferImpl inputBuffer = this.Inputs[0].BufferPool.Queue.GetBuffer(); if (inputBuffer.CheckState()) { // Populate the new input buffer with user provided image data. var result = this.Inputs[0].ManagedInputCallback.Callback(inputBuffer); inputBuffer.ReadIntoBuffer(result.BufferFeed, result.DataLength, result.EOF); this.Inputs[0].SendBuffer(inputBuffer); } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.LogDebug($"In native {nameof(FileEncodeOutputPort)} callback"); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.PrintProperties(); bufferImpl.ParseEvents(); this.ProcessBuffer(bufferImpl); }
/// <summary> /// The callback function to carry out. /// </summary> /// <param name="buffer">The working buffer header.</param> /// <returns>A <see cref="ProcessResult"/> object based on the result of the callback function.</returns> public virtual ProcessResult Callback(MMALBufferImpl buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("In managed input callback"); } if (this.EncodingType != null && this.WorkingPort.EncodingType != this.EncodingType) { throw new ArgumentException("Port Encoding Type not supported for this handler."); } return(this.WorkingPort.ComponentReference.Handler?.Process(buffer.AllocSize)); }
internal override void NativeInputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("Releasing input port buffer"); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.Release(); if (!this.Trigger) { this.Trigger = true; } }
internal override unsafe void NativeInputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { lock (MMALPortBase.InputLock) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("Releasing input port buffer"); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.Release(); if (this.Trigger != null && this.Trigger.CurrentCount > 0) { this.Trigger.Signal(); } } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug($"Putting output port buffer back into queue {((IntPtr)MMALImageFileEncoder.WorkingQueue.Ptr).ToString()}"); } var bufferImpl = new MMALBufferImpl(buffer); bufferImpl.PrintProperties(); MMALImageFileEncoder.WorkingQueue.Put(bufferImpl); if (port->IsEnabled == 1 && !this.Trigger) { this.Trigger = true; } }
/// <inheritdoc /> public override void Callback(MMALBufferImpl buffer) { if (this.WorkingPort.ComponentReference.GetType() != typeof(MMALImageEncoder)) { throw new ArgumentException($"Working port component is not of type {nameof(MMALImageEncoder)}"); } base.Callback(buffer); var eos = buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_FRAME_END) || buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS); if (eos) { // In rapid capture mode, provide the ability to do post-processing once we have a complete frame. this.WorkingPort.Handler?.PostProcess(); } if (eos && this.WorkingPort.Handler?.GetType() == typeof(ImageStreamCaptureHandler)) { ((ImageStreamCaptureHandler)this.WorkingPort.Handler).NewFile(); } }
/// <summary> /// The native callback MMAL passes buffer headers to. /// </summary> /// <param name="port">The port the buffer is sent to.</param> /// <param name="buffer">The buffer header.</param> internal override void NativeOutputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { lock (MMALPortBase.OutputLock) { if (MMALCameraConfig.Debug) { MMALLog.Logger.Debug("In native output callback"); } var bufferImpl = new MMALBufferImpl(buffer); if (MMALCameraConfig.Debug) { bufferImpl.PrintProperties(); } var triggered = this.Trigger != null && this.Trigger.CurrentCount == 0; var eos = (this.Timeout.HasValue && DateTime.Now.CompareTo(this.Timeout.Value) > 0) || this.ComponentReference.ForceStopProcessing; if (bufferImpl.Ptr != null && (IntPtr)bufferImpl.Ptr != IntPtr.Zero && bufferImpl.Length > 0 && !eos && !triggered) { this.ManagedOutputCallback.Callback(bufferImpl); } // Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. this.ReleaseOutputBuffer(bufferImpl); if (eos) { if (this.Trigger != null && this.Trigger.CurrentCount > 0) { MMALLog.Logger.Debug("Timeout exceeded, triggering signal."); this.Trigger.Signal(); } } } }
internal virtual unsafe void NativeInputPortCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (MMALCameraConfig.Debug) { MMALLog.Logger.LogDebug($"{this.Name}: In native input callback."); } var bufferImpl = new MMALBufferImpl(buffer); if (bufferImpl.CheckState()) { if (bufferImpl.Cmd > 0) { if (bufferImpl.Cmd == MMALEvents.MMAL_EVENT_FORMAT_CHANGED) { MMALLog.Logger.LogInformation("EVENT FORMAT CHANGED"); } } } bufferImpl.PrintProperties(); this.ReleaseBuffer(bufferImpl); }
/// <summary> /// Encodes/decodes user provided image data. /// </summary> /// <param name="outputPort">The output port to begin processing on. Usually will be 0.</param> /// <returns>An awaitable task.</returns> public virtual async Task Convert(int outputPort = 0) { MMALLog.Logger.Info("Beginning Video decode from stream. Please note, this process may take some time depending on the size of the input stream."); // Enable control, input and output ports. Input & Output ports should have been pre-configured by user prior to this point. this.Control.Start(); this.Inputs[0].Start(); this.Outputs[outputPort].Start(); this.EnableComponent(); WorkingQueue = MMALQueueImpl.Create(); var eosReceived = false; while (!eosReceived) { await this.WaitForTriggers().ConfigureAwait(false); this.GetAndSendInputBuffer(); MMALLog.Logger.Debug("Getting processed output pool buffer"); while (true) { MMALBufferImpl buffer = WorkingQueue.GetBuffer(); if (buffer.CheckState()) { eosReceived = ((int)buffer.Flags & (int)MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS) == (int)MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS; if (buffer.Cmd > 0) { if (buffer.Cmd == MMALEvents.MMAL_EVENT_FORMAT_CHANGED) { this.ProcessFormatChangedEvent(buffer); } else { buffer.Release(); } } else { if (buffer.Length > 0) { this.Outputs[0].ManagedOutputCallback.Callback(buffer); } else { MMALLog.Logger.Debug("Buffer length empty."); } // Ensure we release the buffer before any signalling or we will cause a memory leak due to there still being a reference count on the buffer. buffer.Release(); } } else { MMALLog.Logger.Debug("Buffer null."); break; } } this.GetAndSendOutputBuffer(); } MMALLog.Logger.Info("Received EOS. Exiting."); this.DisableComponent(); this.CleanPortPools(); WorkingQueue.Dispose(); }