Skip to content

Commit

Permalink
rpicam-vid: Update for camera sync algorithm
Browse files Browse the repository at this point in the history
A "sync" option has been added, which may take the values "server" or
"client", turning the camera into either the server of client of a
synchronised recording.

Setting the camera into sync mode, and skipping frames while waiting
for sync, is delegated to the RPiCamEncoder class, so that all video
recording applications acquire the functionality.

Signed-off-by: David Plowman <[email protected]>
Signed-off-by: Arsen Mikovic <[email protected]>
Signed-off-by: Naushir Patuck <[email protected]>
  • Loading branch information
naushir authored and davidplowman committed Oct 3, 2024
1 parent a8ccf9f commit e4d2959
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
build
*~
.vscode/
1 change: 0 additions & 1 deletion apps/rpicam_vid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ static void event_loop(RPiCamEncoder &app)
app.StopEncoder();
return;
}

CompletedRequestPtr &completed_request = std::get<CompletedRequestPtr>(msg.payload);
app.EncodeBuffer(completed_request, app.VideoStream());
app.ShowPreview(completed_request, app.VideoStream());
Expand Down
17 changes: 17 additions & 0 deletions core/rpicam_encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,30 @@ class RPiCamEncoder : public RPiCamApp
createEncoder();
encoder_->SetInputDoneCallback(std::bind(&RPiCamEncoder::encodeBufferDone, this, std::placeholders::_1));
encoder_->SetOutputReadyCallback(encode_output_ready_callback_);

// Set up the encode function to wait for synchronisation with another camera system,
// when this has been requested in the options.
VideoOptions const *options = GetOptions();
libcamera::ControlList cl;
if (options->sync == 0)
cl.set(libcamera::controls::rpi::SyncMode, libcamera::controls::rpi::SyncModeOff);
else if (options->sync == 1)
cl.set(libcamera::controls::rpi::SyncMode, libcamera::controls::rpi::SyncModeServer);
else if (options->sync == 2)
cl.set(libcamera::controls::rpi::SyncMode, libcamera::controls::rpi::SyncModeClient);
SetControls(cl);
}
// This is callback when the encoder gives you the encoded output data.
void SetEncodeOutputReadyCallback(EncodeOutputReadyCallback callback) { encode_output_ready_callback_ = callback; }
void SetMetadataReadyCallback(MetadataReadyCallback callback) { metadata_ready_callback_ = callback; }
void EncodeBuffer(CompletedRequestPtr &completed_request, Stream *stream)
{
assert(encoder_);

// If sync was enabled, and the SyncWait metadata is still "true" then we must skip this frame.
if (GetOptions()->sync && completed_request->metadata.get(controls::rpi::SyncWait).value_or(true))
return;

StreamInfo info = GetStreamInfo(stream);
FrameBuffer *buffer = completed_request->buffers[stream];
BufferReadSync r(this, buffer);
Expand Down
14 changes: 14 additions & 0 deletions core/video_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ struct VideoOptions : public Options
"Add a time offset (in microseconds if no units provided) to the audio stream, relative to the video stream. "
"The offset value can be either positive or negative.")
#endif
("sync", value<std::string>(&sync_)->default_value("off"),
"Whether to synchronise with another camera. Use \"off\", \"server\" or \"client\".")
;
// clang-format on
}
Expand Down Expand Up @@ -191,6 +193,7 @@ struct VideoOptions : public Options
uint32_t segment;
size_t circular;
uint32_t frames;
uint32_t sync;

virtual bool Parse(int argc, char *argv[]) override
{
Expand Down Expand Up @@ -235,6 +238,15 @@ struct VideoOptions : public Options
level = "4.2";
}

if (strcasecmp(sync_.c_str(), "off") == 0)
sync = 0;
else if (strcasecmp(sync_.c_str(), "server") == 0)
sync = 1;
else if (strcasecmp(sync_.c_str(), "client") == 0)
sync = 2;
else
throw std::runtime_error("incorrect sync value " + sync_);

return true;
}
virtual void Print() const override
Expand All @@ -254,6 +266,7 @@ struct VideoOptions : public Options
std::cerr << " split: " << split << std::endl;
std::cerr << " segment: " << segment << std::endl;
std::cerr << " circular: " << circular << std::endl;
std::cerr << " sync: " << sync << std::endl;
}

private:
Expand All @@ -262,4 +275,5 @@ struct VideoOptions : public Options
std::string av_sync_;
std::string audio_bitrate_;
#endif /* LIBAV_PRESENT */
std::string sync_;
};

0 comments on commit e4d2959

Please sign in to comment.