* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
*\r
*/\r
+// TODO: Try to recover consumer from bad_alloc...\r
#include "../StdAfx.h"\r
\r
#ifdef _MSC_VER\r
\r
namespace caspar { namespace core {\r
\r
-class key_read_frame_adapter : public core::read_frame\r
-{\r
- ogl_device& ogl_;\r
- safe_ptr<read_frame> fill_;\r
- std::shared_ptr<host_buffer> key_;\r
- tbb::mutex mutex_;\r
-public:\r
- key_read_frame_adapter(ogl_device& ogl, const safe_ptr<read_frame>& fill)\r
- : ogl_(ogl)\r
- , fill_(fill)\r
- {\r
- }\r
-\r
- virtual const boost::iterator_range<const uint8_t*> image_data()\r
- {\r
- tbb::mutex::scoped_lock lock(mutex_);\r
- if(!key_)\r
- {\r
- key_ = ogl_.create_host_buffer(fill_->image_data().size(), host_buffer::write_only); \r
- fast_memsfhl(key_->data(), fill_->image_data().begin(), fill_->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
- }\r
-\r
- auto ptr = static_cast<const uint8_t*>(key_->data());\r
- return boost::iterator_range<const uint8_t*>(ptr, ptr + key_->size());\r
- }\r
-\r
- virtual const boost::iterator_range<const int16_t*> audio_data()\r
- {\r
- return fill_->audio_data();\r
- } \r
-};\r
- \r
struct output::implementation\r
{ \r
typedef std::pair<safe_ptr<read_frame>, safe_ptr<read_frame>> fill_and_key;\r
\r
void add(int index, safe_ptr<frame_consumer>&& consumer)\r
{ \r
- consumer->initialize(channel_.get_format_desc());\r
channel_.execution().invoke([&]\r
{\r
consumers_.erase(index);\r
+ });\r
+\r
+ consumer->initialize(channel_.get_format_desc());\r
+\r
+ channel_.execution().invoke([&]\r
+ {\r
consumers_.insert(std::make_pair(index, consumer));\r
\r
CASPAR_LOG(info) << print() << L" " << consumer->print() << L" Added.";\r
}\r
\r
void execute(const safe_ptr<read_frame>& frame)\r
- { \r
- try\r
- { \r
- if(!has_synchronization_clock())\r
- timer_.tick(1.0/channel_.get_format_desc().fps);\r
- \r
- auto fill = frame;\r
- auto key = make_safe<key_read_frame_adapter>(channel_.ogl(), frame);\r
+ { \r
+ if(!has_synchronization_clock())\r
+ timer_.tick(1.0/channel_.get_format_desc().fps);\r
\r
- auto it = consumers_.begin();\r
- while(it != consumers_.end())\r
- {\r
- try\r
- {\r
- auto consumer = it->second;\r
-\r
- if(consumer->get_video_format_desc() != channel_.get_format_desc())\r
- consumer->initialize(channel_.get_format_desc());\r
-\r
- auto frame = consumer->key_only() ? key : fill;\r
-\r
- if(static_cast<size_t>(frame->image_data().size()) == consumer->get_video_format_desc().size)\r
- consumer->send(frame);\r
-\r
- ++it;\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- CASPAR_LOG(error) << print() << L" " << it->second->print() << L" Removed.";\r
- consumers_.erase(it++);\r
- }\r
- }\r
+ if(frame->image_size() != channel_.get_format_desc().size)\r
+ {\r
+ timer_.tick(1.0/channel_.get_format_desc().fps);\r
+ return;\r
}\r
- catch(...)\r
+ \r
+ auto it = consumers_.begin();\r
+ while(it != consumers_.end())\r
{\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
+ auto consumer = it->second;\r
+\r
+ if(consumer->get_video_format_desc() != channel_.get_format_desc())\r
+ consumer->initialize(channel_.get_format_desc());\r
+\r
+ if(consumer->send(frame))\r
+ ++it;\r
+ else\r
+ consumers_.erase(it++);\r
}\r
}\r
\r