Commit e86600b6 authored by Philippe Gorley's avatar Philippe Gorley

audio: stash active inputs in videomanager

Needed for audio streaming because the audio input needs to be accessed
at call level so it can tell the input to switch to a file or a
different input.

Getting a shared pointer to an AudioInput should only be done during
setup, so as to not walk the whole map in audio processing loops.

Change-Id: I49be1cb3c641b50e6f70356f330d40e1c27bef61
parent 41886925
......@@ -33,6 +33,7 @@
#include "system_codec_container.h"
#include "video/sinkclient.h"
#include "client/ring_signal.h"
#include "audio/ringbufferpool.h"
#include <functional>
#include <memory>
......@@ -420,4 +421,31 @@ getVideoDeviceMonitor()
return Manager::instance().getVideoManager().videoDeviceMonitor;
}
std::shared_ptr<AudioInput>
getAudioInput(const std::string& id)
{
auto& vmgr = Manager::instance().getVideoManager();
std::lock_guard<std::mutex> lk(vmgr.audioMutex);
// erase expired audio inputs
for (auto it = vmgr.audioInputs.cbegin(); it != vmgr.audioInputs.cend();) {
if (it->second.expired())
it = vmgr.audioInputs.erase(it);
else
++it;
}
auto it = vmgr.audioInputs.find(id);
if (it != vmgr.audioInputs.end()) {
if (auto input = it->second.lock()) {
return input;
}
}
auto input = std::make_shared<AudioInput>(id);
vmgr.audioInputs[id] = input;
Manager::instance().getRingBufferPool().bindCallID(id, RingBufferPool::DEFAULT_ID);
return input;
}
} // namespace ring
......@@ -26,8 +26,10 @@
#include <memory> // for weak/shared_ptr
#include <vector>
#include <map>
#include <mutex>
#include <string>
#include "audio/audio_input.h"
#include "video/video_device_monitor.h"
#include "video/video_base.h"
#include "video/video_input.h"
......@@ -37,7 +39,8 @@ namespace ring {
struct VideoManager
{
public:
/* VideoManager acts as a cache of the active VideoInput.
/**
* VideoManager acts as a cache of the active VideoInput.
* When this input is needed, you must use getVideoCamera
* to create the instance if not done yet and obtain a shared pointer
* for your own usage.
......@@ -49,10 +52,18 @@ struct VideoManager
std::shared_ptr<video::VideoFrameActiveWriter> videoPreview;
video::VideoDeviceMonitor videoDeviceMonitor;
std::atomic_bool started;
/**
* VideoManager also acts as a cache of the active AudioInput(s).
* When one of these is needed, you must use getAudioInput, which will
* create an instance if need be and return a shared_ptr.
*/
std::map<std::string, std::weak_ptr<AudioInput>> audioInputs;
std::mutex audioMutex;
};
std::shared_ptr<video::VideoFrameActiveWriter> getVideoCamera();
video::VideoDeviceMonitor& getVideoDeviceMonitor();
std::shared_ptr<AudioInput> getAudioInput(const std::string& id);
} // namespace ring
......
......@@ -41,6 +41,7 @@ AudioInput::AudioInput(const std::string& id) :
[this] { process(); },
[] {})
{
RING_DBG() << "Creating audio input with id: " << id;
loop_.start();
}
......
......@@ -41,6 +41,7 @@
#include "audio/audiobuffer.h"
#include "audio/ringbufferpool.h"
#include "audio/resampler.h"
#include "client/videomanager.h"
#include "manager.h"
#include "observer.h"
#include "smartools.h"
......@@ -78,7 +79,7 @@ class AudioSender : public Observer<std::shared_ptr<AudioFrame>> {
std::unique_ptr<MediaEncoder> audioEncoder_;
std::unique_ptr<MediaIOHandle> muxContext_;
std::unique_ptr<Resampler> resampler_;
std::unique_ptr<AudioInput> audioInput_;
std::shared_ptr<AudioInput> audioInput_;
std::weak_ptr<MediaRecorder> recorder_;
uint64_t sent_samples = 0;
......@@ -147,8 +148,8 @@ AudioSender::setup(SocketPair& socketPair)
#endif
// NOTE do after encoder is ready to encode
audioInput_.reset(new AudioInput(id_));
auto codec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec);
audioInput_ = ring::getAudioInput(id_);
audioInput_->setFormat(codec->audioformat);
audioInput_->attach(this);
......
......@@ -26,10 +26,12 @@
#include "media_stream.h"
#include "manager.h"
#include "logger.h"
#include "client/videomanager.h"
namespace ring {
LocalRecorder::LocalRecorder(const bool& audioOnly) {
LocalRecorder::LocalRecorder(const bool& audioOnly)
{
isAudioOnly_ = audioOnly;
recorder_->audioOnly(audioOnly);
}
......@@ -69,7 +71,7 @@ LocalRecorder::startRecording()
Manager::instance().getRingBufferPool().bindHalfDuplexOut(path_, RingBufferPool::DEFAULT_ID);
Manager::instance().startAudioDriverStream();
audioInput_.reset(new AudioInput(path_));
audioInput_ = ring::getAudioInput(path_);
audioInput_->setFormat(AudioFormat::STEREO());
audioInput_->initRecorder(recorder_);
......
......@@ -66,7 +66,7 @@ class LocalRecorder : public Recordable {
// media inputs
std::shared_ptr<ring::video::VideoInput> videoInput_;
std::unique_ptr<ring::AudioInput> audioInput_;
std::shared_ptr<ring::AudioInput> audioInput_;
};
} // namespace ring
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment