From 93c3365a547fbb7467b6c47571c5a68e17b31e0c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 23 Sep 2012 14:02:01 +0100 Subject: Untested first cut. --- src/lib/util.h | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'src/lib/util.h') diff --git a/src/lib/util.h b/src/lib/util.h index 568fe05d0..c3a42e448 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -56,29 +56,6 @@ enum ContentType { extern void md5_data (std::string, void const *, int); #endif -/** @class SocketReader - * @brief A helper class from reading from sockets. - * - * You can probably do this stuff directly in boost, but I'm not sure how. - */ -class SocketReader -{ -public: - SocketReader (boost::shared_ptr); - - void read_definite_and_consume (uint8_t *, int); - void read_indefinite (uint8_t *, int); - void consume (int); - -private: - /** socket we are reading from */ - boost::shared_ptr _socket; - /** a buffer for small reads */ - uint8_t _buffer[256]; - /** amount of valid data in the buffer */ - int _buffer_data; -}; - /** @class Size * @brief Representation of the size of something */ struct Size @@ -136,4 +113,31 @@ extern std::string crop_string (Position, Size); extern int dcp_audio_sample_rate (int); extern std::string colour_lut_index_to_name (int index); +class DeadlineWrapper +{ +public: + DeadlineWrapper (boost::asio::io_service& io_service); + + void set_socket (boost::shared_ptr socket); + + void connect (boost::asio::ip::basic_resolver_entry const & endpoint, int timeout); + void write (uint8_t const * data, int size, int timeout); + int read (uint8_t* data, int size, int timeout); + + void read_definite_and_consume (uint8_t* data, int size, int timeout); + void read_indefinite (uint8_t* data, int size, int timeout); + void consume (int amount); + +private: + void check (); + + boost::asio::io_service& _io_service; + boost::asio::deadline_timer _deadline; + boost::shared_ptr _socket; + /** a buffer for small reads */ + uint8_t _buffer[256]; + /** amount of valid data in the buffer */ + int _buffer_data; +}; + #endif -- cgit v1.2.3 From 6726393a4b186333b8e1080f3f1c5c4b77d4c2e6 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 23 Sep 2012 16:51:10 +0100 Subject: Multi-thread test. --- src/lib/util.h | 2 ++ test/test.cc | 53 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 17 deletions(-) (limited to 'src/lib/util.h') diff --git a/src/lib/util.h b/src/lib/util.h index c3a42e448..2785a5dc1 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -131,6 +131,8 @@ public: private: void check (); + DeadlineWrapper (DeadlineWrapper const &); + boost::asio::io_service& _io_service; boost::asio::deadline_timer _deadline; boost::shared_ptr _socket; diff --git a/test/test.cc b/test/test.cc index 2a99c862f..b77eb2b51 100644 --- a/test/test.cc +++ b/test/test.cc @@ -254,6 +254,17 @@ BOOST_AUTO_TEST_CASE (paths_test) BOOST_CHECK_EQUAL (s.content_path(), "build/test/a/b/c/d/e/foo/bar/baz"); } +void +do_remote_encode (shared_ptr frame, ServerDescription* description, shared_ptr locally_encoded) +{ + shared_ptr remotely_encoded; + BOOST_CHECK_NO_THROW (remotely_encoded = frame->encode_remotely (description)); + BOOST_CHECK (remotely_encoded); + + BOOST_CHECK_EQUAL (locally_encoded->size(), remotely_encoded->size()); + BOOST_CHECK (memcmp (locally_encoded->data(), remotely_encoded->data(), locally_encoded->size()) == 0); +} + BOOST_AUTO_TEST_CASE (client_server_test) { shared_ptr image (new SimpleImage (PIX_FMT_RGB24, Size (1998, 1080))); @@ -271,29 +282,37 @@ BOOST_AUTO_TEST_CASE (client_server_test) FileLog log ("build/test/client_server_test.log"); - DCPVideoFrame frame ( - image, - Size (1998, 1080), - 0, - Scaler::from_id ("bicubic"), - 0, - 24, - "", - 0, - 200000000, - &log + shared_ptr frame ( + new DCPVideoFrame ( + image, + Size (1998, 1080), + 0, + Scaler::from_id ("bicubic"), + 0, + 24, + "", + 0, + 200000000, + &log + ) ); - shared_ptr locally_encoded = frame.encode_locally (); + shared_ptr locally_encoded = frame->encode_locally (); Config::instance()->set_server_port (61920); Server* server = new Server (&log); - new thread (boost::bind (&Server::run, server, 1)); + new thread (boost::bind (&Server::run, server, 2)); - ServerDescription description ("localhost", 1); - shared_ptr remotely_encoded = frame.encode_remotely (&description); + ServerDescription description ("localhost", 2); - BOOST_CHECK_EQUAL (locally_encoded->size(), remotely_encoded->size()); - BOOST_CHECK (memcmp (locally_encoded->data(), remotely_encoded->data(), locally_encoded->size()) == 0); + thread* a = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); + thread* b = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); + thread* c = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); + thread* d = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); + + a->join (); + b->join (); + c->join (); + d->join (); } -- cgit v1.2.3 From e89fb9d81358b51ed0e231725f7fb6eb63f96c5b Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 23 Sep 2012 17:50:31 +0100 Subject: Use io_service per thread. --- src/lib/dcp_video_frame.cc | 11 ++++------- src/lib/dcp_video_frame.h | 2 +- src/lib/server.cc | 28 +++++++++++++--------------- src/lib/server.h | 7 ++++--- src/lib/util.cc | 30 ++++++++---------------------- src/lib/util.h | 10 ++++++---- test/test.cc | 17 ++++++++--------- 7 files changed, 44 insertions(+), 61 deletions(-) (limited to 'src/lib/util.h') diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index ee29d8601..5c0ec6a6a 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -297,10 +297,7 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) asio::ip::tcp::resolver::query query (serv->host_name(), boost::lexical_cast (Config::instance()->server_port ())); asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query); - shared_ptr socket (new asio::ip::tcp::socket (io_service)); - - DeadlineWrapper wrapper (io_service); - wrapper.set_socket (socket); + DeadlineWrapper wrapper; wrapper.connect (*endpoint_iterator, 30); @@ -378,12 +375,12 @@ EncodedData::write (shared_ptr opt, int frame) * @param socket Socket */ void -EncodedData::send (DeadlineWrapper& wrapper) +EncodedData::send (shared_ptr wrapper) { stringstream s; s << _size; - wrapper.write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); - wrapper.write (_data, _size, 30); + wrapper->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); + wrapper->write (_data, _size, 30); } #ifdef DEBUG_HASH diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index d82aee367..752f0dda7 100644 --- a/src/lib/dcp_video_frame.h +++ b/src/lib/dcp_video_frame.h @@ -48,7 +48,7 @@ public: virtual ~EncodedData () {} - void send (DeadlineWrapper& wrapper); + void send (boost::shared_ptr wrapper); void write (boost::shared_ptr, int); #ifdef DEBUG_HASH diff --git a/src/lib/server.cc b/src/lib/server.cc index 9e61c2282..1f860d254 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -70,14 +70,11 @@ Server::Server (Log* log) } int -Server::process (shared_ptr socket) +Server::process (shared_ptr wrapper) { - DeadlineWrapper wrapper (_io_service); - wrapper.set_socket (socket); - char buffer[128]; - wrapper.read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); - wrapper.consume (strlen (buffer) + 1); + wrapper->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); + wrapper->consume (strlen (buffer) + 1); stringstream s (buffer); @@ -124,7 +121,7 @@ Server::process (shared_ptr socket) } for (int i = 0; i < image->components(); ++i) { - wrapper.read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); + wrapper->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); } #ifdef DEBUG_HASH @@ -151,7 +148,7 @@ Server::worker_thread () _worker_condition.wait (lock); } - shared_ptr socket = _queue.front (); + shared_ptr wrapper = _queue.front (); _queue.pop_front (); lock.unlock (); @@ -162,12 +159,12 @@ Server::worker_thread () gettimeofday (&start, 0); try { - frame = process (socket); + frame = process (wrapper); } catch (std::exception& e) { cerr << "Error: " << e.what() << "\n"; } - socket.reset (); + wrapper.reset (); lock.lock (); @@ -193,11 +190,12 @@ Server::run (int num_threads) for (int i = 0; i < num_threads; ++i) { _worker_threads.push_back (new thread (bind (&Server::worker_thread, this))); } - - asio::ip::tcp::acceptor acceptor (_io_service, asio::ip::tcp::endpoint (asio::ip::tcp::v4(), Config::instance()->server_port ())); + + asio::io_service io_service; + asio::ip::tcp::acceptor acceptor (io_service, asio::ip::tcp::endpoint (asio::ip::tcp::v4(), Config::instance()->server_port ())); while (1) { - shared_ptr socket (new asio::ip::tcp::socket (_io_service)); - acceptor.accept (*socket); + shared_ptr wrapper (new DeadlineWrapper); + acceptor.accept (wrapper->socket ()); mutex::scoped_lock lock (_worker_mutex); @@ -206,7 +204,7 @@ Server::run (int num_threads) _worker_condition.wait (lock); } - _queue.push_back (socket); + _queue.push_back (wrapper); _worker_condition.notify_all (); } } diff --git a/src/lib/server.h b/src/lib/server.h index 747081443..4cb6f2563 100644 --- a/src/lib/server.h +++ b/src/lib/server.h @@ -28,6 +28,8 @@ #include #include "log.h" +class DeadlineWrapper; + /** @class ServerDescription * @brief Class to describe a server to which we can send encoding work. */ @@ -80,11 +82,10 @@ public: private: void worker_thread (); - int process (boost::shared_ptr socket); + int process (boost::shared_ptr wrapper); - boost::asio::io_service _io_service; std::vector _worker_threads; - std::list > _queue; + std::list > _queue; boost::mutex _worker_mutex; boost::condition _worker_condition; Log* _log; diff --git a/src/lib/util.cc b/src/lib/util.cc index 3f48d696b..8713c5922 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -438,28 +438,20 @@ colour_lut_index_to_name (int index) return ""; } -DeadlineWrapper::DeadlineWrapper (asio::io_service& io_service) - : _io_service (io_service) - , _deadline (io_service) +DeadlineWrapper::DeadlineWrapper () + : _deadline (_io_service) + , _socket (_io_service) , _buffer_data (0) { _deadline.expires_at (posix_time::pos_infin); check (); } -void -DeadlineWrapper::set_socket (shared_ptr socket) -{ - _socket = socket; -} - void DeadlineWrapper::check () { if (_deadline.expires_at() <= asio::deadline_timer::traits_type::now ()) { - if (_socket) { - _socket->close (); - } + _socket.close (); _deadline.expires_at (posix_time::pos_infin); } @@ -469,15 +461,13 @@ DeadlineWrapper::check () void DeadlineWrapper::connect (asio::ip::basic_resolver_entry const & endpoint, int timeout) { - assert (_socket); - system::error_code ec = asio::error::would_block; - _socket->async_connect (endpoint, lambda::var(ec) = lambda::_1); + _socket.async_connect (endpoint, lambda::var(ec) = lambda::_1); do { _io_service.run_one(); } while (ec == asio::error::would_block); - if (ec || !_socket->is_open ()) { + if (ec || !_socket.is_open ()) { throw NetworkError ("connect timed out"); } } @@ -485,12 +475,10 @@ DeadlineWrapper::connect (asio::ip::basic_resolver_entry const & void DeadlineWrapper::write (uint8_t const * data, int size, int timeout) { - assert (_socket); - _deadline.expires_from_now (posix_time::seconds (timeout)); system::error_code ec = asio::error::would_block; - asio::async_write (*_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1); + asio::async_write (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1); do { _io_service.run_one (); } while (ec == asio::error::would_block); @@ -503,14 +491,12 @@ DeadlineWrapper::write (uint8_t const * data, int size, int timeout) int DeadlineWrapper::read (uint8_t* data, int size, int timeout) { - assert (_socket); - _deadline.expires_from_now (posix_time::seconds (timeout)); system::error_code ec = asio::error::would_block; int amount_read = 0; - _socket->async_read_some ( + _socket.async_read_some ( asio::buffer (data, size), (lambda::var(ec) = lambda::_1, lambda::var(amount_read) = lambda::_2) ); diff --git a/src/lib/util.h b/src/lib/util.h index 2785a5dc1..8d6e2f541 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -116,9 +116,11 @@ extern std::string colour_lut_index_to_name (int index); class DeadlineWrapper { public: - DeadlineWrapper (boost::asio::io_service& io_service); + DeadlineWrapper (); - void set_socket (boost::shared_ptr socket); + boost::asio::ip::tcp::socket& socket () { + return _socket; + } void connect (boost::asio::ip::basic_resolver_entry const & endpoint, int timeout); void write (uint8_t const * data, int size, int timeout); @@ -133,9 +135,9 @@ private: DeadlineWrapper (DeadlineWrapper const &); - boost::asio::io_service& _io_service; + boost::asio::io_service _io_service; boost::asio::deadline_timer _deadline; - boost::shared_ptr _socket; + boost::asio::ip::tcp::socket _socket; /** a buffer for small reads */ uint8_t _buffer[256]; /** amount of valid data in the buffer */ diff --git a/test/test.cc b/test/test.cc index b77eb2b51..638d526e0 100644 --- a/test/test.cc +++ b/test/test.cc @@ -306,13 +306,12 @@ BOOST_AUTO_TEST_CASE (client_server_test) ServerDescription description ("localhost", 2); - thread* a = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); - thread* b = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); - thread* c = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); - thread* d = new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)); - - a->join (); - b->join (); - c->join (); - d->join (); + list threads; + for (int i = 0; i < 8; ++i) { + threads.push_back (new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded))); + } + + for (list::iterator i = threads.begin(); i != threads.end(); ++i) { + (*i)->join (); + } } -- cgit v1.2.3 From 737c3392039740f7a22a9ff922f8492905173b9c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 23 Sep 2012 17:56:08 +0100 Subject: Tidy up naming. --- src/lib/dcp_video_frame.cc | 21 ++++++++++----------- src/lib/dcp_video_frame.h | 2 +- src/lib/server.cc | 22 +++++++++++----------- src/lib/server.h | 6 +++--- src/lib/util.cc | 18 +++++++++--------- src/lib/util.h | 8 ++++---- 6 files changed, 38 insertions(+), 39 deletions(-) (limited to 'src/lib/util.h') diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 5c0ec6a6a..d8af3462d 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -293,13 +293,12 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) { asio::io_service io_service; asio::ip::tcp::resolver resolver (io_service); - asio::ip::tcp::resolver::query query (serv->host_name(), boost::lexical_cast (Config::instance()->server_port ())); asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query); - DeadlineWrapper wrapper; + Socket socket; - wrapper.connect (*endpoint_iterator, 30); + socket.connect (*endpoint_iterator, 30); #ifdef DEBUG_HASH _input->hash ("Input for remote encoding (before sending)"); @@ -322,19 +321,19 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) s << _input->line_size()[i] << " "; } - wrapper.write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); + socket.write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); for (int i = 0; i < _input->components(); ++i) { - wrapper.write (_input->data()[i], _input->line_size()[i] * _input->lines(i), 30); + socket.write (_input->data()[i], _input->line_size()[i] * _input->lines(i), 30); } char buffer[32]; - wrapper.read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); - wrapper.consume (strlen (buffer) + 1); + socket.read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); + socket.consume (strlen (buffer) + 1); shared_ptr e (new RemotelyEncodedData (atoi (buffer))); /* now read the rest */ - wrapper.read_definite_and_consume (e->data(), e->size(), 30); + socket.read_definite_and_consume (e->data(), e->size(), 30); #ifdef DEBUG_HASH e->hash ("Encoded image (after receiving)"); @@ -375,12 +374,12 @@ EncodedData::write (shared_ptr opt, int frame) * @param socket Socket */ void -EncodedData::send (shared_ptr wrapper) +EncodedData::send (shared_ptr socket) { stringstream s; s << _size; - wrapper->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); - wrapper->write (_data, _size, 30); + socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); + socket->write (_data, _size, 30); } #ifdef DEBUG_HASH diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index 752f0dda7..da4e0c301 100644 --- a/src/lib/dcp_video_frame.h +++ b/src/lib/dcp_video_frame.h @@ -48,7 +48,7 @@ public: virtual ~EncodedData () {} - void send (boost::shared_ptr wrapper); + void send (boost::shared_ptr socket); void write (boost::shared_ptr, int); #ifdef DEBUG_HASH diff --git a/src/lib/server.cc b/src/lib/server.cc index 1f860d254..8ca426049 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -70,11 +70,11 @@ Server::Server (Log* log) } int -Server::process (shared_ptr wrapper) +Server::process (shared_ptr socket) { char buffer[128]; - wrapper->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); - wrapper->consume (strlen (buffer) + 1); + socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); + socket->consume (strlen (buffer) + 1); stringstream s (buffer); @@ -121,7 +121,7 @@ Server::process (shared_ptr wrapper) } for (int i = 0; i < image->components(); ++i) { - wrapper->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); + socket->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); } #ifdef DEBUG_HASH @@ -130,7 +130,7 @@ Server::process (shared_ptr wrapper) DCPVideoFrame dcp_video_frame (image, out_size, padding, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log); shared_ptr encoded = dcp_video_frame.encode_locally (); - encoded->send (wrapper); + encoded->send (socket); #ifdef DEBUG_HASH encoded->hash ("Encoded image (as made by server and as sent back)"); @@ -148,7 +148,7 @@ Server::worker_thread () _worker_condition.wait (lock); } - shared_ptr wrapper = _queue.front (); + shared_ptr socket = _queue.front (); _queue.pop_front (); lock.unlock (); @@ -159,12 +159,12 @@ Server::worker_thread () gettimeofday (&start, 0); try { - frame = process (wrapper); + frame = process (socket); } catch (std::exception& e) { cerr << "Error: " << e.what() << "\n"; } - wrapper.reset (); + socket.reset (); lock.lock (); @@ -194,8 +194,8 @@ Server::run (int num_threads) asio::io_service io_service; asio::ip::tcp::acceptor acceptor (io_service, asio::ip::tcp::endpoint (asio::ip::tcp::v4(), Config::instance()->server_port ())); while (1) { - shared_ptr wrapper (new DeadlineWrapper); - acceptor.accept (wrapper->socket ()); + shared_ptr socket (new Socket); + acceptor.accept (socket->socket ()); mutex::scoped_lock lock (_worker_mutex); @@ -204,7 +204,7 @@ Server::run (int num_threads) _worker_condition.wait (lock); } - _queue.push_back (wrapper); + _queue.push_back (socket); _worker_condition.notify_all (); } } diff --git a/src/lib/server.h b/src/lib/server.h index 4cb6f2563..32ba8dc4b 100644 --- a/src/lib/server.h +++ b/src/lib/server.h @@ -28,7 +28,7 @@ #include #include "log.h" -class DeadlineWrapper; +class Socket; /** @class ServerDescription * @brief Class to describe a server to which we can send encoding work. @@ -82,10 +82,10 @@ public: private: void worker_thread (); - int process (boost::shared_ptr wrapper); + int process (boost::shared_ptr socket); std::vector _worker_threads; - std::list > _queue; + std::list > _queue; boost::mutex _worker_mutex; boost::condition _worker_condition; Log* _log; diff --git a/src/lib/util.cc b/src/lib/util.cc index 8713c5922..d12bd3e77 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -438,7 +438,7 @@ colour_lut_index_to_name (int index) return ""; } -DeadlineWrapper::DeadlineWrapper () +Socket::Socket () : _deadline (_io_service) , _socket (_io_service) , _buffer_data (0) @@ -448,18 +448,18 @@ DeadlineWrapper::DeadlineWrapper () } void -DeadlineWrapper::check () +Socket::check () { if (_deadline.expires_at() <= asio::deadline_timer::traits_type::now ()) { _socket.close (); _deadline.expires_at (posix_time::pos_infin); } - _deadline.async_wait (boost::bind (&DeadlineWrapper::check, this)); + _deadline.async_wait (boost::bind (&Socket::check, this)); } void -DeadlineWrapper::connect (asio::ip::basic_resolver_entry const & endpoint, int timeout) +Socket::connect (asio::ip::basic_resolver_entry const & endpoint, int timeout) { system::error_code ec = asio::error::would_block; _socket.async_connect (endpoint, lambda::var(ec) = lambda::_1); @@ -473,7 +473,7 @@ DeadlineWrapper::connect (asio::ip::basic_resolver_entry const & } void -DeadlineWrapper::write (uint8_t const * data, int size, int timeout) +Socket::write (uint8_t const * data, int size, int timeout) { _deadline.expires_from_now (posix_time::seconds (timeout)); system::error_code ec = asio::error::would_block; @@ -489,7 +489,7 @@ DeadlineWrapper::write (uint8_t const * data, int size, int timeout) } int -DeadlineWrapper::read (uint8_t* data, int size, int timeout) +Socket::read (uint8_t* data, int size, int timeout) { _deadline.expires_from_now (posix_time::seconds (timeout)); system::error_code ec = asio::error::would_block; @@ -517,7 +517,7 @@ DeadlineWrapper::read (uint8_t* data, int size, int timeout) * @param size Amount of data to consume, in bytes. */ void -DeadlineWrapper::consume (int size) +Socket::consume (int size) { assert (_buffer_data >= size); @@ -534,7 +534,7 @@ DeadlineWrapper::consume (int size) * @param size Number of bytes to read. */ void -DeadlineWrapper::read_definite_and_consume (uint8_t* data, int size, int timeout) +Socket::read_definite_and_consume (uint8_t* data, int size, int timeout) { int const from_buffer = min (_buffer_data, size); if (from_buffer > 0) { @@ -563,7 +563,7 @@ DeadlineWrapper::read_definite_and_consume (uint8_t* data, int size, int timeout * @param size Maximum amount of data to read. */ void -DeadlineWrapper::read_indefinite (uint8_t* data, int size, int timeout) +Socket::read_indefinite (uint8_t* data, int size, int timeout) { assert (size < int (sizeof (_buffer))); diff --git a/src/lib/util.h b/src/lib/util.h index 8d6e2f541..d7f233003 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -113,10 +113,10 @@ extern std::string crop_string (Position, Size); extern int dcp_audio_sample_rate (int); extern std::string colour_lut_index_to_name (int index); -class DeadlineWrapper +class Socket { public: - DeadlineWrapper (); + Socket (); boost::asio::ip::tcp::socket& socket () { return _socket; @@ -124,7 +124,6 @@ public: void connect (boost::asio::ip::basic_resolver_entry const & endpoint, int timeout); void write (uint8_t const * data, int size, int timeout); - int read (uint8_t* data, int size, int timeout); void read_definite_and_consume (uint8_t* data, int size, int timeout); void read_indefinite (uint8_t* data, int size, int timeout); @@ -132,8 +131,9 @@ public: private: void check (); + int read (uint8_t* data, int size, int timeout); - DeadlineWrapper (DeadlineWrapper const &); + Socket (Socket const &); boost::asio::io_service _io_service; boost::asio::deadline_timer _deadline; -- cgit v1.2.3 From 3fc9a435a720d8b2abd78c1bdc7b34bc635ad797 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 24 Sep 2012 01:58:56 +0100 Subject: Some doxygen documentation improvements. --- Doxyfile | 2 +- doc/mainpage.txt | 2 +- src/lib/config.h | 18 +++++++++++++----- src/lib/decoder.cc | 2 ++ src/lib/encoder.cc | 5 +++++ src/lib/encoder.h | 5 +++++ src/lib/exceptions.h | 5 +++++ src/lib/job.cc | 4 +++- src/lib/job.h | 12 +++++++++--- src/lib/util.cc | 23 +++++++++++++++++++++++ src/lib/util.h | 19 ++++++++++++++++++- src/wx/film_viewer.cc | 3 +++ src/wx/wx_util.cc | 19 ++++++++++++++++++- src/wx/wx_util.h | 5 ++++- 14 files changed, 110 insertions(+), 14 deletions(-) (limited to 'src/lib/util.h') diff --git a/Doxyfile b/Doxyfile index 80a4b9c25..56f7e1d3c 100644 --- a/Doxyfile +++ b/Doxyfile @@ -661,7 +661,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = src \ +INPUT = src/lib src/wx src/tools \ doc/mainpage.txt # This tag can be used to specify the character encoding of the source files diff --git a/doc/mainpage.txt b/doc/mainpage.txt index 81c3b4558..e89ca8d26 100644 --- a/doc/mainpage.txt +++ b/doc/mainpage.txt @@ -23,7 +23,7 @@ * and libsndfile (http://www.mega-nerd.com/libsndfile/) for WAV file manipulation. It * also makes heavy use of the boost libraries (http://www.boost.org/). libtiff * (http://www.libtiff.org/) is used for TIFF encoding and decoding, and the GUI is - * built using GTK (http://www.gtk.org/) and GTKMM (http://www.gtkmm.org). It also uses libmhash (http://mhash.sourceforge.net/) + * built using wxWidgets (http://wxwidgets.org/). It also uses libmhash (http://mhash.sourceforge.net/) * for debugging purposes. * * Thanks are due to the authors and communities of all DVD-o-matic's dependencies. diff --git a/src/lib/config.h b/src/lib/config.h index b002da7df..840dcdaef 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -81,18 +81,22 @@ public: return _reference_filters; } + /** @return The IP address of a TMS that we can copy DCPs to */ std::string tms_ip () const { return _tms_ip; } + /** @return The path on a TMS that we should write DCPs to */ std::string tms_path () const { return _tms_path; } + /** @return User name to log into the TMS with */ std::string tms_user () const { return _tms_user; } + /** @return Password to log into the TMS with */ std::string tms_password () const { return _tms_password; } @@ -146,21 +150,25 @@ public: Changed (); } + /** @param i IP address of a TMS that we can copy DCPs to */ void set_tms_ip (std::string i) { _tms_ip = i; Changed (); } + /** @param p Path on a TMS that we should write DCPs to */ void set_tms_path (std::string p) { _tms_path = p; Changed (); } + /** @param u User name to log into the TMS with */ void set_tms_user (std::string u) { _tms_user = u; Changed (); } + /** @param p Password to log into the TMS with */ void set_tms_password (std::string p) { _tms_password = p; Changed (); @@ -189,21 +197,21 @@ private: /** J2K encoding servers to use */ std::vector _servers; - /** Screen definitions */ std::vector > _screens; - /** Scaler to use for the "A" part of A/B comparisons */ Scaler const * _reference_scaler; - /** Filters to use for the "A" part of A/B comparisons */ std::vector _reference_filters; - + /** The IP address of a TMS that we can copy DCPs to */ std::string _tms_ip; + /** The path on a TMS that we should write DCPs to */ std::string _tms_path; + /** User name to log into the TMS with */ std::string _tms_user; + /** Password to log into the TMS with */ std::string _tms_password; - + /** Our sound processor */ SoundProcessor const * _sound_processor; /** Singleton instance, or 0 */ diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index fc808d819..9332511bc 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -87,6 +87,7 @@ Decoder::~Decoder () delete _delay_line; } +/** Start off a decode processing run */ void Decoder::process_begin () { @@ -120,6 +121,7 @@ Decoder::process_begin () _audio_frames_processed = 0; } +/** Finish off a decode processing run */ void Decoder::process_end () { diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 18ccd3f57..62ba922da 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -60,6 +60,7 @@ Encoder::current_frames_per_second () const return _history_size / (seconds (now) - seconds (_time_history.back ())); } +/** @return true if the last frame to be processed was skipped as it already existed */ bool Encoder::skipping () const { @@ -67,6 +68,7 @@ Encoder::skipping () const return _just_skipped; } +/** @return Index of last frame to be successfully encoded */ int Encoder::last_frame () const { @@ -74,6 +76,9 @@ Encoder::last_frame () const return _last_frame; } +/** Should be called when a frame has been encoded successfully. + * @param n Frame index. + */ void Encoder::frame_done (int n) { diff --git a/src/lib/encoder.h b/src/lib/encoder.h index 5c0c4c03f..539b2912c 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -84,10 +84,15 @@ protected: /** Mutex for _time_history, _just_skipped and _last_frame */ mutable boost::mutex _history_mutex; + /** List of the times of completion of the last _history_size frames; + first is the most recently completed. + */ std::list _time_history; + /** Number of frames that we should keep history for */ static int const _history_size; /** true if the last frame we processed was skipped (because it was already done) */ bool _just_skipped; + /** Index of the last frame to be processed */ int _last_frame; }; diff --git a/src/lib/exceptions.h b/src/lib/exceptions.h index 6b567805b..8ef09875b 100644 --- a/src/lib/exceptions.h +++ b/src/lib/exceptions.h @@ -77,6 +77,9 @@ public: class FileError : public StringError { public: + /** @param m Error message. + * @param f Name of the file that this exception concerns. + */ FileError (std::string m, std::string f) : StringError (m) , _file (f) @@ -84,11 +87,13 @@ public: virtual ~FileError () throw () {} + /** @return name of the file that this exception concerns */ std::string file () const { return _file; } private: + /** name of the file that this exception concerns */ std::string _file; }; diff --git a/src/lib/job.cc b/src/lib/job.cc index d446b3913..22754eb90 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -223,7 +223,7 @@ Job::set_error (string e) _error = e; } -/** Set that this job's progress will always be unknown */ +/** Say that this job's progress will always be unknown */ void Job::set_progress_unknown () { @@ -231,6 +231,7 @@ Job::set_progress_unknown () _progress_unknown = true; } +/** @return Human-readable status of this job */ string Job::status () const { @@ -252,6 +253,7 @@ Job::status () const return s.str (); } +/** @return An estimate of the remaining time for this job, in seconds */ int Job::remaining_time () const { diff --git a/src/lib/job.h b/src/lib/job.h index 95599bdbb..fee887b42 100644 --- a/src/lib/job.h +++ b/src/lib/job.h @@ -72,6 +72,7 @@ protected: virtual int remaining_time () const; + /** Description of a job's state */ enum State { NEW, ///< the job hasn't been started yet RUNNING, ///< the job is running @@ -82,10 +83,11 @@ protected: void set_state (State); void set_error (std::string e); + /** FilmState for this job */ boost::shared_ptr _fs; + /** options in use for this job */ boost::shared_ptr _opt; - - /** A log that this job can write to */ + /** a log that this job can write to */ Log* _log; private: @@ -94,11 +96,15 @@ private: /** mutex for _state and _error */ mutable boost::mutex _state_mutex; + /** current state of the job */ State _state; + /** message for an error that has occurred (when state == FINISHED_ERROR) */ std::string _error; + /** time that this job was started */ time_t _start_time; - + + /** mutex for _stack and _progress_unknown */ mutable boost::mutex _progress_mutex; struct Level { diff --git a/src/lib/util.cc b/src/lib/util.cc index d12bd3e77..73222083a 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -369,6 +369,9 @@ md5_data (string title, void const * data, int size) } #endif +/** @param file File name. + * @return MD5 digest of file's contents. + */ string md5_digest (string file) { @@ -404,6 +407,9 @@ md5_digest (string file) return s.str (); } +/** @param An arbitrary sampling rate. + * @return The appropriate DCP-approved sampling rate (48kHz or 96kHz). + */ int dcp_audio_sample_rate (int fs) { @@ -424,6 +430,9 @@ bool operator!= (Crop const & a, Crop const & b) return !(a == b); } +/** @param index Colour LUT index. + * @return Human-readable name. + */ string colour_lut_index_to_name (int index) { @@ -458,6 +467,10 @@ Socket::check () _deadline.async_wait (boost::bind (&Socket::check, this)); } +/** Blocking connect with timeout. + * @param endpoint End-point to connect to. + * @param timeout Time-out in seconds. + */ void Socket::connect (asio::ip::basic_resolver_entry const & endpoint, int timeout) { @@ -472,6 +485,11 @@ Socket::connect (asio::ip::basic_resolver_entry const & endpoint, } } +/** Blocking write with timeout. + * @param data Buffer to write. + * @param size Number of bytes to write. + * @param timeout Time-out, in seconds. + */ void Socket::write (uint8_t const * data, int size, int timeout) { @@ -488,6 +506,11 @@ Socket::write (uint8_t const * data, int size, int timeout) } } +/** Blocking read with timeout. + * @param data Buffer to read to. + * @param size Number of bytes to read. + * @param timeout Time-out, in seconds. + */ int Socket::read (uint8_t* data, int size, int timeout) { diff --git a/src/lib/util.h b/src/lib/util.h index d7f233003..63d492e60 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -80,19 +80,25 @@ struct Size int height; }; +/** A description of the crop of an image or video. */ struct Crop { Crop () : left (0), right (0), top (0), bottom (0) {} - + + /** Number of pixels to remove from the left-hand side */ int left; + /** Number of pixels to remove from the right-hand side */ int right; + /** Number of pixels to remove from the top */ int top; + /** Number of pixels to remove from the bottom */ int bottom; }; extern bool operator== (Crop const & a, Crop const & b); extern bool operator!= (Crop const & a, Crop const & b); +/** A position */ struct Position { Position () @@ -105,7 +111,9 @@ struct Position , y (y_) {} + /** x coordinate */ int x; + /** y coordinate */ int y; }; @@ -113,11 +121,20 @@ extern std::string crop_string (Position, Size); extern int dcp_audio_sample_rate (int); extern std::string colour_lut_index_to_name (int index); +/** @class Socket + * @brief A class to wrap a boost::asio::ip::tcp::socket with some things + * that are useful for DVD-o-matic. + * + * This class wraps some things that I could not work out how to do with boost; + * most notably, sync read/write calls with timeouts, and the ability to peak into + * data being read. + */ class Socket { public: Socket (); + /** @return Our underlying socket */ boost::asio::ip::tcp::socket& socket () { return _socket; } diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 56f20449b..0d17baf83 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -47,6 +47,7 @@ public: { } + /** Handle a paint event */ void paint_event (wxPaintEvent& ev) { if (_current_image != _pending_image) { @@ -67,6 +68,7 @@ public: } } + /** Handle a size event */ void size_event (wxSizeEvent &) { if (!_image) { @@ -101,6 +103,7 @@ public: } } + /** Clear our thumbnail image */ void clear () { delete _bitmap; diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc index 44d9462e5..4277ed12d 100644 --- a/src/wx/wx_util.cc +++ b/src/wx/wx_util.cc @@ -27,6 +27,12 @@ using namespace std; using namespace boost; +/** Add a wxStaticText to a wxSizer, aligning it at vertical centre. + * @param s Sizer to add to. + * @param p Parent window for the wxStaticText. + * @param t Text for the wxStaticText. + * @param prop Properties to pass when calling Add() on the wxSizer. + */ wxStaticText * add_label_to_sizer (wxSizer* s, wxWindow* p, string t, int prop) { @@ -35,6 +41,10 @@ add_label_to_sizer (wxSizer* s, wxWindow* p, string t, int prop) return m; } +/** Pop up an error dialogue box. + * @param parent Parent. + * @param m Message. + */ void error_dialog (wxWindow* parent, string m) { @@ -43,12 +53,18 @@ error_dialog (wxWindow* parent, string m) d->Destroy (); } +/** @param s wxWidgets string. + * @return Corresponding STL string. + */ string wx_to_std (wxString s) { return string (s.mb_str ()); } +/** @param s STL string. + * @return Corresponding wxWidgets string. + */ wxString std_to_wx (string s) { @@ -75,15 +91,16 @@ ThreadedStaticText::~ThreadedStaticText () delete _thread; } +/** Run our thread and post the result to the GUI thread via AddPendingEvent */ void ThreadedStaticText::run (function fn) { - /* Run the thread and post the result to the GUI thread via AddPendingEvent */ wxCommandEvent ev (wxEVT_COMMAND_TEXT_UPDATED, _update_event_id); ev.SetString (std_to_wx (fn ())); GetEventHandler()->AddPendingEvent (ev); } +/** Called in the GUI thread when our worker thread has finished */ void ThreadedStaticText::thread_finished (wxCommandEvent& ev) { diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h index 3a454c7c4..12a6e8837 100644 --- a/src/wx/wx_util.h +++ b/src/wx/wx_util.h @@ -30,7 +30,9 @@ extern wxStaticText* add_label_to_sizer (wxSizer *, wxWindow *, std::string, int extern std::string wx_to_std (wxString); extern wxString std_to_wx (std::string); -/** A wxStaticText whose content is computed in a separate thread, to avoid holding +/** @class ThreadedStaticText + * + * @brief A wxStaticText whose content is computed in a separate thread, to avoid holding * up the GUI while work is done. */ class ThreadedStaticText : public wxStaticText @@ -43,6 +45,7 @@ private: void run (boost::function fn); void thread_finished (wxCommandEvent& ev); + /** Thread to do our work in */ boost::thread* _thread; static const int _update_event_id; -- cgit v1.2.3 From 4fd257106009b2db170dafddece06ee3c190fceb Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 24 Sep 2012 23:49:53 +0100 Subject: Remove long-since disused hash debugging. --- src/lib/dcp_video_frame.cc | 30 ------------------------------ src/lib/dcp_video_frame.h | 4 ---- src/lib/image.cc | 32 +------------------------------- src/lib/image.h | 4 ---- src/lib/server.cc | 8 -------- src/lib/util.cc | 24 +++++++++++------------- src/lib/util.h | 4 +--- src/lib/wscript | 8 ++------ src/tools/servomatictest.cc | 9 --------- wscript | 2 -- 10 files changed, 15 insertions(+), 110 deletions(-) (limited to 'src/lib/util.h') diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index d8af3462d..96c40358a 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -55,10 +55,6 @@ #include "image.h" #include "log.h" -#ifdef DEBUG_HASH -#include -#endif - using namespace std; using namespace boost; @@ -255,12 +251,6 @@ DCPVideoFrame::encode_locally () /* Set event manager to null (openjpeg 1.3 bug) */ _cinfo->event_mgr = 0; -#ifdef DEBUG_HASH - md5_data ("J2K in X frame " + lexical_cast (_frame), _image->comps[0].data, size * sizeof (int)); - md5_data ("J2K in Y frame " + lexical_cast (_frame), _image->comps[1].data, size * sizeof (int)); - md5_data ("J2K in Z frame " + lexical_cast (_frame), _image->comps[2].data, size * sizeof (int)); -#endif - /* Setup the encoder parameters using the current image and user parameters */ opj_setup_encoder (_cinfo, _parameters, _image); @@ -271,10 +261,6 @@ DCPVideoFrame::encode_locally () throw EncodeError ("jpeg2000 encoding failed"); } -#ifdef DEBUG_HASH - md5_data ("J2K out frame " + lexical_cast (_frame), _cio->buffer, cio_tell (_cio)); -#endif - { stringstream s; s << "Finished locally-encoded frame " << _frame; @@ -300,10 +286,6 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) socket.connect (*endpoint_iterator, 30); -#ifdef DEBUG_HASH - _input->hash ("Input for remote encoding (before sending)"); -#endif - stringstream s; s << "encode " << _input->size().width << " " << _input->size().height << " " @@ -335,10 +317,6 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) /* now read the rest */ socket.read_definite_and_consume (e->data(), e->size(), 30); -#ifdef DEBUG_HASH - e->hash ("Encoded image (after receiving)"); -#endif - { stringstream s; s << "Finished remotely-encoded frame " << _frame; @@ -382,14 +360,6 @@ EncodedData::send (shared_ptr socket) socket->write (_data, _size, 30); } -#ifdef DEBUG_HASH -void -EncodedData::hash (string n) const -{ - md5_data (n, _data, _size); -} -#endif - /** @param s Size of data in bytes */ RemotelyEncodedData::RemotelyEncodedData (int s) : EncodedData (new uint8_t[s], s) diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index da4e0c301..72f885e45 100644 --- a/src/lib/dcp_video_frame.h +++ b/src/lib/dcp_video_frame.h @@ -51,10 +51,6 @@ public: void send (boost::shared_ptr socket); void write (boost::shared_ptr, int); -#ifdef DEBUG_HASH - void hash (std::string) const; -#endif - /** @return data */ uint8_t* data () const { return _data; diff --git a/src/lib/image.cc b/src/lib/image.cc index f16bb9f77..89536da33 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -27,6 +27,7 @@ #include #include #include +#include extern "C" { #include #include @@ -39,10 +40,6 @@ extern "C" { #include "exceptions.h" #include "scaler.h" -#ifdef DEBUG_HASH -#include -#endif - using namespace std; using namespace boost; @@ -85,33 +82,6 @@ Image::components () const return 0; } -#ifdef DEBUG_HASH -/** Write a MD5 hash of the image's data to stdout. - * @param n Title to give the output. - */ -void -Image::hash (string n) const -{ - MHASH ht = mhash_init (MHASH_MD5); - if (ht == MHASH_FAILED) { - throw EncodeError ("could not create hash thread"); - } - - for (int i = 0; i < components(); ++i) { - mhash (ht, data()[i], line_size()[i] * lines(i)); - } - - uint8_t hash[16]; - mhash_deinit (ht, hash); - - printf ("%s: ", n.c_str ()); - for (int i = 0; i < int (mhash_get_block_size (MHASH_MD5)); ++i) { - printf ("%.2x", hash[i]); - } - printf ("\n"); -} -#endif - /** Scale this image to a given size and convert it to RGB. * @param out_size Output image size in pixels. * @param scaler Scaler to use. diff --git a/src/lib/image.h b/src/lib/image.h index 97ab1d5ff..0161d2b01 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -68,10 +68,6 @@ public: boost::shared_ptr scale_and_convert_to_rgb (Size, int, Scaler const *) const; boost::shared_ptr post_process (std::string) const; -#ifdef DEBUG_HASH - void hash (std::string) const; -#endif - void make_black (); PixelFormat pixel_format () const { diff --git a/src/lib/server.cc b/src/lib/server.cc index 8ca426049..f8c4425d9 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -124,17 +124,9 @@ Server::process (shared_ptr socket) socket->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); } -#ifdef DEBUG_HASH - image->hash ("Image for encoding (as received by server)"); -#endif - DCPVideoFrame dcp_video_frame (image, out_size, padding, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log); shared_ptr encoded = dcp_video_frame.encode_locally (); encoded->send (socket); - -#ifdef DEBUG_HASH - encoded->hash ("Encoded image (as made by server and as sent back)"); -#endif return frame; } diff --git a/src/lib/util.cc b/src/lib/util.cc index 73222083a..c779268e2 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -40,6 +40,7 @@ #include #include #include +#include extern "C" { #include #include @@ -61,10 +62,6 @@ extern "C" { #include "player_manager.h" #endif -#ifdef DEBUG_HASH -#include -#endif - using namespace std; using namespace boost; @@ -347,9 +344,8 @@ split_at_spaces_considering_quotes (string s) return out; } -#ifdef DEBUG_HASH -void -md5_data (string title, void const * data, int size) +string +md5_hash (void const * data, int size) { MHASH ht = mhash_init (MHASH_MD5); if (ht == MHASH_FAILED) { @@ -360,14 +356,16 @@ md5_data (string title, void const * data, int size) uint8_t hash[16]; mhash_deinit (ht, hash); - - printf ("%s [%d]: ", title.c_str (), size); - for (int i = 0; i < int (mhash_get_block_size (MHASH_MD5)); ++i) { - printf ("%.2x", hash[i]); + + int const N = mhash_get_block_size (MHASH_MD5); + stringstream s; + s << hex << setfill('0') << setw(2); + for (int i = 0; i < N; ++i) { + s << ((int) hash[i]); } - printf ("\n"); + + return s.str (); } -#endif /** @param file File name. * @return MD5 digest of file's contents. diff --git a/src/lib/util.h b/src/lib/util.h index 63d492e60..03d04b852 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -52,9 +52,7 @@ enum ContentType { VIDEO }; -#ifdef DEBUG_HASH -extern void md5_data (std::string, void const *, int); -#endif +extern std::string md5_hash (void const *, int); /** @class Size * @brief Representation of the size of something */ diff --git a/src/lib/wscript b/src/lib/wscript index 71a2b23f4..26740a7e9 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -1,17 +1,13 @@ def configure(conf): - if conf.options.debug_hash: - conf.env.append_value('CXXFLAGS', '-DDEBUG_HASH') - conf.check_cc(msg = 'Checking for library libmhash', function_name = 'mhash_init', header_name = 'mhash.h', lib = 'mhash', uselib_store = 'MHASH') + conf.check_cc(msg = 'Checking for library libmhash', function_name = 'mhash_init', header_name = 'mhash.h', lib = 'mhash', uselib_store = 'MHASH') def build(bld): obj = bld(features = 'cxx cxxshlib') obj.name = 'libdvdomatic' obj.export_includes = ['.'] - obj.uselib = 'AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE SNDFILE BOOST_FILESYSTEM BOOST_THREAD OPENJPEG POSTPROC TIFF SIGC++ MAGICK SSH DCP GLIB' + obj.uselib = 'AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE SNDFILE BOOST_FILESYSTEM BOOST_THREAD OPENJPEG POSTPROC TIFF SIGC++ MAGICK SSH DCP GLIB MHASH' if bld.env.TARGET_WINDOWS: obj.uselib += ' WINSOCK2' - if bld.env.DEBUG_HASH: - obj.uselib += ' MHASH' obj.source = """ ab_transcode_job.cc ab_transcoder.cc diff --git a/src/tools/servomatictest.cc b/src/tools/servomatictest.cc index 0f37e73a5..d6804c981 100644 --- a/src/tools/servomatictest.cc +++ b/src/tools/servomatictest.cc @@ -47,12 +47,8 @@ process_video (shared_ptr image, int frame) shared_ptr local (new DCPVideoFrame (image, Size (1024, 1024), 0, Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_)); shared_ptr remote (new DCPVideoFrame (image, Size (1024, 1024), 0, Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_)); -#if defined(DEBUG_HASH) - cout << "Frame " << frame << ":\n"; -#else cout << "Frame " << frame << ": "; cout.flush (); -#endif shared_ptr local_encoded = local->encode_locally (); shared_ptr remote_encoded; @@ -64,11 +60,6 @@ process_video (shared_ptr image, int frame) remote_error = e.what (); } -#if defined(DEBUG_HASH) - cout << "Frame " << frame << ": "; - cout.flush (); -#endif - if (!remote_error.empty ()) { cout << "\033[0;31mnetwork problem: " << remote_error << "\033[0m\n"; return; diff --git a/wscript b/wscript index 71a89dfd3..69d68a35c 100644 --- a/wscript +++ b/wscript @@ -9,7 +9,6 @@ def options(opt): opt.load('compiler_cxx') opt.load('winres') - opt.add_option('--debug-hash', action='store_true', default = False, help = 'print hashes of data at various points') opt.add_option('--enable-debug', action='store_true', default = False, help = 'build with debugging information and without optimisation') opt.add_option('--disable-gui', action='store_true', default = False, help = 'disable building of GUI tools') opt.add_option('--disable-player', action='store_true', default = False, help = 'disable building of the player components') @@ -37,7 +36,6 @@ def configure(conf): boost_lib_suffix = '' boost_thread = 'boost_thread' - conf.env.DEBUG_HASH = conf.options.debug_hash conf.env.TARGET_WINDOWS = conf.options.target_windows conf.env.DISABLE_GUI = conf.options.disable_gui conf.env.DISABLE_PLAYER = conf.options.disable_player -- cgit v1.2.3 From 82af50304f55a961cba6afefbfa7edd5440bfcc4 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 25 Sep 2012 01:20:58 +0100 Subject: Basic J2K hash checking. --- src/lib/check_hashes_job.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++ src/lib/check_hashes_job.h | 33 +++++++++++++++++++ src/lib/dcp_video_frame.cc | 11 ++++++- src/lib/film.cc | 4 ++- src/lib/transcode_job.cc | 1 - src/lib/util.h | 3 +- src/lib/wscript | 1 + 7 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 src/lib/check_hashes_job.cc create mode 100644 src/lib/check_hashes_job.h (limited to 'src/lib/util.h') diff --git a/src/lib/check_hashes_job.cc b/src/lib/check_hashes_job.cc new file mode 100644 index 000000000..87eb40d14 --- /dev/null +++ b/src/lib/check_hashes_job.cc @@ -0,0 +1,79 @@ +/* + Copyright (C) 2012 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include "check_hashes_job.h" +#include "film_state.h" +#include "options.h" +#include "log.h" + +using namespace std; +using namespace boost; + +CheckHashesJob::CheckHashesJob (shared_ptr s, shared_ptr o, Log* l) + : Job (s, o, l) + , _bad (0) +{ + +} + +string +CheckHashesJob::name () const +{ + stringstream s; + s << "Check hashes of " << _fs->name; + return s.str (); +} + +void +CheckHashesJob::run () +{ + _bad = 0; + + for (int i = 0; i < _fs->length; ++i) { + string const j2k_file = _opt->frame_out_path (i, false); + string const hash_file = j2k_file + ".md5"; + + ifstream ref (hash_file.c_str ()); + string hash; + ref >> hash; + + if (hash != md5_digest (j2k_file)) { + _log->log ("Frame " + lexical_cast (i) + " has wrong hash; deleting."); + filesystem::remove (j2k_file); + filesystem::remove (hash_file); + ++_bad; + } + + set_progress (float (i) / _fs->length); + } + + set_progress (1); + set_state (FINISHED_OK); +} + +string +CheckHashesJob::status () const +{ + stringstream s; + s << Job::status () << "; " << _bad << " bad frames found"; + return s.str (); +} diff --git a/src/lib/check_hashes_job.h b/src/lib/check_hashes_job.h new file mode 100644 index 000000000..b59cf031b --- /dev/null +++ b/src/lib/check_hashes_job.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2012 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "job.h" + +class CheckHashesJob : public Job +{ +public: + CheckHashesJob (boost::shared_ptr s, boost::shared_ptr o, Log* l); + + std::string name () const; + void run (); + std::string status () const; + +private: + int _bad; +}; diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 96c40358a..da7133c4b 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -344,8 +345,16 @@ EncodedData::write (shared_ptr opt, int frame) fwrite (_data, 1, _size, f); fclose (f); + string const real_j2k = opt->frame_out_path (frame, false); + /* Rename the file from foo.j2c.tmp to foo.j2c now that it is complete */ - filesystem::rename (tmp_j2k, opt->frame_out_path (frame, false)); + filesystem::rename (tmp_j2k, real_j2k); + + /* Write a file containing the hash */ + string const hash = real_j2k + ".md5"; + ofstream h (hash.c_str()); + h << md5_digest (_data, _size) << "\n"; + h.close (); } /** Send this data to a socket. diff --git a/src/lib/film.cc b/src/lib/film.cc index d1334130e..583a15e19 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -48,6 +48,7 @@ #include "scaler.h" #include "decoder_factory.h" #include "config.h" +#include "check_hashes_job.h" using namespace std; using namespace boost; @@ -544,7 +545,8 @@ Film::make_dcp (bool transcode, int freq) JobManager::instance()->add (shared_ptr (new TranscodeJob (fs, o, log ()))); } } - + + JobManager::instance()->add (shared_ptr (new CheckHashesJob (fs, o, log ()))); JobManager::instance()->add (shared_ptr (new MakeDCPJob (fs, o, log ()))); } diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index c91058973..2de6e90ca 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -78,7 +78,6 @@ TranscodeJob::run () _log->log (s.str ()); throw; - } } diff --git a/src/lib/util.h b/src/lib/util.h index 03d04b852..bc5a00fc4 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -46,14 +46,13 @@ extern double seconds (struct timeval); extern void dvdomatic_setup (); extern std::vector split_at_spaces_considering_quotes (std::string); extern std::string md5_digest (std::string); +extern std::string md5_digest (void const *, int); enum ContentType { STILL, VIDEO }; -extern std::string md5_hash (void const *, int); - /** @class Size * @brief Representation of the size of something */ struct Size diff --git a/src/lib/wscript b/src/lib/wscript index 803ffd9ee..c809226ce 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -8,6 +8,7 @@ def build(bld): obj.source = """ ab_transcode_job.cc ab_transcoder.cc + check_hashes_job.cc config.cc copy_from_dvd_job.cc cross.cc -- cgit v1.2.3