/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "HDMIAudioOutput.h" #include "Util.h" #include "util/Math.h" /* ******************************************************************************* * CONSTANTS ******************************************************************************* */ #define AO_DEV_ID 1 namespace Video { namespace MPP5 { /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ HDMIAudioOutput::HDMIAudioOutput(const std::string& arg) : Core::AudioOutput("MPP5::AudioOutput(" + arg + ")"), MPPChannel((uint32_t)HI_ID_AO, AO_DEV_ID, 0) { setSampleRate(48000); setSampleFormat(Core::SampleFormat::S16P); setChannelLayout(Core::ChannelLayout::STEREO); setFrameSize(1024); } HDMIAudioOutput::~HDMIAudioOutput() { } void HDMIAudioOutput::initialize() { _bitWidth = Util::getBitWidth(getSampleFormat()); _sndMode = Util::getSndMode(getChannelLayout()); hi_aio_attr attr; attr.sample_rate = (hi_audio_sample_rate)getSampleRate(); attr.bit_width = _bitWidth; attr.work_mode = HI_AIO_MODE_I2S_MASTER; attr.i2s_type = HI_AIO_I2STYPE_INNERHDMI; attr.snd_mode = _sndMode; attr.expand_flag = 0; attr.frame_num = 8; attr.point_num_per_frame = getFrameSize(); attr.chn_cnt = Core::channelLayoutChannels(getChannelLayout()); attr.clk_share = 0; int rc = hi_mpi_ao_set_pub_attr(deviceID(), &attr); if (rc != HI_SUCCESS) throw Poco::InvalidAccessException( Poco::format("%s: Configure pub-attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc); rc = hi_mpi_ao_enable(deviceID()); if (rc != HI_SUCCESS) throw Poco::InvalidAccessException(Poco::format("%s: Enable FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc); rc = hi_mpi_ao_set_volume(deviceID(), getVolumeValue()); if (rc != HI_SUCCESS) throw Poco::InvalidAccessException(Poco::format("%s: Configure volume FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc); rc = hi_mpi_ao_enable_chn(deviceID(), channelID()); if (rc != HI_SUCCESS) throw Poco::InvalidAccessException( Poco::format("%s: Enable CHM#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc); } void HDMIAudioOutput::deinitialize() { hi_mpi_ao_disable_chn(deviceID(), channelID()); hi_mpi_ao_disable(deviceID()); } void HDMIAudioOutput::onConfigChanged(ParameterNames& names) { if (!started()) return; int rc = hi_mpi_ao_set_volume(deviceID(), getVolumeValue()); if (rc != HI_SUCCESS) throw Poco::InvalidAccessException(Poco::format("%s: Configure volume FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc); } void HDMIAudioOutput::writeFrame(Core::Frame::Ptr pFrame) { hi_audio_frame frame = {}; frame.bit_width = HI_AUDIO_BIT_WIDTH_16; frame.len = pFrame->length; frame.time_stamp = pFrame->timestamp; frame.snd_mode = HI_AUDIO_SOUND_MODE_MONO; frame.virt_addr[0] = pFrame->data[0].get(); if (HI_AUDIO_SOUND_MODE_STEREO == _sndMode) frame.virt_addr[1] = pFrame->data[1].get(); int rc = hi_mpi_ao_send_frame(deviceID(), channelID(), &frame, 100); if (rc != HI_SUCCESS) throw Poco::InvalidAccessException(Poco::format("%s: Send frame FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc); } int HDMIAudioOutput::getVolumeValue() { auto lineMapping = [](int inputMin, int inputMax, int outMin, int outMax, int input) -> int { return (input - inputMin) * (outMax - outMin) / (inputMax - inputMin) + outMin; }; int gain = ::Util::Math::clamp(getGain(), -100, 100); if (gain < 0) return lineMapping(-100, -1, -121, -1, gain); return lineMapping(0, 100, 0, 6, gain); } } }