diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-05-31 14:19:50 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-05-31 14:19:50 +0100 |
| commit | f385ef03e5ea27519a31c0839447735a7fba0602 (patch) | |
| tree | 310902e785a95c2e3be1ba389f29cd7bd480f2a2 /src/lib | |
| parent | c13771610ef9a01cb29342bca82f9999f8b5ddbc (diff) | |
Various stuff; mostly change to decoder scaling and adding subtitle; scaling test.
Diffstat (limited to 'src/lib')
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 |
