43#include <asio/io_context.hpp>
49 const std::string& streamId,
50 const std::shared_ptr<MediaRecorder>&
rec)
52 , rtcpCheckerThread_([] {
return true; }, [
this] { processRtcpChecker(); }, [] {})
56 JAMI_DEBUG(
"Created Audio RTP session: {} - stream id {}", fmt::ptr(
this), streamId_);
70AudioRtpSession::startSender()
72 std::lock_guard lock(
mutex_);
73 JAMI_DEBUG(
"Start audio RTP sender: input [{}] - muted [{}]",
75 muteState_ ?
"YES" :
"NO");
83 audioInput_->detach(sender_.get());
92 audioInput_->detach(sender_.get());
100 if (
pos != std::string::npos) {
108 audioInput_->setRecorderCallback(
111 if (
auto shared = w.lock())
112 shared->attachLocalRecorder(ms);
115 audioInput_->setMuted(muteState_);
127 }
catch (
const std::exception&
e) {
128 JAMI_ERROR(
"Exception while retrieving audio parameters: {}",
e.what());
140 initSeqVal_ = sender_->getLastSeqValue() + 1;
145 }
catch (
const MediaEncoderException&
e) {
151 sender_->setVoiceCallback(voiceCallback_);
154 auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(
send_.
codec);
155 audioInput_->setFormat(codec->audioformat);
156 audioInput_->attach(sender_.get());
159 rtcpCheckerThread_.
start();
165 std::lock_guard lock(
mutex_);
175AudioRtpSession::startReceiver()
182 receiveThread_.reset();
190 receiveThread_.reset(
new AudioReceiveThread(
streamId_,
195 receiveThread_->setRecorderCallback([w=
weak_from_this()](
const MediaStream& ms) {
197 if (
auto shared = w.lock())
198 shared->attachRemoteRecorder(ms);
203 receiveThread_->startReceiver();
209 std::lock_guard lock(
mutex_);
238 }
catch (
const std::runtime_error&
e) {
239 JAMI_ERROR(
"Socket creation failed: {}",
e.what());
250 std::lock_guard lock(
mutex_);
252 JAMI_DEBUG(
"[{}] Stopping receiver", fmt::ptr(
this));
254 if (
not receiveThread_)
260 receiveThread_->stopReceiver();
263 audioInput_->detach(sender_.get());
268 rtcpCheckerThread_.
join();
270 receiveThread_.reset();
280 if (
auto shared = w.lock()) {
281 std::lock_guard lock(shared->mutex_);
282 if (dir == Direction::SEND) {
283 shared->muteState_ = muted;
284 if (shared->audioInput_) {
285 shared->audioInput_->setMuted(muted);
288 if (shared->receiveThread_) {
289 auto ms = shared->receiveThread_->getInfo();
290 ms.name = shared->streamId_ +
":remote";
292 if (auto ob = shared->recorder_->getStream(ms.name)) {
293 shared->receiveThread_->detach(ob);
294 shared->recorder_->removeStream(ms);
297 if (auto ob = shared->recorder_->addStream(ms)) {
298 shared->receiveThread_->attach(ob);
308AudioRtpSession::setVoiceCallback(std::function<
void(
bool)> cb)
310 std::lock_guard lock(mutex_);
311 voiceCallback_ = std::move(cb);
313 sender_->setVoiceCallback(voiceCallback_);
318AudioRtpSession::check_RCTP_Info_RR(
RTCPInfo& rtcpi)
320 auto rtcpInfoVect = socketPair_->getRtcpRR();
321 unsigned totalLost = 0;
322 unsigned totalJitter = 0;
323 unsigned nbDropNotNull = 0;
324 auto vectSize = rtcpInfoVect.size();
327 for (
const auto& it : rtcpInfoVect) {
328 if (it.fraction_lost != 0)
330 totalLost += it.fraction_lost;
331 totalJitter += ntohl(it.jitter);
333 rtcpi.
packetLoss = nbDropNotNull ? (float) (100 * totalLost) / (256.0 * nbDropNotNull) : 0;
336 rtcpi.
jitter = (totalJitter / vectSize / 90000.0f) * 1000;
338 rtcpi.
latency = socketPair_->getLastLatency();
345AudioRtpSession::adaptQualityAndBitrate()
348 if (check_RCTP_Info_RR(rtcpi)) {
349 dropProcessing(&rtcpi);
354AudioRtpSession::dropProcessing(RTCPInfo* rtcpi)
356 auto pondLoss = getPonderateLoss(rtcpi->packetLoss);
357 setNewPacketLoss(pondLoss);
361AudioRtpSession::setNewPacketLoss(
unsigned int newPL)
363 newPL = std::clamp((
int) newPL, 0, 100);
364 if (newPL != packetLoss_) {
366 auto ret = sender_->setPacketLoss(newPL);
377AudioRtpSession::getPonderateLoss(
float lastLoss)
379 static float pond = 10.0f;
381 pond = floor(0.5 * lastLoss + 0.5 * pond);
382 if (lastLoss > pond) {
390AudioRtpSession::processRtcpChecker()
392 adaptQualityAndBitrate();
393 socketPair_->waitForRTCP(std::chrono::seconds(rtcp_checking_interval));
397AudioRtpSession::attachRemoteRecorder(
const MediaStream& ms)
399 std::lock_guard lock(mutex_);
400 if (!recorder_ || !receiveThread_)
402 MediaStream remoteMS = ms;
403 remoteMS.name = streamId_ +
":remote";
404 if (
auto ob = recorder_->addStream(remoteMS)) {
405 receiveThread_->attach(ob);
410AudioRtpSession::attachLocalRecorder(
const MediaStream& ms)
412 std::lock_guard lock(mutex_);
413 if (!recorder_ || !audioInput_)
415 MediaStream localMS = ms;
416 localMS.name = streamId_ +
":local";
417 if (
auto ob = recorder_->addStream(localMS)) {
418 audioInput_->attach(ob);
423AudioRtpSession::initRecorder()
428 receiveThread_->setRecorderCallback(
430 Manager::instance().ioContext()->post([w=std::move(w), ms]() {
431 if (
auto shared = w.lock())
432 shared->attachRemoteRecorder(ms);
436 audioInput_->setRecorderCallback(
438 Manager::instance().ioContext()->post([w=std::move(w), ms]() {
439 if (
auto shared = w.lock())
440 shared->attachLocalRecorder(ms);
446AudioRtpSession::deinitRecorder()
450 if (receiveThread_) {
451 auto ms = receiveThread_->getInfo();
452 ms.name = streamId_ +
":remote";
453 if (
auto ob = recorder_->getStream(ms.name)) {
454 receiveThread_->detach(ob);
455 recorder_->removeStream(ms);
459 auto ms = audioInput_->getInfo();
460 ms.name = streamId_ +
":local";
461 if (
auto ob = recorder_->getStream(ms.name)) {
462 audioInput_->detach(ob);
463 recorder_->removeStream(ms);
void deinitRecorder() override
void setMuted(bool muted, Direction dir=Direction::SEND) override
void start(std::unique_ptr< dhtnet::IceSocket > rtp_sock, std::unique_ptr< dhtnet::IceSocket > rtcp_sock) override
virtual ~AudioRtpSession()
AudioRtpSession(const std::string &callId, const std::string &streamId, const std::shared_ptr< MediaRecorder > &rec)
void restartSender() override
std::string getSrtpKeyInfo() const
std::string getCryptoSuite() const
static LIBJAMI_TEST_EXPORT Manager & instance()
std::shared_ptr< asio::io_context > ioContext() const
RingBufferPool & getRingBufferPool()
Return a pointer to the instance of the RingBufferPool.
std::shared_ptr< RingBuffer > createRingBuffer(const std::string &id)
Create a new ringbuffer with a default readoffset.
void bindHalfDuplexOut(const std::string &readerBufferId, const std::string &sourceBufferId)
Attaches a reader the specified source.
std::string getRemoteRtpUri() const
std::recursive_mutex mutex_
MediaDescription receive_
const std::string streamId_
std::function< void(MediaType, bool)> onSuccessfulSetup_
std::unique_ptr< SocketPair > socketPair_
bool isRunning() const noexcept
#define JAMI_ERROR(formatstr,...)
#define JAMI_DEBUG(formatstr,...)
#define JAMI_WARNING(formatstr,...)
void emitSignal(Args... args)
static constexpr auto NEWPARAMS_TIMEOUT
std::shared_ptr< AudioInput > getAudioInput(const std::string &device)
Simple macro to hide class' copy constructor and assignment operator.