Skip to content

Commit ccec94c

Browse files
Fix Windows crash on exit with upcoming NDI video output plugin (#510)
### Fix Windows crash on exit with upcoming NDI video output plugin ### Linked issues NA ### Summarize your change. This commit makes sure that the allocated video modules are released when RV exits. To do so, the TwkApp::VideoModules container which previously contained raw pointers (std::vector<VideoModule*>) which were never released on exit, has been converted to std::vector<std::shared_ptr<VideoModule>> ### Describe the reason for the change. This missing TwkApp::VideoModules cleanup on exit, was causing a crash on Windows when the upcoming NDI video output plugin was unloaded. More specifically: The NDI crash was caused when trying to unload the NDI dll without having called the NDIlib_destroy(). Note that NDIlib_initialize() is called when allocating an NDI video module while the NDIlib_destroy() is called when releasing the NDI video module. So it became essential to fix this TwkApp::VideoModules cleanup on exit to prevent a crash on Windows. ### Describe what you have tested and on which operating system. Successfully tested on macOS and Windows. ### Add a list of changes, and note any that might need special attention during the review. ### If possible, provide screenshots. Signed-off-by: Bernard Laberge <[email protected]>
1 parent 0360669 commit ccec94c

File tree

8 files changed

+19
-31
lines changed

8 files changed

+19
-31
lines changed

src/lib/app/RvCommon/RvApplication.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ RvApplication::findPresentationDevice(const std::string& dpath) const
17871787

17881788
if (mindex >= 0)
17891789
{
1790-
VideoModule* m = videoModules()[mindex];
1790+
VideoModule* m = videoModules()[mindex].get();
17911791
openVideoModule(m);
17921792
const VideoModule::VideoDevices& devs = m->devices();
17931793
string dname = parts[1].toUtf8().constData();

src/lib/app/RvCommon/RvPreferences.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3249,7 +3249,7 @@ RvPreferences::updateVideo()
32493249

32503250
if (m_currentVideoDevice < 0 && m_currentVideoModule >= 0)
32513251
{
3252-
VideoModule* m = vmods[m_currentVideoModule];
3252+
const auto m = vmods[m_currentVideoModule];
32533253
const VideoModule::VideoDevices& devs = m->devices();
32543254
string dname = parts[1].toUtf8().constData();
32553255

@@ -3277,12 +3277,12 @@ RvPreferences::updateVideo()
32773277

32783278
for (size_t i = 0; i < vmods.size(); i++)
32793279
{
3280-
TwkApp::VideoModule* mod = vmods[i];
3280+
auto mod = vmods[i];
32813281
m_ui.videoModuleCombo->addItem(QString::fromUtf8(mod->name().c_str()));
32823282

32833283
if (i == m_currentVideoModule)
32843284
{
3285-
if (!mod->isOpen()) RvApp()->openVideoModule(mod);
3285+
if (!mod->isOpen()) RvApp()->openVideoModule(mod.get());
32863286
m_ui.videoModuleCombo->setCurrentIndex(i);
32873287
m_ui.videoDeviceCombo->clear();
32883288
m_ui.videoDeviceCombo->hide();
@@ -3810,7 +3810,7 @@ RvPreferences::currentVideoDevice() const
38103810
m_currentVideoModule == -1) return 0;
38113811

38123812
const IPCore::Application::VideoModules& vmods = RvApp()->videoModules();
3813-
VideoModule* mod = vmods[m_currentVideoModule];
3813+
const auto mod = vmods[m_currentVideoModule];
38143814
const VideoModule::VideoDevices& devs = mod->devices();
38153815
return devs[m_currentVideoDevice];
38163816
}

src/lib/app/RvCommon/RvTopViewToolBar.cpp

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -485,20 +485,12 @@ RvTopViewToolBar::receiveEvent(const Event& event)
485485
const string deviceName = contents.substr(p+1);
486486
const string moduleName = contents.substr(0, p);
487487

488-
const IPCore::Application::VideoModules& modules = RvApp()->videoModules();
489-
490-
for (size_t i = 0; i < modules.size(); i++)
488+
for (const auto module : RvApp()->videoModules())
491489
{
492-
const VideoModule* module = modules[i];
493-
494490
if (module->name() == moduleName)
495491
{
496-
const VideoModule::VideoDevices& devices = module->devices();
497-
498-
for (size_t q = 0; q < devices.size(); q++)
492+
for (const auto device : module->devices())
499493
{
500-
const VideoDevice* device = devices[q];
501-
502494
if (device->name() == deviceName)
503495
{
504496
m_outputDevice = device;
@@ -1025,17 +1017,10 @@ RvTopViewToolBar::monitorMenuUpdate()
10251017

10261018
QString html = "<style type=\"text/css\"> td { padding: 4px; } </style><table>";
10271019

1028-
const IPCore::Application::VideoModules& modules = RvApp()->videoModules();
1029-
1030-
for (size_t i = 0; i < modules.size(); i++)
1020+
for (const auto module : RvApp()->videoModules())
10311021
{
1032-
const VideoModule* module = modules[i];
1033-
const VideoModule::VideoDevices& devices = module->devices();
1034-
1035-
for (size_t q = 0; q < devices.size(); q++)
1022+
for (const auto device : module->devices())
10361023
{
1037-
const VideoDevice* device = devices[q];
1038-
10391024
VideoDevice::VideoFormat format = device->videoFormatAtIndex(device->currentVideoFormat());
10401025
VideoDevice::DataFormat data = device->dataFormatAtIndex(device->currentDataFormat());
10411026

src/lib/app/TwkApp/Application.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Application::Application() : TwkUtil::Notifier()
2626
Application::~Application()
2727
{
2828
m_app = 0;
29+
30+
// Make sure to release all the video modules before we unload the plugins
31+
m_videoModules.clear();
2932
}
3033

3134
void
@@ -58,7 +61,7 @@ Application::receive(Notifier* originator,
5861
VideoModule*
5962
Application::primaryVideoModule() const
6063
{
61-
return m_videoModules.empty() ? 0 : m_videoModules.front();
64+
return m_videoModules.empty() ? 0 : m_videoModules.front().get();
6265
}
6366

6467
void

src/lib/app/TwkApp/TwkApp/Application.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#include <TwkUtil/Notifier.h>
1111
#include <TwkApp/Document.h>
1212
#include <TwkApp/OutputPlugins.h>
13+
#include <TwkApp/VideoModule.h>
1314

1415
namespace TwkApp {
15-
class VideoModule;
1616

1717
//
1818
// class Application
@@ -38,7 +38,7 @@ class Application : public TwkUtil::Notifier
3838
//
3939

4040
typedef std::vector<Document*> Documents;
41-
typedef std::vector<VideoModule*> VideoModules;
41+
typedef std::vector<std::shared_ptr<VideoModule>> VideoModules;
4242
typedef TwkUtil::Notifier Notifier;
4343

4444
//
@@ -59,7 +59,7 @@ class Application : public TwkUtil::Notifier
5959

6060
void loadOutputPlugins(const std::string& envvar);
6161
void unloadOutputPlugins();
62-
void addVideoModule(VideoModule* m) { m_videoModules.push_back(m); }
62+
void addVideoModule(VideoModule* m) { m_videoModules.push_back(std::shared_ptr<VideoModule>(m)); }
6363
virtual VideoModule* primaryVideoModule() const;
6464
const VideoModules& videoModules() const { return m_videoModules; }
6565

src/lib/ip/IPCore/IPCore/Application.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class Application : public TwkApp::Application
4444
typedef std::vector<std::string> StringVector;
4545
typedef std::map<std::string,std::string> PropEnvMap;
4646
typedef TwkApp::VideoModule VideoModule;
47-
typedef std::vector<VideoModule*> VideoModules;
47+
typedef std::vector<std::shared_ptr<VideoModule>> VideoModules;
4848
typedef size_t DispatchID;
4949
typedef std::function<void(DispatchID)> DispatchCallback;
5050

src/lib/ip/IPCore/IPCore/IPGraph.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class IPGraph : public TwkApp::EventNode
126126
typedef IPNode::IPNodes IPNodes;
127127
typedef TwkApp::VideoModule VideoModule;
128128
typedef TwkApp::VideoDevice VideoDevice;
129-
typedef std::vector<VideoModule*> VideoModules;
129+
typedef std::vector<std::shared_ptr<VideoModule>> VideoModules;
130130
typedef std::vector<DisplayGroupIPNode*> DisplayGroups;
131131
typedef IPImage::InternalGLMatricesContext InternalGLMatricesContext;
132132
typedef int WorkItemID;

src/lib/ip/IPCore/IPGraph.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ IPGraph::setPhysicalDevicesInternal(const VideoModules& modules)
712712
{
713713
for (size_t i = 0; i < modules.size(); i++)
714714
{
715-
const VideoModule* module = modules[i];
715+
const VideoModule* module = modules[i].get();
716716
const TwkApp::VideoModule::VideoDevices& devices = module->devices();
717717

718718
for (size_t j = 0; j < devices.size(); j++)

0 commit comments

Comments
 (0)