]> git.sesse.net Git - casparcg/blobdiff - core/producer/flash/flash_producer.cpp
2.0.0.2:
[casparcg] / core / producer / flash / flash_producer.cpp
index 50b1adf10634e78aae3fccd3a3154418475e21be..ca777dff21ca1ee730c12f592a71903ab672f3db 100644 (file)
 #include "bitmap.h"\r
 \r
 #include "../../format/video_format.h"\r
-#include "../../../common/utility/find_file.h"\r
 #include "../../server.h"\r
 #include "../../../common/concurrency/executor.h"\r
-#include "../../../common/utility/memory.h"\r
 #include "../../../common/utility/scope_exit.h"\r
 \r
-#include "../../processor/frame.h"\r
+#include "../../processor/draw_frame.h"\r
 #include "../../processor/composite_frame.h"\r
 \r
 #include <boost/assign.hpp>\r
@@ -59,20 +57,17 @@ extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;
 struct flash_producer::implementation\r
 {      \r
        implementation(flash_producer* self, const std::wstring& filename) \r
-               : flashax_container_(nullptr), filename_(filename), self_(self),\r
-                       bitmap_pool_(new bitmap_pool), executor_([=]{run();}), invalid_count_(0)\r
+               : flashax_container_(nullptr), filename_(filename), self_(self), executor_([=]{run();}), invalid_count_(0)\r
        {       \r
                if(!boost::filesystem::exists(filename))\r
-                       BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(common::narrow(filename)));\r
+                       BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(narrow(filename)));\r
 \r
-               frame_buffer_.set_capacity(flash_producer::DEFAULT_BUFFER_SIZE);                \r
+               frame_buffer_.set_capacity(3);          \r
        }\r
 \r
        ~implementation() \r
        {\r
                stop();\r
-               if(frame_processor_)\r
-                       frame_processor_->release_tag(this);\r
        }\r
 \r
        void start(bool force = true)\r
@@ -156,7 +151,7 @@ struct flash_producer::implementation
                        {\r
                                CASPAR_LOG(debug) << "Retrying. Count: " << retries;\r
                                if(retries > 3)\r
-                                       BOOST_THROW_EXCEPTION(operation_failed() << warg_name_info(L"param") << warg_value_info(param));\r
+                                       BOOST_THROW_EXCEPTION(operation_failed() << arg_name_info("param") << arg_value_info(narrow(param)));\r
                        }\r
                        is_empty_ = false;      \r
                });\r
@@ -187,7 +182,7 @@ struct flash_producer::implementation
                                stop();\r
 \r
                                frame_buffer_.clear();\r
-                               frame_buffer_.try_push(nullptr); // EOF\r
+                               frame_buffer_.try_push(draw_frame::eof()); // EOF\r
                \r
                                current_frame_ = nullptr;\r
                        });\r
@@ -228,92 +223,80 @@ struct flash_producer::implementation
                        }\r
 \r
                        auto format_desc = frame_processor_->get_video_format_desc();\r
-                       bool is_progressive = format_desc.update == video_update_format::progressive || (flashax_container_->GetFPS() - format_desc.fps/2 == 0);\r
+                       bool is_progressive = format_desc.mode == video_mode::progressive || (flashax_container_->GetFPS() - format_desc.fps/2 == 0);\r
 \r
-                       frame_ptr result;\r
-\r
-                       if(is_progressive)                                                      \r
-                               result = do_render_frame();             \r
+                       std::shared_ptr<draw_frame> frame;\r
+                       if(is_progressive)\r
+                               frame = do_receive();\r
                        else\r
-                       {\r
-                               frame_ptr frame1 = do_render_frame();\r
-                               frame_ptr frame2 = do_render_frame();\r
-                               result = composite_frame::interlace(frame1, frame2, format_desc.update);\r
-                       }\r
-\r
-                       frame_buffer_.push(result);\r
+                               frame = std::shared_ptr<composite_frame>(composite_frame::interlace(do_receive(), do_receive(), format_desc.mode));\r
+                       \r
+                       frame_buffer_.push(frame);\r
                        is_empty_ = flashax_container_->IsEmpty();\r
                }\r
        }\r
                \r
-       frame_ptr do_render_frame()\r
+       safe_ptr<draw_frame> do_receive()\r
        {\r
                auto format_desc = frame_processor_->get_video_format_desc();\r
 \r
                flashax_container_->Tick();\r
                invalid_count_ = !flashax_container_->InvalidRectangle() ? std::min(2, invalid_count_+1) : 0;\r
                if(current_frame_ == nullptr || invalid_count_ < 2)\r
-               {               \r
-                       bitmap_ptr frame;               \r
-                       if(!bitmap_pool_->try_pop(frame))                                       \r
-                       {       \r
-                               CASPAR_LOG(trace) << "Allocated bitmap";\r
-                               frame = std::make_shared<bitmap>(format_desc.width, format_desc.height);                                        \r
-                               common::clear(frame->data(), frame->size());\r
-                       }\r
-                       flashax_container_->DrawControl(frame->hdc());\r
-\r
-                       auto pool = bitmap_pool_;\r
-                       current_frame_.reset(frame.get(), [=](bitmap*)\r
-                       {\r
-                               if(pool->try_push(frame))\r
-                                       common::clear(frame->data(), frame->size());\r
-                       });\r
+               {                               \r
+                       std::fill_n(bmp_frame_->data(), bmp_frame_->size(), 0);                 \r
+                       flashax_container_->DrawControl(bmp_frame_->hdc());\r
+                       current_frame_ = bmp_frame_;\r
                }       \r
 \r
-               auto frame = frame_processor_->create_frame(format_desc.width, format_desc.height, this);\r
-               common::aligned_parallel_memcpy(frame->data(), current_frame_->data(), current_frame_->size()); \r
-\r
+               auto frame = frame_processor_->create_frame(format_desc.width, format_desc.height);\r
+               std::copy(current_frame_->data(), current_frame_->data() + current_frame_->size(), frame->pixel_data().begin());\r
                return frame;\r
        }\r
                \r
-       frame_ptr render_frame()\r
-       {\r
-               if(!frame_buffer_.try_pop(last_frame_) && is_empty_)\r
-                       return frame::empty();\r
-               \r
-               return last_frame_;\r
+       safe_ptr<draw_frame> receive()\r
+       {               \r
+               return ((frame_buffer_.try_pop(last_frame_) || !is_empty_) && last_frame_) ? safe_ptr<draw_frame>(last_frame_) : draw_frame::empty();\r
        }\r
 \r
-       void initialize(const frame_processor_device_ptr& frame_processor)\r
+       void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
        {\r
                frame_processor_ = frame_processor;\r
+               auto format_desc = frame_processor_->get_video_format_desc();\r
+               bmp_frame_ = std::make_shared<bitmap>(format_desc.width, format_desc.height);\r
                start(false);\r
        }\r
-       \r
-       typedef tbb::concurrent_bounded_queue<bitmap_ptr> bitmap_pool;\r
-       std::shared_ptr<bitmap_pool> bitmap_pool_;\r
 \r
+       std::wstring print() const\r
+       {\r
+               return L"flash_producer. filename: " + filename_;\r
+       }\r
+       \r
        CComObject<flash::FlashAxContainer>* flashax_container_;\r
                \r
-       tbb::concurrent_bounded_queue<frame_ptr> frame_buffer_;\r
-       frame_ptr last_frame_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<draw_frame>> frame_buffer_;\r
+\r
+       std::shared_ptr<draw_frame> last_frame_;\r
+\r
        bitmap_ptr current_frame_;\r
-               \r
+       bitmap_ptr bmp_frame_;\r
+\r
        std::wstring filename_;\r
        flash_producer* self_;\r
 \r
        tbb::atomic<bool> is_empty_;\r
-       common::executor executor_;\r
+       executor executor_;\r
        int invalid_count_;\r
 \r
-       frame_processor_device_ptr frame_processor_;\r
+       std::shared_ptr<frame_processor_device> frame_processor_;\r
 };\r
 \r
+flash_producer::flash_producer(flash_producer&& other) : impl_(std::move(other.impl_)){}\r
 flash_producer::flash_producer(const std::wstring& filename) : impl_(new implementation(this, filename)){}\r
-frame_ptr flash_producer::render_frame(){return impl_->render_frame();}\r
+safe_ptr<draw_frame> flash_producer::receive(){return impl_->receive();}\r
 void flash_producer::param(const std::wstring& param){impl_->param(param);}\r
-void flash_producer::initialize(const frame_processor_device_ptr& frame_processor) { impl_->initialize(frame_processor);}\r
+void flash_producer::initialize(const safe_ptr<frame_processor_device>& frame_processor) { impl_->initialize(frame_processor);}\r
+std::wstring flash_producer::print() const {return impl_->print();}\r
 \r
 std::wstring flash_producer::find_template(const std::wstring& template_name)\r
 {\r
@@ -326,13 +309,20 @@ std::wstring flash_producer::find_template(const std::wstring& template_name)
        return L"";\r
 }\r
 \r
-flash_producer_ptr create_flash_producer(const std::vector<std::wstring>& params)\r
+safe_ptr<flash_producer> create_flash_producer(const std::vector<std::wstring>& params)\r
 {\r
-       // TODO: Check for flash support\r
-       auto filename = params[0];\r
-       std::wstring result_filename = common::find_file(server::media_folder() + filename, list_of(L"swf"));\r
+       static const std::vector<std::wstring> extensions = list_of(L"swf");\r
+       std::wstring filename = server::media_folder() + L"\\" + params[0];\r
+       \r
+       auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
+               {                                       \r
+                       return boost::filesystem::is_regular_file(boost::filesystem::wpath(filename).replace_extension(ex));\r
+               });\r
+\r
+       if(ext == extensions.end())\r
+               BOOST_THROW_EXCEPTION(file_not_found() << msg_info(narrow(filename)));\r
 \r
-       return result_filename.empty() ? nullptr : std::make_shared<flash_producer>(result_filename);\r
+       return make_safe<flash_producer>(filename + L"." + *ext);\r
 }\r
 \r
 }}}
\ No newline at end of file