feat: add streamer-owned recording control service
Introduce a dedicated streamer-side recording control plane instead of sharing the producer recorder API. - register streamer-owned recorder endpoints as a NATS micro service - add explicit MP4 and MCAP recorder control protobufs and subject helpers - wire recorder lifecycle handling into the pipeline runtime - add MP4 writer and depth-alignment support files used by the new recording flow
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include "proto/cvmmap_streamer/recorder_control.pb.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
namespace cvmmap_streamer::protocol {
|
||||
|
||||
enum class RpcErrorCode : std::uint8_t {
|
||||
InvalidRequest,
|
||||
Unsupported,
|
||||
Busy,
|
||||
Internal,
|
||||
};
|
||||
|
||||
struct RpcError {
|
||||
RpcErrorCode code{RpcErrorCode::Internal};
|
||||
std::string message{};
|
||||
};
|
||||
|
||||
struct NatsRequestReplyServerOptions {
|
||||
std::string nats_url{};
|
||||
std::string instance_name{};
|
||||
std::string namespace_name{};
|
||||
std::string ipc_prefix{};
|
||||
std::string base_name{};
|
||||
std::string nats_target_key{};
|
||||
std::string backend{"cvmmap-streamer"};
|
||||
std::string recording_formats{};
|
||||
};
|
||||
|
||||
class NatsRequestReplyServer {
|
||||
public:
|
||||
explicit NatsRequestReplyServer(NatsRequestReplyServerOptions options);
|
||||
~NatsRequestReplyServer();
|
||||
|
||||
NatsRequestReplyServer(const NatsRequestReplyServer &) = delete;
|
||||
NatsRequestReplyServer &operator=(const NatsRequestReplyServer &) = delete;
|
||||
|
||||
template <class Request, class Response>
|
||||
void register_proto_endpoint(
|
||||
std::string endpoint_name,
|
||||
std::string subject,
|
||||
std::function<std::expected<Response, RpcError>(const Request &)> handler) {
|
||||
register_raw_endpoint(
|
||||
std::move(endpoint_name),
|
||||
std::move(subject),
|
||||
[handler = std::move(handler)](std::span<const std::uint8_t> payload) {
|
||||
Request request;
|
||||
Response response;
|
||||
if (!request.ParseFromArray(
|
||||
payload.data(),
|
||||
static_cast<int>(payload.size()))) {
|
||||
response.set_code(cvmmap_streamer::proto::RPC_CODE_INVALID_REQUEST);
|
||||
response.set_error_message("failed to parse protobuf request");
|
||||
return response.SerializeAsString();
|
||||
}
|
||||
|
||||
auto handled = handler(request);
|
||||
if (!handled) {
|
||||
response.set_code(to_proto_rpc_code(handled.error().code));
|
||||
response.set_error_message(handled.error().message);
|
||||
return response.SerializeAsString();
|
||||
}
|
||||
|
||||
return handled->SerializeAsString();
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool start();
|
||||
void stop();
|
||||
|
||||
private:
|
||||
struct Endpoint;
|
||||
struct Impl;
|
||||
|
||||
void register_raw_endpoint(
|
||||
std::string endpoint_name,
|
||||
std::string subject,
|
||||
std::function<std::string(std::span<const std::uint8_t>)> handler);
|
||||
|
||||
static cvmmap_streamer::proto::RpcCode to_proto_rpc_code(RpcErrorCode code);
|
||||
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace cvmmap_streamer::protocol
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace cvmmap_streamer::protocol {
|
||||
|
||||
inline std::string streamer_subject_prefix(std::string_view target_key) {
|
||||
return std::string("cvmmap.") + std::string(target_key) + ".streamer";
|
||||
}
|
||||
|
||||
inline std::string subject_recorder_mp4_start(std::string_view target_key) {
|
||||
return streamer_subject_prefix(target_key) + ".recorder.mp4.start";
|
||||
}
|
||||
|
||||
inline std::string subject_recorder_mp4_stop(std::string_view target_key) {
|
||||
return streamer_subject_prefix(target_key) + ".recorder.mp4.stop";
|
||||
}
|
||||
|
||||
inline std::string subject_recorder_mp4_status(std::string_view target_key) {
|
||||
return streamer_subject_prefix(target_key) + ".recorder.mp4.status";
|
||||
}
|
||||
|
||||
inline std::string subject_recorder_mcap_start(std::string_view target_key) {
|
||||
return streamer_subject_prefix(target_key) + ".recorder.mcap.start";
|
||||
}
|
||||
|
||||
inline std::string subject_recorder_mcap_stop(std::string_view target_key) {
|
||||
return streamer_subject_prefix(target_key) + ".recorder.mcap.stop";
|
||||
}
|
||||
|
||||
inline std::string subject_recorder_mcap_status(std::string_view target_key) {
|
||||
return streamer_subject_prefix(target_key) + ".recorder.mcap.status";
|
||||
}
|
||||
|
||||
} // namespace cvmmap_streamer::protocol
|
||||
Reference in New Issue
Block a user