void execute(const safe_ptr<read_frame>& frame) { if(!has_synchronization_clock()) timer_.tick(1.0/channel_.get_format_desc().fps); if(frame->image_size() != channel_.get_format_desc().size) { timer_.tick(1.0/channel_.get_format_desc().fps); return; } auto it = consumers_.begin(); while(it != consumers_.end()) { auto consumer = it->second; if(consumer->get_video_format_desc() != channel_.get_format_desc()) consumer->initialize(channel_.get_format_desc()); try { if(consumer->send(frame)) ++it; else consumers_.erase(it++); } catch(...) { CASPAR_LOG_CURRENT_EXCEPTION(); CASPAR_LOG(warning) << "Trying to restart consumer: " << consumer->print() << L"."; try { consumer->initialize(channel_.get_format_desc()); consumer->send(frame); } catch(...) { CASPAR_LOG_CURRENT_EXCEPTION(); CASPAR_LOG(warning) << "Consumer restart failed, trying to restart channel: " << consumer->print() << L"."; try { restart_channel_(); consumer->initialize(channel_.get_format_desc()); consumer->send(frame); } catch(...) { CASPAR_LOG_CURRENT_EXCEPTION(); CASPAR_LOG(error) << "Failed to recover consumer: " << consumer->print() << L". Removing it."; consumers_.erase(it++); } } } } }
virtual bool send(const safe_ptr<core::read_frame>& frame) override { auto format_desc = format_desc_; boost::thread async([format_desc, frame] { try { auto filename = narrow(env::data_folder()) + boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time()) + ".png"; auto bitmap = std::shared_ptr<FIBITMAP>(FreeImage_Allocate(format_desc.width, format_desc.height, 32), FreeImage_Unload); memcpy(FreeImage_GetBits(bitmap.get()), frame->image_data().begin(), frame->image_size()); FreeImage_FlipVertical(bitmap.get()); FreeImage_Save(FIF_PNG, bitmap.get(), filename.c_str(), 0); } catch(...) { CASPAR_LOG_CURRENT_EXCEPTION(); } }); async.detach(); return false; }