43#include <asio/io_context.hpp>
44#include <asio/post.hpp>
50 const std::string& streamId,
51 const std::shared_ptr<MediaRecorder>&
rec)
53 , rtcpCheckerThread_([] {
return true; }, [
this] { processRtcpChecker(); }, [] {})
57 JAMI_DEBUG(
"Created Audio RTP session: {} - stream id {}", fmt::ptr(
this), streamId_);
71AudioRtpSession::startSender()
73 std::lock_guard lock(
mutex_);
74 JAMI_DEBUG(
"Start audio RTP sender: input [{}] - muted [{}]",
76 muteState_ ?
"YES" :
"NO");
84 audioInput_->detach(sender_.get());
93 audioInput_->detach(sender_.get());
101 if (
pos != std::string::npos) {
109 audioInput_->setRecorderCallback(
112 if (
auto shared = w.lock())
113 shared->attachLocalRecorder(ms);
116 audioInput_->setMuted(muteState_);
128 }
catch (
const std::exception&
e) {
129 JAMI_ERROR(
"Exception while retrieving audio parameters: {}",
e.what());
141 initSeqVal_ = sender_->getLastSeqValue() + 1;
146 }
catch (
const MediaEncoderException&
e) {
152 sender_->setVoiceCallback(voiceCallback_);
155 auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(
send_.
codec);
156 audioInput_->setFormat(codec->audioformat);
157 audioInput_->attach(sender_.get());
160 rtcpCheckerThread_.
start();
166 std::lock_guard lock(
mutex_);
176AudioRtpSession::startReceiver()
183 receiveThread_.reset();
191 receiveThread_.reset(
new AudioReceiveThread(
streamId_,
196 receiveThread_->setRecorderCallback([w=
weak_from_this()](
const MediaStream& ms) {
198 if (
auto shared = w.lock())
199 shared->attachRemoteRecorder(ms);
204 receiveThread_->startReceiver();
210 std::lock_guard lock(
mutex_);
239 }
catch (
const std::runtime_error&
e) {
240 JAMI_ERROR(
"Socket creation failed: {}",
e.what());
251 std::lock_guard lock(
mutex_);
253 JAMI_DEBUG(
"[{}] Stopping receiver", fmt::ptr(
this));
255 if (
not receiveThread_)
261 receiveThread_->stopReceiver();
264 audioInput_->detach(sender_.get());
269 rtcpCheckerThread_.
join();
271 receiveThread_.reset();
281 if (
auto shared = w.lock()) {
282 std::lock_guard lock(shared->mutex_);
283 if (dir == Direction::SEND) {
284 shared->muteState_ = muted;
285 if (shared->audioInput_) {
286 shared->audioInput_->setMuted(muted);
289 if (shared->receiveThread_) {
290 auto ms = shared->receiveThread_->getInfo();
291 ms.name = shared->streamId_ +
":remote";
293 if (auto ob = shared->recorder_->getStream(ms.name)) {
294 shared->receiveThread_->detach(ob);
295 shared->recorder_->removeStream(ms);
298 if (auto ob = shared->recorder_->addStream(ms)) {
299 shared->receiveThread_->attach(ob);
309AudioRtpSession::setVoiceCallback(std::function<
void(
bool)> cb)
311 std::lock_guard lock(mutex_);
312 voiceCallback_ = std::move(cb);
314 sender_->setVoiceCallback(voiceCallback_);
319AudioRtpSession::check_RCTP_Info_RR(
RTCPInfo& rtcpi)
321 auto rtcpInfoVect = socketPair_->getRtcpRR();
322 unsigned totalLost = 0;
323 unsigned totalJitter = 0;
324 unsigned nbDropNotNull = 0;
325 auto vectSize = rtcpInfoVect.size();
328 for (
const auto& it : rtcpInfoVect) {
329 if (it.fraction_lost != 0)
331 totalLost += it.fraction_lost;
332 totalJitter += ntohl(it.jitter);
334 rtcpi.
packetLoss = nbDropNotNull ? (float) (100 * totalLost) / (256.0 * nbDropNotNull) : 0;
337 rtcpi.
jitter = (totalJitter / vectSize / 90000.0f) * 1000;
339 rtcpi.
latency = socketPair_->getLastLatency();
346AudioRtpSession::adaptQualityAndBitrate()
349 if (check_RCTP_Info_RR(rtcpi)) {
350 dropProcessing(&rtcpi);
355AudioRtpSession::dropProcessing(RTCPInfo* rtcpi)
357 auto pondLoss = getPonderateLoss(rtcpi->packetLoss);
358 setNewPacketLoss(pondLoss);
362AudioRtpSession::setNewPacketLoss(
unsigned int newPL)
364 newPL = std::clamp((
int) newPL, 0, 100);
365 if (newPL != packetLoss_) {
367 auto ret = sender_->setPacketLoss(newPL);
378AudioRtpSession::getPonderateLoss(
float lastLoss)
380 static float pond = 10.0f;
382 pond = floor(0.5 * lastLoss + 0.5 * pond);
383 if (lastLoss > pond) {
391AudioRtpSession::processRtcpChecker()
393 adaptQualityAndBitrate();
394 socketPair_->waitForRTCP(std::chrono::seconds(rtcp_checking_interval));
398AudioRtpSession::attachRemoteRecorder(
const MediaStream& ms)
400 std::lock_guard lock(mutex_);
401 if (!recorder_ || !receiveThread_)
403 MediaStream remoteMS = ms;
404 remoteMS.name = streamId_ +
":remote";
405 if (
auto ob = recorder_->addStream(remoteMS)) {
406 receiveThread_->attach(ob);
411AudioRtpSession::attachLocalRecorder(
const MediaStream& ms)
413 std::lock_guard lock(mutex_);
414 if (!recorder_ || !audioInput_)
416 MediaStream localMS = ms;
417 localMS.name = streamId_ +
":local";
418 if (
auto ob = recorder_->addStream(localMS)) {
419 audioInput_->attach(ob);
424AudioRtpSession::initRecorder()
429 receiveThread_->setRecorderCallback(
431 asio::post(*Manager::instance().ioContext(), [w=std::move(w), ms]() {
432 if (
auto shared = w.lock())
433 shared->attachRemoteRecorder(ms);
437 audioInput_->setRecorderCallback(
439 asio::post(*Manager::instance().ioContext(), [w=std::move(w), ms]() {
440 if (
auto shared = w.lock())
441 shared->attachLocalRecorder(ms);
447AudioRtpSession::deinitRecorder()
451 if (receiveThread_) {
452 auto ms = receiveThread_->getInfo();
453 ms.name = streamId_ +
":remote";
454 if (
auto ob = recorder_->getStream(ms.name)) {
455 receiveThread_->detach(ob);
456 recorder_->removeStream(ms);
460 auto ms = audioInput_->getInfo();
461 ms.name = streamId_ +
":local";
462 if (
auto ob = recorder_->getStream(ms.name)) {
463 audioInput_->detach(ob);
464 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()
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.