// Use shared_ptr to emulate move semantics\r
input_.push(std::make_shared<std::vector<short>>(std::move(frame->audio_data()))); \r
\r
- if(GetStatus() != Playing)\r
+ if(GetStatus() != Playing && input_.size() > 1)\r
Play();\r
}\r
\r
}\r
\r
bool OnGetData(sf::SoundStream::Chunk& data)\r
- {\r
+ {\r
static std::vector<short> silence(1920*2, 0);\r
\r
std::shared_ptr<std::vector<short>> audio_data;\r
data.Samples = container_.back().data();\r
data.NbSamples = container_.back().size();\r
}\r
- return true;\r
- }\r
+ return true;\r
+ }\r
\r
boost::circular_buffer<std::vector<short>> container_;\r
tbb::concurrent_bounded_queue<std::shared_ptr<std::vector<short>>> input_;\r
return frame_format::invalid;\r
}\r
\r
-}} //namespace caspar\r
+}}\r
\r
implementation(size_t width, size_t height) \r
: pbo_(0), data_(nullptr), width_(width), height_(height), \r
size_(width*height*4), reading_(false), texture_(0), alpha_(1.0f), \r
- x_(0.0f), y_(0.0f), mode_(video_mode::progressive)\r
+ x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
+ texcoords_(0.0, 1.0, 1.0, 0.0)\r
{ \r
}\r
\r
\r
GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
glBegin(GL_QUADS);\r
- glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);\r
- glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);\r
- glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);\r
- glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);\r
+ glTexCoord2d(texcoords_.left, texcoords_.bottom); glVertex2d(-1.0, -1.0);\r
+ glTexCoord2d(texcoords_.right, texcoords_.bottom); glVertex2d( 1.0, -1.0);\r
+ glTexCoord2d(texcoords_.right, texcoords_.top); glVertex2d( 1.0, 1.0);\r
+ glTexCoord2d(texcoords_.left, texcoords_.top); glVertex2d(-1.0, 1.0);\r
glEnd();\r
glPopMatrix();\r
}\r
void reset()\r
{\r
audio_data_.clear();\r
- alpha_ = 1.0f;\r
- x_ = 0.0f;\r
- y_ = 0.0f;\r
- mode_ = video_mode::progressive;\r
+ alpha_ = 1.0f;\r
+ x_ = 0.0f;\r
+ y_ = 0.0f;\r
+ texcoords_ = rectangle(0.0, 1.0, 1.0, 0.0);\r
+ mode_ = video_mode::progressive;\r
}\r
\r
gpu_frame* self_;\r
double x_;\r
double y_;\r
video_mode mode_;\r
+ rectangle texcoords_;\r
};\r
\r
gpu_frame::gpu_frame(size_t width, size_t height) \r
double gpu_frame::x() const { return impl_->x_;}\r
double gpu_frame::y() const { return impl_->y_;}\r
void gpu_frame::translate(double x, double y) { impl_->x_ += x; impl_->y_ += y; }\r
+void gpu_frame::texcoords(const rectangle& texcoords){impl_->texcoords_ = texcoords;}\r
void gpu_frame::mode(video_mode mode){ impl_->mode_ = mode;}\r
video_mode gpu_frame::mode() const{ return impl_->mode_;}\r
}}
\ No newline at end of file
\r
#include <Glee.h>\r
\r
+#include <boost/tuple/tuple.hpp>\r
+\r
namespace caspar { namespace core {\r
\r
+struct rectangle\r
+{\r
+ rectangle(double left, double top, double right, double bottom)\r
+ : left(left), top(top), right(right), bottom(bottom)\r
+ {}\r
+ double left;\r
+ double top;\r
+ double right;\r
+ double bottom;\r
+};\r
+\r
class gpu_frame : boost::noncopyable\r
{\r
public:\r
virtual double x() const;\r
virtual double y() const;\r
virtual void translate(double x, double y);\r
+ virtual void texcoords(const rectangle& texcoords);\r
\r
virtual void mode(video_mode mode);\r
virtual video_mode mode() const;\r
};\r
\r
// This is somewhat a hack... needs redesign\r
-cg_producer_ptr get_default_cg_producer(const renderer::render_device_ptr& render_device, unsigned int exLayer)\r
+cg_producer_ptr get_default_cg_producer(const renderer::render_device_ptr& render_device, unsigned int render_layer)\r
{\r
if(!render_device)\r
BOOST_THROW_EXCEPTION(null_argument() << msg_info("render_device"));\r
\r
- auto producer = std::dynamic_pointer_cast<cg_producer>(render_device->active(exLayer));\r
+ auto producer = std::dynamic_pointer_cast<cg_producer>(render_device->active(render_layer));\r
if(!producer)\r
{\r
producer = std::make_shared<cg_producer>(render_device->get_frame_format_desc()); \r
- render_device->load(exLayer, producer, renderer::load_option::auto_play); \r
+ render_device->load(render_layer, producer, renderer::load_option::auto_play); \r
}\r
\r
return producer;\r
\r
gpu_frame_ptr get_frame()\r
{\r
- return ++current_frame_ >= info_.duration ? nullptr : compose(get_producer_frame(dest_), get_producer_frame(source_));\r
+ if(++current_frame_ >= info_.duration)\r
+ return nullptr;\r
+\r
+ return compose(get_producer_frame(dest_), get_producer_frame(source_));\r
}\r
\r
gpu_frame_ptr get_producer_frame(frame_producer_ptr& producer)\r
src_frame->translate(0.0f-alpha, 0.0f);\r
}\r
}\r
+ else if(info_.type == transition_type::wipe)\r
+ {\r
+ if(info_.direction == transition_direction::from_left) \r
+ {\r
+ dest_frame->translate(-1.0f+alpha, 0.0f);\r
+ dest_frame->texcoords(rectangle(-1.0+alpha, 1.0, alpha, 0.0));\r
+ }\r
+ else if(info_.direction == transition_direction::from_right)\r
+ {\r
+ dest_frame->translate(1.0f-alpha, 0.0f);\r
+ dest_frame->texcoords(rectangle(1.0-alpha, 1.0, 2.0-alpha, 0.0));\r
+ }\r
+ }\r
+\r
return composite;\r
}\r
\r
\r
void synchronize()\r
{\r
- auto remaining = boost::posix_time::microseconds(period_) - (boost::posix_time::microsec_clock::local_time() - time_);\r
+ auto remaining = boost::posix_time::microseconds(period_) - \r
+ (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
+ boost::this_thread::sleep(remaining - \r
+ boost::posix_time::microseconds(5000));\r
time_ = boost::posix_time::microsec_clock::local_time();\r
}\r
private:\r
struct display_device::implementation\r
{\r
public:\r
- implementation(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers) : consumers_(consumers), fmt_(format_desc)\r
+ implementation(const frame_format_desc& format_desc, \r
+ const std::vector<frame_consumer_ptr>& consumers) \r
+ : consumers_(consumers), fmt_(format_desc)\r
{\r
if(consumers.empty())\r
BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
- << msg_info("display_device requires atleast one consumer"));\r
+ << msg_info("display_device requires atleast one consumer"));\r
\r
- if(std::any_of(consumers.begin(), consumers.end(), [&](const frame_consumer_ptr& pConsumer){ return pConsumer->get_frame_format_desc() != format_desc;}))\r
+ if(std::any_of(consumers.begin(), consumers.end(), \r
+ [&](const frame_consumer_ptr& pConsumer)\r
+ { return pConsumer->get_frame_format_desc() != format_desc;}))\r
+ {\r
BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
- << msg_info("All consumers must have same frameformat as display_device."));\r
- \r
- needs_clock_ = !std::any_of(consumers.begin(), consumers.end(), std::mem_fn(&frame_consumer::has_sync_clock));\r
+ << msg_info("All consumers must have same frameformat as display_device."));\r
+ }\r
+\r
+ needs_clock_ = !std::any_of(consumers.begin(), consumers.end(), \r
+ std::mem_fn(&frame_consumer::has_sync_clock));\r
frame_buffer_.set_capacity(3);\r
is_running_ = true;\r
display_thread_ = boost::thread([=]{run();});\r
{\r
try\r
{\r
- consumer->prepare(frame); // Could block\r
+ consumer->prepare(frame);\r
prepared_frames_.push_back(frame);\r
\r
if(prepared_frames_.size() > 2)\r
{\r
- consumer->display(prepared_frames_.front()); // Could block\r
+ consumer->display(prepared_frames_.front());\r
prepared_frames_.pop_front();\r
}\r
}\r
CASPAR_LOG(warning) << "Removed consumer from render-device.";\r
if(consumers_.empty())\r
{\r
- CASPAR_LOG(warning) << "No consumers available. Shutting down display-device.";\r
+ CASPAR_LOG(warning) \r
+ << "No consumers available. Shutting down display-device.";\r
is_running_ = false;\r
}\r
}\r
\r
struct layer::implementation\r
{ \r
- implementation() : preview_frame_(nullptr), active_(nullptr), background_(nullptr), last_frame_(nullptr) {}\r
+ implementation() \r
+ : preview_frame_(nullptr), active_(nullptr), \r
+ background_(nullptr), last_frame_(nullptr) {}\r
\r
void load(const frame_producer_ptr& frame_producer, load_option option)\r
{\r
std::vector<gpu_frame_ptr> render_frames(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()), [&](const tbb::blocked_range<size_t>& r)\r
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()), \r
+ [&](const tbb::blocked_range<size_t>& r)\r
{\r
auto it = layers.begin();\r
std::advance(it, r.begin());\r
\r
struct render_device::implementation : boost::noncopyable\r
{ \r
- implementation(const frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers) \r
- : display_device_(new display_device(format_desc, consumers)), fmt_(format_desc), frame_processor_(new gpu_frame_processor(format_desc))\r
+ implementation(const frame_format_desc& format_desc, unsigned int index, \r
+ const std::vector<frame_consumer_ptr>& consumers) \r
+ : display_device_(new display_device(format_desc, consumers)), \r
+ fmt_(format_desc), \r
+ frame_processor_(new gpu_frame_processor(format_desc))\r
{ \r
is_running_ = true;\r
\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
layers_.clear();\r
- CASPAR_LOG(error) << "Unexpected exception. Cleared layers in render-device";\r
+ CASPAR_LOG(error) \r
+ << "Unexpected exception. Cleared layers in render-device";\r
}\r
}\r
\r
CASPAR_LOG(info) << L"Ended render_device thread";\r
}\r
\r
- void load(int exLayer, const frame_producer_ptr& producer, load_option option)\r
+ void load(int render_layer, const frame_producer_ptr& producer, load_option option)\r
{\r
if(producer->get_frame_format_desc() != fmt_)\r
- BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("pProducer") << msg_info("Invalid frame format"));\r
+ BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("pProducer") \r
+ << msg_info("Invalid frame format"));\r
\r
producer->initialize(frame_processor_);\r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- layers_[exLayer].load(producer, option);\r
+ layers_[render_layer].load(producer, option);\r
}\r
\r
- void pause(int exLayer)\r
+ void pause(int render_layer)\r
{ \r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- auto it = layers_.find(exLayer);\r
+ auto it = layers_.find(render_layer);\r
if(it != layers_.end())\r
it->second.pause(); \r
}\r
\r
- void play(int exLayer)\r
+ void play(int render_layer)\r
{ \r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- auto it = layers_.find(exLayer);\r
+ auto it = layers_.find(render_layer);\r
if(it != layers_.end())\r
it->second.play(); \r
}\r
\r
- void stop(int exLayer)\r
+ void stop(int render_layer)\r
{ \r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- auto it = layers_.find(exLayer);\r
+ auto it = layers_.find(render_layer);\r
if(it != layers_.end())\r
it->second.stop();\r
}\r
\r
- void clear(int exLayer)\r
+ void clear(int render_layer)\r
{\r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- auto it = layers_.find(exLayer);\r
+ auto it = layers_.find(render_layer);\r
if(it != layers_.end())\r
it->second.clear(); \r
}\r
layers_.clear();\r
} \r
\r
- frame_producer_ptr active(int exLayer) const\r
+ frame_producer_ptr active(int render_layer) const\r
{\r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- auto it = layers_.find(exLayer);\r
+ auto it = layers_.find(render_layer);\r
return it != layers_.end() ? it->second.active() : nullptr;\r
}\r
\r
- frame_producer_ptr background(int exLayer) const\r
+ frame_producer_ptr background(int render_layer) const\r
{\r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
- auto it = layers_.find(exLayer);\r
+ auto it = layers_.find(render_layer);\r
return it != layers_.end() ? it->second.background() : nullptr;\r
}\r
\r
\r
render_device::render_device(const frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers) \r
: impl_(new implementation(format_desc, index, consumers)){}\r
-void render_device::load(int exLayer, const frame_producer_ptr& pProducer, load_option option){impl_->load(exLayer, pProducer, option);}\r
-void render_device::pause(int exLayer){impl_->pause(exLayer);}\r
-void render_device::play(int exLayer){impl_->play(exLayer);}\r
-void render_device::stop(int exLayer){impl_->stop(exLayer);}\r
-void render_device::clear(int exLayer){impl_->clear(exLayer);}\r
+void render_device::load(int render_layer, const frame_producer_ptr& pProducer, load_option option){impl_->load(render_layer, pProducer, option);}\r
+void render_device::pause(int render_layer){impl_->pause(render_layer);}\r
+void render_device::play(int render_layer){impl_->play(render_layer);}\r
+void render_device::stop(int render_layer){impl_->stop(render_layer);}\r
+void render_device::clear(int render_layer){impl_->clear(render_layer);}\r
void render_device::clear(){impl_->clear();}\r
-frame_producer_ptr render_device::active(int exLayer) const {return impl_->active(exLayer);}\r
-frame_producer_ptr render_device::background(int exLayer) const {return impl_->background(exLayer);}\r
+frame_producer_ptr render_device::active(int render_layer) const {return impl_->active(render_layer);}\r
+frame_producer_ptr render_device::background(int render_layer) const {return impl_->background(render_layer);}\r
const frame_format_desc& render_device::get_frame_format_desc() const{return impl_->fmt_;}\r
}}}\r
class render_device : boost::noncopyable\r
{ \r
public:\r
- render_device(const frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers);\r
+ render_device(const frame_format_desc& format_desc, unsigned int index, \r
+ const std::vector<frame_consumer_ptr>& consumers);\r
\r
- void load(int exLayer, const frame_producer_ptr& producer, load_option option = load_option::none); \r
- void pause(int exLayer);\r
- void play(int exLayer);\r
- void stop(int exLayer);\r
- void clear(int exLayer);\r
+ void load(int render_layer, const frame_producer_ptr& producer, \r
+ load_option option = load_option::none); \r
+ void pause(int render_layer);\r
+ void play(int render_layer);\r
+ void stop(int render_layer);\r
+ void clear(int render_layer);\r
void clear();\r
\r
- frame_producer_ptr active(int exLayer) const;\r
- frame_producer_ptr background(int exLayer) const;\r
+ frame_producer_ptr active(int render_layer) const;\r
+ frame_producer_ptr background(int render_layer) const;\r
\r
const frame_format_desc& get_frame_format_desc() const; \r
private:\r
const frame_format_desc& get_frame_format_desc() const\r
{ \r
static frame_format_desc format;\r
- return format();\r
+ return format;\r
}\r
void initialize(const frame_factory_ptr& factory)\r
{}\r