size_t RingBufferPool::getData(AudioBuffer& buffer, const std::string& call_id) { std::lock_guard<std::recursive_mutex> lk(stateLock_); const auto bindings = getReadBindings(call_id); if (not bindings) return 0; // No mixing if (bindings->size() == 1) return (*bindings->cbegin())->get(buffer, call_id); buffer.reset(); buffer.setFormat(internalAudioFormat_); size_t size = 0; AudioBuffer mixBuffer(buffer); for (const auto& rbuf : *bindings) { // XXX: is it normal to only return the last positive size? size = rbuf->get(mixBuffer, call_id); if (size > 0) buffer.mix(mixBuffer); } return size; }
void AudioSender::process() { auto& mainBuffer = Manager::instance().getRingBufferPool(); auto mainBuffFormat = mainBuffer.getInternalAudioFormat(); // compute nb of byte to get corresponding to 1 audio frame const std::size_t samplesToGet = std::chrono::duration_cast<std::chrono::seconds>(mainBuffFormat.sample_rate * secondsPerPacket_).count(); if (mainBuffer.availableForGet(id_) < samplesToGet) { const auto wait_time = std::chrono::duration_cast<std::chrono::milliseconds>(secondsPerPacket_); if (not mainBuffer.waitForDataAvailable(id_, samplesToGet, wait_time)) return; } // get data micData_.setFormat(mainBuffFormat); micData_.resize(samplesToGet); const auto samples = mainBuffer.getData(micData_, id_); if (samples != samplesToGet) return; // down/upmix as needed auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec); micData_.setChannelNum(accountAudioCodec->audioformat.nb_channels, true); if (mainBuffFormat.sample_rate != accountAudioCodec->audioformat.sample_rate) { if (not resampler_) { RING_DBG("Creating audio resampler"); resampler_.reset(new Resampler(accountAudioCodec->audioformat)); } resampledData_.setFormat(accountAudioCodec->audioformat); resampledData_.resize(samplesToGet); resampler_->resample(micData_, resampledData_); Smartools::getInstance().setLocalAudioCodec(audioEncoder_->getEncoderName()); if (audioEncoder_->encode_audio(resampledData_) < 0) RING_ERR("encoding failed"); } else { if (audioEncoder_->encode_audio(micData_) < 0) RING_ERR("encoding failed"); } }
size_t RingBufferPool::getAvailableData(AudioBuffer& buffer, const std::string& call_id) { std::lock_guard<std::recursive_mutex> lk(stateLock_); auto bindings = getReadBindings(call_id); if (not bindings) return 0; // No mixing if (bindings->size() == 1) { return (*bindings->cbegin())->get(buffer, call_id); } size_t availableSamples = std::numeric_limits<size_t>::max(); for (const auto& rbuf : *bindings) availableSamples = std::min(availableSamples, rbuf->availableForGet(call_id)); if (availableSamples == std::numeric_limits<size_t>::max()) return 0; availableSamples = std::min(availableSamples, buffer.frames()); buffer.resize(availableSamples); buffer.reset(); buffer.setFormat(internalAudioFormat_); AudioBuffer mixBuffer(buffer); for (const auto &rbuf : *bindings) { if (rbuf->get(mixBuffer, call_id) > 0) buffer.mix(mixBuffer); } return availableSamples; }