\r
#include "consumer/frame_consumer_device.h"\r
\r
-#include "processor/composite_frame.h"\r
+#include "processor/draw_frame.h"\r
#include "processor/draw_frame.h"\r
#include "processor/frame_processor_device.h"\r
\r
void tick()\r
{ \r
auto drawed_frame = draw();\r
- auto future_frame = processor_device_->process(std::move(drawed_frame));\r
- consumer_device_.consume(std::move(future_frame));\r
+ auto processed_frame = processor_device_->process(std::move(drawed_frame));\r
+ consumer_device_.consume(std::move(processed_frame));\r
\r
executor_.begin_invoke([=]{tick();});\r
}\r
}); \r
boost::range::remove_erase(frames, draw_frame::eof());\r
boost::range::remove_erase(frames, draw_frame::empty());\r
- return composite_frame(frames);\r
+ return draw_frame(frames);\r
}\r
\r
void load(int render_layer, const safe_ptr<frame_producer>& producer, bool autoplay)\r
\r
if(embed_audio_)\r
{ \r
- auto& frame_audio_data = frame->audio_data().empty() ? silence : frame->audio_data();\r
+ auto frame_audio_data = frame->audio_data().empty() ? silence.data() : const_cast<short*>(frame->audio_data().begin());\r
\r
- encode_hanc(reinterpret_cast<BLUE_UINT32*>(hanc->data()), const_cast<short*>(frame_audio_data.data()), audio_samples, audio_nchannels);\r
+ encode_hanc(reinterpret_cast<BLUE_UINT32*>(hanc->data()), frame_audio_data, audio_samples, audio_nchannels);\r
\r
- sdk_->system_buffer_write_async(const_cast<unsigned char*>(frame->pixel_data().begin()), \r
- frame->pixel_data().size(), \r
+ sdk_->system_buffer_write_async(const_cast<unsigned char*>(frame->image_data().begin()), \r
+ frame->image_data().size(), \r
nullptr, \r
BlueImage_HANC_DMABuffer(current_id_, BLUE_DATA_IMAGE));\r
\r
}\r
else\r
{\r
- sdk_->system_buffer_write_async(const_cast<unsigned char*>(frame->pixel_data().begin()),\r
- frame->pixel_data().size(), \r
+ sdk_->system_buffer_write_async(const_cast<unsigned char*>(frame->image_data().begin()),\r
+ frame->image_data().size(), \r
nullptr, \r
BlueImage_DMABuffer(current_id_, BLUE_DATA_IMAGE));\r
\r
{\r
active_ = executor_.begin_invoke([=]\r
{ \r
- std::copy(frame->pixel_data().begin(), frame->pixel_data().end(), static_cast<char*>(reserved_frames_.front().first));\r
+ std::copy(frame->image_data().begin(), frame->image_data().end(), static_cast<char*>(reserved_frames_.front().first));\r
\r
if(FAILED(output_->DisplayVideoFrameSync(reserved_frames_.front().second)))\r
CASPAR_LOG(error) << L"DECKLINK: Failed to display frame.";\r
\r
void tick()\r
{\r
- boost::shared_future<frame_type> future_frame;\r
- input_.pop(future_frame);\r
+ frame_type frame;\r
+ input_.pop(frame);\r
\r
- auto frame = future_frame.get();\r
-\r
buffer_.push_back(frame);\r
\r
clock_sync clock;\r
buffer_.pop_front();\r
}\r
\r
- void consume(boost::unique_future<frame_type>&& frame)\r
+ void consume(frame_type&& frame)\r
{ \r
- input_.push(boost::shared_future<frame_type>(std::move(frame)));\r
+ input_.push(std::move(frame));\r
executor_.begin_invoke([=]{tick();});\r
}\r
\r
- tbb::concurrent_bounded_queue<boost::shared_future<frame_type>> input_;\r
+ tbb::concurrent_bounded_queue<frame_type> input_;\r
\r
executor executor_; \r
\r
frame_consumer_device::frame_consumer_device(frame_consumer_device&& other) : impl_(std::move(other.impl_)){}\r
frame_consumer_device::frame_consumer_device(const video_format_desc& format_desc, const std::vector<safe_ptr<frame_consumer>>& consumers)\r
: impl_(new implementation(format_desc, consumers)){}\r
-void frame_consumer_device::consume(boost::unique_future<safe_ptr<const read_frame>>&& future_frame) { impl_->consume(std::move(future_frame)); }\r
+void frame_consumer_device::consume(safe_ptr<const read_frame>&& future_frame) { impl_->consume(std::move(future_frame)); }\r
}}
\ No newline at end of file
public:\r
frame_consumer_device(frame_consumer_device&& other);\r
frame_consumer_device(const video_format_desc& format_desc, const std::vector<safe_ptr<frame_consumer>>& consumers);\r
- void consume(boost::unique_future<safe_ptr<const read_frame>>&& future_frame);\r
+ void consume(safe_ptr<const read_frame>&& future_frame);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
\r
void send(const safe_ptr<const read_frame>& frame)\r
{ \r
- input_.push(frame->audio_data()); \r
+ input_.push(std::vector<short>(frame->audio_data().begin(), frame->audio_data().end())); \r
\r
if(GetStatus() != Playing && input_.size() > 2) \r
Play(); \r
void render(const safe_ptr<const read_frame>& frame)\r
{ \r
auto ptr = pbos_.front().map_write();\r
- std::copy_n(frame->pixel_data().begin(), frame->pixel_data().size(), reinterpret_cast<char*>(ptr));\r
+ std::copy_n(frame->image_data().begin(), frame->image_data().size(), reinterpret_cast<char*>(ptr));\r
\r
GL(glClear(GL_COLOR_BUFFER_BIT)); \r
pbos_.back().bind_texture(); \r
<ClInclude Include="format\pixel_format.h" />\r
<ClInclude Include="format\video_format.h" />\r
<ClInclude Include="processor\audio_processor.h" />\r
- <ClInclude Include="processor\composite_frame.h" />\r
+ <ClInclude Include="processor\buffer\read_buffer.h" />\r
+ <ClInclude Include="processor\buffer\write_buffer.h" />\r
<ClInclude Include="processor\frame_processor_device.h" />\r
<ClInclude Include="processor\image_processor.h" />\r
<ClInclude Include="processor\fwd.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\draw_frame.h" />\r
<ClInclude Include="processor\write_frame.h" />\r
<ClInclude Include="producer\color\color_producer.h" />\r
<ClInclude Include="producer\ffmpeg\audio\audio_decoder.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="format\pixel_format.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="format\video_format.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\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\composite_frame.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+ <ClCompile Include="processor\buffer\read_buffer.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\buffer\write_buffer.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)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
- <ClCompile Include="processor\transform_frame.cpp">\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
<Filter Include="Source\channel\processor\audio">\r
<UniqueIdentifier>{e3d8bd98-8cb9-4f4a-8cf0-bd455ce9138d}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source\channel\processor\buffer">\r
+ <UniqueIdentifier>{d6518ab7-eb0c-4cbe-b83c-a9e32c062b6f}</UniqueIdentifier>\r
+ </Filter>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="StdAfx.h">\r
<ClInclude Include="consumer\frame_consumer_device.h">\r
<Filter>Source\channel\consumer</Filter>\r
</ClInclude>\r
- <ClInclude Include="server.h">\r
- <Filter>Source</Filter>\r
- </ClInclude>\r
<ClInclude Include="processor\frame_processor_device.h">\r
<Filter>Source\channel\processor</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\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\read_frame.h">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\draw_frame.h">\r
- <Filter>Source\channel\processor\frame</Filter>\r
- </ClInclude>\r
<ClInclude Include="processor\image_processor.h">\r
<Filter>Source\channel\processor\image</Filter>\r
</ClInclude>\r
<ClInclude Include="producer\layer.h">\r
<Filter>Source\channel</Filter>\r
</ClInclude>\r
+ <ClInclude Include="server.h">\r
+ <Filter>Source</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="processor\write_frame.h">\r
+ <Filter>Source\channel\processor\frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="processor\draw_frame.h">\r
+ <Filter>Source\channel\processor\frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="processor\buffer\write_buffer.h">\r
+ <Filter>Source\channel\processor\buffer</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="processor\buffer\read_buffer.h">\r
+ <Filter>Source\channel\processor\buffer</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="StdAfx.cpp">\r
<ClCompile Include="consumer\decklink\decklink_consumer.cpp">\r
<Filter>Source\channel\consumer\decklink</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\transform_frame.cpp">\r
- <Filter>Source\channel\processor\frame</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\write_frame.cpp">\r
- <Filter>Source\channel\processor\frame</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\composite_frame.cpp">\r
- <Filter>Source\channel\processor\frame</Filter>\r
- </ClCompile>\r
<ClCompile Include="processor\read_frame.cpp">\r
<Filter>Source\channel\processor\frame</Filter>\r
</ClCompile>\r
- <ClCompile Include="format\pixel_format.cpp">\r
- <Filter>Source\channel\format</Filter>\r
- </ClCompile>\r
<ClCompile Include="processor\image_processor.cpp">\r
<Filter>Source\channel\processor\image</Filter>\r
</ClCompile>\r
<ClCompile Include="producer\layer.cpp">\r
<Filter>Source\channel</Filter>\r
</ClCompile>\r
+ <ClCompile Include="processor\write_frame.cpp">\r
+ <Filter>Source\channel\processor\frame</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="processor\draw_frame.cpp">\r
+ <Filter>Source\channel\processor\frame</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="processor\buffer\read_buffer.cpp">\r
+ <Filter>Source\channel\processor\buffer</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="processor\buffer\write_buffer.cpp">\r
+ <Filter>Source\channel\processor\buffer</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<Midl Include="consumer\decklink\DeckLinkAPI_v7_3.idl">\r
+++ /dev/null
-#include "..\StdAfx.h"\r
-\r
-#include "pixel_format.h"\r
-\r
-namespace caspar { namespace core {\r
- \r
-size_t hash(const pixel_format_desc& desc)\r
-{\r
- size_t hash = 0;\r
- switch(desc.pix_fmt)\r
- {\r
- case pixel_format::ycbcr:\r
- case pixel_format::ycbcra:\r
- // 0-10 (11) width\r
- // 11-21 (11) height\r
- // 22-24 (3) x-ratio\r
- // 25-27 (3) y-ratio\r
- // 28-29 (2) unused\r
- // 30 (1) alpha\r
- // 31 (1) yuv = true => 1\r
- hash |= ( desc.planes[0].width & 0x7FF ) << 0;\r
- hash |= ( desc.planes[0].height & 0x7FF ) << 11;\r
- hash |= ((desc.planes[0].height/desc.planes[1].height) & 0x7 ) << 22;\r
- hash |= ((desc.planes[0].width/desc.planes[1].width) & 0x7 ) << 25;\r
- hash |= desc.pix_fmt == pixel_format::ycbcra ? (1 << 30) : 0;\r
- hash |= 1 << 31;\r
- return hash;\r
- case pixel_format::bgra:\r
- case pixel_format::rgba:\r
- case pixel_format::argb:\r
- case pixel_format::abgr:\r
- \r
- //0-10 (11) height\r
- //11-21 (11) width\r
- //22-29 (8) unused\r
- //30 (1) alpha\r
- //31 (1) yuv = false => 0\r
- hash |= (desc.planes[0].height & 0xFFFF) << 0;\r
- hash |= (desc.planes[0].width & 0xFFFF) << 15;\r
- hash |= 1 << 30;\r
- return hash;\r
-\r
- default:\r
- return hash;\r
- };\r
-}\r
- \r
-}}\r
pixel_format::type pix_fmt;\r
std::vector<plane> planes;\r
};\r
-\r
-size_t hash(const pixel_format_desc& desc);\r
- \r
-inline bool operator==(const pixel_format_desc& lhs, const pixel_format_desc& rhs)\r
-{\r
- return hash(lhs) == hash(rhs);\r
-}\r
-\r
-inline bool operator!=(const pixel_format_desc& lhs, const pixel_format_desc& rhs)\r
-{\r
- return !(lhs == rhs);\r
-}\r
\r
-}}\r
-\r
-namespace std {\r
-\r
-template<> struct hash<caspar::core::pixel_format_desc>\r
-{\r
- size_t operator()(const caspar::core::pixel_format_desc& desc) const { return caspar::core::hash(desc);}\r
-};\r
-\r
-}
\ No newline at end of file
+}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "draw_frame.h"\r
-#include "composite_frame.h"\r
-#include "transform_frame.h"\r
-#include "image_processor.h"\r
-#include "../../common/utility/singleton_pool.h"\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-#include <tbb/parallel_for.h>\r
-\r
-namespace caspar { namespace core {\r
- \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::process_image, std::placeholders::_1, std::ref(processor)));\r
- }\r
-\r
- void process_audio(audio_processor& processor)\r
- {\r
- boost::range::for_each(frames_, std::bind(&draw_frame::process_audio, std::placeholders::_1, std::ref(processor)));\r
- }\r
- \r
- std::vector<safe_ptr<draw_frame>> frames_;\r
-};\r
-\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
-composite_frame& composite_frame::operator=(const composite_frame& other)\r
-{\r
- composite_frame temp(other);\r
- temp.swap(*this);\r
- return *this;\r
-}\r
-composite_frame& composite_frame::operator=(composite_frame&& other)\r
-{\r
- composite_frame temp(std::move(other));\r
- temp.swap(*this);\r
- return *this;\r
-}\r
-\r
-composite_frame::composite_frame(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2)\r
-{\r
- std::vector<safe_ptr<draw_frame>> frames;\r
- frames.push_back(frame1);\r
- frames.push_back(frame2);\r
- impl_ = singleton_pool<implementation>::make_shared(std::move(frames));\r
-}\r
-\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(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2, video_mode::type mode)\r
-{ \r
- auto my_frame1 = make_safe<transform_frame>(frame1);\r
- auto my_frame2 = make_safe<transform_frame>(frame2);\r
- if(mode == video_mode::upper)\r
- {\r
- my_frame1->video_mode(video_mode::upper); \r
- my_frame2->video_mode(video_mode::lower); \r
- }\r
- else\r
- {\r
- my_frame1->video_mode(video_mode::lower); \r
- my_frame2->video_mode(video_mode::upper); \r
- }\r
-\r
- std::vector<safe_ptr<draw_frame>> frames;\r
- frames.push_back(my_frame1);\r
- frames.push_back(my_frame2);\r
- return make_safe<composite_frame>(frames);\r
-}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "fwd.h"\r
-\r
-#include "draw_frame.h"\r
-\r
-#include "../format/video_format.h"\r
-\r
-#include <memory>\r
-#include <algorithm>\r
-\r
-namespace caspar { namespace core {\r
- \r
-class composite_frame : public draw_frame\r
-{\r
-public:\r
- composite_frame(const std::vector<safe_ptr<draw_frame>>& frames);\r
- composite_frame(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2);\r
- \r
- void swap(composite_frame& other);\r
-\r
- composite_frame(const composite_frame& other);\r
- composite_frame(composite_frame&& other);\r
-\r
- composite_frame& operator=(const composite_frame& other);\r
- composite_frame& operator=(composite_frame&& other);\r
-\r
- static safe_ptr<composite_frame> interlace(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2, video_mode::type mode);\r
- \r
-private: \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
-};\r
- \r
-}}
\ No newline at end of file
\r
#include "fwd.h"\r
\r
+#include "draw_frame.h"\r
+\r
+#include "../format/video_format.h"\r
+#include "../format/pixel_format.h"\r
+\r
#include <boost/noncopyable.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
\r
-#include "../../common/utility/safe_ptr.h"\r
+#include <memory>\r
+#include <array>\r
+#include <vector>\r
\r
namespace caspar { namespace core {\r
\r
-class draw_frame : boost::noncopyable\r
-{ \r
+class draw_frame\r
+{\r
public:\r
- virtual ~draw_frame(){}\r
+ draw_frame();\r
+ draw_frame(const safe_ptr<draw_frame>& frame);\r
+ draw_frame(safe_ptr<draw_frame>&& frame);\r
+ draw_frame(const std::vector<safe_ptr<draw_frame>>& frames);\r
+ draw_frame(std::vector<safe_ptr<draw_frame>>&& frame);\r
+ draw_frame(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2);\r
+ draw_frame(safe_ptr<draw_frame>&& frame1, safe_ptr<draw_frame>&& frame2);\r
+\r
+ void swap(draw_frame& other);\r
+ \r
+ draw_frame(const draw_frame& other);\r
+ draw_frame(draw_frame&& other);\r
+\r
+ draw_frame& operator=(const draw_frame& other);\r
+ draw_frame& operator=(draw_frame&& other);\r
\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
+ static safe_ptr<draw_frame> interlace(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2, video_mode::type mode);\r
+ \r
static safe_ptr<draw_frame> eof()\r
{\r
- struct eof_frame : public draw_frame\r
- {\r
- virtual void process_image(image_processor&){}\r
- virtual void process_audio(audio_processor&){}\r
- };\r
+ struct eof_frame : public draw_frame{};\r
static safe_ptr<draw_frame> frame = make_safe<eof_frame>();\r
return frame;\r
}\r
\r
static safe_ptr<draw_frame> empty()\r
{\r
- struct empty_frame : public draw_frame\r
- {\r
- virtual void process_image(image_processor&){}\r
- virtual void process_audio(audio_processor&){}\r
- };\r
+ struct empty_frame : public draw_frame{};\r
static safe_ptr<draw_frame> frame = make_safe<empty_frame>();\r
return frame;\r
}\r
\r
- virtual void process_image(image_processor& processor) = 0;\r
- virtual void process_audio(audio_processor& processor) = 0;\r
+ virtual void process_image(image_processor& processor);\r
+ virtual void process_audio(audio_processor& processor);\r
+ \r
+private:\r
+ struct implementation;\r
+ std::shared_ptr<implementation> impl_;\r
};\r
\r
-\r
-\r
}}
\ No newline at end of file
#include <boost/range/algorithm.hpp>\r
\r
namespace caspar { namespace core {\r
- \r
+\r
+\r
struct frame_processor_device::implementation : boost::noncopyable\r
{ \r
- implementation(const video_format_desc& format_desc) : fmt_(format_desc), writing_(draw_frame::empty()), image_processor_(format_desc)\r
- { \r
- executor_.start();\r
+ implementation(const video_format_desc& format_desc) : fmt_(format_desc), image_processor_(format_desc)\r
+ {\r
+ for(size_t n = 0; n < 3; ++n)\r
+ {\r
+ image_buffer_.push(std::move(image_processor_.begin_pass()));\r
+ image_processor_.end_pass();\r
+ \r
+ audio_buffer_.push(std::move(audio_processor_.begin_pass()));\r
+ audio_processor_.end_pass();\r
+ }\r
}\r
- \r
- boost::unique_future<safe_ptr<const read_frame>> process(safe_ptr<draw_frame>&& frame)\r
+ \r
+ safe_ptr<const read_frame> process(safe_ptr<draw_frame>&& frame)\r
{ \r
- return executor_.begin_invoke([=]() -> safe_ptr<const read_frame>\r
- { \r
- auto result_frame = image_processor_.begin_pass();\r
- writing_->process_image(image_processor_);\r
- image_processor_.end_pass();\r
+ image_buffer_.push(std::move(image_processor_.begin_pass()));\r
+ frame->process_image(image_processor_);\r
+ image_processor_.end_pass();\r
\r
- auto result_audio = audio_processor_.begin_pass();\r
- writing_->process_audio(audio_processor_);\r
- audio_processor_.end_pass();\r
+ audio_buffer_.push(std::move(audio_processor_.begin_pass()));\r
+ frame->process_audio(audio_processor_);\r
+ audio_processor_.end_pass();\r
+ \r
+ auto image = image_buffer_.front().get();\r
+ auto audio = audio_buffer_.front();\r
\r
- writing_ = frame;\r
- \r
- result_frame->audio_data(result_audio);\r
- return result_frame;\r
- });\r
+ image_buffer_.pop();\r
+ audio_buffer_.pop();\r
+\r
+ return make_safe<const read_frame>(std::move(image), std::move(audio));\r
}\r
\r
safe_ptr<write_frame> create_frame(const pixel_format_desc& desc)\r
{\r
- auto pool = &pools_[desc];\r
- std::shared_ptr<write_frame> frame;\r
- if(!pool->try_pop(frame))\r
- 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([=]\r
- {\r
- frame->map();\r
- pool->push(frame);\r
- });\r
- });\r
+ return make_safe<write_frame>(desc, image_processor_.create_buffers(desc));\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
- tbb::concurrent_unordered_map<pixel_format_desc, tbb::concurrent_bounded_queue<std::shared_ptr<write_frame>>, std::hash<pixel_format_desc>> pools_;\r
- \r
+\r
+ std::queue<boost::unique_future<safe_ptr<const read_buffer>>> image_buffer_;\r
+ std::queue<std::vector<short>> audio_buffer_;\r
+ \r
const video_format_desc fmt_;\r
};\r
\r
frame_processor_device::frame_processor_device(frame_processor_device&& other) : impl_(std::move(other.impl_)){}\r
frame_processor_device::frame_processor_device(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-boost::unique_future<safe_ptr<const read_frame>> frame_processor_device::process(safe_ptr<draw_frame>&& frame){return impl_->process(std::move(frame));}\r
+safe_ptr<const read_frame> frame_processor_device::process(safe_ptr<draw_frame>&& frame){return impl_->process(std::move(frame));}\r
const video_format_desc& frame_processor_device::get_video_format_desc() const { return impl_->fmt_; }\r
safe_ptr<write_frame> frame_processor_device::create_frame(const pixel_format_desc& desc){ return impl_->create_frame(desc); } \r
safe_ptr<write_frame> frame_processor_device::create_frame(size_t width, size_t height, pixel_format::type pix_fmt)\r
frame_processor_device(frame_processor_device&& other); // nothrow\r
frame_processor_device(const video_format_desc& format_desc);\r
\r
- boost::unique_future<safe_ptr<const read_frame>> process(safe_ptr<draw_frame>&& frame); // nothrow\r
+ safe_ptr<const read_frame> process(safe_ptr<draw_frame>&& frame); // nothrow\r
\r
safe_ptr<write_frame> create_frame(const pixel_format_desc& desc); \r
safe_ptr<write_frame> create_frame(size_t width, size_t height, pixel_format::type pix_fmt = pixel_format::bgra); \r
class read_frame;\r
class write_frame;\r
class draw_frame;\r
-class transform_frame;\r
-class composite_frame;\r
+class draw_frame;\r
+class draw_frame;\r
\r
class image_processor;\r
class frame_processor;\r
\r
#include "image_processor.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
+#include "buffer/read_buffer.h"\r
+#include "buffer/write_buffer.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
+#include <common/concurrency/executor.h>\r
\r
#include <Glee.h>\r
#include <SFML/Window.hpp>\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) : fbo_(format_desc.width, format_desc.height), current_(pixel_format::invalid), reading_(create_reading())\r
+\r
+struct renderer\r
+{ \r
+ renderer(const video_format_desc& format_desc) : fbo_(format_desc.width, format_desc.height), reading_(create_reading())\r
{\r
transform_stack_.push(image_transform());\r
transform_stack_.top().mode = video_mode::progressive;\r
set_mode(transform_stack_.top().mode);\r
}\r
\r
- void render(const pixel_format_desc& desc, std::vector<gl::pbo>& pbos)\r
+ void render(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>>& buffers)\r
{\r
- set_pixel_format(desc.pix_fmt);\r
+ shaders_[desc.pix_fmt].use();\r
\r
- for(size_t n = 0; n < pbos.size(); ++n)\r
+ for(size_t n = 0; n < buffers.size(); ++n)\r
{\r
+ auto buffer = buffers[n];\r
+\r
glActiveTexture(GL_TEXTURE0+n);\r
- pbos[n].unmap_write();\r
+ buffer->unmap();\r
+ \r
+ bool fit = buffer->width() == fbo_.width() && buffer->height() == fbo_.height();\r
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fit ? GL_NEAREST : GL_LINEAR));\r
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fit ? GL_NEAREST : GL_LINEAR));\r
}\r
\r
auto t = transform_stack_.top();\r
glPopMatrix();\r
}\r
\r
- safe_ptr<read_frame> begin_pass()\r
+ safe_ptr<const read_buffer> begin_pass()\r
{\r
reading_->map();\r
GL(glClear(GL_COLOR_BUFFER_BIT));\r
glPolygonStipple(progressive_pattern);\r
}\r
\r
- void set_pixel_format(pixel_format::type format)\r
+ safe_ptr<read_buffer> create_reading()\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
+ std::shared_ptr<read_buffer> frame;\r
if(!pool_.try_pop(frame)) \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
+ frame = std::make_shared<read_buffer>(fbo_.width(), fbo_.height());\r
+ return safe_ptr<read_buffer>(frame.get(), [=](read_buffer*){pool_.push(frame);});\r
}\r
\r
const ogl_context context_;\r
\r
- tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>> pool_;\r
+ tbb::concurrent_bounded_queue<std::shared_ptr<read_buffer>> pool_;\r
\r
std::stack<image_transform> transform_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
+ safe_ptr<read_buffer> reading_;\r
};\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
-safe_ptr<read_frame> image_processor::begin_pass()\r
-{\r
- if(!impl_)\r
- impl_.reset(new implementation(format_desc_));\r
- return impl_->begin_pass();\r
-}\r
-void image_processor::end_pass()\r
+struct image_processor::implementation : boost::noncopyable\r
{\r
- if(!impl_)\r
- impl_.reset(new implementation(format_desc_));\r
- impl_->end_pass();\r
-}\r
+ implementation(const video_format_desc& format_desc) : format_desc_(format_desc)\r
+ {\r
+ executor_.start();\r
+ }\r
+ \r
+ void begin(const image_transform& transform)\r
+ {\r
+ executor_.begin_invoke([=]{get()->begin(transform);});\r
+ }\r
+ \r
+ void render(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>>& buffers)\r
+ {\r
+ executor_.begin_invoke([=]() mutable{get()->render(desc, buffers);});\r
+ }\r
+\r
+ void end()\r
+ {\r
+ executor_.begin_invoke([=]{get()->end();});\r
+ }\r
+\r
+ boost::unique_future<safe_ptr<const read_buffer>> begin_pass()\r
+ {\r
+ return executor_.begin_invoke([=]{return get()->begin_pass();});\r
+ }\r
+\r
+ void end_pass()\r
+ {\r
+ executor_.begin_invoke([=]{get()->end_pass();});\r
+ }\r
+\r
+ std::unique_ptr<renderer>& get()\r
+ {\r
+ if(!renderer_)\r
+ renderer_.reset(new renderer(format_desc_));\r
+ return renderer_;\r
+ }\r
+\r
+ std::vector<safe_ptr<write_buffer>> create_buffers(const pixel_format_desc& format)\r
+ {\r
+ std::vector<safe_ptr<write_buffer>> buffers;\r
+ std::transform(format.planes.begin(), format.planes.end(), std::back_inserter(buffers), [&](const pixel_format_desc::plane& plane) -> safe_ptr<write_buffer>\r
+ {\r
+ size_t key = ((plane.channels << 24) & 0x0F000000) | ((plane.width << 12) & 0x00FFF000) | ((plane.height << 0) & 0x00000FFF);\r
+ auto pool = &write_frames_[key];\r
+ std::shared_ptr<write_buffer> buffer;\r
+ if(!pool->try_pop(buffer))\r
+ {\r
+ executor_.begin_invoke([&]\r
+ {\r
+ buffer = std::make_shared<write_buffer>(plane.width, plane.height, plane.channels);\r
+ buffer->map();\r
+ }).get(); \r
+ }\r
+\r
+ return safe_ptr<write_buffer>(buffer.get(), [=](write_buffer*)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ buffer->map();\r
+ pool->push(buffer);\r
+ });\r
+ });\r
+ });\r
+ return buffers;\r
+ }\r
+ \r
+ tbb::concurrent_unordered_map<size_t, tbb::concurrent_bounded_queue<std::shared_ptr<write_buffer>>> write_frames_;\r
+\r
+ const video_format_desc format_desc_;\r
+ std::unique_ptr<renderer> renderer_;\r
+ executor executor_; \r
+};\r
+\r
+image_processor::image_processor(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
+void image_processor::begin(const image_transform& transform) { impl_->begin(transform);}\r
+void image_processor::process(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>>& buffers){ impl_->render(desc, buffers);}\r
+void image_processor::end(){impl_->end();}\r
+boost::unique_future<safe_ptr<const read_buffer>> image_processor::begin_pass(){ return impl_->begin_pass();}\r
+void image_processor::end_pass(){impl_->end_pass();}\r
+std::vector<safe_ptr<write_buffer>> image_processor::create_buffers(const pixel_format_desc& format){return impl_->create_buffers(format);}\r
\r
}}
\ No newline at end of file
#pragma once\r
\r
-#include "read_frame.h"\r
+#include "buffer/write_buffer.h"\r
+#include "buffer/read_buffer.h"\r
\r
#include "../format/video_format.h"\r
#include "../format/pixel_format.h"\r
\r
#include <boost/tuple/tuple.hpp>\r
+#include <boost/thread/future.hpp>\r
\r
#include <memory>\r
#include <array>\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 process(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>>& buffers);\r
void end();\r
\r
- safe_ptr<read_frame> begin_pass();\r
+ boost::unique_future<safe_ptr<const read_buffer>> begin_pass();\r
void end_pass();\r
+\r
+ std::vector<safe_ptr<write_buffer>> create_buffers(const pixel_format_desc& format);\r
+\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_shader_ptr;\r
\r
#include "../StdAfx.h"\r
\r
#include "read_frame.h"\r
-#include "../format/pixel_format.h"\r
-#include "../../common/gl/utility.h"\r
-#include "../../common/gl/pixel_buffer_object.h"\r
-#include "../../common/utility/singleton_pool.h"\r
\r
-#include <boost/range/algorithm.hpp>\r
+#include "buffer/read_buffer.h"\r
+\r
+#include <common/gl/utility.h>\r
+#include <common/utility/singleton_pool.h>\r
\r
namespace caspar { namespace core {\r
\r
struct read_frame::implementation : boost::noncopyable\r
{\r
- implementation(size_t width, size_t height) : pbo_(width, height, GL_BGRA)\r
- {\r
- CASPAR_LOG(trace) << "[read_frame] Allocated.";\r
- } \r
-\r
- const boost::iterator_range<const unsigned char*> pixel_data() const\r
- {\r
- if(!pbo_.data())\r
- return boost::iterator_range<const unsigned char*>();\r
-\r
- auto ptr = static_cast<const unsigned char*>(pbo_.data());\r
- return boost::iterator_range<const unsigned char*>(ptr, ptr+pbo_.size());\r
- }\r
+ implementation(safe_ptr<const read_buffer>&& image_data, std::vector<short>&& audio_data) : image_data_(std::move(image_data)), audio_data_(std::move(audio_data)){} \r
\r
- gl::pbo pbo_;\r
+ safe_ptr<const read_buffer> image_data_;\r
std::vector<short> audio_data_;\r
};\r
\r
-read_frame::read_frame(size_t width, size_t height) : impl_(singleton_pool<implementation>::make_shared(width, height)){}\r
-const boost::iterator_range<const unsigned char*> read_frame::pixel_data() const{return impl_->pixel_data();}\r
-const std::vector<short>& read_frame::audio_data() const { return impl_->audio_data_; }\r
-void read_frame::audio_data(const std::vector<short>& audio_data) { impl_->audio_data_ = audio_data; }\r
-void read_frame::unmap(){impl_->pbo_.unmap_read();}\r
-void read_frame::map(){impl_->pbo_.map_read();}\r
+read_frame::read_frame(){}\r
+read_frame::read_frame(safe_ptr<const read_buffer>&& image_data, std::vector<short>&& audio_data) : impl_(singleton_pool<implementation>::make_shared(image_data, audio_data)){}\r
+\r
+const boost::iterator_range<const unsigned char*> read_frame::image_data() const\r
+{\r
+ if(!impl_ || !impl_->image_data_->data())\r
+ return boost::iterator_range<const unsigned char*>();\r
+ auto ptr = static_cast<const unsigned char*>(impl_->image_data_->data());\r
+ return boost::iterator_range<const unsigned char*>(ptr, ptr + impl_->image_data_->size());\r
+}\r
+const boost::iterator_range<const short*> read_frame::audio_data() const\r
+{\r
+ if(!impl_)\r
+ return boost::iterator_range<const short*>();\r
+ return boost::iterator_range<const short*>(impl_->audio_data_.data(), impl_->audio_data_.data() + impl_->audio_data_.size());\r
+}\r
\r
}}
\ No newline at end of file
#pragma once\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
+#include "buffer/read_buffer.h" \r
\r
#include <boost/noncopyable.hpp>\r
#include <boost/range/iterator_range.hpp>\r
\r
class read_frame\r
{\r
- friend class image_processor;\r
public:\r
- explicit read_frame(size_t width, size_t height);\r
- \r
- const boost::iterator_range<const unsigned char*> pixel_data() const;\r
+ read_frame();\r
+ read_frame(safe_ptr<const read_buffer>&& image_data, std::vector<short>&& audio_data);\r
\r
- const std::vector<short>& audio_data() const;\r
- void audio_data(const std::vector<short>& audio_data);\r
+ const boost::iterator_range<const unsigned char*> image_data() const;\r
+ const boost::iterator_range<const short*> audio_data() const;\r
\r
private:\r
- void unmap();\r
- void map();\r
-\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "transform_frame.h"\r
-\r
-#include "draw_frame.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
-#include "../../common/gl/pixel_buffer_object.h"\r
-#include "../../common/utility/singleton_pool.h"\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-#include <tbb/parallel_for.h>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct transform_frame::implementation\r
-{\r
- implementation(const safe_ptr<draw_frame>& frame) : frame_(frame){}\r
- implementation(safe_ptr<draw_frame>&& frame) : frame_(std::move(frame)){}\r
- \r
- void process_image(image_processor& processor)\r
- {\r
- processor.begin(image_transform_);\r
- frame_->process_image(processor);\r
- processor.end();\r
- }\r
-\r
- void process_audio(audio_processor& processor)\r
- {\r
- processor.begin(audio_transform_);\r
- frame_->process_audio(processor);\r
- processor.end();\r
- }\r
- \r
- safe_ptr<draw_frame> frame_;\r
- std::vector<short> audio_data_;\r
- std::vector<short> override_audio_data_;\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(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
-transform_frame& transform_frame::operator=(const transform_frame& other)\r
-{\r
- transform_frame temp(other);\r
- temp.swap(*this);\r
- return *this;\r
-}\r
-transform_frame::transform_frame(transform_frame&& other) : impl_(std::move(other.impl_)){}\r
-transform_frame& transform_frame::operator=(transform_frame&& other)\r
-{\r
- transform_frame temp(std::move(other));\r
- temp.swap(*this);\r
- return *this;\r
-}\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
+++ /dev/null
-#pragma once\r
-\r
-#include "fwd.h"\r
-\r
-#include "draw_frame.h"\r
-\r
-#include "../format/video_format.h"\r
-#include "../format/pixel_format.h"\r
-\r
-#include <boost/noncopyable.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
- \r
-class transform_frame : public draw_frame\r
-{\r
-public:\r
- transform_frame();\r
- transform_frame(const safe_ptr<draw_frame>& frame);\r
- transform_frame(safe_ptr<draw_frame>&& frame);\r
-\r
- void swap(transform_frame& other);\r
- \r
- transform_frame(const transform_frame& other);\r
- transform_frame(transform_frame&& other);\r
-\r
- transform_frame& operator=(const transform_frame& other);\r
- transform_frame& operator=(transform_frame&& other);\r
- \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
-private:\r
-\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
-};\r
-\r
-}}
\ No newline at end of file
\r
#include "write_frame.h"\r
\r
+#include "buffer/write_buffer.h"\r
+\r
#include "draw_frame.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
-#include "../../common/gl/pixel_buffer_object.h"\r
#include "../../common/utility/singleton_pool.h"\r
\r
#include <boost/range/algorithm.hpp>\r
\r
struct write_frame::implementation : boost::noncopyable\r
{\r
- implementation(const pixel_format_desc& desc) : desc_(desc)\r
- {\r
- CASPAR_LOG(trace) << "[write_frame] Allocated.";\r
-\r
- static GLenum mapping[] = {GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGR, GL_BGRA};\r
- std::transform(desc_.planes.begin(), desc_.planes.end(), std::back_inserter(pbos_), [&](const pixel_format_desc::plane& plane)\r
- {\r
- return gl::pbo(plane.width, plane.height, mapping[plane.channels-1]);\r
- });\r
- boost::range::for_each(pbos_, std::mem_fn(&gl::pbo::map_write));\r
- }\r
+ implementation(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>> buffers) : desc_(desc), buffers_(buffers){}\r
\r
- void unmap()\r
- {\r
- boost::range::for_each(pbos_, std::mem_fn(&gl::pbo::unmap_write));\r
- }\r
-\r
- void map()\r
- {\r
- boost::range::for_each(pbos_, std::mem_fn(&gl::pbo::map_write));\r
- }\r
-\r
void process_image(image_processor& processor)\r
{\r
- processor.process(desc_, pbos_);\r
+ processor.process(desc_, buffers_);\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
+ boost::iterator_range<unsigned char*> image_data(size_t index)\r
{\r
- if(index >= pbos_.size() || !pbos_[index].data())\r
+ if(index >= buffers_.size() || !buffers_[index]->data())\r
return boost::iterator_range<const unsigned char*>();\r
- auto ptr = static_cast<unsigned char*>(pbos_[index].data());\r
- return boost::iterator_range<unsigned char*>(ptr, ptr+pbos_[index].size());\r
+ auto ptr = static_cast<unsigned char*>(buffers_[index]->data());\r
+ return boost::iterator_range<unsigned char*>(ptr, ptr+buffers_[index]->size());\r
}\r
- const boost::iterator_range<const unsigned char*> pixel_data(size_t index) const\r
+ const boost::iterator_range<const unsigned char*> image_data(size_t index) const\r
{\r
- if(index >= pbos_.size() || !pbos_[index].data())\r
+ if(index >= buffers_.size() || !buffers_[index]->data())\r
return boost::iterator_range<const unsigned char*>();\r
- auto ptr = static_cast<const unsigned char*>(pbos_[index].data());\r
- return boost::iterator_range<const unsigned char*>(ptr, ptr+pbos_[index].size());\r
+ auto ptr = static_cast<const unsigned char*>(buffers_[index]->data());\r
+ return boost::iterator_range<const unsigned char*>(ptr, ptr+buffers_[index]->size());\r
}\r
\r
- std::vector<gl::pbo> pbos_;\r
+ std::vector<safe_ptr<write_buffer>> buffers_;\r
std::vector<short> audio_data_;\r
const pixel_format_desc desc_;\r
};\r
\r
-write_frame::write_frame(const pixel_format_desc& desc) : impl_(singleton_pool<implementation>::make_shared(desc)){}\r
+write_frame::write_frame(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>> buffers) : impl_(singleton_pool<implementation>::make_shared(desc, buffers)){}\r
write_frame::write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
void write_frame::swap(write_frame& other){impl_.swap(other.impl_);}\r
write_frame& write_frame::operator=(write_frame&& other)\r
temp.swap(*this);\r
return *this;\r
}\r
-void write_frame::map(){impl_->map();} \r
-void write_frame::unmap(){impl_->unmap();} \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
+boost::iterator_range<unsigned char*> write_frame::image_data(size_t index){return impl_->image_data(index);}\r
std::vector<short>& write_frame::audio_data() { return impl_->audio_data_; }\r
}}
\ No newline at end of file
\r
#include "fwd.h"\r
\r
+#include "buffer\write_buffer.h"\r
+\r
#include "draw_frame.h"\r
\r
#include "../format/video_format.h"\r
\r
namespace caspar { namespace core {\r
\r
-class write_frame : public draw_frame\r
+class write_frame : public draw_frame, boost::noncopyable\r
{\r
- friend class frame_processor_device;\r
public: \r
- write_frame(const pixel_format_desc& desc);\r
+ explicit write_frame(const pixel_format_desc& desc, std::vector<safe_ptr<write_buffer>> buffers);\r
write_frame(write_frame&& other);\r
- \r
- void swap(write_frame& other);\r
-\r
write_frame& operator=(write_frame&& other);\r
\r
- boost::iterator_range<unsigned char*> pixel_data(size_t index = 0);\r
- const boost::iterator_range<const unsigned char*> pixel_data(size_t index = 0) const;\r
- \r
+ void swap(write_frame& other);\r
+ \r
+ boost::iterator_range<unsigned char*> image_data(size_t index = 0); \r
std::vector<short>& audio_data();\r
+\r
+ virtual void process_image(image_processor& processor);\r
+ virtual void process_audio(audio_processor& processor);\r
\r
private:\r
- \r
- void map();\r
- void unmap();\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
};\r
void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
{\r
auto frame = frame_processor->create_frame(1, 1, pixel_format::bgra);\r
- auto& value = *reinterpret_cast<unsigned long*>(frame->pixel_data().begin());\r
+ auto& value = *reinterpret_cast<unsigned long*>(frame->image_data().begin());\r
std::wstringstream str(color_str_.substr(1));\r
str >> std::hex >> value; \r
frame_ = std::move(frame);\r
#include "video/video_decoder.h"\r
\r
#include "../../format/video_format.h"\r
-#include "../../processor/transform_frame.h"\r
#include "../../processor/draw_frame.h"\r
-#include "../../server.h"\r
+#include "../../processor/draw_frame.h"\r
\r
#include <tbb/mutex.h>\r
#include <tbb/parallel_invoke.h>\r
struct ffmpeg_producer_impl\r
{\r
public:\r
- ffmpeg_producer_impl(const std::wstring& filename, const std::vector<std::wstring>& params) : filename_(filename), last_frame_(transform_frame(draw_frame::empty())), underrun_count_(0),\r
+ ffmpeg_producer_impl(const std::wstring& filename, const std::vector<std::wstring>& params) : filename_(filename), last_frame_(draw_frame(draw_frame::empty())), underrun_count_(0),\r
input_(filename), video_decoder_(input_.get_video_codec_context().get()), audio_decoder_(input_.get_audio_codec_context().get())\r
{ \r
input_.set_loop(std::find(params.begin(), params.end(), L"LOOP") != params.end());\r
\r
auto write = std::move(video_frame_channel_.front());\r
write->audio_data() = std::move(audio_data);\r
- auto transform = transform_frame(write);\r
+ auto transform = draw_frame(write);\r
video_frame_channel_.pop_front();\r
\r
// TODO: Make generic for all formats and modes.\r
if(!ouput_channel_.empty())\r
{\r
result = std::move(ouput_channel_.front());\r
- last_frame_ = transform_frame(result);\r
+ last_frame_ = draw_frame(result);\r
last_frame_->audio_volume(0.0); // last_frame should not have audio\r
ouput_channel_.pop();\r
}\r
std::deque<safe_ptr<write_frame>> video_frame_channel_; \r
std::deque<std::vector<short>> audio_chunk_channel_;\r
\r
- std::queue<safe_ptr<transform_frame>> ouput_channel_;\r
+ std::queue<safe_ptr<draw_frame>> ouput_channel_;\r
\r
const std::wstring filename_;\r
\r
- safe_ptr<transform_frame> last_frame_;\r
+ safe_ptr<draw_frame> last_frame_;\r
\r
video_format_desc format_desc_;\r
};\r
std::shared_ptr<ffmpeg_producer_impl> impl_;\r
};\r
\r
-safe_ptr<frame_producer> create_ffmpeg_producer(const std::vector<std::wstring>& params)\r
+safe_ptr<frame_producer> create_ffmpeg_producer(const std::vector<std::wstring>& params)\r
{ \r
static const std::vector<std::wstring> extensions = list_of(L"mpg")(L"avi")(L"mov")(L"dv")(L"wav")(L"mp3")(L"mp4")(L"f4v")(L"flv");\r
- std::wstring filename = server::media_folder() + L"\\" + params[0];\r
+ std::wstring filename = params[0];\r
\r
auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
{ \r
if(buffer.try_pop(packet))\r
{\r
buffer_size_ -= packet->size();\r
- executor_.begin_invoke([this]{read_file();});\r
- assert(executor_.size() < 8);\r
+ if(executor_.size() < 4)\r
+ executor_.begin_invoke([this]{read_file();});\r
return std::move(*packet);\r
}\r
return aligned_buffer();\r
tbb::parallel_for(0, static_cast<int>(desc_.planes.size()), 1, [&](int n)\r
{\r
auto plane = desc_.planes[n];\r
- auto result = write->pixel_data(n).begin();\r
+ auto result = write->image_data(n).begin();\r
auto decoded = decoded_frame->data[n];\r
auto decoded_linesize = decoded_frame->linesize[n];\r
\r
\r
AVFrame av_frame; \r
avcodec_get_frame_defaults(&av_frame);\r
- avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), write->pixel_data().begin(), PIX_FMT_BGRA, width_, height_);\r
+ avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), write->image_data().begin(), PIX_FMT_BGRA, width_, height_);\r
\r
sws_scale(sws_context_.get(), decoded_frame->data, decoded_frame->linesize, 0, height_, av_frame.data, av_frame.linesize); \r
\r
#include "../../StdAfx.h"\r
\r
-#if defined(_MSC_VER)\r
-#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
-#endif\r
-\r
#include "cg_producer.h"\r
\r
#include "flash_producer.h"\r
\r
-#include "../../processor/draw_frame.h"\r
#include "../../Server.h"\r
\r
#include <boost/filesystem.hpp>\r
-#include <boost/assign.hpp>\r
\r
namespace caspar { namespace core { namespace flash {\r
\r
-struct template_version\r
-{\r
- enum type\r
- {\r
- _17,\r
- _18,\r
- invalid,\r
- count\r
- };\r
-};\r
-\r
struct cg_producer::implementation : boost::noncopyable\r
{\r
public:\r
-\r
- implementation() : ver_(template_version::invalid), flash_producer_(create_flash()){}\r
-\r
- safe_ptr<flash_producer> create_flash()\r
- { \r
- if(boost::filesystem::exists(server::template_folder()+TEXT("cg.fth.18")))\r
- {\r
- CASPAR_LOG(info) << L"Running version 1.8 template graphics.";\r
- ver_ = template_version::_18;\r
- return safe_ptr<flash_producer>(flash_producer(server::template_folder()+TEXT("cg.fth.18")));\r
- }\r
- else if(boost::filesystem::exists(server::template_folder()+TEXT("cg.fth.17")))\r
- {\r
- CASPAR_LOG(info) << L"Running version 1.7 template graphics.";\r
- ver_ = template_version::_17;\r
- return safe_ptr<flash_producer>(flash_producer(server::template_folder()+TEXT("cg.fth.17")));\r
- }\r
- else \r
- BOOST_THROW_EXCEPTION(file_not_found() << msg_info("No templatehost found.")); \r
- }\r
+ implementation() : flash_producer_(flash_producer(server::template_folder()+TEXT("cg.fth.18"))){}\r
\r
void clear()\r
{\r
- flash_producer_ = create_flash();\r
+ flash_producer_ = flash_producer(server::template_folder()+TEXT("cg.fth.18"));\r
}\r
\r
- void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& label, const std::wstring& data)\r
+ void add(int layer, const std::wstring& filename, bool play_on_load, const std::wstring& label, const std::wstring& data)\r
{\r
CASPAR_LOG(info) << "Invoking add-command";\r
\r
std::wstringstream param;\r
\r
- std::wstring filename = template_name;\r
-\r
- if(ver_ == template_version::_17)\r
- {\r
- std::wstring::size_type pos = template_name.find('.');\r
- filename = (pos != std::wstring::npos) ? template_name.substr(0, pos) : template_name;\r
- }\r
-\r
param << TEXT("<invoke name=\"Add\" returntype=\"xml\"><arguments><number>") << layer << TEXT("</number><string>") << filename << TEXT("</string>") << (play_on_load?TEXT("<true/>"):TEXT("<false/>")) << TEXT("<string>") << label << TEXT("</string><string><![CDATA[ ") << data << TEXT(" ]]></string></arguments></invoke>");\r
\r
flash_producer_->param(param.str());\r
}\r
\r
safe_ptr<flash_producer> flash_producer_;\r
- template_version::type ver_;\r
std::shared_ptr<frame_processor_device> frame_processor_;\r
};\r
\r
\r
#include "cg_producer.h"\r
\r
-#include "../../processor/draw_frame.h"\r
-#include "../../server.h"\r
-\r
-#include <boost/assign/list_of.hpp>\r
-\r
-using namespace boost::assign;\r
-\r
namespace caspar { namespace core { namespace flash {\r
\r
struct ct_producer : public cg_producer\r
\r
safe_ptr<frame_producer> create_ct_producer(const std::vector<std::wstring>& params) \r
{\r
- std::wstring filename = server::media_folder() + L"\\" + params[0] + L".ct";\r
+ std::wstring filename = params[0] + L".ct";\r
return boost::filesystem::exists(filename) ? make_safe<ct_producer>(filename) : frame_producer::empty();\r
}\r
\r
#include "../../format/video_format.h"\r
#include "../../server.h"\r
\r
-#include "../../processor/composite_frame.h"\r
+#include "../../processor/draw_frame.h"\r
\r
#include <common/concurrency/executor.h>\r
\r
\r
safe_ptr<draw_frame> frame = render_frame();\r
if(!is_progressive)\r
- frame = composite_frame::interlace(frame, render_frame(), format_desc_.mode);\r
+ frame = draw_frame::interlace(frame, render_frame(), format_desc_.mode);\r
\r
frame_buffer_.try_push(std::move(frame));\r
}\r
ax_->DrawControl(bmp_frame_->hdc());\r
\r
auto frame = frame_processor_->create_frame();\r
- std::copy(bmp_frame_->data(), bmp_frame_->data() + bmp_frame_->size(), frame->pixel_data().begin());\r
+ std::copy(bmp_frame_->data(), bmp_frame_->data() + bmp_frame_->size(), frame->image_data().begin());\r
current_frame_ = frame;\r
}\r
return current_frame_;\r
#include "../../processor/frame_processor_device.h"\r
#include "../../processor/draw_frame.h"\r
#include "../../format/video_format.h"\r
-#include "../../server.h"\r
\r
#include <boost/assign.hpp>\r
\r
auto bitmap = load_image(filename_);\r
FreeImage_FlipVertical(bitmap.get());\r
auto frame = frame_processor->create_frame(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()));\r
- std::copy_n(FreeImage_GetBits(bitmap.get()), frame->pixel_data().size(), frame->pixel_data().begin());\r
+ std::copy_n(FreeImage_GetBits(bitmap.get()), frame->image_data().size(), frame->image_data().begin());\r
frame_ = std::move(frame);\r
}\r
\r
safe_ptr<frame_producer> create_image_producer(const std::vector<std::wstring>& params)\r
{\r
static const std::vector<std::wstring> extensions = list_of(L"png")(L"tga")(L"bmp")(L"jpg")(L"jpeg");\r
- std::wstring filename = server::media_folder() + L"\\" + params[0];\r
+ std::wstring filename = params[0];\r
\r
auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
{ \r
//#include "image_loader.h"\r
//\r
//#include "../../processor/draw_frame.h"\r
-//#include "../../processor/composite_frame.h"\r
+//#include "../../processor/draw_frame.h"\r
//#include "../../format/video_format.h"\r
//#include "../../processor/frame_processor_device.h"\r
//#include "../../server.h"\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
+// std::fill(frame.image_data().begin(), frame.image_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* frame_data = frame.image_data().begin();\r
// unsigned char* image_data = image_.get();\r
// \r
// if (direction_ == direction::Up || direction_ == direction::Down)\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
+// return draw_frame::interlace(std::move(frame1), std::move(frame2), format_desc_.mode);\r
// } \r
//\r
// return receive(); \r
#include "transition_producer.h"\r
\r
#include "../../format/video_format.h"\r
-#include "../../processor/composite_frame.h"\r
-#include "../../processor/transform_frame.h"\r
+#include "../../processor/draw_frame.h"\r
+#include "../../processor/draw_frame.h"\r
#include "../../processor/frame_processor_device.h"\r
\r
#include <boost/range/algorithm/copy.hpp>\r
\r
double alpha = static_cast<double>(current_frame_)/static_cast<double>(info_.duration);\r
\r
- auto my_src_frame = transform_frame(src_frame);\r
- auto my_dest_frame = transform_frame(dest_frame);\r
+ auto my_src_frame = draw_frame(src_frame);\r
+ auto my_dest_frame = draw_frame(dest_frame);\r
\r
my_src_frame.audio_volume(1.0-alpha);\r
my_dest_frame.audio_volume(alpha);\r
my_dest_frame.texcoord((-1.0+alpha)*dir, 0.0, 0.0-(1.0-alpha)*dir, 0.0); \r
}\r
\r
- return composite_frame(std::move(my_src_frame), std::move(my_dest_frame));\r
+ return draw_frame(std::move(my_src_frame), std::move(my_dest_frame));\r
}\r
\r
void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
//Perform loading of the clip\r
try\r
{\r
+ _parameters[0] = server::media_folder() + L"\\" + _parameters[0];\r
auto pFP = load_media(_parameters); \r
GetChannel()->preview(GetLayerIndex(), pFP);\r
\r
//Perform loading of the clip\r
try\r
{\r
+ _parameters[0] = server::media_folder() + L"\\" + _parameters[0];\r
auto pFP = load_media(_parameters);\r
if(pFP == frame_producer::empty())\r
BOOST_THROW_EXCEPTION(file_not_found() << msg_info(_parameters.size() > 0 ? narrow(_parameters[0]) : ""));\r