\r
#define _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line) name##line\r
#define _CASPAR_EXIT_SCOPE_LINENAME(name, line) _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line)\r
-#define CASPAR_SCOPE_EXIT(f) const auto& _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = caspar::detail::create_scope_exit(f)
\ No newline at end of file
+#define CASPAR_SCOPE_EXIT(f) const auto& _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = caspar::detail::create_scope_exit(f); _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__)
\ No newline at end of file
////////////////////////////////////////////////////////////////////////////////////////////////////\r
/// \class channel\r
///\r
-/// \brief Channel. \r
+/// \brief\r
/// \r
/// |**********| <- empty frame <- |***********| <- frame format <- |**********|\r
/// PROTOCOL -> | PRODUCER | | PROCESSOR | | CONSUMER | -> DISPLAY DEVICE\r
CASPAR_LOG(error) << "BLUECARD ERROR: Failed to disable video output. (device " << device_index_ << TEXT(")"); \r
}\r
\r
- void send(const consumer_frame& frame)\r
+ void send(const read_frame& frame)\r
{ \r
static size_t audio_samples = 1920;\r
static size_t audio_nchannels = 2;\r
unsigned long res_fmt_; \r
unsigned long engine_mode_;\r
\r
- boost::optional<consumer_frame> transferring_frame_;\r
+ boost::optional<read_frame> transferring_frame_;\r
\r
std::array<page_locked_buffer_ptr, 3> hanc_buffers_;\r
int current_id_;\r
};\r
\r
consumer::consumer(const video_format_desc& format_desc, unsigned int device_index, bool embed_audio) : impl_(new implementation(format_desc, device_index, embed_audio)){} \r
-void consumer::send(const consumer_frame& frame){impl_->send(frame);}\r
+void consumer::send(const read_frame& frame){impl_->send(frame);}\r
frame_consumer::sync_mode consumer::synchronize(){return impl_->synchronize();}\r
size_t consumer::buffer_depth() const{return impl_->buffer_depth();}\r
}}}\r
public:\r
consumer(const video_format_desc& format_desc, unsigned int deviceIndex, bool embed_audio = false);\r
\r
- virtual void send(const consumer_frame&);\r
+ virtual void send(const read_frame&);\r
virtual sync_mode synchronize();\r
virtual size_t buffer_depth() const;\r
private:\r
CoUninitialize();\r
}\r
\r
- void send(const consumer_frame& frame)\r
+ void send(const read_frame& frame)\r
{\r
active_ = executor_.begin_invoke([=]\r
{ \r
};\r
\r
decklink_consumer::decklink_consumer(const video_format_desc& format_desc, bool internalKey) : pImpl_(new Implementation(format_desc, internalKey)){}\r
-void decklink_consumer::send(const consumer_frame& frame){pImpl_->send(frame);}\r
+void decklink_consumer::send(const read_frame& frame){pImpl_->send(frame);}\r
frame_consumer::sync_mode decklink_consumer::synchronize(){return pImpl_->synchronize();}\r
size_t decklink_consumer::buffer_depth() const{return pImpl_->buffer_depth();}\r
\r
public:\r
explicit decklink_consumer(const video_format_desc& format_desc, bool internalKey = false);\r
\r
- virtual void send(const consumer_frame&);\r
+ virtual void send(const read_frame&);\r
virtual sync_mode synchronize();\r
virtual size_t buffer_depth() const;\r
private:\r
#pragma once\r
\r
#include "../format/video_format.h"\r
-#include "../processor/consumer_frame.h"\r
+#include "../processor/read_frame.h"\r
\r
#include <boost/noncopyable.hpp>\r
\r
\r
virtual ~frame_consumer() {}\r
\r
- virtual void send(const consumer_frame& frame) = 0;\r
+ virtual void send(const read_frame& frame) = 0;\r
virtual sync_mode synchronize() = 0;\r
virtual size_t buffer_depth() const = 0;\r
};\r
executor_.begin_invoke([=]{tick();});\r
}\r
\r
- void process(const consumer_frame& frame)\r
+ void process(const read_frame& frame)\r
{ \r
buffer_.push_back(frame);\r
\r
common::executor executor_; \r
\r
size_t max_depth_;\r
- std::deque<consumer_frame> buffer_; \r
+ std::deque<read_frame> buffer_; \r
\r
std::vector<frame_consumer_ptr> consumers_;\r
\r
Stop();\r
}\r
\r
- void send(const consumer_frame& frame)\r
+ void send(const read_frame& frame)\r
{ \r
input_.push(frame.audio_data()); \r
\r
};\r
\r
consumer::consumer(const video_format_desc&) : impl_(new implementation()){}\r
-void consumer::send(const consumer_frame& frame){impl_->send(frame);}\r
+void consumer::send(const read_frame& frame){impl_->send(frame);}\r
frame_consumer::sync_mode consumer::synchronize(){return impl_->synchronize();}\r
size_t consumer::buffer_depth() const{return impl_->buffer_depth();}\r
}}}\r
public: \r
explicit consumer(const video_format_desc& format_desc);\r
\r
- virtual void send(const consumer_frame&);\r
+ virtual void send(const read_frame&);\r
virtual sync_mode synchronize();\r
virtual size_t buffer_depth() const;\r
private:\r
return std::make_pair(width, height);\r
}\r
\r
- void render(const consumer_frame& frame)\r
+ void render(const read_frame& frame)\r
{ \r
auto ptr = pbos_.front().end_write();\r
std::copy_n(frame.pixel_data().begin(), frame.pixel_data().size(), reinterpret_cast<char*>(ptr));\r
std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
}\r
\r
- void send(const consumer_frame& frame)\r
+ void send(const read_frame& frame)\r
{\r
active_ = executor_.begin_invoke([=]\r
{\r
\r
consumer::consumer(const video_format_desc& format_desc, unsigned int screen_index, stretch stretch, bool windowed)\r
: impl_(new implementation(format_desc, screen_index, stretch, windowed)){}\r
-void consumer::send(const consumer_frame& frame){impl_->send(frame);}\r
+void consumer::send(const read_frame& frame){impl_->send(frame);}\r
frame_consumer::sync_mode consumer::synchronize(){return impl_->synchronize();}\r
size_t consumer::buffer_depth() const{return impl_->buffer_depth();}\r
}}}\r
public: \r
explicit consumer(const video_format_desc& format_desc, unsigned int screen_index = 0, stretch stretch = stretch::fill, bool windowed = false);\r
\r
- virtual void send(const consumer_frame&);\r
+ virtual void send(const read_frame&);\r
virtual sync_mode synchronize();\r
virtual size_t buffer_depth() const;\r
private:\r
<ClInclude Include="format\pixel_format.h" />\r
<ClInclude Include="format\video_format.h" />\r
<ClInclude Include="processor\composite_frame.h" />\r
- <ClInclude Include="processor\consumer_frame.h" />\r
- <ClInclude Include="processor\drawable_frame.h" />\r
<ClInclude Include="processor\frame_processor_device.h" />\r
<ClInclude Include="processor\frame_renderer.h" />\r
<ClInclude Include="processor\frame_shader.h" />\r
<ClInclude Include="processor\fwd.h" />\r
- <ClInclude Include="processor\producer_frame.h" />\r
+ <ClInclude Include="processor\draw_frame.h" />\r
<ClInclude Include="processor\read_frame.h" />\r
<ClInclude Include="processor\transform_frame.h" />\r
<ClInclude Include="processor\write_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\draw_frame.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\frame_processor_device.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<ClCompile Include="producer\image\image_scroll_producer.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
</ClCompile>\r
<ClCompile Include="producer\layer.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<UniqueIdentifier>{f19ced4f-4ad2-4c0a-b51f-50e89909d669}</UniqueIdentifier>\r
</Filter>\r
<Filter Include="Source\channel\processor\frame">\r
- <UniqueIdentifier>{deed18de-67bf-4bb9-9f5e-565af7ab64eb}</UniqueIdentifier>\r
+ <UniqueIdentifier>{1b9effc5-16ee-4be7-9189-d2b6bec0165a}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\channel\producer\ffmpeg\io">\r
+ <UniqueIdentifier>{eaa43a39-9ff0-4291-b717-4d4231d8295a}</UniqueIdentifier>\r
</Filter>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="producer\ffmpeg\ffmpeg_producer.h">\r
<Filter>Source\channel\producer\ffmpeg</Filter>\r
</ClInclude>\r
- <ClInclude Include="producer\ffmpeg\input.h">\r
- <Filter>Source\channel\producer\ffmpeg</Filter>\r
- </ClInclude>\r
<ClInclude Include="producer\ffmpeg\audio\audio_decoder.h">\r
<Filter>Source\channel\producer\ffmpeg\audio</Filter>\r
</ClInclude>\r
<ClInclude Include="consumer\decklink\util.h">\r
<Filter>Source\channel\consumer\decklink</Filter>\r
</ClInclude>\r
+ <ClInclude Include="processor\fwd.h">\r
+ <Filter>Source\channel\processor</Filter>\r
+ </ClInclude>\r
<ClInclude Include="processor\write_frame.h">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\read_frame.h">\r
+ <ClInclude Include="processor\transform_frame.h">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClInclude>\r
<ClInclude Include="processor\composite_frame.h">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\transform_frame.h">\r
+ <ClInclude Include="processor\read_frame.h">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\fwd.h">\r
- <Filter>Source\channel\processor</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\producer_frame.h">\r
- <Filter>Source\channel\processor</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\consumer_frame.h">\r
- <Filter>Source\channel\processor</Filter>\r
+ <ClInclude Include="producer\ffmpeg\input.h">\r
+ <Filter>Source\channel\producer\ffmpeg\io</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\drawable_frame.h">\r
+ <ClInclude Include="processor\draw_frame.h">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClInclude>\r
</ItemGroup>\r
<ClCompile Include="producer\ffmpeg\ffmpeg_producer.cpp">\r
<Filter>Source\channel\producer\ffmpeg</Filter>\r
</ClCompile>\r
- <ClCompile Include="producer\ffmpeg\input.cpp">\r
- <Filter>Source\channel\producer\ffmpeg</Filter>\r
- </ClCompile>\r
<ClCompile Include="producer\ffmpeg\audio\audio_decoder.cpp">\r
<Filter>Source\channel\producer\ffmpeg\audio</Filter>\r
</ClCompile>\r
<ClCompile Include="consumer\decklink\decklink_consumer.cpp">\r
<Filter>Source\channel\consumer\decklink</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\read_frame.cpp">\r
+ <ClCompile Include="processor\transform_frame.cpp">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClCompile>\r
<ClCompile Include="processor\write_frame.cpp">\r
<ClCompile Include="processor\composite_frame.cpp">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\transform_frame.cpp">\r
+ <ClCompile Include="processor\read_frame.cpp">\r
+ <Filter>Source\channel\processor\frame</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="producer\ffmpeg\input.cpp">\r
+ <Filter>Source\channel\producer\ffmpeg\io</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="processor\draw_frame.cpp">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClCompile>\r
</ItemGroup>\r
#include "../StdAfx.h"\r
\r
-#include "producer_frame.h"\r
+#include "draw_frame.h"\r
#include "composite_frame.h"\r
#include "transform_frame.h"\r
#include "../../common/gl/utility.h"\r
\r
struct composite_frame::implementation : boost::noncopyable\r
{ \r
- implementation(const std::vector<producer_frame>& frames) : frames_(frames) {}\r
- \r
- void begin_write()\r
- {\r
- for(size_t n = 0; n < frames_.size(); ++n)\r
- frames_[n].begin_write();\r
- }\r
-\r
- void end_write()\r
- {\r
- for(size_t n = 0; n < frames_.size(); ++n)\r
- frames_[n].end_write(); \r
- }\r
- \r
- void draw(frame_shader& shader)\r
- {\r
- for(size_t n = 0; n < frames_.size(); ++n)\r
- frames_[n].draw(shader);\r
- }\r
- \r
- std::vector<short>& audio_data()\r
- {\r
- if(!audio_data_.empty() || frames_.empty())\r
- return audio_data_;\r
- \r
- audio_data_.resize(1920*2, 0);\r
- \r
- for(size_t n = 0; n < frames_.size(); ++n)\r
+ implementation(std::vector<draw_frame>&& frames) : frames_(std::move(frames)), audio_data_(1920*2, 0)\r
+ { \r
+ boost::range::for_each(frames_, [&](const draw_frame& frame)\r
{\r
- auto& frame = frames_[n];\r
tbb::parallel_for\r
(\r
tbb::blocked_range<size_t>(0, frame.audio_data().size()),\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 begin_write()\r
+ {\r
+ boost::range::for_each(frames_, std::mem_fn(&draw_frame::begin_write));\r
+ }\r
\r
- return audio_data_;\r
+ void end_write()\r
+ {\r
+ boost::range::for_each(frames_, std::mem_fn(&draw_frame::end_write));\r
}\r
\r
- std::vector<producer_frame> frames_;\r
+ void draw(frame_shader& shader)\r
+ {\r
+ boost::range::for_each(frames_, std::bind(&draw_frame::draw, std::placeholders::_1, std::ref(shader)));\r
+ }\r
+ \r
+ std::vector<draw_frame> frames_;\r
std::vector<short> audio_data_;\r
};\r
\r
-#if defined(_MSC_VER)\r
-#pragma warning (disable : 4355) // 'this' : used in base member initializer list\r
-#endif\r
-\r
-composite_frame::composite_frame(const std::vector<producer_frame>& frames) : impl_(new implementation(frames)){}\r
+composite_frame::composite_frame(std::vector<draw_frame>&& frames) : impl_(new implementation(std::move(frames))){}\r
composite_frame::composite_frame(composite_frame&& other) : impl_(std::move(other.impl_)){}\r
composite_frame& composite_frame::operator=(composite_frame&& other)\r
{\r
return *this;\r
}\r
\r
-composite_frame::composite_frame(const producer_frame& frame1, const producer_frame& frame2)\r
+composite_frame::composite_frame(draw_frame&& frame1, draw_frame&& frame2)\r
{\r
- std::vector<producer_frame> frames;\r
- frames.push_back(frame1);\r
- frames.push_back(frame2);\r
- impl_.reset(new implementation(frames));\r
+ std::vector<draw_frame> frames;\r
+ frames.push_back(std::move(frame1));\r
+ frames.push_back(std::move(frame2));\r
+ impl_.reset(new implementation(std::move(frames)));\r
}\r
\r
void composite_frame::begin_write(){impl_->begin_write();}\r
void composite_frame::end_write(){impl_->end_write();} \r
void composite_frame::draw(frame_shader& shader){impl_->draw(shader);}\r
-std::vector<short>& composite_frame::audio_data(){return impl_->audio_data();}\r
-const std::vector<short>& composite_frame::audio_data() const{return impl_->audio_data();}\r
+const std::vector<short>& composite_frame::audio_data() const {return impl_->audio_data_;}\r
\r
-composite_frame composite_frame::interlace(producer_frame&& frame1, producer_frame&& frame2, video_mode::type mode)\r
+composite_frame composite_frame::interlace(draw_frame&& frame1, draw_frame&& frame2, video_mode::type mode)\r
{ \r
transform_frame my_frame1 = std::move(frame1);\r
transform_frame my_frame2 = std::move(frame2);\r
my_frame2.video_mode(video_mode::upper);\r
}\r
\r
- std::vector<producer_frame> frames;\r
+ std::vector<draw_frame> frames;\r
frames.push_back(std::move(my_frame1));\r
frames.push_back(std::move(my_frame2));\r
- return composite_frame(frames);\r
+ return composite_frame(std::move(frames));\r
}\r
\r
}}
\ No newline at end of file
\r
#include "fwd.h"\r
\r
-#include "drawable_frame.h"\r
+#include "draw_frame.h"\r
\r
#include "../format/video_format.h"\r
\r
\r
namespace caspar { namespace core {\r
\r
-class composite_frame : public drawable_frame\r
+class composite_frame : public draw_frame_impl\r
{\r
public:\r
- composite_frame(const std::vector<producer_frame>& frames);\r
- composite_frame(const producer_frame& frame1, const producer_frame& frame2);\r
+ composite_frame(std::vector<draw_frame>&& frames);\r
+ composite_frame(draw_frame&& frame1, draw_frame&& frame2);\r
composite_frame(composite_frame&& other);\r
composite_frame& operator=(composite_frame&& other);\r
\r
- static composite_frame interlace(producer_frame&& frame1, producer_frame&& frame2, video_mode::type mode);\r
+ static composite_frame interlace(draw_frame&& frame1, draw_frame&& frame2, video_mode::type mode);\r
\r
virtual const std::vector<short>& audio_data() const;\r
- virtual std::vector<short>& audio_data();\r
+\r
+private:\r
\r
virtual void begin_write();\r
virtual void end_write();\r
virtual void draw(frame_shader& shader);\r
\r
-private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
+++ /dev/null
-#pragma once\r
-\r
-#include "read_frame.h"\r
-\r
-#include <boost/noncopyable.hpp>\r
-#include <boost/range/iterator_range.hpp>\r
-\r
-#include <memory>\r
-#include <vector>\r
-\r
-namespace caspar { namespace core {\r
-\r
-class consumer_frame\r
-{\r
-public: \r
- consumer_frame(read_frame&& frame) : frame_(std::move(frame)){}\r
- const boost::iterator_range<const unsigned char*> pixel_data() const {return frame_.pixel_data();}\r
- const std::vector<short>& audio_data() const {return frame_.audio_data();}\r
- \r
-private:\r
- read_frame frame_;\r
-};\r
-typedef std::shared_ptr<consumer_frame> consumer_frame_ptr;\r
-typedef std::unique_ptr<consumer_frame> consumer_frame_uptr;\r
-\r
-}}
\ No newline at end of file
--- /dev/null
+#include "../stdafx.h"\r
+\r
+#include "draw_frame.h"\r
+\r
+#include "frame_shader.h"\r
+\r
+namespace caspar { namespace core {\r
+ \r
+const std::vector<short>& draw_frame::audio_data() const \r
+{\r
+ static std::vector<short> no_audio;\r
+ return impl_ ? impl_->audio_data() : no_audio;\r
+} \r
+\r
+void draw_frame::swap(draw_frame& other)\r
+{\r
+ impl_.swap(other.impl_);\r
+ std::swap(type_, other.type_);\r
+}\r
+ \r
+void draw_frame::begin_write()\r
+{\r
+ if(impl_)\r
+ impl_->begin_write();\r
+}\r
+\r
+void draw_frame::end_write()\r
+{\r
+ if(impl_)\r
+ impl_->end_write();\r
+}\r
+\r
+void draw_frame::draw(frame_shader& shader)\r
+{\r
+ if(impl_)\r
+ impl_->draw(shader);\r
+}\r
+\r
+eof_frame draw_frame::eof(){return eof_frame();}\r
+empty_frame draw_frame::empty(){return empty_frame();}\r
+ \r
+bool draw_frame::operator==(const eof_frame&){return type_ == eof_type;}\r
+bool draw_frame::operator!=(const eof_frame&){return type_ != eof_type;}\r
+\r
+bool draw_frame::operator==(const empty_frame&){return type_ == empty_type;}\r
+bool draw_frame::operator!=(const empty_frame&){return type_ != empty_type;}\r
+\r
+bool draw_frame::operator==(const draw_frame& other){return impl_ == other.impl_ && type_ == other.type_;}\r
+bool draw_frame::operator!=(const draw_frame& other){return !(*this == other);}\r
+ \r
+draw_frame& draw_frame::operator=(const draw_frame& other)\r
+{\r
+ draw_frame temp(other);\r
+ temp.swap(*this);\r
+ return *this;\r
+}\r
+draw_frame& draw_frame::operator=(draw_frame&& other)\r
+{\r
+ impl_ = std::move(other.impl_);\r
+ std::swap(type_, other.type_);\r
+ return *this;\r
+}\r
+draw_frame& draw_frame::operator=(eof_frame&&)\r
+{\r
+ impl_ = nullptr;\r
+ type_ = eof_type;\r
+ return *this;\r
+} \r
+draw_frame& draw_frame::operator=(empty_frame&&)\r
+{\r
+ impl_ = nullptr;\r
+ type_ = empty_type;\r
+ return *this;\r
+} \r
+\r
+}}
\ No newline at end of file
--- /dev/null
+#pragma once\r
+\r
+#include "fwd.h"\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
+#include <boost/variant.hpp>\r
+#include <boost/type_traits.hpp>\r
+\r
+#include <memory>\r
+#include <vector>\r
+#include <type_traits>\r
+\r
+namespace caspar { namespace core {\r
+ \r
+struct eof_frame{};\r
+struct empty_frame{};\r
+ \r
+struct draw_frame_impl : boost::noncopyable\r
+{ \r
+ virtual const std::vector<short>& audio_data() const = 0;\r
+ \r
+ virtual void begin_write() = 0;\r
+ virtual void end_write() = 0;\r
+ virtual void draw(frame_shader& shader) = 0;\r
+};\r
+\r
+class draw_frame\r
+{\r
+ enum frame_type\r
+ {\r
+ normal_type,\r
+ eof_type,\r
+ empty_type\r
+ };\r
+\r
+ //TODO: Move constructor is called when copy constructor should be called.\r
+ template<typename T>\r
+ void init(T&& other, const boost::true_type&)\r
+ {\r
+ impl_ = other.impl_;\r
+ type_ = other.type_;\r
+ }\r
+ \r
+ template<typename T>\r
+ void init(T&& impl, const boost::false_type&)\r
+ {\r
+ impl_ = std::make_shared<T>(std::move(impl));\r
+ type_ = normal_type;\r
+ }\r
+\r
+public:\r
+ draw_frame() : type_(empty_type){}\r
+ draw_frame(const draw_frame& other) : impl_(other.impl_), type_(other.type_){}\r
+\r
+ template<typename T>\r
+ draw_frame(T&& val)\r
+ {\r
+ init(std::forward<T>(val), boost::is_same<typename std::remove_reference<T>::type, draw_frame>());\r
+ }\r
+\r
+ draw_frame(eof_frame&&) : type_(eof_type){}\r
+ draw_frame(empty_frame&&) : type_(empty_type){}\r
+ \r
+ void swap(draw_frame& other);\r
+ draw_frame& operator=(const draw_frame& other);\r
+ draw_frame& operator=(draw_frame&& other);\r
+ draw_frame& operator=(eof_frame&&);\r
+ draw_frame& operator=(empty_frame&&);\r
+\r
+ static eof_frame eof();\r
+ static empty_frame empty();\r
+ \r
+ bool operator==(const eof_frame&);\r
+ bool operator!=(const eof_frame&);\r
+\r
+ bool operator==(const empty_frame&);\r
+ bool operator!=(const empty_frame&);\r
+\r
+ bool operator==(const draw_frame& other);\r
+ bool operator!=(const draw_frame& other);\r
+ \r
+ const std::vector<short>& audio_data() const;\r
+\r
+ void begin_write();\r
+ void end_write();\r
+ void draw(frame_shader& shader);\r
+private: \r
+ draw_frame_impl_ptr impl_;\r
+ frame_type type_;\r
+};\r
+\r
+}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <memory>\r
-#include <array>\r
-#include <vector>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct drawable_frame : boost::noncopyable\r
-{ \r
- virtual const std::vector<short>& audio_data() const = 0;\r
- virtual std::vector<short>& audio_data() = 0;\r
- \r
- virtual void begin_write() = 0;\r
- virtual void end_write() = 0;\r
- virtual void draw(frame_shader& shader) = 0;\r
-};\r
-\r
-\r
-}}
\ No newline at end of file
\r
#include "frame_renderer.h"\r
#include "write_frame.h"\r
+#include "draw_frame.h"\r
#include "read_frame.h"\r
-#include "composite_frame.h"\r
-#include "producer_frame.h"\r
\r
#include "../format/video_format.h"\r
\r
}));\r
}\r
\r
- void send(const producer_frame& frame)\r
+ void send(const draw_frame& frame)\r
{ \r
auto future = executor_.begin_invoke([=]{return renderer_->render(frame);}); \r
output_.push(std::move(future)); // Blocks\r
}\r
\r
- consumer_frame receive()\r
+ read_frame receive()\r
{\r
- boost::shared_future<consumer_frame> future;\r
+ boost::shared_future<read_frame> future;\r
\r
if(!output_.try_pop(future))\r
{\r
std::unique_ptr<sf::Context> ogl_context_;\r
std::unique_ptr<frame_renderer> renderer_; \r
\r
- tbb::concurrent_bounded_queue<boost::shared_future<consumer_frame>> output_; \r
+ tbb::concurrent_bounded_queue<boost::shared_future<read_frame>> output_; \r
tbb::concurrent_unordered_map<pixel_format_desc, tbb::concurrent_bounded_queue<write_frame_impl_ptr>, std::hash<pixel_format_desc>> frame_pools_;\r
\r
const video_format_desc fmt_;\r
};\r
\r
frame_processor_device::frame_processor_device(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-void frame_processor_device::send(const producer_frame& frame){impl_->send(std::move(frame));}\r
-consumer_frame frame_processor_device::receive(){return impl_->receive();}\r
+void frame_processor_device::send(const draw_frame& frame){impl_->send(std::move(frame));}\r
+read_frame frame_processor_device::receive(){return impl_->receive();}\r
const video_format_desc& frame_processor_device::get_video_format_desc() const { return impl_->fmt_; }\r
\r
write_frame frame_processor_device::create_frame(const pixel_format_desc& desc){ return impl_->create_frame(desc); } \r
#include <vector>\r
\r
#include "fwd.h"\r
+#include "write_frame.h"\r
\r
#include "../format/video_format.h"\r
-#include "../consumer/frame_consumer_device.h"\r
\r
namespace caspar { namespace core {\r
\r
public:\r
frame_processor_device(const video_format_desc& format_desc);\r
\r
- void send(const producer_frame& frame);\r
- consumer_frame receive();\r
+ void send(const draw_frame& frame);\r
+ read_frame receive();\r
\r
write_frame create_frame(const pixel_format_desc& desc); \r
write_frame create_frame(size_t width, size_t height); \r
#include "frame_shader.h"\r
#include "write_frame.h"\r
#include "read_frame.h"\r
-#include "producer_frame.h"\r
-#include "consumer_frame.h"\r
+#include "draw_frame.h"\r
+#include "read_frame.h"\r
\r
#include "../format/video_format.h"\r
\r
GL(glViewport(0, 0, format_desc.width, format_desc.height));\r
}\r
\r
- consumer_frame render(const producer_frame& frame)\r
+ read_frame render(const draw_frame& frame)\r
{\r
read_frame_impl_ptr result;\r
try\r
reading_->begin_read();\r
reading_->audio_data() = drawing_.audio_data();\r
\r
- drawing_ = producer_frame::empty();\r
+ drawing_ = draw_frame::empty();\r
}\r
catch(...)\r
{\r
common::gl::frame_buffer_object fbo_;\r
\r
read_frame_impl_ptr reading_; \r
- producer_frame writing_;\r
- producer_frame drawing_;\r
+ draw_frame writing_;\r
+ draw_frame drawing_;\r
\r
frame_shader shader_;\r
\r
};\r
\r
frame_renderer::frame_renderer(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-consumer_frame frame_renderer::render(const producer_frame& frame){return impl_->render(std::move(frame));}\r
+read_frame frame_renderer::render(const draw_frame& frame){return impl_->render(std::move(frame));}\r
}}
\ No newline at end of file
public:\r
frame_renderer(const video_format_desc& format_desc_);\r
\r
- consumer_frame render(const producer_frame& frame);\r
+ read_frame render(const draw_frame& frame);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
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};\r
\r
-struct frame_shader::implementation\r
+struct frame_shader::implementation : boost::noncopyable\r
{\r
implementation(const video_format_desc& format_desc) : current_(pixel_format::invalid), format_desc_(format_desc), alpha_(1.0)\r
{\r
namespace caspar { namespace core {\r
\r
class read_frame;\r
-typedef std::shared_ptr<read_frame> read_frame_ptr;\r
-\r
-struct drawable_frame;\r
-typedef std::shared_ptr<drawable_frame> drawable_frame_ptr;\r
-\r
class write_frame;\r
-typedef std::shared_ptr<write_frame> write_frame_ptr;\r
+class draw_frame;\r
+\r
+struct draw_frame_impl;\r
+typedef std::shared_ptr<draw_frame_impl> draw_frame_impl_ptr;\r
\r
class transform_frame;\r
typedef std::shared_ptr<transform_frame> transform_frame_ptr;\r
class composite_frame;\r
typedef std::shared_ptr<composite_frame> composite_frame_ptr;\r
\r
-class consumer_frame;\r
-class producer_frame;\r
-\r
class frame_shader;\r
typedef std::shared_ptr<frame_shader> frame_shader_ptr;\r
\r
+++ /dev/null
-#pragma once\r
-\r
-#include "write_frame.h"\r
-#include "composite_frame.h"\r
-#include "transform_frame.h"\r
-\r
-#include <boost/noncopyable.hpp>\r
-#include <boost/range/iterator_range.hpp>\r
-#include <boost/variant.hpp>\r
-#include <boost/utility/enable_if.hpp>\r
-\r
-#include <memory>\r
-#include <vector>\r
-#include <type_traits>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct eof_frame{};\r
-struct empty_frame{};\r
-\r
-class producer_frame\r
-{\r
- enum frame_type\r
- {\r
- normal_type,\r
- eof_type,\r
- empty_type\r
- };\r
-public:\r
- producer_frame() : type_(empty_type){}\r
- producer_frame(const producer_frame& other) : frame_(other.frame_), type_(other.type_){}\r
- producer_frame(producer_frame&& other) : frame_(std::move(other.frame_)), type_(other.type_){}\r
- \r
- producer_frame(drawable_frame_ptr&& frame) : frame_(std::move(frame)), type_(normal_type){}\r
- producer_frame(write_frame&& frame) : frame_(std::make_shared<write_frame>(std::move(frame))), type_(normal_type){}\r
- producer_frame(composite_frame&& frame) : frame_(std::make_shared<composite_frame>(std::move(frame))), type_(normal_type){}\r
- producer_frame(transform_frame&& frame) : frame_(std::make_shared<transform_frame>(std::move(frame))), type_(normal_type){}\r
-\r
- producer_frame(eof_frame&&) : type_(eof_type){}\r
- producer_frame(empty_frame&&) : type_(empty_type){}\r
- \r
- const std::vector<short>& audio_data() const \r
- {\r
- static std::vector<short> no_audio;\r
- return frame_ ? frame_->audio_data() : no_audio;\r
- } \r
-\r
- void begin_write()\r
- {\r
- if(frame_)\r
- frame_->begin_write();\r
- }\r
-\r
- void end_write()\r
- {\r
- if(frame_)\r
- frame_->end_write();\r
- }\r
-\r
- void draw(frame_shader& shader)\r
- {\r
- if(frame_)\r
- frame_->draw(shader);\r
- }\r
-\r
- void swap(producer_frame& other)\r
- {\r
- frame_.swap(other.frame_);\r
- std::swap(type_, other.type_);\r
- }\r
-\r
- static eof_frame eof(){return eof_frame();}\r
- static empty_frame empty(){return empty_frame();}\r
- \r
- bool operator==(const eof_frame&){return type_ == eof_type;}\r
- bool operator!=(const eof_frame&){return type_ != eof_type;}\r
-\r
- bool operator==(const empty_frame&){return type_ == empty_type;}\r
- bool operator!=(const empty_frame&){return type_ != empty_type;}\r
-\r
- bool operator==(const producer_frame& other){return frame_ == other.frame_ && type_ == other.type_;}\r
- bool operator!=(const producer_frame& other){return !(*this == other);}\r
- \r
- producer_frame& operator=(const producer_frame& other)\r
- {\r
- producer_frame temp(other);\r
- temp.swap(*this);\r
- return *this;\r
- }\r
- producer_frame& operator=(producer_frame&& other)\r
- {\r
- frame_ = std::move(other.frame_);\r
- std::swap(type_, other.type_);\r
- return *this;\r
- }\r
- producer_frame& operator=(eof_frame&& frame)\r
- {\r
- frame_ = nullptr;\r
- type_ = eof_type;\r
- return *this;\r
- } \r
- producer_frame& operator=(empty_frame&& frame)\r
- {\r
- frame_ = nullptr;\r
- type_ = empty_type;\r
- return *this;\r
- } \r
-\r
-private: \r
- drawable_frame_ptr frame_;\r
- frame_type type_;\r
-};\r
-\r
-}}
\ No newline at end of file
#pragma once\r
\r
+#include "../../common/exception/exceptions.h"\r
+\r
#include "../format/video_format.h"\r
#include "../format/pixel_format.h"\r
\r
class read_frame\r
{\r
public:\r
- explicit read_frame(const read_frame_impl_ptr& frame) : frame_(frame){}\r
+ explicit read_frame(const read_frame_impl_ptr& frame) : frame_(frame)\r
+ {\r
+ if(!frame)\r
+ BOOST_THROW_EXCEPTION(null_argument() << msg_info("frame"));\r
+ }\r
read_frame(read_frame&& other) : frame_(std::move(other.frame_)){}\r
read_frame& operator=(read_frame&& other)\r
{\r
\r
const boost::iterator_range<const unsigned char*> pixel_data() const { return frame_->pixel_data();}\r
const std::vector<short>& audio_data() const { return frame_->audio_data();}\r
- std::vector<short>& audio_data() { return frame_->audio_data();};\r
- \r
- void begin_read(){ frame_->begin_read();}\r
- void end_read(){ frame_->end_read();}\r
\r
private:\r
read_frame_impl_ptr frame_;\r
\r
#include "transform_frame.h"\r
\r
-#include "producer_frame.h"\r
+#include "draw_frame.h"\r
#include "frame_shader.h"\r
\r
#include "../format/pixel_format.h"\r
\r
struct transform_frame::implementation : boost::noncopyable\r
{\r
- implementation(const producer_frame& frame) : frame_(frame), audio_volume_(255), calculated_audio_volume_(audio_volume_){}\r
+ implementation(const draw_frame& frame) : frame_(frame), audio_volume_(255), override_audio_(false){}\r
+ implementation(const draw_frame& frame, const std::vector<short>& audio_data) : frame_(frame), audio_volume_(255), audio_data_(audio_data), override_audio_(true){}\r
+ implementation(draw_frame&& frame) : frame_(std::move(frame)), audio_volume_(255), override_audio_(false){}\r
\r
void begin_write(){frame_.begin_write();}\r
void end_write(){frame_.end_write();}\r
\r
void draw(frame_shader& shader)\r
{\r
- if(frame_ == producer_frame::empty() || frame_ == producer_frame::eof())\r
- return;\r
-\r
shader.begin(transform_);\r
frame_.draw(shader);\r
shader.end();\r
}\r
\r
- std::vector<short>& audio_data()\r
+ void audio_volume(unsigned char volume)\r
{\r
- if(!audio_data_.empty() && calculated_audio_volume_ == audio_volume_)\r
- return audio_data_;\r
+ if(volume == audio_volume_)\r
+ return;\r
\r
- calculated_audio_volume_ = audio_volume_;\r
- audio_data_ = frame_.audio_data();\r
+ audio_volume_ = volume;\r
+ if(!override_audio_)\r
+ audio_data_ = frame_.audio_data();\r
tbb::parallel_for\r
(\r
tbb::blocked_range<size_t>(0, audio_data_.size()),\r
audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n])*audio_volume_)>>8); \r
}\r
);\r
- \r
- return audio_data_;\r
}\r
\r
+ bool override_audio_;\r
std::vector<short> audio_data_;\r
\r
shader_transform transform_;\r
\r
- unsigned char calculated_audio_volume_;\r
unsigned char audio_volume_;\r
- producer_frame frame_;\r
+ draw_frame frame_;\r
};\r
\r
-transform_frame::transform_frame(const producer_frame& frame) : impl_(new implementation(std::move(frame))){}\r
+transform_frame::transform_frame(const draw_frame& frame) : impl_(new implementation(frame)){}\r
+transform_frame::transform_frame(const draw_frame& frame, const std::vector<short>& audio_data) : impl_(new implementation(frame, audio_data)){}\r
+transform_frame::transform_frame(draw_frame&& frame) : impl_(new implementation(std::move(frame))){}\r
transform_frame::transform_frame(transform_frame&& other) : impl_(std::move(other.impl_)){}\r
transform_frame& transform_frame::operator=(transform_frame&& other)\r
{\r
void transform_frame::begin_write(){impl_->begin_write();}\r
void transform_frame::end_write(){impl_->end_write();} \r
void transform_frame::draw(frame_shader& shader){impl_->draw(shader);}\r
-void transform_frame::audio_volume(unsigned char volume){impl_->audio_volume_ = volume;}\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
-std::vector<short>& transform_frame::audio_data() { return impl_->audio_data(); }\r
-const std::vector<short>& transform_frame::audio_data() const { return impl_->audio_data(); }\r
+const std::vector<short>& transform_frame::audio_data() const { return impl_->audio_data_; }\r
}}
\ No newline at end of file
\r
#include "fwd.h"\r
\r
-#include "drawable_frame.h"\r
+#include "draw_frame.h"\r
\r
#include "../format/video_format.h"\r
#include "../format/pixel_format.h"\r
\r
namespace caspar { namespace core {\r
\r
-class transform_frame : public drawable_frame\r
+class transform_frame : public draw_frame_impl\r
{\r
public:\r
- transform_frame(const producer_frame& frame);\r
+ transform_frame(const draw_frame& frame);\r
+ transform_frame(const draw_frame& frame, const std::vector<short>& audio_data);\r
+ transform_frame(draw_frame&& frame);\r
+\r
transform_frame(transform_frame&& other);\r
transform_frame& operator=(transform_frame&& other);\r
\r
- virtual std::vector<short>& audio_data();\r
virtual const std::vector<short>& audio_data() const;\r
\r
void audio_volume(unsigned char volume);\r
void video_mode(video_mode::type mode);\r
void alpha(double value);\r
\r
+private:\r
+\r
virtual void begin_write();\r
virtual void end_write();\r
virtual void draw(frame_shader& shader);\r
\r
-private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
\r
#include "write_frame.h"\r
\r
-#include "producer_frame.h"\r
+#include "draw_frame.h"\r
#include "frame_shader.h"\r
\r
#include "../format/pixel_format.h"\r
\r
#include "fwd.h"\r
\r
-#include "drawable_frame.h"\r
+#include "draw_frame.h"\r
+\r
+#include "../../common/exception/exceptions.h"\r
\r
#include "../format/video_format.h"\r
#include "../format/pixel_format.h"\r
\r
std::vector<short>& audio_data();\r
const std::vector<short>& audio_data() const;\r
- \r
+ \r
void begin_write();\r
void end_write();\r
void draw(frame_shader& shader);\r
-\r
+ \r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
typedef std::shared_ptr<write_frame_impl> write_frame_impl_ptr;\r
\r
-class write_frame : public drawable_frame\r
+class write_frame : public draw_frame_impl\r
{\r
public:\r
- explicit write_frame(const write_frame_impl_ptr& frame) : frame_(frame){}\r
- write_frame(write_frame&& other) : frame_(std::move(other.frame_)){}\r
+ explicit write_frame(const write_frame_impl_ptr& frame) : impl_(frame)\r
+ {\r
+ if(!frame)\r
+ BOOST_THROW_EXCEPTION(null_argument() << msg_info("frame"));\r
+ }\r
+ write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
write_frame& operator=(write_frame&& other)\r
{\r
- frame_ = std::move(other.frame_);\r
+ impl_ = std::move(other.impl_);\r
return *this;\r
}\r
\r
- boost::iterator_range<unsigned char*> pixel_data(size_t index = 0) {return frame_->pixel_data(index);}\r
- const boost::iterator_range<const unsigned char*> pixel_data(size_t index = 0) const {return frame_->pixel_data(index);}\r
+ boost::iterator_range<unsigned char*> pixel_data(size_t index = 0) {return impl_->pixel_data(index);}\r
+ const boost::iterator_range<const unsigned char*> pixel_data(size_t index = 0) const {return impl_->pixel_data(index);}\r
\r
- void reset() {return frame_->reset();}\r
-\r
- virtual std::vector<short>& audio_data() {return frame_->audio_data();}\r
- virtual const std::vector<short>& audio_data() const {return frame_->audio_data();}\r
+ virtual const std::vector<short>& audio_data() const {return impl_->audio_data();}\r
\r
- virtual void begin_write() {return frame_->begin_write();}\r
- virtual void end_write() {return frame_->end_write();}\r
- virtual void draw(frame_shader& shader) {return frame_->draw(shader);}\r
private:\r
- write_frame_impl_ptr frame_;\r
+ virtual void begin_write() {return impl_->begin_write();}\r
+ virtual void end_write() {return impl_->end_write();}\r
+ virtual void draw(frame_shader& shader) {return impl_->draw(shader);}\r
+\r
+ write_frame_impl_ptr impl_;\r
};\r
\r
\r
\r
#include "color_producer.h"\r
\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../format/video_format.h"\r
\r
#include <intrin.h>\r
public:\r
explicit color_producer(const std::wstring& color) : color_str_(color), color_value_(get_pixel_color_value(color)){}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{ \r
return frame_;\r
}\r
return + L"color_producer. color: " + color_str_;\r
}\r
\r
- producer_frame frame_;\r
+ draw_frame frame_;\r
unsigned int color_value_;\r
std::wstring color_str_;\r
};\r
#include "video/video_transformer.h"\r
\r
#include "../../format/video_format.h"\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
+#include "../../processor/transform_Frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../../common/utility/scope_exit.h"\r
#include "../../server.h"\r
\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
{\r
+ format_desc_ = frame_processor->get_video_format_desc();\r
video_transformer_->initialize(frame_processor);\r
}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{\r
while(ouput_channel_.empty() && !input_->is_eof())\r
{ \r
if(!video_packet.empty())\r
{\r
auto decoded_frame = video_decoder_->execute(video_packet);\r
- auto transformed_frame = video_transformer_->execute(decoded_frame);\r
- video_frame_channel_.push_back(std::move(transformed_frame)); \r
+ auto frame = video_transformer_->execute(decoded_frame);\r
+ video_frame_channel_.push_back(std::move(frame)); \r
}\r
}, \r
[&] \r
}\r
});\r
\r
- if(video_packet.empty() && audio_packet.empty())\r
+ while(!video_frame_channel_.empty() && (!audio_chunk_channel_.empty() || !has_audio_))\r
+ {\r
+ std::vector<short> audio_data;\r
+ if(has_audio_) \r
+ {\r
+ audio_data = std::move(audio_chunk_channel_.front());\r
+ audio_chunk_channel_.pop_front();\r
+ }\r
+ \r
+ auto transform = transform_frame(std::move(video_frame_channel_.front()), std::move(audio_data));\r
+ video_frame_channel_.pop_front();\r
+ \r
+ // TODO: Make generic for all formats and modes.\r
+ if(input_->get_video_codec_context()->codec_id == CODEC_ID_DVVIDEO) // Move up one field \r
+ transform.translate(0.0f, 1.0/static_cast<double>(format_desc_.height)); \r
+ \r
+ ouput_channel_.push(std::move(transform));\r
+ } \r
+\r
+ if(ouput_channel_.empty() && video_packet.empty() && audio_packet.empty())\r
{\r
if(underrun_count_++ == 0)\r
CASPAR_LOG(warning) << "### File read underflow has STARTED.";\r
\r
- // Return last frame without audio.\r
- //last_frame_.audio_data().clear(); TODO\r
return last_frame_;\r
}\r
else if(underrun_count_ > 0)\r
CASPAR_LOG(trace) << "### File Read Underrun has ENDED with " << underrun_count_ << " ticks.";\r
underrun_count_ = 0;\r
}\r
-\r
- while(!video_frame_channel_.empty() && (!audio_chunk_channel_.empty() || !has_audio_))\r
- {\r
- if(has_audio_) \r
- {\r
- video_frame_channel_.front().audio_data() = std::move(audio_chunk_channel_.front());\r
- audio_chunk_channel_.pop_front();\r
- }\r
- \r
- auto frame = std::move(video_frame_channel_.front());\r
- video_frame_channel_.pop_front();\r
- ouput_channel_.push(std::move(frame));\r
- } \r
}\r
\r
+ draw_frame result = last_frame_;\r
if(!ouput_channel_.empty())\r
{\r
- last_frame_ = std::move(ouput_channel_.front());\r
+ result = std::move(ouput_channel_.front());\r
+ last_frame_ = transform_frame(result, std::vector<short>()); // last_frame should not have audio, override it!\r
ouput_channel_.pop();\r
}\r
else if(input_->is_eof())\r
- last_frame_ = producer_frame::eof();\r
+ last_frame_ = draw_frame::eof();\r
\r
- return last_frame_;\r
+ return result;\r
}\r
\r
std::wstring print() const\r
\r
video_decoder_uptr video_decoder_;\r
video_transformer_uptr video_transformer_;\r
- std::deque<transform_frame> video_frame_channel_;\r
+ std::deque<draw_frame> video_frame_channel_;\r
\r
audio_decoder_ptr audio_decoder_;\r
std::deque<std::vector<short>> audio_chunk_channel_;\r
\r
- std::queue<transform_frame> ouput_channel_;\r
+ std::queue<draw_frame> ouput_channel_;\r
\r
std::wstring filename_;\r
\r
long underrun_count_;\r
\r
- producer_frame last_frame_;\r
+ draw_frame last_frame_;\r
+\r
+ video_format_desc format_desc_;\r
};\r
\r
frame_producer_ptr create_ffmpeg_producer(const std::vector<std::wstring>& params)\r
#include "video_transformer.h"\r
\r
#include "../../../format/video_format.h"\r
-#include "../../../processor/transform_frame.h"\r
-#include "../../../processor/transform_frame.h"\r
-#include "../../../processor/producer_frame.h"\r
+#include "../../../processor/draw_frame.h"\r
+#include "../../../processor/draw_frame.h"\r
+#include "../../../processor/draw_frame.h"\r
#include "../../../processor/frame_processor_device.h"\r
\r
#include <tbb/parallel_for.h>\r
}\r
}\r
\r
- transform_frame execute(const std::shared_ptr<AVFrame>& decoded_frame)\r
+ draw_frame execute(const std::shared_ptr<AVFrame>& decoded_frame)\r
{ \r
if(decoded_frame == nullptr)\r
- return transform_frame(producer_frame::eof()); // TODO\r
+ return draw_frame::eof(); // TODO\r
\r
- transform_frame transform = producer_frame::eof();\r
if(sws_context_ == nullptr)\r
{\r
auto write = frame_processor_->create_frame(desc_);\r
});\r
});\r
\r
- transform = producer_frame(std::move(write));\r
+ return std::move(write);\r
}\r
else\r
{\r
\r
sws_scale(sws_context_.get(), decoded_frame->data, decoded_frame->linesize, 0, height_, av_frame.data, av_frame.linesize); \r
\r
- transform = producer_frame(std::move(write));\r
- }\r
- \r
- // TODO: Make generic for all formats and modes.\r
- if(codec_context_->codec_id == CODEC_ID_DVVIDEO) // Move up one field \r
- transform.translate(0.0f, 1.0/static_cast<double>(frame_processor_->get_video_format_desc().height)); \r
- \r
- return transform;\r
+ return std::move(write);\r
+ } \r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
};\r
\r
video_transformer::video_transformer(AVCodecContext* codec_context) : impl_(new implementation(codec_context)){}\r
-transform_frame video_transformer::execute(const std::shared_ptr<AVFrame>& decoded_frame){return impl_->execute(decoded_frame);}\r
+draw_frame video_transformer::execute(const std::shared_ptr<AVFrame>& decoded_frame){return impl_->execute(decoded_frame);}\r
void video_transformer::initialize(const frame_processor_device_ptr& frame_processor){impl_->initialize(frame_processor); }\r
}}}
\ No newline at end of file
{\r
public:\r
video_transformer(AVCodecContext* codec_context);\r
- transform_frame execute(const std::shared_ptr<AVFrame>& video_packet); \r
+ draw_frame execute(const std::shared_ptr<AVFrame>& video_packet); \r
void initialize(const frame_processor_device_ptr& frame_processor);\r
private:\r
struct implementation;\r
#include "cg_producer.h"\r
#include "flash_producer.h"\r
\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../Server.h"\r
\r
#include <boost/filesystem.hpp>\r
flash_producer_->param(param.str());\r
}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{\r
- return flash_producer_ ? flash_producer_->receive() : producer_frame::empty();\r
+ return flash_producer_ ? flash_producer_->receive() : draw_frame::empty();\r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
}\r
\r
cg_producer::cg_producer() : impl_(new implementation()){}\r
-producer_frame cg_producer::receive(){return impl_->receive();}\r
+draw_frame cg_producer::receive(){return impl_->receive();}\r
void cg_producer::clear(){impl_->clear();}\r
void cg_producer::add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, template_name, play_on_load, startFromLabel, data);}\r
void cg_producer::remove(int layer){impl_->remove(layer);}\r
\r
cg_producer();\r
\r
- virtual producer_frame receive();\r
+ virtual draw_frame receive();\r
virtual void initialize(const frame_processor_device_ptr& frame_processor);\r
\r
void clear();\r
\r
#include "cg_producer.h"\r
\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../server.h"\r
\r
#include <boost/assign/list_of.hpp>\r
{\r
ct_producer(const std::wstring& filename) : filename_(filename), initialized_(false){}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{\r
if(!initialized_)\r
{\r
#include "../../../common/concurrency/executor.h"\r
#include "../../../common/utility/scope_exit.h"\r
\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../processor/composite_frame.h"\r
\r
#include <boost/assign.hpp>\r
stop();\r
\r
frame_buffer_.clear();\r
- frame_buffer_.try_push(producer_frame::eof()); // EOF\r
+ frame_buffer_.try_push(draw_frame::eof()); // EOF\r
\r
current_frame_ = nullptr;\r
});\r
auto format_desc = frame_processor_->get_video_format_desc();\r
bool is_progressive = format_desc.mode == video_mode::progressive || (flashax_container_->GetFPS() - format_desc.fps/2 == 0);\r
\r
- producer_frame result;\r
+ draw_frame result;\r
\r
if(is_progressive) \r
result = do_receive(); \r
}\r
}\r
\r
- producer_frame do_receive()\r
+ draw_frame do_receive()\r
{\r
auto format_desc = frame_processor_->get_video_format_desc();\r
\r
\r
auto frame = frame_processor_->create_frame(format_desc.width, format_desc.height);\r
std::copy(current_frame_->data(), current_frame_->data() + current_frame_->size(), frame.pixel_data().begin());\r
- return producer_frame(std::make_shared<write_frame>(std::move(frame)));\r
+ return std::move(frame);\r
}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{ \r
- return (frame_buffer_.try_pop(last_frame_) || !is_empty_) ? last_frame_ : producer_frame::empty();\r
+ return (frame_buffer_.try_pop(last_frame_) || !is_empty_) ? last_frame_ : draw_frame::empty();\r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
\r
CComObject<flash::FlashAxContainer>* flashax_container_;\r
\r
- tbb::concurrent_bounded_queue<producer_frame> frame_buffer_;\r
+ tbb::concurrent_bounded_queue<draw_frame> frame_buffer_;\r
\r
- producer_frame last_frame_;\r
+ draw_frame last_frame_;\r
\r
bitmap_ptr current_frame_;\r
bitmap_ptr bmp_frame_;\r
};\r
\r
flash_producer::flash_producer(const std::wstring& filename) : impl_(new implementation(this, filename)){}\r
-producer_frame flash_producer::receive(){return impl_->receive();}\r
+draw_frame flash_producer::receive(){return impl_->receive();}\r
void flash_producer::param(const std::wstring& param){impl_->param(param);}\r
void flash_producer::initialize(const frame_processor_device_ptr& frame_processor) { impl_->initialize(frame_processor);}\r
std::wstring flash_producer::print() const {return impl_->print();}\r
\r
flash_producer(const std::wstring& filename);\r
\r
- virtual producer_frame receive();\r
+ virtual draw_frame receive();\r
virtual void initialize(const frame_processor_device_ptr& frame_processor);\r
virtual std::wstring print() const;\r
\r
*/\r
#pragma once\r
\r
-#include "../processor/write_frame.h"\r
+#include "../processor/draw_frame.h"\r
#include "../processor/frame_processor_device.h"\r
\r
#include <boost/noncopyable.hpp>\r
virtual ~frame_producer(){} \r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
- /// \fn virtual producer_frame :::receive() = 0;\r
+ /// \fn virtual draw_frame :::receive() = 0;\r
///\r
/// \brief Renders a frame.\r
/// \r
///\r
/// \return The frame. \r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
- virtual producer_frame receive() = 0;\r
+ virtual draw_frame receive() = 0;\r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
/// \fn virtual std::shared_ptr<frame_producer> :::get_following_producer() const\r
virtual void initialize(const frame_processor_device_ptr& frame_processor) = 0;\r
\r
virtual std::wstring print() const { return L"Unknown frame_producer.";}\r
+\r
+ static const std::shared_ptr<frame_producer>& empty()\r
+ { \r
+ struct empty_frame_producer : public frame_producer\r
+ {\r
+ virtual draw_frame receive(){return draw_frame::empty();}\r
+ virtual std::shared_ptr<frame_producer> get_following_producer() const { return nullptr; }\r
+ virtual void initialize(const frame_processor_device_ptr&){}\r
+ };\r
+ static std::shared_ptr<frame_producer> empty_producer = std::make_shared<empty_frame_producer>();\r
+ return empty_producer;\r
+ }\r
};\r
typedef std::shared_ptr<frame_producer> frame_producer_ptr;\r
\r
\r
#include "../format/video_format.h"\r
#include "../processor/composite_frame.h"\r
-#include "../processor/producer_frame.h"\r
+#include "../processor/draw_frame.h"\r
\r
#include "../../common/utility/scope_exit.h"\r
#include "../../common/concurrency/executor.h"\r
\r
namespace caspar { namespace core {\r
\r
-std::vector<producer_frame> receive(std::map<int, layer>& layers)\r
+std::vector<draw_frame> receive(std::map<int, layer>& layers)\r
{ \r
- std::vector<producer_frame> frames(layers.size(), producer_frame::empty());\r
+ std::vector<draw_frame> frames(layers.size(), draw_frame::empty());\r
tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()), \r
[&](const tbb::blocked_range<size_t>& r)\r
{\r
for(size_t i = r.begin(); i != r.end(); ++i, ++it)\r
frames[i] = it->second.receive();\r
}); \r
+ boost::range::remove_erase(frames, draw_frame::eof());\r
+ boost::range::remove_erase(frames, draw_frame::empty());\r
return frames;\r
}\r
\r
\r
void tick()\r
{ \r
- try\r
- { \r
- frame_processor_->send(composite_frame(receive(layers_)));\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- layers_.clear();\r
- CASPAR_LOG(error) << "Unexpected exception. Cleared layers in render-device";\r
- }\r
+ frame_processor_->send(composite_frame(receive(layers_)));\r
executor_.begin_invoke([=]{tick();});\r
}\r
\r
public:\r
frame_producer_device(const frame_processor_device_ptr& frame_processor);\r
\r
- void load(int render_layer, const frame_producer_ptr& producer, load_option::type option = load_option::none); \r
- void pause(int render_layer);\r
- void play(int render_layer);\r
- void stop(int render_layer);\r
- void clear(int render_layer);\r
- void clear();\r
+ void load (int render_layer, const frame_producer_ptr& producer, load_option::type option = load_option::none); \r
+ void pause (int render_layer);\r
+ void play (int render_layer);\r
+ void stop (int render_layer);\r
+ void clear (int render_layer);\r
+ void clear ();\r
\r
boost::unique_future<frame_producer_ptr> foreground(int render_layer) const;\r
boost::unique_future<frame_producer_ptr> background(int render_layer) const;\r
#include "image_loader.h"\r
\r
#include "../../processor/frame_processor_device.h"\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../format/video_format.h"\r
#include "../../server.h"\r
\r
{\r
image_producer(const std::wstring& filename) : filename_(filename) {}\r
\r
- producer_frame receive(){return frame_;}\r
+ draw_frame receive(){return frame_;}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
{\r
\r
frame_processor_device_ptr frame_processor_;\r
std::wstring filename_;\r
- producer_frame frame_;\r
+ draw_frame frame_;\r
};\r
\r
frame_producer_ptr create_image_producer(const std::vector<std::wstring>& params)\r
-#include "../../StdAfx.h"\r
-\r
-#include "image_scroll_producer.h"\r
-\r
-#include "image_loader.h"\r
-\r
-#include "../../processor/producer_frame.h"\r
-#include "../../processor/composite_frame.h"\r
-#include "../../format/video_format.h"\r
-#include "../../processor/frame_processor_device.h"\r
-#include "../../server.h"\r
-\r
-#include <tbb/parallel_for.h>\r
-#include <tbb/parallel_invoke.h>\r
-#include <tbb/scalable_allocator.h>\r
-\r
-#include <boost/assign.hpp>\r
-#include <boost/algorithm/string/case_conv.hpp>\r
-\r
-using namespace boost::assign;\r
-\r
-namespace caspar { namespace core { namespace image{\r
-\r
-enum direction\r
-{\r
- Up, Down, Left, Right\r
-};\r
-\r
-struct image_scroll_producer : public frame_producer\r
-{\r
- static const int DEFAULT_SCROLL_SPEED = 50;\r
-\r
- image_scroll_producer(const std::wstring& filename, const std::vector<std::wstring>& params) \r
- : speed_(image_scroll_producer::DEFAULT_SCROLL_SPEED), direction_(direction::Up), offset_(0), filename_(filename)\r
- {\r
- auto pos = filename.find_last_of(L'_');\r
- if(pos != std::wstring::npos && pos + 1 < filename.size())\r
- {\r
- std::wstring speedStr = filename.substr(pos + 1);\r
- pos = speedStr.find_first_of(L'.');\r
- if(pos != std::wstring::npos)\r
- {\r
- speedStr = speedStr.substr(0, pos); \r
- speed_ = common::lexical_cast_or_default<int>(speedStr, image_scroll_producer::DEFAULT_SCROLL_SPEED);\r
- }\r
- }\r
-\r
- loop_ = std::find(params.begin(), params.end(), L"LOOP") != params.end();\r
- }\r
-\r
- void load_and_pad_image(const std::wstring& filename)\r
- {\r
- auto pBitmap = load_image(filename);\r
-\r
- size_t width = FreeImage_GetWidth(pBitmap.get());\r
- size_t height = FreeImage_GetHeight(pBitmap.get());\r
-\r
- image_width_ = std::max(width, format_desc_.width);\r
- image_height_ = std::max(height, format_desc_.height);\r
-\r
- image_ = std::shared_ptr<unsigned char>(static_cast<unsigned char*>(scalable_aligned_malloc(image_width_*image_height_*4, 16)));\r
- std::fill_n(image_.get(), image_width_*image_height_*4, 0);\r
-\r
- unsigned char* pBits = FreeImage_GetBits(pBitmap.get());\r
- \r
- for (size_t i = 0; i < height; ++i)\r
- std::copy_n(&pBits[i* width * 4], width * 4, &image_.get()[i * image_width_ * 4]);\r
- }\r
-\r
- producer_frame do_receive()\r
- {\r
- auto frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height);\r
- std::fill(frame.pixel_data().begin(), frame.pixel_data().end(), 0);\r
-\r
- const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
- const int delta_y = direction_ == direction::Up ? speed_ : -speed_;\r
-\r
- unsigned char* frame_data = frame.pixel_data().begin();\r
- unsigned char* image_data = image_.get();\r
- \r
- if (direction_ == direction::Up || direction_ == direction::Down)\r
- {\r
- tbb::parallel_for(static_cast<size_t>(0), format_desc_.height, static_cast<size_t>(1), [&](size_t i)\r
- {\r
- int srcRow = i + offset_;\r
- int dstInxex = i * format_desc_.width * 4;\r
- int srcIndex = srcRow * format_desc_.width * 4;\r
- int size = format_desc_.width * 4;\r
-\r
- std::copy_n(&image_data[srcIndex], size, &frame_data[dstInxex]);\r
- }); \r
- \r
- offset_ += delta_y;\r
- }\r
- else\r
- {\r
- tbb::parallel_for(static_cast<size_t>(0), format_desc_.height, static_cast<size_t>(1), [&](size_t i)\r
- {\r
- int correctOffset = offset_;\r
- int dstIndex = i * format_desc_.width * 4;\r
- int srcIndex = (i * image_width_ + correctOffset) * 4;\r
- \r
- int stopOffset = std::min<int>(correctOffset + format_desc_ .width, image_width_);\r
- int size = (stopOffset - correctOffset) * 4;\r
-\r
- std::copy_n(&image_data[srcIndex], size, &frame_data[dstIndex]);\r
- });\r
-\r
- offset_ += delta_x;\r
- }\r
-\r
- return std::move(frame);\r
- }\r
- \r
- producer_frame receive()\r
- { \r
- if(format_desc_.mode != video_mode::progressive) \r
- {\r
- producer_frame frame1;\r
- producer_frame frame2;\r
- tbb::parallel_invoke([&]{ frame1 = std::move(do_receive()); }, [&]{ frame2 = std::move(do_receive()); });\r
- return composite_frame::interlace(std::move(frame1), std::move(frame2), format_desc_.mode);\r
- } \r
-\r
- return receive(); \r
- }\r
- \r
- void initialize(const frame_processor_device_ptr& frame_processor)\r
- {\r
- frame_processor_ = frame_processor;\r
- format_desc_ = frame_processor_->get_video_format_desc();\r
- \r
- if(image_width_ - format_desc_.width > image_height_ - format_desc_.height)\r
- direction_ = speed_ < 0 ? direction::Right : direction::Left;\r
- else\r
- direction_ = speed_ < 0 ? direction::Down : direction::Up;\r
-\r
- if (direction_ == direction::Down)\r
- offset_ = image_height_ - format_desc_.height;\r
- else if (direction_ == direction::Right)\r
- offset_ = image_width_ - format_desc_.width;\r
-\r
- speed_ = static_cast<int>(abs(static_cast<double>(speed_) / format_desc_.fps));\r
- \r
- load_and_pad_image(filename_);\r
- }\r
- \r
-\r
- std::wstring print() const\r
- {\r
- return L"image_scroll_producer. filename: " + filename_;\r
- }\r
-\r
- const video_format_desc& get_video_format_desc() const { return format_desc_; } \r
- \r
- int image_width_;\r
- int image_height_;\r
- int speed_;\r
- int offset_;\r
- direction direction_;\r
-\r
- tbb::atomic<bool> loop_;\r
- std::shared_ptr<unsigned char> image_;\r
- video_format_desc format_desc_;\r
-\r
- std::wstring filename_;\r
-\r
- frame_processor_device_ptr frame_processor_;\r
-};\r
-\r
-frame_producer_ptr create_image_scroll_producer(const std::vector<std::wstring>& params)\r
-{\r
- static const std::vector<std::wstring> extensions = list_of(L"spng")(L"stga")(L"sbmp")(L"sjpg")(L"sjpeg");\r
- std::wstring filename = server::media_folder() + L"\\" + params[0];\r
- \r
- auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
- { \r
- return boost::filesystem::is_regular_file(boost::filesystem::wpath(filename).replace_extension(ex));\r
- });\r
-\r
- if(ext == extensions.end())\r
- return nullptr;\r
-\r
- return std::make_shared<image_scroll_producer>(filename + L"." + *ext, params);\r
-}\r
-\r
-}}}
\ No newline at end of file
+//#include "../../StdAfx.h"\r
+//\r
+//#include "image_scroll_producer.h"\r
+//\r
+//#include "image_loader.h"\r
+//\r
+//#include "../../processor/draw_frame.h"\r
+//#include "../../processor/composite_frame.h"\r
+//#include "../../format/video_format.h"\r
+//#include "../../processor/frame_processor_device.h"\r
+//#include "../../server.h"\r
+//\r
+//#include <tbb/parallel_for.h>\r
+//#include <tbb/parallel_invoke.h>\r
+//#include <tbb/scalable_allocator.h>\r
+//\r
+//#include <boost/assign.hpp>\r
+//#include <boost/algorithm/string/case_conv.hpp>\r
+//\r
+//using namespace boost::assign;\r
+//\r
+//namespace caspar { namespace core { namespace image{\r
+//\r
+//enum direction\r
+//{\r
+// Up, Down, Left, Right\r
+//};\r
+//\r
+//struct image_scroll_producer : public frame_producer\r
+//{\r
+// static const int DEFAULT_SCROLL_SPEED = 50;\r
+//\r
+// image_scroll_producer(const std::wstring& filename, const std::vector<std::wstring>& params) \r
+// : speed_(image_scroll_producer::DEFAULT_SCROLL_SPEED), direction_(direction::Up), offset_(0), filename_(filename)\r
+// {\r
+// auto pos = filename.find_last_of(L'_');\r
+// if(pos != std::wstring::npos && pos + 1 < filename.size())\r
+// {\r
+// std::wstring speedStr = filename.substr(pos + 1);\r
+// pos = speedStr.find_first_of(L'.');\r
+// if(pos != std::wstring::npos)\r
+// {\r
+// speedStr = speedStr.substr(0, pos); \r
+// speed_ = common::lexical_cast_or_default<int>(speedStr, image_scroll_producer::DEFAULT_SCROLL_SPEED);\r
+// }\r
+// }\r
+//\r
+// loop_ = std::find(params.begin(), params.end(), L"LOOP") != params.end();\r
+// }\r
+//\r
+// void load_and_pad_image(const std::wstring& filename)\r
+// {\r
+// auto pBitmap = load_image(filename);\r
+//\r
+// size_t width = FreeImage_GetWidth(pBitmap.get());\r
+// size_t height = FreeImage_GetHeight(pBitmap.get());\r
+//\r
+// image_width_ = std::max(width, format_desc_.width);\r
+// image_height_ = std::max(height, format_desc_.height);\r
+//\r
+// image_ = std::shared_ptr<unsigned char>(static_cast<unsigned char*>(scalable_aligned_malloc(image_width_*image_height_*4, 16)));\r
+// std::fill_n(image_.get(), image_width_*image_height_*4, 0);\r
+//\r
+// unsigned char* pBits = FreeImage_GetBits(pBitmap.get());\r
+// \r
+// for (size_t i = 0; i < height; ++i)\r
+// std::copy_n(&pBits[i* width * 4], width * 4, &image_.get()[i * image_width_ * 4]);\r
+// }\r
+//\r
+// draw_frame do_receive()\r
+// {\r
+// auto frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height);\r
+// std::fill(frame.pixel_data().begin(), frame.pixel_data().end(), 0);\r
+//\r
+// const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
+// const int delta_y = direction_ == direction::Up ? speed_ : -speed_;\r
+//\r
+// unsigned char* frame_data = frame.pixel_data().begin();\r
+// unsigned char* image_data = image_.get();\r
+// \r
+// if (direction_ == direction::Up || direction_ == direction::Down)\r
+// {\r
+// tbb::parallel_for(static_cast<size_t>(0), format_desc_.height, static_cast<size_t>(1), [&](size_t i)\r
+// {\r
+// int srcRow = i + offset_;\r
+// int dstInxex = i * format_desc_.width * 4;\r
+// int srcIndex = srcRow * format_desc_.width * 4;\r
+// int size = format_desc_.width * 4;\r
+//\r
+// std::copy_n(&image_data[srcIndex], size, &frame_data[dstInxex]);\r
+// }); \r
+// \r
+// offset_ += delta_y;\r
+// }\r
+// else\r
+// {\r
+// tbb::parallel_for(static_cast<size_t>(0), format_desc_.height, static_cast<size_t>(1), [&](size_t i)\r
+// {\r
+// int correctOffset = offset_;\r
+// int dstIndex = i * format_desc_.width * 4;\r
+// int srcIndex = (i * image_width_ + correctOffset) * 4;\r
+// \r
+// int stopOffset = std::min<int>(correctOffset + format_desc_ .width, image_width_);\r
+// int size = (stopOffset - correctOffset) * 4;\r
+//\r
+// std::copy_n(&image_data[srcIndex], size, &frame_data[dstIndex]);\r
+// });\r
+//\r
+// offset_ += delta_x;\r
+// }\r
+//\r
+// return std::move(frame);\r
+// }\r
+// \r
+// draw_frame receive()\r
+// { \r
+// if(format_desc_.mode != video_mode::progressive) \r
+// {\r
+// draw_frame frame1;\r
+// draw_frame frame2;\r
+// tbb::parallel_invoke([&]{ frame1 = std::move(do_receive()); }, [&]{ frame2 = std::move(do_receive()); });\r
+// return composite_frame::interlace(std::move(frame1), std::move(frame2), format_desc_.mode);\r
+// } \r
+//\r
+// return receive(); \r
+// }\r
+// \r
+// void initialize(const frame_processor_device_ptr& frame_processor)\r
+// {\r
+// frame_processor_ = frame_processor;\r
+// format_desc_ = frame_processor_->get_video_format_desc();\r
+// \r
+// if(image_width_ - format_desc_.width > image_height_ - format_desc_.height)\r
+// direction_ = speed_ < 0 ? direction::Right : direction::Left;\r
+// else\r
+// direction_ = speed_ < 0 ? direction::Down : direction::Up;\r
+//\r
+// if (direction_ == direction::Down)\r
+// offset_ = image_height_ - format_desc_.height;\r
+// else if (direction_ == direction::Right)\r
+// offset_ = image_width_ - format_desc_.width;\r
+//\r
+// speed_ = static_cast<int>(abs(static_cast<double>(speed_) / format_desc_.fps));\r
+// \r
+// load_and_pad_image(filename_);\r
+// }\r
+// \r
+//\r
+// std::wstring print() const\r
+// {\r
+// return L"image_scroll_producer. filename: " + filename_;\r
+// }\r
+//\r
+// const video_format_desc& get_video_format_desc() const { return format_desc_; } \r
+// \r
+// int image_width_;\r
+// int image_height_;\r
+// int speed_;\r
+// int offset_;\r
+// direction direction_;\r
+//\r
+// tbb::atomic<bool> loop_;\r
+// std::shared_ptr<unsigned char> image_;\r
+// video_format_desc format_desc_;\r
+//\r
+// std::wstring filename_;\r
+//\r
+// frame_processor_device_ptr frame_processor_;\r
+//};\r
+//\r
+//frame_producer_ptr create_image_scroll_producer(const std::vector<std::wstring>& params)\r
+//{\r
+// static const std::vector<std::wstring> extensions = list_of(L"spng")(L"stga")(L"sbmp")(L"sjpg")(L"sjpeg");\r
+// std::wstring filename = server::media_folder() + L"\\" + params[0];\r
+// \r
+// auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
+// { \r
+// return boost::filesystem::is_regular_file(boost::filesystem::wpath(filename).replace_extension(ex));\r
+// });\r
+//\r
+// if(ext == extensions.end())\r
+// return nullptr;\r
+//\r
+// return std::make_shared<image_scroll_producer>(filename + L"." + *ext, params);\r
+//}\r
+//\r
+//}}}
\ No newline at end of file
\r
#include "layer.h"\r
\r
-#include "../processor/producer_frame.h"\r
+#include "../processor/draw_frame.h"\r
#include "../producer/frame_producer.h"\r
\r
#include "../format/video_format.h"\r
\r
struct layer::implementation\r
{ \r
- implementation() : foreground_(nullptr), background_(nullptr), last_frame_(producer_frame::empty()) {}\r
+ implementation() : foreground_(nullptr), background_(nullptr), last_frame_(draw_frame::empty()) {}\r
\r
void load(const frame_producer_ptr& frame_producer, load_option::type option)\r
{ \r
void stop()\r
{\r
foreground_ = nullptr;\r
- last_frame_ = producer_frame::empty();\r
+ last_frame_ = draw_frame::empty();\r
}\r
\r
void clear()\r
{\r
foreground_ = nullptr;\r
background_ = nullptr;\r
- last_frame_ = producer_frame::empty();\r
+ last_frame_ = draw_frame::empty();\r
}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{ \r
if(!foreground_ || is_paused_)\r
return last_frame_;\r
{\r
last_frame_ = foreground_->receive();\r
\r
- if(last_frame_ == producer_frame::eof() && foreground_->get_following_producer())\r
+ if(last_frame_ == draw_frame::eof())\r
{\r
CASPAR_LOG(info) << L"EOF: " << foreground_->print();\r
auto following = foreground_->get_following_producer();\r
- following->set_leading_producer(foreground_);\r
+ if(following)\r
+ following->set_leading_producer(foreground_);\r
foreground_ = following;\r
last_frame_ = receive();\r
}\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
CASPAR_LOG(warning) << L"Removed " << (foreground_ ? foreground_->print() : L"empty") << L" from layer.";\r
foreground_ = nullptr;\r
- last_frame_ = producer_frame::empty();\r
+ last_frame_ = draw_frame::empty();\r
}\r
catch(...){}\r
}\r
} \r
\r
tbb::atomic<bool> is_paused_;\r
- producer_frame last_frame_;\r
+ draw_frame last_frame_;\r
frame_producer_ptr foreground_;\r
frame_producer_ptr background_;\r
};\r
void layer::pause(){impl_->pause();}\r
void layer::stop(){impl_->stop();}\r
void layer::clear(){impl_->clear();}\r
-producer_frame layer::receive() {return impl_->receive();}\r
+draw_frame layer::receive() {return impl_->receive();}\r
frame_producer_ptr layer::foreground() const { return impl_->foreground_;}\r
frame_producer_ptr layer::background() const { return impl_->background_;}\r
}}
\ No newline at end of file
frame_producer_ptr foreground() const;\r
frame_producer_ptr background() const;\r
\r
- producer_frame receive();\r
+ draw_frame receive();\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
#include "transition_producer.h"\r
\r
#include "../../format/video_format.h"\r
-#include "../../processor/producer_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../processor/composite_frame.h"\r
#include "../../processor/transform_frame.h"\r
#include "../../processor/frame_processor_device.h"\r
\r
struct transition_producer::implementation : boost::noncopyable\r
{\r
- implementation(const frame_producer_ptr& dest, const transition_info& info) \r
- : current_frame_(0), info_(info), dest_producer_(dest), org_dest_producer_(dest)\r
+ implementation(const frame_producer_ptr& dest, const transition_info& info) : current_frame_(0), info_(info), dest_producer_(dest), org_dest_producer_(dest)\r
{\r
if(!dest)\r
BOOST_THROW_EXCEPTION(null_argument() << arg_name_info("dest"));\r
org_source_producer_ = source_producer_ = producer;\r
}\r
\r
- producer_frame receive()\r
+ draw_frame receive()\r
{\r
if(current_frame_ == 0)\r
CASPAR_LOG(info) << "Transition started.";\r
\r
- producer_frame result = [&]() -> producer_frame\r
+ draw_frame result = [&]() -> draw_frame\r
{\r
if(current_frame_++ >= info_.duration)\r
- return producer_frame::eof();\r
+ return draw_frame::eof();\r
\r
- producer_frame source;\r
- producer_frame dest;\r
+ draw_frame source;\r
+ draw_frame dest;\r
\r
tbb::parallel_invoke\r
(\r
return compose(dest, source);\r
}();\r
\r
- if(result == producer_frame::eof())\r
+ if(result == draw_frame::eof())\r
CASPAR_LOG(info) << "Transition ended.";\r
\r
return result;\r
}\r
\r
- producer_frame receive(frame_producer_ptr& producer)\r
+ draw_frame receive(frame_producer_ptr& producer)\r
{\r
if(!producer)\r
- return producer_frame::eof();\r
+ return draw_frame::eof();\r
\r
- producer_frame frame = producer_frame::eof();\r
+ draw_frame frame = draw_frame::eof();\r
try\r
{\r
frame = producer->receive();\r
CASPAR_LOG(warning) << "Removed producer from transition.";\r
}\r
\r
- if(frame == producer_frame::eof())\r
+ if(frame == draw_frame::eof())\r
{\r
if(!producer || !producer->get_following_producer())\r
- return producer_frame::eof();\r
+ return draw_frame::eof();\r
\r
try\r
{\r
return frame;\r
}\r
\r
- producer_frame compose(producer_frame dest_frame, producer_frame src_frame) \r
+ draw_frame compose(draw_frame dest_frame, draw_frame src_frame) \r
{ \r
- if(dest_frame == producer_frame::eof() && src_frame == producer_frame::eof())\r
- return producer_frame::eof();\r
+ if(dest_frame == draw_frame::eof() && src_frame == draw_frame::eof())\r
+ return draw_frame::eof();\r
\r
if(info_.type == transition::cut) \r
return src_frame;\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
- transform_frame my_src_frame = std::move(src_frame);\r
- transform_frame my_dest_frame = std::move(dest_frame);\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_dest_frame.texcoord((-1.0+alpha)*dir, 1.0, 1.0-(1.0-alpha)*dir, 0.0); \r
}\r
\r
- return std::make_shared<composite_frame>(std::move(my_src_frame), std::move(my_dest_frame));\r
+ return composite_frame(std::move(my_src_frame), std::move(my_dest_frame));\r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
};\r
\r
transition_producer::transition_producer(const frame_producer_ptr& dest, const transition_info& info) : impl_(new implementation(dest, info)){}\r
-producer_frame transition_producer::receive(){return impl_->receive();}\r
+draw_frame transition_producer::receive(){return impl_->receive();}\r
frame_producer_ptr transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
void transition_producer::set_leading_producer(const frame_producer_ptr& producer) { impl_->set_leading_producer(producer); }\r
void transition_producer::initialize(const frame_processor_device_ptr& frame_processor) { impl_->initialize(frame_processor);}\r
struct transition_info\r
{\r
transition_info() : type(transition::cut), duration(0), direction(transition_direction::from_left){}\r
- \r
+ \r
size_t duration;\r
transition_direction::type direction;\r
transition::type type;\r
public:\r
transition_producer(const frame_producer_ptr& destination, const transition_info& info);\r
\r
- producer_frame receive();\r
+ draw_frame receive();\r
\r
frame_producer_ptr get_following_producer() const;\r
void set_leading_producer(const frame_producer_ptr& producer);\r
#include "../producer/flash/flash_producer.h"\r
#include "../producer/flash/ct_producer.h"\r
#include "../producer/image/image_producer.h"\r
-#include "../producer/image/image_scroll_producer.h"\r
+//#include "../producer/image/image_scroll_producer.h"\r
\r
#include "../../common/exception/exceptions.h"\r
\r
(&flash::create_flash_producer)\r
(&flash::create_ct_producer)\r
(&image::create_image_producer)\r
- (&image::create_image_scroll_producer)\r
+ // (&image::create_image_scroll_producer)\r
(&ffmpeg::create_ffmpeg_producer)\r
(&create_color_producer);\r
\r
wcmd = L"CG 1-2 ADD 1 BBTELEFONARE 1";\r
else if(wcmd.substr(0, 1) == L"7")\r
wcmd = L"LOAD 1-1 720p2500";\r
+ else if(wcmd.substr(0, 1) == L"8")\r
+ wcmd = L"LOAD 1-1 #FFFFFFFF AUTOPLAY";\r
\r
wcmd += L"\r\n";\r
amcp.Parse(wcmd.c_str(), wcmd.length(), dummy);\r