]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: Further diagnostics improvements.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 2 Feb 2011 10:41:33 +0000 (10:41 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 2 Feb 2011 10:41:33 +0000 (10:41 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@442 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

14 files changed:
common/common.vcxproj
common/common.vcxproj.filters
common/concurrency/executor.h
common/diagnostics/graph.cpp
common/diagnostics/graph.h
common/log/log.cpp
core/consumer/bluefish/bluefish_consumer.cpp
core/consumer/frame_consumer_device.cpp
core/consumer/oal/oal_consumer.cpp
core/consumer/ogl/ogl_consumer.cpp
core/producer/ffmpeg/input.cpp
core/producer/flash/flash_producer.cpp
mixer/frame_mixer_device.cpp
shell/caspar.config

index e3dfb72d24cc8d253a16317c7a829843d38ac65a..90d6ab280fd73a3884287dc1f05fb406666f7b1f 100644 (file)
   <ItemGroup>\r
     <ClInclude Include="compiler\vs\disable_silly_warnings.h" />\r
     <ClInclude Include="concurrency\executor.h" />\r
+    <ClInclude Include="diagnostics\context.h" />\r
     <ClInclude Include="diagnostics\graph.h" />\r
+    <ClInclude Include="diagnostics\sink_backend.h" />\r
     <ClInclude Include="exception\exceptions.h" />\r
     <ClInclude Include="exception\win32_exception.h" />\r
     <ClInclude Include="gl\gl_check.h" />\r
     <ClInclude Include="utility\timer.h" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="diagnostics\context.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="diagnostics\graph.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="diagnostics\sink_backend.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="exception\win32_exception.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
index 658daa79cbb19c96824559812eff5c130274fa46..9c9cca0a24366b53cfb0bb8fc8e74b4815e43c57 100644 (file)
     <ClCompile Include="diagnostics\graph.cpp">\r
       <Filter>Source\diagnostics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="diagnostics\context.cpp">\r
+      <Filter>Source\diagnostics</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="diagnostics\sink_backend.cpp">\r
+      <Filter>Source\log</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="exception\exceptions.h">\r
     <ClInclude Include="diagnostics\graph.h">\r
       <Filter>Source\diagnostics</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="diagnostics\context.h">\r
+      <Filter>Source\diagnostics</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="diagnostics\sink_backend.h">\r
+      <Filter>Source\log</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 0603449fb1ebed5e000ad334e01d975a7e2e78cc..6d79d151777a7382b0b3f685dff27626ac91ced5 100644 (file)
 \r
 namespace caspar {\r
 \r
+namespace detail {\r
+\r
+typedef struct tagTHREADNAME_INFO\r
+{\r
+       DWORD dwType; // must be 0x1000\r
+       LPCSTR szName; // pointer to name (in user addr space)\r
+       DWORD dwThreadID; // thread ID (-1=caller thread)\r
+       DWORD dwFlags; // reserved for future use, must be zero\r
+} THREADNAME_INFO;\r
+\r
+inline void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)\r
+{\r
+       THREADNAME_INFO info;\r
+       {\r
+               info.dwType = 0x1000;\r
+               info.szName = szThreadName;\r
+               info.dwThreadID = dwThreadID;\r
+               info.dwFlags = 0;\r
+       }\r
+       __try\r
+       {\r
+               RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );\r
+       }\r
+       __except (EXCEPTION_CONTINUE_EXECUTION)\r
+       {\r
+       }       \r
+}\r
+\r
+}\r
+\r
 class executor : boost::noncopyable\r
 {\r
 public:\r
                \r
-       explicit executor(const std::function<void()>& f = nullptr)\r
+       explicit executor(const std::wstring& name = L"executor") : name_(narrow(name))\r
        {\r
                is_running_ = false;\r
-               f_ = f != nullptr ? f : [this]{run();};\r
        }\r
-\r
+       \r
        virtual ~executor()\r
        {\r
                stop();\r
+               clear();\r
                if(boost::this_thread::get_id() != thread_.get_id())\r
                        thread_.join();\r
        }\r
@@ -41,7 +71,7 @@ public:
                if(is_running_.fetch_and_store(true))\r
                        return;\r
                clear();\r
-               thread_ = boost::thread(f_);\r
+               thread_ = boost::thread([this]{run();});\r
        }\r
                        \r
        void stop() // noexcept\r
@@ -130,12 +160,13 @@ private:
 \r
        void run() // noexcept\r
        {\r
-               win32_exception::install_handler();\r
+               win32_exception::install_handler();             \r
+               detail::SetThreadName(GetCurrentThreadId(), name_.c_str());\r
                while(is_running_)\r
                        execute();\r
        }\r
        \r
-       std::function<void()> f_;\r
+       std::string name_;\r
        boost::thread thread_;\r
        tbb::atomic<bool> is_running_;\r
        tbb::concurrent_bounded_queue<std::function<void()>> execution_queue_;\r
index 67e122a2fefa942e566a84e6d687b48e6436f67a..a9d5937cb5617ff3adab6336bf4f89d59d4ba74e 100644 (file)
@@ -1,6 +1,7 @@
 #include "../stdafx.h"\r
 \r
 #include "graph.h"\r
+#include "context.h"\r
 \r
 #pragma warning (disable : 4244)\r
 \r
 \r
 namespace caspar { namespace diagnostics {\r
 \r
-struct drawable : public sf::Drawable\r
-{\r
-       virtual ~drawable(){}\r
-       virtual void render(sf::RenderTarget& target) = 0;\r
-       virtual void Render(sf::RenderTarget& target) const { const_cast<drawable*>(this)->render(target);}\r
-};\r
-\r
-class context : public drawable\r
-{      \r
-       timer timer_;\r
-       sf::RenderWindow window_;\r
-       \r
-       std::list<std::shared_ptr<drawable>> drawables_;\r
-       std::map<size_t, sf::Font> fonts_;\r
-               \r
-       executor executor_;\r
-public:                                        \r
-\r
-       template<typename Func>\r
-       static auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
-       {       \r
-               return get_instance().executor_.begin_invoke(std::forward<Func>(func)); \r
-       }\r
-\r
-       static void register_drawable(const std::shared_ptr<drawable>& drawable)\r
-       {\r
-               begin_invoke([=]\r
-               {\r
-                       get_instance().drawables_.push_back(drawable);\r
-               });\r
-       }\r
-                       \r
-private:\r
-\r
-       void tick()\r
-       {\r
-               sf::Event e;\r
-               while(window_.GetEvent(e)){}            \r
-               glClear(GL_COLOR_BUFFER_BIT);\r
-               window_.Draw(*this);\r
-               window_.Display();\r
-               timer_.tick(1.0/50.0);\r
-               executor_.begin_invoke([this]{tick();});\r
-       }\r
-\r
-       void render(sf::RenderTarget& target)\r
-       {\r
-               auto count = std::max<size_t>(5, drawables_.size());\r
-\r
-               int n = 0;\r
-               for(auto it = drawables_.begin(); it != drawables_.end(); ++n)\r
-               {\r
-                       auto& drawable = *it;\r
-                       if(!drawable.unique())\r
-                       {\r
-                               drawable->SetScale(window_.GetWidth(), window_.GetHeight()/count);\r
-                               drawable->SetPosition(0.0f, n* window_.GetHeight()/count);\r
-                               target.Draw(*drawable);                         \r
-                               ++it;           \r
-                       }\r
-                       else                    \r
-                               it = drawables_.erase(it);                      \r
-               }               \r
-       }       \r
-       \r
-       static context& get_instance()\r
-       {\r
-               static context impl;\r
-               return impl;\r
-       }\r
-\r
-       context()\r
-       {\r
-               executor_.start();\r
-               executor_.begin_invoke([this]\r
-               {\r
-                       window_.Create(sf::VideoMode(600, 1000), "CasparCG Diagnostics");\r
-                       window_.SetPosition(0, 0);\r
-                       window_.SetActive();\r
-                       glEnable(GL_BLEND);\r
-                       glEnable(GL_LINE_SMOOTH);\r
-                       glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\r
-                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
-                       tick();\r
-               });\r
-       }\r
-};\r
-       \r
 class guide : public drawable\r
 {\r
        float value_;\r
@@ -139,18 +52,29 @@ public:
 class line : public drawable\r
 {\r
        boost::optional<diagnostics::guide> guide_;\r
-       boost::circular_buffer<float> line_data_;\r
-       std::vector<float> tick_data_;\r
+       boost::circular_buffer<std::pair<float, bool>> line_data_;\r
+\r
+       std::vector<float>              tick_data_;\r
+       bool                                    tick_tag_;\r
        color c_;\r
 public:\r
        line(size_t res = 600)\r
                : line_data_(res)\r
-               , c_(1.0f, 1.0f, 1.0f){}\r
+               , tick_tag_(false)\r
+               , c_(1.0f, 1.0f, 1.0f)\r
+       {\r
+               line_data_.push_back(std::make_pair(-1.0f, false));\r
+       }\r
        \r
        void update(float value)\r
        {\r
                tick_data_.push_back(value);\r
        }\r
+       \r
+       void tag()\r
+       {\r
+               tick_tag_ = true;\r
+       }\r
 \r
        void guide(const guide& guide)\r
        {\r
@@ -175,22 +99,39 @@ public:
                if(!tick_data_.empty())\r
                {\r
                        float sum = std::accumulate(tick_data_.begin(), tick_data_.end(), 0.0) + std::numeric_limits<float>::min();\r
-                       line_data_.push_back(static_cast<float>(sum)/static_cast<float>(tick_data_.size()));\r
+                       line_data_.push_back(std::make_pair(static_cast<float>(sum)/static_cast<float>(tick_data_.size()), tick_tag_));\r
                        tick_data_.clear();\r
                }\r
                else if(!line_data_.empty())\r
                {\r
-                       line_data_.push_back(line_data_.back());\r
+                       line_data_.push_back(std::make_pair(line_data_.back().first, tick_tag_));\r
                }\r
+               tick_tag_ = false;\r
 \r
                if(guide_)\r
                        target.Draw(*guide_);\r
                \r
                glBegin(GL_LINE_STRIP);\r
                glColor4f(c_.red, c_.green, c_.blue, 1.0f);             \r
-               for(size_t n = 0; n < line_data_.size(); ++n)                           \r
-                       glVertex3f(x+n*dx, std::max(0.05f, std::min(0.95f, (1.0f-line_data_[n])*0.8f + 0.1f)), 0.0f);           \r
+               for(size_t n = 0; n < line_data_.size(); ++n)           \r
+                       if(line_data_[n].first > -0.5)\r
+                               glVertex3f(x+n*dx, std::max(0.05f, std::min(0.95f, (1.0f-line_data_[n].first)*0.8f + 0.1f)), 0.0f);             \r
                glEnd();\r
+                               \r
+               glEnable(GL_LINE_STIPPLE);\r
+               glLineStipple(3, 0xAAAA);\r
+               for(size_t n = 0; n < line_data_.size(); ++n)   \r
+               {\r
+                       if(line_data_[n].second)\r
+                       {\r
+                               glBegin(GL_LINE_STRIP);\r
+                               glColor4f(c_.red, c_.green, c_.blue, c_.alpha);                                 \r
+                                       glVertex3f(x+n*dx, 0.0f, 0.0f);                         \r
+                                       glVertex3f(x+n*dx, 1.0f, 0.0f);         \r
+                               glEnd();\r
+                       }\r
+               }\r
+               glDisable(GL_LINE_STIPPLE);\r
        }\r
 };\r
 \r
@@ -209,6 +150,14 @@ struct graph::implementation : public drawable
                });\r
        }\r
 \r
+       void tag(const std::string& name)\r
+       {\r
+               context::begin_invoke([=]\r
+               {\r
+                       lines_[name].tag();\r
+               });\r
+       }\r
+\r
        void set_color(const std::string& name, color c)\r
        {\r
                context::begin_invoke([=]\r
@@ -283,7 +232,9 @@ graph::graph(const std::string& name) : impl_(new implementation(name))
 {\r
        context::register_drawable(impl_);\r
 }\r
+\r
 void graph::update(const std::string& name, float value){impl_->update(name, value);}\r
+void graph::tag(const std::string& name){impl_->tag(name);}\r
 void graph::guide(const std::string& name, float value){impl_->guide(name, value);}\r
 void graph::set_color(const std::string& name, color c){impl_->set_color(name, c);}\r
 \r
index f9e5f31d983c05e2ee72964600d82b0b787ad33f..26c10d1fc9f852b434998fcd22b7018925bb1a6a 100644 (file)
@@ -26,6 +26,7 @@ class graph
        graph(const std::string& name);\r
 public:\r
        void update(const std::string& name, float value);\r
+       void tag(const std::string& name);\r
        void guide(const std::string& name, float value);\r
        void set_color(const std::string& name, color c);\r
 private:\r
index 0ac0278c16a1a53cc83311d2f8bda7024259a7cb..5ee9065f3870e87799090d8c911381c3f547954b 100644 (file)
@@ -8,6 +8,7 @@
 #include "log.h"\r
 \r
 #include "../exception/exceptions.h"\r
+#include "../diagnostics/sink_backend.h"\r
 \r
 #include <ios>\r
 #include <string>\r
@@ -53,12 +54,9 @@ void init()
 \r
        typedef boost::log::sinks::synchronous_sink<boost::log::sinks::wtext_file_backend> file_sink_type;\r
 \r
-       typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::wtext_ostream_backend> stream_sink_type;\r
-\r
-       auto stream_backend = boost::make_shared<boost::log::sinks::wtext_ostream_backend>();\r
-       stream_backend->add_stream(boost::shared_ptr<std::wostream>(&std::wcout, boost::log::empty_deleter()));\r
-       stream_backend->auto_flush(true);\r
+       typedef boost::log::sinks::asynchronous_sink<diagnostics::sink_backend> stream_sink_type;\r
 \r
+       auto stream_backend = boost::make_shared<diagnostics::sink_backend>();\r
        auto stream_sink = boost::make_shared<stream_sink_type>(stream_backend);\r
 \r
        stream_sink->locked_backend()->set_formatter(\r
@@ -86,7 +84,7 @@ void add_file_sink(const std::wstring& folder)
                        BOOST_THROW_EXCEPTION(directory_not_found());\r
 \r
                auto file_sink = boost::make_shared<file_sink_type>(\r
-                       boost::log::keywords::file_name = (folder + L"caspar_%Y-%m-%d_%H-%M-%S.%N.log"),\r
+                       boost::log::keywords::file_name = (folder + L"%Y-%m-%d_%H-%M-%S.%N.log"),\r
                        boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),\r
                        boost::log::keywords::auto_flush = true\r
                );\r
index 8b46919d75805d86628e066d80f5f4b799c4527a..705e81fa82711b70e07d2b357f116c054d57de43 100644 (file)
@@ -105,7 +105,7 @@ struct bluefish_consumer::implementation : boost::noncopyable
        executor executor_;\r
 public:\r
        implementation::implementation(unsigned int device_index, bool embed_audio) \r
-               : graph_(diagnostics::create_graph("bluefish[" + boost::lexical_cast<std::string>(device_index) + "]"))\r
+               : graph_(diagnostics::create_graph("blue[" + boost::lexical_cast<std::string>(device_index) + "]"))\r
                , device_index_(device_index)           \r
                , mem_fmt_(MEM_FMT_ARGB_PC)\r
                , upd_fmt_(UPD_FMT_FRAME)\r
index eb823192e754b41981695cf35cbad22dbfded0f3..3ca5896232889592e30c2dfa59fd13bae60b01d8 100644 (file)
 namespace caspar { namespace core {\r
        \r
 struct frame_consumer_device::implementation\r
-{\r
-       safe_ptr<diagnostics::graph> graph_;\r
-       timer perf_timer_;\r
-       \r
+{      \r
        timer clock_;\r
 \r
        boost::circular_buffer<safe_ptr<const read_frame>> buffer_;\r
@@ -35,11 +32,9 @@ struct frame_consumer_device::implementation
        executor executor_;     \r
 public:\r
        implementation(const video_format_desc& format_desc) \r
-               : graph_(diagnostics::create_graph("output"))\r
-               , format_desc_(format_desc)\r
+               : format_desc_(format_desc)\r
+               , executor_(L"frame_consumer_device")\r
        {               \r
-               graph_->guide("frame-time", 0.5f);      \r
-               graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
                executor_.set_capacity(2);\r
                executor_.start();\r
        }\r
@@ -97,9 +92,6 @@ public:
                        }\r
 \r
                        clock_.tick(1.0/format_desc_.fps);\r
-                       \r
-                       graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
-                       perf_timer_.reset();\r
                });\r
        }\r
 };\r
index 8d07d58a0257c6f0576f0cf5929e8d3ae56cbc80..70e767763198c5f5224ae42206e59bac22fb05e4 100644 (file)
@@ -46,7 +46,7 @@ struct oal_consumer::implementation : public sf::SoundStream, boost::noncopyable
        video_format_desc format_desc_;\r
 public:\r
        implementation() \r
-               : graph_(diagnostics::create_graph("audio"))\r
+               : graph_(diagnostics::create_graph("oal"))\r
                , container_(5)\r
        {\r
                graph_->guide("frame-time", 0.5);\r
index 726b75cf628bed7cc19fe6f98abbb720046487ed..ea1af91c78ae66340956c5308eeac9540bc0b281 100644 (file)
@@ -79,7 +79,7 @@ public:
                , screen_x_(0)\r
                , screen_y_(0)\r
                , screen_index_(screen_index)\r
-               , graph_(diagnostics::create_graph("screen[" + boost::lexical_cast<std::string>(screen_index) + "]"))\r
+               , graph_(diagnostics::create_graph("ogl[" + boost::lexical_cast<std::string>(screen_index) + "]"))\r
        {               \r
                graph_->guide("frame-time", 0.5);\r
                graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
index 83bbaac09fa5e53d7ad98b8041a498c5876bf8ee..45c52d2149c7307e833b835d9d2a2c12c0441743 100644 (file)
@@ -12,6 +12,7 @@
 \r
 #include <boost/exception/error_info.hpp>\r
 #include <boost/thread/once.hpp>\r
+#include <boost/thread/thread.hpp>\r
 \r
 #include <errno.h>\r
 #include <system_error>\r
@@ -31,7 +32,7 @@ namespace caspar { namespace core { namespace ffmpeg{
                \r
 struct input::implementation : boost::noncopyable\r
 {              \r
-       static const size_t BUFFER_SIZE = 2 << 24;\r
+       static const size_t PACKET_BUFFER_COUNT = 50;\r
 \r
        safe_ptr<diagnostics::graph> graph_;\r
 \r
@@ -45,11 +46,12 @@ struct input::implementation : boost::noncopyable
        bool loop_;\r
        int video_s_index_;\r
        int     audio_s_index_;\r
-\r
-       tbb::atomic<size_t>     buffer_size_;\r
-       \r
+               \r
        tbb::concurrent_bounded_queue<std::shared_ptr<aligned_buffer>> video_packet_buffer_;\r
        tbb::concurrent_bounded_queue<std::shared_ptr<aligned_buffer>> audio_packet_buffer_;\r
+\r
+       boost::condition_variable cond_;\r
+       boost::mutex mutex_;\r
        \r
        executor executor_;\r
 public:\r
@@ -59,8 +61,11 @@ public:
                , video_s_index_(-1)\r
                , audio_s_index_(-1)\r
                , filename_(filename)\r
+               , executor_(print())\r
        {                       \r
-               graph_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f));        \r
+               graph_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f));\r
+               graph_->set_color("stop", diagnostics::color(1.0f, 0.5f, 0.5f));\r
+               graph_->set_color("seek", diagnostics::color(0.5f, 1.0f, 0.5f));        \r
 \r
                int errn;\r
                AVFormatContext* weak_format_context_;\r
@@ -99,6 +104,9 @@ public:
 \r
        ~implementation()\r
        {\r
+               video_packet_buffer_.clear();\r
+               audio_packet_buffer_.clear();\r
+               cond_.notify_all();\r
                executor_.clear();\r
                CASPAR_LOG(info) << print() << " ended.";\r
        }\r
@@ -125,30 +133,34 @@ public:
        }\r
                \r
        void read_file() // For every packet taken: read in a number of packets.\r
-       {               \r
-               for(size_t n = 0; buffer_size_ < BUFFER_SIZE && (n < 3 || video_packet_buffer_.size() < 3 || audio_packet_buffer_.size() < 3) && executor_.is_running(); ++n)\r
+       {                               \r
+               AVPacket tmp_packet;\r
+               safe_ptr<AVPacket> read_packet(&tmp_packet, av_free_packet);    \r
+\r
+               if (av_read_frame(format_context_.get(), read_packet.get()) >= 0) // NOTE: read_packet is only valid until next call of av_safe_ptr<read_frame> or av_close_input_file\r
                {\r
-                       AVPacket tmp_packet;\r
-                       safe_ptr<AVPacket> read_packet(&tmp_packet, av_free_packet);    \r
-\r
-                       if (av_read_frame(format_context_.get(), read_packet.get()) >= 0) // NOTE: read_packet is only valid until next call of av_safe_ptr<read_frame> or av_close_input_file\r
-                       {\r
-                               auto packet = std::make_shared<aligned_buffer>(read_packet->data, read_packet->data + read_packet->size);\r
-                               if(read_packet->stream_index == video_s_index_)                                                 \r
-                               {\r
-                                       buffer_size_ += packet->size();\r
-                                       video_packet_buffer_.try_push(std::move(packet));       \r
-                               }\r
-                               else if(read_packet->stream_index == audio_s_index_)    \r
-                               {\r
-                                       buffer_size_ += packet->size();\r
-                                       audio_packet_buffer_.try_push(std::move(packet));\r
-                               }\r
-                       }\r
-                       else if(!loop_ || !seek_frame(0, AVSEEK_FLAG_BACKWARD)) // TODO: av_seek_frame does not work for all formats\r
-                               executor_.stop();\r
-                       graph_->update("input-buffer", static_cast<float>(buffer_size_)/static_cast<float>(BUFFER_SIZE));\r
+                       auto packet = std::make_shared<aligned_buffer>(read_packet->data, read_packet->data + read_packet->size);\r
+                       if(read_packet->stream_index == video_s_index_)                 \r
+                               video_packet_buffer_.try_push(std::move(packet));       \r
+                       else if(read_packet->stream_index == audio_s_index_)    \r
+                               audio_packet_buffer_.try_push(std::move(packet));               \r
                }\r
+               else if(!loop_ || !seek_frame(0, AVSEEK_FLAG_BACKWARD)) // TODO: av_seek_frame does not work for all formats\r
+               {                       \r
+                       graph_->tag("stop");\r
+                       executor_.stop();\r
+               }\r
+               else\r
+                       graph_->tag("seek");\r
+\r
+               boost::this_thread::yield();\r
+                       \r
+               graph_->update("input-buffer", static_cast<float>(video_packet_buffer_.size())/static_cast<float>(PACKET_BUFFER_COUNT));                \r
+               \r
+               executor_.begin_invoke([this]{read_file();});           \r
+               boost::unique_lock<boost::mutex> lock(mutex_);\r
+               while(executor_.is_running() && audio_packet_buffer_.size() > PACKET_BUFFER_COUNT && video_packet_buffer_.size() > PACKET_BUFFER_COUNT)\r
+                       cond_.wait(lock);               \r
        }\r
        \r
        bool seek_frame(int64_t seek_target, int flags = 0)\r
@@ -179,15 +191,9 @@ public:
        \r
        aligned_buffer get_packet(tbb::concurrent_bounded_queue<std::shared_ptr<aligned_buffer>>& buffer)\r
        {\r
+               cond_.notify_all();\r
                std::shared_ptr<aligned_buffer> packet;\r
-               if(buffer.try_pop(packet))\r
-               {\r
-                       buffer_size_ -= packet->size();\r
-                       if(executor_.size() < 4)\r
-                               executor_.begin_invoke([this]{read_file();});\r
-                       return std::move(*packet);\r
-               }\r
-               return aligned_buffer();\r
+               return buffer.try_pop(packet) ? std::move(*packet) : aligned_buffer();\r
        }\r
 \r
        bool is_eof() const\r
index e163e374a0d28dff515776521575b5d0e1e047fe..08af4bbd8a659bd670ff1d4436dabb6d6bbaacda 100644 (file)
@@ -77,7 +77,8 @@ public:
                , head_(draw_frame::empty())\r
        {\r
                graph_->guide("frame-time", 0.5f);\r
-               graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));          \r
+               graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));  \r
+               graph_->set_color("param", diagnostics::color(1.0f, 0.5f, 0.0f));                       \r
                CASPAR_LOG(info) << print() << L" Started";\r
                \r
                if(FAILED(CComObject<caspar::flash::FlashAxContainer>::CreateInstance(&ax_)))\r
@@ -128,6 +129,7 @@ public:
        {               \r
                if(!ax_->FlashCall(param))\r
                        CASPAR_LOG(warning) << "Flash Function Call Failed. Param: " << param;\r
+               graph_->tag("param");\r
        }\r
        \r
        safe_ptr<draw_frame> render_frame(bool has_underflow)\r
@@ -188,6 +190,7 @@ public:
                : filename_(filename)\r
                , graph_(diagnostics::create_graph(narrow(print())))\r
                , tail_(draw_frame::empty())            \r
+               , executor_(print())\r
        {       \r
                if(!boost::filesystem::exists(filename))\r
                        BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(narrow(filename)));  \r
index b2bd8abce4fa47b3b8fb21005396cacbdec3b021..c6abc32efbe896f9b77aff7d05714b9fcd2c3218 100644 (file)
@@ -30,6 +30,7 @@ struct frame_mixer_device::implementation : boost::noncopyable
 {              \r
        safe_ptr<diagnostics::graph> graph_;\r
        timer perf_timer_;\r
+       timer wait_perf_timer_;\r
 \r
        const video_format_desc format_desc_;\r
 \r
@@ -48,9 +49,11 @@ public:
                , format_desc_(format_desc)\r
                , image_mixer_(format_desc)\r
                , output_(output)\r
+               , executor_(L"frame_mixer_device")\r
        {\r
                graph_->guide("frame-time", 0.5f);      \r
                graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+               graph_->set_color("frame-wait", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                graph_->set_color("output-buffer", diagnostics::color( 0.0f, 1.0f, 0.0f));              \r
                executor_.start();\r
                executor_.set_capacity(2);\r
@@ -85,7 +88,9 @@ public:
                        audio_mixer_.end_pass();\r
                        graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
 \r
+                       wait_perf_timer_.reset();\r
                        output_(make_safe<const read_frame>(std::move(image.get()), std::move(audio)));\r
+                       graph_->update("frame-wait", static_cast<float>(wait_perf_timer_.elapsed()/format_desc_.interval*0.5));\r
                });\r
                graph_->update("output-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
        }\r
index 2c40573ee28482d19821cc9049d2fe6cc69d2efb..cb91e85bade7a36fe480e884f318549f76890c25 100644 (file)
@@ -18,6 +18,7 @@
         </ogl>\r
         <audio/>\r
         <bluefish>\r
+          <embedded-audio>true</embedded-audio>\r
           <device>1</device>\r
         </bluefish>\r
         <!--decklink>\r