Various Doxygen fixes.
[dcpomatic.git] / test / client_server_test.cc
1 /*
2     Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /** @file  test/client_server_test.cc
22  *  @brief Test the server class.
23  *  @ingroup specific
24  *
25  *  Create a test image and then encode it using the standard mechanism
26  *  and also using a EncodeServer object running on localhost.  Compare the resulting
27  *  encoded data to check that they are the same.
28  */
29
30 #include "lib/encode_server.h"
31 #include "lib/image.h"
32 #include "lib/cross.h"
33 #include "lib/dcp_video.h"
34 #include "lib/player_video.h"
35 #include "lib/raw_image_proxy.h"
36 #include "lib/j2k_image_proxy.h"
37 #include "lib/encode_server_description.h"
38 #include "lib/file_log.h"
39 #include <boost/test/unit_test.hpp>
40 #include <boost/thread.hpp>
41
42 using std::list;
43 using boost::shared_ptr;
44 using boost::thread;
45 using boost::optional;
46 using dcp::Data;
47
48 void
49 do_remote_encode (shared_ptr<DCPVideo> frame, EncodeServerDescription description, Data locally_encoded)
50 {
51         Data remotely_encoded;
52         BOOST_CHECK_NO_THROW (remotely_encoded = frame->encode_remotely (description, 60));
53
54         BOOST_CHECK_EQUAL (locally_encoded.size(), remotely_encoded.size());
55         BOOST_CHECK_EQUAL (memcmp (locally_encoded.data().get(), remotely_encoded.data().get(), locally_encoded.size()), 0);
56 }
57
58 BOOST_AUTO_TEST_CASE (client_server_test_rgb)
59 {
60         shared_ptr<Image> image (new Image (AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), true));
61         uint8_t* p = image->data()[0];
62
63         for (int y = 0; y < 1080; ++y) {
64                 uint8_t* q = p;
65                 for (int x = 0; x < 1998; ++x) {
66                         *q++ = x % 256;
67                         *q++ = y % 256;
68                         *q++ = (x + y) % 256;
69                 }
70                 p += image->stride()[0];
71         }
72
73         shared_ptr<Image> sub_image (new Image (AV_PIX_FMT_RGBA, dcp::Size (100, 200), true));
74         p = sub_image->data()[0];
75         for (int y = 0; y < 200; ++y) {
76                 uint8_t* q = p;
77                 for (int x = 0; x < 100; ++x) {
78                         *q++ = y % 256;
79                         *q++ = x % 256;
80                         *q++ = (x + y) % 256;
81                         *q++ = 1;
82                 }
83                 p += sub_image->stride()[0];
84         }
85
86         shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_rgb.log"));
87
88         shared_ptr<PlayerVideo> pvf (
89                 new PlayerVideo (
90                         shared_ptr<ImageProxy> (new RawImageProxy (image)),
91                         Crop (),
92                         optional<double> (),
93                         dcp::Size (1998, 1080),
94                         dcp::Size (1998, 1080),
95                         EYES_BOTH,
96                         PART_WHOLE,
97                         ColourConversion ()
98                         )
99                 );
100
101         pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
102
103         shared_ptr<DCPVideo> frame (
104                 new DCPVideo (
105                         pvf,
106                         0,
107                         24,
108                         200000000,
109                         RESOLUTION_2K,
110                         log
111                         )
112                 );
113
114         Data locally_encoded = frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
115
116         EncodeServer* server = new EncodeServer (log, true, 2);
117
118         new thread (boost::bind (&EncodeServer::run, server));
119
120         /* Let the server get itself ready */
121         dcpomatic_sleep (1);
122
123         EncodeServerDescription description ("localhost", 2);
124
125         list<thread*> threads;
126         for (int i = 0; i < 8; ++i) {
127                 threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
128         }
129
130         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
131                 (*i)->join ();
132         }
133
134         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
135                 delete *i;
136         }
137
138         delete server;
139 }
140
141 BOOST_AUTO_TEST_CASE (client_server_test_yuv)
142 {
143         shared_ptr<Image> image (new Image (AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true));
144
145         for (int i = 0; i < image->planes(); ++i) {
146                 uint8_t* p = image->data()[i];
147                 for (int j = 0; j < image->line_size()[i]; ++j) {
148                         *p++ = j % 256;
149                 }
150         }
151
152         shared_ptr<Image> sub_image (new Image (AV_PIX_FMT_RGBA, dcp::Size (100, 200), true));
153         uint8_t* p = sub_image->data()[0];
154         for (int y = 0; y < 200; ++y) {
155                 uint8_t* q = p;
156                 for (int x = 0; x < 100; ++x) {
157                         *q++ = y % 256;
158                         *q++ = x % 256;
159                         *q++ = (x + y) % 256;
160                         *q++ = 1;
161                 }
162                 p += sub_image->stride()[0];
163         }
164
165         shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_yuv.log"));
166
167         shared_ptr<PlayerVideo> pvf (
168                 new PlayerVideo (
169                         shared_ptr<ImageProxy> (new RawImageProxy (image)),
170                         Crop (),
171                         optional<double> (),
172                         dcp::Size (1998, 1080),
173                         dcp::Size (1998, 1080),
174                         EYES_BOTH,
175                         PART_WHOLE,
176                         ColourConversion ()
177                         )
178                 );
179
180         pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
181
182         shared_ptr<DCPVideo> frame (
183                 new DCPVideo (
184                         pvf,
185                         0,
186                         24,
187                         200000000,
188                         RESOLUTION_2K,
189                         log
190                         )
191                 );
192
193         Data locally_encoded = frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
194
195         EncodeServer* server = new EncodeServer (log, true, 2);
196
197         new thread (boost::bind (&EncodeServer::run, server));
198
199         /* Let the server get itself ready */
200         dcpomatic_sleep (1);
201
202         EncodeServerDescription description ("localhost", 2);
203
204         list<thread*> threads;
205         for (int i = 0; i < 8; ++i) {
206                 threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
207         }
208
209         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
210                 (*i)->join ();
211         }
212
213         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
214                 delete *i;
215         }
216
217         delete server;
218 }
219
220 BOOST_AUTO_TEST_CASE (client_server_test_j2k)
221 {
222         shared_ptr<Image> image (new Image (AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true));
223
224         for (int i = 0; i < image->planes(); ++i) {
225                 uint8_t* p = image->data()[i];
226                 for (int j = 0; j < image->line_size()[i]; ++j) {
227                         *p++ = j % 256;
228                 }
229         }
230
231         shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_j2k.log"));
232
233         shared_ptr<PlayerVideo> raw_pvf (
234                 new PlayerVideo (
235                         shared_ptr<ImageProxy> (new RawImageProxy (image)),
236                         Crop (),
237                         optional<double> (),
238                         dcp::Size (1998, 1080),
239                         dcp::Size (1998, 1080),
240                         EYES_BOTH,
241                         PART_WHOLE,
242                         ColourConversion ()
243                         )
244                 );
245
246         shared_ptr<DCPVideo> raw_frame (
247                 new DCPVideo (
248                         raw_pvf,
249                         0,
250                         24,
251                         200000000,
252                         RESOLUTION_2K,
253                         log
254                         )
255                 );
256
257         Data raw_locally_encoded = raw_frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
258
259         shared_ptr<PlayerVideo> j2k_pvf (
260                 new PlayerVideo (
261                         shared_ptr<ImageProxy> (new J2KImageProxy (raw_locally_encoded, dcp::Size (1998, 1080), AV_PIX_FMT_XYZ12LE)),
262                         Crop (),
263                         optional<double> (),
264                         dcp::Size (1998, 1080),
265                         dcp::Size (1998, 1080),
266                         EYES_BOTH,
267                         PART_WHOLE,
268                         PresetColourConversion::all().front().conversion
269                         )
270                 );
271
272         shared_ptr<DCPVideo> j2k_frame (
273                 new DCPVideo (
274                         j2k_pvf,
275                         0,
276                         24,
277                         200000000,
278                         RESOLUTION_2K,
279                         log
280                         )
281                 );
282
283         Data j2k_locally_encoded = j2k_frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
284
285         EncodeServer* server = new EncodeServer (log, true, 2);
286
287         new thread (boost::bind (&EncodeServer::run, server));
288
289         /* Let the server get itself ready */
290         dcpomatic_sleep (1);
291
292         EncodeServerDescription description ("localhost", 2);
293
294         list<thread*> threads;
295         for (int i = 0; i < 8; ++i) {
296                 threads.push_back (new thread (boost::bind (do_remote_encode, j2k_frame, description, j2k_locally_encoded)));
297         }
298
299         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
300                 (*i)->join ();
301         }
302
303         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
304                 delete *i;
305         }
306
307         delete server;
308 }