]> git.sesse.net Git - casparcg/commitdiff
graph: Minor improvements.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 23 Dec 2011 09:04:45 +0000 (09:04 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 23 Dec 2011 09:04:45 +0000 (09:04 +0000)
frame_producer: print init and uninit.
ffmpeg/input: Use executor instead of explicit thread and cond-var.

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

common/diagnostics/graph.cpp
core/producer/frame_producer.cpp
core/producer/frame_producer.h
modules/decklink/producer/decklink_producer.cpp
modules/ffmpeg/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/input/input.cpp
modules/ffmpeg/producer/video/video_decoder.cpp
modules/flash/producer/cg_producer.cpp
modules/flash/producer/flash_producer.cpp
modules/image/producer/image_producer.cpp

index 22e1aa414eac1ffd5fa2499291ec16bc463e7373..6eac2c00e198adb52ebb878e1e7a25a50345eb22 100644 (file)
@@ -143,7 +143,7 @@ private:
                glClear(GL_COLOR_BUFFER_BIT);\r
                window_->Draw(*this);\r
                window_->Display();\r
-               boost::this_thread::sleep(boost::posix_time::milliseconds(15));\r
+               boost::this_thread::sleep(boost::posix_time::milliseconds(10));\r
                executor_.begin_invoke([this]{tick();});\r
        }\r
 \r
@@ -198,7 +198,7 @@ class line : public drawable
        tbb::atomic<bool>       tick_tag_;\r
        tbb::atomic<int>        color_;\r
 public:\r
-       line(size_t res = 600)\r
+       line(size_t res = 1200)\r
                : line_data_(res)\r
        {\r
                tick_data_      = -1.0f;\r
index aaa9c24947fbcfdeab2a5b2b7986fc9c9e972f8e..79fbba6f787e5808f5234d0de31b8ed21bb4d923 100644 (file)
@@ -81,7 +81,6 @@ public:
                                catch(...){}\r
                                                                \r
                                producer2.reset();\r
-                               CASPAR_LOG(debug) << str << L" Destroyed.";\r
                                pool->push(destroyer);\r
                        }); \r
                }\r
@@ -108,11 +107,43 @@ public:
        virtual uint32_t                                                                                        nb_frames() const override                                                                                              {return (*producer_)->nb_frames();}\r
 };\r
 \r
-safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::frame_producer>&& producer)\r
+safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::frame_producer> producer)\r
 {\r
        return make_safe<destroy_producer_proxy>(std::move(producer));\r
 }\r
 \r
+class print_producer_proxy : public frame_producer\r
+{      \r
+       std::shared_ptr<frame_producer> producer_;\r
+public:\r
+       print_producer_proxy(safe_ptr<frame_producer>&& producer) \r
+               : producer_(std::move(producer))\r
+       {\r
+               CASPAR_LOG(info) << producer_->print() << L" Initialized";\r
+       }\r
+\r
+       ~print_producer_proxy()\r
+       {               \r
+               auto str = producer_->print();\r
+               producer_.reset();\r
+               CASPAR_LOG(info) << str << L" Uninitialized";\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame>                                                           receive(int hints) override                                                                                             {return (producer_)->receive(hints);}\r
+       virtual safe_ptr<basic_frame>                                                           last_frame() const override                                                                                             {return (producer_)->last_frame();}\r
+       virtual std::wstring                                                                            print() const override                                                                                                  {return (producer_)->print();}\r
+       virtual boost::property_tree::wptree                                            info() const override                                                                                                   {return (producer_)->info();}\r
+       virtual boost::unique_future<std::wstring>                                      call(const std::wstring& str) override                                                                  {return (producer_)->call(str);}\r
+       virtual safe_ptr<frame_producer>                                                        get_following_producer() const override                                                                 {return (producer_)->get_following_producer();}\r
+       virtual void                                                                                            set_leading_producer(const safe_ptr<frame_producer>& producer) override {(producer_)->set_leading_producer(producer);}\r
+       virtual uint32_t                                                                                        nb_frames() const override                                                                                              {return (producer_)->nb_frames();}\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer_print_proxy(safe_ptr<core::frame_producer> producer)\r
+{\r
+       return make_safe<print_producer_proxy>(std::move(producer));\r
+}\r
+\r
 class last_frame_producer : public frame_producer\r
 {\r
        const std::wstring                      print_;\r
@@ -209,6 +240,9 @@ safe_ptr<core::frame_producer> do_create_producer(const safe_ptr<frame_factory>&
        \r
        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
index e26432d6770f32d73aebb0e15b89aba694292008..ffd05d1161acb5fe64b5449d1b3ebd014f56d0e0 100644 (file)
@@ -82,6 +82,6 @@ typedef std::function<safe_ptr<core::frame_producer>(const safe_ptr<frame_factor
 void register_producer_factory(const producer_factory_t& factory); // Not thread-safe.\r
 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_destroy_proxy(safe_ptr<core::frame_producer> producer);\r
 \r
 }}\r
index e18930d3cdb1e22c225a72a8942921944f8ad0f5..9bc14716d143a1b631933999de7365d1f0f2c6c9 100644 (file)
@@ -147,8 +147,6 @@ public:
                        BOOST_THROW_EXCEPTION(caspar_exception() \r
                                                                        << msg_info(narrow(print()) + " Failed to start input stream.")\r
                                                                        << boost::errinfo_api_function("StartStreams"));\r
-               \r
-               CASPAR_LOG(info) << print() << L" Successfully Initialized.";\r
        }\r
 \r
        ~decklink_producer()\r
@@ -280,14 +278,7 @@ public:
        {\r
                context_.reset([&]{return new decklink_producer(format_desc, device_index, frame_factory, filter_str);}); \r
        }\r
-\r
-       ~decklink_producer_proxy()\r
-       {\r
-               auto str = print();\r
-               context_.reset();\r
-               CASPAR_LOG(info) << str << L" Successfully Uninitialized.";     \r
-       }\r
-\r
+       \r
        // frame_producer\r
                                \r
        virtual safe_ptr<core::basic_frame> receive(int hints) override\r
index 1ac7fdeaa796fe61c3db3c1602f62b11e747ca5a..4f00bfaaa12805603388f2c6caefc2664db8e771 100644 (file)
@@ -134,7 +134,7 @@ public:
 \r
        bool ready() const\r
        {\r
-               return packets_.size() > 10;\r
+               return packets_.size() >= 8;\r
        }\r
 \r
        uint32_t nb_frames() const\r
index 1c1383471b66b2daf5409c727a1412d70a673115..9d3d39f9c7c52d0b7b1870b7566e4d1c37527836 100644 (file)
@@ -29,6 +29,7 @@
 #include <core/video_format.h>\r
 \r
 #include <common/diagnostics/graph.h>\r
+#include <common/concurrency/executor.h>\r
 #include <common/exception/exceptions.h>\r
 #include <common/exception/win32_exception.h>\r
 \r
@@ -55,37 +56,31 @@ extern "C"
 #pragma warning (pop)\r
 #endif\r
 \r
-namespace caspar { namespace ffmpeg {\r
-\r
 static const size_t MAX_BUFFER_COUNT = 100;\r
 static const size_t MIN_BUFFER_COUNT = 4;\r
 static const size_t MAX_BUFFER_SIZE  = 16 * 1000000;\r
-       \r
+\r
+namespace caspar { namespace ffmpeg {\r
+               \r
 struct input::implementation : boost::noncopyable\r
 {              \r
-       safe_ptr<diagnostics::graph>                                                            graph_;\r
+       const safe_ptr<diagnostics::graph>                                                      graph_;\r
 \r
        const safe_ptr<AVFormatContext>                                                         format_context_; // Destroy this last\r
        const int                                                                                                       default_stream_index_;\r
                        \r
        const std::wstring                                                                                      filename_;\r
-       tbb::atomic<bool>                                                                                       loop_;\r
        const uint32_t                                                                                          start_;         \r
        const uint32_t                                                                                          length_;\r
+       tbb::atomic<bool>                                                                                       loop_;\r
        uint32_t                                                                                                        frame_number_;\r
        \r
        tbb::concurrent_bounded_queue<std::shared_ptr<AVPacket>>        buffer_;\r
        tbb::atomic<size_t>                                                                                     buffer_size_;\r
-       boost::condition_variable                                                                       buffer_cond_;\r
-       boost::mutex                                                                                            buffer_mutex_;\r
                \r
-       boost::thread                                                                                           thread_;\r
-       tbb::atomic<bool>                                                                                       is_running_;\r
-       tbb::atomic<bool>                                                                                       is_eof_;\r
-\r
-       tbb::recursive_mutex                                                                            mutex_;\r
-\r
-       explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length) \r
+       executor                                                                                                        executor_;\r
+       \r
+       explicit implementation(const safe_ptr<diagnostics::graph> graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length) \r
                : graph_(graph)\r
                , format_context_(open_input(filename))         \r
                , default_stream_index_(av_find_default_stream_index(format_context_.get()))\r
@@ -93,127 +88,110 @@ struct input::implementation : boost::noncopyable
                , start_(start)\r
                , length_(length)\r
                , frame_number_(0)\r
+               , executor_(print())\r
        {               \r
-               is_eof_                 = false;\r
                loop_                   = loop;\r
                buffer_size_    = 0;\r
 \r
                if(start_ > 0)                  \r
-                       do_seek(start_);\r
+                       queued_seek(start_);\r
                                                                \r
                graph_->set_color("seek", diagnostics::color(1.0f, 0.5f, 0.0f));        \r
                graph_->set_color("buffer-count", diagnostics::color(0.7f, 0.4f, 0.4f));\r
                graph_->set_color("buffer-size", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
-               \r
-               is_running_ = true;\r
-               thread_ = boost::thread([this]{run();});\r
 \r
-               CASPAR_LOG(info) << print() << L" Initialized.";\r
+               tick();\r
        }\r
-\r
-       ~implementation()\r
-       {\r
-               is_running_ = false;\r
-               buffer_cond_.notify_all();\r
-               thread_.join();\r
-       }\r
-               \r
+       \r
        bool try_pop(std::shared_ptr<AVPacket>& packet)\r
        {\r
-               const bool result = buffer_.try_pop(packet);\r
-\r
+               auto result = buffer_.try_pop(packet);\r
+               \r
                if(result)\r
                {\r
                        if(packet)\r
                                buffer_size_ -= packet->size;\r
-                       buffer_cond_.notify_all();\r
+                       tick();\r
                }\r
 \r
                graph_->set_value("buffer-size", (static_cast<double>(buffer_size_)+0.001)/MAX_BUFFER_SIZE);\r
                graph_->set_value("buffer-count", (static_cast<double>(buffer_.size()+0.001)/MAX_BUFFER_COUNT));\r
-\r
+               \r
                return result;\r
        }\r
-                       \r
-       void run()\r
-       {               \r
-               caspar::win32_exception::install_handler();\r
 \r
-               try\r
+       void seek(uint32_t target)\r
+       {\r
+               executor_.begin_invoke([=]\r
                {\r
-                       CASPAR_LOG(info) << print() << " Thread Started.";\r
+                       std::shared_ptr<AVPacket> packet;\r
+                       while(buffer_.try_pop(packet) && packet)\r
+                               buffer_size_ -= packet->size;\r
 \r
-                       while(is_running_)\r
-                       {\r
-                               {\r
-                                       boost::unique_lock<boost::mutex> lock(buffer_mutex_);\r
-                                       while(full())\r
-                                               buffer_cond_.timed_wait(lock, boost::posix_time::millisec(20));\r
-                               }\r
-                               read_next_packet();                     \r
-                       }\r
+                       queued_seek(target);\r
 \r
-                       CASPAR_LOG(info) << print() << " Thread Stopped.";\r
-               }\r
-               catch(...)\r
-               {\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-                       is_running_ = false;\r
-               }\r
+                       tick();\r
+               }, high_priority);\r
        }\r
-                       \r
-       void read_next_packet()\r
+       \r
+       std::wstring print() const\r
+       {\r
+               return L"ffmpeg_input[" + filename_ + L")]";\r
+       }\r
+       \r
+       void tick()\r
        {               \r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
-               auto packet = create_packet();\r
-               auto ret        = av_read_frame(format_context_.get(), packet.get()); // packet is only valid until next call of av_read_frame. Use av_dup_packet to extend its life.   \r
-               \r
-               if(is_eof(ret))                                                                                                              \r
+               executor_.begin_invoke([this]\r
                {\r
-                       frame_number_   = 0;\r
-                       is_eof_                 = true;\r
-\r
-                       if(loop_)\r
+                       auto packet = create_packet();\r
+               \r
+                       auto ret = av_read_frame(format_context_.get(), packet.get()); // packet is only valid until next call of av_read_frame. Use av_dup_packet to extend its life.  \r
+               \r
+                       if(is_eof(ret))                                                                                                              \r
                        {\r
-                               do_seek(start_);\r
-                               graph_->set_tag("seek");                \r
-                               CASPAR_LOG(trace) << print() << " Looping.";                    \r
-                       }                                       \r
-               }\r
-               else\r
-               {               \r
-                       THROW_ON_ERROR(ret, "av_read_frame", print());\r
+                               frame_number_   = 0;\r
 \r
-                       if(packet->stream_index == default_stream_index_)\r
-                               ++frame_number_;\r
+                               if(loop_)\r
+                               {\r
+                                       queued_seek(start_);\r
+                                       graph_->set_tag("seek");                \r
+                                       CASPAR_LOG(trace) << print() << " Looping.";                    \r
+                               }               \r
+                               else\r
+                                       executor_.stop();\r
+                       }\r
+                       else\r
+                       {               \r
+                               THROW_ON_ERROR(ret, "av_read_frame", print());\r
+\r
+                               if(packet->stream_index == default_stream_index_)\r
+                                       ++frame_number_;\r
 \r
-                       THROW_ON_ERROR2(av_dup_packet(packet.get()), print());\r
+                               THROW_ON_ERROR2(av_dup_packet(packet.get()), print());\r
                                \r
-                       // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
-                       auto size = packet->size;\r
-                       auto data = packet->data;\r
+                               // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
+                               auto size = packet->size;\r
+                               auto data = packet->data;\r
                        \r
-                       packet = safe_ptr<AVPacket>(packet.get(), [packet, size, data](AVPacket*)\r
-                       {\r
-                               packet->size = size;\r
-                               packet->data = data;\r
-                       });\r
+                               packet = safe_ptr<AVPacket>(packet.get(), [packet, size, data](AVPacket*)\r
+                               {\r
+                                       packet->size = size;\r
+                                       packet->data = data;                            \r
+                               });\r
 \r
-                       buffer_.try_push(packet);\r
-                       buffer_size_ += packet->size;\r
+                               buffer_.try_push(packet);\r
+                               buffer_size_ += packet->size;\r
                                \r
-                       graph_->set_value("buffer-size", (static_cast<double>(buffer_size_)+0.001)/MAX_BUFFER_SIZE);\r
-                       graph_->set_value("buffer-count", (static_cast<double>(buffer_.size()+0.001)/MAX_BUFFER_COUNT));\r
-               }                       \r
-       }\r
+                               graph_->set_value("buffer-size", (static_cast<double>(buffer_size_)+0.001)/MAX_BUFFER_SIZE);\r
+                               graph_->set_value("buffer-count", (static_cast<double>(buffer_.size()+0.001)/MAX_BUFFER_COUNT));\r
+                       }       \r
 \r
-       bool full() const\r
-       {\r
-               return is_running_ && (is_eof_ || (buffer_size_ > MAX_BUFFER_SIZE || buffer_.size() > MAX_BUFFER_COUNT) && buffer_.size() > MIN_BUFFER_COUNT);\r
-       }\r
-       \r
-       void do_seek(const uint32_t target)\r
+                       if((buffer_size_ < MAX_BUFFER_SIZE || buffer_.size() > MIN_BUFFER_COUNT) && buffer_.size() < MAX_BUFFER_COUNT && executor_.is_running())                        \r
+                               tick();                 \r
+               });\r
+       }       \r
+                       \r
+       void queued_seek(const uint32_t target)\r
        {       \r
                CASPAR_LOG(debug) << print() << " Seeking: " << target;\r
 \r
@@ -235,10 +213,7 @@ struct input::implementation : boost::noncopyable
                auto fixed_target = (target*stream->time_base.den*codec->time_base.num)/(stream->time_base.num*codec->time_base.den)*codec->ticks_per_frame;\r
                \r
                THROW_ON_ERROR2(avformat_seek_file(format_context_.get(), default_stream_index_, std::numeric_limits<int64_t>::min(), fixed_target, std::numeric_limits<int64_t>::max(), 0), print());          \r
-\r
-               is_eof_ = false;\r
-               buffer_cond_.notify_all();\r
-\r
+               \r
                auto flush_packet       = create_packet();\r
                flush_packet->data      = nullptr;\r
                flush_packet->size      = 0;\r
@@ -247,18 +222,6 @@ struct input::implementation : boost::noncopyable
                buffer_.push(flush_packet);\r
        }       \r
 \r
-       void seek(uint32_t target)\r
-       {\r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
-               std::shared_ptr<AVPacket> packet;\r
-               while(try_pop(packet))\r
-               {\r
-               }\r
-\r
-               do_seek(target);\r
-       }\r
-\r
        bool is_eof(int ret)\r
        {\r
                if(ret == AVERROR(EIO))\r
@@ -268,16 +231,11 @@ struct input::implementation : boost::noncopyable
 \r
                return ret == AVERROR_EOF || ret == AVERROR(EIO) || frame_number_ >= length_; // av_read_frame doesn't always correctly return AVERROR_EOF;\r
        }\r
-       \r
-       std::wstring print() const\r
-       {\r
-               return L"ffmpeg_input[" + filename_ + L")]";\r
-       }\r
 };\r
 \r
 input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length) \r
        : impl_(new implementation(graph, filename, loop, start, length)){}\r
-bool input::eof() const {return impl_->is_eof_;}\r
+bool input::eof() const {return !impl_->executor_.is_running();}\r
 bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
 safe_ptr<AVFormatContext> input::context(){return impl_->format_context_;}\r
 void input::loop(bool value){impl_->loop_ = value;}\r
index 73fd49bf70d4b12adb639dc99898d7ab0d4b45c0..bb11ad3e5c6fd360f19854d52e82fb8a04968b41 100644 (file)
@@ -137,7 +137,7 @@ public:
        \r
        bool ready() const\r
        {\r
-               return packets_.size() > 10;\r
+               return packets_.size() >= 8;\r
        }\r
 \r
        uint32_t nb_frames() const\r
index 779030bff0b8fc84212a89ec945a69c645a222bf..41ab82d22a58631a7fbff2719f5d27b677a5d820 100644 (file)
@@ -201,7 +201,7 @@ safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<core::video_channel
        {\r
                if(flash_producer->print().find(L"flash[") == std::string::npos) // UGLY hack\r
                {\r
-                       flash_producer = make_safe<cg_producer>(flash::create_producer(video_channel->mixer(), boost::assign::list_of<std::wstring>()));        \r
+                       flash_producer = flash::create_producer(video_channel->mixer(), boost::assign::list_of<std::wstring>());        \r
                        video_channel->stage()->load(render_layer, flash_producer); \r
                        video_channel->stage()->play(render_layer);\r
                }\r
@@ -212,7 +212,7 @@ safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<core::video_channel
                throw;\r
        }\r
 \r
-       return static_pointer_cast<cg_producer>(flash_producer);\r
+       return make_safe<cg_producer>(flash_producer);\r
 }\r
 \r
 safe_ptr<core::frame_producer> create_ct_producer(const safe_ptr<core::frame_factory> frame_factory, const std::vector<std::wstring>& params) \r
index e7b37d1b03c1abed594f3de42a4559a648803214..f19f241170995249073b09c57eda68c6428b59ac 100644 (file)
@@ -199,7 +199,7 @@ public:
                                                \r
                ax_->SetSize(width_, height_);          \r
        \r
-               CASPAR_LOG(info) << print() << L" Successfully initialized with template-host: " << filename << L" width: " << width_ << L" height: " << height_ << L".";\r
+               CASPAR_LOG(info) << print() << L" Initialized.";\r
        }\r
 \r
        ~flash_renderer()\r
@@ -272,7 +272,10 @@ public:
        \r
        std::wstring print()\r
        {\r
-               return L"flash[" + boost::filesystem::wpath(filename_).filename() + L"]";               \r
+               return L"flash-player[" + boost::filesystem::wpath(filename_).filename() \r
+                                 + L"|" + boost::lexical_cast<std::wstring>(width_)\r
+                                 + L"x" + boost::lexical_cast<std::wstring>(height_)\r
+                                 + L"]";               \r
        }\r
 };\r
 \r
index a21ec916696a23439c05177554d7d769857f4795..be9336bd965a6363c699d8f444fd3ab7bf0adb29 100644 (file)
@@ -62,8 +62,6 @@ struct image_producer : public core::frame_producer
                std::copy_n(FreeImage_GetBits(bitmap.get()), frame->image_data().size(), frame->image_data().begin());\r
                frame->commit();\r
                frame_ = std::move(frame);\r
-\r
-               CASPAR_LOG(info) << print() << L" Initialized";\r
        }\r
        \r
        // frame_producer\r