/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "Input.h" #include "Capture.h" #include "InputFormat.h" #include "../core/System.h" #include "Logger.h" namespace Video { namespace V4L2 { /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ Input::Input(const std::string& name): VideoComponent(name), _task(name) { } Input::~Input() { } void Input::start() { _task.run( [this](std::atomic& isCancelled) -> void { const std::string path = getPath(); setCodecID(Core::CodecID::MJPEG); setSignalLost(true); while (!isCancelled) { Poco::SharedPtr pCapture; InputFormat::Collection formats; try { InputFormat::enumerate(path, formats); if (formats.empty()) { Poco::Thread::sleep(2000); continue; } for (auto& c : formats) { if (V4L2_PIX_FMT_MJPEG == c.pixelFormat && !c.resolutions.empty()) { auto p = c.resolutions.begin(); uint64_t maxProduct = 0; for (auto it = c.resolutions.begin(); it != c.resolutions.end(); ++it) { uint32_t fps = it->width * it->height > 3686400 ? 30 : 60; if (it->width <= 2560 && it->height <= 1440 && it->fps <= fps) { uint64_t product = static_cast(it->width) * it->height * it->fps; if (product > maxProduct) { logger().debug("%s: ", name()); maxProduct = product; p = it; } } } DeviceParameters param(path.c_str(), c.pixelFormat, p->width, p->height, p->fps); pCapture = Capture::create(param); if (pCapture.isNull()) continue; logger().information("%s: Camera [%s] found, %s, %ux%u@%u", name(), pCapture->getName(), c.description, p->width, p->height, p->fps); setWidth(p->width); setHeight(p->height); setFrameRate(p->fps); setSignalLost(false); serialCodeManager().increment(); break; } } } catch (...) { Poco::Thread::sleep(2000); continue; } uint8_t* pBuffer = nullptr; ; while (!isCancelled) { try { struct timeval tv = {1, 0}; if (!pCapture->isReadable(&tv)) break; int len = pCapture->getBufferSize(); pBuffer = new uint8_t[len]; int rsize = pCapture->read((char*)pBuffer, len); if (rsize < 0) { logger().error("%s: Failed to read frame!", pCapture->getName()); delete pBuffer; pBuffer = nullptr; break; } int64_t ts = Core::System::timestamp(); Core::Packet::Ptr pPacket = new Core::Packet( serialCodeManager().code(), Core::Packet::FLAG_IS_VIDEO, pBuffer, rsize, ts, ts); pBuffer = nullptr; postToNextComponents(sharedFromThis(), pPacket, Core::MediaType::VIDEO); } catch (...) { if (pBuffer) { delete pBuffer; pBuffer = nullptr; } } } setSignalLost(true); logger().warning("%s: Camera [%s] lost!", name(), pCapture->getName()); } }); } void Input::stop() { _task.cancel(); } void Input::onConfigChanged(ParameterNames& names) { if (!started()) return; if (names.exists(_Path)) { stop(); start(); } } } }