整理代码
This commit is contained in:
commit
c7b4e178ec
364 changed files with 59691 additions and 0 deletions
284
video/core/AbstractAudioInput.cpp
Normal file
284
video/core/AbstractAudioInput.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* INCLUDE
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "AbstractAudioInput.h"
|
||||
#include "System.h"
|
||||
#include "Logger.h"
|
||||
#include "util/Math.h"
|
||||
#include <atomic>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace Video
|
||||
{
|
||||
namespace Core
|
||||
{
|
||||
/*
|
||||
*******************************************************************************
|
||||
* CLASS DEFINE
|
||||
*******************************************************************************
|
||||
*/
|
||||
AbstractAudioInput::AbstractAudioInput(const std::string& name)
|
||||
: AudioComponent(name)
|
||||
{
|
||||
const auto len = 1024 * 32;
|
||||
_pSilentData = new uint8_t[len];
|
||||
memset(_pSilentData, 0x00, len);
|
||||
|
||||
_silentDataCode = serialCodeManager().code();
|
||||
_pSilentFrame = new Frame;
|
||||
|
||||
for (int i = 0; i < Frame::DATA_LINES; i++)
|
||||
_pSilentFrame->data[i] = _pSilentData;
|
||||
}
|
||||
|
||||
AbstractAudioInput::~AbstractAudioInput()
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractAudioInput::run()
|
||||
{
|
||||
updateSilentFrame();
|
||||
|
||||
_task.run(
|
||||
[this](std::atomic<bool>& isCancelled) -> void
|
||||
{
|
||||
Util::Task probeTask;
|
||||
std::atomic<bool> attached(true);
|
||||
setSignalLost(false);
|
||||
|
||||
Frame::Ptr pFrame;
|
||||
SerialCodeWatcher watcher;
|
||||
uint64_t timeline = 0;
|
||||
while (!isCancelled)
|
||||
{
|
||||
if (attached)
|
||||
{
|
||||
pFrame = tryReadFrame(true);
|
||||
if (pFrame.isNull())
|
||||
{
|
||||
probeTask.run(
|
||||
[&](std::atomic<bool>& isCancelled) -> void
|
||||
{
|
||||
while (!isCancelled)
|
||||
{
|
||||
if (!tryReadFrame(false).isNull())
|
||||
{
|
||||
attached = true;
|
||||
setSignalLost(false);
|
||||
break;
|
||||
}
|
||||
|
||||
Poco::Thread::sleep(2000);
|
||||
}
|
||||
});
|
||||
|
||||
attached = false;
|
||||
setSignalLost(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
const int gain = _gain.load(std::memory_order_relaxed);
|
||||
if (gain != 0)
|
||||
applyGain(pFrame, gain);
|
||||
|
||||
const int64_t ptsOffset = _ptsOffsetUs.load(std::memory_order_relaxed);
|
||||
if (ptsOffset != 0)
|
||||
applyPTSOffset(pFrame, ptsOffset);
|
||||
|
||||
pFrame->code = serialCodeManager().code();
|
||||
if (watcher.isChanged(pFrame->code, true))
|
||||
{
|
||||
updateSilentFrame();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pFrame = readSilent(false);
|
||||
}
|
||||
|
||||
if (pFrame->timestamp < timeline)
|
||||
pFrame->timestamp = timeline;
|
||||
else
|
||||
timeline = pFrame->timestamp;
|
||||
|
||||
if (_isMute)
|
||||
pFrame = readSilent(true);
|
||||
|
||||
postToNextComponents(sharedFromThis(), pFrame, MediaType::AUDIO, isCancelled);
|
||||
}
|
||||
|
||||
probeTask.cancel();
|
||||
});
|
||||
}
|
||||
|
||||
void AbstractAudioInput::cancel()
|
||||
{
|
||||
_task.cancel();
|
||||
}
|
||||
|
||||
void AbstractAudioInput::onConfigChanged(ParameterNames& names)
|
||||
{
|
||||
updateSilentFrame();
|
||||
if (names.exists(_Gain))
|
||||
_gain.store(getGain(), std::memory_order_relaxed);
|
||||
|
||||
if (names.exists(_PTSOffset))
|
||||
_ptsOffsetUs.store(getPTSOffset(), std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
Frame::Ptr AbstractAudioInput::tryReadFrame(bool shouldLog)
|
||||
{
|
||||
try
|
||||
{
|
||||
return readFrame();
|
||||
}
|
||||
catch (Poco::Exception& e)
|
||||
{
|
||||
if (shouldLog)
|
||||
logger().error("%s: %s", name(), e.displayText());
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
if (shouldLog)
|
||||
logger().error("%s: %s", name(), std::string(e.what()));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Frame::Ptr AbstractAudioInput::readSilent(bool freezeChannel)
|
||||
{
|
||||
uint64_t now = System::timestamp();
|
||||
_pSilentFrame->timestamp = now;
|
||||
_pSilentFrame->code = _silentDataCode;
|
||||
if (!freezeChannel)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(_duration));
|
||||
}
|
||||
|
||||
return _pSilentFrame;
|
||||
}
|
||||
|
||||
void AbstractAudioInput::updateSilentFrame()
|
||||
{
|
||||
_pSilentFrame->length = Core::sampleFormatCalcLineSize(getSampleFormat(), getChannelLayout(), getFrameSize());
|
||||
_duration = (float)1000000 / getSampleRate() * getFrameSize() * 0.85;
|
||||
_silentDataCode = serialCodeManager().code();
|
||||
}
|
||||
|
||||
void AbstractAudioInput::applyGain(Frame::Ptr pFrame, int gain)
|
||||
{
|
||||
gain = ::Util::Math::clamp(gain, -50, 20);
|
||||
if (gain == 0)
|
||||
return;
|
||||
|
||||
const auto format = getSampleFormat();
|
||||
if (format == SampleFormat::NONE)
|
||||
return;
|
||||
|
||||
const uint32_t channels = (uint32_t)channelLayoutChannels(getChannelLayout());
|
||||
const uint32_t samplesPerChannel = getFrameSize();
|
||||
const double scale = std::pow(10.0, (double)gain / 20.0);
|
||||
|
||||
auto apply = [&](uint8_t* base, uint32_t n)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case SampleFormat::U8:
|
||||
case SampleFormat::U8P:
|
||||
{
|
||||
auto p = (uint8_t*)base;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
{
|
||||
const int64_t v = (int64_t)(p[i] * scale + 0.5);
|
||||
p[i] = (uint8_t)::Util::Math::clamp(v, (int64_t)0, (int64_t)255);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SampleFormat::S16:
|
||||
case SampleFormat::S16P:
|
||||
{
|
||||
auto p = (int16_t*)base;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
{
|
||||
const int64_t v = (int64_t)(p[i] * scale + 0.5);
|
||||
p[i] = (int16_t)::Util::Math::clamp(v, (int64_t)INT16_MIN, (int64_t)INT16_MAX);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SampleFormat::S32:
|
||||
case SampleFormat::S32P:
|
||||
{
|
||||
auto p = (int32_t*)base;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
{
|
||||
const int64_t v = (int64_t)(p[i] * scale + 0.5);
|
||||
p[i] = (int32_t)::Util::Math::clamp(v, (int64_t)INT32_MIN, (int64_t)INT32_MAX);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SampleFormat::S64:
|
||||
case SampleFormat::S64P:
|
||||
{
|
||||
auto p = (int64_t*)base;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
p[i] = (int64_t)(p[i] * scale);
|
||||
break;
|
||||
}
|
||||
case SampleFormat::FLT:
|
||||
case SampleFormat::FLTP:
|
||||
{
|
||||
auto p = (float*)base;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
p[i] = (float)(p[i] * scale);
|
||||
break;
|
||||
}
|
||||
case SampleFormat::DBL:
|
||||
case SampleFormat::DBLP:
|
||||
{
|
||||
auto p = (double*)base;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
p[i] *= scale;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (sampleFormatIsPlanar(format))
|
||||
{
|
||||
for (uint32_t ch = 0; ch < channels; ch++)
|
||||
{
|
||||
if (!pFrame->data[ch])
|
||||
continue;
|
||||
apply(pFrame->data[ch].get(), samplesPerChannel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pFrame->data[0])
|
||||
return;
|
||||
apply(pFrame->data[0].get(), samplesPerChannel * channels);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractAudioInput::applyPTSOffset(Frame::Ptr pFrame, int64_t ptsOffset)
|
||||
{
|
||||
if (ptsOffset != 0)
|
||||
{
|
||||
const int64_t ts = (int64_t)pFrame->timestamp + ptsOffset;
|
||||
pFrame->timestamp = (ts > 0) ? (uint64_t)ts : 0ULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractAudioInput::reset()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue