]> git.sesse.net Git - casparcg/commitdiff
Merged trunk:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 27 Dec 2011 13:21:02 +0000 (13:21 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 27 Dec 2011 13:21:02 +0000 (13:21 +0000)
r1951

---------------------
r1950
AMCP: Print executed command to debug.
---------------------
r1949
print_producer_proxy changes.
---------------------
r1948

---------------------
r1947
flash_producer: Proper uninit.
---------------------
r1946
flash_producer: Don't forget buffering.
---------------------
r1945
flash-producer: Don't reinitialize the thread, only the ax-control.
---------------------
r1944
Missing executor changes.
---------------------
r1943
AMCP: Reply with error on amcp command overflow.
---------------------
r1942
AMCP: - Limit command queue size. - Let CLEAR clear the command queue.
---------------------
r1941

---------------------
r1940
Removed unnecessary printing.
---------------------
r1939
Print entire message, not parts.
---------------------

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

22 files changed:
common/concurrency/executor.h
core/producer/channel/channel_producer.cpp
core/producer/color/color_producer.cpp
core/producer/frame_producer.cpp
core/producer/frame_producer.h
core/producer/separated/separated_producer.cpp
core/producer/transition/transition_producer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/decklink/producer/decklink_producer.cpp
modules/flash/producer/flash_producer.cpp
modules/image/producer/image_producer.cpp
modules/image/producer/image_scroll_producer.cpp
protocol/amcp/AMCPCommand.h
protocol/amcp/AMCPCommandQueue.cpp
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPCommandsImpl.h
protocol/amcp/AMCPProtocolStrategy.cpp
protocol/cii/CIIProtocolStrategy.cpp
protocol/cii/CIIProtocolStrategy.h
protocol/util/AsyncEventServer.cpp
protocol/util/ClientInfo.h
protocol/util/SocketInfo.h

index 614904c5ae05046e50b81018f2088d44fd1488fb..b0b5801638a0a0b4ff2db799d6a9c8c3371f0da0 100644 (file)
@@ -144,6 +144,13 @@ public:
                                SetThreadPriority(GetCurrentThread(), BELOW_NORMAL_PRIORITY_CLASS);\r
                });\r
        }\r
+       \r
+       void clear()\r
+       {               \r
+               std::function<void()> func;\r
+               while(execution_queue_[normal_priority].try_pop(func));\r
+               while(execution_queue_[high_priority].try_pop(func));\r
+       }\r
                                \r
        void stop() // noexcept\r
        {\r
index 883a8ac48900963e1a63c2cc808d2123f87f45ad..e259421428ff3294138b649f4461dace8fc8a9de 100644 (file)
@@ -212,7 +212,8 @@ public:
 \r
 safe_ptr<frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<video_channel>& channel)\r
 {\r
-       return make_safe<channel_producer>(frame_factory, channel);\r
+       return create_producer_print_proxy(\r
+                       make_safe<channel_producer>(frame_factory, channel));\r
 }\r
 \r
 }}
\ No newline at end of file
index 1646312480e3e89acb1e151bfefdacc25eccd093..e1178862acd18c73b1f68704160fd9c12ba05b89 100644 (file)
@@ -124,7 +124,8 @@ safe_ptr<frame_producer> create_color_producer(const safe_ptr<core::frame_factor
        if(color2.length() != 9 || color2[0] != '#')\r
                return core::frame_producer::empty();\r
 \r
-       return make_safe<color_producer>(frame_factory, color2);\r
+       return create_producer_print_proxy(\r
+                       make_safe<color_producer>(frame_factory, color2));\r
 }\r
 safe_ptr<core::write_frame> create_color_frame(void* tag, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& color)\r
 {\r
index c48ef43e7c9e4cc46f1c5bcf489631c333eaf1f4..5f5cb1d7871d383982146d91a959f0835c32a03e 100644 (file)
@@ -74,9 +74,9 @@ public:
                                try\r
                                {\r
                                        if(!producer->unique())\r
-                                               CASPAR_LOG(trace) << str << L" Not destroyed on safe asynchronous destruction thread: " << producer->use_count();\r
+                                               CASPAR_LOG(trace) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count();\r
                                        else\r
-                                               CASPAR_LOG(trace) << str << L" Destroying on safe asynchronous destruction thread.";\r
+                                               CASPAR_LOG(trace) << str << L" Destroying on asynchronous destruction thread.";\r
                                }\r
                                catch(...){}\r
                                                                \r
@@ -89,9 +89,7 @@ public:
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                        try\r
                        {\r
-                               auto str = (*producer_)->print();\r
                                producer_.reset();\r
-                               CASPAR_LOG(debug) << str << L" Destroyed.";\r
                        }\r
                        catch(...){}\r
                }\r
@@ -119,14 +117,15 @@ public:
        print_producer_proxy(safe_ptr<frame_producer>&& producer) \r
                : producer_(std::move(producer))\r
        {\r
-               CASPAR_LOG(info) << producer_->print() << L" Initialized";\r
+               CASPAR_LOG(info) << producer_->print() << L" Initialized.";\r
        }\r
 \r
        ~print_producer_proxy()\r
        {               \r
                auto str = producer_->print();\r
+               CASPAR_LOG(trace) << str << L" Uninitializing.";\r
                producer_.reset();\r
-               CASPAR_LOG(info) << str << L" Uninitialized";\r
+               CASPAR_LOG(info) << str << L" Uninitialized.";\r
        }\r
 \r
        virtual safe_ptr<basic_frame>                                                           receive(int hints) override                                                                                             {return (producer_)->receive(hints);}\r
@@ -241,9 +240,6 @@ safe_ptr<core::frame_producer> do_create_producer(const safe_ptr<frame_factory>&
        if(producer == frame_producer::empty())\r
                producer = create_playlist_producer(my_frame_factory, params);\r
        \r
-       if(producer != frame_producer::empty())\r
-               producer = create_producer_print_proxy(producer);\r
-\r
        return producer;\r
 }\r
 \r
index 9cc59f0e0edf9d8901250576069149659d69c875..19a9e464fc7e4187d6083a5aa3c4a3744b073907 100644 (file)
@@ -83,5 +83,6 @@ void register_producer_factory(const producer_factory_t& factory); // Not thread
 safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>&, const std::vector<std::wstring>& params);\r
 safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>&, const std::wstring& params);\r
 safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::frame_producer> producer);\r
+safe_ptr<core::frame_producer> create_producer_print_proxy(safe_ptr<core::frame_producer> producer);\r
 \r
 }}\r
index f2d159c2b0ce2b0996472842c09ab8febb11bf65..9845849d807bfdc94663acbc79bbe8d458c8bb97 100644 (file)
@@ -104,7 +104,8 @@ struct separated_producer : public frame_producer
 \r
 safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key)\r
 {\r
-       return make_safe<separated_producer>(fill, key);\r
+       return create_producer_print_proxy(\r
+                       make_safe<separated_producer>(fill, key));\r
 }\r
 \r
 }}\r
index 47339f9a86fcd65197587da00421c5b6ef44e844..ad0fe32633700a4a7d05d2a76f6d66900b70e390 100644 (file)
@@ -184,7 +184,8 @@ struct transition_producer : public frame_producer
 \r
 safe_ptr<frame_producer> create_transition_producer(const field_mode::type& mode, const safe_ptr<frame_producer>& destination, const transition_info& info)\r
 {\r
-       return make_safe<transition_producer>(mode, destination, info);\r
+       return create_producer_print_proxy(\r
+                       make_safe<transition_producer>(mode, destination, info));\r
 }\r
 \r
 }}\r
index c0c08702349701560c3b54074d4ef2108c5b7f1a..033662944059470feac58b54159d0e3f38ffdf4f 100644 (file)
@@ -48,13 +48,13 @@ namespace caspar { namespace decklink {
        \r
 struct configuration\r
 {\r
-       int             device_index;\r
+       int     device_index;\r
        bool    embedded_audio;\r
        bool    internal_key;\r
        bool    low_latency;\r
        bool    key_only;\r
-       int             base_buffer_depth;\r
-       int             buffer_depth;\r
+       int     base_buffer_depth;\r
+       int     buffer_depth;\r
        \r
        configuration()\r
                : device_index(1)\r
@@ -73,7 +73,7 @@ class decklink_frame : public IDeckLinkVideoFrame
        const core::video_format_desc                                                           format_desc_;\r
 \r
        const bool                                                                                                      key_only_;\r
-       std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> key_data_;\r
+       std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> data_;\r
 public:\r
        decklink_frame(const safe_ptr<core::read_frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
                : frame_(frame)\r
@@ -82,25 +82,28 @@ public:
        {\r
                ref_count_ = 0;\r
        }\r
+       \r
+       // IUnknown\r
 \r
-       const boost::iterator_range<const int32_t*> audio_data()\r
+       STDMETHOD (QueryInterface(REFIID, LPVOID*))             \r
        {\r
-               return frame_->audio_data();\r
+               return E_NOINTERFACE;\r
        }\r
        \r
-       STDMETHOD (QueryInterface(REFIID, LPVOID*))             {return E_NOINTERFACE;}\r
        STDMETHOD_(ULONG,                       AddRef())                       \r
        {\r
                return ++ref_count_;\r
        }\r
+\r
        STDMETHOD_(ULONG,                       Release())                      \r
        {\r
-               --ref_count_;\r
-               if(ref_count_ == 0)\r
+               if(--ref_count_ == 0)\r
                        delete this;\r
                return ref_count_;\r
        }\r
 \r
+       // IDecklinkVideoFrame\r
+\r
        STDMETHOD_(long,                        GetWidth())                     {return format_desc_.width;}        \r
     STDMETHOD_(long,                   GetHeight())            {return format_desc_.height;}        \r
     STDMETHOD_(long,                   GetRowBytes())          {return format_desc_.width*4;}        \r
@@ -109,24 +112,30 @@ public:
         \r
     STDMETHOD(GetBytes(void** buffer))\r
        {\r
-               static std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> zeros(1920*1080*4, 0);\r
-               if(static_cast<size_t>(frame_->image_data().size()) != format_desc_.size)\r
-               {\r
-                       *buffer = zeros.data();\r
-                       return S_OK;\r
-               }\r
-\r
-               if(!key_only_)\r
-                       *buffer = const_cast<uint8_t*>(frame_->image_data().begin());\r
-               else\r
+               try\r
                {\r
-                       if(key_data_.empty())\r
+                       if(static_cast<int>(frame_->image_data().size()) != format_desc_.size)\r
                        {\r
-                               key_data_.resize(frame_->image_data().size());\r
-                               aligned_memshfl(key_data_.data(), frame_->image_data().begin(), frame_->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
-                               frame_.reset();\r
+                               data_.resize(format_desc_.size, 0);\r
+                               *buffer = data_.data();\r
                        }\r
-                       *buffer = key_data_.data();\r
+                       else if(key_only_)\r
+                       {\r
+                               if(data_.empty())\r
+                               {\r
+                                       data_.resize(frame_->image_data().size());\r
+                                       aligned_memshfl(data_.data(), frame_->image_data().begin(), frame_->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                                       frame_.reset();\r
+                               }\r
+                               *buffer = data_.data();\r
+                       }\r
+                       else\r
+                               *buffer = const_cast<uint8_t*>(frame_->image_data().begin());\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       return E_FAIL;\r
                }\r
 \r
                return S_OK;\r
@@ -134,6 +143,13 @@ public:
         \r
     STDMETHOD(GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode** timecode)){return S_FALSE;}        \r
     STDMETHOD(GetAncillaryData(IDeckLinkVideoFrameAncillary** ancillary))                {return S_FALSE;}\r
+\r
+       // decklink_frame       \r
+\r
+       const boost::iterator_range<const int32_t*> audio_data()\r
+       {\r
+               return frame_->audio_data();\r
+       }\r
 };\r
 \r
 struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback, boost::noncopyable\r
@@ -153,12 +169,12 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink
                \r
        const std::wstring                                      model_name_;\r
        const core::video_format_desc           format_desc_;\r
-       const size_t                                            buffer_size_;\r
+       const int                                               buffer_size_;\r
 \r
        long long                                                       video_scheduled_;\r
        long long                                                       audio_scheduled_;\r
 \r
-       size_t                                                          preroll_count_;\r
+       int                                                             preroll_count_;\r
                \r
        boost::circular_buffer<std::vector<int32_t>>    audio_container_;\r
 \r
@@ -209,7 +225,7 @@ public:
                if(config.embedded_audio)               \r
                        output_->BeginAudioPreroll();           \r
                \r
-               for(size_t n = 0; n < buffer_size_; ++n)\r
+               for(int n = 0; n < buffer_size_; ++n)\r
                        schedule_next_video(make_safe<core::read_frame>());\r
 \r
                if(!config.embedded_audio)\r
@@ -270,10 +286,10 @@ public:
        void enable_audio()\r
        {\r
                if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, 2, bmdAudioOutputStreamTimestamped)))\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() << wmsg_info(print() + L" Could not enable audio output."));\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(u8(print()) + " Could not enable audio output."));\r
                                \r
                if(FAILED(output_->SetAudioCallback(this)))\r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << wmsg_info(print() + L" Could not set audio callback."));\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(u8(print()) + " Could not set audio callback."));\r
 \r
                CASPAR_LOG(info) << print() << L" Enabled embedded-audio.";\r
        }\r
@@ -281,18 +297,18 @@ public:
        void enable_video(BMDDisplayMode display_mode)\r
        {\r
                if(FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) \r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << wmsg_info(print() + L" Could not enable video output."));\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(u8(print()) + " Could not enable video output."));\r
                \r
                if(FAILED(output_->SetScheduledFrameCompletionCallback(this)))\r
                        BOOST_THROW_EXCEPTION(caspar_exception() \r
-                                                                       << wmsg_info(print() + L" Failed to set playback completion callback.")\r
+                                                                       << msg_info(u8(print()) + " Failed to set playback completion callback.")\r
                                                                        << boost::errinfo_api_function("SetScheduledFrameCompletionCallback"));\r
        }\r
 \r
        void start_playback()\r
        {\r
                if(FAILED(output_->StartScheduledPlayback(0, format_desc_.time_scale, 1.0))) \r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << wmsg_info(print() + L" Failed to schedule playback."));\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(u8(print()) + " Failed to schedule playback."));\r
        }\r
        \r
        STDMETHOD (QueryInterface(REFIID, LPVOID*))     {return E_NOINTERFACE;}\r
@@ -386,7 +402,7 @@ public:
        template<typename T>\r
        void schedule_next_audio(const T& audio_data)\r
        {\r
-               const int sample_frame_count = static_cast<int>(audio_data.size())/format_desc_.audio_channels;\r
+               auto sample_frame_count = static_cast<int>(audio_data.size()/format_desc_.audio_channels);\r
 \r
                audio_container_.push_back(std::vector<int32_t>(audio_data.begin(), audio_data.end()));\r
 \r
@@ -417,7 +433,7 @@ public:
                }\r
 \r
                if(!is_running_)\r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << wmsg_info(print() + L" Is not running."));\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(u8(print()) + " Is not running."));\r
                \r
                if(config_.embedded_audio)\r
                        audio_frame_buffer_.push(frame);        \r
@@ -466,7 +482,7 @@ public:
        \r
        virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
        {\r
-               CASPAR_VERIFY(audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size()));\r
+               CASPAR_VERIFY(audio_cadence_.front() == static_cast<int>(frame->audio_data().size()));\r
                boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
 \r
                context_->send(frame);\r
index 717bf31b87095ec727cf1b71f087c4eb4d6722bc..0b78a3b4480d3803cff3951c8e6b0eacc2ee0b50 100644 (file)
@@ -327,7 +327,9 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factor
        if(format_desc.format == core::video_format::invalid)\r
                format_desc = frame_factory->get_video_format_desc();\r
                        \r
-       return create_producer_destroy_proxy(make_safe<decklink_producer_proxy>(frame_factory, format_desc, device_index, filter_str, length));\r
+       return create_producer_print_proxy(\r
+                  create_producer_destroy_proxy(\r
+                       make_safe<decklink_producer_proxy>(frame_factory, format_desc, device_index, filter_str, length)));\r
 }\r
 \r
 }}
\ No newline at end of file
index 2f26ecf3bff30fd982e13ff74960c1bfba5c0690..e0c9d5330493501c96e7e90e4b7172c349667443 100644 (file)
@@ -37,7 +37,8 @@
 #include <core/mixer/write_frame.h>\r
 \r
 #include <common/env.h>\r
-#include <common/concurrency/com_context.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/concurrency/lock.h>\r
 #include <common/diagnostics/graph.h>\r
 #include <common/utility/timer.h>\r
 \r
@@ -297,8 +298,10 @@ struct flash_producer : public core::frame_producer
        int                                                                                                                     width_;\r
        int                                                                                                                     height_;\r
 \r
-       com_context<flash_renderer>                                                                     context_;       \r
+       tbb::atomic<bool>                                                                                       is_running_;\r
+       std::unique_ptr<flash_renderer>                                                         renderer_;\r
 \r
+       executor                                                                                                        executor_;      \r
 public:\r
        flash_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, int width, int height) \r
                : filename_(filename)           \r
@@ -306,9 +309,10 @@ public:
                , last_frame_(core::basic_frame::empty())\r
                , width_(width > 0 ? width : frame_factory->get_video_format_desc().width)\r
                , height_(height > 0 ? height : frame_factory->get_video_format_desc().height)\r
-               , context_(L"flash_producer")\r
+               , executor_(L"flash_producer")\r
        {       \r
                fps_ = 0;\r
+               is_running_ = true;\r
 \r
                graph_->set_color("output-buffer-count", diagnostics::color(1.0f, 1.0f, 0.0f));          \r
                graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f));   \r
@@ -317,12 +321,25 @@ public:
                \r
                frame_buffer_.set_capacity(frame_factory_->get_video_format_desc().fps > 30.0 ? 2 : 1);\r
 \r
-               initialize();                           \r
+               executor_.begin_invoke([]\r
+               {\r
+                       ::CoInitialize(nullptr);\r
+               });                     \r
        }\r
 \r
        ~flash_producer()\r
        {\r
-               frame_buffer_.clear();\r
+               is_running_ = false;\r
+\r
+               safe_ptr<core::basic_frame> frame;\r
+               for(int n = 0; n < 3; ++n)\r
+                       frame_buffer_.try_pop(frame);\r
+\r
+               executor_.invoke([this]\r
+               {\r
+                       renderer_.reset();\r
+                       ::CoUninitialize();\r
+               });\r
        }\r
 \r
        // frame_producer\r
@@ -332,7 +349,7 @@ public:
                graph_->set_value("output-buffer-count", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\r
 \r
                auto frame = core::basic_frame::late();\r
-               if(!frame_buffer_.try_pop(frame) && context_)\r
+               if(!frame_buffer_.try_pop(frame) && renderer_)\r
                        graph_->set_tag("underflow");\r
 \r
                return frame;\r
@@ -340,20 +357,29 @@ public:
 \r
        virtual safe_ptr<core::basic_frame> last_frame() const override\r
        {\r
-               tbb::spin_mutex::scoped_lock lock(last_frame_mutex_);\r
-               return last_frame_;\r
+               return lock(last_frame_mutex_, [this]\r
+               {\r
+                       return last_frame_;\r
+               });\r
        }               \r
        \r
        virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
        {       \r
-               return context_.begin_invoke([=]() -> std::wstring\r
+               return executor_.begin_invoke([=]() -> std::wstring\r
                {\r
-                       if(!context_)\r
-                               initialize();\r
+                       if(!is_running_)\r
+                               return L"";\r
+\r
+                       if(!renderer_)\r
+                       {\r
+                               renderer_.reset(new flash_renderer(safe_ptr<diagnostics::graph>(graph_), frame_factory_, filename_, width_, height_));\r
+                               while(frame_buffer_.try_push(core::basic_frame::empty()));\r
+                               render(renderer_.get());\r
+                       }\r
 \r
                        try\r
                        {\r
-                               return context_->call(param);   \r
+                               return renderer_->call(param);  \r
 \r
                                //const auto& format_desc = frame_factory_->get_video_format_desc();\r
                                //if(abs(context_->fps() - format_desc.fps) > 0.01 && abs(context_->fps()/2.0 - format_desc.fps) > 0.01)\r
@@ -362,12 +388,12 @@ public:
                        catch(...)\r
                        {\r
                                CASPAR_LOG_CURRENT_EXCEPTION();\r
-                               context_.reset(nullptr);\r
+                               renderer_.reset(nullptr);\r
                                frame_buffer_.push(core::basic_frame::empty());\r
                        }\r
 \r
                        return L"";\r
-               });\r
+               }, high_priority);\r
        }\r
                \r
        virtual std::wstring print() const override\r
@@ -383,40 +409,35 @@ public:
        }\r
 \r
        // flash_producer\r
-\r
-       void initialize()\r
-       {\r
-               context_.reset([&]{return new flash_renderer(safe_ptr<diagnostics::graph>(graph_), frame_factory_, filename_, width_, height_);});\r
-               while(frame_buffer_.try_push(core::basic_frame::empty())){}             \r
-               render(context_.get());\r
-       }\r
-\r
+       \r
        safe_ptr<core::basic_frame> render_frame()\r
        {\r
-               auto frame = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity());           \r
-               tbb::spin_mutex::scoped_lock lock(last_frame_mutex_);\r
-               last_frame_ = make_safe<core::basic_frame>(frame);\r
+               auto frame = renderer_->render_frame(frame_buffer_.size() < frame_buffer_.capacity());          \r
+               lock(last_frame_mutex_, [&]\r
+               {\r
+                       last_frame_ = make_safe<core::basic_frame>(frame);\r
+               });\r
                return frame;\r
        }\r
 \r
        void render(const flash_renderer* renderer)\r
        {               \r
-               context_.begin_invoke([=]\r
+               executor_.begin_invoke([=]\r
                {\r
-                       if(context_.get() != renderer) // Since initialize will start a new recursive call make sure the recursive calls are only for a specific instance.\r
+                       if(!is_running_ || renderer_.get() != renderer) // Since initialize will start a new recursive call make sure the recursive calls are only for a specific instance.\r
                                return;\r
 \r
                        try\r
                        {               \r
                                const auto& format_desc = frame_factory_->get_video_format_desc();\r
 \r
-                               if(abs(context_->fps()/2.0 - format_desc.fps) < 2.0) // flash == 2 * format -> interlace\r
+                               if(abs(renderer_->fps()/2.0 - format_desc.fps) < 2.0) // flash == 2 * format -> interlace\r
                                {\r
                                        auto frame1 = render_frame();\r
                                        auto frame2 = render_frame();\r
                                        frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc.field_mode));\r
                                }\r
-                               else if(abs(context_->fps()- format_desc.fps/2.0) < 2.0) // format == 2 * flash -> duplicate\r
+                               else if(abs(renderer_->fps()- format_desc.fps/2.0) < 2.0) // format == 2 * flash -> duplicate\r
                                {\r
                                        auto frame = render_frame();\r
                                        frame_buffer_.push(frame);\r
@@ -428,14 +449,14 @@ public:
                                        frame_buffer_.push(frame);\r
                                }\r
 \r
-                               if(context_->is_empty())\r
+                               if(renderer_->is_empty())\r
                                {\r
-                                       context_.reset(nullptr);\r
+                                       renderer_.reset(nullptr);\r
                                        return;\r
                                }\r
 \r
                                graph_->set_value("output-buffer-count", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));        \r
-                               fps_.fetch_and_store(static_cast<int>(context_->fps()*100.0));                          \r
+                               fps_.fetch_and_store(static_cast<int>(renderer_->fps()*100.0));                         \r
                                graph_->set_text(print());\r
 \r
                                render(renderer);\r
@@ -443,7 +464,7 @@ public:
                        catch(...)\r
                        {\r
                                CASPAR_LOG_CURRENT_EXCEPTION();\r
-                               context_.reset(nullptr);\r
+                               renderer_.reset(nullptr);\r
                                frame_buffer_.push(core::basic_frame::empty());\r
                        }\r
                });\r
@@ -459,7 +480,9 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factor
        if(!boost::filesystem::exists(filename))\r
                BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(u8(filename)));      \r
 \r
-       return create_producer_destroy_proxy(make_safe<flash_producer>(frame_factory, filename, template_host.width, template_host.height));\r
+       return create_producer_print_proxy(\r
+                  create_producer_destroy_proxy(\r
+                       make_safe<flash_producer>(frame_factory, filename, template_host.width, template_host.height)));\r
 }\r
 \r
 std::wstring find_template(const std::wstring& template_name)\r
index e93aeddb4a9a407701df116e7ecfe07f4a4ff78a..df635fdfb7c66b8c42c9d507fa1cd6b0dae79b45 100644 (file)
@@ -104,7 +104,8 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factor
        if(ext == extensions.end())\r
                return core::frame_producer::empty();\r
 \r
-       return make_safe<image_producer>(frame_factory, filename + *ext);\r
+       return create_producer_print_proxy(\r
+                       make_safe<image_producer>(frame_factory, filename + *ext));\r
 }\r
 \r
 \r
index 44797696cd7013aad02f7ac3ba25eee9d7c9c2bf..3fa65bbbb36c30c37dc8383a96dfd6047cfac9d4 100644 (file)
@@ -253,7 +253,8 @@ safe_ptr<core::frame_producer> create_scroll_producer(const safe_ptr<core::frame
        if(speed == 0)\r
                return core::frame_producer::empty();\r
 \r
-       return make_safe<image_scroll_producer>(frame_factory, filename + L"." + *ext, speed);\r
+       return create_producer_print_proxy(\r
+                       make_safe<image_scroll_producer>(frame_factory, filename + L"." + *ext, speed));\r
 }\r
 \r
 }}
\ No newline at end of file
index ad081fdacb21305729c74b4934f41b0735c69cf8..a1b691f5cbcb0510494c9991e84899a3d5eb9502 100644 (file)
@@ -80,9 +80,9 @@ namespace amcp {
                virtual std::wstring print() const = 0;\r
 \r
                void SetScheduling(AMCPCommandScheduling s){scheduling_ = s;}\r
+               void SetReplyString(const std::wstring& str){replyString_ = str;}\r
 \r
        protected:\r
-               void SetReplyString(const std::wstring& str){replyString_ = str;}\r
                std::vector<std::wstring> _parameters;\r
                std::vector<std::wstring> _parameters2;\r
 \r
index 3a0f4ddad4a574375ea1cad0525af6857a7463c8..a77adf54bfa881a5ae5a8474bbb0c792874280dc 100644 (file)
@@ -39,8 +39,23 @@ void AMCPCommandQueue::AddCommand(AMCPCommandPtr pCurrentCommand)
        if(!pCurrentCommand)\r
                return;\r
 \r
-       //if(pNewCommand->GetScheduling() == ImmediatelyAndClear)\r
-       //      executor_.clear();\r
+       if(pCurrentCommand->GetScheduling() == ImmediatelyAndClear)\r
+               executor_.clear();\r
+\r
+       if(executor_.size() > 64)\r
+       {\r
+               try\r
+               {\r
+                       CASPAR_LOG(error) << "AMCP Command Queue Overflow.";\r
+                       CASPAR_LOG(error) << "Failed to execute command:" << pCurrentCommand->print();\r
+                       pCurrentCommand->SetReplyString(L"500 FAILED");\r
+                       pCurrentCommand->SendReply();\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
+       }\r
        \r
        executor_.begin_invoke([=]\r
        {\r
@@ -49,7 +64,7 @@ void AMCPCommandQueue::AddCommand(AMCPCommandPtr pCurrentCommand)
                        try\r
                        {\r
                                if(pCurrentCommand->Execute()) \r
-                                       CASPAR_LOG(trace) << "Executed command: " << pCurrentCommand->print();\r
+                                       CASPAR_LOG(debug) << "Executed command: " << pCurrentCommand->print();\r
                                else \r
                                        CASPAR_LOG(warning) << "Failed to execute command: " << pCurrentCommand->print();\r
                        }\r
index e0116d7e8874cab4556b403bc2420171698bd2d2..dd4c2209c4ec94249f98439d74d0e715785efa06 100644 (file)
@@ -298,9 +298,7 @@ bool CallCommand::DoExecute()
 \r
                if(!result.timed_wait(boost::posix_time::seconds(2)))\r
                        BOOST_THROW_EXCEPTION(timed_out());\r
-\r
-               CASPAR_LOG(info) << "Executed call: " <<  _parameters[0] << TEXT(" successfully");\r
-               \r
+                               \r
                std::wstringstream replyString;\r
                if(result.get().empty())\r
                        replyString << TEXT("202 CALL OK\r\n");\r
@@ -564,9 +562,7 @@ bool SwapCommand::DoExecute()
                        auto ch2 = GetChannels().at(boost::lexical_cast<int>(_parameters[0])-1);\r
                        ch1->stage()->swap_layers(ch2->stage());\r
                }\r
-\r
-               CASPAR_LOG(info) << "Swapped successfully";\r
-\r
+               \r
                SetReplyString(TEXT("202 SWAP OK\r\n"));\r
 \r
                return true;\r
@@ -593,8 +589,6 @@ bool AddCommand::DoExecute()
                auto consumer = create_consumer(_parameters);\r
                GetChannel()->output()->add(GetLayerIndex(consumer->index()), consumer);\r
        \r
-               CASPAR_LOG(info) << "Added " <<  _parameters[0] << TEXT(" successfully");\r
-\r
                SetReplyString(TEXT("202 ADD OK\r\n"));\r
 \r
                return true;\r
@@ -651,8 +645,6 @@ bool LoadCommand::DoExecute()
                auto pFP = create_producer(GetChannel()->frame_factory(), _parameters);         \r
                GetChannel()->stage()->load(GetLayerIndex(), pFP, true);\r
        \r
-               CASPAR_LOG(info) << "Loaded " <<  _parameters[0] << TEXT(" successfully");\r
-\r
                SetReplyString(TEXT("202 LOAD OK\r\n"));\r
 \r
                return true;\r
@@ -765,7 +757,6 @@ bool LoadbgCommand::DoExecute()
                auto pFP2 = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, pFP, transitionInfo);\r
                GetChannel()->stage()->load(GetLayerIndex(), pFP2, false, auto_play ? transitionInfo.duration : -1); // TODO: LOOP\r
        \r
-               CASPAR_LOG(info) << "Loaded " << _parameters[0] << TEXT(" successfully to background");\r
                SetReplyString(TEXT("202 LOADBG OK\r\n"));\r
 \r
                return true;\r
@@ -817,9 +808,7 @@ bool PlayCommand::DoExecute()
                        for(auto it = _parameters.begin(); it != _parameters.end(); ++it)\r
                                lbg.AddParameter(*it);\r
                        if(!lbg.Execute())\r
-                               CASPAR_LOG(warning) << " Failed to play.";\r
-\r
-                       CASPAR_LOG(info) << "Playing " << _parameters[0];\r
+                               throw std::exception();\r
                }\r
 \r
                GetChannel()->stage()->play(GetLayerIndex());\r
index 62e569710a06b68a989e2ae38c9837d0135d3f5c..e8e87071dd15d7172d77d0870482fdb2f789d4a4 100644 (file)
@@ -104,7 +104,7 @@ class StopCommand : public AMCPCommandBase<true, AddToQueue, 0>
        bool DoExecute();\r
 };\r
 \r
-class ClearCommand : public AMCPCommandBase<true, AddToQueue, 0>\r
+class ClearCommand : public AMCPCommandBase<true, ImmediatelyAndClear, 0>\r
 {\r
        std::wstring print() const { return L"ClearCommand";}\r
        bool DoExecute();\r
index d7bc190edef200f547493c7c6ce784c8f241fe4e..d7abbfeeb509100a327f54c8e08ac1a3053e9f24 100644 (file)
@@ -35,6 +35,7 @@
 \r
 #include <boost/algorithm/string/trim.hpp>\r
 #include <boost/algorithm/string/split.hpp>\r
+#include <boost/algorithm/string/replace.hpp>\r
 #include <boost/lexical_cast.hpp>\r
 \r
 #if defined(_MSC_VER)\r
@@ -110,7 +111,9 @@ void AMCPProtocolStrategy::Parse(const TCHAR* pData, int charCount, ClientInfoPt
 }\r
 \r
 void AMCPProtocolStrategy::ProcessMessage(const std::wstring& message, ClientInfoPtr& pClientInfo)\r
-{\r
+{      \r
+       CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << message + L"\\r\\n";\r
+       \r
        bool bError = true;\r
        MessageParserState state = New;\r
 \r
index 005bbe1135dc356c6e9f1d8bc4a38593dbb84e5d..797a98395ed4353100b1d29c13127e827ad35fbe 100644 (file)
@@ -32,6 +32,8 @@
 #include <core/mixer/mixer.h>\r
 #include <common/env.h>\r
 \r
+#include <boost/algorithm/string/replace.hpp>\r
+\r
 #if defined(_MSC_VER)\r
 #pragma warning (push, 1) // TODO: Legacy code, just disable warnings\r
 #endif\r
@@ -61,7 +63,7 @@ void CIIProtocolStrategy::Parse(const TCHAR* pData, int charCount, IO::ClientInf
                        std::wstring message = availibleData.substr(0,pos);\r
 \r
                        if(message.length() > 0) {\r
-                               ProcessMessage(message);\r
+                               ProcessMessage(message, pClientInfo);\r
                                if(pClientInfo != 0)\r
                                        pClientInfo->Send(TEXT("*\r\n"));\r
                        }\r
@@ -81,8 +83,10 @@ void CIIProtocolStrategy::Parse(const TCHAR* pData, int charCount, IO::ClientInf
        currentMessage_ = availibleData;\r
 }\r
 \r
-void CIIProtocolStrategy::ProcessMessage(const std::wstring& message)\r
-{\r
+void CIIProtocolStrategy::ProcessMessage(const std::wstring& message, IO::ClientInfoPtr pClientInfo)\r
+{      \r
+       CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << message + L"\\r\\n";\r
+\r
        std::vector<std::wstring> tokens;\r
        int tokenCount = TokenizeMessage(message, &tokens);\r
 \r
index f6d4d102c9aca9aab89656f165844faee14cf65e..88a3b6fd0416a00571a67d40d5a3a1480a095706 100644 (file)
@@ -79,7 +79,7 @@ private:
        static const TCHAR TokenDelimiter;\r
        static const std::wstring MessageDelimiter;\r
 \r
-       void ProcessMessage(const std::wstring& message);\r
+       void ProcessMessage(const std::wstring& message, IO::ClientInfoPtr pClientInfo);\r
        int TokenizeMessage(const std::wstring& message, std::vector<std::wstring>* pTokenVector);\r
        CIICommandPtr Create(const std::wstring& name);\r
 \r
index 13993fe0a5626f106065665c3ccf749f9f1e6730..4298877bc6773cceca4b8ff7b30ac00cfd972535 100644 (file)
 #include "SocketInfo.h"\r
 \r
 #include <common/log/log.h>\r
-\r
-#include <boost/algorithm/string/replace.hpp>\r
-\r
 #include <string>\r
 #include <algorithm>\r
+#include <boost/algorithm/string/replace.hpp>\r
 \r
 #if defined(_MSC_VER)\r
 #pragma warning (push, 1) // TODO: Legacy code, just disable warnings, will replace with boost::asio in future\r
@@ -356,15 +354,8 @@ bool AsyncEventServer::OnRead(SocketInfoPtr& pSI) {
                }\r
 \r
                //Convert to widechar\r
-               if(ConvertMultiByteToWideChar(pProtocolStrategy_->GetCodepage(), pSI->recvBuffer_, recvResult + pSI->recvLeftoverOffset_, pSI->wideRecvBuffer_, pSI->recvLeftoverOffset_))\r
-               {\r
-                       auto msg =      std::wstring(pSI->wideRecvBuffer_.begin(), pSI->wideRecvBuffer_.end());\r
-                       boost::replace_all(msg, L"\n", L"\\n");\r
-                       boost::replace_all(msg, L"\r", L"\\r");\r
-\r
-                       CASPAR_LOG(info) << L"Received message from " << pSI->host_.c_str() << ": "<< msg;\r
-                       pProtocolStrategy_->Parse(&pSI->wideRecvBuffer_[0], pSI->wideRecvBuffer_.size(), pSI);\r
-               }\r
+               if(ConvertMultiByteToWideChar(pProtocolStrategy_->GetCodepage(), pSI->recvBuffer_, recvResult + pSI->recvLeftoverOffset_, pSI->wideRecvBuffer_, pSI->recvLeftoverOffset_))              \r
+                       pProtocolStrategy_->Parse(&pSI->wideRecvBuffer_[0], pSI->wideRecvBuffer_.size(), pSI);          \r
                else                    \r
                        CASPAR_LOG(error) << "Read from " << pSI->host_.c_str() << TEXT(" failed, could not convert command to UNICODE");\r
                        \r
index 5278d34c3103626aae4f3cacbc678bd1cede0b5f..c7fd4285dad8f6db200f428dece2a54ea06cd235 100644 (file)
@@ -37,6 +37,7 @@ public:
 \r
        virtual void Send(const std::wstring& data) = 0;\r
        virtual void Disconnect() = 0;\r
+       virtual std::wstring print() const = 0;\r
 \r
        std::wstring            currentMessage_;\r
 };\r
@@ -49,6 +50,7 @@ struct ConsoleClientInfo : public caspar::IO::ClientInfo
                std::wcout << (L"#" + data);\r
        }\r
        void Disconnect(){}\r
+       virtual std::wstring print() const {return L"Console";}\r
 };\r
 \r
 }}\r
index 4b6cc405be9d628b426df947f4d084cf69dbcba7..0594fe99e3354644576b3a9d19e21e4085d34c0c 100644 (file)
@@ -44,6 +44,7 @@ public:
 \r
        void Send(const std::wstring& data);\r
        void Disconnect();\r
+       virtual std::wstring print() const override {return host_;}\r
 \r
        SOCKET                  socket_;\r
        HANDLE                  event_;\r