Merge master; fix destruction of Server; some test cleanups.
authorCarl Hetherington <cth@carlh.net>
Thu, 19 Jun 2014 23:53:40 +0000 (00:53 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 19 Jun 2014 23:53:40 +0000 (00:53 +0100)
13 files changed:
1  2 
ChangeLog
src/lib/config.h
src/lib/encoder.h
src/lib/image_content.cc
src/lib/server.cc
src/lib/server.h
src/wx/about_dialog.cc
src/wx/audio_mapping_view.cc
src/wx/config_dialog.cc
test/client_server_test.cc
test/player_test.cc
test/recover_test.cc
test/test.cc

diff --cc ChangeLog
index 3194262ef06886fa797af33075cf0ad15cf0948f,22e314e4668fb1866dcf94ec00b90cc246a02db8..28cd9b332436f39c1d417a90c2b2a973fbd2fa1f
+++ b/ChangeLog
@@@ -1,7 -1,15 +1,19 @@@
 +2014-03-07  Carl Hetherington  <cth@carlh.net>
 +
 +      * Add subtitle view.
 +
+ 2014-06-18  Carl Hetherington  <cth@carlh.net>
+       * Version 1.69.29 released.
+ 2014-06-18  Carl Hetherington  <cth@carlh.net>
+       * Fix thinko causing incorrect audio sample rates in some cases.
+ 2014-06-15  Carl Hetherington  <cth@carlh.net>
+       * Version 1.69.28 released.
  2014-06-12  Carl Hetherington  <cth@carlh.net>
  
        * Version 1.69.27 released.
index f0d2630d0c893b22edf39c7a041d52e5d30ba2f4,671f53ef32dbcaf955f8109e6d46de6444ab8158..d82f520469c258f64b80b27d640a507f0503a962
  #include <boost/shared_ptr.hpp>
  #include <boost/signals2.hpp>
  #include <boost/filesystem.hpp>
 -#include <libdcp/metadata.h>
 +#include <dcp/metadata.h>
  #include "isdcf_metadata.h"
  #include "colour_conversion.h"
--#include "server.h"
  
  class ServerDescription;
  class Scaler;
index ac1d74c57b39af3aa449e43fd628651108701823,a8ee220aaac8cdea58ec3f0cd7c493dddeff93c0..678cdf04eae219bbcd8218765ff0d11facab3725
@@@ -38,6 -38,6 +38,7 @@@ extern "C" 
  #include "util.h"
  #include "config.h"
  #include "cross.h"
++#include "exceptions.h"
  
  class Image;
  class AudioBuffers;
index 8909240dc334e3d793e2ff64cc7d8b4922c8a1f1,6acf0bab924001eaa5b51e1d1349ce134e5e719c..acaedf0505d746b71661d89581192f7ef52d86ec
  #include <libcxml/cxml.h>
  #include "image_content.h"
  #include "image_examiner.h"
--#include "config.h"
  #include "compose.hpp"
  #include "film.h"
  #include "job.h"
  #include "frame_rate_change.h"
++#include "exceptions.h"
  
  #include "i18n.h"
  
index 59364fadd65aba787d1bfac5579c581eeba9a4c2,ed7fb6145c6a4b4498bbf6e3ff552a8fd3b8e01b..66ee2b0e3cf2ca93eeb7512a03763c2598836dcc
@@@ -62,16 -62,16 +62,37 @@@ using boost::thread
  using boost::bind;
  using boost::scoped_array;
  using boost::optional;
 -using libdcp::Size;
 -using libdcp::raw_convert;
 +using dcp::Size;
 +using dcp::raw_convert;
  
  Server::Server (shared_ptr<Log> log, bool verbose)
--      : _log (log)
++      : _terminate (false)
++      , _log (log)
        , _verbose (verbose)
++      , _acceptor (_io_service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), Config::instance()->server_port_base()))
  {
  
  }
  
++Server::~Server ()
++{
++      {
++              boost::mutex::scoped_lock lm (_worker_mutex);
++              _terminate = true;
++              _worker_condition.notify_all ();
++      }
++
++      for (vector<boost::thread*>::iterator i = _worker_threads.begin(); i != _worker_threads.end(); ++i) {
++              (*i)->join ();
++              delete *i;
++      }
++
++      _io_service.stop ();
++
++      _broadcast.io_service.stop ();
++      _broadcast.thread->join ();
++}
++
  /** @param after_read Filled in with gettimeofday() after reading the input from the network.
   *  @param after_encode Filled in with gettimeofday() after encoding the image.
   */
@@@ -117,10 -117,10 +138,14 @@@ Server::worker_thread (
  {
        while (1) {
                boost::mutex::scoped_lock lock (_worker_mutex);
--              while (_queue.empty ()) {
++              while (_queue.empty () && !_terminate) {
                        _worker_condition.wait (lock);
                }
  
++              if (_terminate) {
++                      return;
++              }
++
                shared_ptr<Socket> socket = _queue.front ();
                _queue.pop_front ();
                
@@@ -187,39 -187,39 +212,18 @@@ Server::run (int num_threads
  
        _broadcast.thread = new thread (bind (&Server::broadcast_thread, this));
        
--      boost::asio::io_service io_service;
--
--      boost::asio::ip::tcp::acceptor acceptor (
--              io_service,
--              boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), Config::instance()->server_port_base ())
--              );
--      
--      while (1) {
--              shared_ptr<Socket> socket (new Socket);
--              acceptor.accept (socket->socket ());
--
--              boost::mutex::scoped_lock lock (_worker_mutex);
--              
--              /* Wait until the queue has gone down a bit */
--              while (int (_queue.size()) >= num_threads * 2) {
--                      _worker_condition.wait (lock);
--              }
--              
--              _queue.push_back (socket);
--              _worker_condition.notify_all ();
--      }
++      start_accept ();
++      _io_service.run ();
  }
  
  void
  Server::broadcast_thread ()
  try
  {
--      boost::asio::io_service io_service;
--
        boost::asio::ip::address address = boost::asio::ip::address_v4::any ();
        boost::asio::ip::udp::endpoint listen_endpoint (address, Config::instance()->server_port_base() + 1);
  
--      _broadcast.socket = new boost::asio::ip::udp::socket (io_service);
++      _broadcast.socket = new boost::asio::ip::udp::socket (_broadcast.io_service);
        _broadcast.socket->open (listen_endpoint.protocol ());
        _broadcast.socket->bind (listen_endpoint);
  
                boost::bind (&Server::broadcast_received, this)
                );
  
--      io_service.run ();
++      _broadcast.io_service.run ();
  }
  catch (...)
  {
@@@ -264,3 -264,3 +268,35 @@@ Server::broadcast_received (
                _broadcast.send_endpoint, boost::bind (&Server::broadcast_received, this)
                );
  }
++
++void
++Server::start_accept ()
++{
++      if (_terminate) {
++              return;
++      }
++
++      shared_ptr<Socket> socket (new Socket);
++      _acceptor.async_accept (socket->socket (), boost::bind (&Server::handle_accept, this, socket, boost::asio::placeholders::error));
++}
++
++void
++Server::handle_accept (shared_ptr<Socket> socket, boost::system::error_code const & error)
++{
++      if (error) {
++              return;
++      }
++
++      boost::mutex::scoped_lock lock (_worker_mutex);
++      
++      /* Wait until the queue has gone down a bit */
++      while (_queue.size() >= _worker_threads.size() * 2 && !_terminate) {
++              _worker_condition.wait (lock);
++      }
++      
++      _queue.push_back (socket);
++      _worker_condition.notify_all ();
++
++      start_accept ();
++}
++      
index a9b4b1c1c8982ed9d57c615c9cee6fcfd9df0324,a9b4b1c1c8982ed9d57c615c9cee6fcfd9df0324..9f3e99f9cbe577c20c7c07bedccbe0d7298f8c07
@@@ -90,6 -90,6 +90,7 @@@ class Server : public ExceptionStore, p
  {
  public:
        Server (boost::shared_ptr<Log> log, bool verbose);
++      ~Server ();
  
        void run (int num_threads);
  
@@@ -98,14 -98,14 +99,24 @@@ private
        int process (boost::shared_ptr<Socket> socket, struct timeval &, struct timeval &);
        void broadcast_thread ();
        void broadcast_received ();
++      void start_accept ();
++      void handle_accept (boost::shared_ptr<Socket>, boost::system::error_code const &);
++
++      bool _terminate;
  
        std::vector<boost::thread *> _worker_threads;
        std::list<boost::shared_ptr<Socket> > _queue;
        boost::mutex _worker_mutex;
        boost::condition _worker_condition;
++      
        boost::shared_ptr<Log> _log;
        bool _verbose;
  
++      boost::asio::io_service _io_service;
++      boost::asio::ip::tcp::acceptor _acceptor;
++
++      int _num_threads;
++
        struct Broadcast {
  
                Broadcast ()
                boost::asio::ip::udp::socket* socket;
                char buffer[64];
                boost::asio::ip::udp::endpoint send_endpoint;
++              boost::asio::io_service io_service;
                
        } _broadcast;
  };
Simple merge
index c65eadd5a0676c9122ee968b8f902fe774a399ff,6c1508aeebae25b197b4273ace9aec1b7c48395e..8e92400bdb956ffd7b58205dccf5626bf9015be7
@@@ -24,7 -20,8 +24,8 @@@
  #include <wx/wx.h>
  #include <wx/renderer.h>
  #include <wx/grid.h>
 -#include <libdcp/types.h>
 -#include <libdcp/raw_convert.h>
 +#include <dcp/types.h>
++#include <dcp/raw_convert.h>
  #include "lib/audio_mapping.h"
  #include "lib/util.h"
  #include "audio_mapping_view.h"
@@@ -246,7 -239,7 +247,7 @@@ AudioMappingView::update_cells (
                _grid->SetCellValue (i, 0, wxString::Format (wxT("%d"), i + 1));
  
                for (int j = 1; j < _grid->GetNumberCols(); ++j) {
-                       _grid->SetCellValue (i, j, std_to_wx (lexical_cast<string> (_map.get (i, static_cast<dcp::Channel> (j - 1)))));
 -                      _grid->SetCellValue (i, j, std_to_wx (libdcp::raw_convert<string> (_map.get (i, static_cast<libdcp::Channel> (j - 1)))));
++                      _grid->SetCellValue (i, j, std_to_wx (dcp::raw_convert<string> (_map.get (i, static_cast<dcp::Channel> (j - 1)))));
                }
        }
  
index 68fbc3f1b391b05a0bc1d97de2a42282254e817a,e65e931d023b2db5bda5381a096e03d269a1d3f0..b447e0eee9a57328f76541993b44c498ef785060
@@@ -35,6 -35,6 +35,7 @@@
  #include "lib/filter.h"
  #include "lib/dcp_content_type.h"
  #include "lib/colour_conversion.h"
++#include "lib/log.h"
  #include "config_dialog.h"
  #include "wx_util.h"
  #include "editable_list.h"
index 1816de8e693df8a1a4fac0bf29e324a12efede53,07af1255c486ea42380f570ba6a643d566aedde0..51594a47acbd930347ded076aad887dadd9d8203
@@@ -130,6 -122,6 +130,8 @@@ BOOST_AUTO_TEST_CASE (client_server_tes
        for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
                delete *i;
        }
++
++      delete server;
  }
  
  BOOST_AUTO_TEST_CASE (client_server_test_yuv)
        for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
                delete *i;
        }
++
++      delete server;
  }
  
index 2412fc31299799411ed60608a33395886cad26f3,0000000000000000000000000000000000000000..d480602422b0ee1a810cfc74a1e38c0ad575eb1b
mode 100644,000000..100644
--- /dev/null
@@@ -1,104 -1,0 +1,104 @@@
-       BOOST_CHECK_EQUAL (A->full_length(), DCPTime::from_seconds (3));
 +/*
 +    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
 +
 +    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.
 +
 +*/
 +
 +/** @file  test/player_test.cc
 + *  @brief Various tests of Player.
 + */
 +
 +#include <iostream>
 +#include <boost/test/unit_test.hpp>
 +#include "lib/film.h"
 +#include "lib/ffmpeg_content.h"
 +#include "lib/dcp_content_type.h"
 +#include "lib/ratio.h"
 +#include "lib/audio_buffers.h"
 +#include "lib/player.h"
 +#include "test.h"
 +
 +using std::cout;
 +using std::list;
 +using boost::shared_ptr;
 +
 +/** Player::overlaps */
 +BOOST_AUTO_TEST_CASE (player_overlaps_test)
 +{
 +      shared_ptr<Film> film = new_test_film ("player_overlaps_test");
 +      film->set_container (Ratio::from_id ("185"));
 +      shared_ptr<FFmpegContent> A (new FFmpegContent (film, "test/data/test.mp4"));
 +      shared_ptr<FFmpegContent> B (new FFmpegContent (film, "test/data/test.mp4"));
 +      shared_ptr<FFmpegContent> C (new FFmpegContent (film, "test/data/test.mp4"));
 +
 +      film->examine_and_add_content (A);
 +      film->examine_and_add_content (B);
 +      film->examine_and_add_content (C);
 +      wait_for_jobs ();
 +
++      BOOST_CHECK_EQUAL (A->full_length(), DCPTime (280000));
 +
 +      A->set_position (DCPTime::from_seconds (0));
 +      B->set_position (DCPTime::from_seconds (10));
 +      C->set_position (DCPTime::from_seconds (20));
 +
 +      shared_ptr<Player> player = film->make_player ();
 +
 +      list<shared_ptr<Piece> > o = player->overlaps<FFmpegContent> (DCPTime::from_seconds (0), DCPTime::from_seconds (5));
 +      BOOST_CHECK_EQUAL (o.size(), 1);
 +      BOOST_CHECK_EQUAL (o.front()->content, A);
 +
 +      o = player->overlaps<FFmpegContent> (DCPTime::from_seconds (5), DCPTime::from_seconds (8));
 +      BOOST_CHECK_EQUAL (o.size(), 0);
 +
 +      o = player->overlaps<FFmpegContent> (DCPTime::from_seconds (8), DCPTime::from_seconds (12));
 +      BOOST_CHECK_EQUAL (o.size(), 1);
 +      BOOST_CHECK_EQUAL (o.front()->content, B);
 +
 +      o = player->overlaps<FFmpegContent> (DCPTime::from_seconds (2), DCPTime::from_seconds (12));
 +      BOOST_CHECK_EQUAL (o.size(), 2);
 +      BOOST_CHECK_EQUAL (o.front()->content, A);
 +      BOOST_CHECK_EQUAL (o.back()->content, B);
 +
 +      o = player->overlaps<FFmpegContent> (DCPTime::from_seconds (8), DCPTime::from_seconds (11));
 +      BOOST_CHECK_EQUAL (o.size(), 1);
 +      BOOST_CHECK_EQUAL (o.front()->content, B);
 +}
 +
 +/** Check that the Player correctly generates silence when used with a silent FFmpegContent */
 +BOOST_AUTO_TEST_CASE (player_silence_padding_test)
 +{
 +      shared_ptr<Film> film = new_test_film ("player_silence_padding_test");
 +      film->set_name ("player_silence_padding_test");
 +      shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
 +      film->set_container (Ratio::from_id ("185"));
 +      film->set_audio_channels (6);
 +      
 +      film->examine_and_add_content (c);
 +      wait_for_jobs ();
 +
 +      shared_ptr<Player> player = film->make_player ();
 +      shared_ptr<AudioBuffers> test = player->get_audio (DCPTime (0), DCPTime::from_seconds (1), true);
 +      BOOST_CHECK_EQUAL (test->frames(), 48000);
 +      BOOST_CHECK_EQUAL (test->channels(), film->audio_channels ());
 +
 +      for (int i = 0; i < test->frames(); ++i) {
 +              for (int c = 0; c < test->channels(); ++c) {
 +                      BOOST_CHECK_EQUAL (test->data()[c][i], 0);
 +              }
 +      }
 +}
 +
index bf07811ddce917a3b73d4c9a76888bfe37ba062c,284895e0a75d3bcee73ae157e078fc1ad6b86925..c9a5932418252ab6246467fc8c2749483b43e8d9
@@@ -57,10 -52,8 +57,10 @@@ BOOST_AUTO_TEST_CASE (recover_test
        film->make_dcp ();
        wait_for_jobs ();
  
-       boost::filesystem::path const video = "build/test/recover_test/video/185_2K_3651eded785682b85f4baca4b1d3b7a9_24_bicubic_200000000_P_S_3D.mxf";
++      boost::filesystem::path const video = "build/test/recover_test/video/185_2K_e8efb95857b62aa6ff94e3d669e75776_24_bicubic_100000000_P_S_3D.mxf";
 +
        boost::filesystem::copy_file (
 -              "build/test/recover_test/video/185_2K_58a090f8d70a2b410c534120d35e5256_24_bicubic_200000000_P_S_3D.mxf",
 +              video,
                "build/test/recover_test/original.mxf"
                );
        
diff --cc test/test.cc
index 1d8041656cf05e2acaf76081e327c00f7621661b,0b87b8062a67adc503bf076ba32624cf7678a2ff..32f74a7d2fb62b8243056d11c11b84eeb5eea0b1
@@@ -141,9 -127,9 +141,9 @@@ check_file (boost::filesystem::path ref
  }
  
  static void
 -note (libdcp::NoteType t, string n)
 +note (dcp::NoteType t, string n)
  {
-       if (t == dcp::ERROR) {
 -      if (t == libdcp::ERROR) {
++      if (t == dcp::DCP_ERROR) {
                cerr << n << "\n";
        }
  }