1 #include "../StdAfx.h"
\r
4 #include "../format/pixel_format.h"
\r
5 #include "../../common/utility/memory.h"
\r
6 #include "../../common/gl/utility.h"
\r
7 #include "../../common/gl/pixel_buffer_object.h"
\r
9 #include <boost/range/algorithm.hpp>
\r
11 namespace caspar { namespace core {
\r
15 rectangle(double left, double top, double right, double bottom)
\r
16 : left(left), top(top), right(right), bottom(bottom)
\r
24 GLubyte progressive_pattern[] = {
\r
25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
29 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
30 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
\r
32 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
34 GLubyte upper_pattern[] = {
\r
35 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
36 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
37 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
38 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
39 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
40 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
41 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
\r
42 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
\r
44 GLubyte lower_pattern[] = {
\r
45 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
46 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
47 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
48 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
49 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
50 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
51 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
\r
52 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};
\r
54 struct frame::implementation : boost::noncopyable
\r
56 implementation(size_t width, size_t height)
\r
57 : alpha_(1.0f), x_(0.0f), y_(0.0f), update_fmt_(video_update_format::progressive), texcoords_(0.0, 1.0, 1.0, 0.0), pixel_data_(4, nullptr)
\r
59 desc_.planes[0] = pixel_format_desc::plane(width, height, 4);
\r
60 desc_.pix_fmt = pixel_format::bgra;
\r
61 pixel_data_.resize(4, 0);
\r
62 if(width >= 2 && height >= 2)
\r
64 pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(width, height, GL_BGRA));
\r
69 implementation(const pixel_format_desc& desc)
\r
70 : alpha_(1.0f), x_(0.0f), y_(0.0f), update_fmt_(video_update_format::progressive), texcoords_(0.0, 1.0, 1.0, 0.0), pixel_data_(4, nullptr)
\r
74 for(size_t n = 0; n < desc_.planes.size(); ++n)
\r
76 if(desc_.planes[n].size == 0)
\r
79 GLuint format = [&]() -> GLuint
\r
81 switch(desc_.planes[n].channels)
\r
83 case 1: return GL_LUMINANCE;
\r
84 case 2: return GL_LUMINANCE_ALPHA;
\r
85 case 3: return GL_BGR;
\r
86 case 4: return GL_BGRA;
\r
87 default: BOOST_THROW_EXCEPTION(out_of_range() << msg_info("1-4 channels are supported") << arg_name_info("desc.planes.channels"));
\r
91 pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(desc_.planes[n].width, desc_.planes[n].height, format));
\r
98 pixel_data_ = std::vector<void*>(4, 0);
\r
99 boost::range::for_each(pbo_, std::mem_fn(&common::gl::pixel_buffer_object::begin_write));
\r
104 boost::range::transform(pbo_, pixel_data_.begin(), std::mem_fn(&common::gl::pixel_buffer_object::end_write));
\r
109 pixel_data_ = std::vector<void*>(4, 0);
\r
110 boost::range::for_each(pbo_, std::mem_fn(&common::gl::pixel_buffer_object::begin_read));
\r
115 boost::range::transform(pbo_, pixel_data_.begin(), std::mem_fn(&common::gl::pixel_buffer_object::end_read));
\r
118 void draw(const frame_shader_ptr& shader)
\r
120 shader->use(desc_);
\r
122 glTranslated(x_*2.0, y_*2.0, 0.0);
\r
123 glColor4d(1.0, 1.0, 1.0, alpha_);
\r
125 if(update_fmt_ == video_update_format::progressive)
\r
126 glPolygonStipple(progressive_pattern);
\r
127 else if(update_fmt_ == video_update_format::upper)
\r
128 glPolygonStipple(upper_pattern);
\r
129 else if(update_fmt_ == video_update_format::lower)
\r
130 glPolygonStipple(lower_pattern);
\r
132 for(size_t n = 0; n < pbo_.size(); ++n)
\r
134 glActiveTexture(GL_TEXTURE0+n);
\r
135 pbo_[n]->bind_texture();
\r
138 glTexCoord2d(texcoords_.left, texcoords_.bottom); glVertex2d(-1.0, -1.0);
\r
139 glTexCoord2d(texcoords_.right, texcoords_.bottom); glVertex2d( 1.0, -1.0);
\r
140 glTexCoord2d(texcoords_.right, texcoords_.top); glVertex2d( 1.0, 1.0);
\r
141 glTexCoord2d(texcoords_.left, texcoords_.top); glVertex2d(-1.0, 1.0);
\r
146 unsigned char* data(size_t index)
\r
148 if(pbo_.size() < index)
\r
149 BOOST_THROW_EXCEPTION(out_of_range());
\r
150 return static_cast<unsigned char*>(pixel_data_[index]);
\r
155 audio_data_.clear();
\r
159 texcoords_ = rectangle(0.0, 1.0, 1.0, 0.0);
\r
160 update_fmt_ = video_update_format::progressive;
\r
164 std::vector<common::gl::pixel_buffer_object_ptr> pbo_;
\r
165 std::vector<void*> pixel_data_;
\r
166 std::vector<short> audio_data_;
\r
171 video_update_format::type update_fmt_;
\r
172 rectangle texcoords_;
\r
174 pixel_format_desc desc_;
\r
177 frame::frame(size_t width, size_t height)
\r
178 : impl_(new implementation(width, height)){}
\r
179 frame::frame(const pixel_format_desc& desc)
\r
180 : impl_(new implementation(desc)){}
\r
181 void frame::draw(const frame_shader_ptr& shader){impl_->draw(shader);}
\r
182 void frame::begin_write(){impl_->begin_write();}
\r
183 void frame::end_write(){impl_->end_write();}
\r
184 void frame::begin_read(){impl_->begin_read();}
\r
185 void frame::end_read(){impl_->end_read();}
\r
186 void frame::pix_fmt(pixel_format::type format) {impl_->desc_.pix_fmt = format;}
\r
187 unsigned char* frame::data(size_t index){return impl_->data(index);}
\r
188 size_t frame::size(size_t index) const { return impl_->desc_.planes[index].size; }
\r
189 std::vector<short>& frame::audio_data() { return impl_->audio_data_; }
\r
190 void frame::reset(){impl_->reset();}
\r
191 void frame::alpha(double value){ impl_->alpha_ = value;}
\r
192 void frame::translate(double x, double y) { impl_->x_ += x; impl_->y_ += y; }
\r
193 void frame::texcoords(double left, double top, double right, double bottom){impl_->texcoords_ = rectangle(left, top, right, bottom);}
\r
194 void frame::update_fmt(video_update_format::type fmt){ impl_->update_fmt_ = fmt;}
\r
195 double frame::x() const { return impl_->x_;}
\r
196 double frame::y() const { return impl_->y_;}
\r