]> git.sesse.net Git - casparcg/blob - core/processor/write_frame.cpp
2.0.0.2:
[casparcg] / core / processor / write_frame.cpp
1 #include "../StdAfx.h"\r
2 \r
3 #include "write_frame.h"\r
4 \r
5 #include "draw_frame.h"\r
6 #include "frame_shader.h"\r
7 \r
8 #include "../format/pixel_format.h"\r
9 #include "../../common/gl/utility.h"\r
10 #include "../../common/gl/pixel_buffer_object.h"\r
11 \r
12 #include <boost/range/algorithm.hpp>\r
13 \r
14 namespace caspar { namespace core {\r
15                                                                                                                                                                                                                                                                                                                         \r
16 struct write_frame_impl::implementation : boost::noncopyable\r
17 {\r
18         implementation(const pixel_format_desc& desc) : desc_(desc)\r
19         {                       \r
20                 assert(desc_.planes.size() <= 4);\r
21 \r
22                 std::fill(pixel_data_.begin(), pixel_data_.end(), nullptr);\r
23 \r
24                 for(size_t n = 0; n < desc_.planes.size(); ++n)\r
25                 {\r
26                         if(desc_.planes[n].size == 0)\r
27                                 break;\r
28 \r
29                         GLuint format = [&]() -> GLuint\r
30                         {\r
31                                 switch(desc_.planes[n].channels)\r
32                                 {\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
38                                 }\r
39                         }();\r
40 \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
43                 }\r
44                 end_write();\r
45         }\r
46         \r
47         void begin_write()\r
48         {\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
51         }\r
52 \r
53         void end_write()\r
54         {\r
55                 boost::range::transform(pbo_, pixel_data_.begin(), std::mem_fn(&common::gl::pixel_buffer_object::end_write));\r
56         }\r
57 \r
58         void draw(frame_shader& shader)\r
59         {\r
60                 assert(pbo_.size() == desc_.planes.size());\r
61 \r
62                 for(size_t n = 0; n < pbo_.size(); ++n)\r
63                 {\r
64                         glActiveTexture(GL_TEXTURE0+n);\r
65                         pbo_[n]->bind_texture();\r
66                 }\r
67                 shader.render(desc_);\r
68         }\r
69 \r
70         unsigned char* data(size_t index)\r
71         {\r
72                 return static_cast<unsigned char*>(pixel_data_[index]);\r
73         }\r
74 \r
75         void reset()\r
76         {\r
77                 audio_data_.clear();\r
78                 end_write();\r
79         }\r
80         \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
84         \r
85         const pixel_format_desc desc_;\r
86 };\r
87         \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
93 {\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
96 }\r
97 const boost::iterator_range<const unsigned char*> write_frame_impl::pixel_data(size_t index) const\r
98 {\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
101 }\r
102 \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
106 }}