]> git.sesse.net Git - casparcg/blob - core/frame/gpu_composite_frame.cpp
2.0.0.2:
[casparcg] / core / frame / gpu_composite_frame.cpp
1 #include "../StdAfx.h"\r
2 \r
3 #include "gpu_composite_frame.h"\r
4 #include "../../common/gl/gl_check.h"\r
5 #include "../../common/utility/memory.h"\r
6 \r
7 #include <boost/range/algorithm.hpp>\r
8 \r
9 #include <algorithm>\r
10 #include <numeric>\r
11 \r
12 #include <tbb/parallel_for.h>\r
13 \r
14 namespace caspar { namespace core {\r
15         \r
16 struct gpu_composite_frame::implementation : boost::noncopyable\r
17 {\r
18         implementation(gpu_composite_frame* self) : self_(self){}\r
19 \r
20         void begin_write()\r
21         {\r
22                 boost::range::for_each(frames_, std::mem_fn(&gpu_frame::begin_write));          \r
23         }\r
24 \r
25         void end_write()\r
26         {\r
27                 boost::range::for_each(frames_, std::mem_fn(&gpu_frame::end_write));                            \r
28         }\r
29         \r
30         void begin_read()\r
31         {       \r
32                 boost::range::for_each(frames_, std::mem_fn(&gpu_frame::begin_read));           \r
33         }\r
34 \r
35         void end_read()\r
36         {\r
37                 boost::range::for_each(frames_, std::mem_fn(&gpu_frame::end_read));     \r
38         }\r
39 \r
40         void draw()\r
41         {\r
42                 glPushMatrix();\r
43                 glTranslated(self_->x()*2.0, self_->y()*2.0, 0.0);\r
44                 boost::range::for_each(frames_, std::mem_fn(&gpu_frame::draw));\r
45                 glPopMatrix();\r
46         }\r
47                 \r
48         void add(const gpu_frame_ptr& frame)\r
49         {\r
50                 frames_.push_back(frame);\r
51 \r
52                 if(self_->audio_data().empty())\r
53                         self_->audio_data() = std::move(frame->audio_data());\r
54                 else\r
55                 {\r
56                         tbb::parallel_for\r
57                         (\r
58                                 tbb::blocked_range<size_t>(0, frame->audio_data().size()),\r
59                                 [&](const tbb::blocked_range<size_t>& r)\r
60                                 {\r
61                                         for(size_t n = r.begin(); n < r.end(); ++n)\r
62                                         {\r
63                                                 self_->audio_data()[n] = static_cast<short>(\r
64                                                         static_cast<int>(self_->audio_data()[n]) + \r
65                                                         static_cast<int>(frame->audio_data()[n]) & 0xFFFF);     \r
66                                         }\r
67                                 }\r
68                         );\r
69                 }\r
70         }\r
71 \r
72         unsigned char* data()\r
73         {\r
74                 BOOST_THROW_EXCEPTION(invalid_operation());\r
75         }\r
76 \r
77         gpu_composite_frame* self_;\r
78         std::vector<gpu_frame_ptr> frames_;\r
79         size_t size_;\r
80 };\r
81 \r
82 #pragma warning (disable : 4355)\r
83 \r
84 gpu_composite_frame::gpu_composite_frame() \r
85         : gpu_frame(0, 0), impl_(new implementation(this)){}\r
86 void gpu_composite_frame::begin_write(){impl_->begin_write();}\r
87 void gpu_composite_frame::end_write(){impl_->end_write();}      \r
88 void gpu_composite_frame::begin_read(){impl_->begin_read();}\r
89 void gpu_composite_frame::end_read(){impl_->end_read();}\r
90 void gpu_composite_frame::draw(){impl_->draw();}\r
91 unsigned char* gpu_composite_frame::data(){return impl_->data();}\r
92 void gpu_composite_frame::add(const gpu_frame_ptr& frame){impl_->add(frame);}\r
93 \r
94 gpu_frame_ptr gpu_composite_frame::interlace(const gpu_frame_ptr& frame1,\r
95                                                                                                 const gpu_frame_ptr& frame2, \r
96                                                                                                 video_mode mode)\r
97 {                       \r
98         auto result = std::make_shared<gpu_composite_frame>();\r
99         result->add(frame1);\r
100         result->add(frame2);\r
101         if(mode == video_mode::upper)\r
102         {\r
103                 frame1->mode(video_mode::upper);\r
104                 frame2->mode(video_mode::lower);\r
105         }\r
106         else\r
107         {\r
108                 frame1->mode(video_mode::lower);\r
109                 frame2->mode(video_mode::upper);\r
110         }\r
111         return result;\r
112 }\r
113 \r
114 }}