1 #include "../StdAfx.h"
\r
3 #include "write_frame.h"
\r
5 #include "draw_frame.h"
\r
6 #include "frame_shader.h"
\r
8 #include "../format/pixel_format.h"
\r
9 #include "../../common/gl/utility.h"
\r
10 #include "../../common/gl/pixel_buffer_object.h"
\r
12 #include <boost/range/algorithm.hpp>
\r
14 namespace caspar { namespace core {
\r
16 struct write_frame_impl::implementation : boost::noncopyable
\r
18 implementation(const pixel_format_desc& desc) : desc_(desc)
\r
20 assert(desc_.planes.size() <= 4);
\r
22 std::fill(pixel_data_.begin(), pixel_data_.end(), nullptr);
\r
24 for(size_t n = 0; n < desc_.planes.size(); ++n)
\r
26 if(desc_.planes[n].size == 0)
\r
29 GLuint format = [&]() -> GLuint
\r
31 switch(desc_.planes[n].channels)
\r
33 case 1: return GL_LUMINANCE;
\r
34 case 2: return GL_LUMINANCE_ALPHA;
\r
35 case 3: return GL_BGR;
\r
36 case 4: return GL_BGRA;
\r
37 default: BOOST_THROW_EXCEPTION(out_of_range() << msg_info("1-4 channels are supported") << arg_name_info("desc.planes.channels"));
\r
41 pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(desc_.planes[n].width, desc_.planes[n].height, format));
\r
42 pbo_.back()->is_smooth(true);
\r
49 std::fill(pixel_data_.begin(), pixel_data_.end(), nullptr);
\r
50 boost::range::for_each(pbo_, std::mem_fn(&common::gl::pixel_buffer_object::begin_write));
\r
55 boost::range::transform(pbo_, pixel_data_.begin(), std::mem_fn(&common::gl::pixel_buffer_object::end_write));
\r
58 void draw(frame_shader& shader)
\r
60 assert(pbo_.size() == desc_.planes.size());
\r
62 for(size_t n = 0; n < pbo_.size(); ++n)
\r
64 glActiveTexture(GL_TEXTURE0+n);
\r
65 pbo_[n]->bind_texture();
\r
67 shader.render(desc_);
\r
70 unsigned char* data(size_t index)
\r
72 return static_cast<unsigned char*>(pixel_data_[index]);
\r
77 audio_data_.clear();
\r
81 std::vector<common::gl::pixel_buffer_object_ptr> pbo_;
\r
82 std::array<void*, 4> pixel_data_;
\r
83 std::vector<short> audio_data_;
\r
85 const pixel_format_desc desc_;
\r
88 write_frame_impl::write_frame_impl(const pixel_format_desc& desc) : impl_(new implementation(desc)){}
\r
89 void write_frame_impl::begin_write(){impl_->begin_write();}
\r
90 void write_frame_impl::end_write(){impl_->end_write();}
\r
91 void write_frame_impl::draw(frame_shader& shader){impl_->draw(shader);}
\r
92 boost::iterator_range<unsigned char*> write_frame_impl::pixel_data(size_t index)
\r
94 auto ptr = static_cast<unsigned char*>(impl_->pixel_data_[index]);
\r
95 return boost::iterator_range<unsigned char*>(ptr, ptr+impl_->desc_.planes[index].size);
\r
97 const boost::iterator_range<const unsigned char*> write_frame_impl::pixel_data(size_t index) const
\r
99 auto ptr = static_cast<const unsigned char*>(impl_->pixel_data_[index]);
\r
100 return boost::iterator_range<const unsigned char*>(ptr, ptr+impl_->desc_.planes[index].size);
\r
103 std::vector<short>& write_frame_impl::audio_data() { return impl_->audio_data_; }
\r
104 const std::vector<short>& write_frame_impl::audio_data() const { return impl_->audio_data_; }
\r
105 void write_frame_impl::reset(){impl_->reset();}
\r