<ClInclude Include="log\log.h" />\r
<ClInclude Include="stdafx.h" />\r
<ClInclude Include="utility\scope_exit.h" />\r
+ <ClInclude Include="utility\singleton_pool.h" />\r
<ClInclude Include="utility\string_convert.h" />\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="gl\shader_program.h">\r
<Filter>Source\gl</Filter>\r
</ClInclude>\r
+ <ClInclude Include="utility\singleton_pool.h">\r
+ <Filter>Source\utility</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
--- /dev/null
+#pragma once\r
+ \r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/scalable_allocator.h>\r
+\r
+namespace caspar { namespace common {\r
+\r
+template <typename T>\r
+class singleton_pool\r
+{\r
+public:\r
+ \r
+ static T* allocate()\r
+ {\r
+ T* ptr;\r
+ if(!get_pool().try_pop(ptr))\r
+ ptr = static_cast<T*>(scalable_malloc(sizeof(T)));\r
+ return ptr;\r
+ }\r
+ \r
+ static void deallocate(T* ptr)\r
+ {\r
+ if(!get_pool().try_push(ptr))\r
+ scalable_free(ptr);\r
+ }\r
+\r
+ static void destroy(T* ptr)\r
+ {\r
+ ptr->~T();\r
+ deallocate(ptr);\r
+ }\r
+\r
+ static std::shared_ptr<T> make_shared()\r
+ {\r
+ return std::shared_ptr<T>(new(allocate()) T(), destroy);\r
+ }\r
+ \r
+ template<typename P0>\r
+ static std::shared_ptr<T> make_shared(P0 p0)\r
+ {\r
+ return std::shared_ptr<T>(new(allocate()) T(std::forward<P0>(p0)), destroy);\r
+ }\r
+ \r
+ template<typename P0, typename P1>\r
+ static std::shared_ptr<T> make_shared(P0 p0, P1 p1)\r
+ {\r
+ return std::shared_ptr<T>(new(allocate()) T(std::forward<P0>(p0), std::forward<P1>(p1)), destroy);\r
+ }\r
+ \r
+ template<typename P0, typename P1, typename P2>\r
+ static std::shared_ptr<T> make_shared(P0 p0, P1 p1, P2 p2)\r
+ {\r
+ return std::shared_ptr<T>(new(allocate()) T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)), destroy);\r
+ }\r
+ \r
+ template<typename P0, typename P1, typename P2, typename P3>\r
+ static std::shared_ptr<T> make_shared(P0 p0, P1 p1, P2 p2, P3 p3)\r
+ {\r
+ return std::shared_ptr<T>(new(allocate()) T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)), destroy);\r
+ }\r
+\r
+private:\r
+ struct pool\r
+ {\r
+ ~pool()\r
+ {\r
+ T* ptr;\r
+ while(value.try_pop(ptr))\r
+ scalable_free(ptr);\r
+ }\r
+ tbb::concurrent_bounded_queue<T*> value;\r
+ };\r
+\r
+ static tbb::concurrent_bounded_queue<T*>& get_pool()\r
+ {\r
+ static pool global_pool;\r
+ return global_pool.value;\r
+ }\r
+};\r
+\r
+}}
\ No newline at end of file
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
- <ClCompile Include="format\pixel_format.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\StdAfx.h</PrecompiledHeaderFile>\r
- </ClCompile>\r
<ClCompile Include="format\video_format.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<ClCompile Include="channel.cpp">\r
<Filter>Source\channel</Filter>\r
</ClCompile>\r
- <ClCompile Include="format\pixel_format.cpp">\r
- <Filter>Source\channel\format</Filter>\r
- </ClCompile>\r
<ClCompile Include="consumer\decklink\decklink_consumer.cpp">\r
<Filter>Source\channel\consumer\decklink</Filter>\r
</ClCompile>\r
+++ /dev/null
-#include "..\StdAfx.h"\r
-\r
-#include "pixel_format.h"\r
-\r
-namespace caspar { namespace core {\r
- \r
-size_t hash(const pixel_format_desc& desc)\r
-{\r
- size_t hash = 0;\r
- switch(desc.pix_fmt)\r
- {\r
- case pixel_format::ycbcr:\r
- case pixel_format::ycbcra:\r
- // 0-10 (11) width\r
- // 11-21 (11) height\r
- // 22-24 (3) x-ratio\r
- // 25-27 (3) y-ratio\r
- // 28-29 (2) unused\r
- // 30 (1) alpha\r
- // 31 (1) yuv = true => 1\r
- hash |= ( desc.planes[0].width & 0x7FF ) << 0;\r
- hash |= ( desc.planes[0].height & 0x7FF ) << 11;\r
- hash |= ((desc.planes[0].height/desc.planes[1].height) & 0x7 ) << 22;\r
- hash |= ((desc.planes[0].width/desc.planes[1].width) & 0x7 ) << 25;\r
- hash |= desc.pix_fmt == pixel_format::ycbcra ? (1 << 30) : 0;\r
- hash |= 1 << 31;\r
- return hash;\r
- case pixel_format::bgra:\r
- case pixel_format::rgba:\r
- case pixel_format::argb:\r
- case pixel_format::abgr:\r
- \r
- //0-10 (11) height\r
- //11-21 (11) width\r
- //22-29 (8) unused\r
- //30 (1) alpha\r
- //31 (1) yuv = false => 0\r
- hash |= (desc.planes[0].height & 0xFFFF) << 0;\r
- hash |= (desc.planes[0].width & 0xFFFF) << 15;\r
- hash |= 1 << 30;\r
- return hash;\r
-\r
- default:\r
- return hash;\r
- };\r
-}\r
- \r
-}}\r
pixel_format::type pix_fmt;\r
std::vector<plane> planes;\r
};\r
-\r
-size_t hash(const pixel_format_desc& desc);\r
- \r
-inline bool operator==(const pixel_format_desc& lhs, const pixel_format_desc& rhs)\r
-{\r
- return hash(lhs) == hash(rhs);\r
-}\r
-\r
-inline bool operator!=(const pixel_format_desc& lhs, const pixel_format_desc& rhs)\r
-{\r
- return !(lhs == rhs);\r
-}\r
\r
-}}\r
-\r
-namespace std {\r
-\r
-template<> struct hash<caspar::core::pixel_format_desc>\r
-{\r
- size_t operator()(const caspar::core::pixel_format_desc& desc) const { return caspar::core::hash(desc);}\r
-};\r
-\r
-}
\ No newline at end of file
+}}
\ No newline at end of file
#include "draw_frame.h"\r
#include "composite_frame.h"\r
#include "transform_frame.h"\r
-#include "../../common/gl/utility.h"\r
+#include "frame_shader.h"\r
+#include "../../common/utility/singleton_pool.h"\r
\r
#include <boost/range/algorithm.hpp>\r
-#include <boost/range/algorithm_ext/erase.hpp>\r
-\r
-#include <algorithm>\r
-#include <numeric>\r
\r
#include <tbb/parallel_for.h>\r
\r
\r
struct composite_frame::implementation\r
{ \r
- implementation(std::vector<draw_frame>&& frames) : frames_(std::move(frames)), audio_data_(1920*2, 0)\r
+ implementation(std::vector<draw_frame>&& frames) : frames_(std::move(frames))\r
{ \r
boost::range::for_each(frames_, [&](const draw_frame& frame)\r
{\r
- tbb::parallel_for\r
- (\r
- tbb::blocked_range<size_t>(0, frame.audio_data().size()),\r
- [&](const tbb::blocked_range<size_t>& r)\r
- {\r
- for(size_t n = r.begin(); n < r.end(); ++n) \r
- audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + static_cast<int>(frame.audio_data()[n])) & 0xFFFF); \r
- }\r
- );\r
+ if(audio_data_.empty())\r
+ audio_data_ = frame.audio_data();\r
+ else\r
+ {\r
+ tbb::parallel_for\r
+ (\r
+ tbb::blocked_range<size_t>(0, frame.audio_data().size()),\r
+ [&](const tbb::blocked_range<size_t>& r)\r
+ {\r
+ for(size_t n = r.begin(); n < r.end(); ++n) \r
+ audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + static_cast<int>(frame.audio_data()[n])) & 0xFFFF); \r
+ }\r
+ );\r
+ }\r
});\r
}\r
\r
boost::range::for_each(frames_, std::bind(&detail::draw_frame_access::draw, std::placeholders::_1, std::ref(shader)));\r
}\r
\r
- std::vector<draw_frame> frames_;\r
std::vector<short> audio_data_;\r
+ std::vector<draw_frame> frames_;\r
};\r
\r
-composite_frame::composite_frame(std::vector<draw_frame>&& frames) : impl_(new implementation(std::move(frames))){}\r
+composite_frame::composite_frame(std::vector<draw_frame>&& frames) : impl_(common::singleton_pool<implementation>::make_shared(std::move(frames))){}\r
composite_frame::composite_frame(composite_frame&& other) : impl_(std::move(other.impl_)){}\r
-composite_frame::composite_frame(const composite_frame& other) : impl_(new implementation(*other.impl_)){}\r
+composite_frame::composite_frame(const composite_frame& other) : impl_(common::singleton_pool<implementation>::make_shared(*other.impl_)){}\r
composite_frame& composite_frame::operator=(const composite_frame& other)\r
{\r
composite_frame temp(other);\r
\r
template<typename T>\r
draw_frame(T&& impl, typename std::enable_if<std::is_base_of<detail::draw_frame_impl, typename std::remove_reference<T>::type>::value, void>::type* dummy = nullptr)\r
- : impl_(std::make_shared<T>(std::forward<T>(impl))), tag_(normal_tag){}\r
+ : impl_(std::make_shared<T>(std::forward<T>(impl))), tag_(normal_tag){dummy;}\r
\r
draw_frame(eof_frame&&) : tag_(eof_tag){}\r
draw_frame(empty_frame&&) : tag_(empty_tag){}\r
static GLenum mapping[] = {GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGR, GL_BGRA};\r
auto pooled_pbo = std::make_shared<pbo>(plane.width, plane.height, mapping[plane.channels-1]);\r
pooled_pbo->end_write();\r
- return pbo_ptr(pooled_pbo.get(), [=](pbo*){pool->push(pooled_pbo);});\r
+ return pbo_ptr(pooled_pbo.get(), [=](pbo*)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ pooled_pbo->end_write();\r
+ pool->push(pooled_pbo);\r
+ });\r
+ });\r
}\r
\r
common::executor executor_; \r
reading_frame result;\r
try\r
{\r
- detail::draw_frame_access::end_write(drawing_); // Map data pointer before returning to pool.\r
drawing_ = writing_;\r
writing_ = frame;\r
\r
\r
detail::draw_frame_access::draw(drawing_, shader_);\r
\r
- reading_ = create_reading(drawing_.audio_data()); \r
+ reading_ = create_reading(std::vector<short>(drawing_.audio_data().begin(), drawing_.audio_data().end())); \r
reading_.first->begin_read();\r
\r
drawing_ = draw_frame::empty();\r
#include "../format/pixel_format.h"\r
#include "../../common/gl/utility.h"\r
#include "../../common/gl/pixel_buffer_object.h"\r
+#include "../../common/utility/singleton_pool.h"\r
\r
#include <boost/range/algorithm.hpp>\r
\r
std::vector<short> audio_data_;\r
};\r
\r
-read_frame::read_frame(common::gl::pbo_ptr&& pbo, std::vector<short>&& audio_data) : impl_(new implementation(std::move(pbo), std::move(audio_data))){}\r
+read_frame::read_frame(common::gl::pbo_ptr&& pbo, std::vector<short>&& audio_data) : impl_(common::singleton_pool<implementation>::make_shared(std::move(pbo), std::move(audio_data))){}\r
const boost::iterator_range<const unsigned char*> read_frame::pixel_data() const\r
{\r
if(!impl_->pbo_ || !impl_->pbo_->data())\r
#include "../format/pixel_format.h"\r
#include "../../common/gl/utility.h"\r
#include "../../common/gl/pixel_buffer_object.h"\r
+#include "../../common/utility/singleton_pool.h"\r
\r
#include <boost/range/algorithm.hpp>\r
\r
struct transform_frame::implementation\r
{\r
implementation(const draw_frame& frame) : frame_(frame), audio_volume_(255), override_audio_(false){}\r
- implementation(const draw_frame& frame, const std::vector<short>& audio_data) : frame_(frame), audio_volume_(255), audio_data_(audio_data), override_audio_(true){}\r
+ implementation(const draw_frame& frame, std::vector<short>&& audio_data) : frame_(frame), audio_volume_(255), audio_data_(std::move(audio_data)), override_audio_(true){}\r
implementation(draw_frame&& frame) : frame_(std::move(frame)), audio_volume_(255), override_audio_(false){}\r
\r
void begin_write(){detail::draw_frame_access::begin_write(frame_);}\r
}\r
\r
bool override_audio_;\r
- std::vector<short> audio_data_;\r
- shader_transform transform_; \r
unsigned char audio_volume_;\r
draw_frame frame_;\r
+ std::vector<short> audio_data_;\r
+ shader_transform transform_; \r
};\r
\r
-transform_frame::transform_frame(const draw_frame& frame) : impl_(new implementation(frame)){}\r
-transform_frame::transform_frame(const draw_frame& frame, const std::vector<short>& audio_data) : impl_(new implementation(frame, audio_data)){}\r
-transform_frame::transform_frame(draw_frame&& frame) : impl_(new implementation(std::move(frame))){}\r
-transform_frame::transform_frame(const transform_frame& other) : impl_(new implementation(*other.impl_)){}\r
+transform_frame::transform_frame(const draw_frame& frame) : impl_(common::singleton_pool<implementation>::make_shared(frame)){}\r
+transform_frame::transform_frame(const draw_frame& frame, std::vector<short>&& audio_data) : impl_(common::singleton_pool<implementation>::make_shared(frame, std::move(audio_data))){}\r
+transform_frame::transform_frame(draw_frame&& frame) : impl_(common::singleton_pool<implementation>::make_shared(std::move(frame))){}\r
+transform_frame::transform_frame(const transform_frame& other) : impl_(common::singleton_pool<implementation>::make_shared(*other.impl_)){}\r
transform_frame& transform_frame::operator=(const transform_frame& other)\r
{\r
transform_frame temp(other);\r
{\r
public:\r
transform_frame(const draw_frame& frame);\r
- transform_frame(const draw_frame& frame, const std::vector<short>& audio_data);\r
+ transform_frame(const draw_frame& frame, std::vector<short>&& audio_data);\r
transform_frame(draw_frame&& frame);\r
\r
transform_frame(const transform_frame& other);\r
#include "../format/pixel_format.h"\r
#include "../../common/gl/utility.h"\r
#include "../../common/gl/pixel_buffer_object.h"\r
+#include "../../common/utility/singleton_pool.h"\r
\r
#include <boost/range/algorithm.hpp>\r
\r
const pixel_format_desc desc_;\r
};\r
\r
-write_frame::write_frame(std::vector<common::gl::pbo_ptr>&& pbos, const pixel_format_desc& desc) : impl_(new implementation(std::move(pbos), desc)){}\r
+write_frame::write_frame(std::vector<common::gl::pbo_ptr>&& pbos, const pixel_format_desc& desc) : impl_(common::singleton_pool<implementation>::make_shared(std::move(pbos), desc)){}\r
write_frame::write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
write_frame& write_frame::operator=(write_frame&& other)\r
{\r
draw_frame execute(const std::shared_ptr<AVFrame>& decoded_frame)\r
{ \r
if(decoded_frame == nullptr)\r
- return draw_frame::eof(); // TODO\r
+ return draw_frame::eof();\r
\r
if(sws_context_ == nullptr)\r
{\r