Ring Daemon
Loading...
Searching...
No Matches
audio_sender.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "audio_sender.h"
19#include "libav_deps.h"
20#include "logger.h"
21#include "media_encoder.h"
22#include "media_io_handle.h"
23#include "media_stream.h"
24#include "resampler.h"
25
26#include <memory>
27
28namespace jami {
29
30AudioSender::AudioSender(const std::string& dest,
33 const uint16_t seqVal,
34 const uint16_t mtu)
35 : dest_(dest)
36 , args_(args)
37 , seqVal_(seqVal)
38 , mtu_(mtu)
39{
40 setup(socketPair);
41}
42
44{
45 audioEncoder_.reset();
46 muxContext_.reset();
47}
48
49bool
50AudioSender::setup(SocketPair& socketPair)
51{
52 audioEncoder_.reset(new MediaEncoder);
53 muxContext_.reset(socketPair.createIOContext(mtu_));
54
55 try {
56 /* Encoder setup */
57 JAMI_DBG("audioEncoder_->openOutput %s", dest_.c_str());
58 audioEncoder_->openOutput(dest_, "rtp");
59 audioEncoder_->setOptions(args_);
60 auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(args_.codec);
61 auto ms = MediaStream("audio sender", codec->audioformat);
62 audioEncoder_->setOptions(ms);
63 audioEncoder_->addStream(*args_.codec);
64 audioEncoder_->setInitSeqVal(seqVal_);
65 audioEncoder_->setIOContext(muxContext_->getContext());
66 } catch (const MediaEncoderException& e) {
67 JAMI_ERR("%s", e.what());
68 return false;
69 }
70#ifdef DEBUG_SDP
71 audioEncoder_->print_sdp();
72#endif
73
74 return true;
75}
76
77void
78AudioSender::update(Observable<std::shared_ptr<jami::MediaFrame>>* /*obs*/,
79 const std::shared_ptr<jami::MediaFrame>& framePtr)
80{
81 auto* frame = framePtr->pointer();
82 frame->pts = static_cast<int64_t>(sent_samples);
83 sent_samples += frame->nb_samples;
84
85 // check for change in voice activity, if so, call callback
86 // downcast MediaFrame to AudioFrame
87 bool hasVoice = std::dynamic_pointer_cast<AudioFrame>(framePtr)->has_voice;
88 if (hasVoice != voice_) {
89 voice_ = hasVoice;
90 if (voiceCallback_) {
91 voiceCallback_(voice_);
92 } else {
93 JAMI_ERR("AudioSender no voice callback!");
94 }
95 }
96
97 if (audioEncoder_->encodeAudio(*std::static_pointer_cast<AudioFrame>(framePtr)) < 0)
98 JAMI_ERR("encoding failed");
99}
100
101void
102AudioSender::setVoiceCallback(std::function<void(bool)> cb)
103{
104 if (cb) {
105 voiceCallback_ = std::move(cb);
106 } else {
107 JAMI_ERR("AudioSender attempting to set invalid voice callback");
108 }
109}
110
113{
114 return audioEncoder_->getLastSeqValue();
115}
116
117int
119{
120 // The encoder may be destroy during a bitrate change
121 // when a codec parameter like auto quality change
122 if (!audioEncoder_)
123 return -1; // NOK
124
125 return audioEncoder_->setPacketLoss(pl);
126}
127
128} // namespace jami
AudioSender(const std::string &dest, const MediaDescription &args, SocketPair &socketPair, const uint16_t seqVal, const uint16_t mtu)
void setVoiceCallback(std::function< void(bool)> cb)
int setPacketLoss(uint64_t pl)
uint16_t getLastSeqValue()
void update(Observable< std::shared_ptr< jami::MediaFrame > > *, const std::shared_ptr< jami::MediaFrame > &) override
#define JAMI_ERR(...)
Definition logger.h:230
#define JAMI_DBG(...)
Definition logger.h:228
void emitSignal(Args... args)
Definition jami_signal.h:64
MediaDescription Negotiated RTP media slot.
std::shared_ptr< SystemCodecInfo > codec
RTP.