83 bool got_core_metrics_output;
84 physiology::MetricsBuffer metrics_buffer;
85 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
87 got_core_metrics_output,
88 this->core_metrics_poller.Get(),
89 pe::graph::output_streams::kMetricsBuffer,
90 this->settings.verbosity_level > 2
92 if (got_core_metrics_output) {
93 MP_RETURN_IF_ERROR(this->OnCoreMetricsOutput(metrics_buffer, frame_timestamp));
94 if (TOperationMode == settings::OperationMode::Spot) {
96 this->recording =
false;
97 if (this->load_video) {
98 keep_grabbing_frames =
false;
99 }
else if (this->settings.video_source.auto_lock &&
100 this->video_source->SupportsExposureControls()) {
101 MP_RETURN_IF_ERROR(this->video_source->TurnOnAutoExposure());
109 if (TOperationMode == settings::OperationMode::Continuous) {
110 if (this->settings.enable_edge_metrics) {
111 bool got_edge_metrics_output;
113 physiology::Metrics edge_metrics;
114 mediapipe::Timestamp timestamp;
115 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
116 edge_metrics, got_edge_metrics_output, this->edge_metrics_poller.Get(),
117 pe::graph::output_streams::kEdgeMetrics, timestamp,
118 this->settings.verbosity_level > 2
120 if (got_edge_metrics_output) {
121 MP_RETURN_IF_ERROR(this->OnEdgeMetricsOutput(edge_metrics, timestamp.Value()));
123 }
while (got_edge_metrics_output);
127 return absl::OkStatus();
227 this->operation_context.Reset();
228 if (!this->initialized) {
229 return absl::PermissionDeniedError(
"Client not initialized.");
231 this->running =
true;
232 LOG(INFO) <<
"Set up output pollers.";
237 MP_ASSIGN_OR_RETURN(mediapipe::OutputStreamPoller output_video_poller,
238 this->graph.AddOutputStreamPoller(pe::graph::output_streams::kOutputVideo));
239 MP_ASSIGN_OR_RETURN(mediapipe::OutputStreamPoller status_code_poller,
240 this->graph.AddOutputStreamPoller(pe::graph::output_streams::kStatusCode));
241 MP_ASSIGN_OR_RETURN(mediapipe::OutputStreamPoller blue_tooth_poller,
242 this->graph.AddOutputStreamPoller(pe::graph::output_streams::kBlueTooth));
245 MP_ASSIGN_OR_RETURN(mediapipe::OutputStreamPoller frame_sent_through_poller,
246 this->graph.AddOutputStreamPoller(pe::graph::output_streams::kFrameSentThrough));
251 MP_RETURN_IF_ERROR(this->operation_context.InitializePollers(this->graph));
253 LOG(INFO) <<
"Start running the calculator graph.";
254 MP_RETURN_IF_ERROR(this->graph.StartRun({}));
257 if (this->tuning_enabled) {
258 MP_RETURN_IF_ERROR(this->camera_tuner->StartTuning());
259 LOG(INFO) <<
"Starting camera tuning...";
262 LOG(INFO) <<
"Start to grab and process frames.";
263 this->keep_grabbing_frames =
true;
267#ifdef BENCHMARK_CAMERA_CAPTURE
269 std::chrono::duration<double> interval_capture_time(0.);
270 std::chrono::duration<double> interval_frame_time(0.);
271 int64 frame_interval = 30;
277 this->ScrollPastTimeOffset();
279 physiology::StatusCode previous_status_code = physiology::StatusCode::PROCESSING_NOT_STARTED;
282 while (this->keep_grabbing_frames) {
283 cv::Mat camera_frame_raw;
284#ifdef BENCHMARK_CAMERA_CAPTURE
285 auto frame_loop_start = std::chrono::high_resolution_clock::now();
288 *this->video_source >> camera_frame_raw;
289#ifdef WITH_VIDEO_OUTPUT
290 if (this->stream_writer.isOpened() && this->settings.video_sink.passthrough) {
291 this->stream_writer.write(camera_frame_raw);
294#ifdef BENCHMARK_CAMERA_CAPTURE
295 auto frame_capture_end = std::chrono::high_resolution_clock::now();
297 if (camera_frame_raw.empty()) {
298 LOG(INFO) <<
"Encountered empty frame: assuming end of video or stream reached.";
299 this->keep_grabbing_frames =
false;
304 int64_t frame_timestamp = this->video_source->GetFrameTimestamp();
305 auto mp_frame_timestamp = mediapipe::Timestamp(frame_timestamp);
309 cv::Mat camera_frame;
310 cv::cvtColor(camera_frame_raw, camera_frame, cv::COLOR_BGR2RGB);
313 auto input_frame = absl::make_unique<mediapipe::ImageFrame>(
314 mediapipe::ImageFormat::SRGB, camera_frame.cols, camera_frame.rows,
315 mediapipe::ImageFrame::kDefaultAlignmentBoundary
317 cv::Mat input_frame_mat = mediapipe::formats::MatView(input_frame.get());
319 camera_frame.copyTo(input_frame_mat);
324 .AddPacketToInputStream(
325 pe::graph::input_streams::kRecording,
326 mediapipe::MakePacket<bool>(this->recording).At(mp_frame_timestamp)
331 it::FeedFrameToGraph(std::move(input_frame), this->graph, this->device_context, frame_timestamp,
332 pe::graph::input_streams::kInputVideo)
337 mediapipe::Packet output_video_packet;
338 if (output_video_poller.QueueSize() > 0) {
339 if (!output_video_poller.Next(&output_video_packet))
break;
340 cv::Mat output_frame_rgb;
341 MP_RETURN_IF_ERROR(it::GetFrameFromPacket<TDeviceType>(output_frame_rgb,
342 this->device_context,
343 output_video_packet));
346 cv::cvtColor(output_frame_rgb, this->output_frame_bgr, cv::COLOR_RGB2BGR);
349 MP_RETURN_IF_ERROR(this->OnVideoOutput(this->output_frame_bgr, frame_timestamp));
352 if (!this->settings.headless) {
353 if(this->tuning_enabled && this->camera_tuner->IsTuning()){
354 this->output_frame_bgr = this->camera_tuner->ProcessFrameForDisplay(this->output_frame_bgr);
356 cv::imshow(kWindowName, this->output_frame_bgr);
358#ifdef WITH_VIDEO_OUTPUT
359 if (this->stream_writer.isOpened() && !this->settings.video_sink.passthrough) {
360 this->stream_writer.write(output_frame_bgr);
365 bool got_status_code_packet;
366 physiology::StatusValue status_value;
367 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
368 status_value, got_status_code_packet, status_code_poller, pe::graph::output_streams::kStatusCode,
369 this->settings.verbosity_level > 2
372 if (got_status_code_packet){
373 this->status = status_value;
376 MP_RETURN_IF_ERROR(this->OnStatusCode(this->status));
379 if (this->status.value() != previous_status_code) {
380 MP_RETURN_IF_ERROR(this->OnStatusChange(this->status));
381 previous_status_code = this->status.value();
385 if (this->tuning_enabled && this->camera_tuner->IsTuning()) {
386 auto tuning_status = this->camera_tuner->ProcessFrame(this->status.value(), frame_timestamp);
388 if (!tuning_status.ok()) {
390 LOG(WARNING) <<
"Camera tuning failed: " << tuning_status.message();
391 LOG(WARNING) <<
"Continuing without tuning - recording will be disabled until status is `OK`.";
392 this->tuning_enabled =
false;
393 }
else if (!this->camera_tuner->IsTuning()) {
395 LOG(INFO) <<
"Camera tuning complete!";
396 auto exp = this->camera_tuner->GetTunedExposure();
397 auto gain = this->camera_tuner->GetTunedGain();
399 LOG(INFO) <<
" Tuned exposure: " << *exp;
402 LOG(INFO) <<
" Tuned gain: " << *gain;
404 auto wb = this->camera_tuner->GetTunedWhiteBalance();
406 LOG(INFO) <<
" Tuned white balance: " << *wb;
412 bool got_blue_tooth_packet;
413 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
414 blue_tooth, got_blue_tooth_packet, blue_tooth_poller, pe::graph::output_streams::kBlueTooth,
415 this->settings.verbosity_level > 0
418 bool operation_state_changed;
419 MP_RETURN_IF_ERROR(this->operation_context
420 .QueryPollers(operation_state_changed, this->settings.verbosity_level > 1));
422 bool got_frame_sent_through_packet;
423 bool frame_sent_through;
424 mediapipe::Timestamp frame_sent_through_timestamp;
425 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
426 frame_sent_through, got_frame_sent_through_packet, frame_sent_through_poller,
427 pe::graph::output_streams::kFrameSentThrough, frame_sent_through_timestamp,
428 this->settings.verbosity_level > 4
430 if(got_frame_sent_through_packet){
431 MP_RETURN_IF_ERROR(this->OnFrameSentThrough(frame_sent_through, frame_sent_through_timestamp.Value()));
437 if (this->settings.headless) {
438 if (!this->load_video) {
441 if (!this->recording && this->status.value() == physiology::StatusCode::OK) {
442 if (this->settings.video_source.auto_lock && this->video_source->SupportsExposureControls()) {
443 return this->video_source->TurnOffAutoExposure();
445 this->recording =
true;
446 LOG(INFO) <<
"====== Recording started after timestamp:" << frame_timestamp <<
" ======";
449 std::this_thread::sleep_for(std::chrono::milliseconds(this->settings.interframe_delay_ms));
451 MP_RETURN_IF_ERROR(keys::HandleKeyboardInput(
452 this->keep_grabbing_frames, this->recording, *(this->video_source), this->settings, this->status,
453 this->camera_tuner.get(), this->tuning_enabled
458#ifdef BENCHMARK_CAMERA_CAPTURE
460 bench::HandleCameraBenchmarking(
461 i_frame, interval_capture_time, interval_frame_time, frame_loop_start, frame_capture_end,
462 frame_interval, this->settings.interframe_delay_ms, this->settings.verbosity_level
468 LOG(INFO) <<
"Shutting down.";
469 MP_RETURN_IF_ERROR(this->graph.CloseAllInputStreams());
470 MP_RETURN_IF_ERROR(this->graph.CloseAllPacketSources());
471#ifdef WITH_VIDEO_OUTPUT
472 if (this->stream_writer.isOpened()) {
473 this->stream_writer.release();
476 MP_RETURN_IF_ERROR(this->graph.WaitUntilDone());
477 this->running =
false;
478 return absl::OkStatus();