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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user