+ 2014-10-24 Carl Hetherington <cth@carlh.net>
+
+ * Add a pause button for jobs.
+
+ * Experimental support for bypassing colourspace conversion (#266).
+
+ * Version 1.76.6 released.
+
+ 2014-10-23 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.76.5 released.
+
+ 2014-10-23 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.76.4 released.
+
+ 2014-10-23 Carl Hetherington <cth@carlh.net>
+
+ * Rename 'Add folder' to 'Add image sequence'
+ and add some tooltips.
+
+ * Move the "keep video in sequence" button into
+ the timeline dialogue.
+
+ * Fix mix-placement of content when using the "Down"
+ button to move it.
+
+2014-10-22 Carl Hetherington <cth@carlh.net>
+
+ * Version 2.0.15 released.
+
2014-10-22 Carl Hetherington <cth@carlh.net>
* Version 1.76.3 released.
* New upstream release.
* New upstream release.
* New upstream release.
++<<<<<<< HEAD
+
+ -- Carl Hetherington <carl@d1stkfactory> Wed, 22 Oct 2014 14:24:53 +0100
++=======
+ * New upstream release.
+ * New upstream release.
+
+ -- Carl Hetherington <carl@d1stkfactory> Fri, 24 Oct 2014 01:19:26 +0100
++>>>>>>> origin/master
dcpomatic (0.87-1) UNRELEASED; urgency=low
--- /dev/null
- shared_ptr<dcp::GammaLUT> in_lut = dcp::GammaLUT::cache.get (
- 12, _frame->colour_conversion().input_gamma, _frame->colour_conversion().input_gamma_linearised
- );
-
- /* XXX: libdcp should probably use boost */
-
- double matrix[3][3];
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- matrix[i][j] = _frame->colour_conversion().matrix (i, j);
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/dcp_video_frame.cc
+ * @brief A single frame of video destined for a DCP.
+ *
+ * Given an Image and some settings, this class knows how to encode
+ * the image to J2K either on the local host or on a remote server.
+ *
+ * Objects of this class are used for the queue that we keep
+ * of images that require encoding.
+ */
+
+#include <stdint.h>
+#include <cstring>
+#include <cstdlib>
+#include <stdexcept>
+#include <cstdio>
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <errno.h>
+#include <boost/array.hpp>
+#include <boost/asio.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <dcp/gamma_lut.h>
+#include <dcp/xyz_frame.h>
+#include <dcp/rgb_xyz.h>
+#include <dcp/colour_matrix.h>
+#include <dcp/raw_convert.h>
+#include <libcxml/cxml.h>
+#include "film.h"
+#include "dcp_video.h"
+#include "config.h"
+#include "exceptions.h"
+#include "server.h"
+#include "util.h"
+#include "scaler.h"
+#include "image.h"
+#include "log.h"
+#include "cross.h"
+#include "player_video.h"
+#include "encoded_data.h"
+
+#define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
+
+#include "i18n.h"
+
+using std::string;
+using std::cout;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using dcp::Size;
+using dcp::raw_convert;
+
+#define DCI_COEFFICENT (48.0 / 52.37)
+
+/** Construct a DCP video frame.
+ * @param frame Input frame.
+ * @param index Index of the frame within the DCP.
+ * @param bw J2K bandwidth to use (see Config::j2k_bandwidth ())
+ * @param l Log to write to.
+ */
+DCPVideo::DCPVideo (
+ shared_ptr<const PlayerVideo> frame, int index, int dcp_fps, int bw, Resolution r, bool b, shared_ptr<Log> l
+ )
+ : _frame (frame)
+ , _index (index)
+ , _frames_per_second (dcp_fps)
+ , _j2k_bandwidth (bw)
+ , _resolution (r)
+ , _burn_subtitles (b)
+ , _log (l)
+{
+
+}
+
+DCPVideo::DCPVideo (shared_ptr<const PlayerVideo> frame, shared_ptr<const cxml::Node> node, shared_ptr<Log> log)
+ : _frame (frame)
+ , _log (log)
+{
+ _index = node->number_child<int> ("Index");
+ _frames_per_second = node->number_child<int> ("FramesPerSecond");
+ _j2k_bandwidth = node->number_child<int> ("J2KBandwidth");
+ _resolution = Resolution (node->optional_number_child<int>("Resolution").get_value_or (RESOLUTION_2K));
+ _burn_subtitles = node->bool_child ("BurnSubtitles");
+}
+
+/** J2K-encode this frame on the local host.
+ * @return Encoded data.
+ */
+shared_ptr<EncodedData>
+DCPVideo::encode_locally ()
+{
- shared_ptr<dcp::XYZFrame> xyz = dcp::rgb_to_xyz (
- _frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles),
- in_lut,
- dcp::GammaLUT::cache.get (16, 1 / _frame->colour_conversion().output_gamma, false),
- matrix
- );
-
++ shared_ptr<dcp::XYZFrame> xyz;
++
++ if (_frame->colour_conversion()) {
++ ColourConversion conversion = _frame->colour_conversion().get ();
++ shared_ptr<dcp::GammaLUT> in_lut = dcp::GammaLUT::cache.get (
++ 12, conversion.input_gamma, conversion.input_gamma_linearised
++ );
++
++ /* XXX: dcp should probably use boost */
++
++ double matrix[3][3];
++ for (int i = 0; i < 3; ++i) {
++ for (int j = 0; j < 3; ++j) {
++ matrix[i][j] = conversion.matrix (i, j);
++ }
+ }
++
++ xyz = dcp::rgb_to_xyz (
++ _frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles),
++ in_lut,
++ dcp::GammaLUT::cache.get (16, 1 / conversion.output_gamma, false),
++ matrix
++ );
++ } else {
++ xyz = dcp::xyz_to_xyz (_frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles));
+ }
+
+ /* Set the max image and component sizes based on frame_rate */
+ int max_cs_len = ((float) _j2k_bandwidth) / 8 / _frames_per_second;
+ if (_frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT) {
+ /* In 3D we have only half the normal bandwidth per eye */
+ max_cs_len /= 2;
+ }
+ int const max_comp_size = max_cs_len / 1.25;
+
+ /* get a J2K compressor handle */
+ opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
+ if (cinfo == 0) {
+ throw EncodeError (N_("could not create JPEG2000 encoder"));
+ }
+
+ /* Set encoding parameters to default values */
+ opj_cparameters_t parameters;
+ opj_set_default_encoder_parameters (¶meters);
+
+ /* Set default cinema parameters */
+ parameters.tile_size_on = false;
+ parameters.cp_tdx = 1;
+ parameters.cp_tdy = 1;
+
+ /* Tile part */
+ parameters.tp_flag = 'C';
+ parameters.tp_on = 1;
+
+ /* Tile and Image shall be at (0,0) */
+ parameters.cp_tx0 = 0;
+ parameters.cp_ty0 = 0;
+ parameters.image_offset_x0 = 0;
+ parameters.image_offset_y0 = 0;
+
+ /* Codeblock size = 32x32 */
+ parameters.cblockw_init = 32;
+ parameters.cblockh_init = 32;
+ parameters.csty |= 0x01;
+
+ /* The progression order shall be CPRL */
+ parameters.prog_order = CPRL;
+
+ /* No ROI */
+ parameters.roi_compno = -1;
+
+ parameters.subsampling_dx = 1;
+ parameters.subsampling_dy = 1;
+
+ /* 9-7 transform */
+ parameters.irreversible = 1;
+
+ parameters.tcp_rates[0] = 0;
+ parameters.tcp_numlayers++;
+ parameters.cp_disto_alloc = 1;
+ parameters.cp_rsiz = _resolution == RESOLUTION_2K ? CINEMA2K : CINEMA4K;
+ if (_resolution == RESOLUTION_4K) {
+ parameters.numpocs = 2;
+ parameters.POC[0].tile = 1;
+ parameters.POC[0].resno0 = 0;
+ parameters.POC[0].compno0 = 0;
+ parameters.POC[0].layno1 = 1;
+ parameters.POC[0].resno1 = parameters.numresolution - 1;
+ parameters.POC[0].compno1 = 3;
+ parameters.POC[0].prg1 = CPRL;
+ parameters.POC[1].tile = 1;
+ parameters.POC[1].resno0 = parameters.numresolution - 1;
+ parameters.POC[1].compno0 = 0;
+ parameters.POC[1].layno1 = 1;
+ parameters.POC[1].resno1 = parameters.numresolution;
+ parameters.POC[1].compno1 = 3;
+ parameters.POC[1].prg1 = CPRL;
+ }
+
+ parameters.cp_comment = strdup (N_("DCP-o-matic"));
+ parameters.cp_cinema = _resolution == RESOLUTION_2K ? CINEMA2K_24 : CINEMA4K_24;
+
+ /* 3 components, so use MCT */
+ parameters.tcp_mct = 1;
+
+ /* set max image */
+ parameters.max_comp_size = max_comp_size;
+ parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
+
+ /* Set event manager to null (openjpeg 1.3 bug) */
+ cinfo->event_mgr = 0;
+
+ /* Setup the encoder parameters using the current image and user parameters */
+ opj_setup_encoder (cinfo, ¶meters, xyz->opj_image ());
+
+ opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
+ if (cio == 0) {
+ opj_destroy_compress (cinfo);
+ throw EncodeError (N_("could not open JPEG2000 stream"));
+ }
+
+ int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
+ if (r == 0) {
+ opj_cio_close (cio);
+ opj_destroy_compress (cinfo);
+ throw EncodeError (N_("JPEG2000 encoding failed"));
+ }
+
+ switch (_frame->eyes()) {
+ case EYES_BOTH:
+ LOG_GENERAL (N_("Finished locally-encoded frame %1 for mono"), _index);
+ break;
+ case EYES_LEFT:
+ LOG_GENERAL (N_("Finished locally-encoded frame %1 for L"), _index);
+ break;
+ case EYES_RIGHT:
+ LOG_GENERAL (N_("Finished locally-encoded frame %1 for R"), _index);
+ break;
+ default:
+ break;
+ }
+
+ shared_ptr<EncodedData> enc (new LocallyEncodedData (cio->buffer, cio_tell (cio)));
+
+ opj_cio_close (cio);
+ free (parameters.cp_comment);
+ opj_destroy_compress (cinfo);
+
+ return enc;
+}
+
+/** Send this frame to a remote server for J2K encoding, then read the result.
+ * @param serv Server to send to.
+ * @return Encoded data.
+ */
+shared_ptr<EncodedData>
+DCPVideo::encode_remotely (ServerDescription serv)
+{
+ boost::asio::io_service io_service;
+ boost::asio::ip::tcp::resolver resolver (io_service);
+ boost::asio::ip::tcp::resolver::query query (serv.host_name(), raw_convert<string> (Config::instance()->server_port_base ()));
+ boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query);
+
+ shared_ptr<Socket> socket (new Socket);
+
+ socket->connect (*endpoint_iterator);
+
+ /* Collect all XML metadata */
+ xmlpp::Document doc;
+ xmlpp::Element* root = doc.create_root_node ("EncodingRequest");
+ root->add_child("Version")->add_child_text (raw_convert<string> (SERVER_LINK_VERSION));
+ add_metadata (root);
+
+ LOG_GENERAL (N_("Sending frame %1 to remote"), _index);
+
+ /* Send XML metadata */
+ string xml = doc.write_to_string ("UTF-8");
+ socket->write (xml.length() + 1);
+ socket->write ((uint8_t *) xml.c_str(), xml.length() + 1);
+
+ /* Send binary data */
+ _frame->send_binary (socket, _burn_subtitles);
+
+ /* Read the response (JPEG2000-encoded data); this blocks until the data
+ is ready and sent back.
+ */
+ shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
+ socket->read (e->data(), e->size());
+
+ LOG_GENERAL (N_("Finished remotely-encoded frame %1"), _index);
+
+ return e;
+}
+
+void
+DCPVideo::add_metadata (xmlpp::Element* el) const
+{
+ el->add_child("Index")->add_child_text (raw_convert<string> (_index));
+ el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second));
+ el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
+ el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution)));
+ el->add_child("BurnSubtitles")->add_child_text (_burn_subtitles ? "1" : "0");
+ _frame->add_metadata (el, _burn_subtitles);
+}
+
+Eyes
+DCPVideo::eyes () const
+{
+ return _frame->eyes ();
+}
+
+/** @return true if this DCPVideo is definitely the same as another;
+ * (apart from the frame index), false if it is probably not.
+ */
+bool
+DCPVideo::same (shared_ptr<const DCPVideo> other) const
+{
+ if (_frames_per_second != other->_frames_per_second ||
+ _j2k_bandwidth != other->_j2k_bandwidth ||
+ _resolution != other->_resolution ||
+ _burn_subtitles != other->_burn_subtitles) {
+ return false;
+ }
+
+ return _frame->same (other->_frame);
+}
--- /dev/null
- ColourConversion colour_conversion
+/*
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <dcp/raw_convert.h>
+#include "player_video.h"
+#include "image.h"
+#include "image_proxy.h"
+#include "j2k_image_proxy.h"
+#include "scaler.h"
+
+using std::string;
+using std::cout;
+using dcp::raw_convert;
+using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
++using boost::optional;
+
+PlayerVideo::PlayerVideo (
+ shared_ptr<const ImageProxy> in,
+ DCPTime time,
+ Crop crop,
+ boost::optional<float> fade,
+ dcp::Size inter_size,
+ dcp::Size out_size,
+ Scaler const * scaler,
+ Eyes eyes,
+ Part part,
- _colour_conversion = ColourConversion (node);
++ optional<ColourConversion> colour_conversion
+ )
+ : _in (in)
+ , _time (time)
+ , _crop (crop)
+ , _fade (fade)
+ , _inter_size (inter_size)
+ , _out_size (out_size)
+ , _scaler (scaler)
+ , _eyes (eyes)
+ , _part (part)
+ , _colour_conversion (colour_conversion)
+{
+
+}
+
+PlayerVideo::PlayerVideo (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket, shared_ptr<Log> log)
+{
+ _time = DCPTime (node->number_child<DCPTime::Type> ("Time"));
+ _crop = Crop (node);
+ _fade = node->optional_number_child<float> ("Fade");
+
+ _inter_size = dcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight"));
+ _out_size = dcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight"));
+ _scaler = Scaler::from_id (node->string_child ("Scaler"));
+ _eyes = (Eyes) node->number_child<int> ("Eyes");
+ _part = (Part) node->number_child<int> ("Part");
- _colour_conversion.as_xml (node);
++ _colour_conversion = ColourConversion::from_xml (node);
+
+ _in = image_proxy_factory (node->node_child ("In"), socket, log);
+
+ if (node->optional_number_child<int> ("SubtitleX")) {
+
+ _subtitle.position = Position<int> (node->number_child<int> ("SubtitleX"), node->number_child<int> ("SubtitleY"));
+
+ _subtitle.image.reset (
+ new Image (PIX_FMT_RGBA, dcp::Size (node->number_child<int> ("SubtitleWidth"), node->number_child<int> ("SubtitleHeight")), true)
+ );
+
+ _subtitle.image->read_from_socket (socket);
+ }
+}
+
+void
+PlayerVideo::set_subtitle (PositionImage image)
+{
+ _subtitle = image;
+}
+
+shared_ptr<Image>
+PlayerVideo::image (AVPixelFormat pixel_format, bool burn_subtitle) const
+{
+ shared_ptr<Image> im = _in->image ();
+
+ Crop total_crop = _crop;
+ switch (_part) {
+ case PART_LEFT_HALF:
+ total_crop.right += im->size().width / 2;
+ break;
+ case PART_RIGHT_HALF:
+ total_crop.left += im->size().width / 2;
+ break;
+ case PART_TOP_HALF:
+ total_crop.bottom += im->size().height / 2;
+ break;
+ case PART_BOTTOM_HALF:
+ total_crop.top += im->size().height / 2;
+ break;
+ default:
+ break;
+ }
+
+ shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, _scaler, pixel_format, true);
+
+ if (burn_subtitle && _subtitle.image) {
+ out->alpha_blend (_subtitle.image, _subtitle.position);
+ }
+
+ if (_fade) {
+ out->fade (_fade.get ());
+ }
+
+ return out;
+}
+
+void
+PlayerVideo::add_metadata (xmlpp::Node* node, bool send_subtitles) const
+{
+ node->add_child("Time")->add_child_text (raw_convert<string> (_time.get ()));
+ _crop.as_xml (node);
+ if (_fade) {
+ node->add_child("Fade")->add_child_text (raw_convert<string> (_fade.get ()));
+ }
+ _in->add_metadata (node->add_child ("In"));
+ node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width));
+ node->add_child("InterHeight")->add_child_text (raw_convert<string> (_inter_size.height));
+ node->add_child("OutWidth")->add_child_text (raw_convert<string> (_out_size.width));
+ node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height));
+ node->add_child("Scaler")->add_child_text (_scaler->id ());
+ node->add_child("Eyes")->add_child_text (raw_convert<string> (_eyes));
+ node->add_child("Part")->add_child_text (raw_convert<string> (_part));
++ if (_colour_conversion) {
++ _colour_conversion.get().as_xml (node);
++ }
+ if (send_subtitles && _subtitle.image) {
+ node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle.image->size().width));
+ node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle.image->size().height));
+ node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle.position.x));
+ node->add_child ("SubtitleY")->add_child_text (raw_convert<string> (_subtitle.position.y));
+ }
+}
+
+void
+PlayerVideo::send_binary (shared_ptr<Socket> socket, bool send_subtitles) const
+{
+ _in->send_binary (socket);
+ if (send_subtitles && _subtitle.image) {
+ _subtitle.image->write_to_socket (socket);
+ }
+}
+
+bool
+PlayerVideo::has_j2k () const
+{
+ /* XXX: burnt-in subtitle; maybe other things */
+
+ shared_ptr<const J2KImageProxy> j2k = dynamic_pointer_cast<const J2KImageProxy> (_in);
+ if (!j2k) {
+ return false;
+ }
+
+ return _crop == Crop () && _inter_size == j2k->size();
+}
+
+shared_ptr<EncodedData>
+PlayerVideo::j2k () const
+{
+ shared_ptr<const J2KImageProxy> j2k = dynamic_pointer_cast<const J2KImageProxy> (_in);
+ assert (j2k);
+ return j2k->j2k ();
+}
+
+Position<int>
+PlayerVideo::inter_position () const
+{
+ return Position<int> ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.height) / 2);
+}
+
+/** @return true if this PlayerVideo is definitely the same as another
+ * (apart from _time), false if it is probably not
+ */
+bool
+PlayerVideo::same (shared_ptr<const PlayerVideo> other) const
+{
+ if (_in != other->_in ||
+ _crop != other->_crop ||
+ _fade.get_value_or(0) != other->_fade.get_value_or(0) ||
+ _inter_size != other->_inter_size ||
+ _out_size != other->_out_size ||
+ _scaler != other->_scaler ||
+ _eyes != other->_eyes ||
+ _part != other->_part ||
+ _colour_conversion != other->_colour_conversion ||
+ !_subtitle.same (other->_subtitle)) {
+ return false;
+ }
+
+ return _in->same (other->_in);
+}
--- /dev/null
- ColourConversion
+/*
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/shared_ptr.hpp>
+extern "C" {
+#include <libavutil/pixfmt.h>
+}
+#include "types.h"
+#include "position.h"
+#include "colour_conversion.h"
+#include "position_image.h"
+
+class Image;
+class ImageProxy;
+class Scaler;
+class Socket;
+class Log;
+class EncodedData;
+
+/** Everything needed to describe a video frame coming out of the player, but with the
+ * bits still their raw form. We may want to combine the bits on a remote machine,
+ * or maybe not even bother to combine them at all.
+ */
+class PlayerVideo
+{
+public:
+ PlayerVideo (
+ boost::shared_ptr<const ImageProxy>,
+ DCPTime,
+ Crop,
+ boost::optional<float>,
+ dcp::Size,
+ dcp::Size,
+ Scaler const *,
+ Eyes,
+ Part,
- ColourConversion colour_conversion () const {
++ boost::optional<ColourConversion>
+ );
+
+ PlayerVideo (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>, boost::shared_ptr<Log>);
+
+ void set_subtitle (PositionImage);
+
+ boost::shared_ptr<Image> image (AVPixelFormat pix_fmt, bool burn_subtitle) const;
+
+ void add_metadata (xmlpp::Node* node, bool send_subtitles) const;
+ void send_binary (boost::shared_ptr<Socket> socket, bool send_subtitles) const;
+
+ bool has_j2k () const;
+ boost::shared_ptr<EncodedData> j2k () const;
+
+ DCPTime time () const {
+ return _time;
+ }
+
+ Eyes eyes () const {
+ return _eyes;
+ }
+
- ColourConversion _colour_conversion;
++ boost::optional<ColourConversion> colour_conversion () const {
+ return _colour_conversion;
+ }
+
+ /** @return Position of the content within the overall image once it has been scaled up */
+ Position<int> inter_position () const;
+
+ /** @return Size of the content within the overall image once it has been scaled up */
+ dcp::Size inter_size () const {
+ return _inter_size;
+ }
+
+ bool same (boost::shared_ptr<const PlayerVideo> other) const;
+
+private:
+ boost::shared_ptr<const ImageProxy> _in;
+ DCPTime _time;
+ Crop _crop;
+ boost::optional<float> _fade;
+ dcp::Size _inter_size;
+ dcp::Size _out_size;
+ Scaler const * _scaler;
+ Eyes _eyes;
+ Part _part;
++ boost::optional<ColourConversion> _colour_conversion;
+ PositionImage _subtitle;
+};
}
(*next)->set_position (c->position ());
- c->set_position (c->position() + c->length_after_trim ());
+ c->set_position (c->position() + (*next)->length_after_trim ());
sort (_content.begin(), _content.end(), ContentSorter ());
}
-
-FrameRateChange
-Playlist::active_frame_rate_change (Time t, int dcp_video_frame_rate) const
-{
- for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
- if (!vc) {
- continue;
- }
-
- if (vc->position() >= t && t < vc->end()) {
- return FrameRateChange (vc->video_frame_rate(), dcp_video_frame_rate);
- }
- }
-
- return FrameRateChange (dcp_video_frame_rate, dcp_video_frame_rate);
-}
msgid "could not create file %1"
msgstr "Datei %1 konnte nicht erstellt werden."
- #: src/lib/writer.cc:430
+#: src/lib/ffmpeg.cc:102
+msgid "could not find stream information"
+msgstr "Keine Spur-Information gefunden"
+
-#: src/lib/ffmpeg.cc:105
-msgid "could not find stream information"
-msgstr "Keine Spur-Information gefunden"
-
+ #: src/lib/ffmpeg.cc:179
+ msgid "could not find audio decoder"
+ msgstr "Ton Dekoder nicht gefunden."
+
+ #: src/lib/ffmpeg.cc:158
+ msgid "could not find video decoder"
+ msgstr "Bild-Dekoder nicht gefunden"
+
+ #: src/lib/writer.cc:439
msgid "could not move audio MXF into the DCP (%1)"
msgstr "Ton MXF kann nicht in das DCP verschoben werden (%1)"
msgid "unknown"
msgstr "unbekannt"
- #~ msgid "could not find audio decoder"
- #~ msgstr "Ton Dekoder nicht gefunden."
-
- #~ msgid "could not find video decoder"
- #~ msgstr "Bild-Dekoder nicht gefunden"
-
+#~ msgid "non-bitmap subtitles not yet supported"
+#~ msgstr "Nur Bitmap Untertitel werden unterstützt"
+
#~ msgid "Could not read DCP to make KDM for"
#~ msgstr "DCP konnte nicht zur Schlüsselerstellung geöffnet werden"
msgid "could not find stream information"
msgstr "no se pudo encontrar información del flujo"
+#: src/lib/writer.cc:430
++msgid "could not find audio decoder"
++msgstr "no se encontró el decodificador de audio"
++
+ #: src/lib/ffmpeg.cc:158
+ msgid "could not find video decoder"
+ msgstr "no se pudo encontrar decodificador de vídeo"
+
+ #: src/lib/writer.cc:439
msgid "could not move audio MXF into the DCP (%1)"
msgstr "no s puedo mover el audio MXF en el DCP (%1)"
msgid "unknown"
msgstr "desconocido"
- #~ msgid "could not find audio decoder"
- #~ msgstr "no se encontró el decodificador de audio"
-
- #~ msgid "could not find video decoder"
- #~ msgstr "no se pudo encontrar decodificador de vídeo"
-
+#~ msgid "non-bitmap subtitles not yet supported"
+#~ msgstr "todavía no se soportan subtítulos que no son en mapas de bits"
+
#~ msgid "Could not read DCP to make KDM for"
#~ msgstr "No se pudo leer el DCP para hacer el KDM"
msgid "could not create file %1"
msgstr "Écriture vers fichier distant (%1) impossible"
- #: src/lib/writer.cc:430
+#: src/lib/ffmpeg.cc:102
+msgid "could not find stream information"
+msgstr "information du flux introuvable"
+
-#: src/lib/ffmpeg.cc:105
-msgid "could not find stream information"
-msgstr "information du flux introuvable"
-
+ #: src/lib/ffmpeg.cc:179
+ msgid "could not find audio decoder"
+ msgstr "décodeur audio introuvable"
+
+ #: src/lib/ffmpeg.cc:158
+ msgid "could not find video decoder"
+ msgstr "décodeur vidéo introuvable"
+
+ #: src/lib/writer.cc:439
msgid "could not move audio MXF into the DCP (%1)"
msgstr "ne peut déplacer un MXF son dans le DCP (%1)"
msgid "unknown"
msgstr "Inconnu"
- #~ msgid "could not find audio decoder"
- #~ msgstr "décodeur audio introuvable"
-
- #~ msgid "could not find video decoder"
- #~ msgstr "décodeur vidéo introuvable"
-
+#~ msgid "non-bitmap subtitles not yet supported"
+#~ msgstr "sous-titres non-bitmap non supportés actuellement"
+
#~ msgid "Could not read DCP to make KDM for"
#~ msgstr "DCP illisible pour fabrication de KDM"
msgid "unknown"
msgstr "Errore sconosciuto"
- #~ msgid "could not find audio decoder"
- #~ msgstr "non riesco a trovare il decoder audio"
-
- #~ msgid "could not find video decoder"
- #~ msgstr "non riesco a trovare il decoder video"
-
+#~ msgid "non-bitmap subtitles not yet supported"
+#~ msgstr "sottotitoli non-bitmap non ancora supportati"
+
#~ msgid "Cubic interpolating deinterlacer"
#~ msgstr "Deinterlacciatore cubico interpolato"
msgid "unknown"
msgstr "onbekend"
- #~ msgid "could not find audio decoder"
- #~ msgstr "kan geen audio decoder vinden"
-
- #~ msgid "could not find video decoder"
- #~ msgstr "kan geen videodecoder vinden"
-
+#~ msgid "non-bitmap subtitles not yet supported"
+#~ msgstr "non-bitmap ondertitels worden nog niet ondersteund"
+
#~ msgid "Could not read DCP to make KDM for"
#~ msgstr "Kan DCP niet lezen om KDM te maken"
msgid "unknown"
msgstr "okänd"
- #~ msgid "could not find audio decoder"
- #~ msgstr "kunde inte hitta audio-avkodare"
-
- #~ msgid "could not find video decoder"
- #~ msgstr "kunde inte hitta video-avkodare"
-
+#~ msgid "non-bitmap subtitles not yet supported"
+#~ msgstr "icke-rastergrafiska undertexter stöds inte ännu"
+
#~ msgid "Could not read DCP to make KDM for"
#~ msgstr "Kunde inte läsa DCP för att skapa KDM"
, _video_frame_type (VIDEO_FRAME_TYPE_2D)
, _scale (Config::instance()->default_scale ())
{
- setup_default_colour_conversion ();
+ set_default_colour_conversion ();
}
-VideoContent::VideoContent (shared_ptr<const Film> f, Time s, VideoContent::Frame len)
+VideoContent::VideoContent (shared_ptr<const Film> f, DCPTime s, ContentTime len)
: Content (f, s)
, _video_length (len)
- , _original_video_frame_rate (0)
, _video_frame_rate (0)
, _video_frame_type (VIDEO_FRAME_TYPE_2D)
, _scale (Config::instance()->default_scale ())
, _video_frame_type (VIDEO_FRAME_TYPE_2D)
, _scale (Config::instance()->default_scale ())
{
- setup_default_colour_conversion ();
+ set_default_colour_conversion ();
}
-VideoContent::VideoContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node, int version)
+VideoContent::VideoContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, int version)
: Content (f, node)
{
- _video_length = node->number_child<VideoContent::Frame> ("VideoLength");
_video_size.width = node->number_child<int> ("VideoWidth");
_video_size.height = node->number_child<int> ("VideoHeight");
_video_frame_rate = node->number_child<float> ("VideoFrameRate");
} else {
_scale = VideoContentScale (node->node_child ("Scale"));
}
- _colour_conversion = ColourConversion (node->node_child ("ColourConversion"));
+
+
+ if (node->optional_node_child ("ColourConversion")) {
+ _colour_conversion = ColourConversion (node->node_child ("ColourConversion"));
+ }
+ if (version >= 32) {
+ _fade_in = ContentTime (node->number_child<int64_t> ("FadeIn"));
+ _fade_out = ContentTime (node->number_child<int64_t> ("FadeOut"));
+ }
}
VideoContent::VideoContent (shared_ptr<const Film> f, vector<shared_ptr<Content> > c)
node->add_child("VideoFrameType")->add_child_text (raw_convert<string> (static_cast<int> (_video_frame_type)));
_crop.as_xml (node);
_scale.as_xml (node->add_child("Scale"));
- _colour_conversion.as_xml (node->add_child("ColourConversion"));
+ if (_colour_conversion) {
+ _colour_conversion.get().as_xml (node->add_child("ColourConversion"));
+ }
+ node->add_child("FadeIn")->add_child_text (raw_convert<string> (_fade_in.get ()));
+ node->add_child("FadeOut")->add_child_text (raw_convert<string> (_fade_out.get ()));
}
void
- VideoContent::setup_default_colour_conversion ()
+ VideoContent::set_default_colour_conversion ()
{
- _colour_conversion = PresetColourConversion (_("sRGB"), 2.4, true, dcp::colour_matrix::srgb_to_xyz, 2.6).conversion;
- set_colour_conversion (PresetColourConversion (_("sRGB"), 2.4, true, libdcp::colour_matrix::srgb_to_xyz, 2.6).conversion);
++ set_colour_conversion (PresetColourConversion (_("sRGB"), 2.4, true, dcp::colour_matrix::srgb_to_xyz, 2.6).conversion);
}
void
void set_bottom_crop (int);
void set_scale (VideoContentScale);
+ void unset_colour_conversion ();
void set_colour_conversion (ColourConversion);
+ void set_default_colour_conversion ();
+
+ void set_fade_in (ContentTime);
+ void set_fade_out (ContentTime);
VideoFrameType video_frame_type () const {
boost::mutex::scoped_lock lm (_mutex);
VideoFrameType _video_frame_type;
Crop _crop;
VideoContentScale _scale;
- ColourConversion _colour_conversion;
+ boost::optional<ColourConversion> _colour_conversion;
+ ContentTime _fade_in;
+ ContentTime _fade_out;
};
#endif
bind (&FilmEditor::active_jobs_changed, this, _1)
);
- Config::instance()->Changed.connect (boost::bind (&FilmEditor::config_changed, this));
-
set_film (shared_ptr<Film> ());
-
-- SetSizerAndFit (s);
-}
-
-void
-FilmEditor::make_dcp_panel ()
-{
- _dcp_panel = new wxPanel (_main_notebook);
- _dcp_sizer = new wxBoxSizer (wxVERTICAL);
- _dcp_panel->SetSizer (_dcp_sizer);
-
- wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
- _dcp_sizer->Add (grid, 0, wxEXPAND | wxALL, 8);
-
- int r = 0;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Name"), true, wxGBPosition (r, 0));
- _name = new wxTextCtrl (_dcp_panel, wxID_ANY);
- grid->Add (_name, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND | wxLEFT | wxRIGHT);
- ++r;
-
- int flags = wxALIGN_CENTER_VERTICAL;
-#ifdef __WXOSX__
- flags |= wxALIGN_RIGHT;
-#endif
-
- _use_isdcf_name = new wxCheckBox (_dcp_panel, wxID_ANY, _("Use ISDCF name"));
- grid->Add (_use_isdcf_name, wxGBPosition (r, 0), wxDefaultSpan, flags);
- _edit_isdcf_button = new wxButton (_dcp_panel, wxID_ANY, _("Details..."));
- grid->Add (_edit_isdcf_button, wxGBPosition (r, 1), wxDefaultSpan);
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("DCP Name"), true, wxGBPosition (r, 0));
- _dcp_name = new wxStaticText (_dcp_panel, wxID_ANY, wxT (""));
- grid->Add (_dcp_name, wxGBPosition(r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Container"), true, wxGBPosition (r, 0));
- _container = new wxChoice (_dcp_panel, wxID_ANY);
- grid->Add (_container, wxGBPosition (r, 1), wxDefaultSpan, wxEXPAND);
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Content Type"), true, wxGBPosition (r, 0));
- _dcp_content_type = new wxChoice (_dcp_panel, wxID_ANY);
- grid->Add (_dcp_content_type, wxGBPosition (r, 1));
- ++r;
-
- {
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Frame Rate"), true, wxGBPosition (r, 0));
- _frame_rate_sizer = new wxBoxSizer (wxHORIZONTAL);
- _frame_rate_choice = new wxChoice (_dcp_panel, wxID_ANY);
- _frame_rate_sizer->Add (_frame_rate_choice, 1, wxALIGN_CENTER_VERTICAL);
- _frame_rate_spin = new wxSpinCtrl (_dcp_panel, wxID_ANY);
- _frame_rate_sizer->Add (_frame_rate_spin, 1, wxALIGN_CENTER_VERTICAL);
- setup_frame_rate_widget ();
- _best_frame_rate = new wxButton (_dcp_panel, wxID_ANY, _("Use best"));
- _frame_rate_sizer->Add (_best_frame_rate, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND);
- grid->Add (_frame_rate_sizer, wxGBPosition (r, 1));
- }
- ++r;
-
- _signed = new wxCheckBox (_dcp_panel, wxID_ANY, _("Signed"));
- grid->Add (_signed, wxGBPosition (r, 0), wxGBSpan (1, 2));
- ++r;
-
- _encrypted = new wxCheckBox (_dcp_panel, wxID_ANY, _("Encrypted"));
- grid->Add (_encrypted, wxGBPosition (r, 0), wxGBSpan (1, 2));
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Audio channels"), true, wxGBPosition (r, 0));
- _audio_channels = new wxSpinCtrl (_dcp_panel, wxID_ANY);
- grid->Add (_audio_channels, wxGBPosition (r, 1));
- ++r;
-
- _three_d = new wxCheckBox (_dcp_panel, wxID_ANY, _("3D"));
- grid->Add (_three_d, wxGBPosition (r, 0), wxGBSpan (1, 2));
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Resolution"), true, wxGBPosition (r, 0));
- _resolution = new wxChoice (_dcp_panel, wxID_ANY);
- grid->Add (_resolution, wxGBPosition (r, 1));
- ++r;
-
- {
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("JPEG2000 bandwidth"), true, wxGBPosition (r, 0));
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _j2k_bandwidth = new wxSpinCtrl (_dcp_panel, wxID_ANY);
- s->Add (_j2k_bandwidth, 1);
- add_label_to_sizer (s, _dcp_panel, _("Mbit/s"), false);
- grid->Add (s, wxGBPosition (r, 1));
- }
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Standard"), true, wxGBPosition (r, 0));
- _standard = new wxChoice (_dcp_panel, wxID_ANY);
- grid->Add (_standard, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- ++r;
-
- add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Scaler"), true, wxGBPosition (r, 0));
- _scaler = new wxChoice (_dcp_panel, wxID_ANY);
- grid->Add (_scaler, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- ++r;
-
- vector<Scaler const *> const sc = Scaler::all ();
- for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
- _scaler->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 ();
- for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
- _dcp_content_type->Append (std_to_wx ((*i)->pretty_name ()));
- }
-
- list<int> const dfr = Config::instance()->allowed_dcp_frame_rates ();
- for (list<int>::const_iterator i = dfr.begin(); i != dfr.end(); ++i) {
- _frame_rate_choice->Append (std_to_wx (boost::lexical_cast<string> (*i)));
- }
-
- _audio_channels->SetRange (0, MAX_DCP_AUDIO_CHANNELS);
- _j2k_bandwidth->SetRange (1, Config::instance()->maximum_j2k_bandwidth() / 1000000);
- _frame_rate_spin->SetRange (1, 480);
-
- _resolution->Append (_("2K"));
- _resolution->Append (_("4K"));
-
- _standard->Append (_("SMPTE"));
- _standard->Append (_("Interop"));
-}
-
-void
-FilmEditor::connect_to_widgets ()
-{
- _name->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&FilmEditor::name_changed, this));
- _use_isdcf_name->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&FilmEditor::use_isdcf_name_toggled, this));
- _edit_isdcf_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::edit_isdcf_button_clicked, this));
- _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&FilmEditor::container_changed, this));
- _content->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&FilmEditor::content_selection_changed, this));
- _content->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&FilmEditor::content_selection_changed, this));
- _content->Bind (wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, boost::bind (&FilmEditor::content_right_click, this, _1));
- _content->Bind (wxEVT_DROP_FILES, boost::bind (&FilmEditor::content_files_dropped, this, _1));
- _content_add_file->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::content_add_file_clicked, this));
- _content_add_folder->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::content_add_folder_clicked, this));
- _content_remove->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::content_remove_clicked, this));
- _content_earlier->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::content_earlier_clicked, this));
- _content_later->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::content_later_clicked, this));
- _content_timeline->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::content_timeline_clicked, this));
- _scaler->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&FilmEditor::scaler_changed, this));
- _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&FilmEditor::dcp_content_type_changed, this));
- _frame_rate_choice->Bind(wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&FilmEditor::frame_rate_choice_changed, this));
- _frame_rate_spin->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&FilmEditor::frame_rate_spin_changed, this));
- _best_frame_rate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FilmEditor::best_frame_rate_clicked, this));
- _signed->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&FilmEditor::signed_toggled, this));
- _encrypted->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&FilmEditor::encrypted_toggled, this));
- _audio_channels->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&FilmEditor::audio_channels_changed, this));
- _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&FilmEditor::j2k_bandwidth_changed, this));
- _resolution->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&FilmEditor::resolution_changed, this));
- _three_d->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&FilmEditor::three_d_changed, this));
- _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&FilmEditor::standard_changed, this));
-}
-
-void
-FilmEditor::make_content_panel ()
-{
- _content_panel = new wxPanel (_main_notebook);
- _content_sizer = new wxBoxSizer (wxVERTICAL);
- _content_panel->SetSizer (_content_sizer);
-
- {
- wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-
- _content = new wxListCtrl (_content_panel, wxID_ANY, wxDefaultPosition, wxSize (320, 160), wxLC_REPORT | wxLC_NO_HEADER);
- s->Add (_content, 1, wxEXPAND | wxTOP | wxBOTTOM, 6);
-
- _content->InsertColumn (0, wxT(""));
- _content->SetColumnWidth (0, 512);
-
- wxBoxSizer* b = new wxBoxSizer (wxVERTICAL);
-
- _content_add_file = new wxButton (_content_panel, wxID_ANY, _("Add file(s)..."));
- _content_add_file->SetToolTip (_("Add video, image or sound files to the film."));
- b->Add (_content_add_file, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
-
- _content_add_folder = new wxButton (_content_panel, wxID_ANY, _("Add image\nsequence..."));
- _content_add_folder->SetToolTip (_("Add a directory of image files which will be used as a moving image sequence."));
- b->Add (_content_add_folder, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
-
- _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove"));
- _content_remove->SetToolTip (_("Remove the selected piece of content from the film."));
- b->Add (_content_remove, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
-
- _content_earlier = new wxButton (_content_panel, wxID_ANY, _("Up"));
- _content_earlier->SetToolTip (_("Move the selected piece of content earlier in the film."));
- b->Add (_content_earlier, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
-
- _content_later = new wxButton (_content_panel, wxID_ANY, _("Down"));
- _content_later->SetToolTip (_("Move the selected piece of content later in the film."));
- b->Add (_content_later, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
-
- _content_timeline = new wxButton (_content_panel, wxID_ANY, _("Timeline..."));
- _content_timeline->SetToolTip (_("Open the timeline for the film."));
- b->Add (_content_timeline, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
-
- s->Add (b, 0, wxALL, 4);
-
- _content_sizer->Add (s, 0, wxEXPAND | wxALL, 6);
- }
-
- _content_notebook = new wxNotebook (_content_panel, wxID_ANY);
- _content_sizer->Add (_content_notebook, 1, wxEXPAND | wxTOP, 6);
-
- _video_panel = new VideoPanel (this);
- _panels.push_back (_video_panel);
- _audio_panel = new AudioPanel (this);
- _panels.push_back (_audio_panel);
- _subtitle_panel = new SubtitlePanel (this);
- _panels.push_back (_subtitle_panel);
- _timing_panel = new TimingPanel (this);
- _panels.push_back (_timing_panel);
-
- _content->DragAcceptFiles (true);
-}
-
-/** Called when the name widget has been changed */
-void
-FilmEditor::name_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_name (string (_name->GetValue().mb_str()));
-}
-
-void
-FilmEditor::j2k_bandwidth_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
-}
-
-void
-FilmEditor::signed_toggled ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_signed (_signed->GetValue ());
-}
-
-void
-FilmEditor::encrypted_toggled ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_encrypted (_encrypted->GetValue ());
-}
-
-/** Called when the frame rate choice widget has been changed */
-void
-FilmEditor::frame_rate_choice_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_video_frame_rate (
- boost::lexical_cast<int> (
- wx_to_std (_frame_rate_choice->GetString (_frame_rate_choice->GetSelection ()))
- )
- );
-}
-
-/** Called when the frame rate spin widget has been changed */
-void
-FilmEditor::frame_rate_spin_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_video_frame_rate (_frame_rate_spin->GetValue ());
-}
-
-void
-FilmEditor::audio_channels_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_audio_channels (_audio_channels->GetValue ());
-}
-
-void
-FilmEditor::resolution_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_resolution (_resolution->GetSelection() == 0 ? RESOLUTION_2K : RESOLUTION_4K);
}
-void
-FilmEditor::standard_changed ()
-{
- if (!_film) {
- return;
- }
-
- _film->set_interop (_standard->GetSelection() == 1);
-}
/** Called when the metadata stored in the Film object has changed;
* so that we can update the GUI.
msgid "Add file(s)..."
msgstr "Datei(en) hinzufügen..."
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Ordner hinzufügen..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
-#: src/wx/editable_list.h:62
+#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
msgid "Add..."
msgstr "Hinzufügen..."
msgid "Off"
msgstr "Aus"
+#: src/wx/config_dialog.cc:1167
+msgid "Open console window"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:25
+msgid "Organisation"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:27
+msgid "Organisational unit"
+msgstr ""
+
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
+
#: src/wx/screen_dialog.cc:65
msgid "Other"
msgstr "Andere"
msgid "video"
msgstr "Bild"
- #~ msgid "1 channel"
- #~ msgstr "1 Kanal"
-
- #~ msgid "Audio channels"
- #~ msgstr "Ton Kanäle"
-
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Bild konnte nicht zur Vorschau dekodiert werden (%s)"
-
- #~ msgid "Hz"
- #~ msgstr "Hz"
-
- #~ msgid "With Subtitles"
- #~ msgstr "Mit Untertitelung"
-
- #~ msgid "channels"
- #~ msgstr "Kanäle"
-#~ msgid "Add folder..."
-#~ msgstr "Ordner hinzufügen..."
--
#~ msgid "Default creator"
#~ msgstr "Standard 'creator' (DCI)"
msgid "Add file(s)..."
msgstr "Añadir fichero(s)..."
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Añadir carpeta..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
-#: src/wx/editable_list.h:62
+#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
msgid "Add..."
msgstr "Añadir..."
msgid "Off"
msgstr "Off"
+#: src/wx/config_dialog.cc:1167
+msgid "Open console window"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:25
+#, fuzzy
+msgid "Organisation"
+msgstr "Duración"
+
+#: src/wx/make_signer_chain_dialog.cc:27
+msgid "Organisational unit"
+msgstr ""
+
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
+
#: src/wx/screen_dialog.cc:65
msgid "Other"
msgstr "Otros"
msgid "video"
msgstr "vídeo"
- #~ msgid "1 channel"
- #~ msgstr "1 canal"
-
- #~ msgid "Audio channels"
- #~ msgstr "Canales de audio"
-
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "No se pudo decodificar el vídeo para mostrarlo (%s)"
-
- #~ msgid "Hz"
- #~ msgstr "Hz"
-
- #~ msgid "With Subtitles"
- #~ msgstr "Con subtítulos"
-
- #~ msgid "channels"
- #~ msgstr "canales"
-#~ msgid "Add folder..."
-#~ msgstr "Añadir carpeta..."
--
#~ msgid "Default creator"
#~ msgstr "Creador por defecto"
msgid "Add file(s)..."
msgstr "Ajout fichier(s)..."
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Ajout dossier..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
-#: src/wx/editable_list.h:62
+#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
msgid "Add..."
msgstr "Ajouter..."
msgid "Off"
msgstr "Eteint"
+#: src/wx/config_dialog.cc:1167
+msgid "Open console window"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:25
+#, fuzzy
+msgid "Organisation"
+msgstr "Durée"
+
+#: src/wx/make_signer_chain_dialog.cc:27
+msgid "Organisational unit"
+msgstr ""
+
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
+
#: src/wx/screen_dialog.cc:65
msgid "Other"
msgstr "Autre"
msgid "video"
msgstr "vidéo"
- #~ msgid "1 channel"
- #~ msgstr "1 canal"
-
- #~ msgid "Audio channels"
- #~ msgstr "Canaux audios"
-
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Décodage de la vidéo pour visualisation impossible (%s)"
-
- #~ msgid "Hz"
- #~ msgstr "Hz"
-
- #~ msgid "With Subtitles"
- #~ msgstr "Avec sous-titres"
-
- #~ msgid "channels"
- #~ msgstr "canaux"
-#~ msgid "Add folder..."
-#~ msgstr "Ajout dossier..."
--
#~ msgid "Default creator"
#~ msgstr "Créateur par défaut"
msgid "Add file(s)..."
msgstr "Aggiungi File"
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Aggiungi cartella"
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
-#: src/wx/editable_list.h:62
+#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
msgid "Add..."
msgstr "Aggiungi..."
msgid "Off"
msgstr ""
+#: src/wx/config_dialog.cc:1167
+msgid "Open console window"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:25
+#, fuzzy
+msgid "Organisation"
+msgstr "Durata"
+
+#: src/wx/make_signer_chain_dialog.cc:27
+msgid "Organisational unit"
+msgstr ""
+
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
+
#: src/wx/screen_dialog.cc:65
msgid "Other"
msgstr ""
msgid "video"
msgstr "Video"
- #~ msgid "1 channel"
- #~ msgstr "1 canale"
-
- #~ msgid "Audio channels"
- #~ msgstr "Canali audio"
-
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Non posso decodificare il video per guardarlo (%s)"
-
- #~ msgid "Hz"
- #~ msgstr "Hz"
-
- #~ msgid "With Subtitles"
- #~ msgstr "Con sottotitoli"
-
- #~ msgid "channels"
- #~ msgstr "canali"
-#~ msgid "Add folder..."
-#~ msgstr "Aggiungi cartella"
--
#, fuzzy
#~ msgid "Default creator"
#~ msgstr "Contenitore predefinito"
msgid "Add file(s)..."
msgstr "Voeg bestande(n) toe..."
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Voeg map toe..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
-#: src/wx/editable_list.h:62
+#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
msgid "Add..."
msgstr "Toevoegen.."
msgid "Off"
msgstr "Uit"
+#: src/wx/config_dialog.cc:1167
+msgid "Open console window"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:25
+msgid "Organisation"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:27
+msgid "Organisational unit"
+msgstr ""
+
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
+
#: src/wx/screen_dialog.cc:65
msgid "Other"
msgstr "Andere"
msgid "video"
msgstr "video"
- #~ msgid "1 channel"
- #~ msgstr "1 channel"
-
- #~ msgid "Audio channels"
- #~ msgstr "Audio kanalen"
-
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Kan video niet decoderen voor preview (%s)"
-
- #~ msgid "Hz"
- #~ msgstr "Hz"
-
- #~ msgid "With Subtitles"
- #~ msgstr "Met ondertiteling"
-
- #~ msgid "channels"
- #~ msgstr "kanalen"
-#~ msgid "Add folder..."
-#~ msgstr "Voeg map toe..."
--
#~ msgid "Default creator"
#~ msgstr "Standaard maker"
msgid "Add file(s)..."
msgstr "Lägg till fil(er)..."
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Lägg till folder..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
-#: src/wx/editable_list.h:62
+#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
msgid "Add..."
msgstr "Lägg till..."
msgid "Mbit/s"
msgstr ""
+ #: src/wx/film_editor.cc:293
+ msgid "Move the selected piece of content earlier in the film."
+ msgstr ""
+
+ #: src/wx/film_editor.cc:297
+ msgid "Move the selected piece of content later in the film."
+ msgstr ""
+
# Låter mysko
-#: src/wx/video_panel.cc:280
+#: src/wx/video_panel.cc:301
msgid "Multiple content selected"
msgstr "Flera innehåll valda"
msgid "Off"
msgstr "Av"
+#: src/wx/config_dialog.cc:1167
+msgid "Open console window"
+msgstr ""
+
+#: src/wx/make_signer_chain_dialog.cc:25
+#, fuzzy
+msgid "Organisation"
+msgstr "Längd"
+
+#: src/wx/make_signer_chain_dialog.cc:27
+msgid "Organisational unit"
+msgstr ""
+
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
+
#: src/wx/screen_dialog.cc:65
msgid "Other"
msgstr ""
{
/* Snap starts to ends */
- Time const d = abs (cv->content()->end() - new_position);
+ DCPTime const d = DCPTime (cv->content()->end() - new_position).abs ();
if (first || d < nearest_distance) {
nearest_distance = d;
- nearest_new_position = cv->content()->end();
- nearest_new_position = cv->content()->end() + 1;
++ nearest_new_position = cv->content()->end() + DCPTime::delta ();
}
}
{
/* Snap ends to starts */
- Time const d = abs (cv->content()->position() - (new_position + _down_view->content()->length_after_trim()));
+ DCPTime const d = DCPTime (
+ cv->content()->position() - (new_position + _down_view->content()->length_after_trim())
+ ).abs ();
+
if (d < nearest_distance) {
nearest_distance = d;
- nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim ();
- nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim () - 1;
++ nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim () - DCPTime::delta();
}
}
using std::cout;
using boost::shared_ptr;
-TimelineDialog::TimelineDialog (FilmEditor* ed, shared_ptr<Film> film)
- : wxDialog (ed, wxID_ANY, _("Timeline"), wxDefaultPosition, wxSize (640, 512), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
+TimelineDialog::TimelineDialog (ContentPanel* cp, shared_ptr<Film> film)
+ : wxDialog (cp->panel(), wxID_ANY, _("Timeline"), wxDefaultPosition, wxSize (640, 512), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
+ , _film (film)
- , _timeline (this, ed, film)
+ , _timeline (this, cp, film)
{
wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
&index_to_scale,
&scale_to_index
);
- _scale->add (grid, wxGBPosition (r, 1));
+ _scale->add (grid, wxGBPosition (r, 1), wxGBSpan (1, 2));
++r;
- {
- add_label_to_grid_bag_sizer (grid, this, _("Filters"), true, wxGBPosition (r, 0));
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-
- wxClientDC dc (this);
- wxSize size = dc.GetTextExtent (wxT ("A quite long-ish name"));
- size.SetHeight (-1);
-
- _filters = new wxStaticText (this, wxID_ANY, _("None"), wxDefaultPosition, size);
- s->Add (_filters, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6);
- _filters_button = new wxButton (this, wxID_ANY, _("Edit..."));
- s->Add (_filters_button, 0, wxALIGN_CENTER_VERTICAL);
- grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- }
+ wxClientDC dc (this);
+ wxSize size = dc.GetTextExtent (wxT ("A quite long name"));
+ size.SetHeight (-1);
+
+ add_label_to_grid_bag_sizer (grid, this, _("Filters"), true, wxGBPosition (r, 0));
+ _filters = new wxStaticText (this, wxID_ANY, _("None"), wxDefaultPosition, size);
+ grid->Add (_filters, wxGBPosition (r, 1), wxGBSpan (1, 2), wxALIGN_CENTER_VERTICAL);
+ _filters_button = new wxButton (this, wxID_ANY, _("Edit..."));
+ grid->Add (_filters_button, wxGBPosition (r, 3), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
++r;
- add_label_to_grid_bag_sizer (grid, this, _("Colour conversion"), true, wxGBPosition (r, 0));
- {
- _enable_colour_conversion = new wxCheckBox (this, wxID_ANY, _("Colour conversion"));
- grid->Add (_enable_colour_conversion, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
-
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-
- wxClientDC dc (this);
- wxSize size = dc.GetTextExtent (wxT ("A quite long-ish name"));
- size.SetHeight (-1);
-
- _colour_conversion = new wxStaticText (this, wxID_ANY, wxT (""), wxDefaultPosition, size);
-
- s->Add (_colour_conversion, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6);
- _colour_conversion_button = new wxButton (this, wxID_ANY, _("Edit..."));
- s->Add (_colour_conversion_button, 0, wxALIGN_CENTER_VERTICAL);
- grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- }
++ _enable_colour_conversion = new wxCheckBox (this, wxID_ANY, _("Colour conversion"));
++ grid->Add (_enable_colour_conversion, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+ _colour_conversion = new wxStaticText (this, wxID_ANY, wxT (""), wxDefaultPosition, size);
+ grid->Add (_colour_conversion, wxGBPosition (r, 1), wxGBSpan (1, 2), wxALIGN_CENTER_VERTICAL);
+ _colour_conversion_button = new wxButton (this, wxID_ANY, _("Edit..."));
+ grid->Add (_colour_conversion_button, wxGBPosition (r, 3), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
++r;
_description = new wxStaticText (this, wxID_ANY, wxT ("\n \n \n \n \n"), wxDefaultPosition, wxDefaultSize);
_frame_type->wrapped()->Append (_("3D left only"));
_frame_type->wrapped()->Append (_("3D right only"));
+ _fade_in->Changed.connect (boost::bind (&VideoPanel::fade_in_changed, this));
+ _fade_out->Changed.connect (boost::bind (&VideoPanel::fade_out_changed, this));
+
_filters_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&VideoPanel::edit_filters_clicked, this));
+ _enable_colour_conversion->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&VideoPanel::enable_colour_conversion_clicked, this));
_colour_conversion_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&VideoPanel::edit_colour_conversion_clicked, this));
}
film_content_changed (FFmpegContentProperty::FILTERS);
}
- VideoContentList vc = _editor->selected_video_content ();
+void
+VideoPanel::fade_in_changed ()
+{
+ VideoContentList vc = _parent->selected_video ();
+ for (VideoContentList::const_iterator i = vc.begin(); i != vc.end(); ++i) {
+ (*i)->set_fade_in (_fade_in->get (_parent->film()->video_frame_rate ()));
+ }
+}
+
+void
+VideoPanel::fade_out_changed ()
+{
+ VideoContentList vc = _parent->selected_video ();
+ for (VideoContentList::const_iterator i = vc.begin(); i != vc.end(); ++i) {
+ (*i)->set_fade_out (_fade_out->get (_parent->film()->video_frame_rate ()));
+ }
+}
++
+ void
+ VideoPanel::enable_colour_conversion_clicked ()
+ {
++ VideoContentList vc = _parent->selected_video ();
+ if (vc.size() != 1) {
+ return;
+ }
+
+ if (_enable_colour_conversion->GetValue()) {
+ vc.front()->set_default_colour_conversion ();
+ } else {
+ vc.front()->unset_colour_conversion ();
+ }
+ }
private:
void edit_filters_clicked ();
+ void enable_colour_conversion_clicked ();
void edit_colour_conversion_clicked ();
+ void fade_in_changed ();
+ void fade_out_changed ();
void setup_description ();