/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+* Copyright 2013 Sveriges Television AB http://casparcg.com/\r
*\r
* This file is part of CasparCG (www.casparcg.com).\r
*\r
\r
#include "channel_producer.h"\r
\r
+#include "../../monitor/monitor.h"\r
#include "../../consumer/frame_consumer.h"\r
#include "../../consumer/output.h"\r
#include "../../video_channel.h"\r
#include "../../mixer/read_frame.h"\r
\r
#include <common/exception/exceptions.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/concurrency/future_util.h>\r
\r
#include <tbb/concurrent_queue.h>\r
\r
\r
class channel_consumer : public frame_consumer\r
{ \r
- tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>> frame_buffer_;\r
- core::video_format_desc format_desc_;\r
- int channel_index_;\r
- tbb::atomic<bool> is_running_;\r
+ tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>> frame_buffer_;\r
+ core::video_format_desc format_desc_;\r
+ int channel_index_;\r
+ tbb::atomic<bool> is_running_;\r
+ tbb::atomic<int64_t> current_age_;\r
\r
public:\r
channel_consumer() \r
{\r
is_running_ = true;\r
+ current_age_ = 0;\r
frame_buffer_.set_capacity(3);\r
}\r
\r
\r
// frame_consumer\r
\r
- virtual bool send(const safe_ptr<read_frame>& frame) override\r
+ virtual boost::unique_future<bool> send(const safe_ptr<read_frame>& frame) override\r
{\r
frame_buffer_.try_push(frame);\r
- return is_running_;\r
+ return caspar::wrap_as_future(is_running_.load());\r
}\r
\r
virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
{\r
format_desc_ = format_desc;\r
- channel_index_ = channel_index;\r
+ channel_index_ = channel_index;\r
+ }\r
+\r
+ virtual int64_t presentation_frame_age_millis() const override\r
+ {\r
+ return current_age_;\r
}\r
\r
virtual std::wstring print() const override\r
if(!is_running_)\r
return make_safe<read_frame>();\r
std::shared_ptr<read_frame> frame;\r
- frame_buffer_.try_pop(frame);\r
+ \r
+ if (frame_buffer_.try_pop(frame))\r
+ current_age_ = frame->get_age_millis();\r
+\r
return frame;\r
}\r
};\r
\r
class channel_producer : public frame_producer\r
{\r
+ monitor::subject monitor_subject_;\r
+\r
const safe_ptr<frame_factory> frame_factory_;\r
const safe_ptr<channel_consumer> consumer_;\r
\r
frame_number_++;\r
\r
core::pixel_format_desc desc;\r
- bool double_speed = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - format_desc.fps) < 0.01; \r
- bool half_speed = std::abs(format_desc.fps / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01;\r
+ bool double_speed = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - format_desc.fps) < 0.01; \r
+ bool half_speed = std::abs(format_desc.fps / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01;\r
\r
- if(half_speed && frame_number_ % 2 == 0)\r
+ if(half_speed && frame_number_ % 2 == 0) // Skip frame\r
return receive(0);\r
\r
desc.pix_fmt = core::pixel_format::bgra;\r
desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
auto frame = frame_factory_->create_frame(this, desc);\r
\r
- memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
+ fast_memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
frame->commit();\r
\r
frame_buffer_.push(frame); \r
return L"channel[]";\r
}\r
\r
- boost::property_tree::wptree info() const override\r
+ virtual boost::property_tree::wptree info() const override\r
{\r
boost::property_tree::wptree info;\r
info.add(L"type", L"channel-producer");\r
return info;\r
}\r
+\r
+ monitor::source& monitor_output() \r
+ {\r
+ return monitor_subject_;\r
+ }\r
};\r
\r
safe_ptr<frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<video_channel>& channel)\r
{\r
- return make_safe<channel_producer>(frame_factory, channel);\r
+ return create_producer_print_proxy(\r
+ make_safe<channel_producer>(frame_factory, channel));\r
}\r
\r
}}
\ No newline at end of file