\r
#include "consumer/frame_consumer_device.h"\r
\r
-#include "processor/draw_frame.h"\r
-#include "processor/frame_processor_device.h"\r
+#include "mixer/frame/draw_frame.h"\r
+#include "mixer/frame_mixer_device.h"\r
\r
#include "producer/layer.h"\r
\r
\r
struct channel::implementation : boost::noncopyable\r
{ \r
- const safe_ptr<frame_processor_device> processor_device_;\r
+ const safe_ptr<frame_mixer_device> processor_device_;\r
frame_consumer_device consumer_device_;\r
\r
std::map<int, layer> layers_; \r
public:\r
implementation(const video_format_desc& format_desc) \r
: format_desc_(format_desc)\r
- , processor_device_(frame_processor_device(format_desc))\r
+ , processor_device_(frame_mixer_device(format_desc))\r
, consumer_device_(format_desc)\r
{\r
executor_.start();\r
return draw_frame(frames);\r
}\r
\r
+ // Consumers\r
void add(int index, const safe_ptr<frame_consumer>& consumer)\r
{\r
consumer_device_.add(index, consumer);\r
consumer_device_.remove(index);\r
}\r
\r
+ // Layers and Producers\r
+ void set_video_gain(int index, double value)\r
+ {\r
+ begin_invoke_layer(index, std::bind(&layer::set_video_gain, std::placeholders::_1, value));\r
+ }\r
+\r
+ void set_video_opacity(int index, double value)\r
+ {\r
+ begin_invoke_layer(index, std::bind(&layer::set_video_opacity, std::placeholders::_1, value));\r
+ }\r
+\r
+ void set_audio_gain(int index, double value)\r
+ {\r
+ begin_invoke_layer(index, std::bind(&layer::set_audio_gain, std::placeholders::_1, value));\r
+ }\r
+\r
void load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load)\r
{\r
- CASPAR_LOG(trace) << executor_.size();\r
producer->initialize(processor_device_);\r
executor_.begin_invoke([=]\r
{\r
\r
void pause(int index)\r
{ \r
- executor_.begin_invoke([=]\r
- { \r
- auto it = layers_.find(index);\r
- if(it != layers_.end())\r
- it->second.pause(); \r
- });\r
+ begin_invoke_layer(index, std::mem_fn(&layer::pause));\r
}\r
\r
void play(int index)\r
{ \r
- executor_.begin_invoke([=]\r
- {\r
- auto it = layers_.find(index);\r
- if(it != layers_.end())\r
- it->second.play();\r
- });\r
+ begin_invoke_layer(index, std::mem_fn(&layer::play));\r
}\r
\r
void stop(int index)\r
{ \r
- executor_.begin_invoke([=]\r
- {\r
- auto it = layers_.find(index);\r
- if(it != layers_.end())\r
- {\r
- it->second.stop(); \r
- if(it->second.empty())\r
- layers_.erase(it);\r
- }\r
- });\r
+ begin_invoke_layer(index, std::mem_fn(&layer::stop));\r
}\r
\r
void clear(int index)\r
});\r
} \r
\r
+ template<typename F>\r
+ void begin_invoke_layer(int index, F&& func)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ auto it = layers_.find(index);\r
+ if(it != layers_.end())\r
+ func(it->second); \r
+ });\r
+ }\r
+\r
boost::unique_future<safe_ptr<frame_producer>> foreground(int index) const\r
{\r
return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>\r
\r
channel::channel(channel&& other) : impl_(std::move(other.impl_)){}\r
channel::channel(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
+\r
void channel::add(int index, const safe_ptr<frame_consumer>& consumer){impl_->add(index, consumer);}\r
void channel::remove(int index){impl_->remove(index);}\r
+\r
+void channel::set_video_gain(int index, double value){impl_->set_video_gain(index, value);}\r
+void channel::set_video_opacity(int index, double value){impl_->set_video_opacity(index, value);}\r
+void channel::set_audio_gain(int index, double value){impl_->set_audio_gain(index, value);}\r
void channel::load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load){impl_->load(index, producer, play_on_load);}\r
void channel::preview(int index, const safe_ptr<frame_producer>& producer){impl_->preview(index, producer);}\r
void channel::pause(int index){impl_->pause(index);}\r
/// \brief\r
/// \r
/// |**********| <- empty frame <- |***********| <- frame format <- |**********|\r
-/// PROTOCOL -> | PRODUCER | | PROCESSOR | | CONSUMER | -> DISPLAY DEVICE\r
+/// PROTOCOL -> | PRODUCER | | MIXER | | CONSUMER | -> DISPLAY DEVICE\r
/// |**********| -> rendered frames -> |***********| -> formatted frame -> |**********|\r
/// \r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
public:\r
explicit channel(const video_format_desc& format_desc);\r
channel(channel&& other);\r
- \r
+\r
+ // Consumers\r
void add(int index, const safe_ptr<frame_consumer>& consumer);\r
void remove(int index);\r
+ \r
+ // Layers and Producers\r
+ void set_video_gain(int index, double value);\r
+ void set_video_opacity(int index, double value);\r
+\r
+ void set_audio_gain(int index, double value);\r
\r
void load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load = false);\r
void preview(int index, const safe_ptr<frame_producer>& producer);\r
boost::unique_future<safe_ptr<frame_producer>> foreground(int index) const;\r
boost::unique_future<safe_ptr<frame_producer>> background(int index) const;\r
const video_format_desc& get_video_format_desc() const;\r
+\r
private:\r
struct implementation;\r
safe_ptr<implementation> impl_;\r
#include "util.h"\r
#include "memory.h"\r
\r
-#include "../../processor/read_frame.h"\r
+#include "../../mixer/frame/read_frame.h"\r
\r
#include <common/concurrency/executor.h>\r
\r
#include "DeckLinkAPI_h.h"\r
\r
#include "../../video_format.h"\r
-#include "../../processor/read_frame.h"\r
+#include "../../mixer/frame/read_frame.h"\r
\r
#include <common/concurrency/executor.h>\r
#include <common/exception/exceptions.h>\r
\r
#include "ffmpeg_consumer.h"\r
\r
-#include "../../processor/read_frame.h"\r
+#include "../../mixer/frame/read_frame.h"\r
\r
#include <common/concurrency/executor.h>\r
#include <common/utility/string_convert.h>\r
c->codec_type = AVMEDIA_TYPE_VIDEO;\r
\r
// Put sample parameters.\r
- c->bit_rate = (format_desc_.size*static_cast<int>(format_desc_.fps))/2;\r
+ c->bit_rate = static_cast<int>(static_cast<double>(format_desc_.size)*format_desc_.fps*0.1326);\r
c->width = format_desc_.width;\r
c->height = format_desc_.height;\r
c->time_base.den = static_cast<int>(format_desc_.fps);\r
\r
#include "../../video_format.h"\r
\r
-#include "../../processor/read_frame.h"\r
+#include "../../mixer/frame/read_frame.h"\r
\r
#include <SFML/Audio.hpp>\r
\r
#include "ogl_consumer.h"\r
\r
#include "../../video_format.h"\r
-#include "../../processor/read_frame.h"\r
+#include "../../mixer/frame/read_frame.h"\r
\r
#include <common/gl/gl_check.h>\r
#include <common/concurrency/executor.h>\r
<ClInclude Include="consumer\frame_consumer.h" />\r
<ClInclude Include="consumer\oal\oal_consumer.h" />\r
<ClInclude Include="consumer\ogl\ogl_consumer.h" />\r
- <ClInclude Include="processor\audio_processor.h" />\r
- <ClInclude Include="processor\device_buffer.h" />\r
- <ClInclude Include="processor\frame_processor_device.h" />\r
- <ClInclude Include="processor\host_buffer.h" />\r
- <ClInclude Include="processor\image_kernel.h" />\r
- <ClInclude Include="processor\image_processor.h" />\r
- <ClInclude Include="processor\fwd.h" />\r
- <ClInclude Include="processor\ogl_device.h" />\r
- <ClInclude Include="processor\pixel_format.h" />\r
- <ClInclude Include="processor\read_frame.h" />\r
- <ClInclude Include="processor\draw_frame.h" />\r
- <ClInclude Include="processor\write_frame.h" />\r
+ <ClInclude Include="mixer\audio\audio_mixer.h" />\r
+ <ClInclude Include="mixer\frame\draw_frame.h" />\r
+ <ClInclude Include="mixer\frame\pixel_format.h" />\r
+ <ClInclude Include="mixer\frame\read_frame.h" />\r
+ <ClInclude Include="mixer\frame\write_frame.h" />\r
+ <ClInclude Include="mixer\frame_mixer_device.h" />\r
+ <ClInclude Include="mixer\fwd.h" />\r
+ <ClInclude Include="mixer\gpu\device_buffer.h" />\r
+ <ClInclude Include="mixer\gpu\host_buffer.h" />\r
+ <ClInclude Include="mixer\gpu\ogl_device.h" />\r
+ <ClInclude Include="mixer\image\image_kernel.h" />\r
+ <ClInclude Include="mixer\image\image_mixer.h" />\r
<ClInclude Include="producer\color\color_producer.h" />\r
<ClInclude Include="producer\decklink\decklink_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="processor\audio_processor.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+ <ClCompile Include="mixer\audio\audio_mixer.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\device_buffer.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+ <ClCompile Include="mixer\frame\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="mixer\frame\read_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\host_buffer.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+ <ClCompile Include="mixer\frame\write_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\image_kernel.cpp">\r
+ <ClCompile Include="mixer\frame_mixer_device.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\image_processor.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
+ <ClCompile Include="mixer\gpu\device_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\ogl_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="mixer\gpu\host_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\read_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="mixer\gpu\ogl_device.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\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 Include="mixer\image\image_kernel.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\write_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="mixer\image\image_mixer.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="producer\color\color_producer.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
<Filter Include="Source\consumer\decklink\interop">\r
<UniqueIdentifier>{a5cb89d7-dbbb-4fca-b899-f53a069727b4}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="Source\processor">\r
- <UniqueIdentifier>{53e41831-70b4-4214-bc38-77e0d7aa288b}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\processor\frame">\r
- <UniqueIdentifier>{1b9effc5-16ee-4be7-9189-d2b6bec0165a}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\processor\image">\r
- <UniqueIdentifier>{fe2c2f78-7daf-4b6d-9132-eda45b4c93e1}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\processor\audio">\r
- <UniqueIdentifier>{e3d8bd98-8cb9-4f4a-8cf0-bd455ce9138d}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\processor\ogl">\r
- <UniqueIdentifier>{219e5733-b365-4231-8c79-fd689c46c488}</UniqueIdentifier>\r
- </Filter>\r
<Filter Include="Source\producer">\r
<UniqueIdentifier>{71accefc-1437-4e1d-9ff7-9de654a32df9}</UniqueIdentifier>\r
</Filter>\r
<Filter Include="Source\consumer\ffmpeg">\r
<UniqueIdentifier>{b651856c-ff7e-4f90-be8a-32aba6094dbd}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source\mixer">\r
+ <UniqueIdentifier>{fe65a63a-9c77-450e-8b5a-d08ea7067053}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\mixer\frame">\r
+ <UniqueIdentifier>{3cf873fa-08ad-43e1-b530-fda9d8621ba4}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\mixer\image">\r
+ <UniqueIdentifier>{300816f9-421b-4fab-82e0-acabe5b1e1b7}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\mixer\audio">\r
+ <UniqueIdentifier>{fd06d1d1-2b0b-4913-8416-f8fa1de42442}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\mixer\gpu">\r
+ <UniqueIdentifier>{5e7c7a4c-4a81-4aa1-b628-0344bf89517e}</UniqueIdentifier>\r
+ </Filter>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="consumer\decklink\DeckLinkAPI_h.h">\r
<ClInclude Include="consumer\frame_consumer_device.h">\r
<Filter>Source\consumer</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\frame_processor_device.h">\r
- <Filter>Source\processor</Filter>\r
- </ClInclude>\r
<ClInclude Include="consumer\decklink\decklink_consumer.h">\r
<Filter>Source\consumer\decklink</Filter>\r
</ClInclude>\r
<ClInclude Include="consumer\decklink\util.h">\r
<Filter>Source\consumer\decklink</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\fwd.h">\r
- <Filter>Source\processor</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\read_frame.h">\r
- <Filter>Source\processor\frame</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\image_processor.h">\r
- <Filter>Source\processor\image</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\audio_processor.h">\r
- <Filter>Source\processor\audio</Filter>\r
- </ClInclude>\r
<ClInclude Include="producer\ffmpeg\audio\audio_decoder.h">\r
<Filter>Source\producer\ffmpeg\audio</Filter>\r
</ClInclude>\r
<ClInclude Include="producer\ffmpeg\video\video_decoder.h">\r
<Filter>Source\producer\ffmpeg\video</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\write_frame.h">\r
- <Filter>Source\processor\frame</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\image_kernel.h">\r
- <Filter>Source\processor\image</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\ogl_device.h">\r
- <Filter>Source\processor\ogl</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\host_buffer.h">\r
- <Filter>Source\processor\ogl</Filter>\r
- </ClInclude>\r
- <ClInclude Include="processor\device_buffer.h">\r
- <Filter>Source\processor\ogl</Filter>\r
- </ClInclude>\r
<ClInclude Include="StdAfx.h">\r
<Filter>Afx</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\pixel_format.h">\r
- <Filter>Source\processor</Filter>\r
- </ClInclude>\r
<ClInclude Include="producer\flash\axflash.h">\r
<Filter>Source\producer\flash\interop</Filter>\r
</ClInclude>\r
<ClInclude Include="producer\flash\TimerHelper.h">\r
<Filter>Source\producer\flash\interop</Filter>\r
</ClInclude>\r
- <ClInclude Include="processor\draw_frame.h">\r
- <Filter>Source\processor\frame</Filter>\r
- </ClInclude>\r
<ClInclude Include="video_format.h">\r
<Filter>Source</Filter>\r
</ClInclude>\r
<ClInclude Include="consumer\ffmpeg\ffmpeg_consumer.h">\r
<Filter>Source\consumer\ffmpeg</Filter>\r
</ClInclude>\r
+ <ClInclude Include="mixer\frame_mixer_device.h">\r
+ <Filter>Source\mixer</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\fwd.h">\r
+ <Filter>Source\mixer</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\image\image_kernel.h">\r
+ <Filter>Source\mixer\image</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\image\image_mixer.h">\r
+ <Filter>Source\mixer\image</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\audio\audio_mixer.h">\r
+ <Filter>Source\mixer\audio</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\gpu\device_buffer.h">\r
+ <Filter>Source\mixer\gpu</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\gpu\host_buffer.h">\r
+ <Filter>Source\mixer\gpu</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\gpu\ogl_device.h">\r
+ <Filter>Source\mixer\gpu</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\frame\draw_frame.h">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\frame\pixel_format.h">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\frame\read_frame.h">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="mixer\frame\write_frame.h">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="consumer\decklink\DeckLinkAPI_i.c">\r
<ClCompile Include="consumer\frame_consumer_device.cpp">\r
<Filter>Source\consumer</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\frame_processor_device.cpp">\r
- <Filter>Source\processor</Filter>\r
- </ClCompile>\r
<ClCompile Include="consumer\decklink\decklink_consumer.cpp">\r
<Filter>Source\consumer\decklink</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\read_frame.cpp">\r
- <Filter>Source\processor\frame</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\image_processor.cpp">\r
- <Filter>Source\processor\image</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\audio_processor.cpp">\r
- <Filter>Source\processor\audio</Filter>\r
- </ClCompile>\r
<ClCompile Include="producer\ffmpeg\audio\audio_decoder.cpp">\r
<Filter>Source\producer\ffmpeg\audio</Filter>\r
</ClCompile>\r
<ClCompile Include="producer\ffmpeg\video\video_decoder.cpp">\r
<Filter>Source\producer\ffmpeg\video</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\write_frame.cpp">\r
- <Filter>Source\processor\frame</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\image_kernel.cpp">\r
- <Filter>Source\processor\image</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\ogl_device.cpp">\r
- <Filter>Source\processor\ogl</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\host_buffer.cpp">\r
- <Filter>Source\processor\ogl</Filter>\r
- </ClCompile>\r
- <ClCompile Include="processor\device_buffer.cpp">\r
- <Filter>Source\processor\ogl</Filter>\r
- </ClCompile>\r
<ClCompile Include="StdAfx.cpp">\r
<Filter>Afx</Filter>\r
</ClCompile>\r
<ClCompile Include="producer\flash\Flash9e_i.c">\r
<Filter>Source\producer\flash\interop</Filter>\r
</ClCompile>\r
- <ClCompile Include="processor\draw_frame.cpp">\r
- <Filter>Source\processor\frame</Filter>\r
- </ClCompile>\r
<ClCompile Include="video_format.cpp">\r
<Filter>Source</Filter>\r
</ClCompile>\r
<ClCompile Include="consumer\ffmpeg\ffmpeg_consumer.cpp">\r
<Filter>Source\consumer\ffmpeg</Filter>\r
</ClCompile>\r
+ <ClCompile Include="mixer\frame_mixer_device.cpp">\r
+ <Filter>Source\mixer</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\image\image_kernel.cpp">\r
+ <Filter>Source\mixer\image</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\image\image_mixer.cpp">\r
+ <Filter>Source\mixer\image</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\audio\audio_mixer.cpp">\r
+ <Filter>Source\mixer\audio</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
+ <Filter>Source\mixer\gpu</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
+ <Filter>Source\mixer\gpu</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\gpu\ogl_device.cpp">\r
+ <Filter>Source\mixer\gpu</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\frame\draw_frame.cpp">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\frame\read_frame.cpp">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="mixer\frame\write_frame.cpp">\r
+ <Filter>Source\mixer\frame</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<Midl Include="producer\flash\Flash9e.IDL">\r
+++ /dev/null
-#include "../stdafx.h"\r
-\r
-#include "audio_processor.h"\r
-\r
-namespace caspar { namespace core {\r
- \r
-audio_transform& audio_transform::operator*=(const audio_transform &other) \r
-{\r
- volume *= other.volume;\r
- return *this;\r
-}\r
-\r
-const audio_transform audio_transform::operator*(const audio_transform &other) const \r
-{\r
- return audio_transform(*this) *= other;\r
-}\r
-\r
-struct audio_processor::implementation\r
-{\r
- std::vector<short> audio_data_;\r
- std::stack<audio_transform> transform_stack_;\r
-\r
-public:\r
- implementation()\r
- {\r
- transform_stack_.push(audio_transform());\r
- }\r
-\r
- void begin(const audio_transform& transform)\r
- {\r
- transform_stack_.push(transform_stack_.top()*transform);\r
- }\r
-\r
- void process(const std::vector<short>& audio_data)\r
- { \r
- if(audio_data_.empty())\r
- audio_data_.resize(audio_data.size(), 0);\r
-\r
- tbb::parallel_for\r
- (\r
- tbb::blocked_range<size_t>(0, audio_data.size()),\r
- [&](const tbb::blocked_range<size_t>& r)\r
- {\r
- for(size_t n = r.begin(); n < r.end(); ++n)\r
- {\r
- int sample = static_cast<int>(audio_data[n]);\r
- sample = (static_cast<int>(transform_stack_.top().volume*8192.0)*sample)/8192;\r
- audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + sample) & 0xFFFF);\r
- }\r
- }\r
- );\r
- }\r
-\r
- void end()\r
- {\r
- transform_stack_.pop();\r
- }\r
-\r
- std::vector<short> begin_pass()\r
- {\r
- return std::move(audio_data_);\r
- }\r
-};\r
-\r
-audio_processor::audio_processor() : impl_(new implementation()){}\r
-void audio_processor::begin(const audio_transform& transform){impl_->begin(transform);}\r
-void audio_processor::process(const std::vector<short>& audio_data){impl_->process(audio_data);}\r
-void audio_processor::end(){impl_->end();}\r
-std::vector<short> audio_processor::begin_pass(){return impl_->begin_pass();} \r
-void audio_processor::end_pass(){}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-namespace caspar { namespace core {\r
-\r
-struct audio_transform\r
-{\r
- audio_transform() : volume(1.0){}\r
- double volume;\r
-\r
- audio_transform& operator*=(const audio_transform &other);\r
- const audio_transform operator*(const audio_transform &other) const;\r
-};\r
-\r
-class audio_processor\r
-{\r
-public:\r
- audio_processor();\r
-\r
- void begin(const audio_transform& transform);\r
- void process(const std::vector<short>& audio_data);\r
- void end();\r
- \r
- std::vector<short> begin_pass();\r
- void end_pass();\r
-\r
-private:\r
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "device_buffer.h"\r
-\r
-#include <common/gl/gl_check.h>\r
-\r
-namespace caspar { namespace core {\r
- \r
-GLenum FORMAT[] = {0, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGR, GL_BGRA};\r
-GLenum INTERNAL_FORMAT[] = {0, GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8}; \r
-\r
-struct device_buffer::implementation : boost::noncopyable\r
-{\r
- GLuint id_;\r
-\r
- const size_t width_;\r
- const size_t height_;\r
- const size_t stride_;\r
-\r
-public:\r
- implementation(size_t width, size_t height, size_t stride) \r
- : width_(width)\r
- , height_(height)\r
- , stride_(stride)\r
- { \r
- GL(glGenTextures(1, &id_));\r
- GL(glBindTexture(GL_TEXTURE_2D, id_));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
- GL(glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT[stride_], width_, height_, 0, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
- GL(glBindTexture(GL_TEXTURE_2D, 0)); \r
- } \r
-\r
- ~implementation()\r
- {\r
- GL(glDeleteTextures(1, &id_));\r
- }\r
- \r
- void bind()\r
- {\r
- GL(glBindTexture(GL_TEXTURE_2D, id_));\r
- }\r
-\r
- void unbind()\r
- {\r
- GL(glBindTexture(GL_TEXTURE_2D, 0));\r
- }\r
-\r
- void read(host_buffer& source)\r
- {\r
- GL(glBindTexture(GL_TEXTURE_2D, id_));\r
- source.unmap();\r
- source.bind();\r
- GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
- source.unbind();\r
- GL(glBindTexture(GL_TEXTURE_2D, 0));\r
- }\r
- \r
- void write(host_buffer& target)\r
- {\r
- GL(glBindTexture(GL_TEXTURE_2D, id_));\r
- target.unmap();\r
- target.bind();\r
- GL(glReadPixels(0, 0, width_, height_, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
- target.unbind();\r
- GL(glBindTexture(GL_TEXTURE_2D, 0));\r
- }\r
-\r
- void attach(int index)\r
- {\r
- GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, GL_TEXTURE_2D, id_, 0));\r
- }\r
-};\r
-\r
-device_buffer::device_buffer(size_t width, size_t height, size_t stride) : impl_(new implementation(width, height, stride)){}\r
-size_t device_buffer::stride() const { return impl_->stride_; }\r
-size_t device_buffer::width() const { return impl_->width_; }\r
-size_t device_buffer::height() const { return impl_->height_; }\r
-void device_buffer::attach(int index){impl_->attach(index);}\r
-void device_buffer::bind(){impl_->bind();}\r
-void device_buffer::unbind(){impl_->unbind();}\r
-void device_buffer::read(host_buffer& source){impl_->read(source);}\r
-void device_buffer::write(host_buffer& target){impl_->write(target);}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "host_buffer.h"\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <memory>\r
-\r
-namespace caspar { namespace core {\r
- \r
-class device_buffer : boost::noncopyable\r
-{\r
-public:\r
- device_buffer(size_t width, size_t height, size_t stride);\r
- \r
- size_t stride() const; \r
- size_t width() const;\r
- size_t height() const;\r
- \r
- void bind();\r
- void unbind();\r
-\r
- void attach(int index);\r
- void read(host_buffer& source);\r
- void write(host_buffer& target);\r
- \r
-private:\r
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "draw_frame.h"\r
-\r
-#include "image_processor.h"\r
-#include "audio_processor.h"\r
-#include "pixel_format.h"\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct draw_frame::implementation\r
-{ \r
- std::vector<safe_ptr<draw_frame>> frames_;\r
-\r
- image_transform image_transform_; \r
- audio_transform audio_transform_;\r
-\r
-public:\r
- implementation(const std::vector<safe_ptr<draw_frame>>& frames) \r
- : frames_(frames){}\r
- implementation(std::vector<safe_ptr<draw_frame>>&& frames) \r
- : frames_(std::move(frames)){}\r
- \r
- void process_image(image_processor& processor)\r
- {\r
- processor.begin(image_transform_);\r
- BOOST_FOREACH(auto frame, frames_)\r
- frame->process_image(processor);\r
- processor.end();\r
- }\r
-\r
- void process_audio(audio_processor& processor)\r
- {\r
- processor.begin(audio_transform_);\r
- BOOST_FOREACH(auto frame, frames_)\r
- frame->process_audio(processor);\r
- processor.end();\r
- } \r
-};\r
- \r
-draw_frame::draw_frame() : impl_(new implementation(std::vector<safe_ptr<draw_frame>>())){}\r
-draw_frame::draw_frame(const std::vector<safe_ptr<draw_frame>>& frames) : impl_(new implementation(frames)){}\r
-draw_frame::draw_frame(std::vector<safe_ptr<draw_frame>>&& frames) : impl_(new implementation(std::move(frames))){}\r
-draw_frame::draw_frame(const draw_frame& other) : impl_(new implementation(*other.impl_)){}\r
-draw_frame::draw_frame(const safe_ptr<draw_frame>& frame)\r
-{\r
- std::vector<safe_ptr<draw_frame>> frames;\r
- frames.push_back(frame);\r
- impl_.reset(new implementation(std::move(frames)));\r
-}\r
-draw_frame::draw_frame(safe_ptr<draw_frame>&& frame)\r
-{\r
- std::vector<safe_ptr<draw_frame>> frames;\r
- frames.push_back(std::move(frame));\r
- impl_.reset(new implementation(std::move(frames)));\r
-}\r
-draw_frame::draw_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_.reset(new implementation(std::move(frames)));\r
-}\r
-draw_frame::draw_frame(safe_ptr<draw_frame>&& frame1, safe_ptr<draw_frame>&& frame2)\r
-{\r
- std::vector<safe_ptr<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 draw_frame::swap(draw_frame& other){impl_.swap(other.impl_);}\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(draw_frame&& other) : impl_(std::move(other.impl_)){}\r
-draw_frame& draw_frame::operator=(draw_frame&& other)\r
-{\r
- draw_frame temp(std::move(other));\r
- temp.swap(*this);\r
- return *this;\r
-}\r
-void draw_frame::process_image(image_processor& processor){impl_->process_image(processor);}\r
-void draw_frame::process_audio(audio_processor& processor){impl_->process_audio(processor);}\r
-void draw_frame::audio_volume(double volume){impl_->audio_transform_.volume = volume;}\r
-void draw_frame::translate(double x, double y){impl_->image_transform_.pos = boost::make_tuple(x, y);}\r
-void draw_frame::texcoord(double left, double top, double right, double bottom){impl_->image_transform_.uv = boost::make_tuple(left, top, right, bottom);}\r
-void draw_frame::video_mode(video_mode::type mode){impl_->image_transform_.mode = mode;}\r
-void draw_frame::alpha(double value){impl_->image_transform_.alpha = value;}\r
-const image_transform& draw_frame::get_image_transform() const { return impl_->image_transform_;}\r
-const audio_transform& draw_frame::get_audio_transform() const { return impl_->audio_transform_;}\r
-\r
-safe_ptr<draw_frame> draw_frame::interlace(const safe_ptr<draw_frame>& frame1, const safe_ptr<draw_frame>& frame2, video_mode::type mode)\r
-{ \r
- if(frame1 == frame2 || mode == video_mode::progressive)\r
- return frame1;\r
-\r
- auto my_frame1 = make_safe<draw_frame>(frame1);\r
- auto my_frame2 = make_safe<draw_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<draw_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 "../video_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
-struct image_transform;\r
-struct audio_transform;\r
- \r
-class draw_frame\r
-{\r
-public:\r
- draw_frame(); \r
- draw_frame(safe_ptr<write_frame>&& image, std::vector<short>&& audio);\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
- const image_transform& get_image_transform() const;\r
- const audio_transform& get_audio_transform() const;\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
- 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
- static safe_ptr<draw_frame> frame = make_safe<empty_frame>();\r
- return frame;\r
- }\r
-\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
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "frame_processor_device.h"\r
-\r
-#include "audio_processor.h"\r
-#include "image_processor.h"\r
-\r
-#include "write_frame.h"\r
-#include "read_frame.h"\r
-\r
-#include "../video_format.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-#include <common/concurrency/executor.h>\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <tbb/concurrent_queue.h>\r
-#include <tbb/concurrent_unordered_map.h>\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct frame_processor_device::implementation : boost::noncopyable\r
-{ \r
- const video_format_desc format_desc_;\r
-\r
- audio_processor audio_processor_;\r
- image_processor image_processor_;\r
-\r
-public:\r
- implementation(const video_format_desc& format_desc) \r
- : format_desc_(format_desc)\r
- , image_processor_(format_desc){}\r
- \r
- safe_ptr<const read_frame> process(safe_ptr<draw_frame>&& frame)\r
- { \r
- auto image = image_processor_.begin_pass();\r
- frame->process_image(image_processor_);\r
- image_processor_.end_pass();\r
-\r
- auto audio = audio_processor_.begin_pass();\r
- frame->process_audio(audio_processor_);\r
- audio_processor_.end_pass();\r
-\r
- return make_safe<const read_frame>(std::move(image.get()), std::move(audio));\r
- }\r
- \r
- safe_ptr<write_frame> create_frame(const pixel_format_desc& desc)\r
- {\r
- return make_safe<write_frame>(desc, image_processor_.create_buffers(desc));\r
- }\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
-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_->format_desc_; }\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
-{\r
- // Create bgra frame\r
- pixel_format_desc desc;\r
- desc.pix_fmt = pix_fmt;\r
- desc.planes.push_back(pixel_format_desc::plane(width, height, 4));\r
- return create_frame(desc);\r
-}\r
- \r
-safe_ptr<write_frame> frame_processor_device::create_frame(pixel_format::type pix_fmt)\r
-{\r
- // Create bgra frame with output resolution\r
- pixel_format_desc desc;\r
- desc.pix_fmt = pix_fmt;\r
- desc.planes.push_back(pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4));\r
- return create_frame(desc);\r
-}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG.\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include "fwd.h"\r
-\r
-#include "write_frame.h"\r
-#include "pixel_format.h"\r
-\r
-#include <common/memory/safe_ptr.h>\r
-\r
-namespace caspar { namespace core {\r
-\r
-struct video_format;\r
-\r
-class frame_processor_device : boost::noncopyable\r
-{\r
-public:\r
- frame_processor_device(frame_processor_device&& other); // nothrow\r
- frame_processor_device(const video_format_desc& format_desc);\r
- \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
- safe_ptr<write_frame> create_frame(pixel_format::type pix_fmt = pixel_format::bgra);\r
- \r
- const video_format_desc& get_video_format_desc() const; // nothrow\r
-private:\r
- struct implementation;\r
- safe_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include <memory>\r
-\r
-namespace caspar { namespace core {\r
- \r
-class read_frame;\r
-class write_frame;\r
-class draw_frame;\r
-\r
-class image_processor;\r
-class frame_processor;\r
-class audio_processor;\r
-class frame_processor_device;\r
-\r
-struct pixel_format_desc;\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "host_buffer.h"\r
-\r
-#include <common/gl/gl_check.h>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct host_buffer::implementation : boost::noncopyable\r
-{ \r
- GLuint pbo_;\r
-\r
- const size_t size_;\r
-\r
- void* data_;\r
- GLenum usage_;\r
- GLenum target_;\r
-\r
-public:\r
- implementation(size_t size, usage_t usage) \r
- : size_(size)\r
- , data_(nullptr)\r
- , pbo_(0)\r
- , target_(usage == write_only ? GL_PIXEL_UNPACK_BUFFER : GL_PIXEL_PACK_BUFFER)\r
- , usage_(usage == write_only ? GL_STREAM_DRAW : GL_STREAM_READ)\r
- {\r
- GL(glGenBuffers(1, &pbo_));\r
- GL(glBindBuffer(target_, pbo_));\r
- GL(glBufferData(target_, size_, NULL, usage_)); \r
- GL(glBindBuffer(target_, 0));\r
-\r
- if(!pbo_)\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
- CASPAR_LOG(trace) << "[host_buffer] Allocated.";\r
- } \r
-\r
- ~implementation()\r
- {\r
- GL(glDeleteBuffers(1, &pbo_));\r
- }\r
-\r
- void map()\r
- {\r
- if(data_)\r
- return;\r
- \r
- GL(glBindBuffer(target_, pbo_));\r
- data_ = glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY); \r
- GL(glBindBuffer(target_, 0)); \r
- if(!data_)\r
- BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target_ OpenGL Pixel Buffer Object."));\r
- }\r
-\r
- void unmap()\r
- {\r
- if(!data_)\r
- return;\r
- \r
- GL(glBindBuffer(target_, pbo_));\r
- GL(glUnmapBuffer(target_)); \r
- data_ = nullptr; \r
- GL(glBindBuffer(target_, 0));\r
- }\r
-\r
- void bind()\r
- {\r
- GL(glBindBuffer(target_, pbo_));\r
- }\r
-\r
- void unbind()\r
- {\r
- GL(glBindBuffer(target_, 0));\r
- }\r
-};\r
-\r
-host_buffer::host_buffer(size_t size, usage_t usage) : impl_(new implementation(size, usage)){}\r
-const void* host_buffer::data() const {return impl_->data_;}\r
-void* host_buffer::data() {return impl_->data_;}\r
-void host_buffer::map(){impl_->map();}\r
-void host_buffer::unmap(){impl_->unmap();}\r
-void host_buffer::bind(){impl_->bind();}\r
-void host_buffer::unbind(){impl_->unbind();}\r
-\r
-size_t host_buffer::size() const { return impl_->size_; }\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <memory>\r
-\r
-namespace caspar { namespace core {\r
- \r
-class host_buffer : boost::noncopyable\r
-{\r
-public:\r
- enum usage_t\r
- {\r
- write_only,\r
- read_only\r
- };\r
- host_buffer(size_t size, usage_t usage);\r
- \r
- const void* data() const;\r
- void* data();\r
- size_t size() const; \r
- \r
- void bind();\r
- void unbind();\r
- void unmap();\r
- void map();\r
-private:\r
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "image_kernel.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <Glee.h>\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <unordered_map>\r
-\r
-namespace caspar { namespace core {\r
-\r
-class shader_program\r
-{\r
- GLuint program_;\r
-public:\r
-\r
- shader_program() : program_(0) {}\r
- shader_program(const std::string& vertex_source_str, const std::string& fragment_source_str) : program_(0)\r
- {\r
- GLint success;\r
- \r
- const char* vertex_source = vertex_source_str.c_str();\r
- \r
- auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
- \r
- GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\r
- GL(glCompileShaderARB(vertex_shader));\r
-\r
- GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
- if (success == GL_FALSE)\r
- {\r
- char info[2048];\r
- GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info));\r
- GL(glDeleteObjectARB(vertex_shader));\r
- std::stringstream str;\r
- str << "Failed to compile vertex shader:" << std::endl << info << std::endl;\r
- BOOST_THROW_EXCEPTION(gl::gl_error() << msg_info(str.str()));\r
- }\r
- \r
- const char* fragment_source = fragment_source_str.c_str();\r
- \r
- auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
- \r
- GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\r
- GL(glCompileShaderARB(fragmemt_shader));\r
-\r
- GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
- if (success == GL_FALSE)\r
- {\r
- char info[2048];\r
- GL(glGetInfoLogARB(fragmemt_shader, sizeof(info), 0, info));\r
- GL(glDeleteObjectARB(fragmemt_shader));\r
- std::stringstream str;\r
- str << "Failed to compile fragment shader:" << std::endl << info << std::endl;\r
- BOOST_THROW_EXCEPTION(gl::gl_error() << msg_info(str.str()));\r
- }\r
- \r
- program_ = glCreateProgramObjectARB();\r
- \r
- GL(glAttachObjectARB(program_, vertex_shader));\r
- GL(glAttachObjectARB(program_, fragmemt_shader));\r
-\r
- GL(glLinkProgramARB(program_));\r
- \r
- GL(glDeleteObjectARB(vertex_shader));\r
- GL(glDeleteObjectARB(fragmemt_shader));\r
-\r
- GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
- if (success == GL_FALSE)\r
- {\r
- char info[2048];\r
- GL(glGetInfoLogARB(program_, sizeof(info), 0, info));\r
- GL(glDeleteObjectARB(program_));\r
- std::stringstream str;\r
- str << "Failed to link shader program:" << std::endl << info << std::endl;\r
- BOOST_THROW_EXCEPTION(gl::gl_error() << msg_info(str.str()));\r
- }\r
- GL(glUseProgramObjectARB(program_));\r
- glUniform1i(glGetUniformLocation(program_, "plane[0]"), 0);\r
- glUniform1i(glGetUniformLocation(program_, "plane[1]"), 1);\r
- glUniform1i(glGetUniformLocation(program_, "plane[2]"), 2);\r
- glUniform1i(glGetUniformLocation(program_, "plane[3]"), 3);\r
- }\r
-\r
- shader_program& operator=(shader_program&& other) \r
- {\r
- program_ = other.program_; \r
- other.program_ = 0; \r
- return *this;\r
- }\r
-\r
- ~shader_program()\r
- {\r
- glDeleteProgram(program_);\r
- }\r
-\r
- void use()\r
- { \r
- GL(glUseProgramObjectARB(program_)); \r
- }\r
-};\r
-\r
-GLubyte progressive_pattern[] = {\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
- \r
-GLubyte upper_pattern[] = {\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
- \r
-GLubyte lower_pattern[] = {\r
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \r
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
-\r
-struct image_kernel::implementation\r
-{ \r
- std::unordered_map<pixel_format::type, shader_program> shaders_;\r
-\r
-public:\r
- std::unordered_map<pixel_format::type, shader_program>& shaders()\r
- {\r
- GL(glEnable(GL_POLYGON_STIPPLE));\r
- GL(glEnable(GL_BLEND));\r
- GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); \r
-\r
- if(shaders_.empty())\r
- {\r
- std::string common_vertex = \r
- "void main() "\r
- "{ "\r
- " gl_TexCoord[0] = gl_MultiTexCoord0; "\r
- " gl_FrontColor = gl_Color; "\r
- " gl_Position = ftransform(); "\r
- "} ";\r
-\r
- std::string common_fragment = \r
- "uniform sampler2D plane[4]; "\r
- "uniform vec4 plane_size[2]; "\r
- \r
- // NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf \r
- // TODO: Support for more yuv formats might be needed. \r
- "vec4 ycbcra_to_bgra(float y, float cb, float cr, float a) "\r
- "{ "\r
- " cb -= 0.5; "\r
- " cr -= 0.5; "\r
- " y = 1.164*(y-0.0625); "\r
- " "\r
- " vec4 color; "\r
- " color.r = y + 1.596 * cr; "\r
- " color.g = y - 0.813 * cr - 0.337633 * cb; "\r
- " color.b = y + 2.017 * cb; "\r
- " color.a = a; "\r
- " "\r
- " return color; "\r
- "} " \r
- " ";\r
- \r
- shaders_[pixel_format::abgr] = shader_program(common_vertex, common_fragment +\r
-\r
- "void main() "\r
- "{ "\r
- " vec4 abgr = texture2D(plane[0], gl_TexCoord[0].st);"\r
- " gl_FragColor = abgr.argb * gl_Color; "\r
- "} ");\r
- \r
- shaders_[pixel_format::argb]= shader_program(common_vertex, common_fragment +\r
-\r
- "void main() " \r
- "{ "\r
- " vec4 argb = texture2D(plane[0], gl_TexCoord[0].st);"\r
- " gl_FragColor = argb.grab * gl_Color; " \r
- "} ");\r
- \r
- shaders_[pixel_format::bgra]= shader_program(common_vertex, common_fragment +\r
-\r
- "void main() "\r
- "{ "\r
- " vec4 bgra = texture2D(plane[0], gl_TexCoord[0].st);"\r
- " gl_FragColor = bgra.rgba * gl_Color; "\r
- "} ");\r
- \r
- shaders_[pixel_format::rgba] = shader_program(common_vertex, common_fragment +\r
-\r
- "void main() "\r
- "{ "\r
- " vec4 rgba = texture2D(plane[0], gl_TexCoord[0].st); "\r
- " gl_FragColor = rgba.bgra * gl_Color; "\r
- "} ");\r
- \r
- shaders_[pixel_format::ycbcr] = shader_program(common_vertex, common_fragment +\r
-\r
- "void main() "\r
- "{ "\r
- " float y = texture2D(plane[0], gl_TexCoord[0].st).r;"\r
- " float cb = texture2D(plane[1], gl_TexCoord[0].st).r;"\r
- " float cr = texture2D(plane[2], gl_TexCoord[0].st).r;"\r
- " float a = 1.0; " \r
- " gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
- "} ");\r
- \r
- shaders_[pixel_format::ycbcra] = shader_program(common_vertex, common_fragment +\r
-\r
- "void main() "\r
- "{ "\r
- " float y = texture2D(plane[0], gl_TexCoord[0].st).r;"\r
- " float cb = texture2D(plane[1], gl_TexCoord[0].st).r;"\r
- " float cr = texture2D(plane[2], gl_TexCoord[0].st).r;"\r
- " float a = texture2D(plane[3], gl_TexCoord[0].st).r;"\r
- " gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
- "} ");\r
- }\r
- return shaders_;\r
- }\r
-};\r
-\r
-image_kernel::image_kernel() : impl_(new implementation()){}\r
-\r
-void image_kernel::use(pixel_format::type pix_fmt, video_mode::type mode)\r
-{\r
- impl_->shaders()[pix_fmt].use();\r
-\r
- if(mode == video_mode::upper)\r
- glPolygonStipple(upper_pattern);\r
- else if(mode == video_mode::lower)\r
- glPolygonStipple(lower_pattern);\r
- else\r
- glPolygonStipple(progressive_pattern);\r
-}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "../video_format.h"\r
-\r
-#include "frame_processor_device.h"\r
-\r
-#include <memory>\r
-\r
-namespace caspar { namespace core {\r
- \r
-class image_kernel\r
-{\r
-public:\r
- image_kernel();\r
- void use(pixel_format::type pix_fmt, video_mode::type mode);\r
-\r
-private:\r
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "image_processor.h"\r
-#include "image_kernel.h"\r
-\r
-#include "ogl_device.h"\r
-#include "host_buffer.h"\r
-#include "device_buffer.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-#include <common/gl/gl_check.h>\r
-#include <common/concurrency/executor.h>\r
-\r
-#include <Glee.h>\r
-#include <SFML/Window/Context.hpp>\r
-#include <unordered_map>\r
-\r
-namespace caspar { namespace core {\r
- \r
-image_transform& image_transform::operator*=(const image_transform &other)\r
-{\r
- alpha *= other.alpha;\r
- mode = other.mode;\r
- uv.get<0>() += other.uv.get<0>();\r
- uv.get<1>() += other.uv.get<1>();\r
- uv.get<2>() += other.uv.get<2>();\r
- uv.get<3>() += other.uv.get<3>();\r
- pos.get<0>() += other.pos.get<0>();\r
- pos.get<1>() += other.pos.get<1>();\r
- return *this;\r
-}\r
-\r
-const image_transform image_transform::operator*(const image_transform &other) const\r
-{\r
- return image_transform(*this) *= other;\r
-}\r
-\r
-struct image_processor::implementation : boost::noncopyable\r
-{ \r
- ogl_device context_;\r
-\r
- const video_format_desc format_desc_;\r
- \r
- std::stack<image_transform> transform_stack_;\r
-\r
- GLuint fbo_;\r
- std::array<std::shared_ptr<device_buffer>, 2> render_targets_;\r
-\r
- std::shared_ptr<host_buffer> reading_;\r
-\r
- image_kernel kernel_;\r
-\r
-public:\r
- implementation(const video_format_desc& format_desc) : format_desc_(format_desc)\r
- {\r
- context_.begin_invoke([=]\r
- {\r
- transform_stack_.push(image_transform());\r
- transform_stack_.top().mode = video_mode::progressive;\r
- transform_stack_.top().uv = boost::make_tuple(0.0, 1.0, 1.0, 0.0);\r
-\r
- GL(glEnable(GL_TEXTURE_2D));\r
- GL(glDisable(GL_DEPTH_TEST)); \r
-\r
- render_targets_[0] = context_.create_device_buffer(format_desc.width, format_desc.height, 4);\r
- render_targets_[1] = context_.create_device_buffer(format_desc.width, format_desc.height, 4);\r
- \r
- GL(glGenFramebuffers(1, &fbo_)); \r
- GL(glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_));\r
- GL(glReadBuffer(GL_COLOR_ATTACHMENT0_EXT));\r
-\r
- reading_ = context_.create_host_buffer(format_desc_.size, host_buffer::read_only);\r
- });\r
- }\r
-\r
- ~implementation()\r
- {\r
- glDeleteFramebuffersEXT(1, &fbo_);\r
- }\r
-\r
- void begin(const image_transform& transform)\r
- {\r
- transform_stack_.push(transform_stack_.top()*transform);\r
- }\r
- \r
- void render(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>>& buffers)\r
- {\r
- auto transform = transform_stack_.top();\r
- context_.begin_invoke([=]\r
- {\r
- GL(glLoadIdentity());\r
- GL(glTranslated(transform.pos.get<0>()*2.0, transform.pos.get<1>()*2.0, 0.0));\r
- GL(glColor4d(1.0, 1.0, 1.0, transform.alpha));\r
- GL(glViewport(0, 0, format_desc_.width, format_desc_.height));\r
- kernel_.use(desc.pix_fmt, transform.mode);\r
-\r
- std::vector<safe_ptr<device_buffer>> device_buffers;\r
- for(size_t n = 0; n < buffers.size(); ++n)\r
- {\r
- auto texture = context_.create_device_buffer(desc.planes[n].width, desc.planes[n].height, desc.planes[n].channels);\r
- texture->read(*buffers[n]);\r
- device_buffers.push_back(texture);\r
- }\r
-\r
- for(size_t n = 0; n < buffers.size(); ++n)\r
- {\r
- glActiveTexture(GL_TEXTURE0+n);\r
- device_buffers[n]->bind();\r
- }\r
-\r
- auto t = transform;\r
- glBegin(GL_QUADS);\r
- glTexCoord2d(t.uv.get<0>(), t.uv.get<3>()); glVertex2d(-1.0, -1.0);\r
- glTexCoord2d(t.uv.get<2>(), t.uv.get<3>()); glVertex2d( 1.0, -1.0);\r
- glTexCoord2d(t.uv.get<2>(), t.uv.get<1>()); glVertex2d( 1.0, 1.0);\r
- glTexCoord2d(t.uv.get<0>(), t.uv.get<1>()); glVertex2d(-1.0, 1.0);\r
- glEnd();\r
- });\r
- }\r
-\r
- void end()\r
- {\r
- transform_stack_.pop();\r
- }\r
-\r
- boost::unique_future<safe_ptr<const host_buffer>> begin_pass()\r
- {\r
- return context_.begin_invoke([=]() -> safe_ptr<const host_buffer>\r
- {\r
- reading_->map();\r
- render_targets_[0]->attach(0);\r
- GL(glClear(GL_COLOR_BUFFER_BIT));\r
- return safe_ptr<const host_buffer>(reading_);\r
- });\r
- }\r
-\r
- void end_pass()\r
- {\r
- context_.begin_invoke([=]\r
- {\r
- reading_ = context_.create_host_buffer(format_desc_.size, host_buffer::read_only);\r
- render_targets_[0]->write(*reading_);\r
- std::rotate(render_targets_.begin(), render_targets_.begin() + 1, render_targets_.end());\r
- });\r
- }\r
- \r
- std::vector<safe_ptr<host_buffer>> create_buffers(const pixel_format_desc& format)\r
- {\r
- std::vector<safe_ptr<host_buffer>> buffers;\r
- std::transform(format.planes.begin(), format.planes.end(), std::back_inserter(buffers), [&](const pixel_format_desc::plane& plane) -> safe_ptr<host_buffer>\r
- {\r
- return context_.create_host_buffer(plane.size, host_buffer::write_only);\r
- });\r
- return buffers;\r
- }\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<host_buffer>>& buffers){ impl_->render(desc, buffers);}\r
-void image_processor::end(){impl_->end();}\r
-boost::unique_future<safe_ptr<const host_buffer>> image_processor::begin_pass(){ return impl_->begin_pass();}\r
-void image_processor::end_pass(){impl_->end_pass();}\r
-std::vector<safe_ptr<host_buffer>> image_processor::create_buffers(const pixel_format_desc& format){return impl_->create_buffers(format);}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "host_buffer.h"\r
-\r
-#include "../video_format.h"\r
-\r
-#include <boost/tuple/tuple.hpp>\r
-#include <boost/thread/future.hpp>\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <memory>\r
-#include <array>\r
-\r
-namespace caspar { namespace core {\r
-\r
-struct pixel_format_desc;\r
- \r
-struct image_transform \r
-{\r
- image_transform() : alpha(1.0), pos(boost::make_tuple(0.0, 0.0)), uv(boost::make_tuple(0.0, 0.0, 0.0, 0.0)), mode(video_mode::invalid){}\r
- double alpha;\r
- boost::tuple<double, double> pos;\r
- boost::tuple<double, double, double, double> uv;\r
- video_mode::type mode; \r
-\r
- image_transform& operator*=(const image_transform &other);\r
- const image_transform operator*(const image_transform &other) const;\r
-};\r
-\r
-class image_processor : boost::noncopyable\r
-{\r
-public:\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<safe_ptr<host_buffer>>& buffers);\r
- void end();\r
-\r
- boost::unique_future<safe_ptr<const host_buffer>> begin_pass();\r
- void end_pass();\r
-\r
- std::vector<safe_ptr<host_buffer>> create_buffers(const pixel_format_desc& format);\r
-\r
-private:\r
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../stdafx.h"\r
-\r
-#include "ogl_device.h"\r
-\r
-#include <Glee.h>\r
-#include <SFML/Window.hpp>\r
-\r
-namespace caspar { namespace core {\r
-\r
-ogl_device::ogl_device()\r
-{\r
- executor_.start();\r
- invoke([=]\r
- {\r
- context_.reset(new sf::Context());\r
- context_->SetActive(true);\r
- });\r
-}\r
- \r
-safe_ptr<device_buffer> ogl_device::create_device_buffer(size_t width, size_t height, size_t stride)\r
-{\r
- auto pool = &device_pools_[stride][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
- std::shared_ptr<device_buffer> buffer;\r
- if(!pool->try_pop(buffer)) \r
- {\r
- executor_.invoke([&]\r
- {\r
- buffer = std::make_shared<device_buffer>(width, height, stride);\r
- }); \r
- }\r
- \r
- return safe_ptr<device_buffer>(buffer.get(), [=](device_buffer*){pool->push(buffer);});\r
-}\r
- \r
-safe_ptr<host_buffer> ogl_device::create_host_buffer(size_t size, host_buffer::usage_t usage)\r
-{\r
- auto pool = &host_pools_[usage][size];\r
- std::shared_ptr<host_buffer> buffer;\r
- if(!pool->try_pop(buffer))\r
- {\r
- executor_.invoke([&]\r
- {\r
- buffer = std::make_shared<host_buffer>(size, usage);\r
- if(usage == host_buffer::write_only)\r
- buffer->map();\r
- else\r
- buffer->unmap();\r
- }); \r
- }\r
-\r
- return safe_ptr<host_buffer>(buffer.get(), [=](host_buffer*)\r
- {\r
- executor_.begin_invoke([=]\r
- {\r
- if(usage == host_buffer::write_only)\r
- buffer->map();\r
- else\r
- buffer->unmap();\r
- pool->push(buffer);\r
- });\r
- });\r
-}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include "host_buffer.h"\r
-#include "device_buffer.h"\r
-\r
-#include <common/concurrency/executor.h>\r
-#include <common/memory/safe_ptr.h>\r
-\r
-#include <tbb/concurrent_unordered_map.h>\r
-#include <tbb/concurrent_queue.h>\r
-\r
-#include <boost/thread/future.hpp>\r
-\r
-#include <array>\r
-\r
-namespace caspar { namespace core {\r
-\r
-class ogl_device\r
-{ \r
-public:\r
- \r
- ogl_device();\r
-\r
- template<typename Func>\r
- auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
- { \r
- return executor_.begin_invoke(std::forward<Func>(func));\r
- }\r
- \r
- template<typename Func>\r
- auto invoke(Func&& func) -> decltype(func())\r
- {\r
- return executor_.invoke(std::forward<Func>(func));\r
- }\r
- \r
- safe_ptr<device_buffer> create_device_buffer(size_t width, size_t height, size_t stride);\r
- safe_ptr<host_buffer> create_host_buffer(size_t size, host_buffer::usage_t usage);\r
-\r
-private:\r
- executor executor_;\r
- std::unique_ptr<sf::Context> context_;\r
- \r
- std::array<tbb::concurrent_unordered_map<size_t, tbb::concurrent_bounded_queue<std::shared_ptr<device_buffer>>>, 4> device_pools_;\r
- std::array<tbb::concurrent_unordered_map<size_t, tbb::concurrent_bounded_queue<std::shared_ptr<host_buffer>>>, 2> host_pools_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include <vector>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct pixel_format\r
-{\r
- enum type\r
- {\r
- bgra,\r
- rgba,\r
- argb,\r
- abgr,\r
- ycbcr,\r
- ycbcra,\r
- count,\r
- invalid\r
- };\r
-};\r
-\r
-struct pixel_format_desc\r
-{\r
- struct plane\r
- {\r
- size_t linesize;\r
- size_t width;\r
- size_t height;\r
- size_t size;\r
- size_t channels;\r
-\r
- plane() \r
- : linesize(0)\r
- , width(0)\r
- , height(0)\r
- , size(0)\r
- , channels(0){}\r
-\r
- plane(size_t width, size_t height, size_t channels)\r
- : linesize(width*channels)\r
- , width(width)\r
- , height(height)\r
- , size(width*height*channels)\r
- , channels(channels){}\r
- };\r
-\r
- pixel_format_desc() : pix_fmt(pixel_format::invalid){}\r
- \r
- pixel_format::type pix_fmt;\r
- std::vector<plane> planes;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "read_frame.h"\r
-\r
-#include "host_buffer.h"\r
-\r
-#include <common/gl/gl_check.h>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct read_frame::implementation : boost::noncopyable\r
-{\r
- safe_ptr<const host_buffer> image_data_;\r
- std::vector<short> audio_data_;\r
-\r
-public:\r
- implementation(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data) \r
- : image_data_(std::move(image_data))\r
- , audio_data_(std::move(audio_data)){} \r
-};\r
-\r
-read_frame::read_frame(){}\r
-read_frame::read_frame(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data) : impl_(new implementation(std::move(image_data), std::move(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
+++ /dev/null
-#pragma once\r
-\r
-#include "host_buffer.h" \r
-\r
-#include <boost/noncopyable.hpp>\r
-#include <boost/range/iterator_range.hpp>\r
-\r
-#include <memory>\r
-#include <vector>\r
-\r
-#include "../../common/memory/safe_ptr.h"\r
-\r
-namespace caspar { namespace core {\r
- \r
-class read_frame\r
-{\r
-public:\r
- read_frame();\r
- read_frame(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data);\r
-\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
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "write_frame.h"\r
-\r
-#include "host_buffer.h"\r
-\r
-#include "draw_frame.h"\r
-#include "image_processor.h"\r
-#include "audio_processor.h"\r
-#include "pixel_format.h"\r
-\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct write_frame::implementation : boost::noncopyable\r
-{ \r
- write_frame& self_;\r
- std::vector<safe_ptr<host_buffer>> buffers_;\r
- std::vector<short> audio_data_;\r
- const pixel_format_desc desc_;\r
-\r
-public:\r
- implementation(write_frame& self, const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers) \r
- : self_(self)\r
- , desc_(desc)\r
- , buffers_(buffers){}\r
- \r
- void process_image(image_processor& processor)\r
- {\r
- processor.begin(self_.get_image_transform());\r
- processor.process(desc_, buffers_);\r
- processor.end();\r
- }\r
-\r
- void process_audio(audio_processor& processor)\r
- {\r
- processor.begin(self_.get_audio_transform());\r
- processor.process(audio_data_);\r
- processor.end();\r
- }\r
-\r
- boost::iterator_range<unsigned char*> image_data(size_t index)\r
- {\r
- if(index >= buffers_.size() || !buffers_[index]->data())\r
- return boost::iterator_range<const unsigned char*>();\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*> image_data(size_t index) const\r
- {\r
- if(index >= buffers_.size() || !buffers_[index]->data())\r
- return boost::iterator_range<const unsigned char*>();\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
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable : 4355) // 'this' : used in base member initializer list\r
-#endif\r
- \r
-write_frame::write_frame(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers) : impl_(new implementation(*this, 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
-{\r
- write_frame temp(std::move(other));\r
- temp.swap(*this);\r
- return *this;\r
-}\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::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
+++ /dev/null
-#pragma once\r
-\r
-#include "fwd.h"\r
-\r
-#include "host_buffer.h"\r
-\r
-#include "draw_frame.h"\r
-\r
-#include "../video_format.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
-struct pixel_format_desc;\r
-\r
-class write_frame : public draw_frame, boost::noncopyable\r
-{\r
-public: \r
- explicit write_frame(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers);\r
- write_frame(write_frame&& other);\r
- write_frame& operator=(write_frame&& other);\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
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-typedef std::shared_ptr<write_frame> write_frame_impl_ptr;\r
-\r
-\r
-}}
\ No newline at end of file
\r
#include "color_producer.h"\r
\r
-#include "../../processor/draw_frame.h"\r
+#include "../../mixer/frame/draw_frame.h"\r
\r
#include <sstream>\r
\r
\r
virtual safe_ptr<draw_frame> receive() { return frame_; }\r
\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- auto frame = frame_processor->create_frame(1, 1, pixel_format::bgra);\r
+ auto frame = frame_mixer->create_frame(1, 1, pixel_format::bgra);\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
\r
#include "decklink_producer.h"\r
\r
-#include "../../processor/draw_frame.h"\r
+#include "../../mixer/frame/draw_frame.h"\r
#include "../../consumer/decklink/DeckLinkAPI_h.h" // TODO: Change this\r
#include "../../consumer/decklink/util.h" // TODO: Change this\r
\r
CComPtr<IDeckLink> decklink_;\r
CComQIPtr<IDeckLinkInput> input_;\r
\r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
\r
tbb::concurrent_bounded_queue<safe_ptr<draw_frame>> frame_buffer_;\r
safe_ptr<draw_frame> head_;\r
\r
public:\r
\r
- decklink_input(size_t device_index, const video_format_desc& format_desc, const std::shared_ptr<frame_processor_device>& frame_processor)\r
+ decklink_input(size_t device_index, const video_format_desc& format_desc, const std::shared_ptr<frame_mixer_device>& frame_mixer)\r
: device_index_(device_index)\r
, format_desc_(format_desc)\r
- , frame_processor_(frame_processor)\r
+ , frame_mixer_(frame_mixer)\r
, head_(draw_frame::empty())\r
, tail_(draw_frame::empty())\r
{\r
return S_OK;\r
}\r
\r
+ // TODO: Enable audio input\r
virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* video, IDeckLinkAudioInputPacket* /*audio*/)\r
{ \r
if(!frame_buffer_.try_push(head_) || video == nullptr)\r
desc.planes.push_back(pixel_format_desc::plane(format_desc_.width, format_desc_.height, 1));\r
desc.planes.push_back(pixel_format_desc::plane(format_desc_.width/2, format_desc_.height, 1));\r
desc.planes.push_back(pixel_format_desc::plane(format_desc_.width/2, format_desc_.height, 1)); \r
- auto frame = frame_processor_->create_frame(desc);\r
+ auto frame = frame_mixer_->create_frame(desc);\r
\r
unsigned char* data = reinterpret_cast<unsigned char*>(bytes);\r
int frame_size = (format_desc_.width * 16 / 8) * format_desc_.height;\r
return input_->get_frame();\r
}\r
\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
executor_.start();\r
executor_.invoke([=]\r
{\r
- input_.reset(new decklink_input(device_index_, format_desc_, frame_processor));\r
+ input_.reset(new decklink_input(device_index_, format_desc_, frame_mixer));\r
});\r
}\r
\r
#include "video/video_decoder.h"\r
\r
#include "../../video_format.h"\r
-#include "../../processor/draw_frame.h"\r
+#include "../../mixer/frame/draw_frame.h"\r
+#include "../../mixer/audio/audio_mixer.h"\r
\r
#include <common/env.h>\r
\r
, video_decoder_(input_.get_video_codec_context().get()) \r
, audio_decoder_(input_.get_audio_codec_context().get() ? new audio_decoder(input_.get_audio_codec_context().get(), input_.fps()) : nullptr){}\r
\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- format_desc_ = frame_processor->get_video_format_desc();\r
- video_decoder_.initialize(frame_processor);\r
+ format_desc_ = frame_mixer->get_video_format_desc();\r
+ video_decoder_.initialize(frame_mixer);\r
}\r
\r
virtual safe_ptr<draw_frame> receive()\r
{\r
result = std::move(ouput_channel_.front());\r
last_frame_ = draw_frame(result);\r
- last_frame_->audio_volume(0.0); // last_frame should not have audio\r
+ last_frame_->get_audio_transform().gain = 0.0; // last_frame should not have audio\r
ouput_channel_.pop();\r
}\r
else if(input_.is_eof())\r
#include "video_decoder.h"\r
\r
#include "../../../video_format.h"\r
-#include "../../../processor/draw_frame.h"\r
-#include "../../../processor/frame_processor_device.h"\r
+#include "../../../mixer/frame/draw_frame.h"\r
+#include "../../../mixer/frame_mixer_device.h"\r
+#include "../../../mixer/image/image_mixer.h"\r
\r
#include <common/memory/safe_ptr.h>\r
\r
\r
struct video_decoder::implementation : boost::noncopyable\r
{ \r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
std::shared_ptr<SwsContext> sws_context_;\r
\r
AVCodecContext* codec_context_;\r
\r
if(sws_context_ == nullptr)\r
{\r
- auto write = frame_processor_->create_frame(desc_);\r
+ auto write = frame_mixer_->create_frame(desc_);\r
\r
tbb::parallel_for(0, static_cast<int>(desc_.planes.size()), 1, [&](int n)\r
{\r
});\r
});\r
\r
- if(codec_context_->codec_id == CODEC_ID_DVVIDEO) // Move up one field frame_processor_->get_video_format_desc().mode == video_mode::upper && \r
- write->translate(0.0f, 1.0/static_cast<double>(height_));\r
+ if(codec_context_->codec_id == CODEC_ID_DVVIDEO) // Move up one field frame_mixer_->get_video_format_desc().mode == video_mode::upper && \r
+ write->get_image_transform().pos = boost::make_tuple(0.0f, 1.0/static_cast<double>(height_));\r
\r
return write;\r
}\r
else\r
{\r
- auto write = frame_processor_->create_frame(width_, height_);\r
+ auto write = frame_mixer_->create_frame(width_, height_);\r
\r
AVFrame av_frame; \r
avcodec_get_frame_defaults(&av_frame);\r
} \r
}\r
\r
- void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- frame_processor_ = frame_processor; \r
+ frame_mixer_ = frame_mixer; \r
double frame_rate = static_cast<double>(codec_context_->time_base.den) / static_cast<double>(codec_context_->time_base.num);\r
- if(abs(frame_rate - frame_processor->get_video_format_desc().fps) > std::numeric_limits<double>::min())\r
+ if(abs(frame_rate - frame_mixer->get_video_format_desc().fps) > std::numeric_limits<double>::min())\r
BOOST_THROW_EXCEPTION(file_read_error() << msg_info("Invalid video framerate."));\r
}\r
};\r
\r
video_decoder::video_decoder(AVCodecContext* codec_context) : impl_(new implementation(codec_context)){}\r
safe_ptr<write_frame> video_decoder::execute(const aligned_buffer& video_packet){return impl_->execute(video_packet);}\r
-void video_decoder::initialize(const safe_ptr<frame_processor_device>& frame_processor){impl_->initialize(frame_processor); }\r
+void video_decoder::initialize(const safe_ptr<frame_mixer_device>& frame_mixer){impl_->initialize(frame_mixer); }\r
}}}
\ No newline at end of file
#pragma once\r
\r
-#include "../../../processor/frame_processor_device.h"\r
+#include "../../../mixer/frame_mixer_device.h"\r
\r
#include <memory>\r
\r
public:\r
explicit video_decoder(AVCodecContext* codec_context);\r
safe_ptr<write_frame> execute(const aligned_buffer& video_packet); \r
- void initialize(const safe_ptr<frame_processor_device>& frame_processor);\r
+ void initialize(const safe_ptr<frame_mixer_device>& frame_mixer);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
return flash_producer_->receive();\r
}\r
\r
- void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- frame_processor_ = frame_processor;\r
- flash_producer_->initialize(frame_processor);\r
+ frame_mixer_ = frame_mixer;\r
+ flash_producer_->initialize(frame_mixer);\r
}\r
\r
std::wstring print() const\r
}\r
\r
safe_ptr<flash_producer> flash_producer_;\r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
};\r
\r
safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<channel>& channel, int render_layer)\r
void cg_producer::next(int layer){impl_->next(layer);}\r
void cg_producer::update(int layer, const std::wstring& data){impl_->update(layer, data);}\r
void cg_producer::invoke(int layer, const std::wstring& label){impl_->invoke(layer, label);}\r
-void cg_producer::initialize(const safe_ptr<frame_processor_device>& frame_processor){impl_->initialize(frame_processor);}\r
+void cg_producer::initialize(const safe_ptr<frame_mixer_device>& frame_mixer){impl_->initialize(frame_mixer);}\r
std::wstring cg_producer::print() const{return impl_->print();}\r
}}}
\ No newline at end of file
cg_producer(cg_producer&& other);\r
\r
virtual safe_ptr<draw_frame> receive();\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor);\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer);\r
\r
void clear();\r
void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& start_from_label = TEXT(""), const std::wstring& data = TEXT(""));\r
\r
#include "../../video_format.h"\r
\r
-#include "../../processor/draw_frame.h"\r
-#include "../../processor/frame_processor_device.h"\r
+#include "../../mixer/frame/draw_frame.h"\r
+#include "../../mixer/frame_mixer_device.h"\r
\r
#include <common/concurrency/executor.h>\r
#include <common/utility/timer.h>\r
const std::wstring filename_;\r
const video_format_desc format_desc_;\r
\r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
\r
BYTE* bmp_data_; \r
std::shared_ptr<void> hdc_;\r
safe_ptr<draw_frame> head_;\r
\r
public:\r
- flash_renderer(const std::shared_ptr<frame_processor_device>& frame_processor, const std::wstring& filename) \r
+ flash_renderer(const std::shared_ptr<frame_mixer_device>& frame_mixer, const std::wstring& filename) \r
: filename_(filename)\r
- , format_desc_(frame_processor->get_video_format_desc())\r
- , frame_processor_(frame_processor)\r
+ , format_desc_(frame_mixer->get_video_format_desc())\r
+ , frame_mixer_(frame_mixer)\r
, bmp_data_(nullptr)\r
, hdc_(CreateCompatibleDC(0), DeleteDC)\r
, ax_(nullptr)\r
std::fill_n(bmp_data_, format_desc_.size, 0);\r
ax_->DrawControl(static_cast<HDC>(hdc_.get()));\r
\r
- auto frame = frame_processor_->create_frame();\r
+ auto frame = frame_mixer_->create_frame();\r
std::copy_n(bmp_data_, format_desc_.size, frame->image_data().begin());\r
head_ = frame;\r
} \r
executor executor_;\r
\r
std::shared_ptr<flash_renderer> renderer_;\r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
\r
std::wstring print() const{ return L"flash[" + boost::filesystem::wpath(filename_).filename() + L"]"; } \r
std::wstring filename_;\r
return tail_;\r
}\r
\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- frame_processor_ = frame_processor;\r
- frame_buffer_.set_capacity(static_cast<size_t>(frame_processor->get_video_format_desc().fps/2.0));\r
+ frame_mixer_ = frame_mixer;\r
+ frame_buffer_.set_capacity(static_cast<size_t>(frame_mixer->get_video_format_desc().fps/2.0));\r
while(frame_buffer_.try_push(draw_frame::empty())){}\r
executor_.start();\r
}\r
executor_.begin_invoke([=]\r
{\r
if(!renderer_)\r
- renderer_.reset(new flash_renderer(frame_processor_, filename_));\r
+ renderer_.reset(new flash_renderer(frame_mixer_, filename_));\r
\r
try\r
{\r
flash_producer::flash_producer(const std::wstring& filename) : impl_(new implementation(filename)){}\r
safe_ptr<draw_frame> flash_producer::receive(){return impl_->receive();}\r
void flash_producer::param(const std::wstring& param){impl_->param(param);}\r
-void flash_producer::initialize(const safe_ptr<frame_processor_device>& frame_processor) { impl_->initialize(frame_processor);}\r
+void flash_producer::initialize(const safe_ptr<frame_mixer_device>& frame_mixer) { impl_->initialize(frame_mixer);}\r
std::wstring flash_producer::print() const {return impl_->print();}\r
\r
std::wstring flash_producer::find_template(const std::wstring& template_name)\r
flash_producer(flash_producer&& other);\r
\r
virtual safe_ptr<draw_frame> receive();\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor);\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer);\r
virtual std::wstring print() const;\r
\r
void param(const std::wstring& param);\r
*/\r
#pragma once\r
\r
-#include "../processor/draw_frame.h"\r
-#include "../processor/frame_processor_device.h"\r
+#include "../mixer/frame/draw_frame.h"\r
+#include "../mixer/frame_mixer_device.h"\r
\r
#include <common/memory/safe_ptr.h>\r
\r
virtual void set_leading_producer(const safe_ptr<frame_producer>& /*producer*/) {} // nothrow\r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
- /// \fn virtual void :::initialize(const safe_ptr<frame_processor_device>& frame_processor) = 0;\r
+ /// \fn virtual void :::initialize(const safe_ptr<frame_mixer_device>& frame_mixer) = 0;\r
///\r
- /// \brief Provides the frame frame_processor used to create frames and initializes the producer. \r
+ /// \brief Provides the frame frame_mixer used to create frames and initializes the producer. \r
///\r
- /// \param frame_processor The frame frame_processor. \r
+ /// \param frame_mixer The frame frame_mixer. \r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor) = 0;\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer) = 0;\r
\r
static safe_ptr<frame_producer> empty() // nothrow\r
{\r
struct empty_frame_producer : public frame_producer\r
{\r
virtual safe_ptr<draw_frame> receive(){return draw_frame::empty();}\r
- virtual void initialize(const safe_ptr<frame_processor_device>&){}\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>&){}\r
virtual std::wstring print() const { return L"empty";}\r
};\r
static safe_ptr<frame_producer> producer = make_safe<empty_frame_producer>();\r
#include "image_producer.h"\r
#include "image_loader.h"\r
\r
-#include "../../processor/frame_processor_device.h"\r
-#include "../../processor/draw_frame.h"\r
+#include "../../mixer/frame_mixer_device.h"\r
+#include "../../mixer/frame/draw_frame.h"\r
#include "../../video_format.h"\r
\r
#include <common/env.h>\r
\r
struct image_producer : public frame_producer\r
{ \r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
std::wstring filename_;\r
safe_ptr<draw_frame> frame_;\r
\r
image_producer(image_producer&& other) \r
- : frame_processor_(std::move(other.frame_processor_))\r
+ : frame_mixer_(std::move(other.frame_mixer_))\r
, filename_(std::move(other.filename_))\r
, frame_(draw_frame::empty()){}\r
\r
\r
virtual safe_ptr<draw_frame> receive(){return frame_;}\r
\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- frame_processor_ = frame_processor;\r
+ frame_mixer_ = frame_mixer;\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
+ auto frame = frame_mixer->create_frame(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()));\r
std::copy_n(FreeImage_GetBits(bitmap.get()), frame->image_data().size(), frame->image_data().begin());\r
frame_ = std::move(frame);\r
}\r
//\r
//#include "image_loader.h"\r
//\r
-//#include "../../processor/draw_frame.h"\r
-//#include "../../processor/draw_frame.h"\r
+//#include "../../mixer/draw_frame.h"\r
+//#include "../../mixer/draw_frame.h"\r
//#include "../../video_format.h"\r
-//#include "../../processor/frame_processor_device.h"\r
+//#include "../../mixer/frame_mixer_device.h"\r
//#include "../../configuration.h"\r
//\r
//#include <tbb/parallel_for.h>\r
//\r
// draw_frame do_receive()\r
// {\r
-// auto frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height);\r
+// auto frame = frame_mixer_->create_frame(format_desc_.width, format_desc_.height);\r
// std::fill(frame.image_data().begin(), frame.image_data().end(), 0);\r
//\r
// const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
// return receive(); \r
// }\r
// \r
-// void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
+// void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
// {\r
-// frame_processor_ = frame_processor;\r
-// format_desc_ = frame_processor_->get_video_format_desc();\r
+// frame_mixer_ = frame_mixer;\r
+// format_desc_ = frame_mixer_->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
//\r
// std::wstring filename_;\r
//\r
-// safe_ptr<frame_processor_device> frame_processor_;\r
+// safe_ptr<frame_mixer_device> frame_mixer_;\r
//};\r
//\r
//safe_ptr<frame_producer> create_image_scroll_producer(const std::vector<std::wstring>& params)\r
\r
#include "layer.h"\r
\r
-#include "../processor/draw_frame.h"\r
+#include "../mixer/frame/draw_frame.h"\r
+#include "../mixer/image/image_mixer.h"\r
+#include "../mixer/audio/audio_mixer.h"\r
#include "../producer/frame_producer.h"\r
\r
#include "../video_format.h"\r
const int index_;\r
bool is_paused_;\r
\r
+ double video_gain_;\r
+ double video_opacity_;\r
+ \r
+ double audio_gain_;\r
+\r
public:\r
implementation(int index) \r
: foreground_(frame_producer::empty())\r
, background_(frame_producer::empty())\r
, last_frame_(draw_frame::empty())\r
, index_(index) \r
- , is_paused_(false){}\r
+ , is_paused_(false)\r
+ , video_gain_(1.0)\r
+ , video_opacity_(1.0)\r
+ , audio_gain_(1.0){}\r
\r
void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
{ \r
\r
last_frame_ = receive();\r
}\r
+ else\r
+ {\r
+ last_frame_->get_image_transform().gain *= video_gain_;\r
+ last_frame_->get_image_transform().alpha *= video_opacity_;\r
+ last_frame_->get_audio_transform().gain *= audio_gain_;\r
+ }\r
}\r
catch(...)\r
{\r
}\r
void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);} \r
void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);} \r
+void layer::set_video_gain(double value) { impl_->video_gain_ = value;}\r
+void layer::set_video_opacity(double value) { impl_->video_opacity_ = value;}\r
+void layer::set_audio_gain(double value) { impl_->audio_gain_ = value;}\r
void layer::play(){impl_->play();}\r
void layer::pause(){impl_->pause();}\r
void layer::stop(){impl_->stop();}\r
void layer::clear(){impl_->clear();}\r
-bool layer::empty() const { return impl_->foreground_ == frame_producer::empty() && impl_->background_ == frame_producer::empty();}\r
safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
layer(int index = -1); // nothrow\r
layer(layer&& other); // nothrow\r
layer& operator=(layer&& other); // nothrow\r
+\r
+ void set_video_gain(double value);\r
+ void set_video_opacity(double value);\r
+\r
+ void set_audio_gain(double value);\r
\r
void load(const safe_ptr<frame_producer>& producer, bool play_on_load = false); // nothrow\r
void preview(const safe_ptr<frame_producer>& producer); // nothrow\r
void stop(); // nothrow\r
void clear(); // nothrow\r
\r
- bool empty() const; // nothrow\r
- \r
safe_ptr<frame_producer> foreground() const; // nothrow\r
safe_ptr<frame_producer> background() const; // nothrow\r
\r
#include "transition_producer.h"\r
\r
#include "../../video_format.h"\r
-#include "../../processor/draw_frame.h"\r
-#include "../../processor/frame_processor_device.h"\r
+#include "../../mixer/frame/draw_frame.h"\r
+#include "../../mixer/frame_mixer_device.h"\r
+#include "../../mixer/image/image_mixer.h"\r
+#include "../../mixer/audio/audio_mixer.h"\r
\r
#include <boost/range/algorithm/copy.hpp>\r
\r
safe_ptr<frame_producer> dest_producer_;\r
safe_ptr<frame_producer> source_producer_;\r
\r
- std::shared_ptr<frame_processor_device> frame_processor_;\r
+ std::shared_ptr<frame_mixer_device> frame_mixer_;\r
\r
implementation(const safe_ptr<frame_producer>& dest, const transition_info& info) \r
: current_frame_(0)\r
try\r
{\r
auto following = producer->get_following_producer();\r
- following->initialize(safe_ptr<frame_processor_device>(frame_processor_));\r
+ following->initialize(safe_ptr<frame_mixer_device>(frame_mixer_));\r
following->set_leading_producer(producer);\r
producer = std::move(following);\r
}\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_src_frame.get_audio_transform().gain = 1.0-alpha;\r
+ my_dest_frame.get_audio_transform().gain = alpha;\r
\r
double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0; \r
\r
if(info_.type == transition::mix)\r
- my_dest_frame.alpha(alpha); \r
+ my_dest_frame.get_image_transform().alpha = alpha; \r
else if(info_.type == transition::slide) \r
- my_dest_frame.translate((-1.0+alpha)*dir, 0.0); \r
+ my_dest_frame.get_image_transform().pos = boost::make_tuple((-1.0+alpha)*dir, 0.0); \r
else if(info_.type == transition::push)\r
{\r
- my_dest_frame.translate((-1.0+alpha)*dir, 0.0);\r
- my_src_frame.translate((0.0+alpha)*dir, 0.0);\r
+ my_dest_frame.get_image_transform().pos = boost::make_tuple((-1.0+alpha)*dir, 0.0);\r
+ my_src_frame.get_image_transform().pos = boost::make_tuple((0.0+alpha)*dir, 0.0);\r
}\r
else if(info_.type == transition::wipe)\r
{\r
- my_dest_frame.translate((-1.0+alpha)*dir, 0.0); \r
- my_dest_frame.texcoord((-1.0+alpha)*dir, 0.0, 0.0-(1.0-alpha)*dir, 0.0); \r
+ my_dest_frame.get_image_transform().pos = boost::make_tuple((-1.0+alpha)*dir, 0.0); \r
+ my_dest_frame.get_image_transform().uv = boost::make_tuple((-1.0+alpha)*dir, 0.0, 0.0-(1.0-alpha)*dir, 0.0); \r
}\r
\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
+ void initialize(const safe_ptr<frame_mixer_device>& frame_mixer)\r
{\r
- dest_producer_->initialize(frame_processor);\r
- frame_processor_ = frame_processor;\r
+ dest_producer_->initialize(frame_mixer);\r
+ frame_mixer_ = frame_mixer;\r
}\r
\r
std::wstring print() const\r
safe_ptr<draw_frame> transition_producer::receive(){return impl_->receive();}\r
safe_ptr<frame_producer> transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
void transition_producer::set_leading_producer(const safe_ptr<frame_producer>& producer) { impl_->set_leading_producer(producer); }\r
-void transition_producer::initialize(const safe_ptr<frame_processor_device>& frame_processor) { impl_->initialize(frame_processor);}\r
+void transition_producer::initialize(const safe_ptr<frame_mixer_device>& frame_mixer) { impl_->initialize(frame_mixer);}\r
std::wstring transition_producer::print() const { return impl_->print();}\r
\r
}}\r
\r
virtual safe_ptr<frame_producer> get_following_producer() const;\r
virtual void set_leading_producer(const safe_ptr<frame_producer>& producer);\r
- virtual void initialize(const safe_ptr<frame_processor_device>& frame_processor);\r
+ virtual void initialize(const safe_ptr<frame_mixer_device>& frame_mixer);\r
virtual std::wstring print() const;\r
private:\r
struct implementation;\r
_parameters.clear();\r
}\r
\r
+bool MixerCommand::DoExecute()\r
+{ \r
+ //Perform loading of the clip\r
+ try\r
+ { \r
+ if(_parameters[0] == L"VIDEO")\r
+ {\r
+ if(_parameters[1] == L"OPACITY")\r
+ {\r
+ double value = boost::lexical_cast<double>(_parameters[2]);\r
+ GetChannel()->set_video_opacity(GetLayerIndex(), value);\r
+ }\r
+ else if(_parameters[1] == L"GAIN")\r
+ {\r
+ double value = boost::lexical_cast<double>(_parameters[2]);\r
+ GetChannel()->set_video_gain(GetLayerIndex(), value);\r
+ }\r
+ else if(_parameters[1] == L"RESET")\r
+ {\r
+ GetChannel()->set_video_opacity(GetLayerIndex(), 1.0);\r
+ GetChannel()->set_video_gain(GetLayerIndex(), 1.0);\r
+ }\r
+ }\r
+ else if(_parameters[0] == L"AUDIO")\r
+ {\r
+ if(_parameters[1] == L"GAIN")\r
+ {\r
+ double value = boost::lexical_cast<double>(_parameters[2]);\r
+ GetChannel()->set_audio_gain(GetLayerIndex(), value);\r
+ }\r
+ else if(_parameters[1] == L"RESET")\r
+ {\r
+ GetChannel()->set_audio_gain(GetLayerIndex(), 1.0);\r
+ }\r
+ }\r
+ else if(_parameters[0] == L"RESET")\r
+ {\r
+ GetChannel()->set_video_opacity(GetLayerIndex(), 1.0);\r
+ GetChannel()->set_video_gain(GetLayerIndex(), 1.0);\r
+ GetChannel()->set_audio_gain(GetLayerIndex(), 1.0);\r
+ }\r
+ \r
+ SetReplyString(TEXT("202 MIXER OK\r\n"));\r
+\r
+ return true;\r
+ }\r
+ catch(file_not_found&)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ SetReplyString(TEXT("404 MIXER ERROR\r\n"));\r
+ return false;\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ SetReplyString(TEXT("502 MIXER FAILED\r\n"));\r
+ return false;\r
+ }\r
+}\r
+\r
bool AddCommand::DoExecute()\r
{ \r
//Perform loading of the clip\r
\r
bool ClearCommand::DoExecute()\r
{\r
- int index = GetLayerIndex(std::numeric_limits<int>::max());\r
- if(index == std::numeric_limits<int>::max())\r
- GetChannel()->clear();\r
- else\r
- GetChannel()->clear(index);\r
+ GetChannel()->clear(GetLayerIndex());\r
\r
SetReplyString(TEXT("202 CLEAR OK\r\n"));\r
\r
std::wstring ListTemplates();\r
\r
namespace amcp {\r
+\r
+class MixerCommand : public AMCPCommandBase<true, AddToQueue, 2>\r
+{\r
+ std::wstring print() const { return L"MixerCommand";}\r
+ bool DoExecute();\r
+};\r
\r
class AddCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
{\r
std::wstring s = str;\r
transform(s.begin(), s.end(), s.begin(), toupper);\r
\r
- if (s == TEXT("LOAD")) return std::make_shared<LoadCommand>();\r
+ if (s == TEXT("MIXER")) return std::make_shared<MixerCommand>();\r
+ else if(s == TEXT("LOAD")) return std::make_shared<LoadCommand>();\r
else if(s == TEXT("LOADBG")) return std::make_shared<LoadbgCommand>();\r
else if(s == TEXT("ADD")) return std::make_shared<AddCommand>();\r
else if(s == TEXT("REMOVE")) return std::make_shared<RemoveCommand>();\r