Closed MV10 closed 3 years ago
Modifications to the wiki motion detection example to capture three images at the start of recording, one per second. Motion detection comments removed so that on-demand comments will stand out:
public async Task DetectMotionWithImages()
{
MMALCamera cam = MMALCamera.Instance;
MMALCameraConfig.InlineHeaders = true;
// Stores the most current full frame; will write it on demand in response to a call to NewFile()
using (var imgCaptureHandler = new OnDemandImageCaptureHandler(ramdiskPath, "jpg"))
// Setting continuousCapture puts the handler into fast image processing mode
using (var imgEncoder = new MMALImageEncoder(continuousCapture: true))
using (var vidCaptureHandler = new CircularBufferCaptureHandler(4000000, "/home/pi/videos/detections", "h264"))
using (var motionCircularBufferCaptureHandler = new CircularBufferCaptureHandler(4000000))
using (var splitter = new MMALSplitterComponent())
using (var resizer = new MMALIspComponent())
using (var vidEncoder = new MMALVideoEncoder())
using (var renderer = new MMALVideoRenderer())
{
cam.ConfigureCameraSettings();
splitter.ConfigureInputPort(new MMALPortConfig(MMALEncoding.OPAQUE, MMALEncoding.I420), cam.Camera.VideoPort, null);
resizer.ConfigureOutputPort<VideoPort>(0, new MMALPortConfig(MMALEncoding.RGB24, MMALEncoding.RGB24, width: 640, height: 480), motionCaptureHandler);
vidEncoder.ConfigureOutputPort(new MMALPortConfig(MMALEncoding.H264, MMALEncoding.I420, 0, MMALVideoEncoder.MaxBitrateLevel4, null), vidCaptureHandler);
// Note the image quality argument for still image capture
imgEncoder.ConfigureOutputPort(new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.I420, quality: 90), imgCaptureHandler);
cam.Camera.VideoPort.ConnectTo(splitter);
cam.Camera.PreviewPort.ConnectTo(renderer);
splitter.Outputs[0].ConnectTo(resizer);
splitter.Outputs[1].ConnectTo(vidEncoder);
splitter.Outputs[2].ConnectTo(imgEncoder); // Still-image input/output connection
await Task.Delay(2000);
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
var motionConfig = new MotionConfig(threshold: 130, testFrameInterval: TimeSpan.FromSeconds(3));
await cam.WithMotionDetection(motionCircularBufferCaptureHandler, motionConfig,
async () =>
{
// This callback will be invoked when motion has been detected.
motionCircularBufferCaptureHandler.DisableMotionDetection();
var ctsStopRecording = new CancellationTokenSource();
ctsStopRecording.Token.Register(() =>
{
motionCircularBufferCaptureHandler.EnableMotionDetection();
vidCaptureHandler.StopRecording();
vidCaptureHandler.Split();
});
// These will time out and record a still image one and two seconds after the recording starts
var ctsImageOneSecond = new CancellationTokenSource();
var ctsImageTwoSecond = new CancellationTokenSource();
// Save image on demand by calling NewFile() when the token timeout expires
ctsImageOneSecond.Token.Register(imgCaptureHandler.NewFile)
ctsImageTwoSecond.Token.Register(imgCaptureHandler.NewFile)
// Record an image right now, then set the still-image timers, and the overall recording timer
imgCaptureHandler.NewFile();
ctsImageOneSecond.CancelAfter(1000);
ctsImageTwoSecond.CancelAfter(2000);
ctsStopRecording.CancelAfter(10 * 1000);
await Task.WhenAny(
vidCaptureHandler.StartRecording(vidEncoder.RequestIFrame, ctsStopRecording.Token),
cts.Token.AsTask()
);
if (!recordingCTS.IsCancellationRequested)
{
ctsImageOneSecond.Cancel();
ctsImageTwoSecond.Cancel();
recordingCTS.Cancel();
}
})
.ProcessAsync(cam.Camera.VideoPort, cts.Token);
}
cam.Cleanup();
}
Closing in favor of modifications to existing handlers.
Fixes #163
Adds
OnDemandImageCaptureHandler
andIStreamWriter
to the Processing project.Modifies
FastImageOutputCallbackHandler
in the main project to recognize anIStreamWriter
handler.