Commit 4d295519 authored by Guillaume Roguez's avatar Guillaume Roguez

videomanager: fix bad memory access

- remove videoManager global instance.
- allocate a VideoManager instance when Manager instance is created.
- add Manager::getVideoManager() method to get this instance.
- force getSignalHandlers() to be called before Manager instance creation.

All of this prevents VideoManager to access to signal handlers map,
already destroyed, causing a memory access violation.

Change-Id: I21ebff08fa8d49e797f99299de12dab023c37769
Tuleap: #413
parent 95dd7833
......@@ -39,8 +39,6 @@
namespace DRing {
using ring::videoManager;
void
registerVideoHandlers(const std::map<std::string,
std::shared_ptr<CallbackWrapperBase>>& handlers)
......@@ -61,65 +59,65 @@ registerVideoHandlers(const std::map<std::string,
std::vector<std::string>
getDeviceList()
{
return videoManager.videoDeviceMonitor.getDeviceList();
return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getDeviceList();
}
VideoCapabilities
getCapabilities(const std::string& name)
{
return videoManager.videoDeviceMonitor.getCapabilities(name);
return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getCapabilities(name);
}
std::string
getDefaultDevice()
{
return videoManager.videoDeviceMonitor.getDefaultDevice();
return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getDefaultDevice();
}
void
setDefaultDevice(const std::string& name)
{
RING_DBG("Setting default device to %s", name.c_str());
videoManager.videoDeviceMonitor.setDefaultDevice(name);
ring::Manager::instance().getVideoManager().videoDeviceMonitor.setDefaultDevice(name);
}
std::map<std::string, std::string>
getSettings(const std::string& name)
{
return videoManager.videoDeviceMonitor.getSettings(name).to_map();
return ring::Manager::instance().getVideoManager().videoDeviceMonitor.getSettings(name).to_map();
}
void
applySettings(const std::string& name,
const std::map<std::string, std::string>& settings)
{
videoManager.videoDeviceMonitor.applySettings(name, settings);
ring::Manager::instance().getVideoManager().videoDeviceMonitor.applySettings(name, settings);
}
void
startCamera()
{
videoManager.videoPreview = ring::getVideoCamera();
videoManager.started = switchToCamera();
ring::Manager::instance().getVideoManager().videoPreview = ring::getVideoCamera();
ring::Manager::instance().getVideoManager().started = switchToCamera();
}
void
stopCamera()
{
if (switchInput(""))
videoManager.started = false;
videoManager.videoPreview.reset();
ring::Manager::instance().getVideoManager().started = false;
ring::Manager::instance().getVideoManager().videoPreview.reset();
}
bool
switchInput(const std::string& resource)
{
if (auto call = ring::Manager::instance().getCurrentCall()) {
// TODO remove this part when clients are updated to use CallManager::switchInput
// TODO remove this part when clients are updated to use Callring::Manager::switchInput
call->switchInput(resource);
return true;
} else {
if (auto input = videoManager.videoInput.lock())
if (auto input = ring::Manager::instance().getVideoManager().videoInput.lock())
return input->switchInput(resource).valid();
RING_WARN("Video input not initialized");
}
......@@ -129,13 +127,13 @@ switchInput(const std::string& resource)
bool
switchToCamera()
{
return switchInput(videoManager.videoDeviceMonitor.getMRLForDefaultDevice());
return switchInput(ring::Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice());
}
bool
hasCameraStarted()
{
return videoManager.started;
return ring::Manager::instance().getVideoManager().started;
}
void
......@@ -151,13 +149,13 @@ registerSinkTarget(const std::string& sinkId, const SinkTarget& target)
void
addVideoDevice(const std::string &node)
{
videoManager.videoDeviceMonitor.addDevice(node);
ring::Manager::instance().getVideoManager().videoDeviceMonitor.addDevice(node);
}
void
removeVideoDevice(const std::string &node)
{
videoManager.videoDeviceMonitor.removeDevice(node);
ring::Manager::instance().getVideoManager().videoDeviceMonitor.removeDevice(node);
}
void*
......@@ -181,24 +179,23 @@ releaseFrame(void* frame)
namespace ring {
VideoManager videoManager;
std::shared_ptr<video::VideoFrameActiveWriter>
getVideoCamera()
{
if (auto input = videoManager.videoInput.lock())
auto& vmgr = Manager::instance().getVideoManager();
if (auto input = vmgr.videoInput.lock())
return input;
videoManager.started = false;
vmgr.started = false;
auto input = std::make_shared<video::VideoInput>();
videoManager.videoInput = input;
vmgr.videoInput = input;
return input;
}
video::VideoDeviceMonitor&
getVideoDeviceMonitor()
{
return videoManager.videoDeviceMonitor;
return Manager::instance().getVideoManager().videoDeviceMonitor;
}
} // namespace ring
......@@ -51,8 +51,6 @@ struct VideoManager
std::atomic_bool started;
};
extern VideoManager videoManager;
std::shared_ptr<video::VideoFrameActiveWriter> getVideoCamera();
video::VideoDeviceMonitor& getVideoDeviceMonitor();
......
......@@ -213,6 +213,9 @@ Manager::Manager() :
, ringbufferpool_(new RingBufferPool)
, callFactory(), conferenceMap_()
, accountFactory_(), ice_tf_()
#ifdef RING_VIDEO
, videoManager_(new VideoManager)
#endif
{
// initialize random generator
// mt19937_64 should be seeded with 2 x 32 bits
......
......@@ -66,6 +66,7 @@ class PluginManager;
class AudioFile;
class DTMF;
class RingBufferPool;
class VideoManager;
/** To send multiple string */
typedef std::list<std::string> TokenList;
......@@ -758,7 +759,6 @@ class Manager {
*/
std::vector<std::string> loadAccountOrder() const;
private:
void removeAccounts();
......@@ -961,8 +961,8 @@ class Manager {
#ifdef RING_VIDEO
std::shared_ptr<video::SinkClient> createSinkClient(const std::string& id="", bool mixer=false);
std::shared_ptr<video::SinkClient> getSinkClient(const std::string& id);
VideoManager& getVideoManager() const { return *videoManager_; }
#endif // RING_VIDEO
private:
......@@ -1012,6 +1012,10 @@ class Manager {
const std::map<std::string, std::string>& messages,
const std::string& from) const noexcept;
#endif
#ifdef RING_VIDEO
std::unique_ptr<VideoManager> videoManager_;
#endif
};
// Helper to install a callback to be called once by the main event loop
......
......@@ -73,7 +73,7 @@ void VideoRtpSession::startSender()
if (not conference_) {
videoLocal_ = getVideoCamera();
if (auto input = videoManager.videoInput.lock()) {
if (auto input = Manager::instance().getVideoManager().videoInput.lock()) {
auto newParams = input->switchInput(input_);
try {
if (newParams.valid() &&
......
......@@ -33,6 +33,7 @@
#include "callmanager_interface.h"
#include "configurationmanager_interface.h"
#include "presencemanager_interface.h"
#include "client/ring_signal.h"
#ifdef RING_VIDEO
#include "client/videomanager.h"
......@@ -46,6 +47,11 @@ init(enum InitFlag flags) noexcept
::setDebugMode(flags & DRING_FLAG_DEBUG);
::setConsoleLog(flags & DRING_FLAG_CONSOLE_LOG);
// Following function create a local static variable inside
// This var must have the same live as Manager.
// So we call it now to create this var.
ring::getSignalHandlers();
try {
// current implementation use static variable
return &ring::Manager::instance() != nullptr;
......
......@@ -119,7 +119,7 @@ SIPCall::SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType
#ifdef RING_VIDEO
// The ID is used to associate video streams to calls
, videortp_(id, getVideoSettings())
, videoInput_(videoManager.videoDeviceMonitor.getMRLForDefaultDevice())
, videoInput_(Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice())
#endif
, sdp_(new Sdp(id))
{
......@@ -907,7 +907,7 @@ SIPCall::muteMedia(const std::string& mediaType, bool mute)
if (mute == isVideoMuted_) return;
RING_WARN("[call:%s] video muting %s", getCallId().c_str(), bool_to_str(mute));
isVideoMuted_ = mute;
videoInput_ = isVideoMuted_ ? "" : videoManager.videoDeviceMonitor.getMRLForDefaultDevice();
videoInput_ = isVideoMuted_ ? "" : Manager::instance().getVideoManager().videoDeviceMonitor.getMRLForDefaultDevice();
DRing::switchInput(getCallId(), videoInput_);
emitSignal<DRing::CallSignal::VideoMuted>(getCallId(), isVideoMuted_);
#endif
......
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