]> git.sesse.net Git - casparcg/commitdiff
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 17 Dec 2010 18:39:10 +0000 (18:39 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 17 Dec 2010 18:39:10 +0000 (18:39 +0000)
29 files changed:
common/concurrency/executor.h
common/gl/frame_buffer_object.cpp
common/gl/frame_buffer_object.h
core/core.vcxproj
core/core.vcxproj.filters
core/processor/audio_processor.cpp
core/processor/audio_processor.h
core/processor/composite_frame.cpp
core/processor/composite_frame.h
core/processor/draw_frame.h
core/processor/frame_processor_device.cpp
core/processor/fwd.h
core/processor/image_processor.cpp
core/processor/image_processor.h
core/processor/image_shader.cpp [deleted file]
core/processor/image_shader.h [deleted file]
core/processor/read_frame.h
core/processor/transform_frame.cpp
core/processor/transform_frame.h
core/processor/write_frame.cpp
core/processor/write_frame.h
core/producer/ffmpeg/ffmpeg_producer.cpp
core/producer/ffmpeg/input.cpp
core/producer/ffmpeg/video/video_decoder.cpp
core/producer/ffmpeg/video/video_decoder.h
core/producer/ffmpeg/video/video_transformer.cpp
core/producer/ffmpeg/video/video_transformer.h
core/producer/transition/transition_producer.cpp
shell/main.cpp

index abbfee8d96023a6f00cadb3b7e31b7ae5c463c9f..cf421106c837bdb83e4638e120012eccef425e43 100644 (file)
@@ -15,8 +15,17 @@ namespace caspar {
 class executor\r
 {\r
 public:\r
+\r
+       enum priority\r
+       {\r
+               low_priority = 0,\r
+               normal_priority,\r
+               high_priority\r
+       };\r
+\r
        explicit executor(const std::function<void()>& f = nullptr)\r
        {\r
+               size_ = 0;\r
                is_running_ = false;\r
                f_ = f != nullptr ? f : [this]{run();};\r
        }\r
@@ -40,43 +49,33 @@ public:
        \r
        void stop() // noexcept\r
        {\r
-               if(is_running_.fetch_and_store(false))\r
-               {\r
-                       execution_queue_.clear();\r
-                       execution_queue_.push([](){});                  \r
-               }\r
+               is_running_ = false;            \r
                thread_.join();\r
        }\r
 \r
        void execute() // noexcept\r
        {\r
-               std::function<void()> func;\r
-               execution_queue_.pop(func);     \r
-               func();\r
+               boost::unique_lock<boost::mutex> lock(mut_);\r
+               while(size_ < 1)                \r
+                       cond_.wait(lock);\r
+               \r
+               try_execute();\r
        }\r
 \r
        bool try_execute() // noexcept\r
        {\r
                std::function<void()> func;\r
-               if(execution_queue_.try_pop(func))\r
+               if(execution_queue_[high_priority].try_pop(func) || execution_queue_[normal_priority].try_pop(func) || execution_queue_[low_priority].try_pop(func))\r
+               {\r
                        func();\r
+                       --size_;\r
+               }\r
 \r
                return func != nullptr;\r
        }\r
-\r
-       void clear() // noexcept\r
-       {\r
-               execution_queue_.clear();\r
-       }\r
-\r
+                       \r
        template<typename Func>\r
-       void enqueue(Func&& func) // noexcept\r
-       {\r
-               execution_queue_.push([=]{try{func();}catch(...){CASPAR_LOG_CURRENT_EXCEPTION();}});\r
-       }\r
-       \r
-       template<typename Func>\r
-       auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
+       auto begin_invoke(Func&& func, priority p = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
        {       \r
                typedef decltype(func()) result_type; \r
                                \r
@@ -92,7 +91,7 @@ public:
                        }\r
                        catch(boost::task_already_started&){}\r
                }));\r
-               execution_queue_.push([=]\r
+               execution_queue_[p].push([=]\r
                {\r
                        try\r
                        {\r
@@ -101,17 +100,19 @@ public:
                        catch(boost::task_already_started&){}\r
                        catch(...){CASPAR_LOG_CURRENT_EXCEPTION();}\r
                });\r
+               ++size_;\r
+               cond_.notify_one();\r
 \r
                return std::move(future);               \r
        }\r
        \r
        template<typename Func>\r
-       auto invoke(Func&& func) -> decltype(func())\r
+       auto invoke(Func&& func, priority p = normal_priority) -> decltype(func())\r
        {\r
                if(boost::this_thread::get_id() == thread_.get_id())  // Avoids potential deadlock.\r
                        return func();\r
                \r
-               return begin_invoke(std::forward<Func>(func)).get();\r
+               return begin_invoke(std::forward<Func>(func), p).get();\r
        }\r
                \r
 private:\r
@@ -123,10 +124,14 @@ private:
                        execute();\r
        }\r
 \r
+       tbb::atomic<size_t> size_;\r
+       boost::condition_variable cond_;\r
+       boost::mutex mut_;\r
+\r
        std::function<void()> f_;\r
        boost::thread thread_;\r
        tbb::atomic<bool> is_running_;\r
-       tbb::concurrent_bounded_queue<std::function<void()>> execution_queue_;\r
+       std::array<tbb::concurrent_bounded_queue<std::function<void()>>, 3> execution_queue_;\r
 };\r
 \r
 }
\ No newline at end of file
index 55075fd1d8354a00a974bfe941be9629379823e5..880db4d33ceaa081aca47cad35c9593efde2521e 100644 (file)
@@ -13,7 +13,7 @@ namespace caspar { namespace gl {
 struct frame_buffer_object::implementation\r
 {\r
 public:\r
-       implementation(size_t width, size_t height, GLenum mode) : mode_(mode)\r
+       implementation(size_t width, size_t height, GLenum mode) : mode_(mode), width_(width), height_(height)\r
        {\r
                GL(glGenTextures(1, &texture_));        \r
                GL(glBindTexture(GL_TEXTURE_2D, texture_));                     \r
@@ -46,4 +46,6 @@ public:
 \r
 frame_buffer_object::frame_buffer_object(size_t width, size_t height, GLenum mode) : impl_(new implementation(width, height, mode)){}\r
 void frame_buffer_object::bind_pixel_source() {impl_->bind_pixel_source();}\r
+size_t frame_buffer_object::width() const{return impl_->width_;}\r
+size_t frame_buffer_object::height() const{return impl_->height_;}\r
 }}
\ No newline at end of file
index 3808c91bce975ca943b686fcfffad46aa401c4ef..c107d8c611c7cf5e7f1098da705b842eaff29d44 100644 (file)
@@ -11,6 +11,8 @@ class frame_buffer_object
 public:\r
        frame_buffer_object(size_t width, size_t height, GLenum mode = GL_COLOR_ATTACHMENT0_EXT);\r
        void bind_pixel_source();\r
+       size_t width() const;\r
+       size_t height() const;\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index a03479b9bbf990f4bf6e217dd2e0e41ff017f388..2567ac77a2ecd2ea44fb60c75c2a6a2c4e99c976 100644 (file)
     <ClInclude Include="processor\composite_frame.h" />\r
     <ClInclude Include="processor\frame_processor_device.h" />\r
     <ClInclude Include="processor\image_processor.h" />\r
-    <ClInclude Include="processor\image_shader.h" />\r
     <ClInclude Include="processor\fwd.h" />\r
     <ClInclude Include="processor\draw_frame.h" />\r
     <ClInclude Include="processor\read_frame.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="processor\image_shader.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="processor\read_frame.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
index 789c0911c54ac254271183b9bda12dae2c28f1d7..ef4597be7fe0f9e373afe67fc32e59363707a868 100644 (file)
       <UniqueIdentifier>{eaa43a39-9ff0-4291-b717-4d4231d8295a}</UniqueIdentifier>\r
     </Filter>\r
     <Filter Include="Source\channel\processor\image">\r
-      <UniqueIdentifier>{30fe40ca-8bf0-4a46-a882-16d07b2b441e}</UniqueIdentifier>\r
+      <UniqueIdentifier>{fe2c2f78-7daf-4b6d-9132-eda45b4c93e1}</UniqueIdentifier>\r
     </Filter>\r
     <Filter Include="Source\channel\processor\audio">\r
-      <UniqueIdentifier>{43ca44bb-d718-44df-9342-1913750f7e41}</UniqueIdentifier>\r
+      <UniqueIdentifier>{e3d8bd98-8cb9-4f4a-8cf0-bd455ce9138d}</UniqueIdentifier>\r
     </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="processor\draw_frame.h">\r
       <Filter>Source\channel\processor\frame</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="processor\image_shader.h">\r
-      <Filter>Source\channel\processor\image</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="processor\image_processor.h">\r
       <Filter>Source\channel\processor\image</Filter>\r
     </ClInclude>\r
     <ClCompile Include="format\pixel_format.cpp">\r
       <Filter>Source\channel\format</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="processor\image_shader.cpp">\r
-      <Filter>Source\channel\processor\image</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="processor\image_processor.cpp">\r
       <Filter>Source\channel\processor\image</Filter>\r
     </ClCompile>\r
index e16a5c9e59bc636f3c7ee34f61a87adaef4aa30b..530e70f3f10b775895f0ee3ed94956fe5f090116 100644 (file)
@@ -3,5 +3,68 @@
 #include "audio_processor.h"\r
 \r
 namespace caspar { namespace core {\r
+       \r
+audio_transform& audio_transform::operator*=(const audio_transform &other) \r
+{\r
+       volume *= other.volume;\r
+       return *this;\r
+}\r
+\r
+const audio_transform audio_transform::operator*(const audio_transform &other) const \r
+{\r
+       return audio_transform(*this) *= other;\r
+}\r
+\r
+struct audio_processor::implementation\r
+{\r
+       implementation()\r
+       {\r
+               transform_stack_.push(audio_transform());\r
+       }\r
+\r
+       void begin(const audio_transform& transform)\r
+       {\r
+               transform_stack_.push(transform_stack_.top()*transform);\r
+       }\r
+\r
+       void process(const std::vector<short>& audio_data)\r
+       {               \r
+               if(audio_data_.empty())\r
+                       audio_data_.resize(audio_data.size(), 0);\r
+\r
+               tbb::parallel_for\r
+               (\r
+                       tbb::blocked_range<size_t>(0, audio_data.size()),\r
+                       [&](const tbb::blocked_range<size_t>& r)\r
+                       {\r
+                               for(size_t n = r.begin(); n < r.end(); ++n)\r
+                               {\r
+                                       int sample = static_cast<int>(audio_data[n]);\r
+                                       sample = (static_cast<int>(transform_stack_.top().volume*8192.0)*sample)/8192;\r
+                                       audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + sample) & 0xFFFF);\r
+                               }\r
+                       }\r
+               );\r
+       }\r
+\r
+       void end()\r
+       {\r
+               transform_stack_.pop();\r
+       }\r
+\r
+       std::vector<short> read()\r
+       {\r
+               return std::move(audio_data_);\r
+       }\r
+\r
+       std::vector<short> audio_data_;\r
+       std::stack<audio_transform> transform_stack_;\r
+};\r
+\r
+audio_processor::audio_processor() : impl_(new implementation()){}\r
+void audio_processor::begin(const audio_transform& transform){impl_->begin(transform);}\r
+void audio_processor::process(const std::vector<short>& audio_data){impl_->process(audio_data);}\r
+void audio_processor::end(){impl_->end();}\r
+std::vector<short> audio_processor::read(){return impl_->read();}\r
 \r
 }}
\ No newline at end of file
index 52e17836edd7add0e9daf4e9152fd6ed52bc1adf..4e082c11baaecfe48e8a86db0472e4f37734191e 100644 (file)
@@ -2,11 +2,32 @@
 \r
 namespace caspar { namespace core {\r
 \r
+struct audio_transform\r
+{\r
+       audio_transform() : volume(1.0){}\r
+       double volume;\r
+\r
+       audio_transform& operator*=(const audio_transform &other);\r
+       const audio_transform operator*(const audio_transform &other) const;\r
+};\r
+\r
 class audio_processor\r
 {\r
 public:\r
+       audio_processor();\r
+\r
+       void begin(const audio_transform& transform);\r
+       void process(const std::vector<short>& audio_data);\r
+       void end();\r
+\r
+       std::vector<short> read();\r
+\r
+       void begin_pass(){}\r
+       void end_pass(){}\r
 \r
 private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
 };\r
 \r
 }}
\ No newline at end of file
index 0e91b7cbc1a95e3fdb6b45bca49c204fa65d337a..cc9da92bef008eefca52ad22f8010fab4a277b8f 100644 (file)
@@ -3,7 +3,7 @@
 #include "draw_frame.h"\r
 #include "composite_frame.h"\r
 #include "transform_frame.h"\r
-#include "image_shader.h"\r
+#include "image_processor.h"\r
 #include "../../common/utility/singleton_pool.h"\r
 \r
 #include <boost/range/algorithm.hpp>\r
 \r
 namespace caspar { namespace core {\r
        \r
-struct composite_frame::implementation : public draw_frame_decorator\r
-{      \r
-       implementation(std::vector<safe_ptr<draw_frame>>&& frames) : frames_(std::move(frames))\r
-       {               \r
-               if(frames_.size() < 2)\r
-                       return;\r
-\r
-               boost::range::for_each(frames_, [&](const safe_ptr<draw_frame>& frame)\r
-               {\r
-                       if(audio_data_.empty())\r
-                               audio_data_ = frame->audio_data();\r
-                       else\r
-                       {\r
-                               tbb::parallel_for\r
-                               (\r
-                                       tbb::blocked_range<size_t>(0, frame->audio_data().size()),\r
-                                       [&](const tbb::blocked_range<size_t>& r)\r
-                                       {\r
-                                               for(size_t n = r.begin(); n < r.end(); ++n)                                     \r
-                                                       audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + static_cast<int>(frame->audio_data()[n])) & 0xFFFF);                                            \r
-                                       }\r
-                               );\r
-                       }\r
-               });\r
-       }\r
-       \r
-       void unmap()\r
-       {\r
-               boost::range::for_each(frames_, std::bind(&draw_frame_decorator::unmap, std::placeholders::_1));\r
-       }\r
-               \r
-       void draw(image_shader& shader)\r
+struct composite_frame::implementation\r
+{              \r
+       implementation(const std::vector<safe_ptr<draw_frame>>& frames) : frames_(frames){}\r
+                       \r
+       void process_image(image_processor& processor)\r
        {\r
-               boost::range::for_each(frames_, std::bind(&draw_frame_decorator::draw, std::placeholders::_1, std::ref(shader)));\r
+               boost::range::for_each(frames_, std::bind(&draw_frame::process_image, std::placeholders::_1, std::ref(processor)));\r
        }\r
 \r
-       const std::vector<short>& audio_data() const\r
+       void process_audio(audio_processor& processor)\r
        {\r
-               static std::vector<short> no_audio;\r
-               return !audio_data_.empty() ? audio_data_ : (!frames_.empty() ? frames_.front()->audio_data() : no_audio);\r
+               boost::range::for_each(frames_, std::bind(&draw_frame::process_audio, std::placeholders::_1, std::ref(processor)));\r
        }\r
-                               \r
-       std::vector<short> audio_data_;\r
+                                       \r
        std::vector<safe_ptr<draw_frame>> frames_;\r
 };\r
 \r
-composite_frame::composite_frame(std::vector<safe_ptr<draw_frame>>&& frames) : impl_(singleton_pool<implementation>::make_shared(std::move(frames))){}\r
+composite_frame::composite_frame(const std::vector<safe_ptr<draw_frame>>& frames) : impl_(singleton_pool<implementation>::make_shared(frames)){}\r
 composite_frame::composite_frame(composite_frame&& other) : impl_(std::move(other.impl_)){}\r
 composite_frame::composite_frame(const composite_frame& other) : impl_(singleton_pool<implementation>::make_shared(*other.impl_)){}\r
 void composite_frame::swap(composite_frame& other){impl_.swap(other.impl_);}\r
@@ -83,9 +54,8 @@ composite_frame::composite_frame(safe_ptr<draw_frame>&& frame1, safe_ptr<draw_fr
        impl_.reset(new implementation(std::move(frames)));\r
 }\r
 \r
-void composite_frame::unmap(){impl_->unmap();}\r
-void composite_frame::draw(image_shader& shader){impl_->draw(shader);}\r
-const std::vector<short>& composite_frame::audio_data() const {return impl_->audio_data();}\r
+void composite_frame::process_image(image_processor& processor){impl_->process_image(processor);}\r
+void composite_frame::process_audio(audio_processor& processor){impl_->process_audio(processor);}\r
 \r
 safe_ptr<composite_frame> composite_frame::interlace(safe_ptr<draw_frame>&& frame1, safe_ptr<draw_frame>&& frame2, video_mode::type mode)\r
 {                      \r
@@ -105,7 +75,7 @@ safe_ptr<composite_frame> composite_frame::interlace(safe_ptr<draw_frame>&& fram
        std::vector<safe_ptr<draw_frame>> frames;\r
        frames.push_back(std::move(my_frame1));\r
        frames.push_back(std::move(my_frame2));\r
-       return make_safe<composite_frame>(std::move(frames));\r
+       return make_safe<composite_frame>(frames);\r
 }\r
 \r
 }}
\ No newline at end of file
index d4c86e3d417a529920ef0079517442d9ce8d15a4..e904d89ba374b364575f06eb33d5eab633478d32 100644 (file)
@@ -14,7 +14,7 @@ namespace caspar { namespace core {
 class composite_frame : public draw_frame\r
 {\r
 public:\r
-       explicit composite_frame(std::vector<safe_ptr<draw_frame>>&& frames);\r
+       composite_frame(const std::vector<safe_ptr<draw_frame>>& frames);\r
        composite_frame(safe_ptr<draw_frame>&& frame1, safe_ptr<draw_frame>&& frame2);\r
        \r
        void swap(composite_frame& other);\r
@@ -26,12 +26,10 @@ public:
        composite_frame& operator=(composite_frame&& other);\r
 \r
        static safe_ptr<composite_frame> interlace(safe_ptr<draw_frame>&& frame1, safe_ptr<draw_frame>&& frame2, video_mode::type mode);\r
-       \r
-       virtual const std::vector<short>& audio_data() const;\r
-\r
+               \r
 private:       \r
-       virtual void unmap();\r
-       virtual void draw(image_shader& shader);\r
+       virtual void process_image(image_processor& processor);\r
+       virtual void process_audio(audio_processor& processor);\r
 \r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 9c9321d702f29d7c290581c894c60997a202b087..14ea92829058e1bf258b5bd6e0c4e22e9e0b322a 100644 (file)
@@ -3,39 +3,22 @@
 #include "fwd.h"\r
 \r
 #include <boost/noncopyable.hpp>\r
-#include <boost/range/iterator_range.hpp>\r
-#include <boost/operators.hpp>\r
-\r
-#include <memory>\r
-#include <vector>\r
-#include <type_traits>\r
 \r
 #include "../../common/utility/safe_ptr.h"\r
 \r
 namespace caspar { namespace core {\r
                \r
-struct draw_frame_decorator;\r
-\r
 class draw_frame : boost::noncopyable\r
 {      \r
-       friend struct draw_frame_decorator;\r
-       friend class image_processor;\r
 public:\r
        virtual ~draw_frame(){}\r
-\r
-       virtual const std::vector<short>& audio_data() const = 0;               \r
-\r
+       \r
        static safe_ptr<draw_frame> eof()\r
        {\r
                struct eof_frame : public draw_frame\r
                {\r
-                       virtual const std::vector<short>& audio_data() const\r
-                       {\r
-                               static std::vector<short> audio_data;\r
-                               return audio_data;\r
-                       }\r
-                       virtual void unmap(){}\r
-                       virtual void draw(image_shader&){}\r
+                       virtual void process_image(image_processor&){}\r
+                       virtual void process_audio(audio_processor&){}\r
                };\r
                static safe_ptr<draw_frame> frame = make_safe<eof_frame>();\r
                return frame;\r
@@ -45,28 +28,17 @@ public:
        {\r
                struct empty_frame : public draw_frame\r
                {\r
-                       virtual const std::vector<short>& audio_data() const\r
-                       {\r
-                               static std::vector<short> audio_data;\r
-                               return audio_data;\r
-                       }\r
-                       virtual void unmap(){}\r
-                       virtual void draw(image_shader&){}\r
+                       virtual void process_image(image_processor&){}\r
+                       virtual void process_audio(audio_processor&){}\r
                };\r
                static safe_ptr<draw_frame> frame = make_safe<empty_frame>();\r
                return frame;\r
        }\r
-private:\r
-       virtual void unmap() = 0;\r
-       virtual void draw(image_shader& shader) = 0;\r
-};\r
 \r
-struct draw_frame_decorator\r
-{\r
-protected:\r
-       static void unmap(const safe_ptr<draw_frame>& frame) {frame->unmap();}\r
-       static void draw(const safe_ptr<draw_frame>& frame, image_shader& shader) {frame->draw(shader);}\r
+       virtual void process_image(image_processor& processor) = 0;\r
+       virtual void process_audio(audio_processor& processor) = 0;\r
 };\r
 \r
 \r
+\r
 }}
\ No newline at end of file
index 6809dcdd84a741dc9f5b994a924fa064d81e7fa7..c36c6d33e5d7b5597297a0bdc59bc3dd10123cf3 100644 (file)
@@ -2,7 +2,9 @@
 \r
 #include "frame_processor_device.h"\r
 \r
+#include "audio_processor.h"\r
 #include "image_processor.h"\r
+\r
 #include "write_frame.h"\r
 #include "read_frame.h"\r
 \r
@@ -12,6 +14,7 @@
 #include "../../common/concurrency/executor.h"\r
 #include "../../common/gl/utility.h"\r
 \r
+\r
 #include <tbb/concurrent_queue.h>\r
 #include <tbb/concurrent_unordered_map.h>\r
 \r
@@ -26,16 +29,31 @@ struct frame_processor_device::implementation : boost::noncopyable
 {      \r
        typedef boost::shared_future<safe_ptr<const read_frame>> output_type;\r
 \r
-       implementation(const video_format_desc& format_desc) : fmt_(format_desc)\r
+       implementation(const video_format_desc& format_desc) : fmt_(format_desc), writing_(draw_frame::empty()), image_processor_(format_desc)\r
        {               \r
                output_.set_capacity(3);\r
                executor_.start();\r
-               executor_.invoke([=]{image_processor_.reset(new image_processor(format_desc));});\r
        }\r
                                \r
        void send(safe_ptr<draw_frame>&& frame)\r
        {                       \r
-               output_.push(executor_.begin_invoke([=]{return image_processor_->render(safe_ptr<draw_frame>(frame));})); // Blocks\r
+               output_.push(executor_.begin_invoke([=]() -> safe_ptr<const read_frame>\r
+               {               \r
+                       auto result = image_processor_.read();\r
+                       result->audio_data(audio_processor_.read());\r
+\r
+                       image_processor_.begin_pass();\r
+                       writing_->process_image(image_processor_);\r
+                       image_processor_.end_pass();\r
+\r
+                       audio_processor_.begin_pass();\r
+                       writing_->process_audio(audio_processor_);\r
+                       audio_processor_.end_pass();\r
+\r
+                       writing_ = frame;\r
+\r
+                       return result;\r
+               }));\r
        }\r
 \r
        safe_ptr<const read_frame> receive()\r
@@ -53,15 +71,22 @@ struct frame_processor_device::implementation : boost::noncopyable
                        frame = executor_.invoke([&]{return std::make_shared<write_frame>(desc);});             \r
                return safe_ptr<write_frame>(frame.get(), [=](write_frame*)\r
                {\r
-                       executor_.begin_invoke([=]{frame->map();});\r
-                       frame->audio_data().clear();\r
-                       pool->push(frame);\r
+                       executor_.begin_invoke([=]\r
+                       {\r
+                               frame->map();\r
+                               pool->push(frame);\r
+                       }, executor::high_priority);\r
                });\r
        }\r
+       \r
+       const video_format_desc format_desc_;\r
+               \r
+       safe_ptr<draw_frame>    writing_;\r
+\r
+       audio_processor audio_processor_;\r
+       image_processor image_processor_;\r
                                \r
        executor executor_;     \r
-\r
-       std::unique_ptr<image_processor> image_processor_;      \r
                                \r
        tbb::concurrent_bounded_queue<output_type> output_;     \r
        tbb::concurrent_unordered_map<pixel_format_desc, tbb::concurrent_bounded_queue<std::shared_ptr<write_frame>>, std::hash<pixel_format_desc>> pools_;\r
index 854eaf43b67b505846e12c1b23c0bf0c3e8f63d5..1e03e2525c902b37f5a25aa26f0e019bdcde9a99 100644 (file)
@@ -13,7 +13,8 @@ class draw_frame;
 class transform_frame;\r
 class composite_frame;\r
 \r
-class image_shader;\r
 class image_processor;\r
+class frame_processor;\r
+class audio_processor;\r
 class frame_processor_device;\r
 }}
\ No newline at end of file
index b485eba195245def999da4004d0944b7db79a511..bcfee8c784eb9bed16170752d0fe89da69685c23 100644 (file)
@@ -2,27 +2,17 @@
 \r
 #include "image_processor.h"\r
 \r
-#include "image_shader.h"\r
-#include "write_frame.h"\r
-#include "read_frame.h"\r
-\r
-#include "../format/video_format.h"\r
-\r
 #include "../../common/exception/exceptions.h"\r
 #include "../../common/gl/utility.h"\r
+#include "../../common/gl/shader_program.h"\r
 #include "../../common/gl/frame_buffer_object.h"\r
 \r
 #include <Glee.h>\r
 #include <SFML/Window.hpp>\r
 \r
-#include <tbb/concurrent_queue.h>\r
+#include <boost/noncopyable.hpp>\r
 \r
-#include <boost/range/algorithm_ext/erase.hpp>\r
-#include <boost/range/algorithm.hpp>\r
-\r
-#include <functional>\r
-\r
-namespace caspar { namespace core {\r
+#include <unordered_map>\r
 \r
 struct ogl_context\r
 {\r
@@ -30,53 +20,245 @@ struct ogl_context
        sf::Context context_;\r
 };\r
 \r
+namespace caspar { namespace core {\r
+\r
+GLubyte progressive_pattern[] = {\r
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+       \r
+GLubyte upper_pattern[] = {\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
+               \r
+GLubyte lower_pattern[] = {\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
+       \r
 struct image_processor::implementation : boost::noncopyable\r
-{              \r
-       implementation(const video_format_desc& format_desc) : shader_(format_desc), format_desc_(format_desc),\r
-               fbo_(format_desc.width, format_desc.height), writing_(draw_frame::empty()), reading_(create_reading())\r
-       {       \r
+{\r
+       implementation(const video_format_desc& format_desc) : fbo_(format_desc.width, format_desc.height), current_(pixel_format::invalid), reading_(create_reading())\r
+       {\r
+               alpha_stack_.push(1.0);\r
+               GL(glEnable(GL_POLYGON_STIPPLE));\r
+               GL(glEnable(GL_TEXTURE_2D));\r
+               GL(glEnable(GL_BLEND));\r
+               GL(glDisable(GL_DEPTH_TEST));\r
+               GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));                  \r
+               GL(glViewport(0, 0, format_desc.width, format_desc.height));\r
                reading_->unmap();\r
+\r
+               std::string common_vertex = \r
+                       "void main()                                                                                                                    "\r
+                       "{                                                                                                                                              "\r
+                       "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                     "\r
+                       "       gl_FrontColor = gl_Color;                                                                                       "\r
+                       "       gl_Position = ftransform();                                                                                     "\r
+                       "}                                                                                                                                              ";\r
+\r
+               std::string common_fragment = \r
+                       "uniform sampler2D      plane[4];                                                                                       "\r
+                       "uniform vec4           plane_size[2];                                                                          "\r
+                                                                                                                                                               \r
+                       // NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf               \r
+                       // TODO: Support for more yuv formats might be needed.                                  \r
+                       "vec4 ycbcra_to_bgra(float y, float cb, float cr, float a)                              "\r
+                       "{                                                                                                                                              "\r
+                       "       cb -= 0.5;                                                                                                                      "\r
+                       "       cr -= 0.5;                                                                                                                      "\r
+                       "       y = 1.164*(y-0.0625);                                                                                           "\r
+                       "                                                                                                                                               "\r
+                       "       vec4 color;                                                                                                                     "\r
+                       "       color.r = y + 1.596 * cr;                                                                                       "\r
+                       "       color.g = y - 0.813 * cr - 0.337633 * cb;                                                       "\r
+                       "       color.b = y + 2.017 * cb;                                                                                       "\r
+                       "       color.a = a;                                                                                                            "\r
+                       "                                                                                                                                               "\r
+                       "       return color;                                                                                                           "\r
+                       "}                                                                                                                                              "                       \r
+                       "                                                                                                                                               ";\r
+                       \r
+               shaders_[pixel_format::abgr] = gl::shader_program(common_vertex, common_fragment +\r
+\r
+                       "void main()                                                                                                                    "\r
+                       "{                                                                                                                                              "\r
+                       "       vec4 abgr = texture2D(plane[0], gl_TexCoord[0].st);"\r
+                       "       gl_FragColor = abgr.argb * gl_Color;                                                            "\r
+                       "}                                                                                                                                              ");\r
+               \r
+               shaders_[pixel_format::argb]= gl::shader_program(common_vertex, common_fragment +\r
+\r
+                       "void main()                                                                                                                    "       \r
+                       "{                                                                                                                                              "\r
+                       "       vec4 argb = texture2D(plane[0], gl_TexCoord[0].st);"\r
+                       "       gl_FragColor = argb.grab * gl_Color;                                                            "       \r
+                       "}                                                                                                                                              ");\r
+               \r
+               shaders_[pixel_format::bgra]= gl::shader_program(common_vertex, common_fragment +\r
+\r
+                       "void main()                                                                                                                    "\r
+                       "{                                                                                                                                              "\r
+                       "       vec4 bgra = texture2D(plane[0], gl_TexCoord[0].st);"\r
+                       "       gl_FragColor = bgra.rgba * gl_Color;                                                            "\r
+                       "}                                                                                                                                              ");\r
+               \r
+               shaders_[pixel_format::rgba] = gl::shader_program(common_vertex, common_fragment +\r
+\r
+                       "void main()                                                                                                                    "\r
+                       "{                                                                                                                                              "\r
+                       "       vec4 rgba = texture2D(plane[0], gl_TexCoord[0].st);                                     "\r
+                       "       gl_FragColor = rgba.bgra * gl_Color;                                                            "\r
+                       "}                                                                                                                                              ");\r
+               \r
+               shaders_[pixel_format::ycbcr] = gl::shader_program(common_vertex, common_fragment +\r
+\r
+                       "void main()                                                                                                                    "\r
+                       "{                                                                                                                                              "\r
+                       "       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;"\r
+                       "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;"\r
+                       "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;"\r
+                       "       float a = 1.0;                                                                                                          "       \r
+                       "       gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color;                 "\r
+                       "}                                                                                                                                              ");\r
+               \r
+               shaders_[pixel_format::ycbcra] = gl::shader_program(common_vertex, common_fragment +\r
+\r
+                       "void main()                                                                                                                    "\r
+                       "{                                                                                                                                              "\r
+                       "       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;"\r
+                       "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;"\r
+                       "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;"\r
+                       "       float a  = texture2D(plane[3], gl_TexCoord[0].st).r;"\r
+                       "       gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color;                         "\r
+                       "}                                                                                                                                              ");\r
        }\r
-                               \r
-       safe_ptr<const read_frame> render(safe_ptr<draw_frame>&& frame)\r
-       {                                                               \r
-               frame->unmap(); // Start transfer from system memory to texture. End with draw in next tick.\r
 \r
-               reading_->map(); // Map texture to system memory.\r
-               auto result = reading_;\r
+       void begin(const image_transform& transform)\r
+       {\r
+               alpha_stack_.push(alpha_stack_.top()*transform.alpha);\r
 \r
-               GL(glClear(GL_COLOR_BUFFER_BIT));\r
+               glPushMatrix();\r
+               glColor4d(1.0, 1.0, 1.0, alpha_stack_.top());\r
+               glTranslated(transform.pos.get<0>()*2.0, transform.pos.get<1>()*2.0, 0.0);\r
+\r
+               if(transform.mode == video_mode::upper)\r
+                       glPolygonStipple(upper_pattern);\r
+               else if(transform.mode == video_mode::lower)\r
+                       glPolygonStipple(lower_pattern);\r
+               else\r
+                       glPolygonStipple(progressive_pattern);\r
+       }\r
+               \r
+       void render(const pixel_format_desc& desc, std::vector<gl::pbo>& pbos)\r
+       {\r
+               set_pixel_format(desc.pix_fmt);\r
+\r
+               for(size_t n = 0; n < pbos.size(); ++n)\r
+               {\r
+                       glActiveTexture(GL_TEXTURE0+n);\r
+                       pbos[n].unmap_write();\r
+               }\r
 \r
-               writing_->draw(shader_); // Draw to frame buffer.\r
-               writing_ = frame;\r
+               glBegin(GL_QUADS);\r
+                       glTexCoord2d(0.0, 0.0); glVertex2d(-1.0, -1.0);\r
+                       glTexCoord2d(1.0, 0.0); glVertex2d( 1.0, -1.0);\r
+                       glTexCoord2d(1.0, 1.0); glVertex2d( 1.0,  1.0);\r
+                       glTexCoord2d(0.0, 1.0); glVertex2d(-1.0,  1.0);\r
+               glEnd();\r
+       }\r
 \r
+       void end()\r
+       {\r
+               alpha_stack_.pop();\r
+               glPopMatrix();\r
+       }\r
+\r
+       void begin_pass()\r
+       {\r
+               GL(glClear(GL_COLOR_BUFFER_BIT));\r
+       }\r
+\r
+       void end_pass()\r
+       {\r
                reading_ = create_reading();\r
                reading_->unmap(); // Start transfer from frame buffer to texture. End with map in next tick.\r
-               reading_->audio_data(writing_->audio_data());\r
+       }\r
+\r
+       safe_ptr<read_frame> read()\r
+       {\r
+               reading_->map();\r
+               return reading_;\r
+       }\r
 \r
-               return result;\r
+       void set_pixel_format(pixel_format::type format)\r
+       {\r
+               if(current_ == format)\r
+                       return;\r
+               current_ = format;\r
+               shaders_[format].use();\r
        }\r
 \r
        safe_ptr<read_frame> create_reading()\r
        {\r
                std::shared_ptr<read_frame> frame;\r
                if(!pool_.try_pop(frame))               \r
-                       frame = std::make_shared<read_frame>(format_desc_.width, format_desc_.height);\r
+                       frame = std::make_shared<read_frame>(fbo_.width(), fbo_.height());\r
                return safe_ptr<read_frame>(frame.get(), [=](read_frame*){pool_.push(frame);});\r
        }\r
 \r
        const ogl_context context_;\r
-       const gl::fbo fbo_;\r
-       const video_format_desc format_desc_;\r
-\r
+                \r
        tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>> pool_;\r
-       \r
-       safe_ptr<read_frame>    reading_;\r
-       safe_ptr<draw_frame>    writing_;\r
 \r
-       image_shader shader_;\r
+       std::stack<double> alpha_stack_;\r
+\r
+       pixel_format::type current_;\r
+       std::unordered_map<pixel_format::type, gl::shader_program> shaders_;\r
+       gl::fbo fbo_;\r
+\r
+       safe_ptr<read_frame> reading_;\r
 };\r
-       \r
-image_processor::image_processor(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-safe_ptr<const read_frame> image_processor::render(safe_ptr<draw_frame>&& frame){return impl_->render(std::move(frame));}\r
+\r
+image_processor::image_processor(const video_format_desc& format_desc) : format_desc_(format_desc){}\r
+void image_processor::begin(const image_transform& transform) \r
+{\r
+       if(!impl_)\r
+               impl_.reset(new implementation(format_desc_));\r
+       impl_->begin(transform);\r
+}\r
+void image_processor::process(const pixel_format_desc& desc, std::vector<gl::pbo>& pbos)\r
+{\r
+       if(!impl_)\r
+               impl_.reset(new implementation(format_desc_));\r
+       impl_->render(desc, pbos);\r
+}\r
+void image_processor::end()\r
+{\r
+       if(!impl_)\r
+               impl_.reset(new implementation(format_desc_));\r
+       impl_->end();\r
+}\r
+void image_processor::begin_pass()\r
+{\r
+       if(!impl_)\r
+               impl_.reset(new implementation(format_desc_));\r
+       impl_->begin_pass();\r
+}\r
+void image_processor::end_pass()\r
+{\r
+       if(!impl_)\r
+               impl_.reset(new implementation(format_desc_));\r
+       impl_->end_pass();\r
+}\r
+safe_ptr<read_frame> image_processor::read()\r
+{\r
+       if(!impl_)\r
+               impl_.reset(new implementation(format_desc_));\r
+       return impl_->read();\r
+}\r
 }}
\ No newline at end of file
index a2af401feef3afe806a0964ef6d477cb5cef68f0..87c790758aff2794d52d8a7ef95e62ce2b3610a6 100644 (file)
@@ -1,46 +1,43 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
 #pragma once\r
 \r
-#include "fwd.h"\r
-\r
-#include "../../common/utility/safe_ptr.h"\r
+#include "read_frame.h"\r
 \r
 #include "../format/video_format.h"\r
+#include "../format/pixel_format.h"\r
 \r
-#include <boost/noncopyable.hpp>\r
+#include <boost/tuple/tuple.hpp>\r
 \r
 #include <memory>\r
+#include <array>\r
 \r
 namespace caspar { namespace core {\r
+       \r
+struct image_transform\r
+{\r
+       image_transform() : alpha(1.0), pos(boost::make_tuple(0.0, 0.0)), uv(boost::make_tuple(0.0, 1.0, 1.0, 0.0)), mode(video_mode::invalid){}\r
+       double alpha;\r
+       boost::tuple<double, double> pos;\r
+       boost::tuple<double, double, double, double> uv;\r
+       video_mode::type mode; \r
+};\r
 \r
-class image_processor : boost::noncopyable\r
+class image_processor\r
 {\r
 public:\r
-       image_processor(const video_format_desc& format_desc_);\r
-               \r
-       safe_ptr<const read_frame> render(safe_ptr<draw_frame>&& frame);\r
+       image_processor(const video_format_desc& format_desc);\r
+\r
+       void begin(const image_transform& transform);\r
+       void process(const pixel_format_desc& desc, std::vector<gl::pbo>& pbos);\r
+       void end();\r
+\r
+       void begin_pass();\r
+       void end_pass();\r
+       safe_ptr<read_frame> read();\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
+       video_format_desc format_desc_;\r
 };\r
-typedef std::shared_ptr<image_processor> image_processor_ptr;\r
+typedef std::shared_ptr<image_processor> image_shader_ptr;\r
 \r
 }}
\ No newline at end of file
diff --git a/core/processor/image_shader.cpp b/core/processor/image_shader.cpp
deleted file mode 100644 (file)
index 676fc2f..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-#include "../StdAfx.h"\r
-\r
-#include "image_shader.h"\r
-\r
-#include "../../common/exception/exceptions.h"\r
-#include "../../common/gl/utility.h"\r
-#include "../../common/gl/shader_program.h"\r
-\r
-#include <Glee.h>\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <unordered_map>\r
-\r
-namespace caspar { namespace core {\r
-\r
-GLubyte progressive_pattern[] = {\r
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
-       \r
-GLubyte upper_pattern[] = {\r
-       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
-       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
-       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
-       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
-               \r
-GLubyte lower_pattern[] = {\r
-       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \r
-       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
-       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
-       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
-       \r
-struct image_shader::implementation : boost::noncopyable\r
-{\r
-       implementation(const video_format_desc& format_desc) : current_(pixel_format::invalid), alpha_(1.0)\r
-       {\r
-               GL(glEnable(GL_POLYGON_STIPPLE));\r
-               GL(glEnable(GL_TEXTURE_2D));\r
-               GL(glEnable(GL_BLEND));\r
-               GL(glDisable(GL_DEPTH_TEST));\r
-               GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));                  \r
-               GL(glViewport(0, 0, format_desc.width, format_desc.height));\r
-\r
-               transform_stack_.push(shader_transform());\r
-               std::string common_vertex = \r
-                       "void main()                                                                                                                    "\r
-                       "{                                                                                                                                              "\r
-                       "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                     "\r
-                       "       gl_FrontColor = gl_Color;                                                                                       "\r
-                       "       gl_Position = ftransform();                                                                                     "\r
-                       "}                                                                                                                                              ";\r
-\r
-               std::string common_fragment = \r
-                       "uniform sampler2D      plane[4];                                                                                       "\r
-                       "uniform vec4           plane_size[2];                                                                          "\r
-                                                                                                                                                               \r
-                       // NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf               \r
-                       // TODO: Support for more yuv formats might be needed.                                  \r
-                       "vec4 ycbcra_to_bgra(float y, float cb, float cr, float a)                              "\r
-                       "{                                                                                                                                              "\r
-                       "       cb -= 0.5;                                                                                                                      "\r
-                       "       cr -= 0.5;                                                                                                                      "\r
-                       "       y = 1.164*(y-0.0625);                                                                                           "\r
-                       "                                                                                                                                               "\r
-                       "       vec4 color;                                                                                                                     "\r
-                       "       color.r = y + 1.596 * cr;                                                                                       "\r
-                       "       color.g = y - 0.813 * cr - 0.337633 * cb;                                                       "\r
-                       "       color.b = y + 2.017 * cb;                                                                                       "\r
-                       "       color.a = a;                                                                                                            "\r
-                       "                                                                                                                                               "\r
-                       "       return color;                                                                                                           "\r
-                       "}                                                                                                                                              "                       \r
-                       "                                                                                                                                               ";\r
-                       \r
-               shaders_[pixel_format::abgr] = gl::shader_program(common_vertex, common_fragment +\r
-\r
-                       "void main()                                                                                                                    "\r
-                       "{                                                                                                                                              "\r
-                       "       vec4 abgr = texture2D(plane[0], gl_TexCoord[0].st);"\r
-                       "       gl_FragColor = abgr.argb * gl_Color;                                                            "\r
-                       "}                                                                                                                                              ");\r
-               \r
-               shaders_[pixel_format::argb]= gl::shader_program(common_vertex, common_fragment +\r
-\r
-                       "void main()                                                                                                                    "       \r
-                       "{                                                                                                                                              "\r
-                       "       vec4 argb = texture2D(plane[0], gl_TexCoord[0].st);"\r
-                       "       gl_FragColor = argb.grab * gl_Color;                                                            "       \r
-                       "}                                                                                                                                              ");\r
-               \r
-               shaders_[pixel_format::bgra]= gl::shader_program(common_vertex, common_fragment +\r
-\r
-                       "void main()                                                                                                                    "\r
-                       "{                                                                                                                                              "\r
-                       "       vec4 bgra = texture2D(plane[0], gl_TexCoord[0].st);"\r
-                       "       gl_FragColor = bgra.rgba * gl_Color;                                                            "\r
-                       "}                                                                                                                                              ");\r
-               \r
-               shaders_[pixel_format::rgba] = gl::shader_program(common_vertex, common_fragment +\r
-\r
-                       "void main()                                                                                                                    "\r
-                       "{                                                                                                                                              "\r
-                       "       vec4 rgba = texture2D(plane[0], gl_TexCoord[0].st);                                     "\r
-                       "       gl_FragColor = rgba.bgra * gl_Color;                                                            "\r
-                       "}                                                                                                                                              ");\r
-               \r
-               shaders_[pixel_format::ycbcr] = gl::shader_program(common_vertex, common_fragment +\r
-\r
-                       "void main()                                                                                                                    "\r
-                       "{                                                                                                                                              "\r
-                       "       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;"\r
-                       "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;"\r
-                       "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;"\r
-                       "       float a = 1.0;                                                                                                          "       \r
-                       "       gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color;                 "\r
-                       "}                                                                                                                                              ");\r
-               \r
-               shaders_[pixel_format::ycbcra] = gl::shader_program(common_vertex, common_fragment +\r
-\r
-                       "void main()                                                                                                                    "\r
-                       "{                                                                                                                                              "\r
-                       "       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;"\r
-                       "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;"\r
-                       "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;"\r
-                       "       float a  = texture2D(plane[3], gl_TexCoord[0].st).r;"\r
-                       "       gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color;                         "\r
-                       "}                                                                                                                                              ");\r
-       }\r
-\r
-       void begin(const shader_transform& transform)\r
-       {\r
-               transform_stack_.push(transform);\r
-\r
-               glPushMatrix();\r
-               alpha_ *= transform_stack_.top().alpha;\r
-               glColor4d(1.0, 1.0, 1.0, alpha_);\r
-               glTranslated(transform_stack_.top().pos.get<0>()*2.0, transform_stack_.top().pos.get<1>()*2.0, 0.0);\r
-\r
-               if(transform.mode == video_mode::upper)\r
-                       glPolygonStipple(upper_pattern);\r
-               else if(transform.mode == video_mode::lower)\r
-                       glPolygonStipple(lower_pattern);\r
-               else\r
-                       glPolygonStipple(progressive_pattern);\r
-       }\r
-               \r
-       void render(const pixel_format_desc& desc)\r
-       {\r
-               set_pixel_format(desc.pix_fmt);\r
-\r
-               auto t = transform_stack_.top();\r
-               glBegin(GL_QUADS);\r
-                       glTexCoord2d(0.0, 0.0); glVertex2d(-1.0, -1.0);\r
-                       glTexCoord2d(1.0, 0.0); glVertex2d( 1.0, -1.0);\r
-                       glTexCoord2d(1.0, 1.0); glVertex2d( 1.0,  1.0);\r
-                       glTexCoord2d(0.0, 1.0); glVertex2d(-1.0,  1.0);\r
-               glEnd();\r
-       }\r
-\r
-       void end()\r
-       {\r
-               alpha_ /= transform_stack_.top().alpha;\r
-               glPopMatrix();\r
-               transform_stack_.pop();\r
-       }\r
-\r
-       void set_pixel_format(pixel_format::type format)\r
-       {\r
-               if(current_ == format)\r
-                       return;\r
-               current_ = format;\r
-               shaders_[format].use();\r
-       }\r
-                \r
-       double alpha_;\r
-       std::stack<shader_transform> transform_stack_;\r
-\r
-       pixel_format::type current_;\r
-       std::unordered_map<pixel_format::type, gl::shader_program> shaders_;\r
-};\r
-\r
-image_shader::image_shader(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-void image_shader::begin(const shader_transform& transform) {impl_->begin(transform);}\r
-void image_shader::render(const pixel_format_desc& desc){impl_->render(desc);}\r
-void image_shader::end(){impl_->end();}\r
-}}
\ No newline at end of file
diff --git a/core/processor/image_shader.h b/core/processor/image_shader.h
deleted file mode 100644 (file)
index 209093b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once\r
-\r
-#include "../format/video_format.h"\r
-#include "../format/pixel_format.h"\r
-\r
-#include <boost/tuple/tuple.hpp>\r
-\r
-#include <memory>\r
-#include <array>\r
-\r
-namespace caspar { namespace core {\r
-       \r
-struct shader_transform\r
-{\r
-       shader_transform() : alpha(1.0), pos(boost::make_tuple(0.0, 0.0)), uv(boost::make_tuple(0.0, 1.0, 1.0, 0.0)), mode(video_mode::invalid){}\r
-       double alpha;\r
-       boost::tuple<double, double> pos;\r
-       boost::tuple<double, double, double, double> uv;\r
-       video_mode::type mode; \r
-};\r
-\r
-class image_shader\r
-{\r
-public:\r
-       image_shader(const video_format_desc& format_desc);\r
-\r
-       void begin(const shader_transform& transform);\r
-       void render(const pixel_format_desc& desc);\r
-       void end();\r
-private:\r
-       struct implementation;\r
-       std::shared_ptr<implementation> impl_;\r
-};\r
-typedef std::shared_ptr<image_shader> image_shader_ptr;\r
-\r
-}}
\ No newline at end of file
index 899a25d193f3a0c13c4e5fa2d9d1399c5c1357f2..eaf2279720318d2a5ce3fd732551c93de5263062 100644 (file)
@@ -18,6 +18,7 @@ namespace caspar { namespace core {
        \r
 class read_frame\r
 {\r
+       friend class image_processor;\r
 public:\r
        explicit read_frame(size_t width, size_t height);\r
        \r
@@ -26,10 +27,10 @@ public:
        const std::vector<short>& audio_data() const;\r
        void audio_data(const std::vector<short>& audio_data);\r
        \r
+private:\r
        void unmap();\r
        void map();\r
 \r
-private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
 };\r
index 3fbe84465c002d3b679004347ddbb1d3b09cc739..605b12059251237c9f0d6161260b07dc0c2d5745 100644 (file)
@@ -3,7 +3,8 @@
 #include "transform_frame.h"\r
 \r
 #include "draw_frame.h"\r
-#include "image_shader.h"\r
+#include "image_processor.h"\r
+#include "audio_processor.h"\r
 \r
 #include "../format/pixel_format.h"\r
 #include "../../common/gl/utility.h"\r
 \r
 namespace caspar { namespace core {\r
                                                                                                                                                                                                                                                                                                                \r
-struct transform_frame::implementation : public draw_frame_decorator\r
+struct transform_frame::implementation\r
 {\r
-       implementation(const safe_ptr<draw_frame>& frame) : frame_(frame), audio_volume_(255){}\r
-       implementation(const safe_ptr<draw_frame>& frame, std::vector<short>&& audio_data) : frame_(frame), audio_volume_(255), override_audio_data_(std::move(audio_data)){}\r
-       implementation(safe_ptr<draw_frame>&& frame) : frame_(std::move(frame)), audio_volume_(255){}\r
+       implementation(const safe_ptr<draw_frame>& frame) : frame_(frame){}\r
+       implementation(safe_ptr<draw_frame>&& frame) : frame_(std::move(frame)){}\r
        \r
-       void unmap(){draw_frame_decorator::unmap(frame_);}\r
-\r
-       void draw(image_shader& shader)\r
+       void process_image(image_processor& processor)\r
        {\r
-               shader.begin(transform_);\r
-               draw_frame_decorator::draw(frame_, shader);\r
-               shader.end();\r
+               processor.begin(image_transform_);\r
+               frame_->process_image(processor);\r
+               processor.end();\r
        }\r
 \r
-       void audio_volume(const unsigned char volume)\r
-       {\r
-               if(volume == audio_volume_)\r
-                       return;\r
-               \r
-               audio_volume_ = volume;\r
-\r
-               auto& source = !override_audio_data_.empty() ? override_audio_data_ : frame_->audio_data();\r
-               audio_data_.resize(source.size());\r
-               tbb::parallel_for(tbb::blocked_range<size_t>(0, audio_data_.size()), [&](const tbb::blocked_range<size_t>& r)\r
-               {\r
-                       for(size_t n = r.begin(); n < r.end(); ++n)                                     \r
-                               audio_data_[n] = static_cast<short>((static_cast<int>(source[n])*volume)>>8);                                           \r
-               });\r
-       }\r
-               \r
-       const std::vector<short>& audio_data() const \r
+       void process_audio(audio_processor& processor)\r
        {\r
-               return !audio_data_.empty() ? audio_data_ : (!override_audio_data_.empty() ? override_audio_data_ : frame_->audio_data());\r
+               processor.begin(audio_transform_);\r
+               frame_->process_audio(processor);\r
+               processor.end();\r
        }\r
                \r
-       unsigned char audio_volume_;\r
        safe_ptr<draw_frame> frame_;\r
        std::vector<short> audio_data_;\r
        std::vector<short> override_audio_data_;\r
-       shader_transform transform_;    \r
+       image_transform image_transform_;       \r
+       audio_transform audio_transform_;       \r
 };\r
        \r
 transform_frame::transform_frame() : impl_(singleton_pool<implementation>::make_shared(draw_frame::empty())){}\r
 transform_frame::transform_frame(const safe_ptr<draw_frame>& frame) : impl_(singleton_pool<implementation>::make_shared(frame)){}\r
-transform_frame::transform_frame(const safe_ptr<draw_frame>& frame, std::vector<short>&& audio_data) : impl_(singleton_pool<implementation>::make_shared(frame, std::move(audio_data))){}\r
 transform_frame::transform_frame(safe_ptr<draw_frame>&& frame) : impl_(singleton_pool<implementation>::make_shared(std::move(frame))){}\r
 transform_frame::transform_frame(const transform_frame& other) : impl_(singleton_pool<implementation>::make_shared(*other.impl_)){}\r
 void transform_frame::swap(transform_frame& other){impl_.swap(other.impl_);}\r
@@ -78,12 +61,11 @@ transform_frame& transform_frame::operator=(transform_frame&& other)
        temp.swap(*this);\r
        return *this;\r
 }\r
-void transform_frame::unmap(){impl_->unmap();} \r
-void transform_frame::draw(image_shader& shader){impl_->draw(shader);}\r
-void transform_frame::audio_volume(unsigned char volume){impl_->audio_volume(volume);}\r
-void transform_frame::translate(double x, double y){impl_->transform_.pos = boost::make_tuple(x, y);}\r
-void transform_frame::texcoord(double left, double top, double right, double bottom){impl_->transform_.uv = boost::make_tuple(left, top, right, bottom);}\r
-void transform_frame::video_mode(video_mode::type mode){impl_->transform_.mode = mode;}\r
-void transform_frame::alpha(double value){impl_->transform_.alpha = value;}\r
-const std::vector<short>& transform_frame::audio_data() const { return impl_->audio_data(); }\r
+void transform_frame::process_image(image_processor& processor){impl_->process_image(processor);}\r
+void transform_frame::process_audio(audio_processor& processor){impl_->process_audio(processor);}\r
+void transform_frame::audio_volume(double volume){impl_->audio_transform_.volume = volume;}\r
+void transform_frame::translate(double x, double y){impl_->image_transform_.pos = boost::make_tuple(x, y);}\r
+void transform_frame::texcoord(double left, double top, double right, double bottom){impl_->image_transform_.uv = boost::make_tuple(left, top, right, bottom);}\r
+void transform_frame::video_mode(video_mode::type mode){impl_->image_transform_.mode = mode;}\r
+void transform_frame::alpha(double value){impl_->image_transform_.alpha = value;}\r
 }}
\ No newline at end of file
index ae5a231d023664ac98d20b6c62ace0e3d0187651..ddf301b378b03ee44db564e4fd0fe9d3b9804c88 100644 (file)
@@ -21,7 +21,6 @@ class transform_frame : public draw_frame
 public:\r
        transform_frame();\r
        transform_frame(const safe_ptr<draw_frame>& frame);\r
-       transform_frame(const safe_ptr<draw_frame>& frame, std::vector<short>&& audio_data);\r
        transform_frame(safe_ptr<draw_frame>&& frame);\r
 \r
        void swap(transform_frame& other);\r
@@ -32,18 +31,16 @@ public:
        transform_frame& operator=(const transform_frame& other);\r
        transform_frame& operator=(transform_frame&& other);\r
        \r
-       virtual const std::vector<short>& audio_data() const;\r
-\r
-       void audio_volume(unsigned char volume);\r
+       void audio_volume(double volume);\r
        void translate(double x, double y);\r
        void texcoord(double left, double top, double right, double bottom);\r
        void video_mode(video_mode::type mode);\r
        void alpha(double value);\r
-\r
+       \r
 private:\r
 \r
-       virtual void unmap();\r
-       virtual void draw(image_shader& shader);\r
+       virtual void process_image(image_processor& processor);\r
+       virtual void process_audio(audio_processor& processor);\r
 \r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 2d2ded517e76205bd8f296526bfaa8ad59184ba4..3300d450e527c9796d3b4592034ee1ca526f48e3 100644 (file)
@@ -3,7 +3,8 @@
 #include "write_frame.h"\r
 \r
 #include "draw_frame.h"\r
-#include "image_shader.h"\r
+#include "image_processor.h"\r
+#include "audio_processor.h"\r
 \r
 #include "../format/pixel_format.h"\r
 #include "../../common/gl/utility.h"\r
@@ -38,14 +39,15 @@ struct write_frame::implementation : boost::noncopyable
                boost::range::for_each(pbos_, std::mem_fn(&gl::pbo::map_write));\r
        }\r
 \r
-       void draw(image_shader& shader)\r
+       void process_image(image_processor& processor)\r
        {\r
-               for(size_t n = 0; n < pbos_.size(); ++n)\r
-               {\r
-                       glActiveTexture(GL_TEXTURE0+n);\r
-                       pbos_[n].bind_texture();\r
-               }\r
-               shader.render(desc_);\r
+               processor.process(desc_, pbos_);\r
+       }\r
+\r
+       void process_audio(audio_processor& processor)\r
+       {\r
+               processor.process(audio_data_);\r
+               audio_data_.clear();\r
        }\r
 \r
        boost::iterator_range<unsigned char*> pixel_data(size_t index)\r
@@ -79,9 +81,9 @@ write_frame& write_frame::operator=(write_frame&& other)
 }\r
 void write_frame::map(){impl_->map();} \r
 void write_frame::unmap(){impl_->unmap();}     \r
-void write_frame::draw(image_shader& shader){impl_->draw(shader);}\r
+void write_frame::process_image(image_processor& processor){impl_->process_image(processor);}\r
+void write_frame::process_audio(audio_processor& processor){impl_->process_audio(processor);}\r
 boost::iterator_range<unsigned char*> write_frame::pixel_data(size_t index){return impl_->pixel_data(index);}\r
 const boost::iterator_range<const unsigned char*> write_frame::pixel_data(size_t index) const {return impl_->pixel_data(index);}\r
 std::vector<short>& write_frame::audio_data() { return impl_->audio_data_; }\r
-const std::vector<short>& write_frame::audio_data() const { return impl_->audio_data_; }\r
 }}
\ No newline at end of file
index b4aa453aa613ab749f44085fa2e700098aab4832..c8617d79bc52d3a95945e30e91628f07f051be68 100644 (file)
@@ -4,18 +4,13 @@
 \r
 #include "draw_frame.h"\r
 \r
-#include "../../common/exception/exceptions.h"\r
-#include "../../common/gl/pixel_buffer_object.h"\r
-\r
 #include "../format/video_format.h"\r
 #include "../format/pixel_format.h"\r
 \r
 #include <boost/noncopyable.hpp>\r
-#include <boost/tuple/tuple.hpp>\r
 #include <boost/range/iterator_range.hpp>\r
 \r
 #include <memory>\r
-#include <array>\r
 #include <vector>\r
 \r
 namespace caspar { namespace core {\r
@@ -35,13 +30,13 @@ public:
        const boost::iterator_range<const unsigned char*> pixel_data(size_t index = 0) const;\r
        \r
        std::vector<short>& audio_data();\r
-       virtual const std::vector<short>& audio_data() const;\r
        \r
 private:\r
                \r
        void map();\r
        void unmap();\r
-       void draw(image_shader& shader);\r
+       void process_image(image_processor& processor);\r
+       void process_audio(audio_processor& processor);\r
 \r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 7c9d2fa2ae2078066ca8533ae9278320c791564c..a4d22948ad749e194c5f24597f66cc12d2a4cc67 100644 (file)
@@ -49,7 +49,7 @@ namespace caspar { namespace core { namespace ffmpeg{
 struct ffmpeg_producer_impl\r
 {\r
 public:\r
-       ffmpeg_producer_impl(const std::wstring& filename, const  std::vector<std::wstring>& params) : filename_(filename), underrun_count_(0), last_frame_(draw_frame::empty())\r
+       ffmpeg_producer_impl(const std::wstring& filename, const  std::vector<std::wstring>& params) : filename_(filename), underrun_count_(0), last_frame_(transform_frame(draw_frame::empty()))\r
        {\r
                if(!boost::filesystem::exists(filename))\r
                        BOOST_THROW_EXCEPTION(file_not_found() <<  boost::errinfo_file_name(narrow(filename)));\r
@@ -94,7 +94,7 @@ public:
                                if(!video_packet.empty())\r
                                {\r
                                        auto decoded_frame = video_decoder_->execute(video_packet);\r
-                                       auto frame = make_safe<transform_frame>(video_transformer_->execute(decoded_frame));\r
+                                       auto frame = video_transformer_->execute(decoded_frame);\r
                                        video_frame_channel_.push_back(std::move(frame));       \r
                                }\r
                        }, \r
@@ -116,7 +116,9 @@ public:
                                        audio_chunk_channel_.pop_front();\r
                                }\r
                                                        \r
-                               auto transform = transform_frame(std::move(video_frame_channel_.front()), std::move(audio_data));\r
+                               auto write = std::move(video_frame_channel_.front());\r
+                               write->audio_data() = std::move(audio_data);\r
+                               auto transform = transform_frame(write);\r
                                video_frame_channel_.pop_front();\r
                \r
                                // TODO: Make generic for all formats and modes.\r
@@ -144,11 +146,12 @@ public:
                if(!ouput_channel_.empty())\r
                {\r
                        result = std::move(ouput_channel_.front());\r
-                       last_frame_ = make_safe<transform_frame>(result, std::vector<short>()); // last_frame should not have audio, override it!\r
+                       last_frame_ = transform_frame(result);\r
+                       last_frame_->audio_volume(0.0); // last_frame should not have audio\r
                        ouput_channel_.pop();\r
                }\r
                else if(input_->is_eof())\r
-                       last_frame_ = draw_frame::eof();\r
+                       return draw_frame::eof();\r
 \r
                return result;\r
        }\r
@@ -164,7 +167,7 @@ public:
 \r
        video_decoder_uptr                                              video_decoder_;\r
        video_transformer_uptr                                  video_transformer_;\r
-       std::deque<safe_ptr<transform_frame>>   video_frame_channel_;\r
+       std::deque<safe_ptr<write_frame>>               video_frame_channel_;\r
        \r
        audio_decoder_ptr                                               audio_decoder_;\r
        std::deque<std::vector<short>>                  audio_chunk_channel_;\r
@@ -175,7 +178,7 @@ public:
 \r
        long                                                                    underrun_count_;\r
 \r
-       safe_ptr<draw_frame>                                    last_frame_;\r
+       safe_ptr<transform_frame>                               last_frame_;\r
 \r
        video_format_desc                                               format_desc_;\r
 };\r
index a83ae6f7f567e4f2887c0eb6ce1d179f48a864a1..079a1e731ce7c11b36535e3e0035b04b3b0cad44 100644 (file)
@@ -141,22 +141,30 @@ struct input::implementation : boost::noncopyable
                win32_exception::install_handler();\r
                \r
                is_running_ = true;\r
-               AVPacket tmp_packet;\r
-               while(is_running_)\r
-               {\r
-                       std::shared_ptr<AVPacket> packet(&tmp_packet, av_free_packet);  \r
-                       tbb::queuing_mutex::scoped_lock lock(seek_mutex_);      \r
 \r
-                       if (av_read_frame(format_context_.get(), packet.get()) >= 0) // NOTE: Packet is only valid until next call of av_safe_ptr<read_frame> or av_close_input_file\r
+               try\r
+               {\r
+                       AVPacket tmp_packet;\r
+                       while(is_running_)\r
                        {\r
-                               auto buffer = std::make_shared<aligned_buffer>(packet->data, packet->data + packet->size);\r
-                               if(packet->stream_index == video_s_index_)                                              \r
-                                       video_packet_buffer_.push(buffer);                                              \r
-                               else if(packet->stream_index == audio_s_index_)         \r
-                                       audio_packet_buffer_.push(buffer);              \r
+                               std::shared_ptr<AVPacket> packet(&tmp_packet, av_free_packet);  \r
+                               tbb::queuing_mutex::scoped_lock lock(seek_mutex_);      \r
+\r
+                               if (av_read_frame(format_context_.get(), packet.get()) >= 0) // NOTE: Packet is only valid until next call of av_safe_ptr<read_frame> or av_close_input_file\r
+                               {\r
+                                       auto buffer = std::make_shared<aligned_buffer>(packet->data, packet->data + packet->size);\r
+                                       if(packet->stream_index == video_s_index_)                                              \r
+                                               video_packet_buffer_.push(buffer);                                              \r
+                                       else if(packet->stream_index == audio_s_index_)         \r
+                                               audio_packet_buffer_.push(buffer);              \r
+                               }\r
+                               else if(!loop_ || av_seek_frame(format_context_.get(), -1, 0, AVSEEK_FLAG_BACKWARD) < 0) // TODO: av_seek_frame does not work for all formats\r
+                                       is_running_ = false;\r
                        }\r
-                       else if(!loop_ || av_seek_frame(format_context_.get(), -1, 0, AVSEEK_FLAG_BACKWARD) < 0) // TODO: av_seek_frame does not work for all formats\r
-                               is_running_ = false;\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
                }\r
                \r
                is_running_ = false;\r
index edf8f304fd0412d69d009a829a4d07ea286e082f..b5edfb0e93b514c89b608af051e244d2e9dbc630 100644 (file)
@@ -1,6 +1,8 @@
 #include "../../../stdafx.h"\r
 \r
 #include "video_decoder.h"\r
+\r
+#include "../../../../common/exception/exceptions.h"\r
                \r
 #if defined(_MSC_VER)\r
 #pragma warning (push)\r
@@ -22,19 +24,22 @@ struct video_decoder::implementation : boost::noncopyable
 {\r
        implementation(AVCodecContext* codec_context) : codec_context_(codec_context){}\r
 \r
-       std::shared_ptr<AVFrame> execute(const aligned_buffer& video_packet)\r
+       safe_ptr<AVFrame> execute(const aligned_buffer& video_packet)\r
        {               \r
-               std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
+               safe_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
 \r
                int frame_finished = 0;\r
                const int result = avcodec_decode_video(codec_context_, decoded_frame.get(), &frame_finished, video_packet.data(), video_packet.size());\r
                \r
-               return result >= 0 ? decoded_frame : nullptr;           \r
+               if(result < 0)\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("avcodec_decode_video failed"));\r
+\r
+               return decoded_frame;           \r
        }\r
        \r
        AVCodecContext* codec_context_;\r
 };\r
 \r
 video_decoder::video_decoder(AVCodecContext* codec_context) : impl_(new implementation(codec_context)){}\r
-std::shared_ptr<AVFrame> video_decoder::execute(const aligned_buffer& video_packet){return impl_->execute(video_packet);}\r
+safe_ptr<AVFrame> video_decoder::execute(const aligned_buffer& video_packet){return impl_->execute(video_packet);}\r
 }}}
\ No newline at end of file
index f5c63d2718f9098c5025ff6332cd00c9a22ce44a..5da22c59413c97334d6e0a44663f8657fb78aac6 100644 (file)
@@ -18,7 +18,7 @@ class video_decoder : boost::noncopyable
 {\r
 public:\r
        video_decoder(AVCodecContext* codec_context);\r
-       std::shared_ptr<AVFrame> execute(const aligned_buffer& video_packet);\r
+       safe_ptr<AVFrame> execute(const aligned_buffer& video_packet);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 4a0f9b233e6f1d531bf3d1dc56938c04573a2460..39f490c6a75d8dc01fb84c32c77584b6ff386072 100644 (file)
@@ -103,11 +103,8 @@ struct video_transformer::implementation : boost::noncopyable
                }\r
        }\r
        \r
-       safe_ptr<draw_frame> execute(const std::shared_ptr<AVFrame>& decoded_frame)\r
-       {                               \r
-               if(decoded_frame == nullptr)\r
-                       return draw_frame::eof();\r
-                               \r
+       safe_ptr<write_frame> execute(const safe_ptr<AVFrame>& decoded_frame)\r
+       {                                                               \r
                if(sws_context_ == nullptr)\r
                {\r
                        auto write = frame_processor_->create_frame(desc_);\r
@@ -158,6 +155,6 @@ struct video_transformer::implementation : boost::noncopyable
 };\r
 \r
 video_transformer::video_transformer(AVCodecContext* codec_context) : impl_(new implementation(codec_context)){}\r
-safe_ptr<draw_frame> video_transformer::execute(const std::shared_ptr<AVFrame>& decoded_frame){return impl_->execute(decoded_frame);}\r
+safe_ptr<write_frame> video_transformer::execute(const safe_ptr<AVFrame>& decoded_frame){return impl_->execute(decoded_frame);}\r
 void video_transformer::initialize(const safe_ptr<frame_processor_device>& frame_processor){impl_->initialize(frame_processor); }\r
 }}}
\ No newline at end of file
index 78df2d592b3e7c578ab3d7c81b0f53a258cd212b..d7a020cc2506010f485a8adc1a6023b72db6fe41 100644 (file)
@@ -13,7 +13,7 @@ class video_transformer : boost::noncopyable
 {\r
 public:\r
        video_transformer(AVCodecContext* codec_context);\r
-       safe_ptr<draw_frame> execute(const std::shared_ptr<AVFrame>& video_packet);     \r
+       safe_ptr<write_frame> execute(const safe_ptr<AVFrame>& video_packet);   \r
        void initialize(const safe_ptr<frame_processor_device>& frame_processor);\r
 private:\r
        struct implementation;\r
index 9dbcf87eb47910b1e6614999790b69d4d26cfbc3..3ca738d4ab0cbfe405fe5baffa3099f9df756e74 100644 (file)
@@ -112,13 +112,12 @@ struct transition_producer::implementation : boost::noncopyable
                        return src_frame;\r
                                                                                \r
                double alpha = static_cast<double>(current_frame_)/static_cast<double>(info_.duration);\r
-               unsigned char volume = static_cast<unsigned char>(alpha*256.0);\r
 \r
                auto my_src_frame = transform_frame(src_frame);\r
                auto my_dest_frame = transform_frame(dest_frame);\r
 \r
-               my_src_frame.audio_volume(255-volume);\r
-               my_dest_frame.audio_volume(volume);\r
+               my_src_frame.audio_volume(1.0-alpha);\r
+               my_dest_frame.audio_volume(alpha);\r
 \r
                double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0;           \r
                \r
index 8c4f8871e15a37c250c0ba5f654c88f11f9d5cf5..bc1387de56ad345fe3e2dbdd09b2b49618fe0c20 100644 (file)
@@ -49,7 +49,7 @@ public:
        {\r
                CASPAR_LOG(debug) << L"Started TBB Worker Thread.";\r
                win32_exception::install_handler();\r
-       } \r
+       }\r
 };\r
  \r
 int main(int argc, wchar_t* argv[])\r