fix: use TAI-time-based grain index alignment in passthrough

Instead of chasing headIndex from mxlFlowReaderGetRuntimeInfo (which
points to the NEXT grain to be written, causing perpetual TOO_EARLY),
the passthrough now uses mxlTimestampToIndex + mxlGetNsUntilIndex for
proper timing alignment, matching the pattern used by mxl-gst-sink.

Key changes:
- realign() computes read_index from current TAI time minus 1 grain delay
- process() uses mxlSleepForNs to wait until the target grain is due
- on_add_reader fetches grain_rate from mxlFlowConfigInfo
- Removed separate write_index_ (uses grain_info.index for writer)
This commit is contained in:
Johanness
2026-05-26 22:40:46 +03:00
parent 3e1477c56c
commit 2c712592dd
2 changed files with 29 additions and 12 deletions
+25 -9
View File
@@ -2,6 +2,7 @@
#include <mxl/flow.h>
#include <mxl/mxl.h>
#include <mxl/time.h>
#include <spdlog/spdlog.h>
@@ -19,10 +20,14 @@ void PassthroughNode::on_add_writer(const std::string& port_id, mxlFlowWriter wr
void PassthroughNode::on_add_reader(const std::string& port_id, mxlFlowReader reader) {
if (port_id == "video_in") {
reader_ = reader;
mxlFlowRuntimeInfo runtime{};
mxlFlowReaderGetRuntimeInfo(*reader_, &runtime);
read_index_ = runtime.headIndex;
spdlog::info("Passthrough: reader added on video_in, starting at index {}", read_index_);
mxlFlowConfigInfo config{};
mxlFlowReaderGetConfigInfo(*reader_, &config);
grain_rate_ = config.common.grainRate;
realign();
spdlog::info("Passthrough: reader added on video_in, grain_rate={}/{}, read_index={}",
grain_rate_.numerator, grain_rate_.denominator, read_index_);
}
}
@@ -40,21 +45,32 @@ void PassthroughNode::on_remove_reader(const std::string& port_id) {
}
}
void PassthroughNode::realign() {
auto now = mxlGetTime();
auto current_index = mxlTimestampToIndex(&grain_rate_, now);
constexpr int64_t read_delay_grains = 1;
read_index_ = current_index - read_delay_grains;
aligned_ = true;
}
void PassthroughNode::process() {
if (!reader_ || !writer_) {
if (!reader_ || !writer_ || !aligned_) {
return;
}
auto wait_ns = mxlGetNsUntilIndex(read_index_, &grain_rate_);
if (wait_ns > 0 && wait_ns < 500000000ULL) {
mxlSleepForNs(wait_ns);
}
mxlGrainInfo grain_info{};
uint8_t* payload = nullptr;
auto status = mxlFlowReaderGetGrain(*reader_, read_index_, 20000000ULL, &grain_info, &payload);
if (status != MXL_STATUS_OK) {
if (status == MXL_ERR_OUT_OF_RANGE_TOO_LATE || status == MXL_ERR_OUT_OF_RANGE_TOO_EARLY) {
mxlFlowRuntimeInfo runtime{};
mxlFlowReaderGetRuntimeInfo(*reader_, &runtime);
spdlog::warn("Passthrough: index {} out of range, jumping to head {}", read_index_, runtime.headIndex);
read_index_ = runtime.headIndex;
spdlog::warn("Passthrough: index {} out of range ({}), realigning", read_index_, static_cast<int>(status));
realign();
}
return;
}