整理代码
This commit is contained in:
commit
c7b4e178ec
364 changed files with 59691 additions and 0 deletions
244
video/core/AudioMixer.cpp
Normal file
244
video/core/AudioMixer.cpp
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* INCLUDE
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "AudioMixer.h"
|
||||
#include "System.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace Video
|
||||
{
|
||||
namespace Core
|
||||
{
|
||||
/*
|
||||
*******************************************************************************
|
||||
* CLASS DEFINE
|
||||
*******************************************************************************
|
||||
*/
|
||||
AudioMixer::Channel::Channel(AudioMixer::Ptr pMixer, uint32_t id)
|
||||
: AudioAdaptablePipe(Poco::format(pMixer->name() + "/CH#%u", id)), _pMixer(pMixer), _id(id)
|
||||
{
|
||||
setAttach(false);
|
||||
setInput(nullptr);
|
||||
}
|
||||
|
||||
AudioMixer::Channel::~Channel()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioMixer::Channel::start()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioMixer::Channel::stop()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioMixer::Channel::onConfigChanged(ParameterNames& names)
|
||||
{
|
||||
if (names.exists(_Input))
|
||||
unlink(true, false);
|
||||
|
||||
if (names.exists(_Attach))
|
||||
{
|
||||
auto pInput = getInput();
|
||||
if (pInput)
|
||||
{
|
||||
if (getAttach())
|
||||
{
|
||||
getInput()->link(sharedFromThis());
|
||||
link(mixer());
|
||||
}
|
||||
else
|
||||
getInput()->unlink(sharedFromThis());
|
||||
}
|
||||
}
|
||||
|
||||
serialCodeWatcher().reset();
|
||||
}
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* CLASS DEFINE
|
||||
*******************************************************************************
|
||||
*/
|
||||
AudioMixer::AudioMixer(const std::string& name): AbstractAudioInput(name)
|
||||
{
|
||||
_mixFrame = new Frame();
|
||||
for (int i = 0; i < Frame::DATA_LINES; i++)
|
||||
_mixFrame->data[i] = new uint8_t[1024 * 32];
|
||||
}
|
||||
|
||||
AudioMixer::~AudioMixer()
|
||||
{
|
||||
}
|
||||
|
||||
AudioMixer::Channel::Ptr AudioMixer::getChannel(uint32_t id)
|
||||
{
|
||||
if (_channels.find(id) == _channels.end())
|
||||
{
|
||||
Channel::Ptr pChannel = new Channel(Ptr(this, true), id);
|
||||
syncConfigToChannel(pChannel);
|
||||
_channels[id] = pChannel;
|
||||
}
|
||||
|
||||
return _channels[id];
|
||||
}
|
||||
|
||||
void AudioMixer::syncConfigToChannel(AudioMixer::Channel::Ptr pChannel)
|
||||
{
|
||||
pChannel->setSampleRate(getSampleRate());
|
||||
pChannel->setChannelLayout(getChannelLayout());
|
||||
pChannel->setSampleFormat(getSampleFormat());
|
||||
pChannel->setFrameSize(getFrameSize());
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static inline void mix(const S MIN, const S MAX, uint8_t* i0, uint8_t* i1, uint8_t* o, uint32_t bytes)
|
||||
{
|
||||
T* p0 = reinterpret_cast<T*>(i0);
|
||||
T* p1 = reinterpret_cast<T*>(i1);
|
||||
T* output = reinterpret_cast<T*>(o);
|
||||
|
||||
const size_t count = static_cast<size_t>(bytes / sizeof(T));
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
S a = static_cast<S>(p0[i]);
|
||||
S b = static_cast<S>(p1[i]);
|
||||
|
||||
const int64_t product = static_cast<int64_t>(a) * b;
|
||||
S c = a + b - static_cast<S>(product >> 0x10);
|
||||
|
||||
c = (c > MAX) ? MAX : ((c < MIN) ? MIN : c);
|
||||
output[i] = static_cast<T>(c);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMixer::start()
|
||||
{
|
||||
refreshOutputParams();
|
||||
run();
|
||||
}
|
||||
|
||||
void AudioMixer::stop()
|
||||
{
|
||||
cancel();
|
||||
}
|
||||
|
||||
void AudioMixer::onConfigChanged(ParameterNames& names)
|
||||
{
|
||||
for (auto& m : _channels)
|
||||
{
|
||||
auto pChannel = m.second;
|
||||
syncConfigToChannel(pChannel);
|
||||
pChannel->commit();
|
||||
}
|
||||
|
||||
AbstractAudioInput::onConfigChanged(names);
|
||||
}
|
||||
|
||||
Frame::Ptr AudioMixer::readFrame()
|
||||
{
|
||||
Frame::Ptr pFrame = nullptr;
|
||||
uint64_t pts = 0;
|
||||
uint32_t index = 0;
|
||||
for (auto& m : _channels)
|
||||
{
|
||||
auto pChannel = m.second;
|
||||
Frame::Ptr pReadFrame;
|
||||
|
||||
try
|
||||
{
|
||||
pReadFrame = pChannel->readFrame(32);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
pReadFrame = nullptr;
|
||||
}
|
||||
|
||||
if (!pReadFrame.isNull())
|
||||
{
|
||||
if (pts == 0 || pts > pReadFrame->timestamp)
|
||||
pts = pReadFrame->timestamp;
|
||||
|
||||
if (pFrame == nullptr)
|
||||
pFrame = pReadFrame;
|
||||
else
|
||||
{
|
||||
#define AUDIO_DATA(i) index > 0 ? _mixFrame->data[i].get() : pFrame->data[i].get()
|
||||
switch (getSampleFormat())
|
||||
{
|
||||
case SampleFormat::U8:
|
||||
case SampleFormat::U8P:
|
||||
for (uint32_t i = 0; i < getChannels(); i++)
|
||||
mix<uint8_t, uint16_t>(0, UINT8_MAX, AUDIO_DATA(i), pReadFrame->data[i].get(),
|
||||
_mixFrame->data[i].get(), pFrame->length);
|
||||
break;
|
||||
|
||||
case SampleFormat::S16:
|
||||
case SampleFormat::S16P:
|
||||
for (uint32_t i = 0; i < getChannels(); i++)
|
||||
mix<int16_t, int32_t>(INT16_MIN, INT16_MAX, AUDIO_DATA(i), pReadFrame->data[i].get(),
|
||||
_mixFrame->data[i].get(), pFrame->length);
|
||||
break;
|
||||
|
||||
case SampleFormat::S32:
|
||||
case SampleFormat::S32P:
|
||||
for (uint32_t i = 0; i < getChannels(); i++)
|
||||
mix<int32_t, int64_t>(INT32_MIN, INT32_MAX, AUDIO_DATA(i), pReadFrame->data[i].get(),
|
||||
_mixFrame->data[i].get(), pFrame->length);
|
||||
break;
|
||||
|
||||
case SampleFormat::S64:
|
||||
case SampleFormat::S64P:
|
||||
for (uint32_t i = 0; i < getChannels(); i++)
|
||||
mix<int64_t, int64_t>(INT64_MIN, INT64_MAX, AUDIO_DATA(i), pReadFrame->data[i].get(),
|
||||
_mixFrame->data[i].get(), pFrame->length);
|
||||
break;
|
||||
|
||||
case SampleFormat::FLT:
|
||||
case SampleFormat::FLTP:
|
||||
for (uint32_t i = 0; i < getChannels(); i++)
|
||||
mix<float, float>(-1.0f, 1.0f, AUDIO_DATA(i), pReadFrame->data[i].get(),
|
||||
_mixFrame->data[i].get(), pFrame->length);
|
||||
break;
|
||||
|
||||
case SampleFormat::DBL:
|
||||
case SampleFormat::DBLP:
|
||||
for (uint32_t i = 0; i < getChannels(); i++)
|
||||
mix<double, double>(-1.0, 1.0, AUDIO_DATA(i), pReadFrame->data[i].get(),
|
||||
_mixFrame->data[i].get(), pFrame->length);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pFrame.isNull())
|
||||
return nullptr;
|
||||
|
||||
_traffic++;
|
||||
if (index > 0)
|
||||
{
|
||||
_mixFrame->timestamp = pts;
|
||||
_mixFrame->length = pFrame->length;
|
||||
_mixFrame->code = pFrame->code;
|
||||
return _mixFrame;
|
||||
}
|
||||
else
|
||||
return pFrame;
|
||||
}
|
||||
|
||||
void AudioMixer::refreshOutputParams()
|
||||
{
|
||||
setFrameDuration((float)1000000 / getSampleRate() * getFrameSize());
|
||||
setChannels(channelLayoutChannels(getChannelLayout()));
|
||||
setLineSize(sampleFormatCalcLineSize(getSampleFormat(), getChannelLayout(), getFrameSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue