]> git.sesse.net Git - casparcg/blobdiff - modules/image/producer/image_scroll_producer.cpp
Changed default log level to info and moved logging statements that we always want...
[casparcg] / modules / image / producer / image_scroll_producer.cpp
index 5d10afc5aa0fd64dad54b63bace5a5aad8893d07..1023b551d8b6b561a3ef2a15b4b441f1792371c3 100644 (file)
 #include <core/frame/frame_factory.h>
 #include <core/frame/frame_transform.h>
 #include <core/frame/pixel_format.h>
+#include <core/frame/audio_channel_layout.h>
 #include <core/monitor/monitor.h>
+#include <core/help/help_sink.h>
+#include <core/help/help_repository.h>
 
 #include <common/env.h>
 #include <common/log.h>
 #include <common/except.h>
 #include <common/array.h>
 #include <common/tweener.h>
+#include <common/param.h>
+#include <common/os/filesystem.h>
 
-#include <boost/assign.hpp>
 #include <boost/filesystem.hpp>
-#include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/property_tree/ptree.hpp>
 #include <boost/scoped_array.hpp>
 
 #include <algorithm>
 #include <array>
-
-using namespace boost::assign;
+#include <cstdint>
 
 namespace caspar { namespace image {
                
 struct image_scroll_producer : public core::frame_producer_base
 {      
-       monitor::basic_subject                  event_subject_;
+       core::monitor::subject                  monitor_subject_;
 
        const std::wstring                              filename_;
        std::vector<core::draw_frame>   frames_;
@@ -66,28 +68,25 @@ struct image_scroll_producer : public core::frame_producer_base
        int                                                             height_;
        core::constraints                               constraints_;
 
-       double                                                  delta_;
+       double                                                  delta_                          = 0.0;
        double                                                  speed_;
 
-       int                                                             start_offset_x_;
-       int                                                             start_offset_y_;
+       int                                                             start_offset_x_         = 0;
+       int                                                             start_offset_y_         = 0;
        bool                                                    progressive_;
        
        explicit image_scroll_producer(
-               const spl::shared_ptr<core::frame_factory>& frame_factory, 
-               const core::video_format_desc& format_desc, 
-               const std::wstring& filename, 
-               double speed,
-               double duration,
-               int motion_blur_px = 0,
-               bool premultiply_with_alpha = false,
-               bool progressive = false)
+                       const spl::shared_ptr<core::frame_factory>& frame_factory,
+                       const core::video_format_desc& format_desc,
+                       const std::wstring& filename,
+                       double speed,
+                       double duration,
+                       int motion_blur_px = 0,
+                       bool premultiply_with_alpha = false,
+                       bool progressive = false)
                : filename_(filename)
-               , delta_(0)
                , format_desc_(format_desc)
                , speed_(speed)
-               , start_offset_x_(0)
-               , start_offset_y_(0)
                , progressive_(progressive)
        {
                auto bitmap = load_image(filename_);
@@ -102,7 +101,7 @@ struct image_scroll_producer : public core::frame_producer_base
                bool horizontal = height_ == format_desc_.height;
 
                if (!vertical && !horizontal)
-                       BOOST_THROW_EXCEPTION(
+                       CASPAR_THROW_EXCEPTION(
                                caspar::invalid_argument() << msg_info("Neither width nor height matched the video resolution"));
 
                if (vertical)
@@ -162,7 +161,7 @@ struct image_scroll_producer : public core::frame_producer_base
 
                        blurred_copy.reset(new uint8_t[count]);
                        image_view<bgra_pixel> blurred_view(blurred_copy.get(), width_, height_);
-                       core::tweener blur_tweener(L"easeInQuad");
+                       caspar::tweener blur_tweener(L"easeInQuad");
                        blur(original_view, blurred_view, angle, motion_blur_px, blur_tweener);
                        bytes = blurred_copy.get();
                        bitmap.reset();
@@ -176,7 +175,7 @@ struct image_scroll_producer : public core::frame_producer_base
                        {
                                core::pixel_format_desc desc = core::pixel_format::bgra;
                                desc.planes.push_back(core::pixel_format_desc::plane(width_, format_desc_.height, 4));
-                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc);
+                               auto frame = frame_factory->create_frame(this, desc, core::audio_channel_layout::invalid());
 
                                if(count >= frame.image_data(0).size())
                                {       
@@ -205,7 +204,7 @@ struct image_scroll_producer : public core::frame_producer_base
                        {
                                core::pixel_format_desc desc = core::pixel_format::bgra;
                                desc.planes.push_back(core::pixel_format_desc::plane(format_desc_.width, height_, 4));
-                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc);
+                               auto frame = frame_factory->create_frame(this, desc, core::audio_channel_layout::invalid());
                                if(count >= frame.image_data(0).size())
                                {       
                                        for(int y = 0; y < height_; ++y)
@@ -245,7 +244,7 @@ struct image_scroll_producer : public core::frame_producer_base
                std::vector<core::draw_frame> result;
                result.reserve(frames_.size());
 
-               BOOST_FOREACH(auto& frame, frames_)
+               for (auto& frame : frames_)
                {
                        auto& fill_translation = frame.transform().image_transform.fill_translation;
 
@@ -349,9 +348,9 @@ struct image_scroll_producer : public core::frame_producer_base
                        result = core::draw_frame::interlace(field1, field2, format_desc_.field_mode);
                }
                
-               event_subject_ << monitor::event("file/path") % filename_
-                                          << monitor::event("delta") % delta_ 
-                                          << monitor::event("speed") % speed_;
+               monitor_subject_ << core::monitor::message("/file/path") % filename_
+                                                << core::monitor::message("/delta") % delta_ 
+                                                << core::monitor::message("/speed") % speed_;
 
                return result;
        }
@@ -393,71 +392,82 @@ struct image_scroll_producer : public core::frame_producer_base
                }
        }
 
-       void subscribe(const monitor::observable::observer_ptr& o) override                                                                                                                     
+       core::monitor::subject& monitor_output()
        {
-               return event_subject_.subscribe(o);
-       }
-
-       void unsubscribe(const monitor::observable::observer_ptr& o) override           
-       {
-               return event_subject_.unsubscribe(o);
+               return monitor_subject_;
        }
 };
 
-spl::shared_ptr<core::frame_producer> create_scroll_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+void describe_scroll_producer(core::help_sink& sink, const core::help_repository& repo)
 {
-       static const std::vector<std::wstring> extensions = list_of(L".png")(L".tga")(L".bmp")(L".jpg")(L".jpeg")(L".gif")(L".tiff")(L".tif")(L".jp2")(L".jpx")(L".j2k")(L".j2c");
-       std::wstring filename = env::media_folder() + L"\\" + params[0];
+       sink.short_description(L"Scrolls an image either horizontally or vertically.");
+       sink.syntax(L"[image_file:string] SPEED [speed:float] {BLUR [blur_px:int]} {[premultiply:PREMULTIPLY]} {[progressive:PROGRESSIVE]}");
+       sink.para()
+               ->text(L"Scrolls an image either horizontally or vertically. ")
+               ->text(L"It is the image dimensions that decide if it will be a vertical scroll or a horizontal scroll. ")
+               ->text(L"A horizontal scroll will be selected if the image height is exactly the same as the video format height. ")
+               ->text(L"A vertical scroll will be selected if the image width is exactly the same as the video format width.");
+       sink.definitions()
+               ->item(L"image_file", L"The image without extension. The file has to have either the same width or the same height as the video format.")
+               ->item(L"speed", L"A positive or negative float defining how many pixels to move the image each frame.")
+               ->item(L"blur_px", L"If specified, will do a directional blur in the scrolling direction by the given number of pixels.")
+               ->item(L"premultiply", L"If the image is in straight alpha, use this option to make it display correctly in CasparCG.")
+               ->item(L"progressive", L"When an interlaced video format is used, by default the image is moved every field. This can be overridden by specifying this option, causing the image to only move on full frames.");
+       sink.para()->text(L"If ")->code(L"SPEED [speed]")->text(L" is ommitted, the ordinary ")->see(L"Image Producer")->text(L" will be used instead.");
+       sink.example(L">> PLAY 1-10 cred_1280 SPEED 8 BLUR 2", L"Given that cred_1280 is a as wide as the video mode, this will create a rolling end credits with a little bit of blur and a speed of 8 pixels per frame.");
+}
+
+spl::shared_ptr<core::frame_producer> create_scroll_producer(const core::frame_producer_dependencies& dependencies, const std::vector<std::wstring>& params)
+{
+       static const auto extensions = {
+               L".png",
+               L".tga",
+               L".bmp",
+               L".jpg",
+               L".jpeg",
+               L".gif",
+               L".tiff",
+               L".tif",
+               L".jp2",
+               L".jpx",
+               L".j2k",
+               L".j2c"
+       };
+       std::wstring filename = env::media_folder() + params.at(0);
        
        auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool
-               {                                       
-                       return boost::filesystem::is_regular_file(boost::filesystem::path(filename).replace_extension(ex));
-               });
+       {
+               auto file = caspar::find_case_insensitive(boost::filesystem::path(filename).replace_extension(ex).wstring());
+
+               return static_cast<bool>(file);
+       });
 
        if(ext == extensions.end())
                return core::frame_producer::empty();
        
-       double speed = 0.0;
        double duration = 0.0;
-       auto speed_it = std::find(params.begin(), params.end(), L"SPEED");
-       if(speed_it != params.end())
-       {
-               if(++speed_it != params.end())
-                       speed = boost::lexical_cast<double>(*speed_it);
-       }
+       double speed = get_param(L"SPEED", params, 0.0);
 
        if (speed == 0)
-       {
-               auto duration_it = std::find(params.begin(), params.end(), L"DURATION");
-
-               if (duration_it != params.end() && ++duration_it != params.end())
-               {
-                       duration = boost::lexical_cast<double>(*duration_it);
-               }
-       }
+               duration = get_param(L"DURATION", params, 0.0);
 
        if(speed == 0 && duration == 0)
                return core::frame_producer::empty();
 
-       int motion_blur_px = 0;
-       auto blur_it = std::find(params.begin(), params.end(), L"BLUR");
-       if (blur_it != params.end() && ++blur_it != params.end())
-       {
-               motion_blur_px = boost::lexical_cast<int>(*blur_it);
-       }
+       int motion_blur_px = get_param(L"BLUR", params, 0);
 
-       bool premultiply_with_alpha = std::find(params.begin(), params.end(), L"PREMULTIPLY") != params.end();
-       bool progressive = std::find(params.begin(), params.end(), L"PROGRESSIVE") != params.end();
+       bool premultiply_with_alpha = contains_param(L"PREMULTIPLY", params);
+       bool progressive = contains_param(L"PROGRESSIVE", params);
 
        return core::create_destroy_proxy(spl::make_shared<image_scroll_producer>(
-               frame_factory, 
-               format_desc, 
-               filename + *ext, 
-               -speed, 
-               -duration, 
-               motion_blur_px, 
-               premultiply_with_alpha,
-               progressive));
+                       dependencies.frame_factory,
+                       dependencies.format_desc,
+                       *caspar::find_case_insensitive(filename + *ext),
+                       -speed,
+                       -duration,
+                       motion_blur_px,
+                       premultiply_with_alpha,
+                       progressive));
 }
 
-}}
\ No newline at end of file
+}}