38 , format_(
Manager::instance().getRingBufferPool().getInternalAudioFormat())
45 , loop_([] {
return true; }, [
this] { process(); }, [] {})
47 JAMI_DEBUG(
"Creating audio input with id: {}", id_);
79 decoder_->updateStartTime(
start);
84AudioInput::frameResized(std::shared_ptr<AudioFrame>&&
ptr)
86 std::shared_ptr<AudioFrame>
frame = std::move(
ptr);
87 frame->pointer()->pts =
static_cast<int64_t>(sent_samples);
88 sent_samples +=
frame->pointer()->nb_samples;
90 notify(std::static_pointer_cast<MediaFrame>(std::move(
frame)));
97 decoder_->setSeekTime(
time);
102AudioInput::readFromDevice()
105 std::lock_guard
lk(resourceMutex_);
107 while (ringBuf_ && ringBuf_->isEmpty())
110 while (ringBuf_ && ringBuf_->getLength(id_) == 0)
117 std::this_thread::sleep_until(wakeUp_);
129 std::lock_guard
lk(fmtMutex_);
130 if (
bufferPool.getInternalAudioFormat() != format_)
134 if (recorderCallback_ && settingMS_.exchange(
false)) {
135 recorderCallback_(MediaStream(
"a:local", format_,
static_cast<int64_t>(sent_samples)));
142AudioInput::readFromQueue()
146 if (paused_ || !decoder_->emitFrame(
true)) {
152AudioInput::readFromFile()
156 const auto ret = decoder_->decode();
164 JAMI_ERR() <<
"Failed to decode frame";
167 JAMI_ERR() <<
"Read buffer overflow detected";
176AudioInput::initCapture(
const std::string& device)
183 std::string
pattern =
"window-id:hwnd=";
190 if (
endPos == std::string::npos) {
197#elif defined(__linux__)
202#elif defined(__APPLE__)
219 JAMI_ERROR(
"Failed to start capture stream for desktop audio");
228 playingDevice_ =
true;
233AudioInput::initDevice(
const std::string& device)
236 devOpts_.
input = device;
240 playingDevice_ =
true;
249 devOpts_.
input = path;
250 devOpts_.
name = path;
251 auto decoder = std::make_unique<MediaDecoder>(
demuxer, index, [
this](std::shared_ptr<MediaFrame>&&
frame) {
255 ringBuf_->put(std::static_pointer_cast<AudioFrame>(
frame));
266 sourceRingBufferId_ = id_;
281 deviceGuard_.reset();
293 decoder_->flushBuffers();
298AudioInput::initFile(
const std::string& path)
306 devOpts_.
input = path;
307 devOpts_.
name = path;
310 if (!createDecoder()) {
311 JAMI_WARN() <<
"Unable to decode audio from file, switching back to default device";
312 return initDevice(
"");
318 sourceRingBufferId_ = id_;
319 decodingFile_ =
true;
324std::shared_future<DeviceParams>
328 std::unique_lock
lk(resourceMutex_);
332 auto oldGuard = std::move(deviceGuard_);
336 decodingFile_ =
false;
340 playingDevice_ =
false;
342 sourceRingBufferId_.clear();
343 devOptsFound_ =
false;
345 std::promise<DeviceParams> p;
346 foundDevOpts_.swap(p);
348 if (resource_.empty()) {
350 foundDevOpts(devOpts_);
353 const auto pos = resource_.find(
sep);
354 if (
pos == std::string::npos)
357 const auto prefix = resource_.substr(0,
pos);
358 if ((
pos +
sep.size()) >= resource_.size())
367 ready = initCapture(
suffix);
369 ready = initDevice(
suffix);
372 foundDevOpts(devOpts_);
375 futureDevOpts_ = foundDevOpts_.get_future().share();
380 if (onSuccessfulSetup_)
382 return futureDevOpts_;
388 if (!devOptsFound_) {
389 devOptsFound_ =
true;
390 foundDevOpts_.set_value(
params);
397 settingMS_.exchange(
true);
398 recorderCallback_ =
cb;
400 decoder_->setContextCallback([
this]() {
401 if (recorderCallback_)
407AudioInput::createDecoder()
410 if (devOpts_.
input.empty()) {
411 foundDevOpts(devOpts_);
415 auto decoder = std::make_unique<MediaDecoder>([
this](std::shared_ptr<MediaFrame>&&
frame) {
417 ringBuf_->put(std::static_pointer_cast<AudioFrame>(
frame));
425 if (
decoder->openInput(devOpts_) < 0) {
426 JAMI_ERR() <<
"Unable to open input '" << devOpts_.
input <<
"'";
427 foundDevOpts(devOpts_);
431 if (
decoder->setupAudio() < 0) {
432 JAMI_ERR() <<
"Unable to setup decoder for '" << devOpts_.
input <<
"'";
433 foundDevOpts(devOpts_);
438 devOpts_.
channel = ms.nbChannels;
440 JAMI_DBG() <<
"Created audio decoder: " << ms;
443 foundDevOpts(devOpts_);
444 decoder_->setContextCallback([
this]() {
445 if (recorderCallback_)
454 std::lock_guard
lk(fmtMutex_);
462 JAMI_WARN(
"Audio Input muted [%s]", isMuted ?
"YES" :
"NO");
463 muteState_ = isMuted;
469 std::lock_guard
lk(fmtMutex_);
476 std::lock_guard
lk(fmtMutex_);
Manager (controller) of daemon.
static LIBJAMI_TEST_EXPORT Manager & instance()
std::unique_ptr< AudioDeviceGuard > startCaptureStream(const std::string &captureDevice)
Start a capture stream on the given device (eg.
RingBufferPool & getRingBufferPool()
Return a pointer to the instance of the RingBufferPool.
std::unique_ptr< AudioDeviceGuard > startAudioStream(AudioDeviceType stream)
void notify(std::shared_ptr< MediaFrame > data)
Wrapper class for libswresample.
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.
static const char *const DEFAULT_ID
void flush(const std::string &ringbufferId)
void unBindHalfDuplexOut(const std::string &readerBufferId, const std::string &sourceBufferId)
Detaches a reader from the specified source.
bool isRunning() const noexcept
#define JAMI_ERROR(formatstr,...)
#define JAMI_DEBUG(formatstr,...)
void fillWithSilence(AVFrame *frame)
static constexpr const char DEVICE_DESKTOP[]
static constexpr auto MS_PER_PACKET
void emitSignal(Args... args)
DeviceParams Parameters used by MediaDecoder and MediaEncoder to open a LibAV device/stream.
rational< double > framerate
#define jami_tracepoint(...)