]> git.sesse.net Git - casparcg/commitdiff
* Created custom decklink allocator for reducing memory footprint.
authorHelge Norberg <helge.norberg@gmail.com>
Fri, 13 Sep 2013 15:06:32 +0000 (17:06 +0200)
committerHelge Norberg <helge.norberg@gmail.com>
Fri, 13 Sep 2013 15:06:32 +0000 (17:06 +0200)
* Made sure that more threads have the unstructured exception handler installed (avoids crashing the entire process in case of access violations), and thread naming for more threads.
* Ensure that if an exception occurs while rendering the diagnostic window, the window is closed instead of it stopping to respond to window events.

24 files changed:
common/concurrency/executor.h
common/diagnostics/graph.cpp
common/exception/win32_exception.cpp
common/exception/win32_exception.h
common/memory/page_locked_allocator.h
modules/decklink/consumer/blocking_decklink_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/decklink/decklink.vcxproj
modules/decklink/decklink.vcxproj.filters
modules/decklink/producer/decklink_producer.cpp
modules/decklink/util/decklink_allocator.h [new file with mode: 0644]
modules/decklink/util/util.h
modules/ffmpeg/ffmpeg.cpp
modules/flash/producer/FlashAxContainer.cpp
modules/image/consumer/image_consumer.cpp
modules/oal/consumer/oal_consumer.cpp
modules/ogl/consumer/ogl_consumer.cpp
modules/portaudio/consumer/portaudio_consumer.cpp
protocol/asio/io_service_manager.cpp
protocol/osc/client.cpp
protocol/util/Thread.cpp
protocol/util/Thread.h
shell/casparcg.config
shell/main.cpp

index 7cdc742d61c641fece644c8157a1a71d92f64666..27fd5caa70606e382eda80641e6e4e5526bbb5d1 100644 (file)
@@ -251,8 +251,8 @@ private:
 
        void run() // noexcept
        {
-               win32_exception::install_handler();             
-               detail::SetThreadName(GetCurrentThreadId(), name_.c_str());
+               win32_exception::ensure_handler_installed_for_thread(name_.c_str());
+
                while(is_running_)
                {
                        try
index 542008e3bc33fe3420a29428f4a958ae43dc30ed..3c7da27c3fc7512b5291c837b75b4bd7b52b0ee5 100644 (file)
@@ -140,10 +140,23 @@ private:
                                return;\r
                        }\r
                }               \r
-               glClear(GL_COLOR_BUFFER_BIT);\r
-               window_->Draw(*this);\r
-               window_->Display();\r
-               boost::this_thread::sleep(boost::posix_time::milliseconds(10));\r
+\r
+               try\r
+               {\r
+                       glClear(GL_COLOR_BUFFER_BIT);\r
+                       window_->Draw(*this);\r
+                       window_->Display();\r
+                       boost::this_thread::sleep(boost::posix_time::milliseconds(10));\r
+               }\r
+               catch (...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       CASPAR_LOG(error)\r
+                                       << L"Closing diag window due to error during rendering";\r
+                       window_.reset();\r
+                       return;\r
+               }\r
+\r
                executor_.begin_invoke([this]{tick();});\r
        }\r
 \r
index e0338c59258bb0630e05db01d28a863958aeb2b2..bd983c66dcc95322e90a99d320a3e61dd026a883 100644 (file)
 \r
 #include "../stdafx.h"\r
 \r
+#include <boost/thread.hpp>\r
+\r
 #include "win32_exception.h"\r
 \r
 #include "../log/log.h"\r
+#include "../concurrency/executor.h"\r
 \r
 namespace caspar {\r
 \r
+bool& installed_for_thread()\r
+{\r
+       static boost::thread_specific_ptr<bool> installed;\r
+\r
+       auto for_thread = installed.get();\r
+       \r
+       if (!for_thread)\r
+       {\r
+               for_thread = new bool(false);\r
+               installed.reset(for_thread);\r
+       }\r
+\r
+       return *for_thread;\r
+}\r
+\r
 void win32_exception::install_handler() \r
 {\r
 //#ifndef _DEBUG\r
        _set_se_translator(win32_exception::Handler);\r
+       installed_for_thread() = true;\r
 //#endif\r
 }\r
 \r
+void win32_exception::ensure_handler_installed_for_thread(\r
+               const char* thread_description)\r
+{\r
+       if (!installed_for_thread())\r
+       {\r
+               install_handler();\r
+\r
+               if (thread_description)\r
+                       detail::SetThreadName(GetCurrentThreadId(), thread_description);\r
+       }\r
+}\r
+\r
 void win32_exception::Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo) {\r
        switch(errorCode)\r
        {\r
index 8cfe515bd84951856e7c2136d36769f1f6ad250f..2f9c85964550726d523f9e9ac1c6e6e54466ed36 100644 (file)
@@ -35,6 +35,8 @@ class win32_exception : public std::exception
 public:\r
        typedef const void* address;\r
        static void install_handler();\r
+       static void ensure_handler_installed_for_thread(\r
+                       const char* thread_description = nullptr);\r
 \r
        address location() const { return location_; }\r
        unsigned int error_code() const { return errorCode_; }\r
index 44697f3a9ebed5638304d1dffa8c7e6ba2fd485a..789679d593b803d9c2789d21a698d4bce7f66150 100644 (file)
@@ -84,6 +84,8 @@ public:
        pointer           address(reference x) const { return &x; }\r
        const_pointer     address(const_reference x) const { return &x; }\r
        page_locked_allocator<T>&  operator=(const page_locked_allocator&) { return *this; }\r
+       bool                       operator!=(const page_locked_allocator&) const { return false; }\r
+       bool                       operator==(const page_locked_allocator&) const { return true; }\r
        void              construct(pointer p, const T& val) { new ((T*) p) T(val); }\r
        void              destroy(pointer p) { p->~T(); }\r
 \r
index 573c171b20114b3b6a872eb0454a3798dc84f858..b12ec63ca40c5c4f55964db951fdf91e2e558bc6 100644 (file)
@@ -24,6 +24,7 @@
 #include "decklink_consumer.h"
 
 #include "../util/util.h"
+#include "../util/decklink_allocator.h"
 
 #include "../interop/DeckLinkAPI_h.h"
 
@@ -59,6 +60,7 @@ struct blocking_decklink_consumer : boost::noncopyable
        const int                                                               channel_index_;
        const configuration                                             config_;
 
+       std::unique_ptr<thread_safe_decklink_allocator> allocator_;
        CComPtr<IDeckLink>                                              decklink_;
        CComQIPtr<IDeckLinkOutput>                              output_;
        CComQIPtr<IDeckLinkKeyer>                               keyer_;
@@ -142,6 +144,16 @@ public:
 
        void enable_video(BMDDisplayMode display_mode)
        {
+               if (config_.custom_allocator)
+               {
+                       allocator_.reset(new thread_safe_decklink_allocator(print()));
+
+                       if (FAILED(output_->SetVideoOutputFrameMemoryAllocator(allocator_.get())))
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not set custom memory allocator."));
+
+                       CASPAR_LOG(info) << print() << L" Using custom allocator.";
+               }
+
                if(FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) 
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video output."));
        }
index 11b6fd7f538c065c82e559f4af73be29e6ed6367..8b30bd2571e3f312a7a4a2087ff72839f402b2dc 100644 (file)
@@ -24,6 +24,7 @@
 #include "decklink_consumer.h"\r
 \r
 #include "../util/util.h"\r
+#include "../util/decklink_allocator.h"\r
 \r
 #include "../interop/DeckLinkAPI_h.h"\r
 \r
@@ -33,6 +34,7 @@
 #include <common/concurrency/future_util.h>\r
 #include <common/diagnostics/graph.h>\r
 #include <common/exception/exceptions.h>\r
+#include <common/exception/win32_exception.h>\r
 #include <common/utility/assert.h>\r
 \r
 #include <core/parameters/parameters.h>\r
 namespace caspar { namespace decklink { \r
 \r
 struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback, boost::noncopyable\r
-{              \r
+{\r
        const int                                                       channel_index_;\r
        const configuration                                     config_;\r
 \r
+       std::unique_ptr<thread_safe_decklink_allocator> allocator_;\r
        CComPtr<IDeckLink>                                      decklink_;\r
        CComQIPtr<IDeckLinkOutput>                      output_;\r
        CComQIPtr<IDeckLinkKeyer>                       keyer_;\r
@@ -172,6 +175,16 @@ public:
 \r
        void enable_video(BMDDisplayMode display_mode)\r
        {\r
+               if (config_.custom_allocator)\r
+               {\r
+                       allocator_.reset(new thread_safe_decklink_allocator(print()));\r
+\r
+                       if (FAILED(output_->SetVideoOutputFrameMemoryAllocator(allocator_.get())))\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not set custom memory allocator."));\r
+\r
+                       CASPAR_LOG(info) << print() << L" Using custom allocator.";\r
+               }\r
+\r
                if(FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) \r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video output."));\r
                \r
@@ -200,6 +213,7 @@ public:
 \r
        STDMETHOD(ScheduledFrameCompleted(IDeckLinkVideoFrame* completed_frame, BMDOutputFrameCompletionResult result))\r
        {\r
+               win32_exception::ensure_handler_installed_for_thread("decklink-ScheduledFrameCompleted");\r
                if(!is_running_)\r
                        return E_FAIL;\r
                \r
@@ -243,6 +257,8 @@ public:
                \r
        STDMETHOD(RenderAudioSamples(BOOL preroll))\r
        {\r
+               win32_exception::ensure_handler_installed_for_thread("decklink-RenderAudioSamples");\r
+\r
                if(!is_running_)\r
                        return E_FAIL;\r
                \r
@@ -510,10 +526,11 @@ safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::wptre
        else if(latency == L"normal")\r
                config.latency = configuration::normal_latency;\r
 \r
-       config.key_only                         = ptree.get(L"key-only",                config.key_only);\r
-       config.device_index                     = ptree.get(L"device",                  config.device_index);\r
-       config.embedded_audio           = ptree.get(L"embedded-audio",  config.embedded_audio);\r
-       config.base_buffer_depth        = ptree.get(L"buffer-depth",    config.base_buffer_depth);\r
+       config.key_only                         = ptree.get(L"key-only",                        config.key_only);\r
+       config.device_index                     = ptree.get(L"device",                          config.device_index);\r
+       config.embedded_audio           = ptree.get(L"embedded-audio",          config.embedded_audio);\r
+       config.base_buffer_depth        = ptree.get(L"buffer-depth",            config.base_buffer_depth);\r
+       config.custom_allocator         = ptree.get(L"custom-allocator",        config.custom_allocator);\r
        config.audio_layout =\r
                core::default_channel_layout_repository().get_by_name(\r
                                boost::to_upper_copy(ptree.get(L"channel-layout", L"STEREO")));\r
index 1b5f9e818d61876f5b6c99c33ecbf9e1b59e5473..7b93aaf92f1ebcbf2b10e605960d1c6a5e2cb549 100644 (file)
     <ClInclude Include="interop\DeckLinkAPI_h.h" />\r
     <ClInclude Include="producer\decklink_producer.h" />\r
     <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="util\decklink_allocator.h" />\r
     <ClInclude Include="util\util.h" />\r
   </ItemGroup>\r
   <ItemGroup>\r
index 709b5cd17bd7c881d050910fe52b49bf30a9b0dd..94c91b2ef22524b68f7328ffcbd0a18d193a09a1 100644 (file)
@@ -58,5 +58,8 @@
     <ClInclude Include="consumer\blocking_decklink_consumer.h">\r
       <Filter>source\consumer</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="util\decklink_allocator.h">\r
+      <Filter>source\util</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index d88834d329f65eb7e3fe2b302324144a29975c2a..02a98663d0f95970cd00c6cbeb790eca932c8f3a 100644 (file)
@@ -25,6 +25,7 @@
 \r
 #include "../interop/DeckLinkAPI_h.h"\r
 #include "../util/util.h"\r
+#include "../util/decklink_allocator.h"\r
 \r
 #include "../../ffmpeg/producer/filter/filter.h"\r
 #include "../../ffmpeg/producer/util/util.h"\r
@@ -34,6 +35,7 @@
 #include <common/concurrency/com_context.h>\r
 #include <common/diagnostics/graph.h>\r
 #include <common/exception/exceptions.h>\r
+#include <common/exception/win32_exception.h>\r
 #include <common/log/log.h>\r
 #include <common/memory/memclr.h>\r
 \r
@@ -86,6 +88,7 @@ class decklink_producer : boost::noncopyable, public IDeckLinkInputCallback
        boost::timer                                                                                            tick_timer_;\r
        boost::timer                                                                                            frame_timer_;\r
 \r
+       std::unique_ptr<thread_safe_decklink_allocator>                         allocator_;\r
        CComPtr<IDeckLink>                                                                                      decklink_;\r
        CComQIPtr<IDeckLinkInput>                                                                       input_;\r
        CComQIPtr<IDeckLinkAttributes >                                                         attributes_;\r
@@ -148,7 +151,14 @@ public:
                diagnostics::register_graph(graph_);\r
                \r
                auto display_mode = get_display_mode(input_, format_desc_.format, bmdFormat8BitYUV, bmdVideoInputFlagDefault);\r
-                               \r
+               \r
+               allocator_.reset(new thread_safe_decklink_allocator(print()));\r
+\r
+               if(FAILED(input_->SetVideoInputFrameMemoryAllocator(allocator_.get()))) \r
+                       BOOST_THROW_EXCEPTION(caspar_exception()\r
+                                                                       << msg_info(narrow(print()) + " Could not enable use of custom allocator.")\r
+                                                                       << boost::errinfo_api_function("SetVideoInputFrameMemoryAllocator"));\r
+\r
                // NOTE: bmdFormat8BitARGB is currently not supported by any decklink card. (2011-05-08)\r
                if(FAILED(input_->EnableVideoInput(display_mode, bmdFormat8BitYUV, bmdVideoInputFlagDefault))) \r
                        BOOST_THROW_EXCEPTION(caspar_exception() \r
@@ -191,6 +201,7 @@ public:
 \r
        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* video, IDeckLinkAudioInputPacket* audio)\r
        {       \r
+               win32_exception::ensure_handler_installed_for_thread("decklink-VideoInputFrameArrived");\r
                if(!video)\r
                        return S_OK;\r
 \r
diff --git a/modules/decklink/util/decklink_allocator.h b/modules/decklink/util/decklink_allocator.h
new file mode 100644 (file)
index 0000000..35cc488
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+* Copyright 2013 Sveriges Television AB http://casparcg.com/
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <stack>
+#include <map>
+
+#include <boost/thread.hpp>
+
+#include <tbb/concurrent_queue.h>
+#include <tbb/concurrent_unordered_map.h>
+#include <tbb/atomic.h>
+
+#include <common/utility/assert.h>
+//#include <common/memory/page_locked_allocator.h>
+#include <common/exception/win32_exception.h>
+
+#include "../interop/DeckLinkAPI_h.h"
+
+namespace caspar { namespace decklink {
+
+class thread_safe_decklink_allocator : public IDeckLinkMemoryAllocator
+{
+       typedef std::shared_ptr<
+                       std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>>> buffer;
+
+       std::wstring print_;
+       tbb::concurrent_unordered_map<size_t, tbb::concurrent_queue<void*>> free_;
+       tbb::concurrent_unordered_map<void*, buffer> buffers_;
+       tbb::atomic<size_t> total_allocated_;
+       tbb::atomic<int64_t> total_calls_;
+public:
+       thread_safe_decklink_allocator(const std::wstring& print)
+               : print_(print)
+       {
+               total_allocated_ = 0;
+               total_calls_ = 0;
+       }
+
+       ~thread_safe_decklink_allocator()
+       {
+               CASPAR_LOG(debug)
+                       << print_
+                       << L" allocated a total of " << total_allocated_ << L" bytes"
+                       << L" and was called " << total_calls_ << L" times"
+                       << L" during playout";
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE AllocateBuffer(
+                       unsigned long buffer_size, void** allocated_buffer)
+       {
+               win32_exception::ensure_handler_installed_for_thread(
+                               "decklink-allocator");
+
+               try
+               {
+                       *allocated_buffer = allocate_buffer(buffer_size);
+               }
+               catch (const std::bad_alloc&)
+               {
+                       CASPAR_LOG_CURRENT_EXCEPTION();
+
+                       return E_OUTOFMEMORY;
+               }
+
+               return S_OK;
+       }
+
+       void* allocate_buffer(unsigned long buffer_size)
+       {
+               ++total_calls_;
+               void* result;
+
+               if (!free_[buffer_size].try_pop(result))
+               {
+                       auto buf = std::make_shared<std::vector<uint8_t,
+                                       tbb::cache_aligned_allocator<uint8_t>>>(buffer_size);
+                       result = buf->data();
+                       buffers_.insert(std::make_pair(result, buf));
+
+                       total_allocated_ += buffer_size;
+
+                       CASPAR_LOG(debug)
+                                       << print_
+                                       << L" allocated buffer of size: " << buffer_size
+                                       << L" for a total of " << total_allocated_;
+               }
+
+               return result;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer(void* b)
+       {
+               win32_exception::ensure_handler_installed_for_thread(
+                               "decklink-allocator");
+
+               try
+               {
+                       release_buffer(b);
+               }
+               catch (const std::bad_alloc&)
+               {
+                       CASPAR_LOG_CURRENT_EXCEPTION();
+               }
+
+               return S_OK;
+       }
+
+       void release_buffer(void* b)
+       {
+               auto buf = buffers_[b];
+
+               CASPAR_VERIFY(buf);
+
+               free_[buf->size()].push(b);
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE Commit()
+       {
+               return S_OK;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE Decommit()
+       {
+               return S_OK;
+       }
+
+       STDMETHOD (QueryInterface(REFIID, LPVOID*))     {return E_NOINTERFACE;}
+       STDMETHOD_(ULONG, AddRef())                                     {return 1;}
+       STDMETHOD_(ULONG, Release())                            {return 1;}
+};
+
+}}
index 51865cb42128749767d6b7ca02bb58325c372b73..d4abe5cb66965188080b1fd1dcdfa0ef94aa996c 100644 (file)
@@ -317,6 +317,7 @@ struct configuration
        latency_t                               latency;\r
        bool                                    key_only;\r
        size_t                                  base_buffer_depth;\r
+       bool                                    custom_allocator;\r
        \r
        configuration()\r
                : device_index(1)\r
@@ -326,6 +327,7 @@ struct configuration
                , latency(default_latency)\r
                , key_only(false)\r
                , base_buffer_depth(3)\r
+               , custom_allocator(true)\r
        {\r
        }\r
        \r
index ad9a1becc134a7f4afc8454a789ade2283021b09..68f51c3c94f202d9a8098341442a843a59f61bd7 100644 (file)
@@ -25,6 +25,7 @@
 #include "producer/ffmpeg_producer.h"\r
 \r
 #include <common/log/log.h>\r
+#include <common/exception/win32_exception.h>\r
 \r
 #include <core/parameters/parameters.h>\r
 #include <core/consumer/frame_consumer.h>\r
@@ -55,6 +56,7 @@ namespace caspar { namespace ffmpeg {
        \r
 int ffmpeg_lock_callback(void **mutex, enum AVLockOp op) \r
 { \r
+       win32_exception::ensure_handler_installed_for_thread("ffmpeg-thread");\r
        if(!mutex)\r
                return 0;\r
 \r
@@ -193,6 +195,7 @@ std::shared_ptr<void> temporary_disable_logging_for_thread(bool disable)
 \r
 void log_for_thread(void* ptr, int level, const char* fmt, va_list vl)\r
 {\r
+       win32_exception::ensure_handler_installed_for_thread("ffmpeg-thread");\r
        //if (get_disable_logging_for_thread().get() == nullptr) // It does not matter what the value of the bool is\r
                log_callback(ptr, level, fmt, vl);\r
 }\r
index a08416ddcfc185cb2e8f74fab24106cefbaeefb2..40e35dcc69c9beb46e4b90327b04d576251b742a 100644 (file)
@@ -453,6 +453,7 @@ DEFINE_GUID2(IID_IDirectDraw7,0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,
 ///////////////////\r
 HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID riid, void** ppvObj) \r
 {\r
+       win32_exception::ensure_handler_installed_for_thread("flash-player-thread");\r
 //     ATLTRACE(_T("IServiceProvider::QueryService\n"));\r
        //the flashcontrol asks for an interface {618F8AD4-8B7A-11D0-8FCC-00C04FD9189D}, this is IID for a DirectDraw3 object\r
 \r
@@ -600,6 +601,7 @@ void FlashAxContainer::EnterFullscreen()
 \r
 void STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)\r
 {\r
+       win32_exception::ensure_handler_installed_for_thread("flash-player-thread");\r
        std::wstring str(request);\r
        if(str.find(TEXT("DisplayedTemplate")) != std::wstring::npos)\r
        {\r
index 21fdafb0db7601a0a793d4a81d70f06e6dc50fc8..7c9b8215ec95a6861b5f65f6a64b089d320e0c67 100644 (file)
@@ -21,6 +21,7 @@
 \r
 #include "image_consumer.h"\r
 \r
+#include <common/exception/win32_exception.h>\r
 #include <common/exception/exceptions.h>\r
 #include <common/env.h>\r
 #include <common/log/log.h>\r
@@ -90,6 +91,8 @@ public:
 \r
                boost::thread async([format_desc, frame, filename]\r
                {\r
+                       win32_exception::ensure_handler_installed_for_thread("image-consumer-thread");\r
+\r
                        try\r
                        {\r
                                auto filename2 = filename;\r
index 528176055b8bcfd933f62b2270a4a19b572a3ee3..629598c4b30dde44ca92c92b4040193cf5db9b9b 100644 (file)
@@ -29,6 +29,7 @@
 #include <common/utility/timer.h>
 #include <common/utility/string.h>
 #include <common/concurrency/future_util.h>
+#include <common/exception/win32_exception.h>
 
 #include <core/parameters/parameters.h>
 #include <core/consumer/frame_consumer.h>
@@ -205,7 +206,9 @@ public:
        // oal_consumer
        
        virtual bool OnGetData(sf::SoundStream::Chunk& data) override
-       {               
+       {
+               win32_exception::ensure_handler_installed_for_thread(
+                               "sfml-audio-thread");
                std::shared_ptr<std::vector<audio_buffer_16>> audio_data;               
 
                if (!input_.try_pop(audio_data))
index b4f950f7cd95038083b360cc37a2ada0d9a48181..8e727752721d587c4d31d197236f4e89a9cfbcb8 100644 (file)
@@ -33,6 +33,8 @@
 #include <common/utility/timer.h>\r
 #include <common/utility/string.h>\r
 #include <common/concurrency/future_util.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/exception/win32_exception.h>\r
 \r
 #include <ffmpeg/producer/filter/filter.h>\r
 \r
@@ -273,6 +275,9 @@ public:
 \r
        void run()\r
        {\r
+               win32_exception::ensure_handler_installed_for_thread(\r
+                               "ogl-consumer-thread");\r
+\r
                try\r
                {\r
                        init();\r
index 2708f12576b020afa56ab331949fce0f82e223ec..bbb645498b7702d5851fe87bc5f5f811e8728fa5 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <common/log/log.h>
 #include <common/exception/exceptions.h>
+#include <common/exception/win32_exception.h>
 #include <common/concurrency/future_util.h>
 #include <common/diagnostics/graph.h>
 
@@ -296,6 +297,8 @@ int callback(
                PaStreamCallbackFlags status_flags,
                void* user_data)
 {
+       win32_exception::ensure_handler_installed_for_thread(
+                       "portaudio-callback-thread");
        auto consumer = static_cast<portaudio_consumer*>(user_data);
 
        consumer->write_samples(
index 3261c1816a301488797333aac203b273c9df22a6..0845d8fb4ad0b625e218b29a70b3e64a623c44a1 100644 (file)
@@ -28,6 +28,8 @@
 #include <boost/asio/io_service.hpp>
 #include <boost/thread/thread.hpp>
 
+#include <common/exception/win32_exception.h>
+
 namespace caspar { namespace protocol { namespace asio {
 
 struct io_service_manager::impl
@@ -40,10 +42,17 @@ struct io_service_manager::impl
 
        impl()
                : work_(new boost::asio::io_service::work(service_))
-               , thread_(std::bind(&boost::asio::io_service::run, &service_))
+               , thread_([this] { run(); })
        {
        }
 
+       void run()
+       {
+               win32_exception::ensure_handler_installed_for_thread("asio-thread");
+
+               service_.run();
+       }
+
        ~impl()
        {
                work_.reset();
index 85723b706bb4d12b3f8784810d27c3440c816867..0077756fb210dafc46f7826f59840d2efa55aa03 100644 (file)
@@ -27,6 +27,7 @@
 #include "oscpack/oscOutboundPacketStream.h"
 
 #include <common/utility/string.h>
+#include <common/exception/win32_exception.h>
 
 #include <functional>
 #include <vector>
@@ -127,6 +128,7 @@ public:
        
        void on_next(const core::monitor::message& msg)
        {
+               win32_exception::ensure_handler_installed_for_thread("agents-thread");
                auto data_ptr = make_safe<std::vector<char>>(write_osc_event(msg));
 
                tbb::spin_mutex::scoped_lock lock(endpoints_mutex_);
index 39199f6d8b01da4ddd65addc8f3a2d12dbc33108..763f2bbc82ecb7a5691d78e01f8239b49052f7fc 100644 (file)
@@ -51,8 +51,6 @@ Event::~Event()
        CloseHandle(handle_);\r
 }\r
 \r
-bool Thread::static_bInstallWin32ExceptionHandler_ = true;\r
-\r
 Thread::Thread() : pRunnable_(0), hThread_(0), stopEvent_(TRUE, FALSE), timeout_(10000)  {\r
 }\r
 \r
@@ -108,15 +106,10 @@ bool Thread::Stop(bool bWait) {
        return returnValue;\r
 }\r
 \r
-void Thread::EnableWin32ExceptionHandler(bool bEnable) {\r
-       static_bInstallWin32ExceptionHandler_ = bEnable;\r
-}\r
-\r
 DWORD WINAPI Thread::ThreadEntrypoint(LPVOID pParam) {\r
        Thread* pThis = reinterpret_cast<Thread*>(pParam);\r
        \r
-       if(Thread::static_bInstallWin32ExceptionHandler_)\r
-               win32_exception::install_handler();\r
+       win32_exception::install_handler();\r
 \r
        _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);\r
 \r
index 46a00dbc7587d13bfbe795c5d376d4c0a7409313..caaef1946f9cff3b33c51b865926a5378402794c 100644 (file)
@@ -73,8 +73,6 @@ public:
 \r
        bool IsRunning();\r
 \r
-       static void EnableWin32ExceptionHandler(bool bEnable);\r
-\r
        void SetTimeout(DWORD timeout) {\r
                timeout_ = timeout;\r
        }\r
@@ -92,7 +90,6 @@ private:
        Event                   stopEvent_;\r
 \r
        DWORD                   timeout_;\r
-       static bool             static_bInstallWin32ExceptionHandler_;\r
 };\r
 \r
 }
\ No newline at end of file
index 5bb8f69440296f56e5deb786238421c7956f3365..6b6db1f837c329dc8b900d03a686a97747c95cd3 100644 (file)
@@ -73,6 +73,7 @@
                 <keyer>external [external|internal|default]</keyer>\r
                 <key-only>false [true|false]</key-only>\r
                 <buffer-depth>3 [1..]</buffer-depth>\r
+                <custom-allocator>true [true|false]</custom-allocator>\r
             </decklink>\r
             <blocking-decklink>\r
                 <device>[1..]</device>\r
@@ -80,6 +81,7 @@
                 <channel-layout>stereo [mono|stereo|dts|dolbye|dolbydigital|smpte|passthru]</channel-layout>\r
                 <keyer>external [external|internal|default]</keyer>\r
                 <key-only>false [true|false]</key-only>\r
+                <custom-allocator>true [true|false]</custom-allocator>\r
             </blocking-decklink>\r
             <bluefish>\r
                 <device>[1..]</device>\r
index 36721b83ee0809879773d68456849a0369b16f13..382e3c30797ad0c72378cc651d25877ae8e0f1cc 100644 (file)
@@ -211,7 +211,7 @@ int main(int argc, wchar_t* argv[])
        SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);\r
 \r
        // Install structured exception handler.\r
-       caspar::win32_exception::install_handler();\r
+       caspar::win32_exception::ensure_handler_installed_for_thread("main-thread");\r
                                \r
        // Increase time precision. This will increase accuracy of function like Sleep(1) from 10 ms to 1 ms.\r
        struct inc_prec\r
@@ -226,8 +226,7 @@ int main(int argc, wchar_t* argv[])
                tbb_thread_installer(){observe(true);}\r
                void on_scheduler_entry(bool is_worker)\r
                {\r
-                       //caspar::detail::SetThreadName(GetCurrentThreadId(), "tbb-worker-thread");\r
-                       caspar::win32_exception::install_handler();\r
+                       caspar::win32_exception::ensure_handler_installed_for_thread("tbb-worker-thread");\r
                }\r
        } tbb_thread_installer;\r
 \r
@@ -274,6 +273,8 @@ int main(int argc, wchar_t* argv[])
                        // anyway when the main thread terminates.\r
                        boost::thread stdin_thread([&caspar_server, &shutdown_server_now, &wait_for_keypress]\r
                        {\r
+                               caspar::win32_exception::ensure_handler_installed_for_thread("stdin-thread");\r
+\r
                                // Create a amcp parser for console commands.\r
                                caspar::protocol::amcp::AMCPProtocolStrategy amcp(\r
                                                caspar_server.get_channels(),\r