summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-05-31 14:19:50 +0100
committerCarl Hetherington <cth@carlh.net>2013-05-31 14:19:50 +0100
commitf385ef03e5ea27519a31c0839447735a7fba0602 (patch)
tree310902e785a95c2e3be1ba389f29cd7bd480f2a2 /src/lib
parentc13771610ef9a01cb29342bca82f9999f8b5ddbc (diff)
Various stuff; mostly change to decoder scaling and adding subtitle; scaling test.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ab_transcode_job.cc3
-rw-r--r--src/lib/ab_transcoder.cc4
-rw-r--r--src/lib/combiner.cc6
-rw-r--r--src/lib/combiner.h4
-rw-r--r--src/lib/config.cc6
-rw-r--r--src/lib/config.h10
-rw-r--r--src/lib/container.cc78
-rw-r--r--src/lib/dcp_video_frame.cc105
-rw-r--r--src/lib/dcp_video_frame.h18
-rw-r--r--src/lib/encoder.cc18
-rw-r--r--src/lib/encoder.h6
-rw-r--r--src/lib/ffmpeg_decoder.cc3
-rw-r--r--src/lib/ffmpeg_decoder.h4
-rw-r--r--src/lib/film.cc6
-rw-r--r--src/lib/film.h7
-rw-r--r--src/lib/format.cc126
-rw-r--r--src/lib/format.h80
-rw-r--r--src/lib/image.cc46
-rw-r--r--src/lib/image.h3
-rw-r--r--src/lib/player.cc23
-rw-r--r--src/lib/player.h3
-rw-r--r--src/lib/ratio.cc71
-rw-r--r--src/lib/ratio.h (renamed from src/lib/container.h)20
-rw-r--r--src/lib/server.cc35
-rw-r--r--src/lib/transcode_job.cc2
-rw-r--r--src/lib/util.cc6
-rw-r--r--src/lib/video_content.cc31
-rw-r--r--src/lib/video_content.h10
-rw-r--r--src/lib/video_decoder.cc38
-rw-r--r--src/lib/video_sink.h3
-rw-r--r--src/lib/video_source.cc6
-rw-r--r--src/lib/video_source.h5
-rw-r--r--src/lib/writer.cc3
-rw-r--r--src/lib/wscript3
34 files changed, 271 insertions, 521 deletions
diff --git a/src/lib/ab_transcode_job.cc b/src/lib/ab_transcode_job.cc
index 9a883fdd9..2d6f99c91 100644
--- a/src/lib/ab_transcode_job.cc
+++ b/src/lib/ab_transcode_job.cc
@@ -20,11 +20,8 @@
#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"
diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc
index 1ec298626..a5659b22f 100644
--- a/src/lib/ab_transcoder.cc
+++ b/src/lib/ab_transcoder.cc
@@ -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);
diff --git a/src/lib/combiner.cc b/src/lib/combiner.cc
index db490fd34..ca68ef68a 100644
--- a/src/lib/combiner.cc
+++ b/src/lib/combiner.cc
@@ -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 ();
}
diff --git a/src/lib/combiner.h b/src/lib/combiner.h
index 1b7537d42..46c90b4d8 100644
--- a/src/lib/combiner.h
+++ b/src/lib/combiner.h
@@ -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 */
diff --git a/src/lib/config.cc b/src/lib/config.cc
index c5245bfb4..978428b02 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -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") {
diff --git a/src/lib/config.h b/src/lib/config.h
index c43a4f079..110bcc6a8 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -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
index d679e4848..000000000
--- a/src/lib/container.cc
+++ /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/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc
index 1c1838df7..2f597522c 100644
--- a/src/lib/dcp_video_frame.cc
+++ b/src/lib/dcp_video_frame.cc
@@ -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());
diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h
index ba49c95a4..f234b445a 100644
--- a/src/lib/dcp_video_frame.h
+++ b/src/lib/dcp_video_frame.h
@@ -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
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 3152669ad..f3745ff98 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -22,24 +22,15 @@
*/
#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()
)
));
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index 6815fa6f6..8f724525c 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -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);
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index a1a6636fb..c148bc530 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -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"
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index c37479612..7b8e1b50c 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -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.
diff --git a/src/lib/film.cc b/src/lib/film.cc
index e76d97b59..ef29d35fd 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -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);
diff --git a/src/lib/film.h b/src/lib/film.h
index 31454c5a7..28beeaed1 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -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
index 87bdda3d1..000000000
--- a/src/lib/format.cc
+++ /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
index 06423d2b1..000000000
--- a/src/lib/format.h
+++ /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;
-};
diff --git a/src/lib/image.cc b/src/lib/image.cc
index b166dfac6..a12c61b3e 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -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;
@@ -377,6 +352,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)
{
for (int i = 0; i < components(); ++i) {
diff --git a/src/lib/image.h b/src/lib/image.h
index 34f87b188..f9bda7460 100644
--- a/src/lib/image.h
+++ b/src/lib/image.h
@@ -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 ();
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 2926796ef..e64e1e011 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -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;
diff --git a/src/lib/player.h b/src/lib/player.h
index cdedf1676..cce2bdc21 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -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
index 000000000..5988b3418
--- /dev/null
+++ b/src/lib/ratio.cc
@@ -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/container.h b/src/lib/ratio.h
index 4bf03a3f1..6916a7491 100644
--- a/src/lib/container.h
+++ b/src/lib/ratio.h
@@ -20,10 +20,10 @@
#include <vector>
#include <libdcp/util.h>
-class Container
+class Ratio
{
public:
- Container (float ratio, std::string id, std::string n, std::string d)
+ Ratio (float ratio, std::string id, std::string n, std::string d)
: _ratio (ratio)
, _id (id)
, _nickname (n)
@@ -36,9 +36,6 @@ public:
return _id;
}
- std::string name () const;
-
- /** @return Nickname (e.g. Flat, Scope) */
std::string nickname () const {
return _nickname;
}
@@ -50,11 +47,11 @@ public:
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;
+
+ static void setup_ratios ();
+ static Ratio const * from_id (std::string i);
+ static std::vector<Ratio const *> all () {
+ return _ratios;
}
private:
@@ -65,6 +62,5 @@ private:
std::string _nickname;
std::string _dci_name;
- /** all available containers */
- static std::vector<Container const *> _containers;
+ static std::vector<Ratio const *> _ratios;
};
diff --git a/src/lib/server.cc b/src/lib/server.cc
index 07b826946..5ca04c692 100644
--- a/src/lib/server.cc
+++ b/src/lib/server.cc
@@ -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 ();
diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc
index f9a305367..ce02fa57e 100644
--- a/src/lib/transcode_job.cc
+++ b/src/lib/transcode_job.cc
@@ -25,10 +25,8 @@
#include <iomanip>
#include "transcode_job.h"
#include "film.h"
-#include "format.h"
#include "transcoder.h"
#include "log.h"
-#include "encoder.h"
#include "i18n.h"
diff --git a/src/lib/util.cc b/src/lib/util.cc
index e1bc560c6..71a21105b 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -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 ();
diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc
index ae799dad3..18a128a5d 100644
--- a/src/lib/video_content.cc
+++ b/src/lib/video_content.cc
@@ -20,22 +20,26 @@
#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);
+}
diff --git a/src/lib/video_content.h b/src/lib/video_content.h
index ce2550d12..44f1c2847 100644
--- a/src/lib/video_content.h
+++ b/src/lib/video_content.h
@@ -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
diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc
index 609594e76..cba21d280 100644
--- a/src/lib/video_decoder.cc
+++ b/src/lib/video_decoder.cc
@@ -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);
diff --git a/src/lib/video_sink.h b/src/lib/video_sink.h
index 2da42528c..957aeb4b4 100644
--- a/src/lib/video_sink.h
+++ b/src/lib/video_sink.h
@@ -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
diff --git a/src/lib/video_source.cc b/src/lib/video_source.cc
index 39043c860..824587bcb 100644
--- a/src/lib/video_source.cc
+++ b/src/lib/video_source.cc
@@ -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));
}
diff --git a/src/lib/video_source.h b/src/lib/video_source.h
index c94b5a20a..9242af444 100644
--- a/src/lib/video_source.h
+++ b/src/lib/video_source.h
@@ -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>);
};
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 22aacb640..e9f7ab582 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -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());
}
diff --git a/src/lib/wscript b/src/lib/wscript
index 54941df42..6e69b98b2 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -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