]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 31 Oct 2010 14:11:50 +0000 (14:11 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 31 Oct 2010 14:11:50 +0000 (14:11 +0000)
- Refactored out display_device from render_device.

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@190 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/core.vcxproj
core/core.vcxproj.filters
core/frame/gpu_frame_processor.cpp
core/frame/gpu_frame_processor.h
core/renderer/display_device.cpp [new file with mode: 0644]
core/renderer/display_device.h [new file with mode: 0644]
core/renderer/render_device.cpp

index 282d1c2b9280e7ac1c3aa9b8f3991bc962941289..7224fbc440742fe482fcc0c2b4168f1f11723d2f 100644 (file)
     <ClInclude Include="protocol\clk\CLKCommand.h" />\r
     <ClInclude Include="protocol\clk\CLKProtocolStrategy.h" />\r
     <ClInclude Include="protocol\media.h" />\r
+    <ClInclude Include="renderer\display_device.h" />\r
     <ClInclude Include="renderer\renderer_fwd.h" />\r
     <ClInclude Include="renderer\render_device.h" />\r
     <ClInclude Include="renderer\layer.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="renderer\display_device.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="renderer\render_device.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
index a931ae9d95e406f39f44fe52f2ed686df2f474b5..7808a90b92a75300607cb34e63da153f18b3a321 100644 (file)
     <ClInclude Include="frame\gpu_composite_frame.h">\r
       <Filter>Source\frame\gpu</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="renderer\display_device.h">\r
+      <Filter>Source\renderer</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="StdAfx.cpp">\r
     <ClCompile Include="frame\gpu_composite_frame.cpp">\r
       <Filter>Source\frame\gpu</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="renderer\display_device.cpp">\r
+      <Filter>Source\renderer</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Midl Include="consumer\decklink\DeckLinkAPI_v7_3.idl">\r
index 8309162f6dc71a36158cbbd9b17959822639327b..bdc3c04536534758d8fe3882bc964caaa161ab39 100644 (file)
@@ -93,6 +93,9 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                        output_frame_ = std::make_shared<gpu_frame>(format_desc_.width, format_desc_.height);\r
                        index_ = 0;\r
                });\r
+               composite(std::vector<gpu_frame_ptr>());\r
+               composite(std::vector<gpu_frame_ptr>());\r
+               composite(std::vector<gpu_frame_ptr>());\r
        }\r
 \r
        ~implementation()\r
@@ -128,7 +131,7 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                                                                \r
                                // 4. Output to external buffer\r
                                if(output_frame_->read_unlock())\r
-                                       output_signal_(output_frame_);\r
+                                       finished_frames_.push(output_frame_);\r
                \r
                                // 3. Draw to framebuffer and start asynchronous DMA transfer to page-locked memory                             \r
                                // Clear framebuffer\r
@@ -181,9 +184,9 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                });\r
        }\r
        \r
-       boost::signals2::connection subscribe(const std::function<void(const gpu_frame_ptr&)> func)\r
+       void pop(gpu_frame_ptr& frame)\r
        {\r
-               return output_signal_.connect(func);\r
+               finished_frames_.pop(frame);\r
        }\r
                        \r
        tbb::concurrent_unordered_map<size_t, tbb::concurrent_bounded_queue<gpu_frame_ptr>> reading_frame_pools_;\r
@@ -204,12 +207,12 @@ struct gpu_frame_processor::implementation : boost::noncopyable
        \r
        common::executor executor_;\r
 \r
-       boost::signals2::signal<void(const gpu_frame_ptr&)> output_signal_;     \r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> finished_frames_;  \r
 };\r
        \r
 gpu_frame_processor::gpu_frame_processor(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
 void gpu_frame_processor::push(const std::vector<gpu_frame_ptr>& frames){ impl_->composite(frames);}\r
-boost::signals2::connection gpu_frame_processor::subscribe(const std::function<void(const gpu_frame_ptr&)> func){return impl_->subscribe(func);}\r
+void gpu_frame_processor::pop(gpu_frame_ptr& frame){impl_->pop(frame);}\r
 gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height){return impl_->create_frame(width, height);}\r
 \r
 }}
\ No newline at end of file
index 55eb7f3f7c044b45b9cba8dc9b628b32a345d705..f9d4d0905498bcdf18915b54e41939c06b4d429a 100644 (file)
 #include "frame_fwd.h"\r
 #include "frame_factory.h"\r
 \r
-#include <boost/signals2/signal.hpp>\r
-\r
 namespace caspar { namespace core {\r
 \r
 class gpu_frame_processor : public frame_factory,  boost::noncopyable\r
 {\r
 public:\r
        gpu_frame_processor(const frame_format_desc& format_desc);\r
-\r
-       boost::signals2::connection subscribe(const std::function<void(const gpu_frame_ptr&)> func);\r
+               \r
        void push(const std::vector<gpu_frame_ptr>& frames);\r
+       void pop(gpu_frame_ptr& frame);\r
 \r
        gpu_frame_ptr create_frame(size_t width, size_t height);\r
 private:\r
diff --git a/core/renderer/display_device.cpp b/core/renderer/display_device.cpp
new file mode 100644 (file)
index 0000000..da4412a
--- /dev/null
@@ -0,0 +1,146 @@
+#include "../StdAfx.h"\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning (disable : 4244)\r
+#endif\r
+\r
+#include "display_device.h"\r
+\r
+#include "../frame/frame_format.h"\r
+#include "../frame/gpu_frame.h"\r
+\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/atomic.h>\r
+\r
+#include <boost/foreach.hpp>\r
+#include <boost/thread.hpp>\r
+\r
+#include <boost/date_time/posix_time/posix_time.hpp>\r
+\r
+#include <boost/range/algorithm_ext/erase.hpp>\r
+\r
+namespace caspar { namespace core { namespace renderer {\r
+\r
+class video_sync_clock\r
+{\r
+public:\r
+       video_sync_clock(const frame_format_desc& format_desc)\r
+       {\r
+               period_ = static_cast<long>(get_frame_format_period(format_desc)*1000000.0);\r
+               time_ = boost::posix_time::microsec_clock::local_time();\r
+       }\r
+\r
+       void synchronize()\r
+       {\r
+               auto remaining = boost::posix_time::microseconds(period_) - (boost::posix_time::microsec_clock::local_time() - time_);\r
+               if(remaining > boost::posix_time::microseconds(5000))\r
+                       boost::this_thread::sleep(remaining - boost::posix_time::microseconds(5000));\r
+               time_ = boost::posix_time::microsec_clock::local_time();\r
+       }\r
+private:\r
+       boost::posix_time::ptime time_;\r
+       long period_;\r
+};\r
+\r
+struct display_device::implementation\r
+{\r
+public:\r
+       implementation(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers) : consumers_(consumers), fmt_(format_desc)\r
+       {\r
+               if(consumers.empty())\r
+                       BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
+                                                                                                               << msg_info("display_device requires atleast one consumer"));\r
+\r
+               if(std::any_of(consumers.begin(), consumers.end(), [&](const frame_consumer_ptr& pConsumer){ return pConsumer->get_frame_format_desc() != format_desc;}))\r
+                       BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
+                                                                                                               << msg_info("All consumers must have same frameformat as display_device."));\r
+               \r
+               needs_clock_ = !std::any_of(consumers.begin(), consumers.end(), std::mem_fn(&frame_consumer::has_sync_clock));\r
+               frame_buffer_.set_capacity(3);\r
+               is_running_ = true;\r
+               display_thread_ = boost::thread([=]{run();});\r
+       }\r
+\r
+       ~implementation()\r
+       {\r
+               is_running_ = false;\r
+               frame_buffer_.clear();\r
+               display_thread_.join();\r
+       }\r
+\r
+       void display(const gpu_frame_ptr& frame)\r
+       {\r
+               if(is_running_)\r
+                       frame_buffer_.push(frame);\r
+       }\r
+                       \r
+       void run()\r
+       {\r
+               CASPAR_LOG(info) << L"Started display_device thread";\r
+               win32_exception::install_handler();\r
+                               \r
+               video_sync_clock clock(fmt_);\r
+                               \r
+               while(is_running_)\r
+               {\r
+                       if(needs_clock_)\r
+                               clock.synchronize();\r
+                       \r
+                       gpu_frame_ptr frame;\r
+                       if(!frame_buffer_.try_pop(frame))\r
+                       {\r
+                               CASPAR_LOG(trace) << "Display Buffer Underrun";\r
+                               frame_buffer_.pop(frame);\r
+                       }\r
+                       if(frame != nullptr)                    \r
+                               display_frame(frame);                   \r
+               }\r
+               \r
+               CASPAR_LOG(info) << L"Ended display_device thread";\r
+       }\r
+\r
+       void display_frame(const gpu_frame_ptr& frame)\r
+       {\r
+               BOOST_FOREACH(const frame_consumer_ptr& consumer, consumers_)\r
+               {\r
+                       try\r
+                       {\r
+                               consumer->prepare(frame); // Could block\r
+                               prepared_frames_.push_back(frame);\r
+\r
+                               if(prepared_frames_.size() > 2)\r
+                               {\r
+                                       consumer->display(prepared_frames_.front()); // Could block\r
+                                       prepared_frames_.pop_front();\r
+                               }\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               boost::range::remove_erase(consumers_, consumer);\r
+                               CASPAR_LOG(warning) << "Removed consumer from render-device.";\r
+                               if(consumers_.empty())\r
+                               {\r
+                                       CASPAR_LOG(warning) << "No consumers available. Shutting down display-device.";\r
+                                       is_running_ = false;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       std::deque<gpu_frame_ptr> prepared_frames_;\r
+               \r
+       boost::thread display_thread_;\r
+\r
+       tbb::atomic<bool> is_running_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> frame_buffer_;\r
+\r
+       bool needs_clock_;\r
+       std::vector<frame_consumer_ptr> consumers_;\r
+\r
+       frame_format_desc fmt_;\r
+};\r
+\r
+display_device::display_device(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers) : impl_(new implementation(format_desc, consumers)){}\r
+void display_device::display(const gpu_frame_ptr& frame){impl_->display(frame);}\r
+}}}
\ No newline at end of file
diff --git a/core/renderer/display_device.h b/core/renderer/display_device.h
new file mode 100644 (file)
index 0000000..1f5afce
--- /dev/null
@@ -0,0 +1,21 @@
+#pragma once\r
+\r
+#include "../frame/frame_fwd.h"\r
+#include "../consumer/frame_consumer.h"\r
+\r
+#include <vector>\r
+\r
+namespace caspar { namespace core { namespace renderer {\r
+\r
+class display_device\r
+{\r
+public:\r
+       display_device(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers);\r
+       void display(const gpu_frame_ptr& frame);\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<display_device> display_device_ptr;\r
+\r
+}}}
\ No newline at end of file
index ebbfdc32345fa580159f93da66379baf1a93008f..c7ed28ecf0e5fad8d6ec6a5be324a3cf447cc9ab 100644 (file)
@@ -5,9 +5,9 @@
 #endif\r
 \r
 #include "render_device.h"\r
-#include "layer.h"\r
 \r
-#include "../consumer/frame_consumer.h"\r
+#include "display_device.h"\r
+#include "layer.h"\r
 \r
 #include "../frame/frame_format.h"\r
 #include "../frame/gpu_frame_processor.h"\r
 #include "../../common/utility/scope_exit.h"\r
 #include "../../common/utility/memory.h"\r
 \r
-#include <numeric>\r
-\r
-#include <boost/filesystem.hpp>\r
 #include <boost/thread.hpp>\r
-#include <boost/date_time/posix_time/posix_time.hpp>\r
-#include <boost/range/algorithm.hpp>\r
 #include <boost/range/algorithm_ext/erase.hpp>\r
-#include <boost/range/sub_range.hpp>\r
-#include <boost/range/adaptor/indirected.hpp>\r
 #include <boost/foreach.hpp>\r
 \r
 #include <tbb/parallel_for.h>\r
 #include <tbb/mutex.h>\r
-\r
-using namespace boost::assign;\r
        \r
 namespace caspar { namespace core { namespace renderer {\r
        \r
@@ -42,51 +33,32 @@ std::vector<gpu_frame_ptr> render_frames(std::map<int, layer>& layers)
                std::advance(it, r.begin());\r
                for(size_t i = r.begin(); i != r.end(); ++i, ++it)\r
                        frames[i] = it->second.get_frame();\r
-       });                                     \r
+       });             \r
        return frames;\r
 }\r
 \r
 struct render_device::implementation : boost::noncopyable\r
 {      \r
        implementation(const frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers)  \r
-               : consumers_(consumers), fmt_(format_desc), frame_processor_(new gpu_frame_processor(format_desc)), needs_clock_(false)\r
+               : display_device_(new display_device(format_desc, consumers)), fmt_(format_desc), frame_processor_(new gpu_frame_processor(format_desc))\r
        {       \r
                is_running_ = true;\r
-               if(consumers.empty())\r
-                       BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
-                                                                                                               << msg_info("render_device requires atleast one consumer"));\r
-\r
-               if(std::any_of(consumers.begin(), consumers.end(), [&](const frame_consumer_ptr& pConsumer){ return pConsumer->get_frame_format_desc() != format_desc;}))\r
-                       BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
-                                                                                                               << msg_info("All consumers must have same frameformat as renderdevice."));\r
                \r
-               needs_clock_ = !std::any_of(consumers.begin(), consumers.end(), std::mem_fn(&frame_consumer::has_sync_clock));\r
-\r
-               processor_connection_ = frame_processor_->subscribe([=](const gpu_frame_ptr& frame)\r
-               {\r
-                       frame_buffer_.push(std::move(frame));\r
-               });\r
-\r
-               frame_buffer_.set_capacity(3);\r
-               display_thread_ = boost::thread([=]{display();});\r
-               render_thread_ = boost::thread([=]{render();});\r
+               render_thread_ = boost::thread([=]{run();});\r
 \r
                CASPAR_LOG(info) << L"Initialized render_device with " << format_desc;\r
        }\r
                        \r
        ~implementation()\r
        {\r
-               processor_connection_.disconnect();\r
                is_running_ = false;\r
-               frame_buffer_.clear();\r
-               frame_buffer_.push(nullptr);\r
+               display_device_.reset();\r
                render_thread_.join();\r
-               display_thread_.join();\r
        }\r
                \r
-       void render()\r
+       void run()\r
        {               \r
-               CASPAR_LOG(info) << L"Started render_device::render thread";\r
+               CASPAR_LOG(info) << L"Started render_device thread";\r
                win32_exception::install_handler();\r
                \r
                while(is_running_)\r
@@ -94,13 +66,15 @@ struct render_device::implementation : boost::noncopyable
                        try\r
                        {       \r
                                std::vector<gpu_frame_ptr> next_frames;\r
-                               gpu_frame_ptr composite_frame;          \r
-\r
                                {\r
                                        tbb::mutex::scoped_lock lock(layers_mutex_);    \r
                                        next_frames = render_frames(layers_);\r
                                }\r
                                frame_processor_->push(next_frames);\r
+                                                               \r
+                               gpu_frame_ptr frame;            \r
+                               frame_processor_->pop(frame);\r
+                               display_device_->display(frame);\r
                        }\r
                        catch(...)\r
                        {\r
@@ -110,85 +84,9 @@ struct render_device::implementation : boost::noncopyable
                        }\r
                }\r
 \r
-               CASPAR_LOG(info) << L"Ended render_device::render thread";\r
+               CASPAR_LOG(info) << L"Ended render_device thread";\r
        }\r
-       \r
-       struct video_sync_clock\r
-       {\r
-               video_sync_clock(const frame_format_desc& format_desc)\r
-               {\r
-                       period_ = static_cast<long>(get_frame_format_period(format_desc)*1000000.0);\r
-                       time_ = boost::posix_time::microsec_clock::local_time();\r
-               }\r
 \r
-               void sync_video()\r
-               {\r
-                       auto remaining = boost::posix_time::microseconds(period_) - (boost::posix_time::microsec_clock::local_time() - time_);\r
-                       if(remaining > boost::posix_time::microseconds(5000))\r
-                               boost::this_thread::sleep(remaining - boost::posix_time::microseconds(5000));\r
-                       time_ = boost::posix_time::microsec_clock::local_time();\r
-               }\r
-\r
-               boost::posix_time::ptime time_;\r
-               long period_;\r
-\r
-       };\r
-       \r
-       void display()\r
-       {\r
-               CASPAR_LOG(info) << L"Started render_device::display thread";\r
-               win32_exception::install_handler();\r
-                               \r
-               gpu_frame_ptr frame = frame_processor_->create_frame(fmt_.width, fmt_.height);\r
-               common::clear(frame->data(), frame->size());\r
-               std::deque<gpu_frame_ptr> prepared(3, frame);\r
-\r
-               video_sync_clock clock(fmt_);\r
-                               \r
-               while(is_running_)\r
-               {\r
-                       if(needs_clock_)\r
-                               clock.sync_video();\r
-\r
-                       if(!frame_buffer_.try_pop(frame))\r
-                       {\r
-                               CASPAR_LOG(trace) << "Display Buffer Underrun";\r
-                               frame_buffer_.pop(frame);\r
-                       }\r
-                       if(frame != nullptr)\r
-                       {\r
-                               display_frame(prepared.front(), frame);\r
-                               prepared.push_back(frame);\r
-                               prepared.pop_front();\r
-                       }\r
-               }\r
-               \r
-               CASPAR_LOG(info) << L"Ended render_device::display thread";\r
-       }\r
-\r
-       void display_frame(const gpu_frame_ptr& prepared_frame, const gpu_frame_ptr& next_frame)\r
-       {\r
-               BOOST_FOREACH(const frame_consumer_ptr& consumer, consumers_)\r
-               {\r
-                       try\r
-                       {\r
-                               consumer->prepare(next_frame); // Could block\r
-                               consumer->display(prepared_frame); // Could block\r
-                       }\r
-                       catch(...)\r
-                       {\r
-                               CASPAR_LOG_CURRENT_EXCEPTION();\r
-                               boost::range::remove_erase(consumers_, consumer);\r
-                               CASPAR_LOG(warning) << "Removed consumer from render-device.";\r
-                               if(consumers_.empty())\r
-                               {\r
-                                       CASPAR_LOG(warning) << "No consumers available. Shutting down render-device.";\r
-                                       is_running_ = false;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-               \r
        void load(int exLayer, const frame_producer_ptr& producer, load_option option)\r
        {\r
                if(producer->get_frame_format_desc() != fmt_)\r
@@ -251,24 +149,17 @@ struct render_device::implementation : boost::noncopyable
                return it != layers_.end() ? it->second.background() : nullptr;\r
        }\r
                        \r
+       display_device_ptr display_device_;\r
        boost::thread render_thread_;\r
-       boost::thread display_thread_;\r
                \r
        frame_format_desc fmt_;\r
-       tbb::concurrent_bounded_queue<gpu_frame_ptr> frame_buffer_;\r
-       \r
-       std::vector<frame_consumer_ptr> consumers_;\r
-       \r
+                       \r
        mutable tbb::mutex layers_mutex_;\r
        std::map<int, layer> layers_;\r
        \r
        tbb::atomic<bool> is_running_;  \r
 \r
        gpu_frame_processor_ptr frame_processor_;\r
-\r
-       bool needs_clock_;\r
-\r
-       boost::signals2::scoped_connection processor_connection_;\r
 };\r
 \r
 render_device::render_device(const frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers) \r