125 lines
3.8 KiB
C++
125 lines
3.8 KiB
C++
/*
|
|
*******************************************************************************
|
|
* 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<bool>& 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<Demuxer>();
|
|
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);
|
|
}
|
|
}
|
|
}
|