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

122 lines
3.1 KiB
C++

/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "AudioFrameAdapter.h"
#include "System.h"
namespace Video
{
namespace Core
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
AudioFrameAdapter::AudioFrameAdapter(ChannelLayout layout, SampleFormat format, int frameSize, int sampleRate)
{
int channels = channelLayoutChannels(layout);
_linesize = sampleFormatCalcLineSize(format, layout, frameSize);
_lines = sampleFormatIsPlanar(format) ? channels : 1;
_sampleDuration = 1000000000ul / sampleRate;
_sampleSize = sampleFormatBytesPerSample(format);
if (!sampleFormatIsPlanar(format))
_sampleSize *= channels;
_readIndex = 0;
_sampleRate = sampleRate;
_frameSize = frameSize;
_encodeClock = 0;
}
void AudioFrameAdapter::put(Frame::Ptr pFrame)
{
if (!_pInFrame.isNull())
throw Poco::InvalidAccessException();
_pInFrame = pFrame;
}
Frame::Ptr AudioFrameAdapter::get()
{
int inRemain = remainOfReadFrame();
if (inRemain == 0)
return nullptr;
if (_pOutFrame.isNull())
{
_pOutFrame = new Frame();
for (int i = 0; i < _lines; i++)
_pOutFrame->data[i] = new uint8_t[_linesize];
_pOutFrame->length = _linesize;
_writeIndex = 0;
}
if (0 == _pOutFrame->timestamp)
{
_pOutFrame->timestamp = getInFrameTimestamp();
const uint64_t wall = System::timestamp();
if (0 == _encodeClock)
_encodeClock = wall;
else
{
const int64_t diff = (int64_t)(wall - _encodeClock);
if (diff > 300000 || diff < -300000)
_encodeClock = wall;
else
_encodeClock += (uint64_t)(diff / 8);
}
_pOutFrame->timestamp = _encodeClock;
_encodeClock += 1000000ull * _frameSize / _sampleRate;
}
int bytes = std::min(inRemain, spaceOfOutFrame());
for (int i = 0; i < _lines; i++)
memcpy(_pOutFrame->data[i] + _writeIndex, _pInFrame->data[i] + _readIndex, bytes);
_writeIndex += bytes;
_readIndex += bytes;
if (remainOfReadFrame() == 0)
{
_pInFrame.reset();
_readIndex = 0;
}
Frame::Ptr pFrame = nullptr;
if (spaceOfOutFrame() == 0)
{
pFrame = _pOutFrame;
_pOutFrame.reset();
}
return pFrame;
}
int AudioFrameAdapter::remainOfReadFrame()
{
if (_pInFrame.isNull())
return 0;
return _pInFrame->length - _readIndex;
}
int AudioFrameAdapter::spaceOfOutFrame()
{
if (_pOutFrame.isNull())
return 0;
return _pOutFrame->length - _writeIndex;
}
uint64_t AudioFrameAdapter::getInFrameTimestamp()
{
return _pInFrame->timestamp + _readIndex / _sampleSize * _sampleDuration / 1000;
}
}
}