/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "VideoDecoder.h" #include "Logger.h" #include "Demuxer.h" namespace Video { namespace Core { /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ VideoDecodeHandler::VideoDecodeHandler(const std::string& name, CodecID codecID, VideoComponent::Ptr pPrevious) : _name(name), _pPrevious(pPrevious) { } VideoDecodeHandler::~VideoDecodeHandler() { } /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ VideoDecoder::VideoDecoder(const std::string& name): VideoComponent(name) { } VideoDecoder::~VideoDecoder() { } void VideoDecoder::start() { _task.run( [this](std::atomic& isCancelled) -> void { VideoDecodeHandler::Ptr pHandler; while (!isCancelled) { try { Frame::Ptr pFrame = nullptr; do { if (pHandler.isNull()) { pFrame = pHandler->read(); if (!pFrame.isNull()) break; } Packet::Ptr pPacket = readPacket(1000); if (serialCodeWatcher().isChanged(pPacket->serialCode(), true)) { auto pPrevious = previousComponents().first(); auto pDemuxer = pPrevious.cast(); if (pDemuxer) { auto pEncoder = pDemuxer->videoEncoder(); pEncoder->config().copyTo(config()); serialCodeManager().increment(); pHandler = VideoDecodeHandler::create(pEncoder->getCodecID(), pEncoder); } else throw Poco::NotImplementedException( Poco::format("Unsupported previous component: %s", pPrevious->name())); } pHandler->write(pPacket); pFrame = pHandler->read(); } while (false); if (!pFrame) continue; postToNextComponents(sharedFromThis(), pFrame, MediaType::VIDEO); } catch (Poco::Exception& e) { logger().error("%s: %s", name(), e.displayText()); Poco::Thread::sleep(1000); } catch (std::exception& e) { logger().error("%s: %s", name(), std::string(e.what())); Poco::Thread::sleep(1000); } } }); } void VideoDecoder::stop() { _task.cancel(); } Packet::Ptr VideoDecoder::readPacket(uint32_t timeout) { if (packetQueues().empty()) throw Poco::NotFoundException("Packet queues is empty."); return packetQueues().first()->dequeue(timeout); } void VideoDecoder::onLink(Core::Component::Ptr pPrevious) { packetQueues().add(pPrevious, name(), MediaType::VIDEO); } void VideoDecoder::onUnlink(Core::Component::Ptr pPrevious) { packetQueues().remove(pPrevious); } } }