Use make_shared<>.
[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  *
24  *  Create a test image and then encode it using the standard mechanism
25  *  and also using a EncodeServer object running on localhost.  Compare the resulting
26  *  encoded data to check that they are the same.
27  */
28
29 #include "lib/encode_server.h"
30 #include "lib/image.h"
31 #include "lib/cross.h"
32 #include "lib/dcp_video.h"
33 #include "lib/player_video.h"
34 #include "lib/raw_image_proxy.h"
35 #include "lib/j2k_image_proxy.h"
36 #include "lib/encode_server_description.h"
37 #include "lib/file_log.h"
38 #include <boost/test/unit_test.hpp>
39 #include <boost/thread.hpp>
40 #include <boost/make_shared.hpp>
41
42 using std::list;
43 using boost::shared_ptr;
44 using boost::make_shared;
45 using boost::thread;
46 using boost::optional;
47 using dcp::Data;
48
49 void
50 do_remote_encode (shared_ptr<DCPVideo> frame, EncodeServerDescription description, Data locally_encoded)
51 {
52         Data remotely_encoded;
53         BOOST_CHECK_NO_THROW (remotely_encoded = frame->encode_remotely (description, 60));
54
55         BOOST_CHECK_EQUAL (locally_encoded.size(), remotely_encoded.size());
56         BOOST_CHECK_EQUAL (memcmp (locally_encoded.data().get(), remotely_encoded.data().get(), locally_encoded.size()), 0);
57 }
58
59 BOOST_AUTO_TEST_CASE (client_server_test_rgb)
60 {
61         shared_ptr<Image> image = make_shared<Image> (AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), true);
62         uint8_t* p = image->data()[0];
63
64         for (int y = 0; y < 1080; ++y) {
65                 uint8_t* q = p;
66                 for (int x = 0; x < 1998; ++x) {
67                         *q++ = x % 256;
68                         *q++ = y % 256;
69                         *q++ = (x + y) % 256;
70                 }
71                 p += image->stride()[0];
72         }
73
74         shared_ptr<Image> sub_image = make_shared<Image> (AV_PIX_FMT_RGBA, dcp::Size (100, 200), true);
75         p = sub_image->data()[0];
76         for (int y = 0; y < 200; ++y) {
77                 uint8_t* q = p;
78                 for (int x = 0; x < 100; ++x) {
79                         *q++ = y % 256;
80                         *q++ = x % 256;
81                         *q++ = (x + y) % 256;
82                         *q++ = 1;
83                 }
84                 p += sub_image->stride()[0];
85         }
86
87         shared_ptr<FileLog> log = make_shared<FileLog> ("build/test/client_server_test_rgb.log");
88
89         shared_ptr<PlayerVideo> pvf (
90                 new PlayerVideo (
91                         make_shared<RawImageProxy> (image),
92                         DCPTime (),
93                         Crop (),
94                         optional<double> (),
95                         dcp::Size (1998, 1080),
96                         dcp::Size (1998, 1080),
97                         EYES_BOTH,
98                         PART_WHOLE,
99                         ColourConversion ()
100                         )
101                 );
102
103         pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
104
105         shared_ptr<DCPVideo> frame (
106                 new DCPVideo (
107                         pvf,
108                         0,
109                         24,
110                         200000000,
111                         RESOLUTION_2K,
112                         log
113                         )
114                 );
115
116         Data locally_encoded = frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
117
118         EncodeServer* server = new EncodeServer (log, true, 2);
119
120         new thread (boost::bind (&EncodeServer::run, server));
121
122         /* Let the server get itself ready */
123         dcpomatic_sleep (1);
124
125         EncodeServerDescription description ("localhost", 2);
126
127         list<thread*> threads;
128         for (int i = 0; i < 8; ++i) {
129                 threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
130         }
131
132         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
133                 (*i)->join ();
134         }
135
136         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
137                 delete *i;
138         }
139
140         delete server;
141 }
142
143 BOOST_AUTO_TEST_CASE (client_server_test_yuv)
144 {
145         shared_ptr<Image> image = make_shared<Image> (AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true);
146
147         for (int i = 0; i < image->planes(); ++i) {
148                 uint8_t* p = image->data()[i];
149                 for (int j = 0; j < image->line_size()[i]; ++j) {
150                         *p++ = j % 256;
151                 }
152         }
153
154         shared_ptr<Image> sub_image = make_shared<Image> (AV_PIX_FMT_RGBA, dcp::Size (100, 200), true);
155         uint8_t* p = sub_image->data()[0];
156         for (int y = 0; y < 200; ++y) {
157                 uint8_t* q = p;
158                 for (int x = 0; x < 100; ++x) {
159                         *q++ = y % 256;
160                         *q++ = x % 256;
161                         *q++ = (x + y) % 256;
162                         *q++ = 1;
163                 }
164                 p += sub_image->stride()[0];
165         }
166
167         shared_ptr<FileLog> log = make_shared<FileLog> ("build/test/client_server_test_yuv.log");
168
169         shared_ptr<PlayerVideo> pvf (
170                 new PlayerVideo (
171                         make_shared<RawImageProxy> (image),
172                         DCPTime (),
173                         Crop (),
174                         optional<double> (),
175                         dcp::Size (1998, 1080),
176                         dcp::Size (1998, 1080),
177                         EYES_BOTH,
178                         PART_WHOLE,
179                         ColourConversion ()
180                         )
181                 );
182
183         pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
184
185         shared_ptr<DCPVideo> frame (
186                 new DCPVideo (
187                         pvf,
188                         0,
189                         24,
190                         200000000,
191                         RESOLUTION_2K,
192                         log
193                         )
194                 );
195
196         Data locally_encoded = frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
197
198         EncodeServer* server = new EncodeServer (log, true, 2);
199
200         new thread (boost::bind (&EncodeServer::run, server));
201
202         /* Let the server get itself ready */
203         dcpomatic_sleep (1);
204
205         EncodeServerDescription description ("localhost", 2);
206
207         list<thread*> threads;
208         for (int i = 0; i < 8; ++i) {
209                 threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
210         }
211
212         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
213                 (*i)->join ();
214         }
215
216         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
217                 delete *i;
218         }
219
220         delete server;
221 }
222
223 BOOST_AUTO_TEST_CASE (client_server_test_j2k)
224 {
225         shared_ptr<Image> image = make_shared<Image> (AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true);
226
227         for (int i = 0; i < image->planes(); ++i) {
228                 uint8_t* p = image->data()[i];
229                 for (int j = 0; j < image->line_size()[i]; ++j) {
230                         *p++ = j % 256;
231                 }
232         }
233
234         shared_ptr<FileLog> log = make_shared<FileLog> ("build/test/client_server_test_j2k.log");
235
236         shared_ptr<PlayerVideo> raw_pvf (
237                 new PlayerVideo (
238                         make_shared<RawImageProxy> (image),
239                         DCPTime (),
240                         Crop (),
241                         optional<double> (),
242                         dcp::Size (1998, 1080),
243                         dcp::Size (1998, 1080),
244                         EYES_BOTH,
245                         PART_WHOLE,
246                         ColourConversion ()
247                         )
248                 );
249
250         shared_ptr<DCPVideo> raw_frame (
251                 new DCPVideo (
252                         raw_pvf,
253                         0,
254                         24,
255                         200000000,
256                         RESOLUTION_2K,
257                         log
258                         )
259                 );
260
261         Data raw_locally_encoded = raw_frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
262
263         shared_ptr<PlayerVideo> j2k_pvf (
264                 new PlayerVideo (
265                         /* This J2KImageProxy constructor is private, so no make_shared */
266                         shared_ptr<J2KImageProxy> (new J2KImageProxy (raw_locally_encoded, dcp::Size (1998, 1080))),
267                         DCPTime (),
268                         Crop (),
269                         optional<double> (),
270                         dcp::Size (1998, 1080),
271                         dcp::Size (1998, 1080),
272                         EYES_BOTH,
273                         PART_WHOLE,
274                         PresetColourConversion::all().front().conversion
275                         )
276                 );
277
278         shared_ptr<DCPVideo> j2k_frame (
279                 new DCPVideo (
280                         j2k_pvf,
281                         0,
282                         24,
283                         200000000,
284                         RESOLUTION_2K,
285                         log
286                         )
287                 );
288
289         Data j2k_locally_encoded = j2k_frame->encode_locally (boost::bind (&Log::dcp_log, log.get(), _1, _2));
290
291         EncodeServer* server = new EncodeServer (log, true, 2);
292
293         new thread (boost::bind (&EncodeServer::run, server));
294
295         /* Let the server get itself ready */
296         dcpomatic_sleep (1);
297
298         EncodeServerDescription description ("localhost", 2);
299
300         list<thread*> threads;
301         for (int i = 0; i < 8; ++i) {
302                 threads.push_back (new thread (boost::bind (do_remote_encode, j2k_frame, description, j2k_locally_encoded)));
303         }
304
305         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
306                 (*i)->join ();
307         }
308
309         for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
310                 delete *i;
311         }
312
313         delete server;
314 }