<ClInclude Include="env.h" />\r
<ClInclude Include="stdafx.h" />\r
<ClInclude Include="utility\assert.h" />\r
+ <ClInclude Include="utility\printable.h" />\r
<ClInclude Include="utility\string_convert.h" />\r
<ClInclude Include="utility\timer.h" />\r
</ItemGroup>\r
<ClInclude Include="diagnostics\graph.h">\r
<Filter>Source\diagnostics</Filter>\r
</ClInclude>\r
+ <ClInclude Include="utility\printable.h">\r
+ <Filter>Source\utility</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
typedef boost::error_info<struct tag_arg_name_info, std::string> arg_name_info;\r
typedef boost::error_info<struct tag_arg_value_info, std::string> arg_value_info;\r
typedef boost::error_info<struct tag_msg_info, std::string> msg_info;\r
+typedef boost::error_info<struct tag_source_info, std::string> source_info;\r
typedef boost::error_info<struct tag_inner_info, std::exception_ptr> inner_info;\r
typedef boost::error_info<struct tag_line_info, int> line_info;\r
\r
--- /dev/null
+#pragma once\r
+\r
+#include <string>\r
+#include <functional>\r
+#include <memory>\r
+\r
+namespace caspar {\r
+\r
+typedef std::function<std::wstring()> printer;\r
+\r
+}
\ No newline at end of file
#include "producer/layer.h"\r
\r
#include <common/concurrency/executor.h>\r
+#include <common/utility/printable.h>\r
\r
#include <boost/range/algorithm_ext/erase.hpp>\r
\r
\r
#include <memory>\r
\r
+#ifdef _MSC_VER\r
+#pragma warning(disable : 4355)\r
+#endif\r
+\r
namespace caspar { namespace core {\r
\r
struct channel::implementation : boost::noncopyable\r
{ \r
+ const int index_;\r
+\r
std::shared_ptr<frame_consumer_device> consumer_;\r
std::shared_ptr<frame_mixer_device> mixer_;\r
std::shared_ptr<frame_producer_device> producer_;\r
const video_format_desc format_desc_;\r
\r
public:\r
- implementation(const video_format_desc& format_desc) \r
- : format_desc_(format_desc)\r
+ implementation(int index, const video_format_desc& format_desc) \r
+ : index_(index)\r
+ , format_desc_(format_desc)\r
, consumer_(new frame_consumer_device(format_desc))\r
, mixer_(new frame_mixer_device(format_desc, std::bind(&frame_consumer_device::send, consumer_.get(), std::placeholders::_1)))\r
- , producer_(new frame_producer_device(safe_ptr<frame_factory>(mixer_), std::bind(&frame_mixer_device::send, mixer_.get(), std::placeholders::_1))) {}\r
+ , producer_(new frame_producer_device(safe_ptr<frame_factory>(mixer_), std::bind(&frame_mixer_device::send, mixer_.get(), std::placeholders::_1), std::bind(&implementation::print, this))) {}\r
\r
~implementation()\r
{\r
// Shutdown order is important! Destroy all created frames to mixer before destroying mixer.\r
- CASPAR_LOG(info) << "Shutting down channel.";\r
+ CASPAR_LOG(info) << print() << " shutting down channel.";\r
producer_.reset();\r
- CASPAR_LOG(info) << "Successfully shut down producer-device.";\r
+ CASPAR_LOG(info) << print() << "successfully shut down producer-device.";\r
consumer_.reset();\r
- CASPAR_LOG(info) << "Successfully shut down consumer-device.";\r
+ CASPAR_LOG(info) << print() << "successfully shut down consumer-device.";\r
mixer_.reset();\r
- CASPAR_LOG(info) << "Successfully shut down mixer-device.";\r
+ CASPAR_LOG(info) << print() << "successfully shut down mixer-device.";\r
+ }\r
+\r
+ std::wstring print() const\r
+ {\r
+ return L"channel[" + boost::lexical_cast<std::wstring>(index_) + L"]";\r
}\r
};\r
\r
+channel::channel(int index, const video_format_desc& format_desc) : impl_(new implementation(index, format_desc)){}\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
frame_producer_device& channel::producer() { return *impl_->producer_;} \r
frame_mixer_device& channel::mixer() { return *impl_->mixer_;} \r
frame_consumer_device& channel::consumer() { return *impl_->consumer_;} \r
class channel : boost::noncopyable\r
{\r
public:\r
- explicit channel(const video_format_desc& format_desc);\r
+ explicit channel(int index, const video_format_desc& format_desc);\r
channel(channel&& other);\r
\r
frame_producer_device& producer();\r
{\r
safe_ptr<draw_frame> frame_;\r
std::wstring color_str_;\r
+ printer parent_printer_;\r
\r
public:\r
\r
str >> std::hex >> value; \r
frame_ = std::move(frame);\r
}\r
+\r
+ virtual void set_parent_printer(const printer& parent_printer){parent_printer_ = parent_printer;}\r
\r
virtual safe_ptr<draw_frame> receive() { return frame_; }\r
\r
- virtual std::wstring print() const { return + L"color[" + color_str_ + L"]"; }\r
+ virtual std::wstring print() const { return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"color[" + color_str_ + L"]"; }\r
};\r
\r
safe_ptr<frame_producer> create_color_producer(const std::vector<std::wstring>& params)\r
~co_init(){CoUninitialize();}\r
} co_;\r
\r
+ printer parent_printer_;\r
const video_format_desc format_desc_;\r
std::wstring model_name_;\r
const size_t device_index_;\r
\r
public:\r
\r
- decklink_input(const video_format_desc& format_desc, size_t device_index, const std::shared_ptr<frame_factory>& frame_factory)\r
- : format_desc_(format_desc)\r
+ decklink_input(const video_format_desc& format_desc, size_t device_index, const std::shared_ptr<frame_factory>& frame_factory, const printer& parent_printer)\r
+ : parent_printer_(parent_printer)\r
+ , format_desc_(format_desc)\r
, device_index_(device_index)\r
, model_name_(L"DECKLINK")\r
, frame_factory_(frame_factory)\r
if(FAILED(input_->StartStreams()))\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to start input stream."));\r
\r
- CASPAR_LOG(info) << print() << " Successfully initialized decklink for " << format_desc_.name;\r
+ CASPAR_LOG(info) << print() << " successfully initialized decklink for " << format_desc_.name;\r
}\r
\r
~decklink_input()\r
\r
std::wstring print() const\r
{\r
- return model_name_ + L" [input-" + boost::lexical_cast<std::wstring>(device_index_) + L"]";\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L" [" + model_name_ + L"device:" + boost::lexical_cast<std::wstring>(device_index_) + L"]";\r
}\r
};\r
\r
class decklink_producer : public frame_producer\r
{ \r
const size_t device_index_;\r
+ printer parent_printer_;\r
\r
std::unique_ptr<decklink_input> input_;\r
\r
executor_.start();\r
executor_.invoke([=]\r
{\r
- input_.reset(new decklink_input(format_desc_, device_index_, frame_factory));\r
+ input_.reset(new decklink_input(format_desc_, device_index_, frame_factory, parent_printer_));\r
});\r
}\r
+\r
+ virtual void set_parent_printer(const printer& parent_printer) { parent_printer_ = parent_printer;}\r
\r
virtual safe_ptr<draw_frame> receive()\r
{\r
\r
std::wstring print() const\r
{\r
- return input_ ? input_->print() : L"Unknown Decklink [input-" + boost::lexical_cast<std::wstring>(device_index_) + L"]";\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + (input_ ? input_->print() : L"Unknown Decklink [input-" + boost::lexical_cast<std::wstring>(device_index_) + L"]");\r
}\r
};\r
\r
struct ffmpeg_producer : public frame_producer\r
{\r
const std::wstring filename_;\r
+ const bool loop_;\r
+ printer parent_printer_;\r
\r
safe_ptr<diagnostics::graph> graph_;\r
timer perf_timer_;\r
safe_ptr<draw_frame> last_frame_;\r
std::shared_ptr<frame_factory> frame_factory_;\r
\r
- input input_; \r
+ std::unique_ptr<input> input_; \r
public:\r
explicit ffmpeg_producer(const std::wstring& filename, bool loop) \r
: filename_(filename)\r
+ , loop_(loop)\r
, graph_(diagnostics::create_graph(narrow(print()))) \r
, last_frame_(draw_frame(draw_frame::empty()))\r
- , input_(graph_, filename, loop)\r
\r
{\r
graph_->guide("frame-time", 0.5);\r
virtual void initialize(const safe_ptr<frame_factory>& frame_factory)\r
{\r
frame_factory_ = frame_factory;\r
- video_decoder_.reset(input_.get_video_codec_context().get() ? new video_decoder(input_.get_video_codec_context().get(), frame_factory) : nullptr);\r
- audio_decoder_.reset(input_.get_audio_codec_context().get() ? new audio_decoder(input_.get_audio_codec_context().get(), frame_factory->get_video_format_desc().fps) : nullptr);\r
+ input_.reset(new input(graph_, filename_, loop_, std::bind(&ffmpeg_producer::print, this)));\r
+ video_decoder_.reset(input_->get_video_codec_context().get() ? new video_decoder(input_->get_video_codec_context().get(), frame_factory) : nullptr);\r
+ audio_decoder_.reset(input_->get_audio_codec_context().get() ? new audio_decoder(input_->get_audio_codec_context().get(), frame_factory->get_video_format_desc().fps) : nullptr);\r
}\r
\r
+ virtual void set_parent_printer(const printer& parent_printer) \r
+ {\r
+ parent_printer_ = parent_printer;\r
+ }\r
+\r
virtual safe_ptr<draw_frame> receive()\r
{\r
perf_timer_.reset();\r
\r
- while(ouput_channel_.empty() && !input_.is_eof())\r
+ while(ouput_channel_.empty() && !input_->is_eof())\r
{ \r
aligned_buffer video_packet;\r
if(video_frame_channel_.size() < 3 && video_decoder_) \r
- video_packet = input_.get_video_packet(); \r
+ video_packet = input_->get_video_packet(); \r
\r
aligned_buffer audio_packet;\r
if(audio_chunk_channel_.size() < 3 && audio_decoder_) \r
- audio_packet = input_.get_audio_packet(); \r
+ audio_packet = input_->get_audio_packet(); \r
\r
tbb::parallel_invoke(\r
[&]\r
last_frame_->get_audio_transform().set_gain(0.0); // last_frame should not have audio\r
ouput_channel_.pop();\r
}\r
- else if(input_.is_eof())\r
+ else if(input_->is_eof())\r
return draw_frame::eof();\r
\r
return result;\r
\r
virtual std::wstring print() const\r
{\r
- return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"]";\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"]";\r
}\r
};\r
\r
\r
#include <common/concurrency/executor.h>\r
#include <common/diagnostics/graph.h>\r
+#include <common/utility/printable.h>\r
\r
#include <tbb/concurrent_queue.h>\r
#include <tbb/queuing_mutex.h>\r
{ \r
static const size_t PACKET_BUFFER_COUNT = 50;\r
\r
+ printer parent_printer_;\r
safe_ptr<diagnostics::graph> graph_;\r
\r
std::shared_ptr<AVFormatContext> format_context_; // Destroy this last\r
\r
executor executor_;\r
public:\r
- explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop) \r
- : graph_(graph)\r
+ explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, const printer& parent_printer) \r
+ : parent_printer_(parent_printer)\r
+ , graph_(graph)\r
, loop_(loop)\r
, video_s_index_(-1)\r
, audio_s_index_(-1)\r
if((errn = -av_open_input_file(&weak_format_context_, narrow(filename).c_str(), nullptr, 0, nullptr)) > 0)\r
BOOST_THROW_EXCEPTION(\r
file_read_error() << \r
+ source_info(narrow(print())) << \r
msg_info("No format context found.") << \r
boost::errinfo_api_function("av_open_input_file") <<\r
boost::errinfo_errno(errn) <<\r
if((errn = -av_find_stream_info(format_context_.get())) > 0)\r
BOOST_THROW_EXCEPTION(\r
file_read_error() << \r
+ source_info(narrow(print())) << \r
boost::errinfo_api_function("av_find_stream_info") <<\r
msg_info("No stream found.") << \r
boost::errinfo_errno(errn));\r
\r
video_codec_context_ = open_stream(CODEC_TYPE_VIDEO, video_s_index_);\r
if(!video_codec_context_)\r
- CASPAR_LOG(warning) << "Could not open any video stream.";\r
+ CASPAR_LOG(warning) << print() << " Could not open any video stream.";\r
\r
audio_codex_context_ = open_stream(CODEC_TYPE_AUDIO, audio_s_index_);\r
if(!audio_codex_context_)\r
- CASPAR_LOG(warning) << "Could not open any audio stream.";\r
+ CASPAR_LOG(warning) << print() << " Could not open any audio stream.";\r
\r
if(!video_codec_context_ && !audio_codex_context_)\r
- BOOST_THROW_EXCEPTION(file_read_error() << msg_info("No video or audio codec context found.")); \r
+ BOOST_THROW_EXCEPTION(\r
+ file_read_error() << \r
+ source_info(narrow(print())) << \r
+ msg_info("No video or audio codec context found.")); \r
\r
executor_.start();\r
executor_.begin_invoke([this]{read_file();});\r
- CASPAR_LOG(info) << print() << " started.";\r
+ CASPAR_LOG(info) << print() << " Started.";\r
}\r
\r
~implementation()\r
executor_.clear();\r
executor_.stop();\r
cond_.notify_all();\r
- CASPAR_LOG(info) << print() << " stopped.";\r
+ CASPAR_LOG(info) << print() << " Stopped.";\r
}\r
\r
std::shared_ptr<AVCodecContext> open_stream(int codec_type, int& s_index)\r
\r
bool result = av_seek_frame(format_context_.get(), stream_index, seek_target, flags) >= 0;\r
if(!result)\r
- CASPAR_LOG(warning) << "Failed to seek frame.";\r
+ CASPAR_LOG(warning) << print() << " Failed to seek frame.";\r
return result;\r
}\r
\r
\r
std::wstring print() const\r
{\r
- return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"] buffer thread";\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"[async_input]";\r
}\r
};\r
\r
-input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop) : impl_(new implementation(graph, filename, loop)){}\r
+input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, const printer& parent_printer) : impl_(new implementation(graph, filename, loop, parent_printer)){}\r
const std::shared_ptr<AVCodecContext>& input::get_video_codec_context() const{return impl_->video_codec_context_;}\r
const std::shared_ptr<AVCodecContext>& input::get_audio_codec_context() const{return impl_->audio_codex_context_;}\r
bool input::is_eof() const{return impl_->is_eof();}\r
#pragma once\r
\r
#include <common/diagnostics/graph.h>\r
+#include <common/utility/printable.h>\r
\r
#include <tbb/cache_aligned_allocator.h>\r
\r
class input : boost::noncopyable\r
{\r
public:\r
- explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop);\r
+ explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, const printer& parent_printer);\r
const std::shared_ptr<AVCodecContext>& get_video_codec_context() const;\r
const std::shared_ptr<AVCodecContext>& get_audio_codec_context() const;\r
\r
\r
struct cg_producer::implementation : boost::noncopyable\r
{\r
+ printer parent_printer_;\r
+ safe_ptr<flash_producer> flash_producer_;\r
+ std::shared_ptr<frame_factory> frame_factory_;\r
public:\r
implementation() \r
: flash_producer_(flash_producer(env::template_host())){}\r
void clear()\r
{\r
flash_producer_ = flash_producer(env::template_host());\r
+ flash_producer_->set_parent_printer(parent_printer_);\r
flash_producer_->initialize(safe_ptr<frame_factory>(frame_factory_));\r
}\r
\r
{\r
frame_factory_ = frame_factory;\r
flash_producer_->initialize(frame_factory);\r
+ flash_producer_->set_parent_printer(parent_printer_);\r
+ }\r
+\r
+ void set_parent_printer(const printer& parent_printer) \r
+ {\r
+ parent_printer_ = parent_printer;\r
}\r
\r
std::wstring print() const\r
{\r
return flash_producer_->print();\r
}\r
-\r
- safe_ptr<flash_producer> flash_producer_;\r
- std::shared_ptr<frame_factory> frame_factory_;\r
};\r
\r
safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<channel>& channel, int render_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_factory>& frame_factory){impl_->initialize(frame_factory);}\r
+void cg_producer::set_parent_printer(const printer& parent_printer) { impl_->set_parent_printer(parent_printer);}\r
std::wstring cg_producer::print() const{return impl_->print();}\r
}}}
\ No newline at end of file
\r
virtual safe_ptr<draw_frame> receive();\r
virtual void initialize(const safe_ptr<frame_factory>& frame_factory);\r
+ virtual void set_parent_printer(const printer& parent_printer);\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
co_init(){CoInitialize(nullptr);}\r
~co_init(){CoUninitialize();}\r
} co_;\r
-\r
+ \r
+ printer parent_printer_;\r
const std::wstring filename_;\r
const video_format_desc format_desc_;\r
\r
safe_ptr<diagnostics::graph> graph_;\r
timer perf_timer_;\r
\r
- std::function<std::wstring()> print_;\r
+ std::wstring print()\r
+ {\r
+ return parent_printer_();\r
+ }\r
\r
public:\r
- flash_renderer(const safe_ptr<diagnostics::graph>& graph, const std::shared_ptr<frame_factory>& frame_factory, const std::wstring& filename, const std::function<std::wstring()>& print) \r
- : graph_(graph)\r
+ flash_renderer(const safe_ptr<diagnostics::graph>& graph, const std::shared_ptr<frame_factory>& frame_factory, const std::wstring& filename, const printer& parent_printer) \r
+ : parent_printer_(parent_printer)\r
+ , graph_(graph)\r
, filename_(filename)\r
, format_desc_(frame_factory->get_video_format_desc())\r
, frame_factory_(frame_factory)\r
, hdc_(CreateCompatibleDC(0), DeleteDC)\r
, ax_(nullptr)\r
, head_(draw_frame::empty())\r
- , print_(print)\r
{\r
graph_->guide("frame-time", 0.5f);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f)); \r
graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); \r
\r
if(FAILED(CComObject<caspar::flash::FlashAxContainer>::CreateInstance(&ax_)))\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print_()) + "Failed to create FlashAxContainer"));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + "Failed to create FlashAxContainer"));\r
\r
- ax_->set_print(print_);\r
+ ax_->set_print(parent_printer_);\r
\r
if(FAILED(ax_->CreateAxControl()))\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print_()) + "Failed to Create FlashAxControl"));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + "Failed to Create FlashAxControl"));\r
\r
CComPtr<IShockwaveFlash> spFlash;\r
if(FAILED(ax_->QueryControl(&spFlash)))\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print_()) + "Failed to Query FlashAxControl"));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + "Failed to Query FlashAxControl"));\r
\r
if(FAILED(spFlash->put_Playing(true)) )\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print_()) + "Failed to start playing Flash"));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + "Failed to start playing Flash"));\r
\r
if(FAILED(spFlash->put_Movie(CComBSTR(filename.c_str()))))\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print_()) + "Failed to Load Template Host"));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + "Failed to Load Template Host"));\r
\r
if(FAILED(spFlash->put_ScaleMode(2))) //Exact fit. Scale without respect to the aspect ratio.\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print_()) + "Failed to Set Scale Mode"));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + "Failed to Set Scale Mode"));\r
\r
ax_->SetFormat(format_desc_);\r
\r
\r
bmp_.reset(CreateDIBSection(static_cast<HDC>(hdc_.get()), &info, DIB_RGB_COLORS, reinterpret_cast<void**>(&bmp_data_), 0, 0), DeleteObject);\r
SelectObject(static_cast<HDC>(hdc_.get()), bmp_.get()); \r
- CASPAR_LOG(info) << print() << L" Thread started.";\r
+ CASPAR_LOG(info) << parent_printer_() << L" Thread started.";\r
}\r
\r
~flash_renderer()\r
ax_->DestroyAxControl();\r
ax_->Release();\r
}\r
- CASPAR_LOG(info) << print_() << L" Thread ended.";\r
+ CASPAR_LOG(info) << print() << L" Thread ended.";\r
}\r
\r
void param(const std::wstring& param)\r
{ \r
if(!ax_->FlashCall(param))\r
- CASPAR_LOG(warning) << print_() << " Flash function call failed. Param: " << param << ".";\r
+ CASPAR_LOG(warning) << print() << " Flash function call failed. Param: " << param << ".";\r
graph_->tag("param");\r
}\r
\r
\r
struct flash_producer::implementation\r
{ \r
+ printer parent_printer_;\r
const std::wstring filename_; \r
tbb::atomic<int> fps_;\r
\r
\r
std::wstring print() const\r
{ \r
- return L"flash[" + boost::filesystem::wpath(filename_).filename() + L", " + \r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"flash[" + boost::filesystem::wpath(filename_).filename() + L", " + \r
boost::lexical_cast<std::wstring>(fps_) + \r
(interlaced(fps_, format_desc_) ? L"i" : L"p") + L"]"; \r
} \r
executor_.start();\r
}\r
\r
+ virtual void set_parent_printer(const printer& parent_printer) \r
+ {\r
+ parent_printer_ = parent_printer;\r
+ }\r
+\r
virtual safe_ptr<draw_frame> receive()\r
{ \r
if(!renderer_)\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_factory>& frame_factory) { impl_->initialize(frame_factory);}\r
+void flash_producer::set_parent_printer(const printer& parent_printer){impl_->set_parent_printer(parent_printer);}\r
std::wstring flash_producer::print() const {return impl_->print();}\r
\r
std::wstring flash_producer::find_template(const std::wstring& template_name)\r
\r
virtual safe_ptr<draw_frame> receive();\r
virtual void initialize(const safe_ptr<frame_factory>& frame_factory);\r
+ virtual void set_parent_printer(const printer& parent_printer);\r
virtual std::wstring print() const;\r
\r
void param(const std::wstring& param);\r
#include "../mixer/frame_factory.h"\r
\r
#include <common/memory/safe_ptr.h>\r
+#include <common/utility/printable.h>\r
\r
#include <boost/noncopyable.hpp>\r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual void initialize(const safe_ptr<frame_factory>& frame_factory) = 0;\r
\r
+ virtual void set_parent_printer(const printer& parent_printer) = 0;\r
+\r
static const safe_ptr<frame_producer>& empty() // nothrow\r
{\r
struct empty_frame_producer : public frame_producer\r
virtual safe_ptr<draw_frame> receive(){return draw_frame::empty();}\r
virtual void initialize(const safe_ptr<frame_factory>&){}\r
virtual std::wstring print() const { return L"empty";}\r
+ virtual void set_parent_printer(const printer& parent_printer) {}\r
};\r
static safe_ptr<frame_producer> producer = make_safe<empty_frame_producer>();\r
return producer;\r
#include "layer.h"\r
\r
#include <common/concurrency/executor.h>\r
+#include <common/utility/printable.h>\r
\r
#include <boost/range/algorithm_ext/erase.hpp>\r
#include <boost/lexical_cast.hpp>\r
\r
struct frame_producer_device::implementation : boost::noncopyable\r
{ \r
- std::array<layer, frame_producer_device::MAX_LAYER+1> layers_; \r
+ const printer parent_printer_;\r
+\r
+ std::vector<layer> layers_; \r
\r
tbb::spin_mutex output_mutex_;\r
output_func output_;\r
const safe_ptr<frame_factory> factory_;\r
\r
mutable executor executor_;\r
+\r
public:\r
- implementation(const safe_ptr<frame_factory>& factory, const output_func& output) \r
- : factory_(factory)\r
+ implementation(const safe_ptr<frame_factory>& factory, const output_func& output, const printer& parent_printer) \r
+ : parent_printer_(parent_printer)\r
+ , factory_(factory)\r
, output_(output)\r
{\r
+ for(int n = 0; n < frame_producer_device::MAX_LAYER+1; ++n)\r
+ layers_.push_back(layer(n, parent_printer_));\r
+\r
executor_.start();\r
executor_.begin_invoke([=]{tick();});\r
}\r
\r
void load(size_t index, const safe_ptr<frame_producer>& producer, bool play_on_load)\r
{\r
+ producer->set_parent_printer(std::bind(&layer::print, &layers_.at(index)));\r
producer->initialize(factory_);\r
executor_.invoke([&]\r
{\r
{\r
executor_.invoke([&]\r
{\r
- layers_.at(index) = std::move(layer());\r
+ layers_.at(index) = std::move(layer(index, parent_printer_));\r
});\r
}\r
\r
{\r
executor_.invoke([&]\r
{\r
- for(auto it = layers_.begin(); it != layers_.end(); ++it)\r
- *it = std::move(layer());\r
+ for(size_t n = 0; n < layers_.size(); ++n)\r
+ layers_[n] = layer(n, parent_printer_);\r
});\r
} \r
\r
}\r
};\r
\r
-frame_producer_device::frame_producer_device(const safe_ptr<frame_factory>& factory, const output_func& output) : impl_(new implementation(factory, output)){}\r
+frame_producer_device::frame_producer_device(const safe_ptr<frame_factory>& factory, const output_func& output, const printer& printer) : impl_(new implementation(factory, output, printer)){}\r
frame_producer_device::frame_producer_device(frame_producer_device&& other) : impl_(std::move(other.impl_)){}\r
void frame_producer_device::load(size_t index, const safe_ptr<frame_producer>& producer, bool play_on_load){impl_->load(index, producer, play_on_load);}\r
void frame_producer_device::preview(size_t index, const safe_ptr<frame_producer>& producer){impl_->preview(index, producer);}\r
#include "frame_producer.h"\r
\r
#include <common/memory/safe_ptr.h>\r
+#include <common/utility/printable.h>\r
\r
#include <boost/noncopyable.hpp>\r
#include <boost/thread/future.hpp>\r
\r
typedef std::function<void(const std::vector<safe_ptr<draw_frame>>&)> output_func;\r
\r
- explicit frame_producer_device(const safe_ptr<frame_factory>& factory, const output_func& output);\r
+ explicit frame_producer_device(const safe_ptr<frame_factory>& factory, const output_func& output, const printer& printer);\r
frame_producer_device(frame_producer_device&& other);\r
\r
void load(size_t index, const safe_ptr<frame_producer>& producer, bool play_on_load = false);\r
\r
struct image_producer : public frame_producer\r
{ \r
+ printer parent_printer_;\r
std::shared_ptr<frame_factory> frame_factory_;\r
std::wstring filename_;\r
safe_ptr<draw_frame> frame_;\r
std::copy_n(FreeImage_GetBits(bitmap.get()), frame->image_data().size(), frame->image_data().begin());\r
frame_ = std::move(frame);\r
}\r
+ \r
+ virtual void set_parent_printer(const printer& parent_printer) \r
+ {\r
+ parent_printer_ = parent_printer;\r
+ }\r
\r
virtual std::wstring print() const\r
{\r
- return L"image_producer. filename: " + filename_;\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"image_producer. filename: " + filename_;\r
}\r
};\r
\r
\r
#include <common/concurrency/executor.h>\r
#include <common/utility/assert.h>\r
+#include <common/utility/printable.h>\r
\r
#include <mixer/frame/draw_frame.h>\r
#include <mixer/image/image_mixer.h>\r
\r
void do_remove(safe_ptr<frame_producer>& producer)\r
{\r
+ auto name = producer->print();\r
producer = frame_producer::empty();\r
- CASPAR_LOG(info) << L"frame_remover[" + boost::lexical_cast<std::wstring>(--count_) + L"] removed: " << producer->print();\r
+ CASPAR_LOG(info) << L"async_remover[" + boost::lexical_cast<std::wstring>(--count_) + L"] Removed: " << name << L".";\r
}\r
public:\r
\r
void remove(safe_ptr<frame_producer>&& producer)\r
{\r
CASPAR_ASSERT(producer.unique());\r
- CASPAR_LOG(info) << L"frame_remover[" + boost::lexical_cast<std::wstring>(++count_) + L"] removing: " << producer->print();\r
+ CASPAR_LOG(info) << L"async_remover[" + boost::lexical_cast<std::wstring>(++count_) + L"] Removing: " << producer->print() << L".";\r
executor_.begin_invoke(std::bind(&frame_producer_remover::do_remove, this, std::move(producer)));\r
}\r
};\r
frame_producer_remover g_remover;\r
\r
struct layer::implementation : boost::noncopyable\r
-{ \r
+{ \r
+ printer parent_printer_;\r
safe_ptr<frame_producer> foreground_;\r
safe_ptr<frame_producer> background_;\r
safe_ptr<draw_frame> last_frame_;\r
bool is_paused_;\r
-\r
+ tbb::atomic<int> index_;\r
public:\r
- implementation() \r
- : foreground_(frame_producer::empty())\r
+ implementation(int index, const printer& parent_printer) \r
+ : parent_printer_(parent_printer)\r
+ , foreground_(frame_producer::empty())\r
, background_(frame_producer::empty())\r
, last_frame_(draw_frame::empty())\r
- , is_paused_(false){}\r
+ , is_paused_(false)\r
+ {\r
+ index_ = index;\r
+ }\r
\r
void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
{ \r
{\r
background_->set_leading_producer(foreground_);\r
foreground_ = background_;\r
- CASPAR_LOG(info) << foreground_->print() << L" started";\r
+ CASPAR_LOG(info) << foreground_->print() << L" Started.";\r
background_ = frame_producer::empty();\r
}\r
is_paused_ = false;\r
following->set_leading_producer(foreground_);\r
g_remover.remove(std::move(foreground_));\r
foreground_ = following;\r
- CASPAR_LOG(info) << foreground_->print() << L" started";\r
+ CASPAR_LOG(info) << foreground_->print() << L" Started.";\r
\r
last_frame_ = receive();\r
}\r
}\r
catch(...)\r
{\r
+ CASPAR_LOG(error) << print() << L"Unhandled Exception: ";\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
stop();\r
}\r
\r
return last_frame_;\r
}\r
+ \r
+ std::wstring print() const\r
+ {\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]";\r
+ }\r
};\r
\r
-layer::layer() \r
+layer::layer(int index, const printer& parent_printer) \r
{\r
- impl_ = new implementation();\r
+ impl_ = new implementation(index, parent_printer);\r
}\r
layer::layer(layer&& other) \r
{\r
void layer::swap(layer& other)\r
{\r
impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\r
+ impl_->index_ = other.impl_->index_.compare_and_swap(impl_->index_, other.impl_->index_);\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
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
+std::wstring layer::print() const { return impl_->print();}\r
}}
\ No newline at end of file
#pragma once\r
\r
#include <common/memory/safe_ptr.h>\r
+#include <common/utility/printable.h>\r
\r
#include <boost/noncopyable.hpp>\r
\r
class layer : boost::noncopyable\r
{\r
public:\r
- layer(); // nothrow\r
+ layer(int index, const printer& parent_printer = nullptr); // nothrow\r
layer(layer&& other); // nothrow\r
~layer(); // nothrow\r
layer& operator=(layer&& other); // nothrow\r
safe_ptr<frame_producer> background() const; // nothrow\r
\r
safe_ptr<draw_frame> receive(); // nothrow\r
+\r
+ std::wstring print() const;\r
private:\r
struct implementation;\r
tbb::atomic<implementation*> impl_;\r
\r
struct transition_producer::implementation : boost::noncopyable\r
{ \r
+ printer parent_printer_;\r
unsigned short current_frame_;\r
\r
const transition_info info_;\r
format_desc_ = frame_factory_->get_video_format_desc();\r
}\r
\r
+ virtual void set_parent_printer(const printer& parent_printer) \r
+ {\r
+ dest_producer_->set_parent_printer(std::bind(&implementation::print, this));\r
+ parent_printer_ = parent_printer;\r
+ }\r
+\r
safe_ptr<frame_producer> get_following_producer() const\r
{\r
return dest_producer_;\r
\r
std::wstring print() const\r
{\r
- return L"transition[" + source_producer_->print() + L"->" + dest_producer_->print() + L"]";\r
+ return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"transition[length:" + boost::lexical_cast<std::wstring>(info_.duration) + L"]";\r
}\r
};\r
\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_factory>& frame_factory) { impl_->initialize(frame_factory);}\r
+void transition_producer::set_parent_printer(const printer& parent_printer) {impl_->set_parent_printer(parent_printer);}\r
std::wstring transition_producer::print() const { return impl_->print();}\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_factory>& frame_factory);\r
+ virtual void set_parent_printer(const printer& parent_printer);\r
virtual std::wstring print() const;\r
private:\r
struct implementation;\r
if(format_desc.format == video_format::invalid)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid videomode."));\r
\r
- channels_.push_back(channel(format_desc));\r
+ channels_.push_back(channel(channels_.size(), format_desc));\r
\r
int index = 0;\r
BOOST_FOREACH(auto& xml_consumer, xml_channel.second.get_child("consumers"))\r