#ifndef OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP #define OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP #include // std::queue #include #include #include namespace op { // Note: The goal of WQueueAssembler and WQueueSplitter (integrated in wDatumProducer) is to reduce the latency // of OpenPose. E.g., if 4 cameras in stereo mode, without this, OpenPose would have to process all 4 cameras // with the same GPU. In this way, this work is parallelized over GPUs (1 view for each). // Pros: Latency highly recuded, same speed // Cons: Requires these extra 2 classes and proper threads for them template class WQueueAssembler : public Worker> { public: explicit WQueueAssembler(); virtual ~WQueueAssembler(); void initializationOnThread(); void work(std::shared_ptr& tDatums); private: std::shared_ptr mNextTDatums; DELETE_COPY(WQueueAssembler); }; } // Implementation namespace op { template WQueueAssembler::WQueueAssembler() { } template WQueueAssembler::~WQueueAssembler() { } template void WQueueAssembler::initializationOnThread() { } template void WQueueAssembler::work(std::shared_ptr& tDatums) { try { // Profiling speed const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); // Input TDatums -> enqueue it if (checkNoNullNorEmpty(tDatums)) { // Sanity check if (tDatums->size() > 1) error("This function assumes that WQueueSplitter (inside WDatumProducer)" " was applied in the first place, i.e., that there is only 1 element" " per TDatums (size = " + std::to_string(tDatums->size()) + ").", __LINE__, __FUNCTION__, __FILE__); auto tDatumPtr = (*tDatums)[0]; // Single view --> Return if (tDatumPtr->subIdMax == 0) return; // Multiple view --> Merge views into different TDatums (1st frame) if (mNextTDatums == nullptr) mNextTDatums = std::make_shared(); // Multiple view --> Merge views into different TDatums mNextTDatums->emplace_back(tDatumPtr); // Last view - Return frame if (mNextTDatums->back()->subId == mNextTDatums->back()->subIdMax) { tDatums = mNextTDatums; mNextTDatums = nullptr; // Profiling speed Profiler::timerEnd(profilerKey); Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); // Debugging log opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); } // Non-last view - Return nothing else tDatums = nullptr; } // Sleep if no new tDatums to either pop or push else std::this_thread::sleep_for(std::chrono::milliseconds{1}); } catch (const std::exception& e) { this->stop(); tDatums = nullptr; error(e.what(), __LINE__, __FUNCTION__, __FILE__); } } extern template class WQueueAssembler; } #endif // OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP