// Copyright 2020 The MediaPipe Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "absl/time/time.h" #include "mediapipe/framework/calculator_framework.h" #include "mediapipe/framework/deps/clock.h" #include "mediapipe/framework/deps/monotonic_clock.h" #include "mediapipe/framework/port/logging.h" #include "mediapipe/framework/port/ret_check.h" #include "mediapipe/framework/port/status.h" namespace mediapipe { namespace { // Tag name for clock side packet. constexpr char kClockTag[] = "CLOCK"; } // namespace // A calculator that outputs the current clock time at which it receives input // packets. Use a separate instance of this calculator for each input stream // you wish to output a clock time for. // // InputSidePacket (Optional): // CLOCK: A clock to use for querying the current time. // // Inputs: // A single packet stream we wish to get the current clocktime for // Outputs: // A single stream of absl::Time packets, representing the clock time at which // we received the input stream's packets. // Example config: // node { // calculator: "ClockTimestampCalculator" // input_side_packet: "CLOCK:monotonic_clock" // input_stream: "packet_stream" // output_stream: "packet_clocktime_stream" // } // class ClockTimestampCalculator : public CalculatorBase { public: ClockTimestampCalculator() {} static absl::Status GetContract(CalculatorContract* cc); absl::Status Open(CalculatorContext* cc) override; absl::Status Process(CalculatorContext* cc) override; private: // Clock object. std::shared_ptr<::mediapipe::Clock> clock_; }; REGISTER_CALCULATOR(ClockTimestampCalculator); absl::Status ClockTimestampCalculator::GetContract(CalculatorContract* cc) { RET_CHECK_EQ(cc->Inputs().NumEntries(), 1); RET_CHECK_EQ(cc->Outputs().NumEntries(), 1); cc->Inputs().Index(0).SetAny(); cc->Outputs().Index(0).Set(); // Optional Clock input side packet. if (cc->InputSidePackets().HasTag(kClockTag)) { cc->InputSidePackets() .Tag(kClockTag) .Set>(); } return absl::OkStatus(); } absl::Status ClockTimestampCalculator::Open(CalculatorContext* cc) { // Direct passthrough, as far as timestamp and bounds are concerned. cc->SetOffset(TimestampDiff(0)); // Initialize the clock. if (cc->InputSidePackets().HasTag(kClockTag)) { clock_ = cc->InputSidePackets() .Tag("CLOCK") .Get>(); } else { clock_.reset( ::mediapipe::MonotonicClock::CreateSynchronizedMonotonicClock()); } return absl::OkStatus(); } absl::Status ClockTimestampCalculator::Process(CalculatorContext* cc) { // Push the Time packet to output. auto timestamp_packet = MakePacket(clock_->TimeNow()); cc->Outputs().Index(0).AddPacket(timestamp_packet.At(cc->InputTimestamp())); return absl::OkStatus(); } } // namespace mediapipe