122 lines
3.1 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|