#include "G330FrameTimestampCalculator.hpp"
#include "logger/LoggerInterval.hpp"
#include "InternalTypes.hpp"
#include "frame/Frame.hpp"
namespace libobsensor {
G330FrameTimestampCalculatorBaseDeviceTime::G330FrameTimestampCalculatorBaseDeviceTime(IDevice *device, uint64_t deviceTimeFreq, uint64_t frameTimeFreq)
: device_(device), deviceTimeFreq_(deviceTimeFreq), frameTimeFreq_(frameTimeFreq), prevSrcTsp_(0), prevHostTsp_(0), baseDevTime_(0), devTime_(0) {
auto propServer = device->getPropertyServer();
std::vector<uint32_t> supportedProps;
if(propServer->isPropertySupported(OB_PROP_TIMER_RESET_SIGNAL_BOOL, PROP_OP_WRITE, PROP_ACCESS_INTERNAL)) {
supportedProps.push_back(OB_PROP_TIMER_RESET_SIGNAL_BOOL);
}
if(propServer->isPropertySupported(OB_STRUCT_DEVICE_TIME, PROP_OP_WRITE, PROP_ACCESS_INTERNAL)) {
supportedProps.push_back(OB_STRUCT_DEVICE_TIME);
}
if(!supportedProps.empty()) {
propServer->registerAccessCallback(supportedProps, [&](uint32_t, const uint8_t *, size_t, PropertyOperationType operationType) {
if(operationType == PROP_OP_WRITE) {
clear();
}
});
}
}
void G330FrameTimestampCalculatorBaseDeviceTime::calculate(std::shared_ptr<Frame> frame) {
auto srcTimestamp = frame->getTimeStampUsec();
auto rstTsp = calculate(srcTimestamp);
frame->setTimeStampUsec(rstTsp);
}
uint64_t G330FrameTimestampCalculatorBaseDeviceTime::calculate(uint64_t srcTimestamp) {
bool tspDecrease = (srcTimestamp < prevSrcTsp_) && (prevSrcTsp_ - srcTimestamp > 0.5 * frameTimeFreq_);
uint64_t curHostTsp = utils::getNowTimesMs();
int64_t srcTspDiffMs = static_cast<int64_t>((static_cast<double>(srcTimestamp) - prevSrcTsp_) / frameTimeFreq_ * 1000); int64_t hostTspDiffMs = curHostTsp - prevHostTsp_;
uint64_t prevSrcTspMs = static_cast<uint64_t>(static_cast<double>(prevSrcTsp_) / frameTimeFreq_ * 1000);
bool tspDiffAbnormal = ((static_cast<double>(hostTspDiffMs) - srcTspDiffMs) >= prevSrcTspMs / 2);
if(devTime_ == 0 || ((tspDecrease || tspDiffAbnormal) && (srcTimestamp != 0 || prevSrcTsp_ != 0)) || prevSrcTspMs <= 50) {
LOG_DEBUG_INTVL_MS(1000, "updateBaseTimeStamp:");
LOG_DEBUG_INTVL_MS(1000, "\tsrcTimestamp={0}, prevSrcTsp_={1}, tspDecrease={2}", srcTimestamp, prevSrcTsp_, tspDecrease);
LOG_DEBUG_INTVL_MS(1000, "\tsrcTspDiffMs={0}, hostTspDiffMs={1}, tspDiffAbnormal={2}", srcTspDiffMs, hostTspDiffMs, tspDiffAbnormal);
{
auto propertyServer = device_->getPropertyServer();
auto devTime = propertyServer->getStructureDataT<OBDeviceTime>(OB_STRUCT_DEVICE_TIME);
devTime_ = static_cast<uint64_t>((static_cast<double>(devTime.time) + devTime.rtt / 2) / deviceTimeFreq_ * frameTimeFreq_);
}
uint64_t overFlowTimes = devTime_ / (256 * frameTimeFreq_);
uint64_t calculateLeftoverTimestamp = devTime_ - overFlowTimes * (256 * frameTimeFreq_);
if(overFlowTimes > 0) {
if(calculateLeftoverTimestamp < srcTimestamp) {
baseDevTime_ = (overFlowTimes - 1) * (256 * frameTimeFreq_);
}
else {
baseDevTime_ = devTime_ - calculateLeftoverTimestamp;
}
} else {
baseDevTime_ = 0;
}
}
prevHostTsp_ = curHostTsp;
prevSrcTsp_ = srcTimestamp;
auto outputTsp = baseDevTime_ + srcTimestamp;
auto timestampUsec = static_cast<double>(outputTsp) / frameTimeFreq_ * 1000000;
return static_cast<uint64_t>(timestampUsec);
}
void G330FrameTimestampCalculatorBaseDeviceTime::clear() {
prevSrcTsp_ = 0;
prevHostTsp_ = 0;
baseDevTime_ = 0;
}
}