DCPVideoFrame -> DCPVideo and PlayerVideoFrame -> PlayerVideo.
authorCarl Hetherington <cth@carlh.net>
Tue, 1 Jul 2014 13:28:04 +0000 (14:28 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 1 Jul 2014 13:28:04 +0000 (14:28 +0100)
21 files changed:
src/lib/dcp_video.cc [new file with mode: 0644]
src/lib/dcp_video.h [new file with mode: 0644]
src/lib/dcp_video_frame.cc [deleted file]
src/lib/dcp_video_frame.h [deleted file]
src/lib/encoder.cc
src/lib/encoder.h
src/lib/player.cc
src/lib/player.h
src/lib/player_video.cc [new file with mode: 0644]
src/lib/player_video.h [new file with mode: 0644]
src/lib/player_video_frame.cc [deleted file]
src/lib/player_video_frame.h [deleted file]
src/lib/server.cc
src/lib/transcoder.cc
src/lib/writer.cc
src/lib/wscript
src/tools/dcpomatic_server_cli.cc
src/tools/server_test.cc
src/wx/film_viewer.cc
src/wx/film_viewer.h
test/client_server_test.cc

diff --git a/src/lib/dcp_video.cc b/src/lib/dcp_video.cc
new file mode 100644 (file)
index 0000000..8d4a592
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
+
+    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  src/dcp_video_frame.cc
+ *  @brief A single frame of video destined for a DCP.
+ *
+ *  Given an Image and some settings, this class knows how to encode
+ *  the image to J2K either on the local host or on a remote server.
+ *
+ *  Objects of this class are used for the queue that we keep
+ *  of images that require encoding.
+ */
+
+#include <stdint.h>
+#include <cstring>
+#include <cstdlib>
+#include <stdexcept>
+#include <cstdio>
+#include <iomanip>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <errno.h>
+#include <boost/array.hpp>
+#include <boost/asio.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <dcp/gamma_lut.h>
+#include <dcp/xyz_frame.h>
+#include <dcp/rgb_xyz.h>
+#include <dcp/colour_matrix.h>
+#include <dcp/raw_convert.h>
+#include <libcxml/cxml.h>
+#include "film.h"
+#include "dcp_video.h"
+#include "config.h"
+#include "exceptions.h"
+#include "server.h"
+#include "util.h"
+#include "scaler.h"
+#include "image.h"
+#include "log.h"
+#include "cross.h"
+#include "player_video.h"
+
+#define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
+
+#include "i18n.h"
+
+using std::string;
+using std::stringstream;
+using std::cout;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using dcp::Size;
+using dcp::raw_convert;
+
+#define DCI_COEFFICENT (48.0 / 52.37)
+
+/** Construct a DCP video frame.
+ *  @param frame Input frame.
+ *  @param index Index of the frame within the DCP.
+ *  @param bw J2K bandwidth to use (see Config::j2k_bandwidth ())
+ *  @param l Log to write to.
+ */
+DCPVideo::DCPVideo (
+       shared_ptr<const PlayerVideo> frame, int index, int dcp_fps, int bw, Resolution r, shared_ptr<Log> l
+       )
+       : _frame (frame)
+       , _index (index)
+       , _frames_per_second (dcp_fps)
+       , _j2k_bandwidth (bw)
+       , _resolution (r)
+       , _log (l)
+{
+       
+}
+
+DCPVideo::DCPVideo (shared_ptr<const PlayerVideo> frame, shared_ptr<const cxml::Node> node, shared_ptr<Log> log)
+       : _frame (frame)
+       , _log (log)
+{
+       _index = node->number_child<int> ("Index");
+       _frames_per_second = node->number_child<int> ("FramesPerSecond");
+       _j2k_bandwidth = node->number_child<int> ("J2KBandwidth");
+       _resolution = Resolution (node->optional_number_child<int>("Resolution").get_value_or (RESOLUTION_2K));
+}
+
+/** J2K-encode this frame on the local host.
+ *  @return Encoded data.
+ */
+shared_ptr<EncodedData>
+DCPVideo::encode_locally ()
+{
+       shared_ptr<dcp::GammaLUT> in_lut = dcp::GammaLUT::cache.get (
+               12, _frame->colour_conversion().input_gamma, _frame->colour_conversion().input_gamma_linearised
+               );
+       
+       /* XXX: libdcp should probably use boost */
+       
+       double matrix[3][3];
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       matrix[i][j] = _frame->colour_conversion().matrix (i, j);
+               }
+       }
+
+       shared_ptr<dcp::XYZFrame> xyz = dcp::rgb_to_xyz (
+               _frame->image(),
+               in_lut,
+               dcp::GammaLUT::cache.get (16, 1 / _frame->colour_conversion().output_gamma, false),
+               matrix
+               );
+
+       /* Set the max image and component sizes based on frame_rate */
+       int max_cs_len = ((float) _j2k_bandwidth) / 8 / _frames_per_second;
+       if (_frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT) {
+               /* In 3D we have only half the normal bandwidth per eye */
+               max_cs_len /= 2;
+       }
+       int const max_comp_size = max_cs_len / 1.25;
+
+       /* get a J2K compressor handle */
+       opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
+       if (cinfo == 0) {
+               throw EncodeError (N_("could not create JPEG2000 encoder"));
+       }
+
+       /* Set encoding parameters to default values */
+       opj_cparameters_t parameters;
+       opj_set_default_encoder_parameters (&parameters);
+
+       /* Set default cinema parameters */
+       parameters.tile_size_on = false;
+       parameters.cp_tdx = 1;
+       parameters.cp_tdy = 1;
+       
+       /* Tile part */
+       parameters.tp_flag = 'C';
+       parameters.tp_on = 1;
+       
+       /* Tile and Image shall be at (0,0) */
+       parameters.cp_tx0 = 0;
+       parameters.cp_ty0 = 0;
+       parameters.image_offset_x0 = 0;
+       parameters.image_offset_y0 = 0;
+
+       /* Codeblock size = 32x32 */
+       parameters.cblockw_init = 32;
+       parameters.cblockh_init = 32;
+       parameters.csty |= 0x01;
+       
+       /* The progression order shall be CPRL */
+       parameters.prog_order = CPRL;
+       
+       /* No ROI */
+       parameters.roi_compno = -1;
+       
+       parameters.subsampling_dx = 1;
+       parameters.subsampling_dy = 1;
+       
+       /* 9-7 transform */
+       parameters.irreversible = 1;
+       
+       parameters.tcp_rates[0] = 0;
+       parameters.tcp_numlayers++;
+       parameters.cp_disto_alloc = 1;
+       parameters.cp_rsiz = _resolution == RESOLUTION_2K ? CINEMA2K : CINEMA4K;
+       if (_resolution == RESOLUTION_4K) {
+               parameters.numpocs = 2;
+               parameters.POC[0].tile = 1;
+               parameters.POC[0].resno0 = 0; 
+               parameters.POC[0].compno0 = 0;
+               parameters.POC[0].layno1 = 1;
+               parameters.POC[0].resno1 = parameters.numresolution - 1;
+               parameters.POC[0].compno1 = 3;
+               parameters.POC[0].prg1 = CPRL;
+               parameters.POC[1].tile = 1;
+               parameters.POC[1].resno0 = parameters.numresolution - 1; 
+               parameters.POC[1].compno0 = 0;
+               parameters.POC[1].layno1 = 1;
+               parameters.POC[1].resno1 = parameters.numresolution;
+               parameters.POC[1].compno1 = 3;
+               parameters.POC[1].prg1 = CPRL;
+       }
+       
+       parameters.cp_comment = strdup (N_("DCP-o-matic"));
+       parameters.cp_cinema = _resolution == RESOLUTION_2K ? CINEMA2K_24 : CINEMA4K_24;
+
+       /* 3 components, so use MCT */
+       parameters.tcp_mct = 1;
+       
+       /* set max image */
+       parameters.max_comp_size = max_comp_size;
+       parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
+
+       /* Set event manager to null (openjpeg 1.3 bug) */
+       cinfo->event_mgr = 0;
+
+       /* Setup the encoder parameters using the current image and user parameters */
+       opj_setup_encoder (cinfo, &parameters, xyz->opj_image ());
+
+       opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
+       if (cio == 0) {
+               opj_destroy_compress (cinfo);
+               throw EncodeError (N_("could not open JPEG2000 stream"));
+       }
+
+       int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
+       if (r == 0) {
+               opj_cio_close (cio);
+               opj_destroy_compress (cinfo);
+               throw EncodeError (N_("JPEG2000 encoding failed"));
+       }
+
+       switch (_frame->eyes()) {
+       case EYES_BOTH:
+               LOG_GENERAL (N_("Finished locally-encoded frame %1 for mono"), _index);
+               break;
+       case EYES_LEFT:
+               LOG_GENERAL (N_("Finished locally-encoded frame %1 for L"), _index);
+               break;
+       case EYES_RIGHT:
+               LOG_GENERAL (N_("Finished locally-encoded frame %1 for R"), _index);
+               break;
+       default:
+               break;
+       }
+
+       shared_ptr<EncodedData> enc (new LocallyEncodedData (cio->buffer, cio_tell (cio)));
+
+       opj_cio_close (cio);
+       free (parameters.cp_comment);
+       opj_destroy_compress (cinfo);
+
+       return enc;
+}
+
+/** Send this frame to a remote server for J2K encoding, then read the result.
+ *  @param serv Server to send to.
+ *  @return Encoded data.
+ */
+shared_ptr<EncodedData>
+DCPVideo::encode_remotely (ServerDescription serv)
+{
+       boost::asio::io_service io_service;
+       boost::asio::ip::tcp::resolver resolver (io_service);
+       boost::asio::ip::tcp::resolver::query query (serv.host_name(), raw_convert<string> (Config::instance()->server_port_base ()));
+       boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query);
+
+       shared_ptr<Socket> socket (new Socket);
+
+       socket->connect (*endpoint_iterator);
+
+       /* Collect all XML metadata */
+       xmlpp::Document doc;
+       xmlpp::Element* root = doc.create_root_node ("EncodingRequest");
+       root->add_child("Version")->add_child_text (raw_convert<string> (SERVER_LINK_VERSION));
+       add_metadata (root);
+
+       LOG_GENERAL (N_("Sending frame %1 to remote"), _index);
+       
+       /* Send XML metadata */
+       stringstream xml;
+       doc.write_to_stream (xml, "UTF-8");
+       socket->write (xml.str().length() + 1);
+       socket->write ((uint8_t *) xml.str().c_str(), xml.str().length() + 1);
+
+       /* Send binary data */
+       _frame->send_binary (socket);
+
+       /* Read the response (JPEG2000-encoded data); this blocks until the data
+          is ready and sent back.
+       */
+       shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
+       socket->read (e->data(), e->size());
+
+       LOG_GENERAL (N_("Finished remotely-encoded frame %1"), _index);
+       
+       return e;
+}
+
+void
+DCPVideo::add_metadata (xmlpp::Element* el) const
+{
+       el->add_child("Index")->add_child_text (raw_convert<string> (_index));
+       el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second));
+       el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
+       el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution)));
+       _frame->add_metadata (el);
+}
+
+Eyes
+DCPVideo::eyes () const
+{
+       return _frame->eyes ();
+}
+
+EncodedData::EncodedData (int s)
+       : _data (new uint8_t[s])
+       , _size (s)
+{
+
+}
+
+EncodedData::EncodedData (boost::filesystem::path file)
+{
+       _size = boost::filesystem::file_size (file);
+       _data = new uint8_t[_size];
+
+       FILE* f = fopen_boost (file, "rb");
+       if (!f) {
+               throw FileError (_("could not open file for reading"), file);
+       }
+       
+       size_t const r = fread (_data, 1, _size, f);
+       if (r != size_t (_size)) {
+               fclose (f);
+               throw FileError (_("could not read encoded data"), file);
+       }
+               
+       fclose (f);
+}
+
+
+EncodedData::~EncodedData ()
+{
+       delete[] _data;
+}
+
+/** Write this data to a J2K file.
+ *  @param Film Film.
+ *  @param frame DCP frame index.
+ */
+void
+EncodedData::write (shared_ptr<const Film> film, int frame, Eyes eyes) const
+{
+       boost::filesystem::path const tmp_j2c = film->j2c_path (frame, eyes, true);
+
+       FILE* f = fopen_boost (tmp_j2c, "wb");
+       
+       if (!f) {
+               throw WriteFileError (tmp_j2c, errno);
+       }
+
+       fwrite (_data, 1, _size, f);
+       fclose (f);
+
+       boost::filesystem::path const real_j2c = film->j2c_path (frame, eyes, false);
+
+       /* Rename the file from foo.j2c.tmp to foo.j2c now that it is complete */
+       boost::filesystem::rename (tmp_j2c, real_j2c);
+}
+
+void
+EncodedData::write_info (shared_ptr<const Film> film, int frame, Eyes eyes, dcp::FrameInfo fin) const
+{
+       boost::filesystem::path const info = film->info_path (frame, eyes);
+       FILE* h = fopen_boost (info, "w");
+       fin.write (h);
+       fclose (h);
+}
+
+/** Send this data to a socket.
+ *  @param socket Socket
+ */
+void
+EncodedData::send (shared_ptr<Socket> socket)
+{
+       socket->write (_size);
+       socket->write (_data, _size);
+}
+
+LocallyEncodedData::LocallyEncodedData (uint8_t* d, int s)
+       : EncodedData (s)
+{
+       memcpy (_data, d, s);
+}
+
+/** @param s Size of data in bytes */
+RemotelyEncodedData::RemotelyEncodedData (int s)
+       : EncodedData (s)
+{
+
+}
diff --git a/src/lib/dcp_video.h b/src/lib/dcp_video.h
new file mode 100644 (file)
index 0000000..7b01966
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
+
+    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 <dcp/picture_mxf_writer.h>
+#include "util.h"
+
+/** @file  src/dcp_video_frame.h
+ *  @brief A single frame of video destined for a DCP.
+ */
+
+class Film;
+class ServerDescription;
+class Scaler;
+class Image;
+class Log;
+class Subtitle;
+class PlayerVideo;
+
+/** @class EncodedData
+ *  @brief Container for J2K-encoded data.
+ */
+class EncodedData : public boost::noncopyable
+{
+public:
+       /** @param s Size of data, in bytes */
+       EncodedData (int s);
+
+       EncodedData (boost::filesystem::path);
+
+       virtual ~EncodedData ();
+
+       void send (boost::shared_ptr<Socket> socket);
+       void write (boost::shared_ptr<const Film>, int, Eyes) const;
+       void write_info (boost::shared_ptr<const Film>, int, Eyes, dcp::FrameInfo) const;
+
+       /** @return data */
+       uint8_t* data () const {
+               return _data;
+       }
+
+       /** @return data size, in bytes */
+       int size () const {
+               return _size;
+       }
+
+protected:
+       uint8_t* _data; ///< data
+       int _size;      ///< data size in bytes
+};
+
+/** @class LocallyEncodedData
+ *  @brief EncodedData that was encoded locally; this class
+ *  just keeps a pointer to the data, but does no memory
+ *  management.
+ */
+class LocallyEncodedData : public EncodedData
+{
+public:
+       /** @param d Data (which will be copied by this class)
+        *  @param s Size of data, in bytes.
+        */
+       LocallyEncodedData (uint8_t* d, int s);
+};
+
+/** @class RemotelyEncodedData
+ *  @brief EncodedData that is being read from a remote server;
+ *  this class allocates and manages memory for the data.
+ */
+class RemotelyEncodedData : public EncodedData
+{
+public:
+       RemotelyEncodedData (int s);
+};
+
+/** @class DCPVideo
+ *  @brief A single frame of video destined for a DCP.
+ *
+ *  Given an Image and some settings, this class knows how to encode
+ *  the image to J2K either on the local host or on a remote server.
+ *
+ *  Objects of this class are used for the queue that we keep
+ *  of images that require encoding.
+ */
+class DCPVideo : public boost::noncopyable
+{
+public:
+       DCPVideo (boost::shared_ptr<const PlayerVideo>, int, int, int, Resolution, boost::shared_ptr<Log>);
+       DCPVideo (boost::shared_ptr<const PlayerVideo>, cxml::ConstNodePtr, boost::shared_ptr<Log>);
+
+       boost::shared_ptr<EncodedData> encode_locally ();
+       boost::shared_ptr<EncodedData> encode_remotely (ServerDescription);
+
+       int index () const {
+               return _index;
+       }
+
+       Eyes eyes () const;
+       
+private:
+
+       void add_metadata (xmlpp::Element *) const;
+       
+       boost::shared_ptr<const PlayerVideo> _frame;
+       int _index;                      ///< frame index within the DCP's intrinsic duration
+       int _frames_per_second;          ///< Frames per second that we will use for the DCP
+       int _j2k_bandwidth;              ///< J2K bandwidth to use
+       Resolution _resolution;          ///< Resolution (2K or 4K)
+
+       boost::shared_ptr<Log> _log; ///< log
+};
diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc
deleted file mode 100644 (file)
index 4054f05..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-    Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
-
-    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  src/dcp_video_frame.cc
- *  @brief A single frame of video destined for a DCP.
- *
- *  Given an Image and some settings, this class knows how to encode
- *  the image to J2K either on the local host or on a remote server.
- *
- *  Objects of this class are used for the queue that we keep
- *  of images that require encoding.
- */
-
-#include <stdint.h>
-#include <cstring>
-#include <cstdlib>
-#include <stdexcept>
-#include <cstdio>
-#include <iomanip>
-#include <sstream>
-#include <iostream>
-#include <fstream>
-#include <unistd.h>
-#include <errno.h>
-#include <boost/array.hpp>
-#include <boost/asio.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <dcp/gamma_lut.h>
-#include <dcp/xyz_frame.h>
-#include <dcp/rgb_xyz.h>
-#include <dcp/colour_matrix.h>
-#include <dcp/raw_convert.h>
-#include <libcxml/cxml.h>
-#include "film.h"
-#include "dcp_video_frame.h"
-#include "config.h"
-#include "exceptions.h"
-#include "server.h"
-#include "util.h"
-#include "scaler.h"
-#include "image.h"
-#include "log.h"
-#include "cross.h"
-#include "player_video_frame.h"
-
-#define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
-
-#include "i18n.h"
-
-using std::string;
-using std::stringstream;
-using std::cout;
-using boost::shared_ptr;
-using boost::lexical_cast;
-using dcp::Size;
-using dcp::raw_convert;
-
-#define DCI_COEFFICENT (48.0 / 52.37)
-
-/** Construct a DCP video frame.
- *  @param frame Input frame.
- *  @param index Index of the frame within the DCP.
- *  @param bw J2K bandwidth to use (see Config::j2k_bandwidth ())
- *  @param l Log to write to.
- */
-DCPVideoFrame::DCPVideoFrame (
-       shared_ptr<const PlayerVideoFrame> frame, int index, int dcp_fps, int bw, Resolution r, shared_ptr<Log> l
-       )
-       : _frame (frame)
-       , _index (index)
-       , _frames_per_second (dcp_fps)
-       , _j2k_bandwidth (bw)
-       , _resolution (r)
-       , _log (l)
-{
-       
-}
-
-DCPVideoFrame::DCPVideoFrame (shared_ptr<const PlayerVideoFrame> frame, shared_ptr<const cxml::Node> node, shared_ptr<Log> log)
-       : _frame (frame)
-       , _log (log)
-{
-       _index = node->number_child<int> ("Index");
-       _frames_per_second = node->number_child<int> ("FramesPerSecond");
-       _j2k_bandwidth = node->number_child<int> ("J2KBandwidth");
-       _resolution = Resolution (node->optional_number_child<int>("Resolution").get_value_or (RESOLUTION_2K));
-}
-
-/** J2K-encode this frame on the local host.
- *  @return Encoded data.
- */
-shared_ptr<EncodedData>
-DCPVideoFrame::encode_locally ()
-{
-       shared_ptr<dcp::GammaLUT> in_lut = dcp::GammaLUT::cache.get (
-               12, _frame->colour_conversion().input_gamma, _frame->colour_conversion().input_gamma_linearised
-               );
-       
-       /* XXX: libdcp should probably use boost */
-       
-       double matrix[3][3];
-       for (int i = 0; i < 3; ++i) {
-               for (int j = 0; j < 3; ++j) {
-                       matrix[i][j] = _frame->colour_conversion().matrix (i, j);
-               }
-       }
-
-       shared_ptr<dcp::XYZFrame> xyz = dcp::rgb_to_xyz (
-               _frame->image(),
-               in_lut,
-               dcp::GammaLUT::cache.get (16, 1 / _frame->colour_conversion().output_gamma, false),
-               matrix
-               );
-
-       /* Set the max image and component sizes based on frame_rate */
-       int max_cs_len = ((float) _j2k_bandwidth) / 8 / _frames_per_second;
-       if (_frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT) {
-               /* In 3D we have only half the normal bandwidth per eye */
-               max_cs_len /= 2;
-       }
-       int const max_comp_size = max_cs_len / 1.25;
-
-       /* get a J2K compressor handle */
-       opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
-       if (cinfo == 0) {
-               throw EncodeError (N_("could not create JPEG2000 encoder"));
-       }
-
-       /* Set encoding parameters to default values */
-       opj_cparameters_t parameters;
-       opj_set_default_encoder_parameters (&parameters);
-
-       /* Set default cinema parameters */
-       parameters.tile_size_on = false;
-       parameters.cp_tdx = 1;
-       parameters.cp_tdy = 1;
-       
-       /* Tile part */
-       parameters.tp_flag = 'C';
-       parameters.tp_on = 1;
-       
-       /* Tile and Image shall be at (0,0) */
-       parameters.cp_tx0 = 0;
-       parameters.cp_ty0 = 0;
-       parameters.image_offset_x0 = 0;
-       parameters.image_offset_y0 = 0;
-
-       /* Codeblock size = 32x32 */
-       parameters.cblockw_init = 32;
-       parameters.cblockh_init = 32;
-       parameters.csty |= 0x01;
-       
-       /* The progression order shall be CPRL */
-       parameters.prog_order = CPRL;
-       
-       /* No ROI */
-       parameters.roi_compno = -1;
-       
-       parameters.subsampling_dx = 1;
-       parameters.subsampling_dy = 1;
-       
-       /* 9-7 transform */
-       parameters.irreversible = 1;
-       
-       parameters.tcp_rates[0] = 0;
-       parameters.tcp_numlayers++;
-       parameters.cp_disto_alloc = 1;
-       parameters.cp_rsiz = _resolution == RESOLUTION_2K ? CINEMA2K : CINEMA4K;
-       if (_resolution == RESOLUTION_4K) {
-               parameters.numpocs = 2;
-               parameters.POC[0].tile = 1;
-               parameters.POC[0].resno0 = 0; 
-               parameters.POC[0].compno0 = 0;
-               parameters.POC[0].layno1 = 1;
-               parameters.POC[0].resno1 = parameters.numresolution - 1;
-               parameters.POC[0].compno1 = 3;
-               parameters.POC[0].prg1 = CPRL;
-               parameters.POC[1].tile = 1;
-               parameters.POC[1].resno0 = parameters.numresolution - 1; 
-               parameters.POC[1].compno0 = 0;
-               parameters.POC[1].layno1 = 1;
-               parameters.POC[1].resno1 = parameters.numresolution;
-               parameters.POC[1].compno1 = 3;
-               parameters.POC[1].prg1 = CPRL;
-       }
-       
-       parameters.cp_comment = strdup (N_("DCP-o-matic"));
-       parameters.cp_cinema = _resolution == RESOLUTION_2K ? CINEMA2K_24 : CINEMA4K_24;
-
-       /* 3 components, so use MCT */
-       parameters.tcp_mct = 1;
-       
-       /* set max image */
-       parameters.max_comp_size = max_comp_size;
-       parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
-
-       /* Set event manager to null (openjpeg 1.3 bug) */
-       cinfo->event_mgr = 0;
-
-       /* Setup the encoder parameters using the current image and user parameters */
-       opj_setup_encoder (cinfo, &parameters, xyz->opj_image ());
-
-       opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
-       if (cio == 0) {
-               opj_destroy_compress (cinfo);
-               throw EncodeError (N_("could not open JPEG2000 stream"));
-       }
-
-       int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
-       if (r == 0) {
-               opj_cio_close (cio);
-               opj_destroy_compress (cinfo);
-               throw EncodeError (N_("JPEG2000 encoding failed"));
-       }
-
-       switch (_frame->eyes()) {
-       case EYES_BOTH:
-               LOG_GENERAL (N_("Finished locally-encoded frame %1 for mono"), _index);
-               break;
-       case EYES_LEFT:
-               LOG_GENERAL (N_("Finished locally-encoded frame %1 for L"), _index);
-               break;
-       case EYES_RIGHT:
-               LOG_GENERAL (N_("Finished locally-encoded frame %1 for R"), _index);
-               break;
-       default:
-               break;
-       }
-
-       shared_ptr<EncodedData> enc (new LocallyEncodedData (cio->buffer, cio_tell (cio)));
-
-       opj_cio_close (cio);
-       free (parameters.cp_comment);
-       opj_destroy_compress (cinfo);
-
-       return enc;
-}
-
-/** Send this frame to a remote server for J2K encoding, then read the result.
- *  @param serv Server to send to.
- *  @return Encoded data.
- */
-shared_ptr<EncodedData>
-DCPVideoFrame::encode_remotely (ServerDescription serv)
-{
-       boost::asio::io_service io_service;
-       boost::asio::ip::tcp::resolver resolver (io_service);
-       boost::asio::ip::tcp::resolver::query query (serv.host_name(), raw_convert<string> (Config::instance()->server_port_base ()));
-       boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query);
-
-       shared_ptr<Socket> socket (new Socket);
-
-       socket->connect (*endpoint_iterator);
-
-       /* Collect all XML metadata */
-       xmlpp::Document doc;
-       xmlpp::Element* root = doc.create_root_node ("EncodingRequest");
-       root->add_child("Version")->add_child_text (raw_convert<string> (SERVER_LINK_VERSION));
-       add_metadata (root);
-
-       LOG_GENERAL (N_("Sending frame %1 to remote"), _index);
-       
-       /* Send XML metadata */
-       stringstream xml;
-       doc.write_to_stream (xml, "UTF-8");
-       socket->write (xml.str().length() + 1);
-       socket->write ((uint8_t *) xml.str().c_str(), xml.str().length() + 1);
-
-       /* Send binary data */
-       _frame->send_binary (socket);
-
-       /* Read the response (JPEG2000-encoded data); this blocks until the data
-          is ready and sent back.
-       */
-       shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
-       socket->read (e->data(), e->size());
-
-       LOG_GENERAL (N_("Finished remotely-encoded frame %1"), _index);
-       
-       return e;
-}
-
-void
-DCPVideoFrame::add_metadata (xmlpp::Element* el) const
-{
-       el->add_child("Index")->add_child_text (raw_convert<string> (_index));
-       el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second));
-       el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
-       el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution)));
-       _frame->add_metadata (el);
-}
-
-Eyes
-DCPVideoFrame::eyes () const
-{
-       return _frame->eyes ();
-}
-
-EncodedData::EncodedData (int s)
-       : _data (new uint8_t[s])
-       , _size (s)
-{
-
-}
-
-EncodedData::EncodedData (boost::filesystem::path file)
-{
-       _size = boost::filesystem::file_size (file);
-       _data = new uint8_t[_size];
-
-       FILE* f = fopen_boost (file, "rb");
-       if (!f) {
-               throw FileError (_("could not open file for reading"), file);
-       }
-       
-       size_t const r = fread (_data, 1, _size, f);
-       if (r != size_t (_size)) {
-               fclose (f);
-               throw FileError (_("could not read encoded data"), file);
-       }
-               
-       fclose (f);
-}
-
-
-EncodedData::~EncodedData ()
-{
-       delete[] _data;
-}
-
-/** Write this data to a J2K file.
- *  @param Film Film.
- *  @param frame DCP frame index.
- */
-void
-EncodedData::write (shared_ptr<const Film> film, int frame, Eyes eyes) const
-{
-       boost::filesystem::path const tmp_j2c = film->j2c_path (frame, eyes, true);
-
-       FILE* f = fopen_boost (tmp_j2c, "wb");
-       
-       if (!f) {
-               throw WriteFileError (tmp_j2c, errno);
-       }
-
-       fwrite (_data, 1, _size, f);
-       fclose (f);
-
-       boost::filesystem::path const real_j2c = film->j2c_path (frame, eyes, false);
-
-       /* Rename the file from foo.j2c.tmp to foo.j2c now that it is complete */
-       boost::filesystem::rename (tmp_j2c, real_j2c);
-}
-
-void
-EncodedData::write_info (shared_ptr<const Film> film, int frame, Eyes eyes, dcp::FrameInfo fin) const
-{
-       boost::filesystem::path const info = film->info_path (frame, eyes);
-       FILE* h = fopen_boost (info, "w");
-       fin.write (h);
-       fclose (h);
-}
-
-/** Send this data to a socket.
- *  @param socket Socket
- */
-void
-EncodedData::send (shared_ptr<Socket> socket)
-{
-       socket->write (_size);
-       socket->write (_data, _size);
-}
-
-LocallyEncodedData::LocallyEncodedData (uint8_t* d, int s)
-       : EncodedData (s)
-{
-       memcpy (_data, d, s);
-}
-
-/** @param s Size of data in bytes */
-RemotelyEncodedData::RemotelyEncodedData (int s)
-       : EncodedData (s)
-{
-
-}
diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h
deleted file mode 100644 (file)
index 7393efd..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
-    Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
-
-    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 <dcp/picture_mxf_writer.h>
-#include "util.h"
-
-/** @file  src/dcp_video_frame.h
- *  @brief A single frame of video destined for a DCP.
- */
-
-class Film;
-class ServerDescription;
-class Scaler;
-class Image;
-class Log;
-class Subtitle;
-class PlayerVideoFrame;
-
-/** @class EncodedData
- *  @brief Container for J2K-encoded data.
- */
-class EncodedData : public boost::noncopyable
-{
-public:
-       /** @param s Size of data, in bytes */
-       EncodedData (int s);
-
-       EncodedData (boost::filesystem::path);
-
-       virtual ~EncodedData ();
-
-       void send (boost::shared_ptr<Socket> socket);
-       void write (boost::shared_ptr<const Film>, int, Eyes) const;
-       void write_info (boost::shared_ptr<const Film>, int, Eyes, dcp::FrameInfo) const;
-
-       /** @return data */
-       uint8_t* data () const {
-               return _data;
-       }
-
-       /** @return data size, in bytes */
-       int size () const {
-               return _size;
-       }
-
-protected:
-       uint8_t* _data; ///< data
-       int _size;      ///< data size in bytes
-};
-
-/** @class LocallyEncodedData
- *  @brief EncodedData that was encoded locally; this class
- *  just keeps a pointer to the data, but does no memory
- *  management.
- */
-class LocallyEncodedData : public EncodedData
-{
-public:
-       /** @param d Data (which will be copied by this class)
-        *  @param s Size of data, in bytes.
-        */
-       LocallyEncodedData (uint8_t* d, int s);
-};
-
-/** @class RemotelyEncodedData
- *  @brief EncodedData that is being read from a remote server;
- *  this class allocates and manages memory for the data.
- */
-class RemotelyEncodedData : public EncodedData
-{
-public:
-       RemotelyEncodedData (int s);
-};
-
-/** @class DCPVideoFrame
- *  @brief A single frame of video destined for a DCP.
- *
- *  Given an Image and some settings, this class knows how to encode
- *  the image to J2K either on the local host or on a remote server.
- *
- *  Objects of this class are used for the queue that we keep
- *  of images that require encoding.
- */
-class DCPVideoFrame : public boost::noncopyable
-{
-public:
-       DCPVideoFrame (boost::shared_ptr<const PlayerVideoFrame>, int, int, int, Resolution, boost::shared_ptr<Log>);
-       DCPVideoFrame (boost::shared_ptr<const PlayerVideoFrame>, cxml::ConstNodePtr, boost::shared_ptr<Log>);
-
-       boost::shared_ptr<EncodedData> encode_locally ();
-       boost::shared_ptr<EncodedData> encode_remotely (ServerDescription);
-
-       int index () const {
-               return _index;
-       }
-
-       Eyes eyes () const;
-       
-private:
-
-       void add_metadata (xmlpp::Element *) const;
-       
-       boost::shared_ptr<const PlayerVideoFrame> _frame;
-       int _index;                      ///< frame index within the DCP's intrinsic duration
-       int _frames_per_second;          ///< Frames per second that we will use for the DCP
-       int _j2k_bandwidth;              ///< J2K bandwidth to use
-       Resolution _resolution;          ///< Resolution (2K or 4K)
-
-       boost::shared_ptr<Log> _log; ///< log
-};
index 0756586a91d54101ce89ba61d41f4cca2f3790f6..2b1f1d9b3bab37236f1bb69462d658e598216540 100644 (file)
 #include "film.h"
 #include "log.h"
 #include "config.h"
-#include "dcp_video_frame.h"
+#include "dcp_video.h"
 #include "server.h"
 #include "cross.h"
 #include "writer.h"
 #include "server_finder.h"
 #include "player.h"
-#include "player_video_frame.h"
+#include "player_video.h"
 
 #include "i18n.h"
 
@@ -125,7 +125,7 @@ Encoder::process_end ()
             So just mop up anything left in the queue here.
        */
 
-       for (list<shared_ptr<DCPVideoFrame> >::iterator i = _queue.begin(); i != _queue.end(); ++i) {
+       for (list<shared_ptr<DCPVideo> >::iterator i = _queue.begin(); i != _queue.end(); ++i) {
                LOG_GENERAL (N_("Encode left-over frame %1"), (*i)->index ());
                try {
                        _writer->write ((*i)->encode_locally(), (*i)->index (), (*i)->eyes ());
@@ -181,7 +181,7 @@ Encoder::frame_done ()
 }
 
 void
-Encoder::process_video (shared_ptr<PlayerVideoFrame> pvf)
+Encoder::process_video (shared_ptr<PlayerVideo> pvf)
 {
        _waker.nudge ();
        
@@ -213,8 +213,8 @@ Encoder::process_video (shared_ptr<PlayerVideoFrame> pvf)
        } else {
                /* Queue this new frame for encoding */
                LOG_TIMING ("adding to queue of %1", _queue.size ());
-               _queue.push_back (shared_ptr<DCPVideoFrame> (
-                                         new DCPVideoFrame (
+               _queue.push_back (shared_ptr<DCPVideo> (
+                                         new DCPVideo (
                                                  pvf,
                                                  _video_frames_out,
                                                  _film->video_frame_rate(),
@@ -284,7 +284,7 @@ try
                }
 
                LOG_TIMING ("[%1] encoder thread wakes with queue of %2", boost::this_thread::get_id(), _queue.size());
-               shared_ptr<DCPVideoFrame> vf = _queue.front ();
+               shared_ptr<DCPVideo> vf = _queue.front ();
                LOG_TIMING ("[%1] encoder thread pops frame %2 (%3) from queue", boost::this_thread::get_id(), vf->index(), vf->eyes ());
                _queue.pop_front ();
                
index 6bb97012abaebfceedf57f30960aaa3fb3bfbf30..4502b7151dc08c47ba16f7462e629a42521ed897 100644 (file)
@@ -44,12 +44,12 @@ class Image;
 class AudioBuffers;
 class Film;
 class ServerDescription;
-class DCPVideoFrame;
+class DCPVideo;
 class EncodedData;
 class Writer;
 class Job;
 class ServerFinder;
-class PlayerVideoFrame;
+class PlayerVideo;
 
 /** @class Encoder
  *  @brief Encoder to J2K and WAV for DCP.
@@ -70,7 +70,7 @@ public:
        /** Call with a frame of video.
         *  @param f Video frame.
         */
-       void process_video (boost::shared_ptr<PlayerVideoFrame> f);
+       void process_video (boost::shared_ptr<PlayerVideo> f);
 
        /** Call with some audio data */
        void process_audio (boost::shared_ptr<const AudioBuffers>);
@@ -107,7 +107,7 @@ private:
        int _video_frames_out;
 
        bool _terminate;
-       std::list<boost::shared_ptr<DCPVideoFrame> > _queue;
+       std::list<boost::shared_ptr<DCPVideo> > _queue;
        std::list<boost::thread *> _threads;
        mutable boost::mutex _mutex;
        /** condition to manage thread wakeups when we have nothing to do */
index 380133b61da5a970eb09dd2da62ef83fd6ecd21d..b634028ba3a99ab6b8455041882c8b7eaa6c01fb 100644 (file)
@@ -41,7 +41,7 @@
 #include "render_subtitles.h"
 #include "config.h"
 #include "content_video.h"
-#include "player_video_frame.h"
+#include "player_video.h"
 #include "frame_rate_change.h"
 
 #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
@@ -292,11 +292,11 @@ Player::set_approximate_size ()
        _approximate_size = true;
 }
 
-shared_ptr<PlayerVideoFrame>
+shared_ptr<PlayerVideo>
 Player::black_player_video_frame () const
 {
-       return shared_ptr<PlayerVideoFrame> (
-               new PlayerVideoFrame (
+       return shared_ptr<PlayerVideo> (
+               new PlayerVideo (
                        shared_ptr<const ImageProxy> (new RawImageProxy (_black_image, _film->log ())),
                        Crop (),
                        _video_container_size,
@@ -309,8 +309,8 @@ Player::black_player_video_frame () const
        );
 }
 
-/** @return All PlayerVideoFrames at the given time (there may be two frames for 3D) */
-list<shared_ptr<PlayerVideoFrame> >
+/** @return All PlayerVideos at the given time (there may be two frames for 3D) */
+list<shared_ptr<PlayerVideo> >
 Player::get_video (DCPTime time, bool accurate)
 {
        if (!_have_valid_pieces) {
@@ -322,13 +322,13 @@ Player::get_video (DCPTime time, bool accurate)
                time + DCPTime::from_frames (1, _film->video_frame_rate ())
                );
 
-       list<shared_ptr<PlayerVideoFrame> > pvf;
+       list<shared_ptr<PlayerVideo> > pvf;
 
        if (ov.empty ()) {
                /* No video content at this time */
                pvf.push_back (black_player_video_frame ());
        } else {
-               /* Create a PlayerVideoFrame from the content's video at this time */
+               /* Create a PlayerVideo from the content's video at this time */
 
                shared_ptr<Piece> piece = ov.back ();
                shared_ptr<VideoDecoder> decoder = dynamic_pointer_cast<VideoDecoder> (piece->decoder);
@@ -350,8 +350,8 @@ Player::get_video (DCPTime time, bool accurate)
                
                for (list<ContentVideo>::const_iterator i = content_video.begin(); i != content_video.end(); ++i) {
                        pvf.push_back (
-                               shared_ptr<PlayerVideoFrame> (
-                                       new PlayerVideoFrame (
+                               shared_ptr<PlayerVideo> (
+                                       new PlayerVideo (
                                                i->image,
                                                content->crop (),
                                                image_size,
@@ -366,7 +366,7 @@ Player::get_video (DCPTime time, bool accurate)
                }
        }
 
-       /* Add subtitles to whatever PlayerVideoFrames we got */
+       /* Add subtitles to whatever PlayerVideos we got */
        
        list<shared_ptr<Piece> > subs = overlaps<SubtitleContent> (
                time,
@@ -404,7 +404,7 @@ Player::get_video (DCPTime time, bool accurate)
        }
        
        if (!sub_images.empty ()) {
-               for (list<shared_ptr<PlayerVideoFrame> >::const_iterator i = pvf.begin(); i != pvf.end(); ++i) {
+               for (list<shared_ptr<PlayerVideo> >::const_iterator i = pvf.begin(); i != pvf.end(); ++i) {
                        (*i)->set_subtitle (merge (sub_images));
                }
        }       
index 6805dc8c7f08be630073fd640f5bcacb38277407..04503c27a0917c8aaa2e34e6a556fa764b4f3600 100644 (file)
@@ -42,7 +42,7 @@ class Piece;
 class Image;
 class Decoder;
 class Resampler;
-class PlayerVideoFrame;
+class PlayerVideo;
 class ImageProxy;
  
 class PlayerStatistics
@@ -85,7 +85,7 @@ class Player : public boost::enable_shared_from_this<Player>, public boost::nonc
 public:
        Player (boost::shared_ptr<const Film>, boost::shared_ptr<const Playlist>);
 
-       std::list<boost::shared_ptr<PlayerVideoFrame> > get_video (DCPTime time, bool accurate);
+       std::list<boost::shared_ptr<PlayerVideo> > get_video (DCPTime time, bool accurate);
        boost::shared_ptr<AudioBuffers> get_audio (DCPTime time, DCPTime length, bool accurate);
 
        void set_video_container_size (dcp::Size);
@@ -119,7 +119,7 @@ private:
        VideoFrame dcp_to_content_video (boost::shared_ptr<const Piece> piece, DCPTime t) const;
        AudioFrame dcp_to_content_audio (boost::shared_ptr<const Piece> piece, DCPTime t) const;
        ContentTime dcp_to_content_subtitle (boost::shared_ptr<const Piece> piece, DCPTime t) const;
-       boost::shared_ptr<PlayerVideoFrame> black_player_video_frame () const;
+       boost::shared_ptr<PlayerVideo> black_player_video_frame () const;
 
        /** @return Pieces of content type C that overlap a specified time range in the DCP */
        template<class C>
diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc
new file mode 100644 (file)
index 0000000..f8e4a3e
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+    Copyright (C) 2013-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.
+
+*/
+
+#include <dcp/raw_convert.h>
+#include "player_video.h"
+#include "image.h"
+#include "image_proxy.h"
+#include "scaler.h"
+
+using std::string;
+using std::cout;
+using boost::shared_ptr;
+using dcp::raw_convert;
+
+PlayerVideo::PlayerVideo (
+       shared_ptr<const ImageProxy> in,
+       Crop crop,
+       dcp::Size inter_size,
+       dcp::Size out_size,
+       Scaler const * scaler,
+       Eyes eyes,
+       Part part,
+       ColourConversion colour_conversion
+       )
+       : _in (in)
+       , _crop (crop)
+       , _inter_size (inter_size)
+       , _out_size (out_size)
+       , _scaler (scaler)
+       , _eyes (eyes)
+       , _part (part)
+       , _colour_conversion (colour_conversion)
+{
+
+}
+
+PlayerVideo::PlayerVideo (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket, shared_ptr<Log> log)
+{
+       _crop = Crop (node);
+
+       _inter_size = dcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight"));
+       _out_size = dcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight"));
+       _scaler = Scaler::from_id (node->string_child ("Scaler"));
+       _eyes = (Eyes) node->number_child<int> ("Eyes");
+       _part = (Part) node->number_child<int> ("Part");
+       _colour_conversion = ColourConversion (node);
+
+       _in = image_proxy_factory (node->node_child ("In"), socket, log);
+
+       if (node->optional_number_child<int> ("SubtitleX")) {
+               
+               _subtitle.position = Position<int> (node->number_child<int> ("SubtitleX"), node->number_child<int> ("SubtitleY"));
+
+               _subtitle.image.reset (
+                       new Image (PIX_FMT_RGBA, dcp::Size (node->number_child<int> ("SubtitleWidth"), node->number_child<int> ("SubtitleHeight")), true)
+                       );
+               
+               _subtitle.image->read_from_socket (socket);
+       }
+}
+
+void
+PlayerVideo::set_subtitle (PositionImage image)
+{
+       _subtitle = image;
+}
+
+shared_ptr<Image>
+PlayerVideo::image () const
+{
+       shared_ptr<Image> im = _in->image ();
+       
+       Crop total_crop = _crop;
+       switch (_part) {
+       case PART_LEFT_HALF:
+               total_crop.right += im->size().width / 2;
+               break;
+       case PART_RIGHT_HALF:
+               total_crop.left += im->size().width / 2;
+               break;
+       case PART_TOP_HALF:
+               total_crop.bottom += im->size().height / 2;
+               break;
+       case PART_BOTTOM_HALF:
+               total_crop.top += im->size().height / 2;
+               break;
+       default:
+               break;
+       }
+               
+       shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, _scaler, PIX_FMT_RGB24, true);
+
+       Position<int> const container_offset ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.width) / 2);
+
+       if (_subtitle.image) {
+               out->alpha_blend (_subtitle.image, _subtitle.position);
+       }
+
+       return out;
+}
+
+void
+PlayerVideo::add_metadata (xmlpp::Node* node) const
+{
+       _crop.as_xml (node);
+       _in->add_metadata (node->add_child ("In"));
+       node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width));
+       node->add_child("InterHeight")->add_child_text (raw_convert<string> (_inter_size.height));
+       node->add_child("OutWidth")->add_child_text (raw_convert<string> (_out_size.width));
+       node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height));
+       node->add_child("Scaler")->add_child_text (_scaler->id ());
+       node->add_child("Eyes")->add_child_text (raw_convert<string> (_eyes));
+       node->add_child("Part")->add_child_text (raw_convert<string> (_part));
+       _colour_conversion.as_xml (node);
+       if (_subtitle.image) {
+               node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle.image->size().width));
+               node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle.image->size().height));
+               node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle.position.x));
+               node->add_child ("SubtitleY")->add_child_text (raw_convert<string> (_subtitle.position.y));
+       }
+}
+
+void
+PlayerVideo::send_binary (shared_ptr<Socket> socket) const
+{
+       _in->send_binary (socket);
+       if (_subtitle.image) {
+               _subtitle.image->write_to_socket (socket);
+       }
+}
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
new file mode 100644 (file)
index 0000000..73557bb
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    Copyright (C) 2013-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.
+
+*/
+
+#include <boost/shared_ptr.hpp>
+#include "types.h"
+#include "position.h"
+#include "colour_conversion.h"
+#include "position_image.h"
+
+class Image;
+class ImageProxy;
+class Scaler;
+class Socket;
+class Log;
+
+/** Everything needed to describe a video frame coming out of the player, but with the
+ *  bits still their raw form.  We may want to combine the bits on a remote machine,
+ *  or maybe not even bother to combine them at all.
+ */
+class PlayerVideo
+{
+public:
+       PlayerVideo (boost::shared_ptr<const ImageProxy>, Crop, dcp::Size, dcp::Size, Scaler const *, Eyes, Part, ColourConversion);
+       PlayerVideo (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>, boost::shared_ptr<Log>);
+
+       void set_subtitle (PositionImage);
+       
+       boost::shared_ptr<Image> image () const;
+
+       void add_metadata (xmlpp::Node* node) const;
+       void send_binary (boost::shared_ptr<Socket> socket) const;
+
+       Eyes eyes () const {
+               return _eyes;
+       }
+
+       ColourConversion colour_conversion () const {
+               return _colour_conversion;
+       }
+
+private:
+       boost::shared_ptr<const ImageProxy> _in;
+       Crop _crop;
+       dcp::Size _inter_size;
+       dcp::Size _out_size;
+       Scaler const * _scaler;
+       Eyes _eyes;
+       Part _part;
+       ColourConversion _colour_conversion;
+       PositionImage _subtitle;
+};
diff --git a/src/lib/player_video_frame.cc b/src/lib/player_video_frame.cc
deleted file mode 100644 (file)
index 5463925..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-    Copyright (C) 2013-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.
-
-*/
-
-#include <dcp/raw_convert.h>
-#include "player_video_frame.h"
-#include "image.h"
-#include "image_proxy.h"
-#include "scaler.h"
-
-using std::string;
-using std::cout;
-using boost::shared_ptr;
-using dcp::raw_convert;
-
-PlayerVideoFrame::PlayerVideoFrame (
-       shared_ptr<const ImageProxy> in,
-       Crop crop,
-       dcp::Size inter_size,
-       dcp::Size out_size,
-       Scaler const * scaler,
-       Eyes eyes,
-       Part part,
-       ColourConversion colour_conversion
-       )
-       : _in (in)
-       , _crop (crop)
-       , _inter_size (inter_size)
-       , _out_size (out_size)
-       , _scaler (scaler)
-       , _eyes (eyes)
-       , _part (part)
-       , _colour_conversion (colour_conversion)
-{
-
-}
-
-PlayerVideoFrame::PlayerVideoFrame (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket, shared_ptr<Log> log)
-{
-       _crop = Crop (node);
-
-       _inter_size = dcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight"));
-       _out_size = dcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight"));
-       _scaler = Scaler::from_id (node->string_child ("Scaler"));
-       _eyes = (Eyes) node->number_child<int> ("Eyes");
-       _part = (Part) node->number_child<int> ("Part");
-       _colour_conversion = ColourConversion (node);
-
-       _in = image_proxy_factory (node->node_child ("In"), socket, log);
-
-       if (node->optional_number_child<int> ("SubtitleX")) {
-               
-               _subtitle.position = Position<int> (node->number_child<int> ("SubtitleX"), node->number_child<int> ("SubtitleY"));
-
-               _subtitle.image.reset (
-                       new Image (PIX_FMT_RGBA, dcp::Size (node->number_child<int> ("SubtitleWidth"), node->number_child<int> ("SubtitleHeight")), true)
-                       );
-               
-               _subtitle.image->read_from_socket (socket);
-       }
-}
-
-void
-PlayerVideoFrame::set_subtitle (PositionImage image)
-{
-       _subtitle = image;
-}
-
-shared_ptr<Image>
-PlayerVideoFrame::image () const
-{
-       shared_ptr<Image> im = _in->image ();
-       
-       Crop total_crop = _crop;
-       switch (_part) {
-       case PART_LEFT_HALF:
-               total_crop.right += im->size().width / 2;
-               break;
-       case PART_RIGHT_HALF:
-               total_crop.left += im->size().width / 2;
-               break;
-       case PART_TOP_HALF:
-               total_crop.bottom += im->size().height / 2;
-               break;
-       case PART_BOTTOM_HALF:
-               total_crop.top += im->size().height / 2;
-               break;
-       default:
-               break;
-       }
-               
-       shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, _scaler, PIX_FMT_RGB24, true);
-
-       Position<int> const container_offset ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.width) / 2);
-
-       if (_subtitle.image) {
-               out->alpha_blend (_subtitle.image, _subtitle.position);
-       }
-
-       return out;
-}
-
-void
-PlayerVideoFrame::add_metadata (xmlpp::Node* node) const
-{
-       _crop.as_xml (node);
-       _in->add_metadata (node->add_child ("In"));
-       node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width));
-       node->add_child("InterHeight")->add_child_text (raw_convert<string> (_inter_size.height));
-       node->add_child("OutWidth")->add_child_text (raw_convert<string> (_out_size.width));
-       node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height));
-       node->add_child("Scaler")->add_child_text (_scaler->id ());
-       node->add_child("Eyes")->add_child_text (raw_convert<string> (_eyes));
-       node->add_child("Part")->add_child_text (raw_convert<string> (_part));
-       _colour_conversion.as_xml (node);
-       if (_subtitle.image) {
-               node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle.image->size().width));
-               node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle.image->size().height));
-               node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle.position.x));
-               node->add_child ("SubtitleY")->add_child_text (raw_convert<string> (_subtitle.position.y));
-       }
-}
-
-void
-PlayerVideoFrame::send_binary (shared_ptr<Socket> socket) const
-{
-       _in->send_binary (socket);
-       if (_subtitle.image) {
-               _subtitle.image->write_to_socket (socket);
-       }
-}
diff --git a/src/lib/player_video_frame.h b/src/lib/player_video_frame.h
deleted file mode 100644 (file)
index 4c6a9c6..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-    Copyright (C) 2013-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.
-
-*/
-
-#include <boost/shared_ptr.hpp>
-#include "types.h"
-#include "position.h"
-#include "colour_conversion.h"
-#include "position_image.h"
-
-class Image;
-class ImageProxy;
-class Scaler;
-class Socket;
-class Log;
-
-/** Everything needed to describe a video frame coming out of the player, but with the
- *  bits still their raw form.  We may want to combine the bits on a remote machine,
- *  or maybe not even bother to combine them at all.
- */
-class PlayerVideoFrame
-{
-public:
-       PlayerVideoFrame (boost::shared_ptr<const ImageProxy>, Crop, dcp::Size, dcp::Size, Scaler const *, Eyes, Part, ColourConversion);
-       PlayerVideoFrame (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>, boost::shared_ptr<Log>);
-
-       void set_subtitle (PositionImage);
-       
-       boost::shared_ptr<Image> image () const;
-
-       void add_metadata (xmlpp::Node* node) const;
-       void send_binary (boost::shared_ptr<Socket> socket) const;
-
-       Eyes eyes () const {
-               return _eyes;
-       }
-
-       ColourConversion colour_conversion () const {
-               return _colour_conversion;
-       }
-
-private:
-       boost::shared_ptr<const ImageProxy> _in;
-       Crop _crop;
-       dcp::Size _inter_size;
-       dcp::Size _out_size;
-       Scaler const * _scaler;
-       Eyes _eyes;
-       Part _part;
-       ColourConversion _colour_conversion;
-       PositionImage _subtitle;
-};
index 9d1925de1a4a2c80cf0167b5f484e099c6237aab..2469d415142ba0504da0647436b359c14510614b 100644 (file)
 #include "util.h"
 #include "scaler.h"
 #include "image.h"
-#include "dcp_video_frame.h"
+#include "dcp_video.h"
 #include "config.h"
 #include "cross.h"
-#include "player_video_frame.h"
+#include "player_video.h"
 
 #include "i18n.h"
 
@@ -112,9 +112,9 @@ Server::process (shared_ptr<Socket> socket, struct timeval& after_read, struct t
                return -1;
        }
 
-       shared_ptr<PlayerVideoFrame> pvf (new PlayerVideoFrame (xml, socket, _log));
+       shared_ptr<PlayerVideo> pvf (new PlayerVideo (xml, socket, _log));
 
-       DCPVideoFrame dcp_video_frame (pvf, xml, _log);
+       DCPVideo dcp_video_frame (pvf, xml, _log);
 
        gettimeofday (&after_read, 0);
        
index a4cd36a4fb509f17ba6f58eae2729e0bb2901060..1177830be54ba67c9b173826a8e324768bebbfc6 100644 (file)
@@ -61,8 +61,8 @@ Transcoder::go ()
 
        DCPTime const frame = DCPTime::from_frames (1, _film->video_frame_rate ());
        for (DCPTime t; t < _film->length(); t += frame) {
-               list<shared_ptr<PlayerVideoFrame> > v = _player->get_video (t, true);
-               for (list<shared_ptr<PlayerVideoFrame> >::const_iterator i = v.begin(); i != v.end(); ++i) {
+               list<shared_ptr<PlayerVideo> > v = _player->get_video (t, true);
+               for (list<shared_ptr<PlayerVideo> >::const_iterator i = v.begin(); i != v.end(); ++i) {
                        _encoder->process_video (*i);
                }
                _encoder->process_audio (_player->get_audio (t, frame, true));
index 489135b846e8cb7d9d20e32d00a928c8a8117256..ca9b63df42db31eceeb4a9a105786fd12efbc135 100644 (file)
@@ -34,7 +34,7 @@
 #include "film.h"
 #include "ratio.h"
 #include "log.h"
-#include "dcp_video_frame.h"
+#include "dcp_video.h"
 #include "dcp_content_type.h"
 #include "player.h"
 #include "audio_mapping.h"
index 407d9cde41551abab31aa43179de352b1ea26561..1f6a2aa4f3a0770a10ff1612590f9cada08d31af 100644 (file)
@@ -16,7 +16,7 @@ sources = """
           content_subtitle.cc
           cross.cc
           dcp_content_type.cc
-          dcp_video_frame.cc
+          dcp_video.cc
           dcpomatic_time.cc
           dolby_cp750.cc
           encoder.cc
@@ -48,7 +48,7 @@ sources = """
           log.cc
           md5_digester.cc
           player.cc
-          player_video_frame.cc
+          player_video.cc
           playlist.cc
           ratio.cc
           render_subtitles.cc
index e4ac85f4cb6d48f47f19786238ec1a5c221fddc6..c74e258e8ff081680f3b799f354c5ee344ad937c 100644 (file)
@@ -33,7 +33,7 @@
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/condition.hpp>
 #include "lib/config.h"
-#include "lib/dcp_video_frame.h"
+#include "lib/dcp_video.h"
 #include "lib/exceptions.h"
 #include "lib/util.h"
 #include "lib/config.h"
index 5997caab67c61b86212d3f010fb5445fcf086d69..acafa4a8133eadd03d4b106c69dd93d887d69ace 100644 (file)
 #include "lib/util.h"
 #include "lib/scaler.h"
 #include "lib/server.h"
-#include "lib/dcp_video_frame.h"
+#include "lib/dcp_video.h"
 #include "lib/decoder.h"
 #include "lib/exceptions.h"
 #include "lib/scaler.h"
 #include "lib/log.h"
 #include "lib/video_decoder.h"
 #include "lib/player.h"
-#include "lib/player_video_frame.h"
+#include "lib/player_video.h"
 
 using std::cout;
 using std::cerr;
@@ -48,10 +48,10 @@ static shared_ptr<FileLog> log_ (new FileLog ("servomatictest.log"));
 static int frame_count = 0;
 
 void
-process_video (shared_ptr<PlayerVideoFrame> pvf)
+process_video (shared_ptr<PlayerVideo> pvf)
 {
-       shared_ptr<DCPVideoFrame> local  (new DCPVideoFrame (pvf, frame_count, film->video_frame_rate(), 250000000, RESOLUTION_2K, log_));
-       shared_ptr<DCPVideoFrame> remote (new DCPVideoFrame (pvf, frame_count, film->video_frame_rate(), 250000000, RESOLUTION_2K, log_));
+       shared_ptr<DCPVideo> local  (new DCPVideo (pvf, frame_count, film->video_frame_rate(), 250000000, RESOLUTION_2K, log_));
+       shared_ptr<DCPVideo> remote (new DCPVideo (pvf, frame_count, film->video_frame_rate(), 250000000, RESOLUTION_2K, log_));
 
        cout << "Frame " << frame_count << ": ";
        cout.flush ();
index d84a0af340c31e413b6cd65bb68f1e40f22bdf4b..dd3d9ebe9817b576bf935968ce7cae44c8501bb8 100644 (file)
@@ -34,7 +34,7 @@
 #include "lib/examine_content_job.h"
 #include "lib/filter.h"
 #include "lib/player.h"
-#include "lib/player_video_frame.h"
+#include "lib/player_video.h"
 #include "lib/video_content.h"
 #include "lib/video_decoder.h"
 #include "lib/timer.h"
@@ -151,7 +151,7 @@ FilmViewer::get (DCPTime p, bool accurate)
                return;
        }
 
-       list<shared_ptr<PlayerVideoFrame> > pvf = _player->get_video (p, accurate);
+       list<shared_ptr<PlayerVideo> > pvf = _player->get_video (p, accurate);
        if (!pvf.empty ()) {
                _frame = pvf.front()->image ();
                _frame = _frame->scale (_frame->size(), Scaler::from_id ("fastbilinear"), PIX_FMT_RGB24, false);
index c1c087a14d5d75c93a460585297c9619d1033968..189b379bf3beeaa68f43a2d343220e307d891ece 100644 (file)
@@ -28,7 +28,7 @@ class wxToggleButton;
 class FFmpegPlayer;
 class Image;
 class RGBPlusAlphaImage;
-class PlayerVideoFrame;
+class PlayerVideo;
 
 /** @class FilmViewer
  *  @brief A wx widget to view a preview of a Film.
index 51594a47acbd930347ded076aad887dadd9d8203..eab84cc397cb32684b55c5d56ebf57514cd98bc7 100644 (file)
@@ -30,9 +30,9 @@
 #include "lib/server.h"
 #include "lib/image.h"
 #include "lib/cross.h"
-#include "lib/dcp_video_frame.h"
+#include "lib/dcp_video.h"
 #include "lib/scaler.h"
-#include "lib/player_video_frame.h"
+#include "lib/player_video.h"
 #include "lib/image_proxy.h"
 
 using std::list;
@@ -40,7 +40,7 @@ using boost::shared_ptr;
 using boost::thread;
 
 void
-do_remote_encode (shared_ptr<DCPVideoFrame> frame, ServerDescription description, shared_ptr<EncodedData> locally_encoded)
+do_remote_encode (shared_ptr<DCPVideo> frame, ServerDescription description, shared_ptr<EncodedData> locally_encoded)
 {
        shared_ptr<EncodedData> remotely_encoded;
        BOOST_CHECK_NO_THROW (remotely_encoded = frame->encode_remotely (description));
@@ -80,8 +80,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
 
        shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_rgb.log"));
 
-       shared_ptr<PlayerVideoFrame> pvf (
-               new PlayerVideoFrame (
+       shared_ptr<PlayerVideo> pvf (
+               new PlayerVideo (
                        shared_ptr<ImageProxy> (new RawImageProxy (image, log)),
                        Crop (),
                        dcp::Size (1998, 1080),
@@ -95,8 +95,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
 
        pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
 
-       shared_ptr<DCPVideoFrame> frame (
-               new DCPVideoFrame (
+       shared_ptr<DCPVideo> frame (
+               new DCPVideo (
                        pvf,
                        0,
                        24,
@@ -161,8 +161,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
 
        shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_yuv.log"));
 
-       shared_ptr<PlayerVideoFrame> pvf (
-               new PlayerVideoFrame (
+       shared_ptr<PlayerVideo> pvf (
+               new PlayerVideo (
                        shared_ptr<ImageProxy> (new RawImageProxy (image, log)),
                        Crop (),
                        dcp::Size (1998, 1080),
@@ -176,8 +176,8 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
 
        pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
 
-       shared_ptr<DCPVideoFrame> frame (
-               new DCPVideoFrame (
+       shared_ptr<DCPVideo> frame (
+               new DCPVideo (
                        pvf,
                        0,
                        24,