};\r
\r
pixel_buffer_object::pixel_buffer_object(){}\r
+pixel_buffer_object::pixel_buffer_object(pixel_buffer_object&& other) : impl_(std::move(other.impl_)){}\r
pixel_buffer_object::pixel_buffer_object(size_t width, size_t height, GLenum format) \r
: impl_(new implementation(width, height, format)){}\r
+pixel_buffer_object& pixel_buffer_object::operator=(pixel_buffer_object&& other)\r
+{\r
+ impl_ = std::move(other.impl_);\r
+ return *this;\r
+}\r
void pixel_buffer_object::create(size_t width, size_t height, GLenum format)\r
{\r
impl_.reset(new implementation(width, height, format));\r
{\r
public:\r
pixel_buffer_object();\r
+ pixel_buffer_object(pixel_buffer_object&& other);\r
pixel_buffer_object(size_t width, size_t height, GLenum format = GL_BGRA);\r
+ pixel_buffer_object& operator=(pixel_buffer_object&& other);\r
void create(size_t width, size_t height, GLenum format = GL_BGRA);\r
~pixel_buffer_object(){}\r
\r
\r
#define _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line) name##line\r
#define _CASPAR_EXIT_SCOPE_LINENAME(name, line) _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line)\r
-#define CASPAR_SCOPE_EXIT(f) auto _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = caspar::detail::create_scope_exit(f)
\ No newline at end of file
+#define CASPAR_SCOPE_EXIT(f) const auto& _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = caspar::detail::create_scope_exit(f)
\ No newline at end of file
CASPAR_LOG(error) << "BLUECARD ERROR: Failed to disable video output. (device " << device_index_ << TEXT(")"); \r
}\r
\r
- boost::unique_future<void> display(const consumer_frame& frame)\r
- {\r
- return executor_.begin_invoke([=]\r
+ void send(const consumer_frame& frame)\r
+ { \r
+ static size_t audio_samples = 1920;\r
+ static size_t audio_nchannels = 2;\r
+ static std::vector<short> silence(audio_samples*audio_nchannels*2, 0);\r
+\r
+ active_ = executor_.begin_invoke([=]\r
{\r
try\r
{\r
auto hanc = hanc_buffers_.front(); \r
std::rotate(hanc_buffers_.begin(), hanc_buffers_.begin() + 1, hanc_buffers_.end());\r
- \r
- static size_t audio_samples = 1920;\r
- static size_t audio_nchannels = 2;\r
- static std::vector<short> silence(audio_samples*audio_nchannels*2, 0);\r
-\r
\r
unsigned long fieldCount = 0;\r
sdk_->wait_output_video_synch(UPD_FMT_FRAME, fieldCount);\r
});\r
}\r
\r
+ frame_consumer::sync_mode synchronize()\r
+ {\r
+ active_.get();\r
+ return frame_consumer::clock;\r
+ }\r
+\r
+ size_t buffer_depth() const\r
+ {\r
+ return 1;\r
+ }\r
+\r
\r
void encode_hanc(BLUE_UINT32* hanc_data, void* audio_data, size_t audio_samples, size_t audio_nchannels)\r
{ \r
hanc_stream_info_struct hanc_stream_info;\r
memset(&hanc_stream_info, 0, sizeof(hanc_stream_info));\r
\r
- std::fill_n(hanc_stream_info.AudioDBNArray, sizeof(hanc_stream_info.AudioDBNArray)/sizeof(*hanc_stream_info.AudioDBNArray), -1);\r
+ std::fill_n(hanc_stream_info.AudioDBNArray, sizeof(hanc_stream_info.AudioDBNArray)/sizeof(hanc_stream_info.AudioDBNArray[0]), -1);\r
hanc_stream_info.hanc_data_ptr = hanc_data;\r
hanc_stream_info.video_mode = vid_fmt_;\r
\r
} \r
}\r
\r
+ boost::unique_future<void> active_;\r
common::executor executor_;\r
\r
BlueVelvetPtr sdk_;\r
};\r
\r
consumer::consumer(const video_format_desc& format_desc, unsigned int device_index, bool embed_audio) : impl_(new implementation(format_desc, device_index, embed_audio)){} \r
-boost::unique_future<void> consumer::display(const consumer_frame& frame){return impl_->display(frame);}\r
-\r
+void consumer::send(const consumer_frame& frame){impl_->send(frame);}\r
+frame_consumer::sync_mode consumer::synchronize(){return impl_->synchronize();}\r
+size_t consumer::buffer_depth() const{return impl_->buffer_depth();}\r
}}}\r
\r
#endif
\ No newline at end of file
public:\r
consumer(const video_format_desc& format_desc, unsigned int deviceIndex, bool embed_audio = false);\r
\r
- virtual boost::unique_future<void> display(const consumer_frame&); \r
- virtual bool has_sync_clock() const {return true;}\r
+ virtual void send(const consumer_frame&);\r
+ virtual sync_mode synchronize();\r
+ virtual size_t buffer_depth() const;\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
CoUninitialize();\r
}\r
\r
- boost::unique_future<void> display(const consumer_frame& input_frame)\r
+ void send(const consumer_frame& input_frame)\r
{\r
- return executor_.begin_invoke([=]\r
+ active_ = executor_.begin_invoke([=]\r
{\r
- try\r
- {\r
- auto& output_frame = reserved_frames_[current_index_];\r
- current_index_ = (++current_index_) % reserved_frames_.size();\r
+ auto& output_frame = reserved_frames_[current_index_];\r
+ current_index_ = (++current_index_) % reserved_frames_.size();\r
\r
- std::copy(input_frame.data().begin(), input_frame.data().end(), static_cast<char*>(output_frame.first));\r
+ std::copy(input_frame.data().begin(), input_frame.data().end(), static_cast<char*>(output_frame.first));\r
\r
- if(FAILED(output_->DisplayVideoFrameSync(output_frame.second)))\r
- CASPAR_LOG(error) << L"DECKLINK: Failed to display frame.";\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- }\r
+ if(FAILED(output_->DisplayVideoFrameSync(output_frame.second)))\r
+ CASPAR_LOG(error) << L"DECKLINK: Failed to display frame.";\r
});\r
}\r
+ \r
+ frame_consumer::sync_mode synchronize()\r
+ {\r
+ active_.get();\r
+ return frame_consumer::ready;\r
+ }\r
+\r
+ size_t buffer_depth() const\r
+ {\r
+ return 1;\r
+ }\r
\r
+ boost::unique_future<void> active_;\r
common::executor executor_;\r
\r
std::vector<std::pair<void*, CComPtr<IDeckLinkMutableVideoFrame>>> reserved_frames_;\r
video_format_desc format_desc_;\r
};\r
\r
-decklink_consumer::decklink_consumer(const video_format_desc& format_desc, bool internalKey) : pImpl_(new Implementation(format_desc, internalKey))\r
-{}\r
-\r
-boost::unique_future<void> decklink_consumer::display(const consumer_frame& frame)\r
-{\r
- return pImpl_->display(frame);\r
-}\r
+decklink_consumer::decklink_consumer(const video_format_desc& format_desc, bool internalKey) : pImpl_(new Implementation(format_desc, internalKey)){}\r
+void decklink_consumer::send(const consumer_frame& frame){pImpl_->send(frame);}\r
+frame_consumer::sync_mode decklink_consumer::synchronize(){return pImpl_->synchronize();}\r
+size_t decklink_consumer::buffer_depth() const{return pImpl_->buffer_depth();}\r
\r
}}}
\ No newline at end of file
public:\r
explicit decklink_consumer(const video_format_desc& format_desc, bool internalKey = false);\r
\r
- virtual boost::unique_future<void> display(const consumer_frame&);\r
- virtual bool has_sync_clock() const {return false;}\r
+ virtual void send(const consumer_frame&);\r
+ virtual sync_mode synchronize();\r
+ virtual size_t buffer_depth() const;\r
private:\r
struct Implementation;\r
std::tr1::shared_ptr<Implementation> pImpl_;\r
\r
#include <boost/noncopyable.hpp>\r
\r
-#include <boost/thread/future.hpp>\r
-\r
#include <memory>\r
\r
namespace caspar { namespace core {\r
\r
struct frame_consumer : boost::noncopyable\r
{\r
- virtual ~frame_consumer() {}\r
-\r
- virtual boost::unique_future<void> prepare(const consumer_frame&)\r
+ enum sync_mode\r
{\r
- boost::promise<void> promise;\r
- promise.set_value();\r
- return promise.get_future();\r
- }\r
+ ready = 0,\r
+ clock \r
+ };\r
\r
- virtual boost::unique_future<void> display(const consumer_frame&)\r
- {\r
- boost::promise<void> promise;\r
- promise.set_value();\r
- return promise.get_future();\r
- }\r
- virtual bool has_sync_clock() const {return false;}\r
+ virtual ~frame_consumer() {}\r
+\r
+ virtual void send(const consumer_frame&) = 0;\r
+ virtual sync_mode synchronize() = 0;\r
+ virtual size_t buffer_depth() const = 0;\r
};\r
typedef std::shared_ptr<frame_consumer> frame_consumer_ptr;\r
typedef std::shared_ptr<const frame_consumer> frame_consumer_const_ptr;\r
#include <boost/date_time/posix_time/posix_time.hpp>\r
\r
#include <boost/range/algorithm_ext/erase.hpp>\r
+#include <boost/range/algorithm.hpp>\r
\r
namespace caspar { namespace core {\r
\r
-class video_sync_clock\r
+class clock_sync\r
{\r
public:\r
- video_sync_clock(const video_format_desc& format_desc)\r
- {\r
- period_ = static_cast<long>(format_desc.period*1000000.0);\r
- time_ = boost::posix_time::microsec_clock::local_time();\r
- }\r
+ clock_sync() : time_(boost::posix_time::microsec_clock::local_time()){}\r
\r
- void synchronize()\r
- {\r
- auto remaining = boost::posix_time::microseconds(period_) - (boost::posix_time::microsec_clock::local_time() - time_);\r
+ void wait(double period)\r
+ { \r
+ auto remaining = boost::posix_time::microseconds(static_cast<long>(period*1000000.0)) - (boost::posix_time::microsec_clock::local_time() - time_);\r
if(remaining > boost::posix_time::microseconds(5000))\r
boost::this_thread::sleep(remaining - boost::posix_time::microseconds(5000));\r
- time_ = boost::posix_time::microsec_clock::local_time();\r
}\r
private:\r
boost::posix_time::ptime time_;\r
- long period_;\r
};\r
\r
struct frame_consumer_device::implementation\r
public:\r
implementation(const frame_processor_device_ptr& frame_processor, const video_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers) \r
: frame_processor_(frame_processor), consumers_(consumers), fmt_(format_desc)\r
- {\r
- if(consumers.empty())\r
- BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
- << msg_info("frame_consumer_device requires atleast one consumer."));\r
- \r
- needs_clock_ = !std::any_of(consumers.begin(), consumers.end(), std::mem_fn(&frame_consumer::has_sync_clock));\r
- is_running_ = true;\r
+ { \r
+ std::vector<size_t> depths;\r
+ boost::range::transform(consumers_, std::back_inserter(depths), std::mem_fn(&frame_consumer::buffer_depth));\r
+ max_depth_ = *boost::range::max_element(depths);\r
display_thread_ = boost::thread([=]{run();});\r
}\r
\r
\r
void run()\r
{\r
+ is_running_ = true;\r
+ CASPAR_LOG(warning) << "Starting frame_consumer_device."; \r
+\r
win32_exception::install_handler();\r
- \r
- video_sync_clock clock(fmt_);\r
- \r
- while(is_running_)\r
+ \r
+ while(is_running_) \r
{\r
- if(needs_clock_)\r
- clock.synchronize();\r
- \r
- display_frame(frame_processor_->receive()); \r
+ display_frame(frame_processor_->receive()); \r
+ is_running_ = !consumers_.empty();\r
}\r
+ CASPAR_LOG(warning) << "Shutting down frame_consumer_device."; \r
}\r
\r
void display_frame(const consumer_frame& frame)\r
{ \r
- typedef std::vector<std::pair<boost::unique_future<void>, frame_consumer_ptr>> sync_container;\r
- sync_container sync;\r
- boost::range::transform(consumers_, std::back_inserter(sync), [=](const frame_consumer_ptr& consumer)\r
+ buffer_.push_back(frame);\r
+\r
+ clock_sync clock;\r
+ \r
+ boost::range::for_each(consumers_, [&](const frame_consumer_ptr& consumer)\r
{\r
- return std::make_pair(consumer->prepare(frame), consumer);\r
+ size_t offset = max_depth_ - consumer->buffer_depth();\r
+ if(offset < buffer_.size())\r
+ consumer->send(*(buffer_.begin() + offset));\r
});\r
- \r
- prepared_frames_.push_back(frame);\r
- \r
- if(prepared_frames_.size() > 2)\r
- { \r
- boost::range::transform(consumers_, std::back_inserter(sync), [=](const frame_consumer_ptr& consumer)\r
- {\r
- return std::make_pair(consumer->display(prepared_frames_.front()), consumer);\r
- });\r
- prepared_frames_.pop_front();\r
- }\r
-\r
- boost::range::for_each(sync, [=](sync_container::value_type& sync)\r
+ \r
+ frame_consumer::sync_mode sync = frame_consumer::ready;\r
+ boost::range::for_each(consumers_, [&](const frame_consumer_ptr& consumer)\r
{\r
try\r
{\r
- sync.first.get();\r
+ size_t offset = max_depth_ - consumer->buffer_depth();\r
+ if(offset >= buffer_.size())\r
+ return;\r
+\r
+ if(consumer->synchronize() == frame_consumer::clock)\r
+ sync = frame_consumer::clock;\r
}\r
catch(...)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
- boost::range::remove_erase(consumers_, sync.second);\r
+ boost::range::remove_erase(consumers_, consumer);\r
CASPAR_LOG(warning) << "Removed consumer from frame_consumer_device.";\r
- if(consumers_.empty())\r
- {\r
- CASPAR_LOG(warning) << "No consumers available. Shutting down frame_consumer_device.";\r
- is_running_ = false;\r
- }\r
}\r
});\r
+ \r
+ if(sync != frame_consumer::clock)\r
+ clock.wait(fmt_.period);\r
+\r
+ if(buffer_.size() >= max_depth_)\r
+ buffer_.pop_front();\r
}\r
\r
- std::deque<consumer_frame> prepared_frames_;\r
+ size_t max_depth_;\r
+ std::deque<consumer_frame> buffer_;\r
\r
- boost::thread display_thread_;\r
-\r
tbb::atomic<bool> is_running_;\r
+ boost::thread display_thread_;\r
\r
- bool needs_clock_;\r
std::vector<frame_consumer_ptr> consumers_;\r
+ \r
+ frame_processor_device_ptr frame_processor_;\r
\r
const video_format_desc& fmt_;\r
-\r
- frame_processor_device_ptr frame_processor_;\r
};\r
\r
frame_consumer_device::frame_consumer_device(const frame_processor_device_ptr& frame_processor, const video_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers)\r
implementation() : container_(5), underrun_count_(0)\r
{\r
sf::SoundStream::Initialize(2, 48000);\r
+ tickets_.set_capacity(3);\r
}\r
\r
~implementation()\r
Stop();\r
}\r
\r
- boost::unique_future<void> push(const consumer_frame& frame)\r
- {\r
+ void send(const consumer_frame& frame)\r
+ { \r
input_.push(frame.audio_data()); \r
\r
- auto promise = std::make_shared<boost::promise<void>>();\r
- \r
- if(GetStatus() != Playing && input_.size() > 2)\r
- Play();\r
- \r
- if(GetStatus() == Playing)\r
- promises_.push(promise);\r
- else\r
- promise->set_value();\r
+ if(GetStatus() != Playing && input_.size() > 2) \r
+ Play(); \r
+ }\r
\r
- return promise->get_future();\r
+ frame_consumer::sync_mode synchronize()\r
+ {\r
+ tickets_.push(true);\r
+ return frame_consumer::clock;\r
+ }\r
+\r
+ size_t buffer_depth() const\r
+ {\r
+ return 3;\r
}\r
\r
bool OnStart() \r
{\r
static std::vector<short> silence(1920*2, 0);\r
\r
- std::shared_ptr<boost::promise<void>> promise;\r
- promises_.pop(promise);\r
- promise->set_value();\r
+ bool dummy;\r
+ tickets_.pop(dummy);\r
\r
std::vector<short> audio_data; \r
if(!input_.try_pop(audio_data))\r
return true;\r
}\r
\r
- tbb::concurrent_bounded_queue<std::shared_ptr<boost::promise<void>>> promises_;\r
+ tbb::concurrent_bounded_queue<bool> tickets_;\r
tbb::concurrent_bounded_queue<std::vector<short>> input_;\r
\r
long underrun_count_;\r
};\r
\r
consumer::consumer(const video_format_desc&) : impl_(new implementation()){}\r
-boost::unique_future<void> consumer::prepare(const consumer_frame& frame){return impl_->push(frame);}\r
+void consumer::send(const consumer_frame& frame){impl_->send(frame);}\r
+frame_consumer::sync_mode consumer::synchronize(){return impl_->synchronize();}\r
+size_t consumer::buffer_depth() const{return impl_->buffer_depth();}\r
}}}\r
public: \r
explicit consumer(const video_format_desc& format_desc);\r
\r
- virtual boost::unique_future<void> prepare(const consumer_frame& frame);\r
- virtual bool has_sync_clock() const {return true;}\r
+ virtual void send(const consumer_frame&);\r
+ virtual sync_mode synchronize();\r
+ virtual size_t buffer_depth() const;\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
#include "ogl_consumer.h"\r
\r
#include "../../format/video_format.h"\r
-#include "../../processor/write_frame.h"\r
+\r
#include "../../../common/gl/utility.h"\r
#include "../../../common/gl/pixel_buffer_object.h"\r
#include "../../../common/concurrency/executor.h"\r
struct consumer::implementation : boost::noncopyable\r
{ \r
implementation(const video_format_desc& format_desc, unsigned int screen_index, stretch stretch, bool windowed) \r
- : index_(0), format_desc_(format_desc), stretch_(stretch), screen_width_(0), screen_height_(0), windowed_(windowed)\r
+ : format_desc_(format_desc), stretch_(stretch), screen_width_(0), screen_height_(0), windowed_(windowed)\r
{ \r
#ifdef _WIN32\r
DISPLAY_DEVICE dDevice; \r
}\r
\r
void render(const consumer_frame& frame)\r
- { \r
- index_ = (index_ + 1) % 2;\r
- int next_index = (index_ + 1) % 2;\r
- \r
- auto ptr = pbos_[index_].end_write();\r
+ { \r
+ auto ptr = pbos_.front().end_write();\r
std::copy_n(frame.data().begin(), frame.data().size(), reinterpret_cast<char*>(ptr));\r
\r
GL(glClear(GL_COLOR_BUFFER_BIT)); \r
- pbos_[next_index].bind_texture(); \r
+ pbos_.back().bind_texture(); \r
glBegin(GL_QUADS);\r
glTexCoord2f(0.0f, hratio_); glVertex2f(-wSize_, -hSize_);\r
glTexCoord2f(wratio_, hratio_); glVertex2f( wSize_, -hSize_);\r
glTexCoord2f(0.0f, 0.0f); glVertex2f(-wSize_, hSize_);\r
glEnd();\r
\r
- pbos_[next_index].begin_write();\r
+ pbos_.back().begin_write();\r
+\r
+ std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
}\r
- \r
- boost::unique_future<void> display(const consumer_frame& frame)\r
+ \r
+ void send(const consumer_frame& frame)\r
{\r
- return executor_.begin_invoke([=]\r
+ active_ = executor_.begin_invoke([=]\r
{\r
sf::Event e;\r
while(window_.GetEvent(e)){}\r
});\r
}\r
\r
+ frame_consumer::sync_mode synchronize()\r
+ {\r
+ active_.get();\r
+ return frame_consumer::ready;\r
+ }\r
+\r
+ size_t buffer_depth() const\r
+ {\r
+ return 2;\r
+ }\r
+ \r
+ boost::unique_future<void> active_;\r
common::executor executor_;\r
\r
float wratio_;\r
float wSize_;\r
float hSize_;\r
\r
- int index_;\r
- common::gl::pixel_buffer_object pbos_[2];\r
+ std::array<common::gl::pixel_buffer_object, 2> pbos_;\r
\r
bool windowed_;\r
unsigned int screen_width_;\r
\r
consumer::consumer(const video_format_desc& format_desc, unsigned int screen_index, stretch stretch, bool windowed)\r
: impl_(new implementation(format_desc, screen_index, stretch, windowed)){}\r
-boost::unique_future<void> consumer::display(const consumer_frame& frame){return impl_->display(frame);}\r
+void consumer::send(const consumer_frame& frame){impl_->send(frame);}\r
+frame_consumer::sync_mode consumer::synchronize(){return impl_->synchronize();}\r
+size_t consumer::buffer_depth() const{return impl_->buffer_depth();}\r
}}}\r
public: \r
explicit consumer(const video_format_desc& format_desc, unsigned int screen_index = 0, stretch stretch = stretch::fill, bool windowed = false);\r
\r
- virtual boost::unique_future<void> display(const consumer_frame& frame);\r
- virtual bool has_sync_clock() const {return false;}\r
+ virtual void send(const consumer_frame&);\r
+ virtual sync_mode synchronize();\r
+ virtual size_t buffer_depth() const;\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
if(frame == nullptr)\r
return nullptr;\r
\r
+ read_frame_ptr result;\r
try\r
{\r
drawing_ = writing_;\r
writing_ = frame;\r
- \r
- // Write from page-locked system memory to video memory.\r
- writing_->begin_write();\r
- \r
- // Map video memory to page-locked system memory.\r
- reading_->end_read(); // Note: This frame has already been sent, it is assumed that there is external buffering of atleast 2 frames.\r
- \r
- // Clear framebuffer.\r
- GL(glClear(GL_COLOR_BUFFER_BIT)); \r
-\r
- // Draw to framebuffer\r
+ \r
+ writing_->begin_write(); // Note: end_write is done when returned to pool, write_frame::reset();\r
+ \r
+ reading_->end_read();\r
+ result = reading_; \r
+ \r
+ GL(glClear(GL_COLOR_BUFFER_BIT));\r
+ \r
drawing_->draw(shader_);\r
\r
- // Create an output frame\r
reading_ = create_output_frame();\r
\r
- // Read from framebuffer into page-locked memory.\r
reading_->begin_read();\r
reading_->audio_data() = std::move(drawing_->audio_data());\r
- \r
- // Return frames to pool.\r
- // Note: end_write is done in writing_fram::reset();\r
+ \r
drawing_ = nullptr;\r
}\r
catch(...)\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
}\r
\r
- return reading_;\r
+ return result;\r
}\r
\r
read_frame_ptr create_output_frame()\r
public:\r
explicit color_producer(const std::wstring& color) : color_str_(color), color_value_(get_pixel_color_value(color)){}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{ \r
return frame_;\r
}\r
video_transformer_->initialize(frame_processor);\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{\r
while(ouput_channel_.empty() && !input_->is_eof())\r
{ \r
virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Movie( \r
/* [in] */ BSTR pVal) = 0;\r
\r
- virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE render_frameNum( \r
+ virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE receiveNum( \r
/* [retval][out] */ long *pVal) = 0;\r
\r
virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_FrameNum( \r
IShockwaveFlash * This,\r
/* [in] */ BSTR pVal);\r
\r
- /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *render_frameNum )( \r
+ /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *receiveNum )( \r
IShockwaveFlash * This,\r
/* [retval][out] */ long *pVal);\r
\r
#define IShockwaveFlash_put_Movie(This,pVal) \\r
(This)->lpVtbl -> put_Movie(This,pVal)\r
\r
-#define IShockwaveFlash_render_frameNum(This,pVal) \\r
- (This)->lpVtbl -> render_frameNum(This,pVal)\r
+#define IShockwaveFlash_receiveNum(This,pVal) \\r
+ (This)->lpVtbl -> receiveNum(This,pVal)\r
\r
#define IShockwaveFlash_put_FrameNum(This,pVal) \\r
(This)->lpVtbl -> put_FrameNum(This,pVal)\r
DWORD *_pdwStubPhase);\r
\r
\r
-/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_render_frameNum_Proxy( \r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_receiveNum_Proxy( \r
IShockwaveFlash * This,\r
/* [retval][out] */ long *pVal);\r
\r
\r
-void __RPC_STUB IShockwaveFlash_render_frameNum_Stub(\r
+void __RPC_STUB IShockwaveFlash_receiveNum_Stub(\r
IRpcStubBuffer *This,\r
IRpcChannelBuffer *_pRpcChannelBuffer,\r
PRPC_MESSAGE _pRpcMessage,\r
flash_producer_->param(param.str());\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{\r
- return flash_producer_ ? flash_producer_->render_frame() : nullptr;\r
+ return flash_producer_ ? flash_producer_->receive() : nullptr;\r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
}\r
\r
cg_producer::cg_producer() : impl_(new implementation()){}\r
-gpu_frame_ptr cg_producer::render_frame(){return impl_->render_frame();}\r
+gpu_frame_ptr cg_producer::receive(){return impl_->receive();}\r
void cg_producer::clear(){impl_->clear();}\r
void cg_producer::add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, template_name, play_on_load, startFromLabel, data);}\r
void cg_producer::remove(int layer){impl_->remove(layer);}\r
\r
cg_producer();\r
\r
- virtual gpu_frame_ptr render_frame();\r
+ virtual gpu_frame_ptr receive();\r
virtual void initialize(const frame_processor_device_ptr& frame_processor);\r
\r
void clear();\r
{\r
ct_producer(const std::wstring& filename) : filename_(filename), initialized_(false){}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{\r
if(!initialized_)\r
{\r
cg_producer::add(0, filename_, 1);\r
initialized_ = true;\r
}\r
- return cg_producer::render_frame();\r
+ return cg_producer::receive();\r
}\r
\r
std::wstring print() const\r
gpu_frame_ptr result;\r
\r
if(is_progressive) \r
- result = do_render_frame(); \r
+ result = do_receive(); \r
else\r
{\r
- gpu_frame_ptr frame1 = do_render_frame();\r
- gpu_frame_ptr frame2 = do_render_frame();\r
+ gpu_frame_ptr frame1 = do_receive();\r
+ gpu_frame_ptr frame2 = do_receive();\r
result = composite_frame::interlace(frame1, frame2, format_desc.mode);\r
}\r
\r
}\r
}\r
\r
- gpu_frame_ptr do_render_frame()\r
+ gpu_frame_ptr do_receive()\r
{\r
auto format_desc = frame_processor_->get_video_format_desc();\r
\r
return frame;\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{ \r
return (frame_buffer_.try_pop(last_frame_) || !is_empty_) && last_frame_ ? last_frame_ : empty_;\r
}\r
};\r
\r
flash_producer::flash_producer(const std::wstring& filename) : impl_(new implementation(this, filename)){}\r
-gpu_frame_ptr flash_producer::render_frame(){return impl_->render_frame();}\r
+gpu_frame_ptr flash_producer::receive(){return impl_->receive();}\r
void flash_producer::param(const std::wstring& param){impl_->param(param);}\r
void flash_producer::initialize(const frame_processor_device_ptr& frame_processor) { impl_->initialize(frame_processor);}\r
std::wstring flash_producer::print() const {return impl_->print();}\r
\r
flash_producer(const std::wstring& filename);\r
\r
- virtual gpu_frame_ptr render_frame();\r
+ virtual gpu_frame_ptr receive();\r
virtual void initialize(const frame_processor_device_ptr& frame_processor);\r
virtual std::wstring print() const;\r
\r
virtual ~frame_producer(){} \r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
- /// \fn virtual gpu_frame_ptr :::render_frame() = 0;\r
+ /// \fn virtual gpu_frame_ptr :::receive() = 0;\r
///\r
/// \brief Renders a frame.\r
/// \r
///\r
/// \return The frame. \r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
- virtual gpu_frame_ptr render_frame() = 0;\r
+ virtual gpu_frame_ptr receive() = 0;\r
\r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
/// \fn virtual std::shared_ptr<frame_producer> :::get_following_producer() const\r
\r
namespace caspar { namespace core {\r
\r
-std::vector<gpu_frame_ptr> render_frames(std::map<int, layer>& layers)\r
+std::vector<gpu_frame_ptr> receives(std::map<int, layer>& layers)\r
{ \r
std::vector<gpu_frame_ptr> frames(layers.size(), nullptr);\r
tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()), \r
auto it = layers.begin();\r
std::advance(it, r.begin());\r
for(size_t i = r.begin(); i != r.end(); ++i, ++it)\r
- frames[i] = it->second.render_frame();\r
+ frames[i] = it->second.receive();\r
}); \r
return frames;\r
}\r
std::vector<gpu_frame_ptr> frames;\r
{\r
tbb::mutex::scoped_lock lock(layers_mutex_); \r
- frames = render_frames(layers_);\r
+ frames = receives(layers_);\r
} \r
frame_processor_->send(std::make_shared<composite_frame>(frames));\r
}\r
{\r
image_producer(const std::wstring& filename) : filename_(filename) {}\r
\r
- gpu_frame_ptr render_frame(){return frame_;}\r
+ gpu_frame_ptr receive(){return frame_;}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
{\r
std::copy_n(&pBits[i* width * 4], width * 4, &image_.get()[i * image_width_ * 4]);\r
}\r
\r
- gpu_frame_ptr do_render_frame()\r
+ gpu_frame_ptr do_receive()\r
{\r
auto frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height);\r
std::fill(frame->data().begin(), frame->data().end(), 0);\r
return frame;\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{ \r
if(format_desc_.mode != video_mode::progressive) \r
{\r
gpu_frame_ptr frame1;\r
gpu_frame_ptr frame2;\r
- tbb::parallel_invoke([&]{ frame1 = do_render_frame(); }, [&]{ frame2 = do_render_frame(); });\r
+ tbb::parallel_invoke([&]{ frame1 = do_receive(); }, [&]{ frame2 = do_receive(); });\r
return composite_frame::interlace(frame1, frame2, format_desc_.mode);\r
} \r
\r
- return render_frame(); \r
+ return receive(); \r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
if(option == load_option::preview) \r
{\r
foreground_ = nullptr; \r
- last_frame_ = frame_producer->render_frame();\r
+ last_frame_ = frame_producer->receive();\r
}\r
else if(option == load_option::auto_play)\r
play(); \r
last_frame_ = nullptr;\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{ \r
if(!foreground_ || is_paused_)\r
return last_frame_;\r
\r
try\r
{\r
- last_frame_ = foreground_->render_frame();\r
+ last_frame_ = foreground_->receive();\r
\r
if(last_frame_ == nullptr)\r
{\r
auto following = foreground_->get_following_producer();\r
following->set_leading_producer(foreground_);\r
foreground_ = following;\r
- last_frame_ = render_frame();\r
+ last_frame_ = receive();\r
}\r
}\r
catch(...)\r
void layer::pause(){impl_->pause();}\r
void layer::stop(){impl_->stop();}\r
void layer::clear(){impl_->clear();}\r
-gpu_frame_ptr layer::render_frame() {return impl_->render_frame();}\r
+gpu_frame_ptr layer::receive() {return impl_->receive();}\r
frame_producer_ptr layer::foreground() const { return impl_->foreground_;}\r
frame_producer_ptr layer::background() const { return impl_->background_;}\r
}}
\ No newline at end of file
\r
#include "../producer/frame_producer.h"\r
\r
+#include <boost/noncopyable.hpp>\r
+\r
namespace caspar { namespace core {\r
\r
struct load_option\r
};\r
};\r
\r
-class layer\r
+class layer : boost::noncopyable\r
{\r
- layer(const layer& other);\r
- layer& operator=(const layer& other);\r
public:\r
layer();\r
layer(layer&& other);\r
frame_producer_ptr foreground() const;\r
frame_producer_ptr background() const;\r
\r
- gpu_frame_ptr render_frame();\r
+ gpu_frame_ptr receive();\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
org_source_producer_ = source_producer_ = producer;\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr receive()\r
{\r
if(current_frame_ == 0)\r
CASPAR_LOG(info) << "Transition started.";\r
\r
tbb::parallel_invoke\r
(\r
- [&]{dest = render_frame(dest_producer_);},\r
- [&]{source = render_frame(source_producer_);}\r
+ [&]{dest = receive(dest_producer_);},\r
+ [&]{source = receive(source_producer_);}\r
);\r
\r
return compose(dest, source);\r
return result;\r
}\r
\r
- gpu_frame_ptr render_frame(frame_producer_ptr& producer)\r
+ gpu_frame_ptr receive(frame_producer_ptr& producer)\r
{\r
if(!producer)\r
return nullptr;\r
gpu_frame_ptr frame;\r
try\r
{\r
- frame = producer->render_frame();\r
+ frame = producer->receive();\r
}\r
catch(...)\r
{\r
producer = nullptr;\r
}\r
\r
- return render_frame(producer);\r
+ return receive(producer);\r
}\r
return frame;\r
}\r
};\r
\r
transition_producer::transition_producer(const frame_producer_ptr& dest, const transition_info& info) : impl_(new implementation(dest, info)){}\r
-gpu_frame_ptr transition_producer::render_frame(){return impl_->render_frame();}\r
+gpu_frame_ptr transition_producer::receive(){return impl_->receive();}\r
frame_producer_ptr transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
void transition_producer::set_leading_producer(const frame_producer_ptr& producer) { impl_->set_leading_producer(producer); }\r
void transition_producer::initialize(const frame_processor_device_ptr& frame_processor) { impl_->initialize(frame_processor);}\r
public:\r
transition_producer(const frame_producer_ptr& destination, const transition_info& info);\r
\r
- gpu_frame_ptr render_frame();\r
+ gpu_frame_ptr receive();\r
\r
frame_producer_ptr get_following_producer() const;\r
void set_leading_producer(const frame_producer_ptr& producer);\r