p26001-store-acs-soc-fw-app/video/libopus/AudioDecodeHandler.cpp
2026-09-28 21:33:04 +08:00

92 lines
2.8 KiB
C++

/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "AudioDecodeHandler.h"
#include "Logger.h"
#include <cstring>
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;
}
}
}
}