/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "AudioDecodeHandler.h" #include "Logger.h" #include namespace Video { namespace LibOPUS { /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ AudioDecodeHandler::AudioDecodeHandler(Core::CodecID codecID, Core::AudioComponent::Ptr pPrevious) : Core::AudioDecodeHandler(Poco::format("LibOPUS::AudioDecodeHandler(%s)", Core::codecIDToString(codecID)), codecID, pPrevious), _pDecoder(nullptr), _queue("LibOPUS::AudioDecodeHandler", Core::MediaType::AUDIO, 300) { int err; _pDecoder = opus_decoder_create(pPrevious->getSampleRate(), Core::channelLayoutChannels(pPrevious->getChannelLayout()), &err); if (err != OPUS_OK) throw Poco::InvalidAccessException( Poco::format("%s: Create decoder FAIL: %d(%s)", name(), err, std::string(opus_strerror(err))), err); } AudioDecodeHandler::~AudioDecodeHandler() { if (_pDecoder) { opus_decoder_destroy(_pDecoder); _pDecoder = nullptr; } } void AudioDecodeHandler::write(Core::Packet::Ptr pPacket) { const int channels = Core::channelLayoutChannels(previous()->getChannelLayout()); int n = opus_decode(_pDecoder, pPacket->data(), (opus_int32)pPacket->length(), _pcm, 5760, 0); if (n <= 0) { logger().error("%s: Decode FAIL: %d(%s)", name(), n, std::string(opus_strerror(n))); conceal(pPacket); return; } const int bytes = n * channels * (int)sizeof(int16_t); Core::Frame::Ptr pFrame = new Core::Frame(); pFrame->data[0] = new uint8_t[bytes]; memcpy(pFrame->data[0].get(), _pcm, bytes); pFrame->length = bytes; pFrame->timestamp = pPacket->pts(); _queue.enqueue(pFrame, true); } void AudioDecodeHandler::conceal(Core::Packet::Ptr pPacket) { const int channels = Core::channelLayoutChannels(previous()->getChannelLayout()); int n = opus_decode(_pDecoder, NULL, 0, _pcm, 5760, 0); if (n <= 0) return; const int bytes = n * channels * (int)sizeof(int16_t); Core::Frame::Ptr pFrame = new Core::Frame(); pFrame->data[0] = new uint8_t[bytes]; memcpy(pFrame->data[0].get(), _pcm, bytes); pFrame->length = bytes; pFrame->timestamp = pPacket->pts(); _queue.enqueue(pFrame, true); } Core::Frame::Ptr AudioDecodeHandler::read() { try { return _queue.dequeue(0); } catch (Poco::TimeoutException&) { return nullptr; } } } }