#include <boost/assign.hpp>\r
#include <boost/filesystem.hpp>\r
#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm.hpp>\r
\r
#include <GLee.h>\r
\r
{ \r
encode_hanc(reinterpret_cast<BLUE_UINT32*>(hanc->data()), frame_audio_data.data(), audio_samples, audio_nchannels);\r
\r
- sdk_->system_buffer_write_async(frame->data(), \r
- frame->size(), \r
+ sdk_->system_buffer_write_async(frame->data().begin(), \r
+ frame->data().size(), \r
nullptr, \r
BlueImage_HANC_DMABuffer(current_id_, BLUE_DATA_IMAGE));\r
\r
}\r
else\r
{\r
- sdk_->system_buffer_write_async(frame->data(),\r
- frame->size(), \r
+ sdk_->system_buffer_write_async(frame->data().begin(),\r
+ frame->data().size(), \r
nullptr, \r
BlueImage_DMABuffer(current_id_, BLUE_DATA_IMAGE));\r
\r
if(frame != NULL) \r
{\r
std::shared_ptr<DecklinkVideoFrame> pTempFrame = GetReservedFrame();\r
- if(pTempFrame && frame->size() == pTempFrame->size())\r
+ if(pTempFrame && frame->data().size() == pTempFrame->size())\r
{\r
- memcpy(pTempFrame->data(), frame->data(), pTempFrame->size());\r
+ std::copy(frame->data().begin(), frame->data().end(), pTempFrame->data());\r
DoRender(pTempFrame);\r
}\r
else\r
int next_index = (index_ + 1) % 2;\r
\r
auto ptr = pbos_[index_].end_write();\r
- memcpy(ptr, frame->data(), format_desc_.size);\r
+ memcpy(ptr, frame->data().begin(), frame->data().size());\r
\r
GL(glClear(GL_COLOR_BUFFER_BIT)); \r
pbos_[next_index].bind_texture(); \r
size_t channels;\r
};\r
\r
- pixel_format_desc() : pix_fmt(pixel_format::invalid)\r
- {\r
- std::fill(planes.begin(), planes.end(), plane());\r
- }\r
+ pixel_format_desc() : pix_fmt(pixel_format::invalid){}\r
\r
pixel_format::type pix_fmt;\r
- std::array<plane, 4> planes;\r
+ std::vector<plane> planes;\r
};\r
\r
size_t hash(const pixel_format_desc& desc);\r
\r
struct composite_frame::implementation : boost::noncopyable\r
{ \r
- implementation(composite_frame* self, const std::vector<frame_ptr>& frames) : self_(self), frames_(frames)\r
+ implementation(composite_frame* self, const std::vector<frame_ptr>& frames) : self_(self)\r
{\r
+ boost::range::transform(frames, std::back_inserter(frames_), std::static_pointer_cast<internal_frame, frame>);\r
prepare();\r
}\r
\r
implementation(composite_frame* self, const frame_ptr& frame1, const frame_ptr& frame2) : self_(self)\r
{\r
- frames_.push_back(frame1);\r
- frames_.push_back(frame2);\r
+ frames_.push_back(std::static_pointer_cast<internal_frame>(frame1));\r
+ frames_.push_back(std::static_pointer_cast<internal_frame>(frame2));\r
prepare();\r
}\r
\r
[&](const tbb::blocked_range<size_t>& r)\r
{\r
for(size_t n = r.begin(); n < r.end(); ++n)\r
- self_->get_audio_data()[n] = static_cast<short>( static_cast<int>(self_->get_audio_data()[n]) + static_cast<int>(frame->get_audio_data()[n]) & 0xFFFF); \r
+ self_->get_audio_data()[n] = static_cast<short>(static_cast<int>(self_->get_audio_data()[n]) + static_cast<int>(frame->get_audio_data()[n]) & 0xFFFF); \r
}\r
);\r
}\r
\r
void begin_write()\r
{\r
- boost::range::for_each(frames_, std::mem_fn(&frame::begin_write)); \r
+ boost::range::for_each(frames_, std::mem_fn(&internal_frame::begin_write)); \r
}\r
\r
void end_write()\r
{\r
- boost::range::for_each(frames_, std::mem_fn(&frame::end_write)); \r
+ boost::range::for_each(frames_, std::mem_fn(&internal_frame::end_write)); \r
}\r
\r
void begin_read()\r
{ \r
- boost::range::for_each(frames_, std::mem_fn(&frame::begin_read)); \r
+ boost::range::for_each(frames_, std::mem_fn(&internal_frame::begin_read)); \r
}\r
\r
void end_read()\r
{\r
- boost::range::for_each(frames_, std::mem_fn(&frame::end_read)); \r
+ boost::range::for_each(frames_, std::mem_fn(&internal_frame::end_read)); \r
}\r
\r
void draw(frame_shader& shader)\r
{\r
glPushMatrix();\r
glTranslated(self_->get_render_transform().pos.get<0>()*2.0, self_->get_render_transform().pos.get<1>()*2.0, 0.0);\r
- boost::range::for_each(frames_, std::bind(&frame::draw, std::placeholders::_1, shader));\r
+ boost::range::for_each(frames_, std::bind(&internal_frame::draw, std::placeholders::_1, shader));\r
glPopMatrix();\r
}\r
\r
composite_frame* self_;\r
- std::vector<frame_ptr> frames_;\r
+ std::vector<internal_frame_ptr> frames_;\r
};\r
\r
#if defined(_MSC_VER)\r
#pragma warning (disable : 4355) // 'this' : used in base member initializer list\r
#endif\r
\r
-composite_frame::composite_frame(const std::vector<frame_ptr>& frames) : frame(pixel_format_desc()), impl_(new implementation(this, frames)){}\r
-composite_frame::composite_frame(const frame_ptr& frame1, const frame_ptr& frame2) : frame(pixel_format_desc()), impl_(new implementation(this, frame1, frame2)){}\r
+composite_frame::composite_frame(const std::vector<frame_ptr>& frames) : internal_frame(pixel_format_desc()), impl_(new implementation(this, frames)){}\r
+composite_frame::composite_frame(const frame_ptr& frame1, const frame_ptr& frame2) : internal_frame(pixel_format_desc()), impl_(new implementation(this, frame1, frame2)){}\r
void composite_frame::begin_write(){impl_->begin_write();}\r
void composite_frame::end_write(){impl_->end_write();} \r
void composite_frame::begin_read(){impl_->begin_read();}\r
\r
namespace caspar { namespace core {\r
\r
-class composite_frame : public frame\r
+class composite_frame : public internal_frame\r
{\r
public:\r
composite_frame(const std::vector<frame_ptr>& container);\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
-typedef std::shared_ptr<composite_frame> gpu_composite_frame_ptr;\r
+typedef std::shared_ptr<composite_frame> composite_frame_ptr;\r
\r
}}
\ No newline at end of file
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
\r
-struct frame::implementation : boost::noncopyable\r
+struct internal_frame::implementation : boost::noncopyable\r
{\r
implementation(const pixel_format_desc& desc) : desc_(desc)\r
{ \r
std::vector<short> audio_data_;\r
\r
const pixel_format_desc desc_;\r
- frame::render_transform transform_;\r
+ internal_frame::render_transform transform_;\r
};\r
-frame::frame(const pixel_format_desc& desc) : impl_(new implementation(desc)){}\r
-void frame::draw(frame_shader& shader){impl_->draw(shader);}\r
-void frame::begin_write(){impl_->begin_write();}\r
-void frame::end_write(){impl_->end_write();} \r
-void frame::begin_read(){impl_->begin_read();}\r
-void frame::end_read(){impl_->end_read();}\r
-unsigned char* frame::data(size_t index){return impl_->data(index);}\r
-size_t frame::size(size_t index) const { return impl_->desc_.planes[index].size; }\r
-std::vector<short>& frame::get_audio_data() { return impl_->audio_data_; }\r
-const std::vector<short>& frame::get_audio_data() const { return const_cast<frame*>(this)->get_audio_data(); }\r
-void frame::reset(){impl_->reset();}\r
-frame::render_transform& frame::get_render_transform() { return impl_->transform_;}\r
-const frame::render_transform& frame::get_render_transform() const { return const_cast<frame*>(this)->get_render_transform();}\r
+ \r
+std::shared_ptr<frame>& frame::empty()\r
+{\r
+ static auto empty_frame = std::shared_ptr<frame>(new internal_frame(pixel_format_desc()));\r
+ return empty_frame;\r
+}\r
+\r
+internal_frame::internal_frame(const pixel_format_desc& desc) : impl_(new implementation(desc)){}\r
+void internal_frame::draw(frame_shader& shader){impl_->draw(shader);}\r
+void internal_frame::begin_write(){impl_->begin_write();}\r
+void internal_frame::end_write(){impl_->end_write();} \r
+void internal_frame::begin_read(){impl_->begin_read();}\r
+void internal_frame::end_read(){impl_->end_read();}\r
+boost::iterator_range<unsigned char*> internal_frame::data(size_t index)\r
+{\r
+ auto ptr = static_cast<unsigned char*>(impl_->pixel_data_[index]);\r
+ return boost::iterator_range<unsigned char*>(ptr, ptr+impl_->desc_.planes[index].size);\r
+}\r
+\r
+std::vector<short>& internal_frame::get_audio_data() { return impl_->audio_data_; }\r
+void internal_frame::reset(){impl_->reset();}\r
+internal_frame::render_transform& internal_frame::get_render_transform() { return impl_->transform_;}\r
}}
\ No newline at end of file
\r
#include <boost/noncopyable.hpp>\r
#include <boost/tuple/tuple.hpp>\r
+#include <boost/range/iterator_range.hpp>\r
\r
#include <vector>\r
\r
\r
virtual ~frame(){}\r
\r
- virtual unsigned char* data(size_t index = 0);\r
- virtual size_t size(size_t index = 0) const;\r
+ virtual boost::iterator_range<unsigned char*> data(size_t index = 0) = 0;\r
\r
- virtual std::vector<short>& get_audio_data();\r
- const std::vector<short>& get_audio_data() const;\r
+ virtual std::vector<short>& get_audio_data() = 0;\r
+ const std::vector<short>& get_audio_data() const { const_cast<frame*>(this)->get_audio_data();}\r
\r
- virtual render_transform& get_render_transform();\r
- const render_transform& get_render_transform() const;\r
+ virtual render_transform& get_render_transform() = 0;\r
+ const render_transform& get_render_transform() const { const_cast<frame*>(this)->get_render_transform();}\r
\r
- static std::shared_ptr<frame>& empty()\r
- {\r
- static auto empty_frame = std::shared_ptr<frame>(new frame(pixel_format_desc()));\r
- return empty_frame;\r
- }\r
-\r
-protected:\r
- frame(const pixel_format_desc& desc);\r
+ static std::shared_ptr<frame>& empty();\r
+};\r
+typedef std::shared_ptr<frame> frame_ptr;\r
+ \r
+class internal_frame : public frame\r
+{\r
+public:\r
+ internal_frame(const pixel_format_desc& desc);\r
+ \r
+ virtual boost::iterator_range<unsigned char*> data(size_t index = 0);\r
\r
- friend class frame_processor_device;\r
- friend class frame_renderer;\r
+ virtual std::vector<short>& get_audio_data();\r
+ virtual core::frame::render_transform& get_render_transform();\r
\r
virtual void reset();\r
\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
-typedef std::shared_ptr<frame> frame_ptr;\r
- \r
+typedef std::shared_ptr<internal_frame> internal_frame_ptr;\r
+\r
+\r
}}
\ No newline at end of file
\r
frame_ptr create_frame(const pixel_format_desc& desc)\r
{\r
- tbb::concurrent_bounded_queue<frame_ptr>* pool = &frame_pools_[desc];\r
+ auto pool = &frame_pools_[desc];\r
\r
- frame_ptr my_frame;\r
+ internal_frame_ptr my_frame;\r
if(!pool->try_pop(my_frame)) \r
- my_frame = executor_.invoke([&]{return std::shared_ptr<frame>(new frame(desc));}); \r
+ my_frame = executor_.invoke([&]{return std::shared_ptr<internal_frame>(new internal_frame(desc));}); \r
\r
- return frame_ptr(my_frame.get(), [=](frame*)\r
+ return internal_frame_ptr(my_frame.get(), [=](frame*)\r
{\r
executor_.begin_invoke([=]\r
{\r
if(input_frame == nullptr)\r
return;\r
\r
- auto future = executor_.begin_invoke([=]{return renderer_->render(input_frame);}); \r
+ auto future = executor_.begin_invoke([=]{return renderer_->render(std::static_pointer_cast<internal_frame>(input_frame));}); \r
output_.push(std::move(future)); // Blocks\r
}\r
\r
void receive(frame_ptr& output_frame)\r
{\r
- boost::shared_future<frame_ptr> future;\r
+ boost::shared_future<internal_frame_ptr> future;\r
\r
if(!output_.try_pop(future))\r
{\r
\r
std::unique_ptr<frame_renderer> renderer_;\r
\r
- tbb::concurrent_bounded_queue<boost::shared_future<frame_ptr>> output_; \r
- tbb::concurrent_unordered_map<pixel_format_desc, tbb::concurrent_bounded_queue<frame_ptr>, std::hash<pixel_format_desc>> frame_pools_;\r
+ tbb::concurrent_bounded_queue<boost::shared_future<internal_frame_ptr>> output_; \r
+ tbb::concurrent_unordered_map<pixel_format_desc, tbb::concurrent_bounded_queue<internal_frame_ptr>, std::hash<pixel_format_desc>> frame_pools_;\r
\r
video_format_desc fmt_;\r
long underrun_count_;\r
// Create bgra frame\r
pixel_format_desc desc;\r
desc.pix_fmt = pixel_format::bgra;\r
- desc.planes[0] = pixel_format_desc::plane(width, height, 4);\r
+ desc.planes.push_back(pixel_format_desc::plane(width, height, 4));\r
return create_frame(desc);\r
}\r
\r
// Create bgra frame with output resolution\r
pixel_format_desc desc;\r
desc.pix_fmt = pixel_format::bgra;\r
- desc.planes[0] = pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4);\r
+ desc.planes.push_back(pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4));\r
return create_frame(desc);\r
}\r
void frame_processor_device::clear(){impl_->clear();}\r
struct frame_renderer::implementation : boost::noncopyable\r
{ \r
implementation(frame_processor_device& frame_processor, const video_format_desc& format_desc) \r
- : frame_processor_(frame_processor), index_(0), shader_(format_desc), output_frame_(frame::empty()), fbo_(format_desc.width, format_desc.height)\r
+ : frame_processor_(frame_processor), index_(0), shader_(format_desc), fbo_(format_desc.width, format_desc.height)\r
{ \r
- std::fill(writing_.begin(), writing_.end(), frame::empty());\r
+ auto empty = std::make_shared<internal_frame>(pixel_format_desc());\r
+ output_frame_ = empty;\r
+ std::fill(writing_.begin(), writing_.end(), empty);\r
GL(glEnable(GL_POLYGON_STIPPLE));\r
GL(glEnable(GL_TEXTURE_2D));\r
GL(glEnable(GL_BLEND));\r
GL(glViewport(0, 0, format_desc.width, format_desc.height));\r
}\r
\r
- frame_ptr render(const frame_ptr& frame)\r
+ internal_frame_ptr render(const internal_frame_ptr& frame)\r
{\r
if(frame == nullptr)\r
return nullptr;\r
writing_[next_index]->draw(shader_);\r
\r
// Create an output frame\r
- output_frame_ = frame_processor_.create_frame();\r
+ output_frame_ = std::static_pointer_cast<internal_frame>(frame_processor_.create_frame());\r
\r
// Read from framebuffer into page-locked memory.\r
output_frame_->begin_read();\r
\r
size_t index_;\r
\r
- frame_ptr output_frame_; \r
+ internal_frame_ptr output_frame_; \r
\r
frame_processor_device& frame_processor_;\r
\r
- std::array<frame_ptr, 2> writing_;\r
+ std::array<internal_frame_ptr, 2> writing_;\r
\r
common::gl::frame_buffer_object fbo_;\r
frame_shader shader_;\r
};\r
\r
frame_renderer::frame_renderer(frame_processor_device& frame_processor, const video_format_desc& format_desc) : impl_(new implementation(frame_processor, format_desc)){}\r
-frame_ptr frame_renderer::render(const frame_ptr& frames){ return impl_->render(frames);}\r
+internal_frame_ptr frame_renderer::render(const internal_frame_ptr& frames){ return impl_->render(frames);}\r
}}
\ No newline at end of file
public:\r
frame_renderer(frame_processor_device& frame_processor, const video_format_desc& format_desc_);\r
\r
- frame_ptr render(const frame_ptr& frames);\r
+ internal_frame_ptr render(const internal_frame_ptr& frames);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
{\r
auto frame = frame_processor->create_frame();\r
- __stosd(reinterpret_cast<unsigned long*>(frame->data()), color_value_, frame->size() / sizeof(unsigned long));\r
+ __stosd(reinterpret_cast<unsigned long*>(frame->data().begin()), color_value_, frame->data().size() / sizeof(unsigned long));\r
frame_ = frame;\r
}\r
\r
#include "../../../processor/frame_processor_device.h"\r
\r
#include <tbb/parallel_for.h>\r
-#include <tbb/atomic.h>\r
-#include <tbb/mutex.h>\r
-#include <tbb/concurrent_queue.h>\r
-#include <tbb/scalable_allocator.h>\r
-\r
-#include <unordered_map>\r
\r
#if defined(_MSC_VER)\r
#pragma warning (push)\r
case pixel_format::rgba:\r
case pixel_format::abgr:\r
{\r
- desc.planes[0] = pixel_format_desc::plane(dummy_pict.linesize[0]/4, height, 4); \r
+ desc.planes.push_back(pixel_format_desc::plane(dummy_pict.linesize[0]/4, height, 4)); \r
return desc;\r
}\r
case pixel_format::ycbcr:\r
size_t size2 = dummy_pict.data[2] - dummy_pict.data[1];\r
size_t h2 = size2/dummy_pict.linesize[1]; \r
\r
- desc.planes[0] = pixel_format_desc::plane(dummy_pict.linesize[0], height, 1);\r
- desc.planes[1] = pixel_format_desc::plane(dummy_pict.linesize[1], h2, 1);\r
- desc.planes[2] = pixel_format_desc::plane(dummy_pict.linesize[2], h2, 1);\r
+ desc.planes.push_back(pixel_format_desc::plane(dummy_pict.linesize[0], height, 1));\r
+ desc.planes.push_back(pixel_format_desc::plane(dummy_pict.linesize[1], h2, 1));\r
+ desc.planes.push_back(pixel_format_desc::plane(dummy_pict.linesize[2], h2, 1));\r
\r
if(desc.pix_fmt == pixel_format::ycbcra) \r
- desc.planes[3] = pixel_format_desc::plane(dummy_pict.linesize[3], height, 1); \r
+ desc.planes.push_back(pixel_format_desc::plane(dummy_pict.linesize[3], height, 1)); \r
return desc;\r
} \r
default: \r
double param;\r
sws_context_.reset(sws_getContext(width_, height_, pix_fmt_, width_, height_, PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext);\r
if(!sws_context_)\r
- BOOST_THROW_EXCEPTION(\r
- operation_failed() <<\r
- msg_info("Could not create software scaling context.") << \r
- boost::errinfo_api_function("sws_getContext"));\r
+ BOOST_THROW_EXCEPTION( operation_failed() <<\r
+ msg_info("Could not create software scaling context.") << \r
+ boost::errinfo_api_function("sws_getContext"));\r
}\r
}\r
\r
\r
tbb::parallel_for(0, static_cast<int>(desc_.planes.size()), 1, [&](int n)\r
{\r
- if(desc_.planes[n].size == 0)\r
- return;\r
-\r
+ auto plane = desc_.planes[n];\r
+ auto result = result_frame->data(n).begin();\r
+ auto decoded = decoded_frame->data[n];\r
+ auto decoded_linesize = decoded_frame->linesize[n];\r
+ \r
tbb::parallel_for(0, static_cast<int>(desc_.planes[n].height), 1, [&](int y)\r
{\r
- memcpy\r
- (\r
- result_frame->data(n)+y*desc_.planes[n].linesize, \r
- decoded_frame->data[n] + y*decoded_frame->linesize[n], \r
- desc_.planes[n].linesize\r
- );\r
+ memcpy(result+y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
});\r
});\r
}\r
\r
AVFrame av_frame; \r
avcodec_get_frame_defaults(&av_frame);\r
- avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), result_frame->data(), PIX_FMT_BGRA, width_, height_);\r
+ avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), result_frame->data().begin(), PIX_FMT_BGRA, width_, height_);\r
\r
sws_scale(sws_context_.get(), decoded_frame->data, decoded_frame->linesize, 0, height_, av_frame.data, av_frame.linesize); \r
}\r
class cg_producer : public frame_producer\r
{\r
public:\r
-\r
static const unsigned int DEFAULT_LAYER = 5000;\r
\r
cg_producer();\r
\r
- frame_ptr render_frame();\r
+ virtual frame_ptr render_frame();\r
+ virtual void initialize(const frame_processor_device_ptr& frame_processor);\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
void update(int layer, const std::wstring& data);\r
void invoke(int layer, const std::wstring& label);\r
\r
- const video_format_desc& get_video_format_desc() const;\r
- void initialize(const frame_processor_device_ptr& frame_processor);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
using namespace boost::assign;\r
\r
namespace caspar { namespace core { namespace flash {\r
+\r
+struct ct_producer : public cg_producer\r
+{\r
+ ct_producer(const std::wstring& filename) : filename_(filename){}\r
+\r
+ frame_ptr render_frame()\r
+ {\r
+ if(filename_ != L"")\r
+ {\r
+ cg_producer::add(0, filename_, 1);\r
+ filename_ = L"";\r
+ }\r
+ return cg_producer::render_frame();\r
+ }\r
+\r
+ std::wstring filename_;\r
+};\r
\r
frame_producer_ptr create_ct_producer(const std::vector<std::wstring>& params) \r
{\r
- static const std::vector<std::wstring> extensions = list_of(L"ct");\r
- std::wstring filename = server::media_folder() + L"\\" + params[0];\r
- \r
- auto ext = std::find_if(extensions.begin(), extensions.end(), [&](const std::wstring& ex) -> bool\r
- { \r
- return boost::filesystem::is_regular_file(boost::filesystem::wpath(filename).replace_extension(ex));\r
- });\r
-\r
- if(ext == extensions.end())\r
- return nullptr;\r
- \r
- auto producer = std::make_shared<cg_producer>();\r
- producer->add(0, filename, 1);\r
- return producer;\r
+ std::wstring filename = server::media_folder() + L"\\" + params[0] + L".ct";\r
+ return boost::filesystem::exists(filename) ? std::make_shared<ct_producer>(filename) : nullptr;\r
}\r
\r
}\r
invalid_count_ = !flashax_container_->InvalidRectangle() ? std::min(2, invalid_count_+1) : 0;\r
if(current_frame_ == nullptr || invalid_count_ < 2)\r
{ \r
+ std::fill_n(bmp_frame_->data(), bmp_frame_->size(), 0); \r
+ flashax_container_->DrawControl(bmp_frame_->hdc());\r
current_frame_ = bmp_frame_;\r
- memset(current_frame_->data(), 0, current_frame_->size());\r
- \r
- flashax_container_->DrawControl(current_frame_->hdc());\r
} \r
\r
auto frame = frame_processor_->create_frame(format_desc.width, format_desc.height);\r
- memcpy(frame->data(), current_frame_->data(), current_frame_->size()); \r
-\r
+ std::copy(current_frame_->data(), current_frame_->data() + current_frame_->size(), frame->data().begin());\r
return frame;\r
}\r
\r
frame_ptr render_frame()\r
- {\r
- if(!frame_buffer_.try_pop(last_frame_) && is_empty_)\r
- last_frame_ = frame::empty();\r
- \r
- return last_frame_;\r
+ { \r
+ return (frame_buffer_.try_pop(last_frame_) || !is_empty_) && last_frame_ ? last_frame_ : frame::empty();\r
}\r
\r
void initialize(const frame_processor_device_ptr& frame_processor)\r
public:\r
\r
flash_producer(const std::wstring& filename);\r
- frame_ptr render_frame();\r
- const video_format_desc& get_video_format_desc() const;\r
- void initialize(const frame_processor_device_ptr& frame_processor);\r
+\r
+ virtual frame_ptr render_frame();\r
+ virtual void initialize(const frame_processor_device_ptr& frame_processor);\r
\r
void param(const std::wstring& param);\r
\r
auto bitmap = load_image(filename_);\r
FreeImage_FlipVertical(bitmap.get());\r
auto frame = frame_processor->create_frame(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()));\r
- memcpy(frame->data(), FreeImage_GetBits(bitmap.get()), frame->size());\r
+ memcpy(frame->data().begin(), FreeImage_GetBits(bitmap.get()), frame->data().size());\r
frame_ = frame;\r
}\r
\r
frame_ptr do_render_frame()\r
{\r
frame_ptr frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height);\r
- memset(frame->data(), 0, format_desc_.size);\r
+ std::fill(frame->data().begin(), frame->data().end(), 0);\r
\r
const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
const int delta_y = direction_ == direction::Up ? speed_ : -speed_;\r
\r
- unsigned char* frame_data = frame->data();\r
+ unsigned char* frame_data = frame->data().begin();\r
unsigned char* image_data = image_.get();\r
\r
if (direction_ == direction::Up || direction_ == direction::Down)\r
\r
if(last_frame_ == nullptr)\r
{\r
+ CASPAR_LOG(warning) << L"EOF: " << foreground_->print();\r
foreground_ = foreground_->get_following_producer();\r
last_frame_ = render_frame();\r
}\r
<paths>\r
<media-path>C:\\Casparcg\\_media\\</media-path>\r
<log-path>C:\\Casparcg\\_log\\</log-path>\r
- <template-path>C:\\Casparcg\\_templates\\</template-path>\r
+ <template-path>C:\\Casparcg\\</template-path>\r
<data-path>C:\\Casparcg\\_data\\</data-path>\r
</paths>\r
<channels>\r
<channel>\r
- <videomode>1080p2500</videomode>\r
+ <videomode>720p2500</videomode>\r
<consumers>\r
<ogl>\r
<device>1</device>\r
<stretch>uniform</stretch>\r
<windowed>true</windowed>\r
</ogl>\r
- <!--audio/>\r
- <bluefish>\r
+ <audio/>\r
+ <!--bluefish>\r
<device>1</device> \r
<embedded-audio>true</embedded-audio>\r
</bluefish-->\r