#include #include #include #include "NodeBase.hpp" #include "FlowDef.hpp" #include "V210.hpp" class TestPatternNode : public dmf::NodeBase { void run() override { const auto flow_info = config().at("flow_id"); const auto flow_id = flow_info.at("id").get(); const int width = flow_info.value("width", 1920); const int height = flow_info.value("height", 1080); const int fps_num = flow_info.value("fps_num", 25); const int fps_den = flow_info.value("fps_den", 1); log("flow=%s %dx%d @ %d/%d fps", flow_id.c_str(), width, height, fps_num, fps_den); const std::string flow_def = dmf::make_video_flow_def(flow_id, node_id(), width, height, fps_num, fps_den); mxlFlowWriter writer{}; mxlFlowConfigInfo cfg_info{}; bool created = false; mxlStatus st = mxlCreateFlowWriter( instance(), flow_def.c_str(), nullptr, &writer, &cfg_info, &created); if (st != MXL_STATUS_OK) { log("mxlCreateFlowWriter failed (status=%d)", st); return; } const uint32_t stride = cfg_info.discrete.sliceSizes[0]; log("stride=%u B/line grain=%u B ring=%u grains", stride, stride * static_cast(height), cfg_info.discrete.grainCount); const mxlRational rate = {fps_num, fps_den}; uint64_t index = mxlGetCurrentIndex(&rate); log("start index=%llu", index); while (dmf::g_running.load(std::memory_order_relaxed)) { mxlGrainInfo grain{}; uint8_t* buf = nullptr; st = mxlFlowWriterOpenGrain(writer, index, &grain, &buf); if (st != MXL_STATUS_OK) { log("OpenGrain failed (status=%d), skipping index=%llu", st, index); index++; continue; } dmf::v210::fill_frame(buf, width, height, stride); grain.flags = 0; grain.validSlices = grain.totalSlices; // mark grain complete so readers can consume it mxlFlowWriterCommitGrain(writer, &grain); const uint64_t ns = mxlGetNsUntilIndex(index + 1, &rate); if (ns > 0 && ns < 2'000'000'000ULL) mxlSleepForNs(ns); index++; } log("stopped at index=%llu", index); mxlReleaseFlowWriter(instance(), writer); } }; int main() { TestPatternNode node; return node.execute(); }