diff --git a/IVideoFeed.hpp b/IVideoFeed.hpp index efed6cb..7ec3a84 100644 --- a/IVideoFeed.hpp +++ b/IVideoFeed.hpp @@ -17,6 +17,12 @@ enum class FeedRuntimeStatus Error }; +struct V210ReadTiming +{ + uint64_t sourceReadNs = 0; + uint64_t payloadCopyNs = 0; +}; + class IVideoFeed { public: @@ -57,11 +63,13 @@ public: virtual bool readV210FrameInto( uint32_t frameCounter, void* destination, - size_t destinationSize) + size_t destinationSize, + V210ReadTiming* timing = nullptr) { (void)frameCounter; (void)destination; (void)destinationSize; + (void)timing; return false; } virtual uint32_t v210Width() const { return 0; } diff --git a/MxlSdkFeed.cpp b/MxlSdkFeed.cpp index aa7aa9b..0d1b5c4 100644 --- a/MxlSdkFeed.cpp +++ b/MxlSdkFeed.cpp @@ -575,10 +575,17 @@ const VideoFrame& MxlSdkFeed::getFrame(uint32_t frameCounter) bool MxlSdkFeed::readV210FrameInto( uint32_t frameCounter, void* destination, - size_t destinationSize) + size_t destinationSize, + V210ReadTiming* timing) { (void)frameCounter; + if (timing != nullptr) + { + timing->sourceReadNs = 0; + timing->payloadCopyNs = 0; + } + if (!mFlowOpened && !openFlow()) { return false; @@ -598,6 +605,8 @@ bool MxlSdkFeed::readV210FrameInto( uint8_t* payload = nullptr; + const auto readStart = std::chrono::steady_clock::now(); + while (true) { mxlStatus status = mxlFlowReaderGetGrainNonBlocking( @@ -653,6 +662,8 @@ bool MxlSdkFeed::readV210FrameInto( return false; } + const auto readEnd = std::chrono::steady_clock::now(); + const size_t payloadSize = static_cast(mSourceStride) * static_cast(mSourceHeight); @@ -665,7 +676,22 @@ bool MxlSdkFeed::readV210FrameInto( return false; } + const auto copyStart = std::chrono::steady_clock::now(); std::memcpy(destination, payload, payloadSize); + const auto copyEnd = std::chrono::steady_clock::now(); + + if (timing != nullptr) + { + timing->sourceReadNs = + static_cast( + std::chrono::duration_cast( + readEnd - readStart).count()); + timing->payloadCopyNs = + static_cast( + std::chrono::duration_cast( + copyEnd - copyStart).count()); + } + mLastDisplayedIndex = index; ++mFrameVersion; return true; @@ -793,11 +819,17 @@ bool MxlSdkFeed::supportsDirectV210Read() const { return false; } bool MxlSdkFeed::readV210FrameInto( uint32_t frameCounter, void* destination, - size_t destinationSize) + size_t destinationSize, + V210ReadTiming* timing) { (void)frameCounter; (void)destination; (void)destinationSize; + if (timing != nullptr) + { + timing->sourceReadNs = 0; + timing->payloadCopyNs = 0; + } return false; } uint32_t MxlSdkFeed::v210Width() const { return 0; } diff --git a/MxlSdkFeed.hpp b/MxlSdkFeed.hpp index 1601f94..62f39d8 100644 --- a/MxlSdkFeed.hpp +++ b/MxlSdkFeed.hpp @@ -50,7 +50,8 @@ public: bool readV210FrameInto( uint32_t frameCounter, void* destination, - size_t destinationSize) override; + size_t destinationSize, + V210ReadTiming* timing = nullptr) override; uint32_t v210Width() const override; uint32_t v210Height() const override; uint32_t v210Stride() const override; diff --git a/SyntheticV210Feed.cpp b/SyntheticV210Feed.cpp index 187b3d5..c2fcbaf 100644 --- a/SyntheticV210Feed.cpp +++ b/SyntheticV210Feed.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -151,8 +152,15 @@ bool SyntheticV210Feed::supportsDirectV210Read() const bool SyntheticV210Feed::readV210FrameInto( uint32_t frameCounter, void* destination, - size_t destinationSize) + size_t destinationSize, + V210ReadTiming* timing) { + if (timing != nullptr) + { + timing->sourceReadNs = 0; + timing->payloadCopyNs = 0; + } + if (destination == nullptr || mPayloads.empty()) { return false; @@ -171,7 +179,18 @@ bool SyntheticV210Feed::readV210FrameInto( return false; } + const auto copyStart = std::chrono::steady_clock::now(); std::memcpy(destination, payload.data(), payload.size()); + const auto copyEnd = std::chrono::steady_clock::now(); + + if (timing != nullptr) + { + timing->payloadCopyNs = + static_cast( + std::chrono::duration_cast( + copyEnd - copyStart).count()); + } + mGrainIndex = index; ++mFrameVersion; return true; diff --git a/SyntheticV210Feed.hpp b/SyntheticV210Feed.hpp index f2b7c83..6142613 100644 --- a/SyntheticV210Feed.hpp +++ b/SyntheticV210Feed.hpp @@ -30,7 +30,8 @@ public: bool readV210FrameInto( uint32_t frameCounter, void* destination, - size_t destinationSize) override; + size_t destinationSize, + V210ReadTiming* timing = nullptr) override; uint32_t v210Width() const override; uint32_t v210Height() const override; uint32_t v210Stride() const override; diff --git a/main.cpp b/main.cpp index 471bc56..09bf958 100644 --- a/main.cpp +++ b/main.cpp @@ -47,6 +47,8 @@ struct PerfStats uint64_t feedReadTicks = 0; uint64_t uploadDecodeTicks = 0; uint64_t stageCopyTicks = 0; + uint64_t directV210SourceReadNs = 0; + uint64_t directV210PayloadCopyNs = 0; uint64_t uploadRecordTicks = 0; uint64_t submitPresentTicks = 0; uint64_t idleDelayTicks = 0; @@ -65,6 +67,8 @@ struct FramePerfStats uint64_t fenceWaitTicks = 0; uint64_t feedReadTicks = 0; uint64_t stageCopyTicks = 0; + uint64_t directV210SourceReadNs = 0; + uint64_t directV210PayloadCopyNs = 0; uint64_t maxStageCopyTicks = 0; uint64_t maxStageCopyBytes = 0; uint32_t maxStageCopyFeed = 0; @@ -1610,6 +1614,7 @@ int main(int argc, char* argv[]) if (directV210Read) { + V210ReadTiming directReadTiming{}; const size_t v210Bytes = static_cast( feeds[i]->v210Stride() @@ -1622,7 +1627,8 @@ int main(int argc, char* argv[]) feeds[i]->readV210FrameInto( frameCounter, v210Feeds[i].v210MappedData, - v210Bytes + v210Bytes, + &directReadTiming ); const uint64_t version = feeds[i]->frameVersion(); @@ -1632,6 +1638,18 @@ int main(int argc, char* argv[]) recordFeedVersionStats(i, uploadNeeded); + if (config.logPerf) + { + perfStats.directV210SourceReadNs += + directReadTiming.sourceReadNs; + perfStats.directV210PayloadCopyNs += + directReadTiming.payloadCopyNs; + framePerf.directV210SourceReadNs += + directReadTiming.sourceReadNs; + framePerf.directV210PayloadCopyNs += + directReadTiming.payloadCopyNs; + } + if (!uploadNeeded) { continue; @@ -2117,6 +2135,14 @@ int main(int argc, char* argv[]) << (framePerf.feedReadTicks * invMs) << "ms stageCopy=" << (framePerf.stageCopyTicks * invMs) + << "ms v210Read=" + << (static_cast( + framePerf.directV210SourceReadNs) / + 1000000.0) + << "ms v210Copy=" + << (static_cast( + framePerf.directV210PayloadCopyNs) / + 1000000.0) << "ms stageCopies=" << framePerf.stageCopies << " v210Copies=" @@ -2168,6 +2194,14 @@ int main(int argc, char* argv[]) << (perfStats.uploadDecodeTicks * invMs / frames) << "ms stageCopy=" << (perfStats.stageCopyTicks * invMs / frames) + << "ms v210Read=" + << (static_cast( + perfStats.directV210SourceReadNs) / + 1000000.0 / frames) + << "ms v210Copy=" + << (static_cast( + perfStats.directV210PayloadCopyNs) / + 1000000.0 / frames) << "ms uploadRecord=" << (perfStats.uploadRecordTicks * invMs / frames) << "ms submitPresent="