Various stuff; mostly change to decoder scaling and adding subtitle; scaling test.
authorCarl Hetherington <cth@carlh.net>
Fri, 31 May 2013 13:19:50 +0000 (14:19 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 31 May 2013 13:19:50 +0000 (14:19 +0100)
51 files changed:
src/lib/ab_transcode_job.cc
src/lib/ab_transcoder.cc
src/lib/combiner.cc
src/lib/combiner.h
src/lib/config.cc
src/lib/config.h
src/lib/container.cc [deleted file]
src/lib/container.h [deleted file]
src/lib/dcp_video_frame.cc
src/lib/dcp_video_frame.h
src/lib/encoder.cc
src/lib/encoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/film.cc
src/lib/film.h
src/lib/format.cc [deleted file]
src/lib/format.h [deleted file]
src/lib/image.cc
src/lib/image.h
src/lib/player.cc
src/lib/player.h
src/lib/ratio.cc [new file with mode: 0644]
src/lib/ratio.h [new file with mode: 0644]
src/lib/server.cc
src/lib/transcode_job.cc
src/lib/util.cc
src/lib/video_content.cc
src/lib/video_content.h
src/lib/video_decoder.cc
src/lib/video_sink.h
src/lib/video_source.cc
src/lib/video_source.h
src/lib/writer.cc
src/lib/wscript
src/tools/dcpomatic.cc
src/tools/dcpomatic_cli.cc
src/wx/config_dialog.cc
src/wx/film_editor.cc
src/wx/film_editor.h
src/wx/film_viewer.cc
src/wx/film_viewer.h
test/client_server_test.cc
test/container_test.cc [deleted file]
test/dcp_test.cc
test/film_metadata_test.cc
test/format_test.cc [deleted file]
test/make_black_test.cc
test/ratio_test.cc [new file with mode: 0644]
test/scaling_test.cc
test/test.cc

index 9a883fdd93773a87516e47b95c4448b8943f9602..2d6f99c91e8cb7a509bf686154ddf8c1e9f86761 100644 (file)
 #include <stdexcept>
 #include "ab_transcode_job.h"
 #include "film.h"
-#include "format.h"
-#include "filter.h"
 #include "ab_transcoder.h"
 #include "config.h"
-#include "encoder.h"
 
 #include "i18n.h"
 
index 1ec29862603a437192d1a60fed093555171e0c51..a5659b22f555d9c97734ba808b6f0b79c7bfe479 100644 (file)
@@ -50,8 +50,8 @@ ABTranscoder::ABTranscoder (shared_ptr<Film> film_a, shared_ptr<Film> film_b, sh
        , _encoder (new Encoder (film_a, j))
        , _combiner (new Combiner)
 {
-       _player_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3, _4));
-       _player_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3, _4));
+       _player_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3));
+       _player_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3));
 
        _combiner->connect_video (_encoder);
        _player_a->connect_audio (_encoder);
index db490fd34111ce86e56fe0c05d2ba5fa8d76bdc6..ca68ef68afb7d11a9834fd6f0f340226c4507e09 100644 (file)
@@ -32,7 +32,7 @@ Combiner::Combiner ()
  *  @param image Frame image.
  */
 void
-Combiner::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle>, Time)
+Combiner::process_video (shared_ptr<const Image> image, bool, Time)
 {
        _image.reset (new SimpleImage (image));
 }
@@ -42,7 +42,7 @@ Combiner::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitl
  *  @param sub Subtitle (which will be put onto the whole frame)
  */
 void
-Combiner::process_video_b (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, Time t)
+Combiner::process_video_b (shared_ptr<const Image> image, bool, Time t)
 {
        /* Copy the right half of this image into our _image */
        /* XXX: this should probably be in the Image class */
@@ -60,6 +60,6 @@ Combiner::process_video_b (shared_ptr<const Image> image, bool, shared_ptr<Subti
                }
        }
 
-       Video (_image, false, sub, t);
+       Video (_image, false, t);
        _image.reset ();
 }
index 1b7537d42b0eff64d6c85a4c408366fd84385179..46c90b4d8129e56aff5fa47f9b043f2ef0f5bcbe 100644 (file)
@@ -34,8 +34,8 @@ class Combiner : public VideoSource, public VideoSink
 public:
        Combiner ();
 
-       void process_video (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, Time);
-       void process_video_b (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, Time);
+       void process_video (boost::shared_ptr<const Image> i, bool, Time);
+       void process_video_b (boost::shared_ptr<const Image> i, bool, Time);
 
 private:
        /** The image that we are currently working on */
index c5245bfb47135eaf61b01e949caabf8a1f964de2..978428b02dcc61aba49667f3f2cb8e5cde38e45e 100644 (file)
@@ -27,7 +27,7 @@
 #include "server.h"
 #include "scaler.h"
 #include "filter.h"
-#include "container.h"
+#include "ratio.h"
 #include "dcp_content_type.h"
 #include "sound_processor.h"
 
@@ -106,7 +106,7 @@ Config::read ()
 
        c = f.optional_string_child ("DefaultContainer");
        if (c) {
-               _default_container = Container::from_id (c.get ());
+               _default_container = Ratio::from_id (c.get ());
        }
 
        c = f.optional_string_child ("DefaultDCPContentType");
@@ -168,7 +168,7 @@ Config::read_old_metadata ()
                } else if (k == "language") {
                        _language = v;
                } else if (k == "default_container") {
-                       _default_container = Container::from_id (v);
+                       _default_container = Ratio::from_id (v);
                } else if (k == "default_dcp_content_type") {
                        _default_dcp_content_type = DCPContentType::from_dci_name (v);
                } else if (k == "dcp_metadata_issuer") {
index c43a4f079ef4b9753ebb02ea50ec2a2633f4758e..110bcc6a8de5dabbd3aa9a19110f60cb0b200403 100644 (file)
@@ -34,8 +34,8 @@ class ServerDescription;
 class Scaler;
 class Filter;
 class SoundProcessor;
-class Container;
 class DCPContentType;
+class Ratio;
 
 /** @class Config
  *  @brief A singleton class holding configuration.
@@ -114,7 +114,7 @@ public:
                return _default_still_length;
        }
 
-       Container const * default_container () const {
+       Ratio const * default_container () const {
                return _default_container;
        }
 
@@ -193,8 +193,8 @@ public:
                _default_still_length = s;
        }
 
-       void set_default_container (Container const * f) {
-               _default_container = f;
+       void set_default_container (Ratio const * c) {
+               _default_container = c;
        }
 
        void set_default_dcp_content_type (DCPContentType const * t) {
@@ -244,7 +244,7 @@ private:
        DCIMetadata _default_dci_metadata;
        boost::optional<std::string> _language;
        int _default_still_length;
-       Container const * _default_container;
+       Ratio const * _default_container;
        DCPContentType const * _default_dcp_content_type;
        libdcp::XMLMetadata _dcp_metadata;
 
diff --git a/src/lib/container.cc b/src/lib/container.cc
deleted file mode 100644 (file)
index d679e48..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-    Copyright (C) 2013 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 <sstream>
-#include <libdcp/types.h>
-#include "container.h"
-
-#include "i18n.h"
-
-using std::string;
-using std::stringstream;
-using std::vector;
-
-vector<Container const *> Container::_containers;
-
-void
-Container::setup_containers ()
-{
-       _containers.push_back (new Container (float(1285) / 1080, "119", _("1.19"), "F"));
-       _containers.push_back (new Container (float(1436) / 1080, "133", _("4:3"), "F"));
-       _containers.push_back (new Container (float(1480) / 1080, "137", _("Academy"), "F"));
-       _containers.push_back (new Container (float(1485) / 1080, "138", _("1.375"), "F"));
-       _containers.push_back (new Container (float(1793) / 1080, "166", _("1.66"), "F"));
-       _containers.push_back (new Container (float(1920) / 1080, "178", _("16:9"), "F"));
-       _containers.push_back (new Container (float(1998) / 1080, "185", _("Flat"), "F"));
-       _containers.push_back (new Container (float(2048) /  858, "239", _("Scope"), "S"));
-       _containers.push_back (new Container (float(2048) / 1080, "full-frame", _("Full frame"), "C"));
-}
-
-/** @return A name to be presented to the user */
-string
-Container::name () const
-{
-       return _nickname;
-}
-
-Container const *
-Container::from_id (string i)
-{
-       vector<Container const *>::iterator j = _containers.begin ();
-       while (j != _containers.end() && (*j)->id() != i) {
-               ++j;
-       }
-
-       if (j == _containers.end ()) {
-               return 0;
-       }
-
-       return *j;
-}
-
-libdcp::Size
-Container::size (libdcp::Size full_frame) const
-{
-       if (_ratio < static_cast<float>(full_frame.width) / full_frame.height) {
-               return libdcp::Size (full_frame.height * _ratio, full_frame.height);
-       } else {
-               return libdcp::Size (full_frame.width, full_frame.width / _ratio);
-       }
-
-       return libdcp::Size ();
-}
diff --git a/src/lib/container.h b/src/lib/container.h
deleted file mode 100644 (file)
index 4bf03a3..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-    Copyright (C) 2013 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 <vector>
-#include <libdcp/util.h>
-
-class Container
-{
-public:
-       Container (float ratio, std::string id, std::string n, std::string d)
-               : _ratio (ratio)
-               , _id (id)
-               , _nickname (n)
-               , _dci_name (d)
-       {}
-
-       libdcp::Size size (libdcp::Size) const;
-
-       std::string id () const {
-               return _id;
-       }
-
-       std::string name () const;
-
-       /** @return Nickname (e.g. Flat, Scope) */
-       std::string nickname () const {
-               return _nickname;
-       }
-
-       std::string dci_name () const {
-               return _dci_name;
-       }
-
-       float ratio () const {
-               return _ratio;
-       }
-       
-       static void setup_containers ();
-       static Container const * from_id (std::string i);
-       static std::vector<Container const *> all () {
-               return _containers;
-       }
-
-private:
-       float _ratio;
-       /** id for use in metadata */
-       std::string _id;
-       /** nickname (e.g. Flat, Scope) */
-       std::string _nickname;
-       std::string _dci_name;
-
-       /** all available containers */
-       static std::vector<Container const *> _containers;
-};
index 1c1838df79403f046f62511ec84bbe04273e4897..2f597522c3c4401fb17c476d6d2a7ffc20223450 100644 (file)
@@ -53,7 +53,6 @@
 #include "scaler.h"
 #include "image.h"
 #include "log.h"
-#include "subtitle.h"
 
 #include "i18n.h"
 
@@ -66,34 +65,21 @@ using libdcp::Size;
 
 /** Construct a DCP video frame.
  *  @param input Input image.
- *  @param out Required size of output, in pixels (including any padding).
- *  @param s Scaler to use.
- *  @param p Number of pixels of padding either side of the image.
  *  @param f Index of the frame within the DCP.
- *  @param fps Frames per second of the Film's source.
- *  @param pp FFmpeg post-processing string to use.
  *  @param clut Colour look-up table to use (see Config::colour_lut_index ())
  *  @param bw J2K bandwidth to use (see Config::j2k_bandwidth ())
  *  @param l Log to write to.
  */
 DCPVideoFrame::DCPVideoFrame (
-       shared_ptr<const Image> yuv, shared_ptr<Subtitle> sub,
-       Size out, int p, int subtitle_offset, float subtitle_scale,
-       Scaler const * s, int f, int dcp_fps, int clut, int bw, shared_ptr<Log> l
+       shared_ptr<const Image> image, int f, int dcp_fps, int clut, int bw, shared_ptr<Log> l
        )
-       : _input (yuv)
-       , _subtitle (sub)
-       , _out_size (out)
-       , _padding (p)
-       , _subtitle_offset (subtitle_offset)
-       , _subtitle_scale (subtitle_scale)
-       , _scaler (s)
+       : _image (image)
        , _frame (f)
        , _frames_per_second (dcp_fps)
        , _colour_lut (clut)
        , _j2k_bandwidth (bw)
        , _log (l)
-       , _image (0)
+       , _opj_image (0)
        , _parameters (0)
        , _cinfo (0)
        , _cio (0)
@@ -108,8 +94,8 @@ DCPVideoFrame::create_openjpeg_container ()
        for (int i = 0; i < 3; ++i) {
                _cmptparm[i].dx = 1;
                _cmptparm[i].dy = 1;
-               _cmptparm[i].w = _out_size.width;
-               _cmptparm[i].h = _out_size.height;
+               _cmptparm[i].w = _image->size().width;
+               _cmptparm[i].h = _image->size().height;
                _cmptparm[i].x0 = 0;
                _cmptparm[i].y0 = 0;
                _cmptparm[i].prec = 12;
@@ -117,21 +103,21 @@ DCPVideoFrame::create_openjpeg_container ()
                _cmptparm[i].sgnd = 0;
        }
 
-       _image = opj_image_create (3, &_cmptparm[0], CLRSPC_SRGB);
-       if (_image == 0) {
+       _opj_image = opj_image_create (3, &_cmptparm[0], CLRSPC_SRGB);
+       if (_opj_image == 0) {
                throw EncodeError (N_("could not create libopenjpeg image"));
        }
 
-       _image->x0 = 0;
-       _image->y0 = 0;
-       _image->x1 = _out_size.width;
-       _image->y1 = _out_size.height;
+       _opj_image->x0 = 0;
+       _opj_image->y0 = 0;
+       _opj_image->x1 = _image->size().width;
+       _opj_image->y1 = _image->size().height;
 }
 
 DCPVideoFrame::~DCPVideoFrame ()
 {
-       if (_image) {
-               opj_image_destroy (_image);
+       if (_opj_image) {
+               opj_image_destroy (_opj_image);
        }
 
        if (_cio) {
@@ -155,19 +141,6 @@ DCPVideoFrame::~DCPVideoFrame ()
 shared_ptr<EncodedData>
 DCPVideoFrame::encode_locally ()
 {
-       shared_ptr<Image> prepared = _input->scale_and_convert_to_rgb (_out_size, _padding, _scaler, true);
-
-       if (_subtitle) {
-               Rect tx = subtitle_transformed_area (
-                       float (_out_size.width) / _input->size().width,
-                       float (_out_size.height) / _input->size().height,
-                       _subtitle->area(), _subtitle_offset, _subtitle_scale
-                       );
-
-               shared_ptr<Image> im = _subtitle->image()->scale (tx.size(), _scaler, true);
-               prepared->alpha_blend (im, tx.position());
-       }
-
        create_openjpeg_container ();
 
        struct {
@@ -181,9 +154,9 @@ DCPVideoFrame::encode_locally ()
        /* Copy our RGB into the openjpeg container, converting to XYZ in the process */
 
        int jn = 0;
-       for (int y = 0; y < _out_size.height; ++y) {
-               uint8_t* p = prepared->data()[0] + y * prepared->stride()[0];
-               for (int x = 0; x < _out_size.width; ++x) {
+       for (int y = 0; y < _image->size().height; ++y) {
+               uint8_t* p = _image->data()[0] + y * _image->stride()[0];
+               for (int x = 0; x < _image->size().width; ++x) {
 
                        /* In gamma LUT (converting 8-bit input to 12-bit) */
                        s.r = lut_in[_colour_lut][*p++ << 4];
@@ -209,9 +182,9 @@ DCPVideoFrame::encode_locally ()
                        d.z = d.z * DCI_COEFFICENT * (DCI_LUT_SIZE - 1);
                        
                        /* Out gamma LUT */
-                       _image->comps[0].data[jn] = lut_out[LO_DCI][(int) d.x];
-                       _image->comps[1].data[jn] = lut_out[LO_DCI][(int) d.y];
-                       _image->comps[2].data[jn] = lut_out[LO_DCI][(int) d.z];
+                       _opj_image->comps[0].data[jn] = lut_out[LO_DCI][(int) d.x];
+                       _opj_image->comps[1].data[jn] = lut_out[LO_DCI][(int) d.y];
+                       _opj_image->comps[2].data[jn] = lut_out[LO_DCI][(int) d.z];
 
                        ++jn;
                }
@@ -269,7 +242,7 @@ DCPVideoFrame::encode_locally ()
        
        /* set max image */
        _parameters->max_comp_size = max_comp_size;
-       _parameters->tcp_rates[0] = ((float) (3 * _image->comps[0].w * _image->comps[0].h * _image->comps[0].prec)) / (max_cs_len * 8);
+       _parameters->tcp_rates[0] = ((float) (3 * _opj_image->comps[0].w * _opj_image->comps[0].h * _opj_image->comps[0].prec)) / (max_cs_len * 8);
 
        /* get a J2K compressor handle */
        _cinfo = opj_create_compress (CODEC_J2K);
@@ -281,14 +254,14 @@ DCPVideoFrame::encode_locally ()
        _cinfo->event_mgr = 0;
 
        /* Setup the encoder parameters using the current image and user parameters */
-       opj_setup_encoder (_cinfo, _parameters, _image);
+       opj_setup_encoder (_cinfo, _parameters, _opj_image);
 
        _cio = opj_cio_open ((opj_common_ptr) _cinfo, 0, 0);
        if (_cio == 0) {
                throw EncodeError (N_("could not open JPEG2000 stream"));
        }
 
-       int const r = opj_encode (_cinfo, _cio, _image, 0);
+       int const r = opj_encode (_cinfo, _cio, _opj_image, 0);
        if (r == 0) {
                throw EncodeError (N_("JPEG2000 encoding failed"));
        }
@@ -316,42 +289,24 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv)
 
        stringstream s;
        s << N_("encode please\n")
-         << N_("input_width ") << _input->size().width << N_("\n")
-         << N_("input_height ") << _input->size().height << N_("\n")
-         << N_("input_pixel_format ") << _input->pixel_format() << N_("\n")
-         << N_("output_width ") << _out_size.width << N_("\n")
-         << N_("output_height ") << _out_size.height << N_("\n")
-         << N_("padding ") <<  _padding << N_("\n")
-         << N_("subtitle_offset ") << _subtitle_offset << N_("\n")
-         << N_("subtitle_scale ") << _subtitle_scale << N_("\n")
-         << N_("scaler ") << _scaler->id () << N_("\n")
+         << N_("width ") << _image->size().width << N_("\n")
+         << N_("height ") << _image->size().height << N_("\n")
          << N_("frame ") << _frame << N_("\n")
-         << N_("frames_per_second ") << _frames_per_second << N_("\n");
-
-       s << N_("colour_lut ") << _colour_lut << N_("\n")
+         << N_("frames_per_second ") << _frames_per_second << N_("\n")
+         << N_("colour_lut ") << _colour_lut << N_("\n")
          << N_("j2k_bandwidth ") << _j2k_bandwidth << N_("\n");
 
-       if (_subtitle) {
-               s << N_("subtitle_x ") << _subtitle->position().x << N_("\n")
-                 << N_("subtitle_y ") << _subtitle->position().y << N_("\n")
-                 << N_("subtitle_width ") << _subtitle->image()->size().width << N_("\n")
-                 << N_("subtitle_height ") << _subtitle->image()->size().height << N_("\n");
-       }
-
        _log->log (String::compose (
                           N_("Sending to remote; pixel format %1, components %2, lines (%3,%4,%5), line sizes (%6,%7,%8)"),
-                          _input->pixel_format(), _input->components(),
-                          _input->lines(0), _input->lines(1), _input->lines(2),
-                          _input->line_size()[0], _input->line_size()[1], _input->line_size()[2]
+                          _image->pixel_format(), _image->components(),
+                          _image->lines(0), _image->lines(1), _image->lines(2),
+                          _image->line_size()[0], _image->line_size()[1], _image->line_size()[2]
                           ));
 
        socket->write (s.str().length() + 1);
        socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1);
 
-       _input->write_to_socket (socket);
-       if (_subtitle) {
-               _subtitle->image()->write_to_socket (socket);
-       }
+       _image->write_to_socket (socket);
 
        shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
        socket->read (e->data(), e->size());
index ba49c95a43364a125452c8e515aa33c7d8737dda..f234b445abe00f9ba8cd169d1971b95882a76709 100644 (file)
@@ -105,12 +105,8 @@ public:
 class DCPVideoFrame
 {
 public:
-       DCPVideoFrame (
-               boost::shared_ptr<const Image>, boost::shared_ptr<Subtitle>, libdcp::Size,
-               int, int, float, Scaler const *, int, int, int, int, boost::shared_ptr<Log>
-               );
-       
-       virtual ~DCPVideoFrame ();
+       DCPVideoFrame (boost::shared_ptr<const Image>, int, int, int, int, boost::shared_ptr<Log>);
+       ~DCPVideoFrame ();
 
        boost::shared_ptr<EncodedData> encode_locally ();
        boost::shared_ptr<EncodedData> encode_remotely (ServerDescription const *);
@@ -122,13 +118,7 @@ public:
 private:
        void create_openjpeg_container ();
 
-       boost::shared_ptr<const Image> _input; ///< the input image
-       boost::shared_ptr<Subtitle> _subtitle; ///< any subtitle that should be on the image
-       libdcp::Size _out_size;                ///< the required size of the output, in pixels
-       int _padding;
-       int _subtitle_offset;
-       float _subtitle_scale;
-       Scaler const * _scaler;          ///< scaler to use
+       boost::shared_ptr<const Image> _image;
        int _frame;                      ///< frame index within the DCP's intrinsic duration
        int _frames_per_second;          ///< Frames per second that we will use for the DCP
        int _colour_lut;                 ///< Colour look-up table to use
@@ -137,7 +127,7 @@ private:
        boost::shared_ptr<Log> _log; ///< log
 
        opj_image_cmptparm_t _cmptparm[3]; ///< libopenjpeg's opj_image_cmptparm_t
-       opj_image* _image;                 ///< libopenjpeg's image container 
+       opj_image* _opj_image;             ///< libopenjpeg's image container 
        opj_cparameters_t* _parameters;    ///< libopenjpeg's parameters
        opj_cinfo_t* _cinfo;               ///< libopenjpeg's opj_cinfo_t
        opj_cio_t* _cio;                   ///< libopenjpeg's opj_cio_t
index 3152669ad46a0e083d7893781866ba9770f30a4f..f3745ff98aad53da45e403109518bac768ed29ba 100644 (file)
  */
 
 #include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libdcp/picture_asset.h>
 #include "encoder.h"
 #include "util.h"
 #include "film.h"
 #include "log.h"
-#include "exceptions.h"
-#include "filter.h"
 #include "config.h"
 #include "dcp_video_frame.h"
 #include "server.h"
-#include "format.h"
 #include "cross.h"
 #include "writer.h"
-#include "player.h"
-#include "audio_mapping.h"
-#include "container.h"
 
 #include "i18n.h"
 
@@ -178,7 +169,7 @@ Encoder::frame_done ()
 }
 
 void
-Encoder::process_video (shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time)
+Encoder::process_video (shared_ptr<const Image> image, bool same, Time)
 {
        boost::mutex::scoped_lock lock (_mutex);
 
@@ -211,11 +202,8 @@ Encoder::process_video (shared_ptr<const Image> image, bool same, shared_ptr<Sub
                /* XXX: padding */
                _queue.push_back (shared_ptr<DCPVideoFrame> (
                                          new DCPVideoFrame (
-                                                 image, sub, _film->container()->size (_film->full_frame()), 0,
-                                                 _film->subtitle_offset(), _film->subtitle_scale(),
-                                                 _film->scaler(), _video_frames_out, _film->dcp_video_frame_rate(),
-                                                 _film->colour_lut(), _film->j2k_bandwidth(),
-                                                 _film->log()
+                                                 image, _video_frames_out, _film->dcp_video_frame_rate(),
+                                                 _film->colour_lut(), _film->j2k_bandwidth(), _film->log()
                                                  )
                                          ));
                
index 6815fa6f660e6f24261407c2aadd43be081eec45..8f724525cbe791c965d67c3b1e13f06f08f7a1b4 100644 (file)
@@ -40,7 +40,6 @@ extern "C" {
 #include "audio_sink.h"
 
 class Image;
-class Subtitle;
 class AudioBuffers;
 class Film;
 class ServerDescription;
@@ -52,7 +51,7 @@ class Job;
 /** @class Encoder
  *  @brief Encoder to J2K and WAV for DCP.
  *
- *  Video is supplied to process_video as YUV frames, and audio
+ *  Video is supplied to process_video as RGB frames, and audio
  *  is supplied as uncompressed PCM in blocks of various sizes.
  */
 
@@ -68,9 +67,8 @@ public:
        /** Call with a frame of video.
         *  @param i Video frame image.
         *  @param same true if i is the same as the last time we were called.
-        *  @param s A subtitle that should be on this frame, or 0.
         */
-       void process_video (boost::shared_ptr<const Image> i, bool same, boost::shared_ptr<Subtitle> s, Time);
+       void process_video (boost::shared_ptr<const Image> i, bool same, Time);
 
        /** Call with some audio data */
        void process_audio (boost::shared_ptr<const AudioBuffers>, Time);
index a1a6636fb6ed005a12577cffede608c369f94149..c148bc530c7cf8f84fb342a9b3aff8aafbfd2c3b 100644 (file)
@@ -39,9 +39,6 @@ extern "C" {
 }
 #include <sndfile.h>
 #include "film.h"
-#include "format.h"
-#include "transcoder.h"
-#include "job.h"
 #include "filter.h"
 #include "exceptions.h"
 #include "image.h"
index c3747961266789a8b2da5447d15dc9c578d3cc1b..7b8e1b50c14657a89db05eabe7f951e4ac1458a2 100644 (file)
@@ -37,8 +37,6 @@ extern "C" {
 #include "decoder.h"
 #include "video_decoder.h"
 #include "audio_decoder.h"
-#include "film.h"
-#include "ffmpeg_content.h"
 
 struct AVFilterGraph;
 struct AVCodecContext;
@@ -52,6 +50,8 @@ class Job;
 class Options;
 class Image;
 class Log;
+class FFmpegContent;
+class Film;
 
 /** @class FFmpegDecoder
  *  @brief A decoder using FFmpeg to decode content.
index e76d97b5950607d175da422bbda983f881923f37..ef29d35fdde57806a2d0ef8f0a5f9a3def734789 100644 (file)
@@ -32,7 +32,6 @@
 #include <libxml++/libxml++.h>
 #include <libcxml/cxml.h>
 #include "film.h"
-#include "container.h"
 #include "job.h"
 #include "filter.h"
 #include "util.h"
@@ -54,6 +53,7 @@
 #include "imagemagick_content.h"
 #include "sndfile_content.h"
 #include "dcp_content_type.h"
+#include "ratio.h"
 
 #include "i18n.h"
 
@@ -426,7 +426,7 @@ Film::read_metadata ()
        {
                optional<string> c = f.optional_string_child ("Container");
                if (c) {
-                       _container = Container::from_id (c.get ());
+                       _container = Ratio::from_id (c.get ());
                }
        }
 
@@ -602,7 +602,7 @@ Film::set_dcp_content_type (DCPContentType const * t)
 }
 
 void
-Film::set_container (Container const * c)
+Film::set_container (Ratio const * c)
 {
        {
                boost::mutex::scoped_lock lm (_state_mutex);
index 31454c5a7c7c1a8d8a2b18973f09d2abc1c61755..28beeaed1920769eac45801a64f11ffd7cbf1074 100644 (file)
@@ -39,7 +39,6 @@
 #include "playlist.h"
 
 class DCPContentType;
-class Container;
 class Job;
 class Filter;
 class Log;
@@ -169,7 +168,7 @@ public:
                return _dcp_content_type;
        }
 
-       Container const * container () const {
+       Ratio const * container () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _container;
        }
@@ -234,7 +233,7 @@ public:
        void add_content (boost::shared_ptr<Content>);
        void remove_content (boost::shared_ptr<Content>);
        void set_dcp_content_type (DCPContentType const *);
-       void set_container (Container const *);
+       void set_container (Ratio const *);
        void set_scaler (Scaler const *);
        void set_ab (bool);
        void set_with_subtitles (bool);
@@ -286,7 +285,7 @@ private:
        /** The type of content that this Film represents (feature, trailer etc.) */
        DCPContentType const * _dcp_content_type;
        /** The container to put this Film in (flat, scope, etc.) */
-       Container const * _container;
+       Ratio const * _container;
        /** Scaler algorithm to use */
        Scaler const * _scaler;
        /** true to create an A/B comparison DCP, where the left half of the image
diff --git a/src/lib/format.cc b/src/lib/format.cc
deleted file mode 100644 (file)
index 87bdda3..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-    Copyright (C) 2012 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 src/format.cc
- *  @brief Class to describe a format (aspect ratio) that a Film should
- *  be shown in.
- */
-
-#include <sstream>
-#include <cstdlib>
-#include <cassert>
-#include <iomanip>
-#include <iostream>
-#include "format.h"
-#include "film.h"
-#include "playlist.h"
-
-#include "i18n.h"
-
-using std::string;
-using std::setprecision;
-using std::stringstream;
-using std::vector;
-using boost::shared_ptr;
-using libdcp::Size;
-
-vector<Format const *> Format::_formats;
-
-/** @return A name to be presented to the user */
-string
-Format::name () const
-{
-       stringstream s;
-       if (!_nickname.empty ()) {
-               s << _nickname << N_(" (");
-       }
-
-       s << setprecision(3) << ratio() << N_(":1");
-
-       if (!_nickname.empty ()) {
-               s << N_(")");
-       }
-
-       return s.str ();
-}
-
-/** Fill our _formats vector with all available formats */
-void
-Format::setup_formats ()
-{
-       /// TRANSLATORS: these are film picture aspect ratios; "Academy" means 1.37, "Flat" 1.85 and "Scope" 2.39.
-       _formats.push_back (new Format (libdcp::Size (1285, 1080), "119", _("1.19")));
-       _formats.push_back (new Format (libdcp::Size (1436, 1080), "133", _("4:3")));
-       _formats.push_back (new Format (libdcp::Size (1485, 1080), "138", _("1.375")));
-       _formats.push_back (new Format (libdcp::Size (1480, 1080), "137", _("Academy")));
-       _formats.push_back (new Format (libdcp::Size (1793, 1080), "166", _("1.66")));
-       _formats.push_back (new Format (libdcp::Size (1920, 1080), "178", _("16:9")));
-       _formats.push_back (new Format (libdcp::Size (1998, 1080), "185", _("Flat")));
-       _formats.push_back (new Format (libdcp::Size (2048, 858), "239", _("Scope")));
-       _formats.push_back (new Format (libdcp::Size (2048, 1080), "full-frame", _("Full frame")));
-}
-
-/** @param n Nickname.
- *  @return Matching Format, or 0.
- */
-Format const *
-Format::from_nickname (string n)
-{
-       vector<Format const *>::iterator i = _formats.begin ();
-       while (i != _formats.end() && (*i)->nickname() != n) {
-               ++i;
-       }
-
-       if (i == _formats.end ()) {
-               return 0;
-       }
-
-       return *i;
-}
-
-/** @param i Id.
- *  @return Matching Format, or 0.
- */
-Format const *
-Format::from_id (string i)
-{
-       vector<Format const *>::iterator j = _formats.begin ();
-       while (j != _formats.end() && (*j)->id() != i) {
-               ++j;
-       }
-
-       if (j == _formats.end ()) {
-               return 0;
-       }
-
-       return *j;
-}
-
-/** @return All available formats */
-vector<Format const *>
-Format::all ()
-{
-       return _formats;
-}
-
-float
-Format::ratio () const
-{
-       return static_cast<float> (_dcp_size.width) / _dcp_size.height;
-}
diff --git a/src/lib/format.h b/src/lib/format.h
deleted file mode 100644 (file)
index 06423d2..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-    Copyright (C) 2012 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 src/format.h
- *  @brief Classes to describe a format (aspect ratio) that a Film should
- *  be shown in.
- */
-
-#include <string>
-#include <vector>
-#include <libdcp/util.h>
-
-class Film;
-
-class Format
-{
-public:
-       Format (libdcp::Size dcp, std::string id, std::string n)
-               : _dcp_size (dcp)
-               , _id (id)
-               , _nickname (n)
-       {}
-
-       /** @return size in pixels of the images that we should
-        *  put in a DCP for this format.
-        */
-       libdcp::Size dcp_size () const {
-               return _dcp_size;
-       }
-
-       std::string id () const {
-               return _id;
-       }
-
-       /** @return Full name to present to the user */
-       std::string name () const;
-
-       /** @return Nickname (e.g. Flat, Scope) */
-       std::string nickname () const {
-               return _nickname;
-       }
-
-       static Format const * from_nickname (std::string n);
-       static Format const * from_id (std::string i);
-       static std::vector<Format const *> all ();
-       static void setup_formats ();
-
-protected:     
-        /** @return the ratio */
-       float ratio () const;
-
-       /** libdcp::Size in pixels of the images that we should
-        *  put in a DCP for this format.
-        */
-       libdcp::Size _dcp_size;
-       /** id for use in metadata */
-       std::string _id;
-       /** nickname (e.g. Flat, Scope) */
-       std::string _nickname;
-
-private:       
-       /** all available formats */
-       static std::vector<Format const *> _formats;
-};
index b166dfac6a0c72054531dc19cce0b9a7fd445971..a12c61b3e8a9ce3992d5641d351926481e818361 100644 (file)
@@ -121,7 +121,7 @@ Image::scale (libdcp::Size out_size, Scaler const * scaler, bool result_aligned)
  *  @param scaler Scaler to use.
  */
 shared_ptr<Image>
-Image::scale_and_convert_to_rgb (libdcp::Size out_size, int padding, Scaler const * scaler, bool result_aligned) const
+Image::scale_and_convert_to_rgb (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
 {
        assert (scaler);
        /* Empirical testing suggests that sws_scale() will crash if
@@ -129,14 +129,11 @@ Image::scale_and_convert_to_rgb (libdcp::Size out_size, int padding, Scaler cons
        */
        assert (aligned ());
 
-       libdcp::Size content_size = out_size;
-       content_size.width -= (padding * 2);
-
-       shared_ptr<Image> rgb (new SimpleImage (PIX_FMT_RGB24, content_size, result_aligned));
+       shared_ptr<Image> rgb (new SimpleImage (PIX_FMT_RGB24, out_size, result_aligned));
 
        struct SwsContext* scale_context = sws_getContext (
                size().width, size().height, pixel_format(),
-               content_size.width, content_size.height, PIX_FMT_RGB24,
+               out_size.width, out_size.height, PIX_FMT_RGB24,
                scaler->ffmpeg_id (), 0, 0, 0
                );
 
@@ -148,28 +145,6 @@ Image::scale_and_convert_to_rgb (libdcp::Size out_size, int padding, Scaler cons
                rgb->data(), rgb->stride()
                );
 
-       /* Put the image in the right place in a black frame if are padding; this is
-          a bit grubby and expensive, but probably inconsequential in the great
-          scheme of things.
-       */
-       if (padding > 0) {
-               shared_ptr<Image> padded_rgb (new SimpleImage (PIX_FMT_RGB24, out_size, result_aligned));
-               padded_rgb->make_black ();
-
-               /* XXX: we are cheating a bit here; we know the frame is RGB so we can
-                  make assumptions about its composition.
-               */
-               uint8_t* p = padded_rgb->data()[0] + padding * 3;
-               uint8_t* q = rgb->data()[0];
-               for (int j = 0; j < rgb->lines(0); ++j) {
-                       memcpy (p, q, rgb->line_size()[0]);
-                       p += padded_rgb->stride()[0];
-                       q += rgb->stride()[0];
-               }
-
-               rgb = padded_rgb;
-       }
-
        sws_freeContext (scale_context);
 
        return rgb;
@@ -376,6 +351,21 @@ Image::alpha_blend (shared_ptr<const Image> other, Position position)
        }
 }
 
+void
+Image::copy (shared_ptr<const Image> other, Position position)
+{
+       /* Only implemented for RGB24 onto RGB24 so far */
+       assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
+       assert (position.x >= 0 && position.y >= 0);
+
+       int const N = min (position.x + other->size().width, size().width) - position.x;
+       for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
+               uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
+               uint8_t * const op = other->data()[0] + oy * other->stride()[0];
+               memcpy (tp, op, N * 3);
+       }
+}      
+
 void
 Image::read_from_socket (shared_ptr<Socket> socket)
 {
index 34f87b18852966c39a7b446a59ee1809a0ef35e5..f9bda7460327e62706ef2fa3a982c0b4efe478b3 100644 (file)
@@ -71,10 +71,11 @@ public:
        int components () const;
        int lines (int) const;
 
-       boost::shared_ptr<Image> scale_and_convert_to_rgb (libdcp::Size out_size, int padding, Scaler const * scaler, bool aligned) const;
+       boost::shared_ptr<Image> scale_and_convert_to_rgb (libdcp::Size, Scaler const *, bool) const;
        boost::shared_ptr<Image> scale (libdcp::Size, Scaler const *, bool aligned) const;
        boost::shared_ptr<Image> post_process (std::string, bool aligned) const;
        void alpha_blend (boost::shared_ptr<const Image> image, Position pos);
+       void copy (boost::shared_ptr<const Image> image, Position pos);
        boost::shared_ptr<Image> crop (Crop c, bool aligned) const;
        
        void make_black ();
index 2926796ef1d35f440fdf2344899cfc536e884d8a..e64e1e0114edf2cfe63ec17e4aedecad3d190cdd 100644 (file)
@@ -119,6 +119,7 @@ Player::pass ()
        }
 
        if (!earliest) {
+               flush ();
                return true;
        }
 
@@ -144,7 +145,7 @@ Player::pass ()
 }
 
 void
-Player::process_video (weak_ptr<Content> weak_content, shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time time)
+Player::process_video (weak_ptr<Content> weak_content, shared_ptr<const Image> image, bool same, Time time)
 {
        shared_ptr<Content> content = weak_content.lock ();
        if (!content) {
@@ -153,7 +154,7 @@ Player::process_video (weak_ptr<Content> weak_content, shared_ptr<const Image> i
        
        time += content->start ();
        
-        Video (image, same, sub, time);
+        Video (image, same, time);
 }
 
 void
@@ -192,6 +193,18 @@ Player::process_audio (weak_ptr<Content> weak_content, shared_ptr<const AudioBuf
        _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
 }
 
+void
+Player::flush ()
+{
+       if (_audio_buffers.frames() > 0) {
+               shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
+               emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
+               Audio (emit, _next_audio);
+               _next_audio += _film->audio_frames_to_time (_audio_buffers.frames ());
+               _audio_buffers.set_frames (0);
+       }
+}
+
 /** @return true on error */
 void
 Player::seek (Time t)
@@ -236,7 +249,7 @@ Player::add_black_piece (Time s, Time len)
 {
        shared_ptr<NullContent> nc (new NullContent (_film, s, len));
        shared_ptr<BlackDecoder> bd (new BlackDecoder (_film, nc));
-       bd->Video.connect (bind (&Player::process_video, this, nc, _1, _2, _3, _4));
+       bd->Video.connect (bind (&Player::process_video, this, nc, _1, _2, _3));
        _pieces.push_back (shared_ptr<Piece> (new Piece (nc, bd)));
        cout << "\tblack @ " << s << " -- " << (s + len) << "\n";
 }
@@ -274,7 +287,7 @@ Player::setup_pieces ()
                if (fc) {
                        shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio, _subtitles));
                        
-                       fd->Video.connect (bind (&Player::process_video, this, *i, _1, _2, _3, _4));
+                       fd->Video.connect (bind (&Player::process_video, this, *i, _1, _2, _3));
                        fd->Audio.connect (bind (&Player::process_audio, this, *i, _1, _2));
 
                        decoder = fd;
@@ -295,7 +308,7 @@ Player::setup_pieces ()
 
                        if (!id) {
                                id.reset (new ImageMagickDecoder (_film, ic));
-                               id->Video.connect (bind (&Player::process_video, this, *i, _1, _2, _3, _4));
+                               id->Video.connect (bind (&Player::process_video, this, *i, _1, _2, _3));
                        }
 
                        decoder = id;
index cdedf1676eca8d46be8745e29a5aac332d4a8d33..cce2bdc21a600ac3e61b59e40d997c0d876985bf 100644 (file)
@@ -62,7 +62,7 @@ public:
 
 private:
 
-       void process_video (boost::weak_ptr<Content>, boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time);
+       void process_video (boost::weak_ptr<Content>, boost::shared_ptr<const Image>, bool, Time);
        void process_audio (boost::weak_ptr<Content>, boost::shared_ptr<const AudioBuffers>, Time);
        void setup_pieces ();
        void playlist_changed ();
@@ -70,6 +70,7 @@ private:
        void do_seek (Time, bool);
        void add_black_piece (Time, Time);
        void add_silent_piece (Time, Time);
+       void flush ();
 
        boost::shared_ptr<const Film> _film;
        boost::shared_ptr<const Playlist> _playlist;
diff --git a/src/lib/ratio.cc b/src/lib/ratio.cc
new file mode 100644 (file)
index 0000000..5988b34
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+    Copyright (C) 2013 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 <libdcp/types.h>
+#include "ratio.h"
+
+#include "i18n.h"
+
+using std::string;
+using std::stringstream;
+using std::vector;
+
+vector<Ratio const *> Ratio::_ratios;
+
+libdcp::Size
+Ratio::size (libdcp::Size full_frame) const
+{
+       if (_ratio < static_cast<float>(full_frame.width) / full_frame.height) {
+               return libdcp::Size (full_frame.height * _ratio, full_frame.height);
+       } else {
+               return libdcp::Size (full_frame.width, full_frame.width / _ratio);
+       }
+
+       return libdcp::Size ();
+}
+
+
+void
+Ratio::setup_ratios ()
+{
+       _ratios.push_back (new Ratio (float(1285) / 1080, "119", _("1.19"), "F"));
+       _ratios.push_back (new Ratio (float(1436) / 1080, "133", _("4:3"), "F"));
+       _ratios.push_back (new Ratio (float(1480) / 1080, "137", _("Academy"), "F"));
+       _ratios.push_back (new Ratio (float(1485) / 1080, "138", _("1.375"), "F"));
+       _ratios.push_back (new Ratio (float(1793) / 1080, "166", _("1.66"), "F"));
+       _ratios.push_back (new Ratio (float(1920) / 1080, "178", _("16:9"), "F"));
+       _ratios.push_back (new Ratio (float(1998) / 1080, "185", _("Flat"), "F"));
+       _ratios.push_back (new Ratio (float(2048) /  858, "239", _("Scope"), "S"));
+       _ratios.push_back (new Ratio (float(2048) / 1080, "full-frame", _("Full frame"), "C"));
+}
+
+Ratio const *
+Ratio::from_id (string i)
+{
+       vector<Ratio const *>::iterator j = _ratios.begin ();
+       while (j != _ratios.end() && (*j)->id() != i) {
+               ++j;
+       }
+
+       if (j == _ratios.end ()) {
+               return 0;
+       }
+
+       return *j;
+}
diff --git a/src/lib/ratio.h b/src/lib/ratio.h
new file mode 100644 (file)
index 0000000..6916a74
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+    Copyright (C) 2013 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 <vector>
+#include <libdcp/util.h>
+
+class Ratio
+{
+public:
+       Ratio (float ratio, std::string id, std::string n, std::string d)
+               : _ratio (ratio)
+               , _id (id)
+               , _nickname (n)
+               , _dci_name (d)
+       {}
+
+       libdcp::Size size (libdcp::Size) const;
+
+       std::string id () const {
+               return _id;
+       }
+
+       std::string nickname () const {
+               return _nickname;
+       }
+
+       std::string dci_name () const {
+               return _dci_name;
+       }
+
+       float ratio () const {
+               return _ratio;
+       }
+
+       static void setup_ratios ();
+       static Ratio const * from_id (std::string i);
+       static std::vector<Ratio const *> all () {
+               return _ratios;
+       }
+
+private:
+       float _ratio;
+       /** id for use in metadata */
+       std::string _id;
+       /** nickname (e.g. Flat, Scope) */
+       std::string _nickname;
+       std::string _dci_name;
+
+       static std::vector<Ratio const *> _ratios;      
+};
index 07b82694666c3146be87fbae45d13cf4722f19d4..5ca04c69249c2292b005432d0605ae021a72e546 100644 (file)
@@ -98,44 +98,25 @@ Server::process (shared_ptr<Socket> socket)
        stringstream s (buffer.get());
        multimap<string, string> kv = read_key_value (s);
 
-       if (get_required_string (kv, N_("encode")) != N_("please")) {
+       if (get_required_string (kv, "encode") != "please") {
                return -1;
        }
 
-       libdcp::Size in_size (get_required_int (kv, N_("input_width")), get_required_int (kv, N_("input_height")));
-       int pixel_format_int = get_required_int (kv, N_("input_pixel_format"));
-       libdcp::Size out_size (get_required_int (kv, N_("output_width")), get_required_int (kv, N_("output_height")));
-       int padding = get_required_int (kv, N_("padding"));
-       int subtitle_offset = get_required_int (kv, N_("subtitle_offset"));
-       float subtitle_scale = get_required_float (kv, N_("subtitle_scale"));
-       string scaler_id = get_required_string (kv, N_("scaler"));
-       int frame = get_required_int (kv, N_("frame"));
-       int frames_per_second = get_required_int (kv, N_("frames_per_second"));
-       int colour_lut_index = get_required_int (kv, N_("colour_lut"));
-       int j2k_bandwidth = get_required_int (kv, N_("j2k_bandwidth"));
-       Position subtitle_position (get_optional_int (kv, N_("subtitle_x")), get_optional_int (kv, N_("subtitle_y")));
-       libdcp::Size subtitle_size (get_optional_int (kv, N_("subtitle_width")), get_optional_int (kv, N_("subtitle_height")));
+       libdcp::Size size (get_required_int (kv, "width"), get_required_int (kv, "height"));
+       int frame = get_required_int (kv, "frame");
+       int frames_per_second = get_required_int (kv, "frames_per_second");
+       int colour_lut_index = get_required_int (kv, "colour_lut");
+       int j2k_bandwidth = get_required_int (kv, "j2k_bandwidth");
 
        /* This checks that colour_lut_index is within range */
        colour_lut_index_to_name (colour_lut_index);
 
-       PixelFormat pixel_format = (PixelFormat) pixel_format_int;
-       Scaler const * scaler = Scaler::from_id (scaler_id);
-       
-       shared_ptr<Image> image (new SimpleImage (pixel_format, in_size, true));
+       shared_ptr<Image> image (new SimpleImage (PIX_FMT_RGB24, size, true));
 
        image->read_from_socket (socket);
 
-       shared_ptr<Subtitle> sub;
-       if (subtitle_size.width && subtitle_size.height) {
-               shared_ptr<Image> subtitle_image (new SimpleImage (PIX_FMT_RGBA, subtitle_size, true));
-               subtitle_image->read_from_socket (socket);
-               sub.reset (new Subtitle (subtitle_position, subtitle_image));
-       }
-
        DCPVideoFrame dcp_video_frame (
-               image, sub, out_size, padding, subtitle_offset, subtitle_scale,
-               scaler, frame, frames_per_second, colour_lut_index, j2k_bandwidth, _log
+               image, frame, frames_per_second, colour_lut_index, j2k_bandwidth, _log
                );
        
        shared_ptr<EncodedData> encoded = dcp_video_frame.encode_locally ();
index f9a305367ff20a57d33fe788084e54cded401fdf..ce02fa57e7d302c0b7fc392a98f366bb38b639d9 100644 (file)
 #include <iomanip>
 #include "transcode_job.h"
 #include "film.h"
-#include "format.h"
 #include "transcoder.h"
 #include "log.h"
-#include "encoder.h"
 
 #include "i18n.h"
 
index e1bc560c613e9fc21267435255d5b93e7edb89ef..71a21105b6ec2f6e9eb38096fbbf0ce36bb2dcba 100644 (file)
@@ -56,12 +56,11 @@ extern "C" {
 #include "util.h"
 #include "exceptions.h"
 #include "scaler.h"
-#include "format.h"
 #include "dcp_content_type.h"
 #include "filter.h"
 #include "sound_processor.h"
 #include "config.h"
-#include "container.h"
+#include "ratio.h"
 #ifdef DVDOMATIC_WINDOWS
 #include "stack.hpp"
 #endif
@@ -285,8 +284,7 @@ dcpomatic_setup ()
        
        avfilter_register_all ();
        
-       Format::setup_formats ();
-       Container::setup_containers ();
+       Ratio::setup_ratios ();
        DCPContentType::setup_dcp_content_types ();
        Scaler::setup_scalers ();
        Filter::setup_filters ();
index ae799dad383f0de8a90411d3b288b5393c60e667..18a128a5d120687a9e166567267b845bfd6d8af8 100644 (file)
 #include <libcxml/cxml.h>
 #include "video_content.h"
 #include "video_decoder.h"
+#include "ratio.h"
 
 #include "i18n.h"
 
-int const VideoContentProperty::VIDEO_SIZE = 0;
+int const VideoContentProperty::VIDEO_SIZE      = 0;
 int const VideoContentProperty::VIDEO_FRAME_RATE = 1;
-int const VideoContentProperty::VIDEO_CROP = 2;
+int const VideoContentProperty::VIDEO_CROP      = 2;
+int const VideoContentProperty::VIDEO_RATIO     = 3;
 
 using std::string;
 using std::stringstream;
 using std::setprecision;
 using boost::shared_ptr;
 using boost::lexical_cast;
+using boost::optional;
 
 VideoContent::VideoContent (shared_ptr<const Film> f, Time s, ContentVideoFrame len)
        : Content (f, s)
        , _video_length (len)
+       , _ratio (0)
 {
 
 }
@@ -43,6 +47,7 @@ VideoContent::VideoContent (shared_ptr<const Film> f, Time s, ContentVideoFrame
 VideoContent::VideoContent (shared_ptr<const Film> f, boost::filesystem::path p)
        : Content (f, p)
        , _video_length (0)
+       , _ratio (0)
 {
 
 }
@@ -58,6 +63,10 @@ VideoContent::VideoContent (shared_ptr<const Film> f, shared_ptr<const cxml::Nod
        _crop.right = node->number_child<int> ("RightCrop");
        _crop.top = node->number_child<int> ("TopCrop");
        _crop.bottom = node->number_child<int> ("BottomCrop");
+       optional<string> r = node->optional_string_child ("Ratio");
+       if (r) {
+               _ratio = Ratio::from_id (r.get ());
+       }
 }
 
 VideoContent::VideoContent (VideoContent const & o)
@@ -65,6 +74,7 @@ VideoContent::VideoContent (VideoContent const & o)
        , _video_length (o._video_length)
        , _video_size (o._video_size)
        , _video_frame_rate (o._video_frame_rate)
+       , _ratio (o._ratio)
 {
 
 }
@@ -81,6 +91,9 @@ VideoContent::as_xml (xmlpp::Node* node) const
        node->add_child("RightCrop")->add_child_text (boost::lexical_cast<string> (_crop.right));
        node->add_child("TopCrop")->add_child_text (boost::lexical_cast<string> (_crop.top));
        node->add_child("BottomCrop")->add_child_text (boost::lexical_cast<string> (_crop.bottom));
+       if (_ratio) {
+               node->add_child("Ratio")->add_child_text (_ratio->id ());
+       }
 }
 
 void
@@ -191,3 +204,17 @@ VideoContent::set_bottom_crop (int c)
        signal_changed (VideoContentProperty::VIDEO_CROP);
 }
 
+void
+VideoContent::set_ratio (Ratio const * r)
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               if (_ratio == r) {
+                       return;
+               }
+
+               _ratio = r;
+       }
+
+       signal_changed (VideoContentProperty::VIDEO_RATIO);
+}
index ce2550d12d8f2ca4059d3f5860402482d1e1c65e..44f1c28472c08cc1885a4c021a723b9a6a31bc2b 100644 (file)
@@ -24,6 +24,7 @@
 #include "util.h"
 
 class VideoDecoder;
+class Ratio;
 
 class VideoContentProperty
 {
@@ -31,6 +32,7 @@ public:
        static int const VIDEO_SIZE;
        static int const VIDEO_FRAME_RATE;
        static int const VIDEO_CROP;
+       static int const VIDEO_RATIO;
 };
 
 class VideoContent : public virtual Content
@@ -70,6 +72,13 @@ public:
                return _crop;
        }
 
+       void set_ratio (Ratio const *);
+
+       Ratio const * ratio () const {
+               boost::mutex::scoped_lock lm (_mutex);
+               return _ratio;
+       }
+
 protected:
        void take_from_video_decoder (boost::shared_ptr<VideoDecoder>);
 
@@ -79,6 +88,7 @@ private:
        libdcp::Size _video_size;
        float _video_frame_rate;
        Crop _crop;
+       Ratio const * _ratio;
 };
 
 #endif
index 609594e7652c88d278a2c8df3f618961d85bf16d..cba21d280aae20a51fff025cb470fde6d3f5cb10 100644 (file)
@@ -1,5 +1,3 @@
-/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
-
 /*
     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
 
@@ -23,6 +21,7 @@
 #include "subtitle.h"
 #include "film.h"
 #include "image.h"
+#include "ratio.h"
 
 #include "i18n.h"
 
@@ -52,18 +51,45 @@ VideoDecoder::video (shared_ptr<Image> image, bool same, Time t)
                return;
        }
 
+       image->crop (_video_content->crop(), true);
+
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
+       libdcp::Size const container_size = film->container()->size (film->full_frame ());
+       libdcp::Size const image_size = _video_content->ratio()->size (container_size);
+       
+       shared_ptr<Image> out = image->scale_and_convert_to_rgb (image_size, film->scaler(), true);
+
        shared_ptr<Subtitle> sub;
        if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
                sub = _timed_subtitle->subtitle ();
        }
 
-       Video (image, same, sub, t);
+       if (sub) {
+               Rect const tx = subtitle_transformed_area (
+                       float (image_size.width) / video_size().width,
+                       float (image_size.height) / video_size().height,
+                       sub->area(), film->subtitle_offset(), film->subtitle_scale()
+                       );
 
-       shared_ptr<const Film> film = _film.lock ();
-       assert (film);
+               shared_ptr<Image> im = sub->image()->scale (tx.size(), film->scaler(), true);
+               out->alpha_blend (im, tx.position());
+       }
+
+       if (image_size != container_size) {
+               assert (image_size.width <= container_size.width);
+               assert (image_size.height <= container_size.height);
+               shared_ptr<Image> im (new SimpleImage (PIX_FMT_RGB24, container_size, true));
+               im->make_black ();
+               im->copy (out, Position ((container_size.width - image_size.width) / 2, (container_size.height - image_size.height) / 2));
+               out = im;
+       }
+               
+       Video (out, same, t);
 
        if (_frame_rate_conversion.repeat) {
-               Video (image, true, sub, t + film->video_frames_to_time (1));
+               Video (image, true, t + film->video_frames_to_time (1));
                _next_video = t + film->video_frames_to_time (2);
        } else {
                _next_video = t + film->video_frames_to_time (1);
index 2da42528c22ff93ee3d1ea59f9e9356cb46036c0..957aeb4b4e8fd3cc3339ed5b3d37268ee9273b37 100644 (file)
@@ -32,9 +32,8 @@ public:
        /** Call with a frame of video.
         *  @param i Video frame image.
         *  @param same true if i is the same as last time we were called.
-        *  @param s A subtitle that should be on this frame, or 0.
         */
-       virtual void process_video (boost::shared_ptr<const Image> i, bool same, boost::shared_ptr<Subtitle> s, Time) = 0;
+       virtual void process_video (boost::shared_ptr<const Image> i, bool same, Time) = 0;
 };
 
 #endif
index 39043c8601ff35a141b5903013405bf3e7da91d7..824587bcbc0e33c0009a854dd22c2abb062d4357 100644 (file)
@@ -25,11 +25,11 @@ using boost::weak_ptr;
 using boost::bind;
 
 static void
-process_video_proxy (weak_ptr<VideoSink> sink, shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time time)
+process_video_proxy (weak_ptr<VideoSink> sink, shared_ptr<const Image> image, bool same, Time time)
 {
        shared_ptr<VideoSink> p = sink.lock ();
        if (p) {
-               p->process_video (image, same, sub, time);
+               p->process_video (image, same, time);
        }
 }
 
@@ -39,6 +39,6 @@ VideoSource::connect_video (shared_ptr<VideoSink> s)
        /* If we bind, say, a Player (as the VideoSink) to a Decoder (which is owned
           by the Player) we create a cycle.  Use a weak_ptr to break it.
        */
-       Video.connect (bind (process_video_proxy, weak_ptr<VideoSink> (s), _1, _2, _3, _4));
+       Video.connect (bind (process_video_proxy, weak_ptr<VideoSink> (s), _1, _2, _3));
 }
 
index c94b5a20a5ccdfe9ef720c276428b5b43880e522..9242af444c381467307039889af142d0e7086efd 100644 (file)
@@ -42,10 +42,9 @@ public:
        /** Emitted when a video frame is ready.
         *  First parameter is the video image.
         *  Second parameter is true if the image is the same as the last one that was emitted.
-        *  Third parameter is either 0 or a subtitle that should be on this frame.
-        *  Fourth parameter is the time relative to the start of this source's content.
+        *  Third parameter is the time relative to the start of this source's content.
         */
-       boost::signals2::signal<void (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time)> Video;
+       boost::signals2::signal<void (boost::shared_ptr<const Image>, bool, Time)> Video;
 
        void connect_video (boost::shared_ptr<VideoSink>);
 };
index 22aacb64033fcda2dbabdf80acd808179fe519f8..e9f7ab582a8ed95b489859288e46f7cb11d63478 100644 (file)
@@ -27,7 +27,7 @@
 #include "writer.h"
 #include "compose.hpp"
 #include "film.h"
-#include "container.h"
+#include "ratio.h"
 #include "log.h"
 #include "dcp_video_frame.h"
 #include "dcp_content_type.h"
@@ -133,6 +133,7 @@ Writer::fake_write (int frame)
 void
 Writer::write (shared_ptr<const AudioBuffers> audio)
 {
+       cout << "W: audio " << audio->frames() << "\n";
        _sound_asset_writer->write (audio->data(), audio->frames());
 }
 
index 54941df420aac8bc445f4805372711acf94a8dfe..6e69b98b25304c97b8f08df1be79170dce83d737 100644 (file)
@@ -14,7 +14,6 @@ sources = """
           black_decoder.cc
           config.cc
           combiner.cc
-          container.cc
           content.cc
           cross.cc
           dci_metadata.cc
@@ -30,7 +29,6 @@ sources = """
           ffmpeg_decoder.cc
           film.cc
           filter.cc
-          format.cc
           image.cc
           imagemagick_content.cc
           imagemagick_decoder.cc
@@ -41,6 +39,7 @@ sources = """
           null_content.cc
           player.cc
           playlist.cc
+          ratio.cc
           scp_dcp_job.cc
           scaler.cc
           server.cc
index 196045a9b94642fb4005ce010f93b158142bcc7e..8d3de53ffd5d884d476584beaba78c75119fcda0 100644 (file)
 #include "wx/properties_dialog.h"
 #include "wx/wx_ui_signaller.h"
 #include "lib/film.h"
-#include "lib/format.h"
 #include "lib/config.h"
-#include "lib/filter.h"
 #include "lib/util.h"
-#include "lib/scaler.h"
-#include "lib/exceptions.h"
 #include "lib/version.h"
 #include "lib/ui_signaller.h"
 #include "lib/log.h"
index c295a011d76110f6396989e112220d53e7d54f40..c7b7e3b3d9d8b17ebb852277c1f1f1624428ad3c 100644 (file)
@@ -21,7 +21,6 @@
 #include <iomanip>
 #include <getopt.h>
 #include <libdcp/version.h>
-#include "format.h"
 #include "film.h"
 #include "filter.h"
 #include "transcode_job.h"
index ae5bed723253e86aed4c666d1c924a0ec60694d1..3efd7857a667355c888832c1430ff70b6e34b9f1 100644 (file)
@@ -28,7 +28,7 @@
 #include <wx/notebook.h>
 #include "lib/config.h"
 #include "lib/server.h"
-#include "lib/container.h"
+#include "lib/ratio.h"
 #include "lib/scaler.h"
 #include "lib/filter.h"
 #include "lib/dcp_content_type.h"
@@ -171,10 +171,10 @@ ConfigDialog::make_misc_panel ()
 
        _default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this);
 
-       vector<Container const *> fmt = Container::all ();
+       vector<Ratio const *> ratio = Ratio::all ();
        int n = 0;
-       for (vector<Container const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) {
-               _default_container->Append (std_to_wx ((*i)->name ()));
+       for (vector<Ratio const *>::iterator i = ratio.begin(); i != ratio.end(); ++i) {
+               _default_container->Append (std_to_wx ((*i)->nickname ()));
                if (*i == config->default_container ()) {
                        _default_container->SetSelection (n);
                }
@@ -535,8 +535,8 @@ ConfigDialog::default_still_length_changed (wxCommandEvent &)
 void
 ConfigDialog::default_container_changed (wxCommandEvent &)
 {
-       vector<Container const *> fmt = Container::all ();
-       Config::instance()->set_default_container (fmt[_default_container->GetSelection()]);
+       vector<Ratio const *> ratio = Ratio::all ();
+       Config::instance()->set_default_container (ratio[_default_container->GetSelection()]);
 }
 
 void
index 75867d1d57839c84afac3eed713e31367b1a8965..bddce18beaaf699000f5c412100648e110f88589 100644 (file)
 #include <boost/thread.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/lexical_cast.hpp>
-#include "lib/format.h"
 #include "lib/film.h"
 #include "lib/transcode_job.h"
 #include "lib/exceptions.h"
 #include "lib/ab_transcode_job.h"
 #include "lib/job_manager.h"
 #include "lib/filter.h"
+#include "lib/ratio.h"
 #include "lib/config.h"
-#include "lib/ffmpeg_decoder.h"
 #include "lib/imagemagick_content.h"
 #include "lib/sndfile_content.h"
 #include "lib/dcp_content_type.h"
@@ -52,7 +51,6 @@
 #include "imagemagick_content_dialog.h"
 #include "timeline_dialog.h"
 #include "audio_mapping_view.h"
-#include "container.h"
 #include "timecode.h"
 
 using std::string;
@@ -86,7 +84,7 @@ FilmEditor::FilmEditor (shared_ptr<Film> f, wxWindow* parent)
        make_dcp_panel ();
        _main_notebook->AddPage (_dcp_panel, _("DCP"), false);
        
-       setup_formats ();
+       setup_ratios ();
 
        set_film (f);
        connect_to_widgets ();
@@ -167,9 +165,9 @@ FilmEditor::make_dcp_panel ()
                _scaler->Append (std_to_wx ((*i)->name()));
        }
 
-       vector<Container const *> const co = Container::all ();
-       for (vector<Container const *>::const_iterator i = co.begin(); i != co.end(); ++i) {
-               _container->Append (std_to_wx ((*i)->name ()));
+       vector<Ratio const *> const ratio = Ratio::all ();
+       for (vector<Ratio const *>::const_iterator i = ratio.begin(); i != ratio.end(); ++i) {
+               _container->Append (std_to_wx ((*i)->nickname ()));
        }
 
        vector<DCPContentType const *> const ct = DCPContentType::all ();
@@ -259,8 +257,8 @@ FilmEditor::make_video_panel ()
        ++r;
 
        add_label_to_grid_bag_sizer (grid, _video_panel, _("Scale to"), wxGBPosition (r, 0));
-       _format = new wxChoice (_video_panel, wxID_ANY);
-       grid->Add (_format, wxGBPosition (r, 1));
+       _ratio = new wxChoice (_video_panel, wxID_ANY);
+       grid->Add (_ratio, wxGBPosition (r, 1));
        ++r;
 
        _scaling_description = new wxStaticText (_video_panel, wxID_ANY, wxT ("\n \n \n \n"), wxDefaultPosition, wxDefaultSize);
@@ -598,8 +596,8 @@ FilmEditor::film_changed (Film::Property p)
                break;
        case Film::CONTENT:
                setup_content ();
-               setup_formats ();
-//             setup_format ();
+               setup_ratios ();
+//             setup_ratio ();
                setup_subtitle_control_sensitivity ();
                setup_show_audio_sensitivity ();
                break;
@@ -765,14 +763,14 @@ void
 FilmEditor::setup_container ()
 {
        int n = 0;
-       vector<Container const *> containers = Container::all ();
-       vector<Container const *>::iterator i = containers.begin ();
-       while (i != containers.end() && *i != _film->container ()) {
+       vector<Ratio const *> ratios = Ratio::all ();
+       vector<Ratio const *>::iterator i = ratios.begin ();
+       while (i != ratios.end() && *i != _film->container ()) {
                ++i;
                ++n;
        }
        
-       if (i == containers.end()) {
+       if (i == ratios.end()) {
                checked_set (_container, -1);
        } else {
                checked_set (_container, n);
@@ -792,9 +790,9 @@ FilmEditor::container_changed (wxCommandEvent &)
 
        int const n = _container->GetSelection ();
        if (n >= 0) {
-               vector<Container const *> containers = Container::all ();
-               assert (n < int (containers.size()));
-               _film->set_container (containers[n]);
+               vector<Ratio const *> ratios = Ratio::all ();
+               assert (n < int (ratios.size()));
+               _film->set_container (ratios[n]);
        }
 }
 
@@ -878,7 +876,7 @@ FilmEditor::set_things_sensitive (bool s)
        _name->Enable (s);
        _use_dci_name->Enable (s);
        _edit_dci_button->Enable (s);
-       _format->Enable (s);
+       _ratio->Enable (s);
        _content->Enable (s);
        _left_crop->Enable (s);
        _right_crop->Enable (s);
@@ -999,13 +997,13 @@ FilmEditor::audio_gain_calculate_button_clicked (wxCommandEvent &)
 }
 
 void
-FilmEditor::setup_formats ()
+FilmEditor::setup_ratios ()
 {
-       _formats = Format::all ();
+       _ratios = Ratio::all ();
 
-       _format->Clear ();
-       for (vector<Format const *>::iterator i = _formats.begin(); i != _formats.end(); ++i) {
-               _format->Append (std_to_wx ((*i)->name ()));
+       _ratio->Clear ();
+       for (vector<Ratio const *>::iterator i = _ratios.begin(); i != _ratios.end(); ++i) {
+               _ratio->Append (std_to_wx ((*i)->nickname ()));
        }
 
        _dcp_sizer->Layout ();
index c34cd73e005804dad78abfe21916ff55e9ec0354..be1bf7c361da04ba878de17e5de99eac8c5d687b 100644 (file)
@@ -35,7 +35,7 @@ class Film;
 class AudioDialog;
 class TimelineDialog;
 class AudioMappingView;
-class Format;
+class Ratio;
 class Timecode;
 
 /** @class FilmEditor
@@ -102,7 +102,7 @@ private:
        void film_content_changed (boost::weak_ptr<Content>, int);
 
        void set_things_sensitive (bool);
-       void setup_formats ();
+       void setup_ratios ();
        void setup_subtitle_control_sensitivity ();
        void setup_dcp_name ();
        void setup_show_audio_sensitivity ();
@@ -144,8 +144,8 @@ private:
        wxCheckBox* _loop_content;
        wxSpinCtrl* _loop_count;
        wxButton* _edit_dci_button;
-       wxChoice* _format;
-       wxStaticText* _format_description;
+       wxChoice* _ratio;
+       wxStaticText* _ratio_description;
        wxStaticText* _scaling_description;
        wxSpinCtrl* _left_crop;
        wxSpinCtrl* _right_crop;
@@ -173,7 +173,7 @@ private:
        Timecode* _start;
        Timecode* _length;
 
-       std::vector<Format const *> _formats;
+       std::vector<Ratio const *> _ratios;
 
        bool _generally_sensitive;
        AudioDialog* _audio_dialog;
index 97185ca94ba5b5cfc117926324b29c7f1a4583eb..26f99db116b83036e14d40fedd90d1ceb63d5aa9 100644 (file)
 #include <iomanip>
 #include <wx/tglbtn.h>
 #include "lib/film.h"
-#include "lib/container.h"
-#include "lib/format.h"
+#include "lib/ratio.h"
 #include "lib/util.h"
 #include "lib/job_manager.h"
-#include "lib/subtitle.h"
 #include "lib/image.h"
 #include "lib/scaler.h"
 #include "lib/exceptions.h"
@@ -166,7 +164,7 @@ FilmViewer::set_film (shared_ptr<Film> f)
           on and off without needing obtain a new Player.
        */
        
-       _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3, _4));
+       _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3));
        
        _film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
        _film->ContentChanged.connect (boost::bind (&FilmViewer::film_content_changed, this, _1, _2));
@@ -233,12 +231,6 @@ FilmViewer::paint_panel (wxPaintEvent &)
        wxBitmap frame_bitmap (frame);
        dc.DrawBitmap (frame_bitmap, _display_frame_x, 0);
 
-       if (_film->with_subtitles() && _display_sub) {
-               wxImage sub (_display_sub->size().width, _display_sub->size().height, _display_sub->data()[0], _display_sub->alpha(), true);
-               wxBitmap sub_bitmap (sub);
-               dc.DrawBitmap (sub_bitmap, _display_sub_position.x, _display_sub_position.y);
-       }
-
        if (_out_size.width < _panel_size.width) {
                wxPen p (GetBackgroundColour ());
                wxBrush b (GetBackgroundColour ());
@@ -301,29 +293,7 @@ FilmViewer::raw_to_display ()
        }
 
        /* Get a compacted image as we have to feed it to wxWidgets */
-       _display_frame = _raw_frame->scale_and_convert_to_rgb (_film_size, 0, _film->scaler(), false);
-
-       if (_raw_sub) {
-
-               /* Our output is already cropped by the decoder, so we need to account for that
-                  when working out the scale that we are applying.
-               */
-
-               /* XXX */
-               Size const cropped_size = _raw_frame->size ();//_film->cropped_size (_raw_frame->size ());
-
-               Rect tx = subtitle_transformed_area (
-                       float (_film_size.width) / cropped_size.width,
-                       float (_film_size.height) / cropped_size.height,
-                       _raw_sub->area(), _film->subtitle_offset(), _film->subtitle_scale()
-                       );
-               
-               _display_sub.reset (new RGBPlusAlphaImage (_raw_sub->image()->scale (tx.size(), _film->scaler(), false)));
-               _display_sub_position = tx.position();
-               _display_sub_position.x += _display_frame_x;
-       } else {
-               _display_sub.reset ();
-       }
+       _display_frame = _raw_frame->scale_and_convert_to_rgb (_film_size, _film->scaler(), false);
 }      
 
 void
@@ -333,7 +303,7 @@ FilmViewer::calculate_sizes ()
                return;
        }
 
-       Container const * container = _film->container ();
+       Ratio const * container = _film->container ();
        
        float const panel_ratio = static_cast<float> (_panel_size.width) / _panel_size.height;
        float const film_ratio = container ? container->ratio () : 1.78;
@@ -386,10 +356,9 @@ FilmViewer::check_play_state ()
 }
 
 void
-FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, Time t)
+FilmViewer::process_video (shared_ptr<const Image> image, bool, Time t)
 {
        _raw_frame = image;
-       _raw_sub = sub;
 
        raw_to_display ();
 
index 68d51bfbded2accec2137ad088f2d173267f59e1..39755ed35e57958cc6d38c53a463c1c7ab576586 100644 (file)
@@ -28,7 +28,6 @@ class wxToggleButton;
 class FFmpegPlayer;
 class Image;
 class RGBPlusAlphaImage;
-class Subtitle;
 
 /** @class FilmViewer
  *  @brief A wx widget to view a preview of a Film.
@@ -38,14 +37,12 @@ class Subtitle;
  *  1.  get_frame() asks our _player to decode some data.  If it does, process_video()
  *      will be called.
  *
- *  2.  process_video() takes the image and subtitle from the decoder (_raw_frame and _raw_sub)
- *      and calls raw_to_display().
+ *  2.  process_video() takes the image from the decoder (_raw_frame) and calls raw_to_display().
  * 
  *  3.  raw_to_display() copies _raw_frame to _display_frame, processing it and scaling it.
  *
  *  4.  calling _panel->Refresh() and _panel->Update() results in paint_panel() being called;
- *      this creates frame_bitmap from _display_frame and blits it to the display.  It also
- *      blits the subtitle, if required.
+ *      this creates frame_bitmap from _display_frame and blits it to the display.
  *
  * update_from_decoder() asks the player to re-emit its current frame on the next pass(), and then
  * starts from step #1.
@@ -67,7 +64,7 @@ private:
        void slider_moved (wxScrollEvent &);
        void play_clicked (wxCommandEvent &);
        void timer (wxTimerEvent &);
-       void process_video (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time);
+       void process_video (boost::shared_ptr<const Image>, bool, Time);
        void calculate_sizes ();
        void check_play_state ();
        void update_from_raw ();
@@ -92,14 +89,11 @@ private:
        wxTimer _timer;
 
        boost::shared_ptr<const Image> _raw_frame;
-       boost::shared_ptr<Subtitle> _raw_sub;
        boost::shared_ptr<const Image> _display_frame;
        /* The x offset at which we display the actual film content; this corresponds
           to the film's padding converted to our coordinates.
        */
        int _display_frame_x;
-       boost::shared_ptr<RGBPlusAlphaImage> _display_sub;
-       Position _display_sub_position;
        bool _got_frame;
 
        /** Size of our output (including padding if we have any) */
index 9c4482d3c0957fcdb001ec6327cccf6d1eb964a7..51b52331af8c84c938132f29d86ebef06cab4d6b 100644 (file)
@@ -63,12 +63,6 @@ BOOST_AUTO_TEST_CASE (client_server_test)
        shared_ptr<DCPVideoFrame> frame (
                new DCPVideoFrame (
                        image,
-                       subtitle,
-                       libdcp::Size (1998, 1080),
-                       0,
-                       0,
-                       1,
-                       Scaler::from_id ("bicubic"),
                        0,
                        24,
                        0,
diff --git a/test/container_test.cc b/test/container_test.cc
deleted file mode 100644 (file)
index 825a8cd..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-    Copyright (C) 2012 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.
-
-*/
-
-using std::ostream;
-
-namespace libdcp {
-       
-ostream&
-operator<< (ostream& s, libdcp::Size const & t)
-{
-       s << t.width << "x" << t.height;
-       return s;
-}
-
-}
-
-BOOST_AUTO_TEST_CASE (container_test)
-{
-       Container::setup_containers ();
-
-       Container const * c = Container::from_id ("119");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1285, 1080));
-
-       c = Container::from_id ("133");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1436, 1080));
-
-       c = Container::from_id ("137");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1480, 1080));
-
-       c = Container::from_id ("138");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1485, 1080));
-
-       c = Container::from_id ("166");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1793, 1080));
-
-       c = Container::from_id ("178");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1920, 1080));
-
-       c = Container::from_id ("185");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1998, 1080));
-
-       c = Container::from_id ("239");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 858));
-
-       c = Container::from_id ("full-frame");
-       BOOST_CHECK (c);
-       BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 1080));
-}
-
index 795b4dfe3d0078cac76d2f9870764f50457815ff..cf31d674e96831955a63744b923bd9e3edd6562c 100644 (file)
@@ -29,7 +29,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_test)
                dcpomatic_sleep (1);
        }
        
-       film->set_container (Container::from_id ("185"));
+       film->set_container (Ratio::from_id ("185"));
        film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
        film->make_dcp ();
        film->write_metadata ();
index 315461b2285c5f36a3a427ae87ce860ba009709f..397b9e43a5af3de6852debcb5894e42d501a85d1 100644 (file)
@@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE (film_metadata_test)
 
        f->set_name ("fred");
        f->set_dcp_content_type (DCPContentType::from_pretty_name ("Short"));
-       f->set_container (Container::from_id ("185"));
+       f->set_container (Ratio::from_id ("185"));
        f->set_ab (true);
        f->write_metadata ();
 
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE (film_metadata_test)
 
        BOOST_CHECK_EQUAL (g->name(), "fred");
        BOOST_CHECK_EQUAL (g->dcp_content_type(), DCPContentType::from_pretty_name ("Short"));
-       BOOST_CHECK_EQUAL (g->container(), Container::from_id ("185"));
+       BOOST_CHECK_EQUAL (g->container(), Ratio::from_id ("185"));
        BOOST_CHECK_EQUAL (g->ab(), true);
        
        g->write_metadata ();
diff --git a/test/format_test.cc b/test/format_test.cc
deleted file mode 100644 (file)
index 71bc003..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-    Copyright (C) 2012 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.
-
-*/
-
-BOOST_AUTO_TEST_CASE (format_test)
-{
-       Format::setup_formats ();
-       
-       Format const * f = Format::from_nickname ("Flat");
-       BOOST_CHECK (f);
-       BOOST_CHECK_EQUAL (f->dcp_size().width, 1998);
-       BOOST_CHECK_EQUAL (f->dcp_size().height, 1080);
-       
-       f = Format::from_nickname ("Scope");
-       BOOST_CHECK (f);
-       BOOST_CHECK_EQUAL (f->dcp_size().width, 2048);
-       BOOST_CHECK_EQUAL (f->dcp_size().height, 858);
-}
index 3c0b979ffff675d02b8f9d461b1e9d7810067572..c708709150405abd62027b63b2919c48f5037a77 100644 (file)
@@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE (make_black_test)
        for (list<AVPixelFormat>::const_iterator i = pix_fmts.begin(); i != pix_fmts.end(); ++i) {
                boost::shared_ptr<Image> foo (new SimpleImage (*i, in_size, true));
                foo->make_black ();
-               boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, 0, Scaler::from_id ("bicubic"), true);
+               boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, Scaler::from_id ("bicubic"), true);
                
                uint8_t* p = bar->data()[0];
                for (int y = 0; y < bar->size().height; ++y) {
diff --git a/test/ratio_test.cc b/test/ratio_test.cc
new file mode 100644 (file)
index 0000000..6311976
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+    Copyright (C) 2012 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.
+
+*/
+
+using std::ostream;
+
+namespace libdcp {
+       
+ostream&
+operator<< (ostream& s, libdcp::Size const & t)
+{
+       s << t.width << "x" << t.height;
+       return s;
+}
+
+}
+
+BOOST_AUTO_TEST_CASE (ratio_test)
+{
+       Ratio::setup_ratios ();
+
+       Ratio const * r = Ratio::from_id ("119");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1285, 1080));
+
+       r = Ratio::from_id ("133");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1436, 1080));
+
+       r = Ratio::from_id ("137");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1480, 1080));
+
+       r = Ratio::from_id ("138");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1485, 1080));
+
+       r = Ratio::from_id ("166");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1793, 1080));
+
+       r = Ratio::from_id ("178");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1920, 1080));
+
+       r = Ratio::from_id ("185");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1998, 1080));
+
+       r = Ratio::from_id ("239");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 858));
+
+       r = Ratio::from_id ("full-frame");
+       BOOST_CHECK (r);
+       BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 1080));
+}
+
index 60009f10b8151d4ff73340b782198885dde3afa3..dba611043793d1c53713929bd008133ec35346bd 100644 (file)
 
 */
 
+#include "imagemagick_content.h"
+
 /** @file test/scaling_test.cc
  *  @brief Test scaling and black-padding of images from a still-image source.
  */
 
 using boost::shared_ptr;
 
+static void scaling_test_for (shared_ptr<Film> film, shared_ptr<VideoContent> content, string image, string container)
+{
+       content->set_ratio (Ratio::from_id (image));
+       film->set_container (Ratio::from_id (container));
+       film->make_dcp ();
+
+       while (JobManager::instance()->work_to_do ());
+
+       BOOST_CHECK (!JobManager::instance()->errors());
+
+       boost::filesystem::path ref;
+       ref = "test";
+       ref /= "data";
+       ref /= "scaling_test_" + image + "_" + container;
+
+       boost::filesystem::path check;
+       check = "build";
+       check /= "test";
+       check /= "scaling_test";
+       check /= film->dcp_name();
+
+       check_dcp (ref.string(), check.string());
+}
+
 BOOST_AUTO_TEST_CASE (scaling_test)
 {
        shared_ptr<Film> film = new_test_film ("scaling_test");
-       film->examine_and_add_content (shared_ptr<Content> (new ImageMagickContent ("test/data/simple_testcard_640x480.png")));
+       film->set_dcp_content_type (DCPContentType::from_dci_name ("FTR"));
+       film->set_name ("scaling_test");
+       shared_ptr<ImageMagickContent> imc (new ImageMagickContent (film, "test/data/simple_testcard_640x480.png"));
+
+       film->examine_and_add_content (imc);
+       while (JobManager::instance()->work_to_do ());
        
+       imc->set_video_length (1);
+
+       scaling_test_for (film, imc, "133", "185");
+       scaling_test_for (film, imc, "185", "185");
+       scaling_test_for (film, imc, "239", "185");
+
+       scaling_test_for (film, imc, "133", "239");
+       scaling_test_for (film, imc, "185", "239");
+       scaling_test_for (film, imc, "239", "239");
 }
+
index 7d49bb66ad813ead4f1311a07d972fec2becdfb1..2837729c581ca83895d9acd103b37691d47a2095 100644 (file)
@@ -22,7 +22,8 @@
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/date_time.hpp>
-#include "format.h"
+#include <libdcp/dcp.h>
+#include "ratio.h"
 #include "film.h"
 #include "filter.h"
 #include "job_manager.h"
@@ -40,7 +41,6 @@
 #include "ffmpeg_decoder.h"
 #include "sndfile_decoder.h"
 #include "dcp_content_type.h"
-#include "container.h"
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MODULE dcpomatic_test
 #include <boost/test/unit_test.hpp>
@@ -49,6 +49,8 @@ using std::string;
 using std::list;
 using std::stringstream;
 using std::vector;
+using std::min;
+using std::cout;
 using boost::shared_ptr;
 using boost::thread;
 using boost::dynamic_pointer_cast;
@@ -93,13 +95,67 @@ new_test_film (string name)
        return f;
 }
 
+void
+check_file (string ref, string check)
+{
+       uintmax_t N = boost::filesystem::file_size (ref);
+       BOOST_CHECK_EQUAL (N, boost::filesystem::file_size(check));
+       FILE* ref_file = fopen (ref.c_str(), "rb");
+       BOOST_CHECK (ref_file);
+       FILE* check_file = fopen (check.c_str(), "rb");
+       BOOST_CHECK (check_file);
+       
+       int const buffer_size = 65536;
+       uint8_t* ref_buffer = new uint8_t[buffer_size];
+       uint8_t* check_buffer = new uint8_t[buffer_size];
+
+       while (N) {
+               uintmax_t this_time = min (uintmax_t (buffer_size), N);
+               size_t r = fread (ref_buffer, 1, this_time, ref_file);
+               BOOST_CHECK_EQUAL (r, this_time);
+               r = fread (check_buffer, 1, this_time, check_file);
+               BOOST_CHECK_EQUAL (r, this_time);
+
+               BOOST_CHECK_EQUAL (memcmp (ref_buffer, check_buffer, this_time), 0);
+               N -= this_time;
+       }
+
+       delete[] ref_buffer;
+       delete[] check_buffer;
+
+       fclose (ref_file);
+       fclose (check_file);
+}
+
+static void
+note (libdcp::NoteType, string n)
+{
+       cout << n << "\n";
+}
+
+void
+check_dcp (string ref, string check)
+{
+       libdcp::DCP ref_dcp (ref);
+       ref_dcp.read ();
+       libdcp::DCP check_dcp (check);
+       check_dcp.read ();
+
+       libdcp::EqualityOptions options;
+       options.max_mean_pixel_error = 5;
+       options.max_std_dev_pixel_error = 5;
+       options.max_audio_sample_error = 255;
+       
+       BOOST_CHECK (ref_dcp.equals (check_dcp, options, boost::bind (note, _1, _2)));
+}
+
+
 #include "scaling_test.cc"
-#include "container_test.cc"
+#include "ratio_test.cc"
 #include "pixel_formats_test.cc"
 #include "make_black_test.cc"
 #include "film_metadata_test.cc"
 #include "stream_test.cc"
-#include "format_test.cc"
 #include "util_test.cc"
 #include "dcp_test.cc"
 #include "frame_rate_test.cc"