/* ******************************************************************************* * 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; } } }