audio-drain/audio/drain/EndPointWrite.cpp

161 lines
6.1 KiB
C++
Raw Normal View History

/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
2016-10-02 21:41:55 +02:00
#include <audio/drain/EndPointWrite.hpp>
#include <audio/drain/debug.hpp>
2015-01-27 21:26:03 +01:00
2015-04-10 23:00:13 +02:00
audio::drain::EndPointWrite::EndPointWrite() :
m_function(nullptr),
m_bufferSizeMicroseconds(1000000),
m_bufferSizeChunk(32),
m_bufferUnderFlowSize(0) {
}
2015-04-10 23:00:13 +02:00
void audio::drain::EndPointWrite::init() {
audio::drain::EndPoint::init();
2015-02-01 22:22:42 +01:00
m_type = "EndPoint";
if ( audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size() != 0
&& m_output.getFrequency() != 0) {
m_buffer.setCapacity(m_bufferSizeMicroseconds,
audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size(),
m_output.getFrequency());
}
2015-01-29 21:46:01 +01:00
}
2016-07-19 21:43:58 +02:00
ememory::SharedPtr<audio::drain::EndPointWrite> audio::drain::EndPointWrite::create() {
ememory::SharedPtr<audio::drain::EndPointWrite> tmp(new audio::drain::EndPointWrite());
2015-01-29 21:46:01 +01:00
tmp->init();
return tmp;
2015-01-28 22:07:11 +01:00
}
2015-04-10 23:00:13 +02:00
void audio::drain::EndPointWrite::configurationChange() {
audio::drain::EndPoint::configurationChange();
// update the buffer size ...
if ( audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size() != 0
&& m_output.getFrequency() != 0) {
if (std::chrono::microseconds(0) != m_bufferSizeMicroseconds) {
m_buffer.setCapacity(m_bufferSizeMicroseconds,
audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size(),
m_output.getFrequency());
} else {
m_buffer.setCapacity(m_bufferSizeChunk,
audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size(),
m_output.getFrequency());
}
}
m_needProcess = true;
}
2015-04-13 21:49:48 +02:00
bool audio::drain::EndPointWrite::process(audio::Time& _time,
2015-04-10 23:00:13 +02:00
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk){
audio::drain::AutoLogInOut tmpLog("EndPointWrite");
//DRAIN_INFO(" nb Sample in buffer : " << m_buffer.size());
if (m_function != nullptr) {
// TODO : Rework this ...
if (m_buffer.getSize() <= 20000) {
m_function(_time, _inputNbChunk, m_output.getFormat(), m_output.getFrequency(), m_output.getMap());
}
}
// resize output buffer:
//DRAIN_INFO(" resize : " << (int32_t)m_formatSize << "*" << (int32_t)_inputNbChunk << "*" << (int32_t)m_outputMap.size());
m_outputData.resize(m_formatSize*_inputNbChunk*m_output.getMap().size());
// set output pointer:
_outputNbChunk = m_outputData.size()/(m_formatSize*m_output.getMap().size());
_output = &m_outputData[0];
2017-09-07 23:38:26 +02:00
std::unique_lock<ethread::Mutex> lock(m_mutex);
// check if data in the tmpBuffer
if (m_buffer.getSize() == 0) {
if (m_bufferUnderFlowSize == 0) {
DRAIN_WARNING("No data in the user buffer (write null data ... " << _outputNbChunk << " chunks)");
m_bufferUnderFlowSize = 1;
} else {
if (m_bufferUnderFlowSize == 1) {
m_bufferUnderFlowSize = 0;
}
m_bufferUnderFlowSize += _outputNbChunk;
}
// clear the buffer to force the flush on the next elements ...
m_outputData.clear();
_outputNbChunk = 0;
generateStatus("EPW_UNDERFLOW");
// just send no data ...
return true;
} else if (m_bufferUnderFlowSize > 1) {
DRAIN_WARNING("No data in the user buffer (write null data ... " << m_bufferUnderFlowSize << " chunks [In the past])");
}
m_bufferUnderFlowSize = 0;
DRAIN_VERBOSE("Write " << _outputNbChunk << " chunks");
// check if we have enought data:
2017-08-28 00:08:17 +02:00
int32_t nbChunkToCopy = etk::min(_inputNbChunk, m_buffer.getSize());
if (nbChunkToCopy != _inputNbChunk) {
generateStatus("EPW_UNDERFLOW");
}
DRAIN_VERBOSE(" " << nbChunkToCopy << " chunks ==> " << nbChunkToCopy*m_output.getMap().size()*m_formatSize << " Byte sizeBuffer=" << m_buffer.getSize());
_outputNbChunk = nbChunkToCopy;
// copy data to the output:
int32_t nbUnderflow = m_buffer.read(_output, nbChunkToCopy);
if (nbUnderflow != 0) {
DRAIN_WARNING("Undeflow in FIFO ...");
_outputNbChunk -= nbUnderflow;
}
return true;
}
2015-04-10 23:00:13 +02:00
void audio::drain::EndPointWrite::write(const void* _value, size_t _nbChunk) {
2017-09-07 23:38:26 +02:00
std::unique_lock<ethread::Mutex> lock(m_mutex);
DRAIN_VERBOSE("[ASYNC] Write data : " << _nbChunk << " chunks" << " ==> " << m_output);
int32_t nbOverflow = m_buffer.write(_value, _nbChunk);
if (nbOverflow > 0) {
DRAIN_ERROR("Overflow in output buffer : " << nbOverflow << " / " << _nbChunk);
}
}
2015-04-10 23:00:13 +02:00
void audio::drain::EndPointWrite::setBufferSize(size_t _nbChunk) {
m_bufferSizeMicroseconds = std::chrono::microseconds(0);
m_bufferSizeChunk = _nbChunk;
if ( audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size() != 0
&& m_output.getFrequency() != 0) {
m_buffer.setCapacity(_nbChunk,
audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size(),
float(m_output.getFrequency()));
}
}
void audio::drain::EndPointWrite::setBufferSize(const std::chrono::microseconds& _time) {
m_bufferSizeMicroseconds = _time;
m_bufferSizeChunk = 0;
m_buffer.setCapacity(_time,
audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size(),
float(m_output.getFrequency()));
}
2015-04-10 23:00:13 +02:00
size_t audio::drain::EndPointWrite::getBufferSize() {
if (m_bufferSizeChunk != 0) {
return m_bufferSizeChunk;
}
return (int64_t(m_output.getFrequency())*m_bufferSizeMicroseconds.count())/1000000LL;
}
std::chrono::microseconds audio::drain::EndPointWrite::getBufferSizeMicrosecond() {
if (m_bufferSizeMicroseconds != std::chrono::microseconds(0) ) {
return m_bufferSizeMicroseconds;
}
return std::chrono::microseconds(m_bufferSizeChunk*1000000LL/int64_t(m_output.getFrequency()));
}
2015-04-10 23:00:13 +02:00
size_t audio::drain::EndPointWrite::getBufferFillSize() {
return m_buffer.getSize()/(audio::getFormatBytes(m_output.getFormat())*m_output.getMap().size());
}
std::chrono::microseconds audio::drain::EndPointWrite::getBufferFillSizeMicrosecond() {
return std::chrono::microseconds(getBufferFillSize()*1000000LL/int64_t(m_output.getFrequency()));
}