/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "AudioEncoder.h" #include "Logger.h" namespace Video { namespace LibOPUS { /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ AudioEncoder::AudioEncoder(Core::CodecID codecID) : Core::AudioEncoder(Poco::format("LibOPUS::AudioEncoder(%s)", Core::codecIDToString(codecID)), codecID), _pEncoder(nullptr) { } AudioEncoder::~AudioEncoder() { } void AudioEncoder::initialize() { setSampleRate(48000); setFrameSize(960); setSampleFormat(Core::SampleFormat::S16); int channels = Core::channelLayoutChannels(getChannelLayout()); int err; _pEncoder = opus_encoder_create(getSampleRate(), channels, OPUS_APPLICATION_AUDIO, &err); if (err != OPUS_OK) throw Poco::InvalidAccessException( Poco::format("%s: Create encoder FAIL: %d(%s)", name(), err, std::string(opus_strerror(err))), err); opus_encoder_ctl(_pEncoder, OPUS_SET_BITRATE(getBitrate())); opus_encoder_ctl(_pEncoder, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); opus_encoder_ctl(_pEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); opus_encoder_ctl(_pEncoder, OPUS_SET_VBR(1)); opus_encoder_ctl(_pEncoder, OPUS_SET_LSB_DEPTH(Core::sampleFormatBitWidth(getSampleFormat()))); opus_encoder_ctl(_pEncoder, OPUS_SET_DTX(0)); opus_encoder_ctl(_pEncoder, OPUS_SET_COMPLEXITY(1)); } void AudioEncoder::deinitialize() { if (_pEncoder) { opus_encoder_destroy(_pEncoder); _pEncoder = nullptr; } } #define PACKET_MAX_LEN 8192 Core::Packet::Ptr AudioEncoder::encode() { if (!_pEncoder) return nullptr; auto pIn = readFrame(); if (pIn.isNull()) return nullptr; uint8_t* pBuffer = new uint8_t[PACKET_MAX_LEN]; int32_t len = opus_encode(_pEncoder, (int16_t*)pIn->data[0].get(), getFrameSize(), pBuffer, PACKET_MAX_LEN); if (len < 0 || len > PACKET_MAX_LEN) { delete[] pBuffer; logger().error("%s: Encode FAIL: %d(%s)", name(), len, std::string(opus_strerror(len))); return nullptr; } return new Core::Packet(serialCodeManager().code(), 0, pBuffer, len, pIn->timestamp, pIn->timestamp); } void AudioEncoder::onConfigChanged(ParameterNames& names) { Core::AudioEncoder::onConfigChanged(names); } } }