#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"
, _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);
* @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));
}
* @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 */
}
}
- Video (_image, false, sub, t);
+ Video (_image, false, t);
_image.reset ();
}
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 */
#include "server.h"
#include "scaler.h"
#include "filter.h"
-#include "container.h"
+#include "ratio.h"
#include "dcp_content_type.h"
#include "sound_processor.h"
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");
} 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") {
class Scaler;
class Filter;
class SoundProcessor;
-class Container;
class DCPContentType;
+class Ratio;
/** @class Config
* @brief A singleton class holding configuration.
return _default_still_length;
}
- Container const * default_container () const {
+ Ratio const * default_container () const {
return _default_container;
}
_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) {
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;
+++ /dev/null
-/*
- 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 ();
-}
+++ /dev/null
-/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <vector>
-#include <libdcp/util.h>
-
-class Container
-{
-public:
- Container (float ratio, std::string id, std::string n, std::string d)
- : _ratio (ratio)
- , _id (id)
- , _nickname (n)
- , _dci_name (d)
- {}
-
- libdcp::Size size (libdcp::Size) const;
-
- std::string id () const {
- return _id;
- }
-
- std::string name () const;
-
- /** @return Nickname (e.g. Flat, Scope) */
- std::string nickname () const {
- return _nickname;
- }
-
- std::string dci_name () const {
- return _dci_name;
- }
-
- float ratio () const {
- return _ratio;
- }
-
- static void setup_containers ();
- static Container const * from_id (std::string i);
- static std::vector<Container const *> all () {
- return _containers;
- }
-
-private:
- float _ratio;
- /** id for use in metadata */
- std::string _id;
- /** nickname (e.g. Flat, Scope) */
- std::string _nickname;
- std::string _dci_name;
-
- /** all available containers */
- static std::vector<Container const *> _containers;
-};
#include "scaler.h"
#include "image.h"
#include "log.h"
-#include "subtitle.h"
#include "i18n.h"
/** 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)
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;
_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) {
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 {
/* 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];
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;
}
/* 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);
_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"));
}
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());
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 *);
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
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
*/
#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"
}
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);
/* 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()
)
));
#include "audio_sink.h"
class Image;
-class Subtitle;
class AudioBuffers;
class Film;
class ServerDescription;
/** @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.
*/
/** 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);
}
#include <sndfile.h>
#include "film.h"
-#include "format.h"
-#include "transcoder.h"
-#include "job.h"
#include "filter.h"
#include "exceptions.h"
#include "image.h"
#include "decoder.h"
#include "video_decoder.h"
#include "audio_decoder.h"
-#include "film.h"
-#include "ffmpeg_content.h"
struct AVFilterGraph;
struct AVCodecContext;
class Options;
class Image;
class Log;
+class FFmpegContent;
+class Film;
/** @class FFmpegDecoder
* @brief A decoder using FFmpeg to decode content.
#include <libxml++/libxml++.h>
#include <libcxml/cxml.h>
#include "film.h"
-#include "container.h"
#include "job.h"
#include "filter.h"
#include "util.h"
#include "imagemagick_content.h"
#include "sndfile_content.h"
#include "dcp_content_type.h"
+#include "ratio.h"
#include "i18n.h"
{
optional<string> c = f.optional_string_child ("Container");
if (c) {
- _container = Container::from_id (c.get ());
+ _container = Ratio::from_id (c.get ());
}
}
}
void
-Film::set_container (Container const * c)
+Film::set_container (Ratio const * c)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
#include "playlist.h"
class DCPContentType;
-class Container;
class Job;
class Filter;
class Log;
return _dcp_content_type;
}
- Container const * container () const {
+ Ratio const * container () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _container;
}
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);
/** 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
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-/*
- 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;
-};
* @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
*/
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
);
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;
}
}
+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)
{
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 ();
}
if (!earliest) {
+ flush ();
return true;
}
}
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) {
time += content->start ();
- Video (image, same, sub, time);
+ Video (image, same, time);
}
void
_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)
{
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";
}
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;
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;
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 ();
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;
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <vector>
+#include <libdcp/util.h>
+
+class Ratio
+{
+public:
+ Ratio (float ratio, std::string id, std::string n, std::string d)
+ : _ratio (ratio)
+ , _id (id)
+ , _nickname (n)
+ , _dci_name (d)
+ {}
+
+ libdcp::Size size (libdcp::Size) const;
+
+ std::string id () const {
+ return _id;
+ }
+
+ std::string nickname () const {
+ return _nickname;
+ }
+
+ std::string dci_name () const {
+ return _dci_name;
+ }
+
+ float ratio () const {
+ return _ratio;
+ }
+
+ static void setup_ratios ();
+ static Ratio const * from_id (std::string i);
+ static std::vector<Ratio const *> all () {
+ return _ratios;
+ }
+
+private:
+ float _ratio;
+ /** id for use in metadata */
+ std::string _id;
+ /** nickname (e.g. Flat, Scope) */
+ std::string _nickname;
+ std::string _dci_name;
+
+ static std::vector<Ratio const *> _ratios;
+};
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 ();
#include <iomanip>
#include "transcode_job.h"
#include "film.h"
-#include "format.h"
#include "transcoder.h"
#include "log.h"
-#include "encoder.h"
#include "i18n.h"
#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
avfilter_register_all ();
- Format::setup_formats ();
- Container::setup_containers ();
+ Ratio::setup_ratios ();
DCPContentType::setup_dcp_content_types ();
Scaler::setup_scalers ();
Filter::setup_filters ();
#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)
{
}
VideoContent::VideoContent (shared_ptr<const Film> f, boost::filesystem::path p)
: Content (f, p)
, _video_length (0)
+ , _ratio (0)
{
}
_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)
, _video_length (o._video_length)
, _video_size (o._video_size)
, _video_frame_rate (o._video_frame_rate)
+ , _ratio (o._ratio)
{
}
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
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);
+}
#include "util.h"
class VideoDecoder;
+class Ratio;
class VideoContentProperty
{
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
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>);
libdcp::Size _video_size;
float _video_frame_rate;
Crop _crop;
+ Ratio const * _ratio;
};
#endif
-/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
-
/*
Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
#include "subtitle.h"
#include "film.h"
#include "image.h"
+#include "ratio.h"
#include "i18n.h"
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);
/** 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
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);
}
}
/* 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));
}
/** 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>);
};
#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"
void
Writer::write (shared_ptr<const AudioBuffers> audio)
{
+ cout << "W: audio " << audio->frames() << "\n";
_sound_asset_writer->write (audio->data(), audio->frames());
}
black_decoder.cc
config.cc
combiner.cc
- container.cc
content.cc
cross.cc
dci_metadata.cc
ffmpeg_decoder.cc
film.cc
filter.cc
- format.cc
image.cc
imagemagick_content.cc
imagemagick_decoder.cc
null_content.cc
player.cc
playlist.cc
+ ratio.cc
scp_dcp_job.cc
scaler.cc
server.cc
#include "wx/properties_dialog.h"
#include "wx/wx_ui_signaller.h"
#include "lib/film.h"
-#include "lib/format.h"
#include "lib/config.h"
-#include "lib/filter.h"
#include "lib/util.h"
-#include "lib/scaler.h"
-#include "lib/exceptions.h"
#include "lib/version.h"
#include "lib/ui_signaller.h"
#include "lib/log.h"
#include <iomanip>
#include <getopt.h>
#include <libdcp/version.h>
-#include "format.h"
#include "film.h"
#include "filter.h"
#include "transcode_job.h"
#include <wx/notebook.h>
#include "lib/config.h"
#include "lib/server.h"
-#include "lib/container.h"
+#include "lib/ratio.h"
#include "lib/scaler.h"
#include "lib/filter.h"
#include "lib/dcp_content_type.h"
_default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this);
- vector<Container const *> fmt = Container::all ();
+ vector<Ratio const *> ratio = Ratio::all ();
int n = 0;
- for (vector<Container const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) {
- _default_container->Append (std_to_wx ((*i)->name ()));
+ for (vector<Ratio const *>::iterator i = ratio.begin(); i != ratio.end(); ++i) {
+ _default_container->Append (std_to_wx ((*i)->nickname ()));
if (*i == config->default_container ()) {
_default_container->SetSelection (n);
}
void
ConfigDialog::default_container_changed (wxCommandEvent &)
{
- vector<Container const *> fmt = Container::all ();
- Config::instance()->set_default_container (fmt[_default_container->GetSelection()]);
+ vector<Ratio const *> ratio = Ratio::all ();
+ Config::instance()->set_default_container (ratio[_default_container->GetSelection()]);
}
void
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
-#include "lib/format.h"
#include "lib/film.h"
#include "lib/transcode_job.h"
#include "lib/exceptions.h"
#include "lib/ab_transcode_job.h"
#include "lib/job_manager.h"
#include "lib/filter.h"
+#include "lib/ratio.h"
#include "lib/config.h"
-#include "lib/ffmpeg_decoder.h"
#include "lib/imagemagick_content.h"
#include "lib/sndfile_content.h"
#include "lib/dcp_content_type.h"
#include "imagemagick_content_dialog.h"
#include "timeline_dialog.h"
#include "audio_mapping_view.h"
-#include "container.h"
#include "timecode.h"
using std::string;
make_dcp_panel ();
_main_notebook->AddPage (_dcp_panel, _("DCP"), false);
- setup_formats ();
+ setup_ratios ();
set_film (f);
connect_to_widgets ();
_scaler->Append (std_to_wx ((*i)->name()));
}
- vector<Container const *> const co = Container::all ();
- for (vector<Container const *>::const_iterator i = co.begin(); i != co.end(); ++i) {
- _container->Append (std_to_wx ((*i)->name ()));
+ vector<Ratio const *> const ratio = Ratio::all ();
+ for (vector<Ratio const *>::const_iterator i = ratio.begin(); i != ratio.end(); ++i) {
+ _container->Append (std_to_wx ((*i)->nickname ()));
}
vector<DCPContentType const *> const ct = DCPContentType::all ();
++r;
add_label_to_grid_bag_sizer (grid, _video_panel, _("Scale to"), wxGBPosition (r, 0));
- _format = new wxChoice (_video_panel, wxID_ANY);
- grid->Add (_format, wxGBPosition (r, 1));
+ _ratio = new wxChoice (_video_panel, wxID_ANY);
+ grid->Add (_ratio, wxGBPosition (r, 1));
++r;
_scaling_description = new wxStaticText (_video_panel, wxID_ANY, wxT ("\n \n \n \n"), wxDefaultPosition, wxDefaultSize);
break;
case Film::CONTENT:
setup_content ();
- setup_formats ();
-// setup_format ();
+ setup_ratios ();
+// setup_ratio ();
setup_subtitle_control_sensitivity ();
setup_show_audio_sensitivity ();
break;
FilmEditor::setup_container ()
{
int n = 0;
- vector<Container const *> containers = Container::all ();
- vector<Container const *>::iterator i = containers.begin ();
- while (i != containers.end() && *i != _film->container ()) {
+ vector<Ratio const *> ratios = Ratio::all ();
+ vector<Ratio const *>::iterator i = ratios.begin ();
+ while (i != ratios.end() && *i != _film->container ()) {
++i;
++n;
}
- if (i == containers.end()) {
+ if (i == ratios.end()) {
checked_set (_container, -1);
} else {
checked_set (_container, n);
int const n = _container->GetSelection ();
if (n >= 0) {
- vector<Container const *> containers = Container::all ();
- assert (n < int (containers.size()));
- _film->set_container (containers[n]);
+ vector<Ratio const *> ratios = Ratio::all ();
+ assert (n < int (ratios.size()));
+ _film->set_container (ratios[n]);
}
}
_name->Enable (s);
_use_dci_name->Enable (s);
_edit_dci_button->Enable (s);
- _format->Enable (s);
+ _ratio->Enable (s);
_content->Enable (s);
_left_crop->Enable (s);
_right_crop->Enable (s);
}
void
-FilmEditor::setup_formats ()
+FilmEditor::setup_ratios ()
{
- _formats = Format::all ();
+ _ratios = Ratio::all ();
- _format->Clear ();
- for (vector<Format const *>::iterator i = _formats.begin(); i != _formats.end(); ++i) {
- _format->Append (std_to_wx ((*i)->name ()));
+ _ratio->Clear ();
+ for (vector<Ratio const *>::iterator i = _ratios.begin(); i != _ratios.end(); ++i) {
+ _ratio->Append (std_to_wx ((*i)->nickname ()));
}
_dcp_sizer->Layout ();
class AudioDialog;
class TimelineDialog;
class AudioMappingView;
-class Format;
+class Ratio;
class Timecode;
/** @class FilmEditor
void film_content_changed (boost::weak_ptr<Content>, int);
void set_things_sensitive (bool);
- void setup_formats ();
+ void setup_ratios ();
void setup_subtitle_control_sensitivity ();
void setup_dcp_name ();
void setup_show_audio_sensitivity ();
wxCheckBox* _loop_content;
wxSpinCtrl* _loop_count;
wxButton* _edit_dci_button;
- wxChoice* _format;
- wxStaticText* _format_description;
+ wxChoice* _ratio;
+ wxStaticText* _ratio_description;
wxStaticText* _scaling_description;
wxSpinCtrl* _left_crop;
wxSpinCtrl* _right_crop;
Timecode* _start;
Timecode* _length;
- std::vector<Format const *> _formats;
+ std::vector<Ratio const *> _ratios;
bool _generally_sensitive;
AudioDialog* _audio_dialog;
#include <iomanip>
#include <wx/tglbtn.h>
#include "lib/film.h"
-#include "lib/container.h"
-#include "lib/format.h"
+#include "lib/ratio.h"
#include "lib/util.h"
#include "lib/job_manager.h"
-#include "lib/subtitle.h"
#include "lib/image.h"
#include "lib/scaler.h"
#include "lib/exceptions.h"
on and off without needing obtain a new Player.
*/
- _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3, _4));
+ _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3));
_film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
_film->ContentChanged.connect (boost::bind (&FilmViewer::film_content_changed, this, _1, _2));
wxBitmap frame_bitmap (frame);
dc.DrawBitmap (frame_bitmap, _display_frame_x, 0);
- if (_film->with_subtitles() && _display_sub) {
- wxImage sub (_display_sub->size().width, _display_sub->size().height, _display_sub->data()[0], _display_sub->alpha(), true);
- wxBitmap sub_bitmap (sub);
- dc.DrawBitmap (sub_bitmap, _display_sub_position.x, _display_sub_position.y);
- }
-
if (_out_size.width < _panel_size.width) {
wxPen p (GetBackgroundColour ());
wxBrush b (GetBackgroundColour ());
}
/* Get a compacted image as we have to feed it to wxWidgets */
- _display_frame = _raw_frame->scale_and_convert_to_rgb (_film_size, 0, _film->scaler(), false);
-
- if (_raw_sub) {
-
- /* Our output is already cropped by the decoder, so we need to account for that
- when working out the scale that we are applying.
- */
-
- /* XXX */
- Size const cropped_size = _raw_frame->size ();//_film->cropped_size (_raw_frame->size ());
-
- Rect tx = subtitle_transformed_area (
- float (_film_size.width) / cropped_size.width,
- float (_film_size.height) / cropped_size.height,
- _raw_sub->area(), _film->subtitle_offset(), _film->subtitle_scale()
- );
-
- _display_sub.reset (new RGBPlusAlphaImage (_raw_sub->image()->scale (tx.size(), _film->scaler(), false)));
- _display_sub_position = tx.position();
- _display_sub_position.x += _display_frame_x;
- } else {
- _display_sub.reset ();
- }
+ _display_frame = _raw_frame->scale_and_convert_to_rgb (_film_size, _film->scaler(), false);
}
void
return;
}
- Container const * container = _film->container ();
+ Ratio const * container = _film->container ();
float const panel_ratio = static_cast<float> (_panel_size.width) / _panel_size.height;
float const film_ratio = container ? container->ratio () : 1.78;
}
void
-FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, Time t)
+FilmViewer::process_video (shared_ptr<const Image> image, bool, Time t)
{
_raw_frame = image;
- _raw_sub = sub;
raw_to_display ();
class FFmpegPlayer;
class Image;
class RGBPlusAlphaImage;
-class Subtitle;
/** @class FilmViewer
* @brief A wx widget to view a preview of a Film.
* 1. get_frame() asks our _player to decode some data. If it does, process_video()
* will be called.
*
- * 2. process_video() takes the image and subtitle from the decoder (_raw_frame and _raw_sub)
- * and calls raw_to_display().
+ * 2. process_video() takes the image from the decoder (_raw_frame) and calls raw_to_display().
*
* 3. raw_to_display() copies _raw_frame to _display_frame, processing it and scaling it.
*
* 4. calling _panel->Refresh() and _panel->Update() results in paint_panel() being called;
- * this creates frame_bitmap from _display_frame and blits it to the display. It also
- * blits the subtitle, if required.
+ * this creates frame_bitmap from _display_frame and blits it to the display.
*
* update_from_decoder() asks the player to re-emit its current frame on the next pass(), and then
* starts from step #1.
void slider_moved (wxScrollEvent &);
void play_clicked (wxCommandEvent &);
void timer (wxTimerEvent &);
- void process_video (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time);
+ void process_video (boost::shared_ptr<const Image>, bool, Time);
void calculate_sizes ();
void check_play_state ();
void update_from_raw ();
wxTimer _timer;
boost::shared_ptr<const Image> _raw_frame;
- boost::shared_ptr<Subtitle> _raw_sub;
boost::shared_ptr<const Image> _display_frame;
/* The x offset at which we display the actual film content; this corresponds
to the film's padding converted to our coordinates.
*/
int _display_frame_x;
- boost::shared_ptr<RGBPlusAlphaImage> _display_sub;
- Position _display_sub_position;
bool _got_frame;
/** Size of our output (including padding if we have any) */
shared_ptr<DCPVideoFrame> frame (
new DCPVideoFrame (
image,
- subtitle,
- libdcp::Size (1998, 1080),
- 0,
- 0,
- 1,
- Scaler::from_id ("bicubic"),
0,
24,
0,
+++ /dev/null
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-using std::ostream;
-
-namespace libdcp {
-
-ostream&
-operator<< (ostream& s, libdcp::Size const & t)
-{
- s << t.width << "x" << t.height;
- return s;
-}
-
-}
-
-BOOST_AUTO_TEST_CASE (container_test)
-{
- Container::setup_containers ();
-
- Container const * c = Container::from_id ("119");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1285, 1080));
-
- c = Container::from_id ("133");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1436, 1080));
-
- c = Container::from_id ("137");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1480, 1080));
-
- c = Container::from_id ("138");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1485, 1080));
-
- c = Container::from_id ("166");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1793, 1080));
-
- c = Container::from_id ("178");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1920, 1080));
-
- c = Container::from_id ("185");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (1998, 1080));
-
- c = Container::from_id ("239");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 858));
-
- c = Container::from_id ("full-frame");
- BOOST_CHECK (c);
- BOOST_CHECK_EQUAL (c->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 1080));
-}
-
dcpomatic_sleep (1);
}
- film->set_container (Container::from_id ("185"));
+ film->set_container (Ratio::from_id ("185"));
film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
film->make_dcp ();
film->write_metadata ();
f->set_name ("fred");
f->set_dcp_content_type (DCPContentType::from_pretty_name ("Short"));
- f->set_container (Container::from_id ("185"));
+ f->set_container (Ratio::from_id ("185"));
f->set_ab (true);
f->write_metadata ();
BOOST_CHECK_EQUAL (g->name(), "fred");
BOOST_CHECK_EQUAL (g->dcp_content_type(), DCPContentType::from_pretty_name ("Short"));
- BOOST_CHECK_EQUAL (g->container(), Container::from_id ("185"));
+ BOOST_CHECK_EQUAL (g->container(), Ratio::from_id ("185"));
BOOST_CHECK_EQUAL (g->ab(), true);
g->write_metadata ();
+++ /dev/null
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-BOOST_AUTO_TEST_CASE (format_test)
-{
- Format::setup_formats ();
-
- Format const * f = Format::from_nickname ("Flat");
- BOOST_CHECK (f);
- BOOST_CHECK_EQUAL (f->dcp_size().width, 1998);
- BOOST_CHECK_EQUAL (f->dcp_size().height, 1080);
-
- f = Format::from_nickname ("Scope");
- BOOST_CHECK (f);
- BOOST_CHECK_EQUAL (f->dcp_size().width, 2048);
- BOOST_CHECK_EQUAL (f->dcp_size().height, 858);
-}
for (list<AVPixelFormat>::const_iterator i = pix_fmts.begin(); i != pix_fmts.end(); ++i) {
boost::shared_ptr<Image> foo (new SimpleImage (*i, in_size, true));
foo->make_black ();
- boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, 0, Scaler::from_id ("bicubic"), true);
+ boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, Scaler::from_id ("bicubic"), true);
uint8_t* p = bar->data()[0];
for (int y = 0; y < bar->size().height; ++y) {
--- /dev/null
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+using std::ostream;
+
+namespace libdcp {
+
+ostream&
+operator<< (ostream& s, libdcp::Size const & t)
+{
+ s << t.width << "x" << t.height;
+ return s;
+}
+
+}
+
+BOOST_AUTO_TEST_CASE (ratio_test)
+{
+ Ratio::setup_ratios ();
+
+ Ratio const * r = Ratio::from_id ("119");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1285, 1080));
+
+ r = Ratio::from_id ("133");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1436, 1080));
+
+ r = Ratio::from_id ("137");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1480, 1080));
+
+ r = Ratio::from_id ("138");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1485, 1080));
+
+ r = Ratio::from_id ("166");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1793, 1080));
+
+ r = Ratio::from_id ("178");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1920, 1080));
+
+ r = Ratio::from_id ("185");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1998, 1080));
+
+ r = Ratio::from_id ("239");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 858));
+
+ r = Ratio::from_id ("full-frame");
+ BOOST_CHECK (r);
+ BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 1080));
+}
+
*/
+#include "imagemagick_content.h"
+
/** @file test/scaling_test.cc
* @brief Test scaling and black-padding of images from a still-image source.
*/
using boost::shared_ptr;
+static void scaling_test_for (shared_ptr<Film> film, shared_ptr<VideoContent> content, string image, string container)
+{
+ content->set_ratio (Ratio::from_id (image));
+ film->set_container (Ratio::from_id (container));
+ film->make_dcp ();
+
+ while (JobManager::instance()->work_to_do ());
+
+ BOOST_CHECK (!JobManager::instance()->errors());
+
+ boost::filesystem::path ref;
+ ref = "test";
+ ref /= "data";
+ ref /= "scaling_test_" + image + "_" + container;
+
+ boost::filesystem::path check;
+ check = "build";
+ check /= "test";
+ check /= "scaling_test";
+ check /= film->dcp_name();
+
+ check_dcp (ref.string(), check.string());
+}
+
BOOST_AUTO_TEST_CASE (scaling_test)
{
shared_ptr<Film> film = new_test_film ("scaling_test");
- film->examine_and_add_content (shared_ptr<Content> (new ImageMagickContent ("test/data/simple_testcard_640x480.png")));
+ film->set_dcp_content_type (DCPContentType::from_dci_name ("FTR"));
+ film->set_name ("scaling_test");
+ shared_ptr<ImageMagickContent> imc (new ImageMagickContent (film, "test/data/simple_testcard_640x480.png"));
+
+ film->examine_and_add_content (imc);
+ while (JobManager::instance()->work_to_do ());
+ imc->set_video_length (1);
+
+ scaling_test_for (film, imc, "133", "185");
+ scaling_test_for (film, imc, "185", "185");
+ scaling_test_for (film, imc, "239", "185");
+
+ scaling_test_for (film, imc, "133", "239");
+ scaling_test_for (film, imc, "185", "239");
+ scaling_test_for (film, imc, "239", "239");
}
+
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/date_time.hpp>
-#include "format.h"
+#include <libdcp/dcp.h>
+#include "ratio.h"
#include "film.h"
#include "filter.h"
#include "job_manager.h"
#include "ffmpeg_decoder.h"
#include "sndfile_decoder.h"
#include "dcp_content_type.h"
-#include "container.h"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE dcpomatic_test
#include <boost/test/unit_test.hpp>
using std::list;
using std::stringstream;
using std::vector;
+using std::min;
+using std::cout;
using boost::shared_ptr;
using boost::thread;
using boost::dynamic_pointer_cast;
return f;
}
+void
+check_file (string ref, string check)
+{
+ uintmax_t N = boost::filesystem::file_size (ref);
+ BOOST_CHECK_EQUAL (N, boost::filesystem::file_size(check));
+ FILE* ref_file = fopen (ref.c_str(), "rb");
+ BOOST_CHECK (ref_file);
+ FILE* check_file = fopen (check.c_str(), "rb");
+ BOOST_CHECK (check_file);
+
+ int const buffer_size = 65536;
+ uint8_t* ref_buffer = new uint8_t[buffer_size];
+ uint8_t* check_buffer = new uint8_t[buffer_size];
+
+ while (N) {
+ uintmax_t this_time = min (uintmax_t (buffer_size), N);
+ size_t r = fread (ref_buffer, 1, this_time, ref_file);
+ BOOST_CHECK_EQUAL (r, this_time);
+ r = fread (check_buffer, 1, this_time, check_file);
+ BOOST_CHECK_EQUAL (r, this_time);
+
+ BOOST_CHECK_EQUAL (memcmp (ref_buffer, check_buffer, this_time), 0);
+ N -= this_time;
+ }
+
+ delete[] ref_buffer;
+ delete[] check_buffer;
+
+ fclose (ref_file);
+ fclose (check_file);
+}
+
+static void
+note (libdcp::NoteType, string n)
+{
+ cout << n << "\n";
+}
+
+void
+check_dcp (string ref, string check)
+{
+ libdcp::DCP ref_dcp (ref);
+ ref_dcp.read ();
+ libdcp::DCP check_dcp (check);
+ check_dcp.read ();
+
+ libdcp::EqualityOptions options;
+ options.max_mean_pixel_error = 5;
+ options.max_std_dev_pixel_error = 5;
+ options.max_audio_sample_error = 255;
+
+ BOOST_CHECK (ref_dcp.equals (check_dcp, options, boost::bind (note, _1, _2)));
+}
+
+
#include "scaling_test.cc"
-#include "container_test.cc"
+#include "ratio_test.cc"
#include "pixel_formats_test.cc"
#include "make_black_test.cc"
#include "film_metadata_test.cc"
#include "stream_test.cc"
-#include "format_test.cc"
#include "util_test.cc"
#include "dcp_test.cc"
#include "frame_rate_test.cc"