]> git.sesse.net Git - casparcg/blob - modules/silverlight/producer/silverlight_producer.cpp
2.0.0.2: Refactored executor. Optimized frame allocations.
[casparcg] / modules / silverlight / producer / silverlight_producer.cpp
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\r
5 *\r
6 *    CasparCG is free software: you can redistribute it and/or modify\r
7 *    it under the terms of the GNU General Public License as published by\r
8 *    the Free Software Foundation, either version 3 of the License, or\r
9 *    (at your option) any later version.\r
10 *\r
11 *    CasparCG is distributed in the hope that it will be useful,\r
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 *    GNU General Public License for more details.\r
15 \r
16 *    You should have received a copy of the GNU General Public License\r
17 *    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 */\r
20  \r
21 #include "../stdafx.h"\r
22 \r
23 #if defined(_MSC_VER)\r
24 #pragma warning (disable : 4714) // marked as __forceinline not inlined\r
25 #pragma warning (disable : 4146)\r
26 #endif\r
27 \r
28 #include "silverlight_producer.h"\r
29 \r
30 #include "../interop/XcpControlHost.h"\r
31 \r
32 #include <core/video_format.h>\r
33 \r
34 #include <core/mixer/write_frame.h>\r
35 #include <core/producer/frame/frame_factory.h>\r
36 \r
37 #include <common/concurrency/executor.h>\r
38 #include <common/env.h>\r
39 \r
40 #include <boost/filesystem.hpp>\r
41 \r
42 #include <SFML/Graphics.hpp>\r
43 \r
44 namespace caspar {\r
45                 \r
46 class silverlight_renderer\r
47 {\r
48         struct co_init\r
49         {\r
50                 co_init(){CoInitialize(nullptr);}\r
51                 ~co_init(){CoUninitialize();}\r
52         } co;\r
53         \r
54         int id_;\r
55 \r
56         const std::shared_ptr<core::frame_factory> frame_factory_;\r
57         const core::video_format_desc format_desc_;\r
58         \r
59         CComObject<XcpControlHost>* host_;\r
60         tbb::spin_mutex mutex_;\r
61         safe_ptr<core::basic_frame> last_frame_;\r
62 \r
63         sf::RenderWindow window_;\r
64                         \r
65         HDC screen_;\r
66         HDC mem_;\r
67         HBITMAP bmp_;\r
68         unsigned char* bmp_data_;\r
69 \r
70 public:\r
71         silverlight_renderer(const std::shared_ptr<core::frame_factory>& frame_factory) \r
72                 : frame_factory_(frame_factory)\r
73                 , format_desc_(frame_factory->get_video_format_desc())\r
74                 , last_frame_(core::basic_frame::empty())\r
75                 , host_(nullptr)\r
76                 , id_(rand())\r
77                 , window_(sf::VideoMode(format_desc_.width, format_desc_.height, 32), boost::lexical_cast<std::string>(id_), sf::Style::None)\r
78         {\r
79                 if(FAILED(CComObject<XcpControlHost>::CreateInstance(&host_)))\r
80                         BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to create XcpControlHost"));\r
81                 \r
82                 HWND hWnd = ::FindWindow(L"SFML_Window", boost::lexical_cast<std::wstring>(id_).c_str());\r
83                 if(FAILED(host_->CreateXcpControl(hWnd)))\r
84                         BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to Create XcpControl"));\r
85                 \r
86                 screen_= ::GetDC(hWnd);\r
87                 mem_ = ::CreateCompatibleDC(screen_);\r
88                                 \r
89                 BITMAPINFO info;\r
90                 memset(&info, 0, sizeof(BITMAPINFO));\r
91                 info.bmiHeader.biBitCount = 32;\r
92                 info.bmiHeader.biCompression = BI_RGB;\r
93                 info.bmiHeader.biHeight = -static_cast<int>(format_desc_.height);\r
94                 info.bmiHeader.biPlanes = 1;\r
95                 info.bmiHeader.biSize = sizeof(BITMAPINFO);\r
96                 info.bmiHeader.biWidth = format_desc_.width;\r
97 \r
98                 bmp_ = ::CreateDIBSection(screen_, &info, DIB_RGB_COLORS, reinterpret_cast<void**>(&bmp_data_), 0, 0);\r
99                 SelectObject(mem_, bmp_);\r
100         }\r
101 \r
102         ~silverlight_renderer()\r
103         {               \r
104                 DeleteObject(bmp_);\r
105                 DeleteDC(mem_);\r
106                 DeleteDC(screen_);\r
107 \r
108                 if(host_)\r
109                 {\r
110                         host_->DestroyXcpControl();\r
111                         host_->Release();\r
112                 }\r
113         }\r
114                         \r
115         void render()\r
116         {       \r
117                 sf::Event Event;\r
118                 while (window_.GetEvent(Event)){}\r
119                 window_.Display();\r
120                                 \r
121                 auto frame = frame_factory_->create_frame(this);\r
122                 ::BitBlt(mem_, 0, 0, format_desc_.width, format_desc_.height, screen_, 0, 0, SRCCOPY);          \r
123                 std::copy_n(bmp_data_, format_desc_.size, frame->image_data().begin());\r
124 \r
125                 tbb::spin_mutex::scoped_lock lock(mutex_);\r
126                 last_frame_ = frame;\r
127         }\r
128                 \r
129         safe_ptr<core::basic_frame> get_frame()\r
130         {               \r
131                 tbb::spin_mutex::scoped_lock lock(mutex_);\r
132                 return last_frame_;\r
133         }\r
134 };\r
135 \r
136 struct silverlight_producer : public core::frame_producer\r
137 {                               \r
138         std::unique_ptr<silverlight_renderer> renderer_;\r
139         \r
140         executor executor_;\r
141 public:\r
142 \r
143         silverlight_producer(const safe_ptr<core::frame_factory>& frame_factory) : executor_(L"silverlight")\r
144         {\r
145                 executor_.invoke([=]\r
146                 {\r
147                         renderer_.reset(new silverlight_renderer(frame_factory));\r
148                 });\r
149         }\r
150                 \r
151         virtual safe_ptr<core::basic_frame> receive()\r
152         {\r
153                 executor_.begin_invoke([=]\r
154                 {\r
155                         renderer_->render();\r
156                 });\r
157 \r
158                 return renderer_->get_frame();\r
159         }\r
160 \r
161         std::wstring print() const{ return L"silverlight"; }    \r
162 };\r
163 \r
164 safe_ptr<core::frame_producer> create_silverlight_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
165 {\r
166         //std::wstring filename = env::template_folder() + L"\\" + params[0] + L".xap";\r
167         //if(!boost::filesystem::exists(filename))\r
168         //      return frame_producer::empty();\r
169         if(params[0] != L"SILVER")\r
170                 return core::frame_producer::empty();\r
171 \r
172         return make_safe<silverlight_producer>(frame_factory);\r
173 }\r
174 \r
175 }