Rename Encoder -> FilmEncoder, and subclasses.
authorCarl Hetherington <cth@carlh.net>
Tue, 19 Mar 2024 15:29:13 +0000 (16:29 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 21 Apr 2024 21:18:19 +0000 (23:18 +0200)
45 files changed:
src/lib/dcp_decoder.cc
src/lib/dcp_encoder.cc [deleted file]
src/lib/dcp_encoder.h [deleted file]
src/lib/dcp_film_encoder.cc [new file with mode: 0644]
src/lib/dcp_film_encoder.h [new file with mode: 0644]
src/lib/encode_server.cc
src/lib/encode_server_finder.cc
src/lib/encoder.cc [deleted file]
src/lib/encoder.h [deleted file]
src/lib/ffmpeg_encoder.cc [deleted file]
src/lib/ffmpeg_encoder.h [deleted file]
src/lib/ffmpeg_file_encoder.cc
src/lib/ffmpeg_file_encoder.h
src/lib/ffmpeg_film_encoder.cc [new file with mode: 0644]
src/lib/ffmpeg_film_encoder.h [new file with mode: 0644]
src/lib/film.cc
src/lib/film_encoder.cc [new file with mode: 0644]
src/lib/film_encoder.h [new file with mode: 0644]
src/lib/hints.h
src/lib/make_dcp.cc
src/lib/reel_writer.h
src/lib/subtitle_encoder.cc [deleted file]
src/lib/subtitle_encoder.h [deleted file]
src/lib/subtitle_film_encoder.cc [new file with mode: 0644]
src/lib/subtitle_film_encoder.h [new file with mode: 0644]
src/lib/transcode_job.cc
src/lib/transcode_job.h
src/lib/wscript
src/tools/dcpomatic.cc
src/tools/dcpomatic_cli.cc
src/tools/dcpomatic_combiner.cc
src/tools/dcpomatic_editor.cc
src/tools/dcpomatic_kdm.cc
src/wx/config_dialog.cc
src/wx/dcp_timeline.h
src/wx/export_video_file_dialog.h
src/wx/film_viewer.h
src/wx/kdm_cpl_panel.cc
src/wx/timeline_content_view.cc
test/burnt_subtitle_test.cc
test/ffmpeg_encoder_test.cc
test/j2k_encode_threading_test.cc
test/optimise_stills_test.cc
test/video_level_test.cc
test/writer_test.cc

index d473476a00cf7c91b7cbd040b1a314d7587729bc..ce471202f9dad0ba7d85ae1924992af10c79bb71 100644 (file)
@@ -32,6 +32,7 @@
 #include "image.h"
 #include "j2k_image_proxy.h"
 #include "text_decoder.h"
+#include "util.h"
 #include "video_decoder.h"
 #include <dcp/cpl.h>
 #include <dcp/dcp.h>
diff --git a/src/lib/dcp_encoder.cc b/src/lib/dcp_encoder.cc
deleted file mode 100644 (file)
index bd78312..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-/** @file  src/dcp_encoder.cc
- *  @brief A class which takes a Film and some Options, then uses those to encode the film into a DCP.
- *
- *  A decoder is selected according to the content type, and the encoder can be specified
- *  as a parameter to the constructor.
- */
-
-
-#include "audio_decoder.h"
-#include "compose.hpp"
-#include "dcp_encoder.h"
-#include "film.h"
-#include "j2k_encoder.h"
-#include "job.h"
-#include "player.h"
-#include "player_video.h"
-#include "referenced_reel_asset.h"
-#include "text_content.h"
-#include "video_decoder.h"
-#include "writer.h"
-#include <boost/signals2.hpp>
-#include <iostream>
-
-#include "i18n.h"
-
-
-using std::cout;
-using std::dynamic_pointer_cast;
-using std::list;
-using std::make_shared;
-using std::shared_ptr;
-using std::string;
-using std::vector;
-using std::weak_ptr;
-using boost::optional;
-#if BOOST_VERSION >= 106100
-using namespace boost::placeholders;
-#endif
-using namespace dcpomatic;
-
-
-/** Construct a DCP encoder.
- *  @param film Film that we are encoding.
- *  @param job Job that this encoder is being used in.
- */
-DCPEncoder::DCPEncoder (shared_ptr<const Film> film, weak_ptr<Job> job)
-       : Encoder (film, job)
-       , _writer(film, job)
-       , _j2k_encoder(film, _writer)
-       , _finishing (false)
-       , _non_burnt_subtitles (false)
-{
-       _player_video_connection = _player.Video.connect(bind(&DCPEncoder::video, this, _1, _2));
-       _player_audio_connection = _player.Audio.connect(bind(&DCPEncoder::audio, this, _1, _2));
-       _player_text_connection = _player.Text.connect(bind(&DCPEncoder::text, this, _1, _2, _3, _4));
-       _player_atmos_connection = _player.Atmos.connect(bind(&DCPEncoder::atmos, this, _1, _2, _3));
-
-       for (auto c: film->content ()) {
-               for (auto i: c->text) {
-                       if (i->use() && !i->burn()) {
-                               _non_burnt_subtitles = true;
-                       }
-               }
-       }
-}
-
-DCPEncoder::~DCPEncoder ()
-{
-       /* We must stop receiving more video data before we die */
-       _player_video_connection.release ();
-       _player_audio_connection.release ();
-       _player_text_connection.release ();
-       _player_atmos_connection.release ();
-}
-
-void
-DCPEncoder::go ()
-{
-       _writer.start();
-       _j2k_encoder.begin();
-
-       {
-               auto job = _job.lock ();
-               DCPOMATIC_ASSERT (job);
-               job->sub (_("Encoding"));
-       }
-
-       if (_non_burnt_subtitles) {
-               _writer.write(_player.get_subtitle_fonts());
-       }
-
-       while (!_player.pass()) {}
-
-       for (auto i: get_referenced_reel_assets(_film, _film->playlist())) {
-               _writer.write(i);
-       }
-
-       _finishing = true;
-       _j2k_encoder.end();
-       _writer.finish(_film->dir(_film->dcp_name()));
-}
-
-
-void
-DCPEncoder::pause()
-{
-       _j2k_encoder.pause();
-}
-
-
-void
-DCPEncoder::resume()
-{
-       _j2k_encoder.resume();
-}
-
-void
-DCPEncoder::video (shared_ptr<PlayerVideo> data, DCPTime time)
-{
-       _j2k_encoder.encode(data, time);
-}
-
-void
-DCPEncoder::audio (shared_ptr<AudioBuffers> data, DCPTime time)
-{
-       _writer.write(data, time);
-
-       auto job = _job.lock ();
-       DCPOMATIC_ASSERT (job);
-       job->set_progress (float(time.get()) / _film->length().get());
-}
-
-void
-DCPEncoder::text (PlayerText data, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period)
-{
-       if (type == TextType::CLOSED_CAPTION || _non_burnt_subtitles) {
-               _writer.write(data, type, track, period);
-       }
-}
-
-
-void
-DCPEncoder::atmos (shared_ptr<const dcp::AtmosFrame> data, DCPTime time, AtmosMetadata metadata)
-{
-       _writer.write(data, time, metadata);
-}
-
-
-optional<float>
-DCPEncoder::current_rate () const
-{
-       return _j2k_encoder.current_encoding_rate();
-}
-
-Frame
-DCPEncoder::frames_done () const
-{
-       return _j2k_encoder.video_frames_enqueued();
-}
diff --git a/src/lib/dcp_encoder.h b/src/lib/dcp_encoder.h
deleted file mode 100644 (file)
index ce0b722..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "atmos_metadata.h"
-#include "dcp_text_track.h"
-#include "dcpomatic_time.h"
-#include "encoder.h"
-#include "player_text.h"
-#include "j2k_encoder.h"
-#include "writer.h"
-#include <dcp/atmos_frame.h>
-
-
-class AudioBuffers;
-class Film;
-class Job;
-class Player;
-class PlayerVideo;
-
-struct frames_not_lost_when_threads_disappear;
-
-
-/** @class DCPEncoder */
-class DCPEncoder : public Encoder
-{
-public:
-       DCPEncoder (std::shared_ptr<const Film> film, std::weak_ptr<Job> job);
-       ~DCPEncoder ();
-
-       void go () override;
-
-       boost::optional<float> current_rate () const override;
-       Frame frames_done () const override;
-
-       /** @return true if we are in the process of calling Encoder::process_end */
-       bool finishing () const override {
-               return _finishing;
-       }
-
-       void pause() override;
-       void resume() override;
-
-private:
-
-       friend struct ::frames_not_lost_when_threads_disappear;
-
-       void video (std::shared_ptr<PlayerVideo>, dcpomatic::DCPTime);
-       void audio (std::shared_ptr<AudioBuffers>, dcpomatic::DCPTime);
-       void text (PlayerText, TextType, boost::optional<DCPTextTrack>, dcpomatic::DCPTimePeriod);
-       void atmos (std::shared_ptr<const dcp::AtmosFrame>, dcpomatic::DCPTime, AtmosMetadata metadata);
-
-       Writer _writer;
-       J2KEncoder _j2k_encoder;
-       bool _finishing;
-       bool _non_burnt_subtitles;
-
-       boost::signals2::scoped_connection _player_video_connection;
-       boost::signals2::scoped_connection _player_audio_connection;
-       boost::signals2::scoped_connection _player_text_connection;
-       boost::signals2::scoped_connection _player_atmos_connection;
-};
diff --git a/src/lib/dcp_film_encoder.cc b/src/lib/dcp_film_encoder.cc
new file mode 100644 (file)
index 0000000..0403b2d
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+/** @file  src/dcp_film_encoder.cc
+ *  @brief A class which takes a Film and some Options, then uses those to encode the film into a DCP.
+ *
+ *  A decoder is selected according to the content type, and the encoder can be specified
+ *  as a parameter to the constructor.
+ */
+
+
+#include "audio_decoder.h"
+#include "compose.hpp"
+#include "dcp_film_encoder.h"
+#include "film.h"
+#include "j2k_encoder.h"
+#include "job.h"
+#include "player.h"
+#include "player_video.h"
+#include "referenced_reel_asset.h"
+#include "text_content.h"
+#include "video_decoder.h"
+#include "writer.h"
+#include <boost/signals2.hpp>
+#include <iostream>
+
+#include "i18n.h"
+
+
+using std::cout;
+using std::dynamic_pointer_cast;
+using std::list;
+using std::make_shared;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+using std::weak_ptr;
+using boost::optional;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
+using namespace dcpomatic;
+
+
+/** Construct a DCP encoder.
+ *  @param film Film that we are encoding.
+ *  @param job Job that this encoder is being used in.
+ */
+DCPFilmEncoder::DCPFilmEncoder(shared_ptr<const Film> film, weak_ptr<Job> job)
+       : FilmEncoder(film, job)
+       , _writer(film, job)
+       , _j2k_encoder(film, _writer)
+       , _finishing (false)
+       , _non_burnt_subtitles (false)
+{
+       _player_video_connection = _player.Video.connect(bind(&DCPFilmEncoder::video, this, _1, _2));
+       _player_audio_connection = _player.Audio.connect(bind(&DCPFilmEncoder::audio, this, _1, _2));
+       _player_text_connection = _player.Text.connect(bind(&DCPFilmEncoder::text, this, _1, _2, _3, _4));
+       _player_atmos_connection = _player.Atmos.connect(bind(&DCPFilmEncoder::atmos, this, _1, _2, _3));
+
+       for (auto c: film->content ()) {
+               for (auto i: c->text) {
+                       if (i->use() && !i->burn()) {
+                               _non_burnt_subtitles = true;
+                       }
+               }
+       }
+}
+
+DCPFilmEncoder::~DCPFilmEncoder()
+{
+       /* We must stop receiving more video data before we die */
+       _player_video_connection.release ();
+       _player_audio_connection.release ();
+       _player_text_connection.release ();
+       _player_atmos_connection.release ();
+}
+
+void
+DCPFilmEncoder::go()
+{
+       _writer.start();
+       _j2k_encoder.begin();
+
+       {
+               auto job = _job.lock ();
+               DCPOMATIC_ASSERT (job);
+               job->sub (_("Encoding"));
+       }
+
+       if (_non_burnt_subtitles) {
+               _writer.write(_player.get_subtitle_fonts());
+       }
+
+       while (!_player.pass()) {}
+
+       for (auto i: get_referenced_reel_assets(_film, _film->playlist())) {
+               _writer.write(i);
+       }
+
+       _finishing = true;
+       _j2k_encoder.end();
+       _writer.finish(_film->dir(_film->dcp_name()));
+}
+
+
+void
+DCPFilmEncoder::pause()
+{
+       _j2k_encoder.pause();
+}
+
+
+void
+DCPFilmEncoder::resume()
+{
+       _j2k_encoder.resume();
+}
+
+void
+DCPFilmEncoder::video(shared_ptr<PlayerVideo> data, DCPTime time)
+{
+       _j2k_encoder.encode(data, time);
+}
+
+void
+DCPFilmEncoder::audio(shared_ptr<AudioBuffers> data, DCPTime time)
+{
+       _writer.write(data, time);
+
+       auto job = _job.lock ();
+       DCPOMATIC_ASSERT (job);
+       job->set_progress (float(time.get()) / _film->length().get());
+}
+
+void
+DCPFilmEncoder::text(PlayerText data, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period)
+{
+       if (type == TextType::CLOSED_CAPTION || _non_burnt_subtitles) {
+               _writer.write(data, type, track, period);
+       }
+}
+
+
+void
+DCPFilmEncoder::atmos(shared_ptr<const dcp::AtmosFrame> data, DCPTime time, AtmosMetadata metadata)
+{
+       _writer.write(data, time, metadata);
+}
+
+
+optional<float>
+DCPFilmEncoder::current_rate() const
+{
+       return _j2k_encoder.current_encoding_rate();
+}
+
+Frame
+DCPFilmEncoder::frames_done() const
+{
+       return _j2k_encoder.video_frames_enqueued();
+}
diff --git a/src/lib/dcp_film_encoder.h b/src/lib/dcp_film_encoder.h
new file mode 100644 (file)
index 0000000..fbc0aeb
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "atmos_metadata.h"
+#include "dcp_text_track.h"
+#include "dcpomatic_time.h"
+#include "film_encoder.h"
+#include "player_text.h"
+#include "j2k_encoder.h"
+#include "writer.h"
+#include <dcp/atmos_frame.h>
+
+
+class AudioBuffers;
+class Film;
+class Job;
+class Player;
+class PlayerVideo;
+
+struct frames_not_lost_when_threads_disappear;
+
+
+/** @class DCPFilmEncoder */
+class DCPFilmEncoder : public FilmEncoder
+{
+public:
+       DCPFilmEncoder(std::shared_ptr<const Film> film, std::weak_ptr<Job> job);
+       ~DCPFilmEncoder();
+
+       void go () override;
+
+       boost::optional<float> current_rate () const override;
+       Frame frames_done () const override;
+
+       /** @return true if we are in the process of calling Encoder::process_end */
+       bool finishing () const override {
+               return _finishing;
+       }
+
+       void pause() override;
+       void resume() override;
+
+private:
+
+       friend struct ::frames_not_lost_when_threads_disappear;
+
+       void video (std::shared_ptr<PlayerVideo>, dcpomatic::DCPTime);
+       void audio (std::shared_ptr<AudioBuffers>, dcpomatic::DCPTime);
+       void text (PlayerText, TextType, boost::optional<DCPTextTrack>, dcpomatic::DCPTimePeriod);
+       void atmos (std::shared_ptr<const dcp::AtmosFrame>, dcpomatic::DCPTime, AtmosMetadata metadata);
+
+       Writer _writer;
+       J2KEncoder _j2k_encoder;
+       bool _finishing;
+       bool _non_burnt_subtitles;
+
+       boost::signals2::scoped_connection _player_video_connection;
+       boost::signals2::scoped_connection _player_audio_connection;
+       boost::signals2::scoped_connection _player_text_connection;
+       boost::signals2::scoped_connection _player_atmos_connection;
+};
index da5c7270e15be3c420529d0682d6870f44dd9a3f..68ee871f884c3f9338c1db7cf1108cd7548c058d 100644 (file)
@@ -37,6 +37,7 @@
 #include "image.h"
 #include "log.h"
 #include "player_video.h"
+#include "util.h"
 #include "variant.h"
 #include "version.h"
 #include <dcp/raw_convert.h>
index 9ce9e169128c0661dd6b28d2edb84ee620921ba7..143569e1603b3a1d17aefefd66e100974021f5e0 100644 (file)
@@ -26,6 +26,7 @@
 #include "encode_server_description.h"
 #include "encode_server_finder.h"
 #include "exceptions.h"
+#include "util.h"
 #include "variant.h"
 #include <dcp/raw_convert.h>
 #include <libcxml/cxml.h>
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
deleted file mode 100644 (file)
index 5268d86..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-/** @file  src/encoder.cc
- *  @brief A class which takes a Film and some Options, then uses those to encode the film
- *  into some output format.
- *
- *  A decoder is selected according to the content type, and the encoder can be specified
- *  as a parameter to the constructor.
- */
-
-
-#include "encoder.h"
-#include "player.h"
-
-#include "i18n.h"
-
-
-/** Construct an encoder.
- *  @param film Film that we are encoding.
- *  @param job Job that this encoder is being used in.
- */
-Encoder::Encoder (std::shared_ptr<const Film> film, std::weak_ptr<Job> job)
-       : _film (film)
-       , _job (job)
-       , _player(film, Image::Alignment::PADDED)
-{
-
-}
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
deleted file mode 100644 (file)
index aeaf7f6..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-    Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#ifndef DCPOMATIC_ENCODER_H
-#define DCPOMATIC_ENCODER_H
-
-
-#include "player.h"
-#include "player_text.h"
-#include <boost/signals2.hpp>
-
-
-class Film;
-class Encoder;
-class Player;
-class Job;
-class PlayerVideo;
-class AudioBuffers;
-
-
-/** @class Encoder
- *  @brief Parent class for something that can encode a film into some format
- */
-class Encoder
-{
-public:
-       Encoder (std::shared_ptr<const Film> film, std::weak_ptr<Job> job);
-       virtual ~Encoder () {}
-
-       Encoder (Encoder const&) = delete;
-       Encoder& operator= (Encoder const&) = delete;
-
-       virtual void go () = 0;
-
-       /** @return the current frame rate over the last short while */
-       virtual boost::optional<float> current_rate () const {
-               return {};
-       }
-
-       /** @return the number of frames that are done */
-       virtual Frame frames_done () const = 0;
-       virtual bool finishing () const = 0;
-       virtual void pause() {}
-       virtual void resume() {}
-
-protected:
-       std::shared_ptr<const Film> _film;
-       std::weak_ptr<Job> _job;
-       Player _player;
-};
-
-
-#endif
diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc
deleted file mode 100644 (file)
index 60241b2..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
-    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "butler.h"
-#include "cross.h"
-#include "ffmpeg_encoder.h"
-#include "film.h"
-#include "image.h"
-#include "job.h"
-#include "log.h"
-#include "player.h"
-#include "player_video.h"
-#include "compose.hpp"
-#include <iostream>
-
-#include "i18n.h"
-
-
-using std::cout;
-using std::list;
-using std::make_shared;
-using std::shared_ptr;
-using std::string;
-using std::weak_ptr;
-using boost::bind;
-using boost::optional;
-using namespace dcpomatic;
-#if BOOST_VERSION >= 106100
-using namespace boost::placeholders;
-#endif
-
-
-FFmpegEncoder::FFmpegEncoder (
-       shared_ptr<const Film> film,
-       weak_ptr<Job> job,
-       boost::filesystem::path output,
-       ExportFormat format,
-       bool mixdown_to_stereo,
-       bool split_reels,
-       bool audio_stream_per_channel,
-       int x264_crf
-       )
-       : Encoder (film, job)
-       , _output_audio_channels(mixdown_to_stereo ? 2 : (_film->audio_channels() > 8 ? 16 : _film->audio_channels()))
-       , _history (200)
-       , _output (output)
-       , _format (format)
-       , _split_reels (split_reels)
-       , _audio_stream_per_channel (audio_stream_per_channel)
-       , _x264_crf (x264_crf)
-       , _butler(
-               _film,
-               _player,
-               mixdown_to_stereo ? stereo_map() : many_channel_map(),
-               _output_audio_channels,
-               boost::bind(&PlayerVideo::force, FFmpegFileEncoder::pixel_format(format)),
-               VideoRange::VIDEO,
-               Image::Alignment::PADDED,
-               false,
-               false,
-               Butler::Audio::ENABLED
-               )
-{
-       _player.set_always_burn_open_subtitles();
-       _player.set_play_referenced();
-}
-
-
-AudioMapping
-FFmpegEncoder::stereo_map() const
-{
-       auto map = AudioMapping(_film->audio_channels(), 2);
-       float const overall_gain = 2 / (4 + sqrt(2));
-       float const minus_3dB = 1 / sqrt(2);
-       switch (_film->audio_channels()) {
-       case 2:
-               map.set(dcp::Channel::LEFT, 0, 1);
-               map.set(dcp::Channel::RIGHT, 1, 1);
-               break;
-       case 4:
-               map.set(dcp::Channel::LEFT,   0, overall_gain);
-               map.set(dcp::Channel::RIGHT,  1, overall_gain);
-               map.set(dcp::Channel::CENTRE, 0, overall_gain * minus_3dB);
-               map.set(dcp::Channel::CENTRE, 1, overall_gain * minus_3dB);
-               map.set(dcp::Channel::LS,     0, overall_gain);
-               break;
-       case 6:
-               map.set(dcp::Channel::LEFT,   0, overall_gain);
-               map.set(dcp::Channel::RIGHT,  1, overall_gain);
-               map.set(dcp::Channel::CENTRE, 0, overall_gain * minus_3dB);
-               map.set(dcp::Channel::CENTRE, 1, overall_gain * minus_3dB);
-               map.set(dcp::Channel::LS,     0, overall_gain);
-               map.set(dcp::Channel::RS,     1, overall_gain);
-               break;
-       }
-       /* XXX: maybe we should do something better for >6 channel DCPs */
-       return map;
-}
-
-
-AudioMapping
-FFmpegEncoder::many_channel_map() const
-{
-       auto map = AudioMapping(_film->audio_channels(), _output_audio_channels);
-       for (int i = 0; i < _film->audio_channels(); ++i) {
-               map.set(i, i, 1);
-       }
-       return map;
-}
-
-
-void
-FFmpegEncoder::go ()
-{
-       {
-               auto job = _job.lock ();
-               DCPOMATIC_ASSERT (job);
-               job->sub (_("Encoding"));
-       }
-
-       Waker waker;
-
-       list<FileEncoderSet> file_encoders;
-
-       int const files = _split_reels ? _film->reels().size() : 1;
-       for (int i = 0; i < files; ++i) {
-
-               boost::filesystem::path filename = _output;
-               auto extension = dcp::filesystem::extension(filename);
-               filename = dcp::filesystem::change_extension(filename, "");
-
-               if (files > 1) {
-                       /// TRANSLATORS: _reel%1 here is to be added to an export filename to indicate
-                       /// which reel it is.  Preserve the %1; it will be replaced with the reel number.
-                       filename = filename.string() + String::compose(_("_reel%1"), i + 1);
-               }
-
-               file_encoders.push_back (
-                       FileEncoderSet (
-                               _film->frame_size(),
-                               _film->video_frame_rate(),
-                               _film->audio_frame_rate(),
-                               _output_audio_channels,
-                               _format,
-                               _audio_stream_per_channel,
-                               _x264_crf,
-                               _film->three_d(),
-                               filename,
-                               extension
-                               )
-                       );
-       }
-
-       auto reel_periods = _film->reels ();
-       auto reel = reel_periods.begin ();
-       auto encoder = file_encoders.begin ();
-
-       auto const video_frame = DCPTime::from_frames (1, _film->video_frame_rate ());
-       int const audio_frames = video_frame.frames_round(_film->audio_frame_rate());
-       std::vector<float> interleaved(_output_audio_channels * audio_frames);
-       auto deinterleaved = make_shared<AudioBuffers>(_output_audio_channels, audio_frames);
-       int const gets_per_frame = _film->three_d() ? 2 : 1;
-       for (DCPTime time; time < _film->length(); time += video_frame) {
-
-               if (file_encoders.size() > 1 && !reel->contains(time)) {
-                       /* Next reel and file */
-                       ++reel;
-                       ++encoder;
-                       DCPOMATIC_ASSERT (reel != reel_periods.end());
-                       DCPOMATIC_ASSERT (encoder != file_encoders.end());
-               }
-
-               for (int j = 0; j < gets_per_frame; ++j) {
-                       Butler::Error e;
-                       auto video = _butler.get_video(Butler::Behaviour::BLOCKING, &e);
-                       _butler.rethrow();
-                       if (video.first) {
-                               auto fe = encoder->get(video.first->eyes());
-                               if (fe) {
-                                       fe->video(video.first, video.second - reel->from);
-                               }
-                       } else {
-                               if (e.code != Butler::Error::Code::FINISHED) {
-                                       throw DecodeError(String::compose("Error during decoding: %1", e.summary()));
-                               }
-                       }
-               }
-
-               _history.event ();
-
-               {
-                       boost::mutex::scoped_lock lm (_mutex);
-                       _last_time = time;
-               }
-
-               auto job = _job.lock ();
-               if (job) {
-                       job->set_progress(float(time.get()) / _film->length().get());
-               }
-
-               waker.nudge ();
-
-               _butler.get_audio(Butler::Behaviour::BLOCKING, interleaved.data(), audio_frames);
-               /* XXX: inefficient; butler interleaves and we deinterleave again */
-               float* p = interleaved.data();
-               for (int j = 0; j < audio_frames; ++j) {
-                       for (int k = 0; k < _output_audio_channels; ++k) {
-                               deinterleaved->data(k)[j] = *p++;
-                       }
-               }
-               encoder->audio (deinterleaved);
-       }
-
-       for (auto i: file_encoders) {
-               i.flush ();
-       }
-}
-
-optional<float>
-FFmpegEncoder::current_rate () const
-{
-       return _history.rate ();
-}
-
-Frame
-FFmpegEncoder::frames_done () const
-{
-       boost::mutex::scoped_lock lm (_mutex);
-       return _last_time.frames_round (_film->video_frame_rate ());
-}
-
-FFmpegEncoder::FileEncoderSet::FileEncoderSet (
-       dcp::Size video_frame_size,
-       int video_frame_rate,
-       int audio_frame_rate,
-       int channels,
-       ExportFormat format,
-       bool audio_stream_per_channel,
-       int x264_crf,
-       bool three_d,
-       boost::filesystem::path output,
-       string extension
-       )
-{
-       if (three_d) {
-               _encoders[Eyes::LEFT] = make_shared<FFmpegFileEncoder>(
-                       video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
-                       // TRANSLATORS: L here is an abbreviation for "left", to indicate the left-eye part of a 3D export
-                       audio_stream_per_channel, x264_crf, String::compose("%1_%2%3", output.string(), _("L"), extension)
-                       );
-               _encoders[Eyes::RIGHT] = make_shared<FFmpegFileEncoder>(
-                       video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
-                       // TRANSLATORS: R here is an abbreviation for "right", to indicate the right-eye part of a 3D export
-                       audio_stream_per_channel, x264_crf, String::compose("%1_%2%3", output.string(), _("R"), extension)
-                       );
-       } else {
-               _encoders[Eyes::BOTH] = make_shared<FFmpegFileEncoder>(
-                       video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
-                       audio_stream_per_channel, x264_crf, String::compose("%1%2", output.string(), extension)
-                       );
-       }
-}
-
-shared_ptr<FFmpegFileEncoder>
-FFmpegEncoder::FileEncoderSet::get (Eyes eyes) const
-{
-       if (_encoders.size() == 1) {
-               /* We are doing a 2D export... */
-               if (eyes == Eyes::LEFT) {
-                       /* ...but we got some 3D data; put the left eye into the output... */
-                       eyes = Eyes::BOTH;
-               } else if (eyes == Eyes::RIGHT) {
-                       /* ...and ignore the right eye.*/
-                       return {};
-               }
-       }
-
-       auto i = _encoders.find (eyes);
-       DCPOMATIC_ASSERT (i != _encoders.end());
-       return i->second;
-}
-
-void
-FFmpegEncoder::FileEncoderSet::flush ()
-{
-       for (auto& i: _encoders) {
-               i.second->flush ();
-       }
-}
-
-void
-FFmpegEncoder::FileEncoderSet::audio (shared_ptr<AudioBuffers> a)
-{
-       for (auto& i: _encoders) {
-               i.second->audio (a);
-       }
-}
diff --git a/src/lib/ffmpeg_encoder.h b/src/lib/ffmpeg_encoder.h
deleted file mode 100644 (file)
index 2d5c6af..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef DCPOMATIC_FFMPEG_ENCODER_H
-#define DCPOMATIC_FFMPEG_ENCODER_H
-
-#include "audio_mapping.h"
-#include "butler.h"
-#include "encoder.h"
-#include "event_history.h"
-#include "ffmpeg_file_encoder.h"
-
-
-class FFmpegEncoder : public Encoder
-{
-public:
-       FFmpegEncoder (
-               std::shared_ptr<const Film> film,
-               std::weak_ptr<Job> job,
-               boost::filesystem::path output,
-               ExportFormat format,
-               bool mixdown_to_stereo,
-               bool split_reels,
-               bool audio_stream_per_channel,
-               int x264_crf
-               );
-
-       void go () override;
-
-       boost::optional<float> current_rate () const override;
-       Frame frames_done () const override;
-       bool finishing () const override {
-               return false;
-       }
-
-private:
-
-       class FileEncoderSet
-       {
-       public:
-               FileEncoderSet (
-                       dcp::Size video_frame_size,
-                       int video_frame_rate,
-                       int audio_frame_rate,
-                       int channels,
-                       ExportFormat,
-                       bool audio_stream_per_channel,
-                       int x264_crf,
-                       bool three_d,
-                       boost::filesystem::path output,
-                       std::string extension
-                       );
-
-               std::shared_ptr<FFmpegFileEncoder> get (Eyes eyes) const;
-               void flush ();
-               void audio (std::shared_ptr<AudioBuffers>);
-
-       private:
-               std::map<Eyes, std::shared_ptr<FFmpegFileEncoder>> _encoders;
-       };
-
-       AudioMapping stereo_map() const;
-       AudioMapping many_channel_map() const;
-
-       int _output_audio_channels;
-
-       mutable boost::mutex _mutex;
-       dcpomatic::DCPTime _last_time;
-
-       EventHistory _history;
-
-       boost::filesystem::path _output;
-       ExportFormat _format;
-       bool _split_reels;
-       bool _audio_stream_per_channel;
-       int _x264_crf;
-
-       Butler _butler;
-};
-
-#endif
index d7833265d630d130437a5a3bedee49ac6f63f221..4547a8e8ef654d85e8c73dfe2bc780c265def6de 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "compose.hpp"
 #include "cross.h"
-#include "ffmpeg_encoder.h"
+#include "ffmpeg_file_encoder.h"
 #include "ffmpeg_wrapper.h"
 #include "film.h"
 #include "image.h"
index 78840d6a82ef9091de6f5b2baca8c1754dd7feea..907eca53df235587a8fdbe4e6348d79689140631 100644 (file)
 #define DCPOMATIC_FFMPEG_FILE_ENCODER_H
 
 
+#include "audio_buffers.h"
 #include "audio_mapping.h"
 #include "dcpomatic_time.h"
-#include "encoder.h"
 #include "event_history.h"
 #include "image_store.h"
 #include "log.h"
+#include "player_text.h"
+#include "player_video.h"
 #include <dcp/key.h>
 #include <dcp/warnings.h>
 LIBDCP_DISABLE_WARNINGS
diff --git a/src/lib/ffmpeg_film_encoder.cc b/src/lib/ffmpeg_film_encoder.cc
new file mode 100644 (file)
index 0000000..2d100f7
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "butler.h"
+#include "cross.h"
+#include "ffmpeg_film_encoder.h"
+#include "film.h"
+#include "image.h"
+#include "job.h"
+#include "log.h"
+#include "player.h"
+#include "player_video.h"
+#include "compose.hpp"
+#include <iostream>
+
+#include "i18n.h"
+
+
+using std::cout;
+using std::list;
+using std::make_shared;
+using std::shared_ptr;
+using std::string;
+using std::weak_ptr;
+using boost::bind;
+using boost::optional;
+using namespace dcpomatic;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
+
+
+FFmpegFilmEncoder::FFmpegFilmEncoder(
+       shared_ptr<const Film> film,
+       weak_ptr<Job> job,
+       boost::filesystem::path output,
+       ExportFormat format,
+       bool mixdown_to_stereo,
+       bool split_reels,
+       bool audio_stream_per_channel,
+       int x264_crf
+       )
+       : FilmEncoder(film, job)
+       , _output_audio_channels(mixdown_to_stereo ? 2 : (_film->audio_channels() > 8 ? 16 : _film->audio_channels()))
+       , _history (200)
+       , _output (output)
+       , _format (format)
+       , _split_reels (split_reels)
+       , _audio_stream_per_channel (audio_stream_per_channel)
+       , _x264_crf (x264_crf)
+       , _butler(
+               _film,
+               _player,
+               mixdown_to_stereo ? stereo_map() : many_channel_map(),
+               _output_audio_channels,
+               boost::bind(&PlayerVideo::force, FFmpegFileEncoder::pixel_format(format)),
+               VideoRange::VIDEO,
+               Image::Alignment::PADDED,
+               false,
+               false,
+               Butler::Audio::ENABLED
+               )
+{
+       _player.set_always_burn_open_subtitles();
+       _player.set_play_referenced();
+}
+
+
+AudioMapping
+FFmpegFilmEncoder::stereo_map() const
+{
+       auto map = AudioMapping(_film->audio_channels(), 2);
+       float const overall_gain = 2 / (4 + sqrt(2));
+       float const minus_3dB = 1 / sqrt(2);
+       switch (_film->audio_channels()) {
+       case 2:
+               map.set(dcp::Channel::LEFT, 0, 1);
+               map.set(dcp::Channel::RIGHT, 1, 1);
+               break;
+       case 4:
+               map.set(dcp::Channel::LEFT,   0, overall_gain);
+               map.set(dcp::Channel::RIGHT,  1, overall_gain);
+               map.set(dcp::Channel::CENTRE, 0, overall_gain * minus_3dB);
+               map.set(dcp::Channel::CENTRE, 1, overall_gain * minus_3dB);
+               map.set(dcp::Channel::LS,     0, overall_gain);
+               break;
+       case 6:
+               map.set(dcp::Channel::LEFT,   0, overall_gain);
+               map.set(dcp::Channel::RIGHT,  1, overall_gain);
+               map.set(dcp::Channel::CENTRE, 0, overall_gain * minus_3dB);
+               map.set(dcp::Channel::CENTRE, 1, overall_gain * minus_3dB);
+               map.set(dcp::Channel::LS,     0, overall_gain);
+               map.set(dcp::Channel::RS,     1, overall_gain);
+               break;
+       }
+       /* XXX: maybe we should do something better for >6 channel DCPs */
+       return map;
+}
+
+
+AudioMapping
+FFmpegFilmEncoder::many_channel_map() const
+{
+       auto map = AudioMapping(_film->audio_channels(), _output_audio_channels);
+       for (int i = 0; i < _film->audio_channels(); ++i) {
+               map.set(i, i, 1);
+       }
+       return map;
+}
+
+
+void
+FFmpegFilmEncoder::go()
+{
+       {
+               auto job = _job.lock ();
+               DCPOMATIC_ASSERT (job);
+               job->sub (_("Encoding"));
+       }
+
+       Waker waker;
+
+       list<FileEncoderSet> file_encoders;
+
+       int const files = _split_reels ? _film->reels().size() : 1;
+       for (int i = 0; i < files; ++i) {
+
+               boost::filesystem::path filename = _output;
+               auto extension = dcp::filesystem::extension(filename);
+               filename = dcp::filesystem::change_extension(filename, "");
+
+               if (files > 1) {
+                       /// TRANSLATORS: _reel%1 here is to be added to an export filename to indicate
+                       /// which reel it is.  Preserve the %1; it will be replaced with the reel number.
+                       filename = filename.string() + String::compose(_("_reel%1"), i + 1);
+               }
+
+               file_encoders.push_back (
+                       FileEncoderSet (
+                               _film->frame_size(),
+                               _film->video_frame_rate(),
+                               _film->audio_frame_rate(),
+                               _output_audio_channels,
+                               _format,
+                               _audio_stream_per_channel,
+                               _x264_crf,
+                               _film->three_d(),
+                               filename,
+                               extension
+                               )
+                       );
+       }
+
+       auto reel_periods = _film->reels ();
+       auto reel = reel_periods.begin ();
+       auto encoder = file_encoders.begin ();
+
+       auto const video_frame = DCPTime::from_frames (1, _film->video_frame_rate ());
+       int const audio_frames = video_frame.frames_round(_film->audio_frame_rate());
+       std::vector<float> interleaved(_output_audio_channels * audio_frames);
+       auto deinterleaved = make_shared<AudioBuffers>(_output_audio_channels, audio_frames);
+       int const gets_per_frame = _film->three_d() ? 2 : 1;
+       for (DCPTime time; time < _film->length(); time += video_frame) {
+
+               if (file_encoders.size() > 1 && !reel->contains(time)) {
+                       /* Next reel and file */
+                       ++reel;
+                       ++encoder;
+                       DCPOMATIC_ASSERT (reel != reel_periods.end());
+                       DCPOMATIC_ASSERT (encoder != file_encoders.end());
+               }
+
+               for (int j = 0; j < gets_per_frame; ++j) {
+                       Butler::Error e;
+                       auto video = _butler.get_video(Butler::Behaviour::BLOCKING, &e);
+                       _butler.rethrow();
+                       if (video.first) {
+                               auto fe = encoder->get(video.first->eyes());
+                               if (fe) {
+                                       fe->video(video.first, video.second - reel->from);
+                               }
+                       } else {
+                               if (e.code != Butler::Error::Code::FINISHED) {
+                                       throw DecodeError(String::compose("Error during decoding: %1", e.summary()));
+                               }
+                       }
+               }
+
+               _history.event ();
+
+               {
+                       boost::mutex::scoped_lock lm (_mutex);
+                       _last_time = time;
+               }
+
+               auto job = _job.lock ();
+               if (job) {
+                       job->set_progress(float(time.get()) / _film->length().get());
+               }
+
+               waker.nudge ();
+
+               _butler.get_audio(Butler::Behaviour::BLOCKING, interleaved.data(), audio_frames);
+               /* XXX: inefficient; butler interleaves and we deinterleave again */
+               float* p = interleaved.data();
+               for (int j = 0; j < audio_frames; ++j) {
+                       for (int k = 0; k < _output_audio_channels; ++k) {
+                               deinterleaved->data(k)[j] = *p++;
+                       }
+               }
+               encoder->audio (deinterleaved);
+       }
+
+       for (auto i: file_encoders) {
+               i.flush ();
+       }
+}
+
+optional<float>
+FFmpegFilmEncoder::current_rate() const
+{
+       return _history.rate ();
+}
+
+Frame
+FFmpegFilmEncoder::frames_done() const
+{
+       boost::mutex::scoped_lock lm (_mutex);
+       return _last_time.frames_round (_film->video_frame_rate ());
+}
+
+FFmpegFilmEncoder::FileEncoderSet::FileEncoderSet(
+       dcp::Size video_frame_size,
+       int video_frame_rate,
+       int audio_frame_rate,
+       int channels,
+       ExportFormat format,
+       bool audio_stream_per_channel,
+       int x264_crf,
+       bool three_d,
+       boost::filesystem::path output,
+       string extension
+       )
+{
+       if (three_d) {
+               _encoders[Eyes::LEFT] = make_shared<FFmpegFileEncoder>(
+                       video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
+                       // TRANSLATORS: L here is an abbreviation for "left", to indicate the left-eye part of a 3D export
+                       audio_stream_per_channel, x264_crf, String::compose("%1_%2%3", output.string(), _("L"), extension)
+                       );
+               _encoders[Eyes::RIGHT] = make_shared<FFmpegFileEncoder>(
+                       video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
+                       // TRANSLATORS: R here is an abbreviation for "right", to indicate the right-eye part of a 3D export
+                       audio_stream_per_channel, x264_crf, String::compose("%1_%2%3", output.string(), _("R"), extension)
+                       );
+       } else {
+               _encoders[Eyes::BOTH] = make_shared<FFmpegFileEncoder>(
+                       video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
+                       audio_stream_per_channel, x264_crf, String::compose("%1%2", output.string(), extension)
+                       );
+       }
+}
+
+shared_ptr<FFmpegFileEncoder>
+FFmpegFilmEncoder::FileEncoderSet::get(Eyes eyes) const
+{
+       if (_encoders.size() == 1) {
+               /* We are doing a 2D export... */
+               if (eyes == Eyes::LEFT) {
+                       /* ...but we got some 3D data; put the left eye into the output... */
+                       eyes = Eyes::BOTH;
+               } else if (eyes == Eyes::RIGHT) {
+                       /* ...and ignore the right eye.*/
+                       return {};
+               }
+       }
+
+       auto i = _encoders.find (eyes);
+       DCPOMATIC_ASSERT (i != _encoders.end());
+       return i->second;
+}
+
+void
+FFmpegFilmEncoder::FileEncoderSet::flush()
+{
+       for (auto& i: _encoders) {
+               i.second->flush ();
+       }
+}
+
+void
+FFmpegFilmEncoder::FileEncoderSet::audio(shared_ptr<AudioBuffers> a)
+{
+       for (auto& i: _encoders) {
+               i.second->audio (a);
+       }
+}
diff --git a/src/lib/ffmpeg_film_encoder.h b/src/lib/ffmpeg_film_encoder.h
new file mode 100644 (file)
index 0000000..ec6bb45
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_FFMPEG_ENCODER_H
+#define DCPOMATIC_FFMPEG_ENCODER_H
+
+#include "audio_mapping.h"
+#include "butler.h"
+#include "event_history.h"
+#include "ffmpeg_file_encoder.h"
+#include "film_encoder.h"
+
+
+class FFmpegFilmEncoder : public FilmEncoder
+{
+public:
+       FFmpegFilmEncoder(
+               std::shared_ptr<const Film> film,
+               std::weak_ptr<Job> job,
+               boost::filesystem::path output,
+               ExportFormat format,
+               bool mixdown_to_stereo,
+               bool split_reels,
+               bool audio_stream_per_channel,
+               int x264_crf
+               );
+
+       void go () override;
+
+       boost::optional<float> current_rate () const override;
+       Frame frames_done () const override;
+       bool finishing () const override {
+               return false;
+       }
+
+private:
+
+       class FileEncoderSet
+       {
+       public:
+               FileEncoderSet (
+                       dcp::Size video_frame_size,
+                       int video_frame_rate,
+                       int audio_frame_rate,
+                       int channels,
+                       ExportFormat,
+                       bool audio_stream_per_channel,
+                       int x264_crf,
+                       bool three_d,
+                       boost::filesystem::path output,
+                       std::string extension
+                       );
+
+               std::shared_ptr<FFmpegFileEncoder> get (Eyes eyes) const;
+               void flush ();
+               void audio (std::shared_ptr<AudioBuffers>);
+
+       private:
+               std::map<Eyes, std::shared_ptr<FFmpegFileEncoder>> _encoders;
+       };
+
+       AudioMapping stereo_map() const;
+       AudioMapping many_channel_map() const;
+
+       int _output_audio_channels;
+
+       mutable boost::mutex _mutex;
+       dcpomatic::DCPTime _last_time;
+
+       EventHistory _history;
+
+       boost::filesystem::path _output;
+       ExportFormat _format;
+       bool _split_reels;
+       bool _audio_stream_per_channel;
+       int _x264_crf;
+
+       Butler _butler;
+};
+
+#endif
index 540d0b9b947af55e80b89183703c44845e763f05..fd703a72a348380f6ae6ea32e7d03224ce28dd68 100644 (file)
@@ -36,7 +36,7 @@
 #include "cross.h"
 #include "dcp_content.h"
 #include "dcp_content_type.h"
-#include "dcp_encoder.h"
+#include "dcp_film_encoder.h"
 #include "dcpomatic_log.h"
 #include "digester.h"
 #include "environment_info.h"
diff --git a/src/lib/film_encoder.cc b/src/lib/film_encoder.cc
new file mode 100644 (file)
index 0000000..05b911d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+/** @file  src/film_encoder.cc
+ *  @brief A class which takes a Film and some Options, then uses those to encode the film
+ *  into some output format.
+ *
+ *  A decoder is selected according to the content type, and the encoder can be specified
+ *  as a parameter to the constructor.
+ */
+
+
+#include "film_encoder.h"
+#include "player.h"
+
+#include "i18n.h"
+
+
+/** Construct a FilmEncoder.
+ *  @param film Film that we are encoding.
+ *  @param job Job that this encoder is being used in.
+ */
+FilmEncoder::FilmEncoder(std::shared_ptr<const Film> film, std::weak_ptr<Job> job)
+       : _film (film)
+       , _job (job)
+       , _player(film, Image::Alignment::PADDED)
+{
+
+}
diff --git a/src/lib/film_encoder.h b/src/lib/film_encoder.h
new file mode 100644 (file)
index 0000000..ed7626c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+    Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef DCPOMATIC_FILM_ENCODER_H
+#define DCPOMATIC_FILM_ENCODER_H
+
+
+#include "player.h"
+#include "player_text.h"
+#include <boost/signals2.hpp>
+
+
+class Film;
+class Player;
+class Job;
+class PlayerVideo;
+class AudioBuffers;
+
+
+/** @class FilmEncoder
+ *  @brief Parent class for something that can encode a film into some format
+ */
+class FilmEncoder
+{
+public:
+       FilmEncoder(std::shared_ptr<const Film> film, std::weak_ptr<Job> job);
+       virtual ~FilmEncoder() {}
+
+       FilmEncoder(FilmEncoder const&) = delete;
+       FilmEncoder& operator=(FilmEncoder const&) = delete;
+
+       virtual void go () = 0;
+
+       /** @return the current frame rate over the last short while */
+       virtual boost::optional<float> current_rate () const {
+               return {};
+       }
+
+       /** @return the number of frames that are done */
+       virtual Frame frames_done () const = 0;
+       virtual bool finishing () const = 0;
+       virtual void pause() {}
+       virtual void resume() {}
+
+protected:
+       std::shared_ptr<const Film> _film;
+       std::weak_ptr<Job> _job;
+       Player _player;
+};
+
+
+#endif
index 0d65edc218bad3455467a24fc1448eb50592bbdd..e7a6646ef64a7f69269d2cc1a607cfd150ddfcb5 100644 (file)
 
 
 #include "audio_analyser.h"
-#include "signaller.h"
-#include "player_text.h"
 #include "dcp_text_track.h"
 #include "dcpomatic_time.h"
+#include "player_text.h"
+#include "signaller.h"
+#include "text_type.h"
 #include "weak_film.h"
-#include <boost/signals2.hpp>
 #include <boost/atomic.hpp>
-#include <vector>
+#include <boost/signals2.hpp>
 #include <string>
+#include <vector>
 
 
 class Film;
index ddd231243b7d83f744ae2966111d15255c7a6989..41c5e8ec55402b51d0613ee7d77f775c1a1ea65f 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "config.h"
 #include "dcp_content.h"
-#include "dcp_encoder.h"
+#include "dcp_film_encoder.h"
 #include "dcp_transcode_job.h"
 #include "dcpomatic_log.h"
 #include "environment_info.h"
@@ -94,7 +94,7 @@ make_dcp (shared_ptr<Film> film, TranscodeJob::ChangedBehaviour behaviour)
        LOG_GENERAL ("J2K bandwidth %1", film->j2k_bandwidth());
 
        auto tj = make_shared<DCPTranscodeJob>(film, behaviour);
-       tj->set_encoder (make_shared<DCPEncoder>(film, tj));
+       tj->set_encoder(make_shared<DCPFilmEncoder>(film, tj));
        JobManager::instance()->add (tj);
 
        return tj;
index 0886482a817b98685ebec80749cd195a642256af..6f47c6740cc442a32e3cab4bcce6987a92139e0c 100644 (file)
@@ -27,6 +27,7 @@
 #include "player_text.h"
 #include "referenced_reel_asset.h"
 #include "render_text.h"
+#include "text_type.h"
 #include "weak_film.h"
 #include <dcp/atmos_asset_writer.h>
 #include <dcp/file.h>
diff --git a/src/lib/subtitle_encoder.cc b/src/lib/subtitle_encoder.cc
deleted file mode 100644 (file)
index 8b1d9a1..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
-    Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "compose.hpp"
-#include "film.h"
-#include "job.h"
-#include "player.h"
-#include "subtitle_encoder.h"
-#include <dcp/filesystem.h>
-#include <dcp/interop_subtitle_asset.h>
-#include <dcp/raw_convert.h>
-#include <dcp/smpte_subtitle_asset.h>
-#include <boost/filesystem.hpp>
-#include <boost/bind/bind.hpp>
-
-#include "i18n.h"
-
-
-using std::make_pair;
-using std::make_shared;
-using std::pair;
-using std::shared_ptr;
-using std::string;
-using std::vector;
-using boost::optional;
-#if BOOST_VERSION >= 106100
-using namespace boost::placeholders;
-#endif
-using dcp::raw_convert;
-
-
-/** @param output Directory, if there will be multiple output files, or a filename.
- *  @param initial_name Hint that may be used to create filenames, if @ref output is a directory.
- *  @param include_font true to refer to and export any font file (for Interop; ignored for SMPTE).
- */
-SubtitleEncoder::SubtitleEncoder (shared_ptr<const Film> film, shared_ptr<Job> job, boost::filesystem::path output, string initial_name, bool split_reels, bool include_font)
-       : Encoder (film, job)
-       , _split_reels (split_reels)
-       , _include_font (include_font)
-       , _reel_index (0)
-       , _length (film->length())
-{
-       _player.set_play_referenced();
-       _player.set_ignore_video();
-       _player.set_ignore_audio();
-       _player.Text.connect(boost::bind(&SubtitleEncoder::text, this, _1, _2, _3, _4));
-
-       string const extension = film->interop() ? ".xml" : ".mxf";
-
-       int const files = split_reels ? film->reels().size() : 1;
-       for (int i = 0; i < files; ++i) {
-
-               boost::filesystem::path filename = output;
-               if (dcp::filesystem::is_directory(filename)) {
-                       if (files > 1) {
-                               /// TRANSLATORS: _reel%1 here is to be added to an export filename to indicate
-                               /// which reel it is.  Preserve the %1; it will be replaced with the reel number.
-                               filename /= String::compose("%1_reel%2", initial_name, i + 1);
-                       } else {
-                               filename /= initial_name;
-                       }
-               }
-
-               _assets.push_back(make_pair(shared_ptr<dcp::SubtitleAsset>(), dcp::filesystem::change_extension(filename, extension)));
-       }
-
-       for (auto i: film->reels()) {
-               _reels.push_back (i);
-       }
-
-       _default_font = dcp::ArrayData (default_font_file());
-}
-
-
-void
-SubtitleEncoder::go ()
-{
-       {
-               shared_ptr<Job> job = _job.lock ();
-               DCPOMATIC_ASSERT (job);
-               job->sub (_("Extracting"));
-       }
-
-       _reel_index = 0;
-
-       while (!_player.pass()) {}
-
-       int reel = 0;
-       for (auto& i: _assets) {
-               if (!i.first) {
-                       /* No subtitles arrived for this asset; make an empty one so we write something to the output */
-                       if (_film->interop()) {
-                               auto s = make_shared<dcp::InteropSubtitleAsset>();
-                               s->set_movie_title (_film->name());
-                               s->set_reel_number (raw_convert<string>(reel + 1));
-                               i.first = s;
-                       } else {
-                               auto s = make_shared<dcp::SMPTESubtitleAsset>();
-                               s->set_content_title_text (_film->name());
-                               s->set_reel_number (reel + 1);
-                               i.first = s;
-                       }
-               }
-
-               if (!_film->interop() || _include_font) {
-                       for (auto j: _player.get_subtitle_fonts()) {
-                               i.first->add_font(j->id(), j->data().get_value_or(_default_font));
-                       }
-               }
-
-               i.first->write (i.second);
-               ++reel;
-       }
-}
-
-
-void
-SubtitleEncoder::text (PlayerText subs, TextType type, optional<DCPTextTrack> track, dcpomatic::DCPTimePeriod period)
-{
-       if (type != TextType::OPEN_SUBTITLE) {
-               return;
-       }
-
-       if (!_assets[_reel_index].first) {
-               shared_ptr<dcp::SubtitleAsset> asset;
-               auto lang = _film->subtitle_languages ();
-               if (_film->interop ()) {
-                       auto s = make_shared<dcp::InteropSubtitleAsset>();
-                       s->set_movie_title (_film->name());
-                       if (lang.first) {
-                               s->set_language (lang.first->to_string());
-                       }
-                       s->set_reel_number (raw_convert<string>(_reel_index + 1));
-                       _assets[_reel_index].first = s;
-               } else {
-                       auto s = make_shared<dcp::SMPTESubtitleAsset>();
-                       s->set_content_title_text (_film->name());
-                       if (lang.first) {
-                               s->set_language (*lang.first);
-                       } else if (track->language) {
-                               s->set_language (track->language.get());
-                       }
-                       s->set_edit_rate (dcp::Fraction (_film->video_frame_rate(), 1));
-                       s->set_reel_number (_reel_index + 1);
-                       s->set_time_code_rate (_film->video_frame_rate());
-                       s->set_start_time (dcp::Time());
-                       if (_film->encrypted ()) {
-                               s->set_key (_film->key ());
-                       }
-                       _assets[_reel_index].first = s;
-               }
-       }
-
-       for (auto i: subs.string) {
-               /* XXX: couldn't / shouldn't we use period here rather than getting time from the subtitle? */
-               i.set_in  (i.in());
-               i.set_out (i.out());
-               if (_film->interop() && !_include_font) {
-                       i.unset_font ();
-               }
-               _assets[_reel_index].first->add (make_shared<dcp::SubtitleString>(i));
-       }
-
-       if (_split_reels && (_reel_index < int(_reels.size()) - 1) && period.from > _reels[_reel_index].from) {
-               ++_reel_index;
-       }
-
-       _last = period.from;
-
-       auto job = _job.lock ();
-       if (job) {
-               job->set_progress (float(period.from.get()) / _length.get());
-       }
-}
-
-
-Frame
-SubtitleEncoder::frames_done () const
-{
-       if (!_last) {
-               return 0;
-       }
-
-       /* XXX: assuming 24fps here but I don't think it matters */
-       return _last->seconds() * 24;
-}
diff --git a/src/lib/subtitle_encoder.h b/src/lib/subtitle_encoder.h
deleted file mode 100644 (file)
index 0815b1f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-    Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "dcp_text_track.h"
-#include "dcpomatic_time.h"
-#include "encoder.h"
-#include "player_text.h"
-
-
-namespace dcp {
-       class SubtitleAsset;
-}
-
-
-class Film;
-
-
-/** @class SubtitleEncoder.
- *  @brief An `encoder' which extracts a film's subtitles to DCP XML format.
- */
-class SubtitleEncoder : public Encoder
-{
-public:
-       SubtitleEncoder (std::shared_ptr<const Film> film, std::shared_ptr<Job> job, boost::filesystem::path output, std::string initial_name, bool split_reels, bool include_font);
-
-       void go () override;
-
-       /** @return the number of frames that are done */
-       Frame frames_done () const override;
-
-       bool finishing () const override {
-               return false;
-       }
-
-private:
-       void text (PlayerText subs, TextType type, boost::optional<DCPTextTrack> track, dcpomatic::DCPTimePeriod period);
-
-       std::vector<std::pair<std::shared_ptr<dcp::SubtitleAsset>, boost::filesystem::path>> _assets;
-       std::vector<dcpomatic::DCPTimePeriod> _reels;
-       bool _split_reels;
-       bool _include_font;
-       int _reel_index;
-       boost::optional<dcpomatic::DCPTime> _last;
-       dcpomatic::DCPTime _length;
-       dcp::ArrayData _default_font;
-};
diff --git a/src/lib/subtitle_film_encoder.cc b/src/lib/subtitle_film_encoder.cc
new file mode 100644 (file)
index 0000000..93ccc17
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+    Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "compose.hpp"
+#include "film.h"
+#include "job.h"
+#include "player.h"
+#include "subtitle_film_encoder.h"
+#include <dcp/filesystem.h>
+#include <dcp/interop_subtitle_asset.h>
+#include <dcp/raw_convert.h>
+#include <dcp/smpte_subtitle_asset.h>
+#include <boost/filesystem.hpp>
+#include <boost/bind/bind.hpp>
+
+#include "i18n.h"
+
+
+using std::make_pair;
+using std::make_shared;
+using std::pair;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+using boost::optional;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
+using dcp::raw_convert;
+
+
+/** @param output Directory, if there will be multiple output files, or a filename.
+ *  @param initial_name Hint that may be used to create filenames, if @ref output is a directory.
+ *  @param include_font true to refer to and export any font file (for Interop; ignored for SMPTE).
+ */
+SubtitleFilmEncoder::SubtitleFilmEncoder(shared_ptr<const Film> film, shared_ptr<Job> job, boost::filesystem::path output, string initial_name, bool split_reels, bool include_font)
+       : FilmEncoder(film, job)
+       , _split_reels (split_reels)
+       , _include_font (include_font)
+       , _reel_index (0)
+       , _length (film->length())
+{
+       _player.set_play_referenced();
+       _player.set_ignore_video();
+       _player.set_ignore_audio();
+       _player.Text.connect(boost::bind(&SubtitleFilmEncoder::text, this, _1, _2, _3, _4));
+
+       string const extension = film->interop() ? ".xml" : ".mxf";
+
+       int const files = split_reels ? film->reels().size() : 1;
+       for (int i = 0; i < files; ++i) {
+
+               boost::filesystem::path filename = output;
+               if (dcp::filesystem::is_directory(filename)) {
+                       if (files > 1) {
+                               /// TRANSLATORS: _reel%1 here is to be added to an export filename to indicate
+                               /// which reel it is.  Preserve the %1; it will be replaced with the reel number.
+                               filename /= String::compose("%1_reel%2", initial_name, i + 1);
+                       } else {
+                               filename /= initial_name;
+                       }
+               }
+
+               _assets.push_back(make_pair(shared_ptr<dcp::SubtitleAsset>(), dcp::filesystem::change_extension(filename, extension)));
+       }
+
+       for (auto i: film->reels()) {
+               _reels.push_back (i);
+       }
+
+       _default_font = dcp::ArrayData (default_font_file());
+}
+
+
+void
+SubtitleFilmEncoder::go()
+{
+       {
+               shared_ptr<Job> job = _job.lock ();
+               DCPOMATIC_ASSERT (job);
+               job->sub (_("Extracting"));
+       }
+
+       _reel_index = 0;
+
+       while (!_player.pass()) {}
+
+       int reel = 0;
+       for (auto& i: _assets) {
+               if (!i.first) {
+                       /* No subtitles arrived for this asset; make an empty one so we write something to the output */
+                       if (_film->interop()) {
+                               auto s = make_shared<dcp::InteropSubtitleAsset>();
+                               s->set_movie_title (_film->name());
+                               s->set_reel_number (raw_convert<string>(reel + 1));
+                               i.first = s;
+                       } else {
+                               auto s = make_shared<dcp::SMPTESubtitleAsset>();
+                               s->set_content_title_text (_film->name());
+                               s->set_reel_number (reel + 1);
+                               i.first = s;
+                       }
+               }
+
+               if (!_film->interop() || _include_font) {
+                       for (auto j: _player.get_subtitle_fonts()) {
+                               i.first->add_font(j->id(), j->data().get_value_or(_default_font));
+                       }
+               }
+
+               i.first->write (i.second);
+               ++reel;
+       }
+}
+
+
+void
+SubtitleFilmEncoder::text(PlayerText subs, TextType type, optional<DCPTextTrack> track, dcpomatic::DCPTimePeriod period)
+{
+       if (type != TextType::OPEN_SUBTITLE) {
+               return;
+       }
+
+       if (!_assets[_reel_index].first) {
+               shared_ptr<dcp::SubtitleAsset> asset;
+               auto lang = _film->subtitle_languages ();
+               if (_film->interop ()) {
+                       auto s = make_shared<dcp::InteropSubtitleAsset>();
+                       s->set_movie_title (_film->name());
+                       if (lang.first) {
+                               s->set_language (lang.first->to_string());
+                       }
+                       s->set_reel_number (raw_convert<string>(_reel_index + 1));
+                       _assets[_reel_index].first = s;
+               } else {
+                       auto s = make_shared<dcp::SMPTESubtitleAsset>();
+                       s->set_content_title_text (_film->name());
+                       if (lang.first) {
+                               s->set_language (*lang.first);
+                       } else if (track->language) {
+                               s->set_language (track->language.get());
+                       }
+                       s->set_edit_rate (dcp::Fraction (_film->video_frame_rate(), 1));
+                       s->set_reel_number (_reel_index + 1);
+                       s->set_time_code_rate (_film->video_frame_rate());
+                       s->set_start_time (dcp::Time());
+                       if (_film->encrypted ()) {
+                               s->set_key (_film->key ());
+                       }
+                       _assets[_reel_index].first = s;
+               }
+       }
+
+       for (auto i: subs.string) {
+               /* XXX: couldn't / shouldn't we use period here rather than getting time from the subtitle? */
+               i.set_in  (i.in());
+               i.set_out (i.out());
+               if (_film->interop() && !_include_font) {
+                       i.unset_font ();
+               }
+               _assets[_reel_index].first->add (make_shared<dcp::SubtitleString>(i));
+       }
+
+       if (_split_reels && (_reel_index < int(_reels.size()) - 1) && period.from > _reels[_reel_index].from) {
+               ++_reel_index;
+       }
+
+       _last = period.from;
+
+       auto job = _job.lock ();
+       if (job) {
+               job->set_progress (float(period.from.get()) / _length.get());
+       }
+}
+
+
+Frame
+SubtitleFilmEncoder::frames_done() const
+{
+       if (!_last) {
+               return 0;
+       }
+
+       /* XXX: assuming 24fps here but I don't think it matters */
+       return _last->seconds() * 24;
+}
diff --git a/src/lib/subtitle_film_encoder.h b/src/lib/subtitle_film_encoder.h
new file mode 100644 (file)
index 0000000..5423179
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+    Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "dcp_text_track.h"
+#include "dcpomatic_time.h"
+#include "film_encoder.h"
+#include "player_text.h"
+
+
+namespace dcp {
+       class SubtitleAsset;
+}
+
+
+class Film;
+
+
+/** @class SubtitleFilmEncoder.
+ *  @brief An `encoder' which extracts a film's subtitles to DCP XML format.
+ */
+class SubtitleFilmEncoder : public FilmEncoder
+{
+public:
+       SubtitleFilmEncoder(std::shared_ptr<const Film> film, std::shared_ptr<Job> job, boost::filesystem::path output, std::string initial_name, bool split_reels, bool include_font);
+
+       void go () override;
+
+       /** @return the number of frames that are done */
+       Frame frames_done () const override;
+
+       bool finishing () const override {
+               return false;
+       }
+
+private:
+       void text (PlayerText subs, TextType type, boost::optional<DCPTextTrack> track, dcpomatic::DCPTimePeriod period);
+
+       std::vector<std::pair<std::shared_ptr<dcp::SubtitleAsset>, boost::filesystem::path>> _assets;
+       std::vector<dcpomatic::DCPTimePeriod> _reels;
+       bool _split_reels;
+       bool _include_font;
+       int _reel_index;
+       boost::optional<dcpomatic::DCPTime> _last;
+       dcpomatic::DCPTime _length;
+       dcp::ArrayData _default_font;
+};
index ba420ab94f466a8aff684f55dc110c019a13edc4..98c6784a9bbdaadbb7c82f0901ec2e2bb6f01f94 100644 (file)
 #include "compose.hpp"
 #include "content.h"
 #include "config.h"
-#include "dcp_encoder.h"
+#include "dcp_film_encoder.h"
 #include "dcpomatic_log.h"
-#include "encoder.h"
 #include "examine_content_job.h"
 #include "film.h"
+#include "film_encoder.h"
 #include "job_manager.h"
 #include "log.h"
 #include "transcode_job.h"
@@ -84,7 +84,7 @@ TranscodeJob::json_name () const
 
 
 void
-TranscodeJob::set_encoder (shared_ptr<Encoder> e)
+TranscodeJob::set_encoder(shared_ptr<FilmEncoder> e)
 {
        _encoder = e;
 }
@@ -133,7 +133,7 @@ TranscodeJob::run ()
 
                LOG_GENERAL(N_("Transcode job completed successfully: %1 fps"), dcp::locale_convert<string>(frames_per_second(), 2, true));
 
-               if (dynamic_pointer_cast<DCPEncoder>(_encoder)) {
+               if (dynamic_pointer_cast<DCPFilmEncoder>(_encoder)) {
                        try {
                                Analytics::instance()->successful_dcp_encode();
                        } catch (FileError& e) {
index 35870231d5af1f592861c05158f57ea8b49debda..720d7f99bfa7faaeacbf1e8f143952353f813308 100644 (file)
@@ -35,7 +35,7 @@
 #undef IGNORE
 
 
-class Encoder;
+class FilmEncoder;
 
 struct frames_not_lost_when_threads_disappear;
 
@@ -65,7 +65,7 @@ public:
                return true;
        }
 
-       void set_encoder (std::shared_ptr<Encoder> t);
+       void set_encoder(std::shared_ptr<FilmEncoder> encoder);
 
 private:
        friend struct ::frames_not_lost_when_threads_disappear;
@@ -75,7 +75,7 @@ private:
 
        int remaining_time () const override;
 
-       std::shared_ptr<Encoder> _encoder;
+       std::shared_ptr<FilmEncoder> _encoder;
        ChangedBehaviour _changed;
 };
 
index 4eeeb578ed934dccd9c17a1579ee81a38798c728..5e49b1fbf9f25a13bdb568b163ef55fb0e8008ae 100644 (file)
@@ -68,9 +68,9 @@ sources = """
           dcp_content.cc
           dcp_content_type.cc
           dcp_decoder.cc
-          dcp_encoder.cc
           dcp_examiner.cc
           dcp_digest_file.cc
+          dcp_film_encoder.cc
           dcp_subtitle.cc
           dcp_subtitle_content.cc
           dcp_subtitle_decoder.cc
@@ -89,7 +89,6 @@ sources = """
           dolby_cp750.cc
           email.cc
           empty.cc
-          encoder.cc
           encode_server.cc
           encode_server_finder.cc
           encoded_log_entry.cc
@@ -107,14 +106,15 @@ sources = """
           ffmpeg_audio_stream.cc
           ffmpeg_content.cc
           ffmpeg_decoder.cc
-          ffmpeg_encoder.cc
           ffmpeg_examiner.cc
           ffmpeg_file_encoder.cc
+          ffmpeg_film_encoder.cc
           ffmpeg_image_proxy.cc
           ffmpeg_stream.cc
           ffmpeg_subtitle_stream.cc
           ffmpeg_wrapper.cc
           film.cc
+          film_encoder.cc
           film_util.cc
           filter.cc
           font.cc
@@ -187,7 +187,7 @@ sources = """
           string_text_file_content.cc
           string_text_file_decoder.cc
           subtitle_analysis.cc
-          subtitle_encoder.cc
+          subtitle_film_encoder.cc
           territory_type.cc
           text_ring_buffers.cc
           text_type.cc
index 5f723ba0f89940d19f7b65a2ef3dfe66bf340b0a..de4ddebc2b20eeaeb69841b20a941b605addaf67 100644 (file)
@@ -76,7 +76,7 @@
 #include "lib/email.h"
 #include "lib/encode_server_finder.h"
 #include "lib/exceptions.h"
-#include "lib/ffmpeg_encoder.h"
+#include "lib/ffmpeg_film_encoder.h"
 #include "lib/film.h"
 #include "lib/font_config.h"
 #ifdef DCPOMATIC_GROK
@@ -91,7 +91,7 @@
 #include "lib/screen.h"
 #include "lib/send_kdm_email_job.h"
 #include "lib/signal_manager.h"
-#include "lib/subtitle_encoder.h"
+#include "lib/subtitle_film_encoder.h"
 #include "lib/text_content.h"
 #include "lib/transcode_job.h"
 #include "lib/update_checker.h"
@@ -1029,7 +1029,7 @@ private:
 
                auto job = make_shared<TranscodeJob>(_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
                job->set_encoder (
-                       make_shared<FFmpegEncoder> (
+                       make_shared<FFmpegFilmEncoder>(
                                _film, job, dialog.path(), dialog.format(), dialog.mixdown_to_stereo(), dialog.split_reels(), dialog.split_streams(), dialog.x264_crf())
                        );
                JobManager::instance()->add (job);
@@ -1044,7 +1044,7 @@ private:
                }
                auto job = make_shared<TranscodeJob>(_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
                job->set_encoder(
-                       make_shared<SubtitleEncoder>(_film, job, dialog.path(), _film->isdcf_name(true), dialog.split_reels(), dialog.include_font())
+                       make_shared<SubtitleFilmEncoder>(_film, job, dialog.path(), _film->isdcf_name(true), dialog.split_reels(), dialog.include_font())
                        );
                JobManager::instance()->add(job);
        }
index c087f89e796d03b1f77fe0af123005670c8a35d8..9eec498f975d72d2dad73552cd2987c3d8fa71f4 100644 (file)
@@ -25,7 +25,7 @@
 #include "lib/cross.h"
 #include "lib/dcpomatic_log.h"
 #include "lib/encode_server_finder.h"
-#include "lib/ffmpeg_encoder.h"
+#include "lib/ffmpeg_film_encoder.h"
 #include "lib/film.h"
 #include "lib/filter.h"
 #ifdef DCPOMATIC_GROK
@@ -519,7 +519,7 @@ main (int argc, char* argv[])
        if (export_format) {
                auto job = std::make_shared<TranscodeJob>(film, behaviour);
                job->set_encoder (
-                       std::make_shared<FFmpegEncoder> (
+                       std::make_shared<FFmpegFilmEncoder>(
                                film, job, *export_filename, *export_format == "mp4" ? ExportFormat::H264_AAC : ExportFormat::PRORES_HQ, false, false, false, 23
                                )
                        );
index 6588b23b483f9db96d166a705d942c7226505d6d..a28e063e58461195c6f1397e9dd68750a008de12 100644 (file)
@@ -30,6 +30,7 @@
 #include "lib/constants.h"
 #include "lib/cross.h"
 #include "lib/job_manager.h"
+#include "lib/util.h"
 #include <dcp/combine.h>
 LIBDCP_DISABLE_WARNINGS
 #include <wx/filepicker.h>
index e1f541fe820a4c059ed720561a498ecb431dfe60..fc04ce01788e441b14888f6915b86b86f545f5d3 100644 (file)
@@ -29,6 +29,7 @@
 #include "lib/cross.h"
 #include "lib/dcpomatic_log.h"
 #include "lib/null_log.h"
+#include "lib/util.h"
 #include "lib/variant.h"
 #include <dcp/cpl.h>
 #include <dcp/dcp.h>
index d6c8b39459a4a63faebc0fb5a4e25231c976e762..1eda05162780a918de9b2613f4e2f2dd0632d0f3 100644 (file)
@@ -53,6 +53,7 @@
 #include "lib/kdm_with_metadata.h"
 #include "lib/screen.h"
 #include "lib/send_kdm_email_job.h"
+#include "lib/util.h"
 #include "lib/variant.h"
 #include <dcp/encrypted_kdm.h>
 #include <dcp/decrypted_kdm.h>
index 04bb26c2e7bc6dfe7340924eeadfd474aa4217de..05c3f281ccc96acdc3cc6463058e71ea73971195 100644 (file)
@@ -27,6 +27,7 @@
 #include "static_text.h"
 #include "wx_variant.h"
 #include "lib/constants.h"
+#include "lib/util.h"
 #include <dcp/file.h>
 #include <dcp/filesystem.h>
 #include <dcp/raw_convert.h>
index 3413c2814eb823dc910ecc784008ba8d0ae7bb2e..23644c03f5029b3703302239f3107437c26ae38a 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "timecode.h"
 #include "timeline.h"
+#include "lib/change_signaller.h"
+#include "lib/film_property.h"
 #include "lib/rect.h"
 #include <dcp/warnings.h>
 LIBDCP_DISABLE_WARNINGS
index beb33610b4dbda62089d8c5e3d0354bab5daa913..4e626be6b902e2edb017f3967ed3fbcba6bf1499 100644 (file)
@@ -20,7 +20,7 @@
 
 
 #include "table_dialog.h"
-#include "lib/ffmpeg_encoder.h"
+#include "lib/ffmpeg_file_encoder.h"
 #include <dcp/warnings.h>
 LIBDCP_DISABLE_WARNINGS
 #include <wx/wx.h>
index 5824f8baabeba7ca8e233a43a75d4db5ac1b1aad..63aa113d1cafbf2e43b3ec2922a665f44f75de62 100644 (file)
 
 
 #include "video_view.h"
+#include "lib/change_signaller.h"
 #include "lib/config.h"
 #include "lib/film_property.h"
+#include "lib/player.h"
 #include "lib/player_text.h"
 #include "lib/signaller.h"
 #include "lib/timer.h"
index 4e1eb8f3404a62003f1c3a08a5dbffa1e08a7dae..523d0c369f960a08cb6b600125f2b2056fe29592 100644 (file)
@@ -23,6 +23,7 @@
 #include "kdm_cpl_panel.h"
 #include "static_text.h"
 #include "wx_util.h"
+#include <dcp/filesystem.h>
 #include <dcp/warnings.h>
 LIBDCP_DISABLE_WARNINGS
 #include <libxml++/libxml++.h>
index cb0d102405ea34cad4e6b8bc65a4c56820b75557..69a675c4202c1bb74627fec4b9af479a96d099e0 100644 (file)
@@ -23,6 +23,7 @@
 #include "timeline_content_view.h"
 #include "wx_util.h"
 #include "lib/content.h"
+#include "lib/util.h"
 #include <dcp/warnings.h>
 LIBDCP_DISABLE_WARNINGS
 #include <wx/graphics.h>
index 9d25287b2dc29b4fe512e757174eb00dcea7b247..ac14de2c452ce941bbad1c76f55689738a0bb1ad 100644 (file)
@@ -30,7 +30,7 @@
 #include "lib/dcp_content.h"
 #include "lib/dcp_content_type.h"
 #include "lib/film.h"
-#include "lib/ffmpeg_encoder.h"
+#include "lib/ffmpeg_film_encoder.h"
 #include "lib/log_entry.h"
 #include "lib/ratio.h"
 #include "lib/text_content.h"
@@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(burn_empty_subtitle_test)
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
        auto file = boost::filesystem::path("build") / "test" / "burnt_empty_subtitle_test.mov";
        cl.add(file);
-       FFmpegEncoder encoder(film, job, file, ExportFormat::PRORES_4444, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, file, ExportFormat::PRORES_4444, false, false, false, 23);
        encoder.go();
 
        cl.run();
index f0133ff667a42e2e8cd56620ede320754ebdf00d..67bc0ce1e5013e4cc8c39815b3954b6638e7fdea 100644 (file)
@@ -28,8 +28,8 @@
 #include "lib/dcp_content.h"
 #include "lib/dcpomatic_log.h"
 #include "lib/ffmpeg_content.h"
-#include "lib/ffmpeg_encoder.h"
 #include "lib/ffmpeg_examiner.h"
+#include "lib/ffmpeg_film_encoder.h"
 #include "lib/film.h"
 #include "lib/image_content.h"
 #include "lib/ratio.h"
@@ -84,7 +84,7 @@ ffmpeg_content_test (int number, boost::filesystem::path content, ExportFormat f
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
        auto file = boost::filesystem::path("build") / "test" / String::compose("%1.%2", name, extension);
        cl.add (file);
-       FFmpegEncoder encoder (film, job, file, format, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, file, format, false, false, false, 23);
        encoder.go ();
 
        cl.run ();
@@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test5)
 
        film->write_metadata ();
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_prores_test5.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
        encoder.go ();
 }
 
@@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test6)
        film->write_metadata();
 
        auto job = make_shared<TranscodeJob> (film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_prores_test6.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
        encoder.go ();
 }
 
@@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_test7)
        s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_prores_test7.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
        encoder.go ();
 }
 
@@ -211,7 +211,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test2)
        film->write_metadata();
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", ExportFormat::H264_AAC, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", ExportFormat::H264_AAC, false, false, false, 23);
        encoder.go ();
 }
 
@@ -237,7 +237,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test3)
        film->write_metadata();
 
        auto job = make_shared<TranscodeJob> (film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", ExportFormat::H264_AAC, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", ExportFormat::H264_AAC, false, false, false, 23);
        encoder.go ();
 }
 
@@ -251,7 +251,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test4)
        film->set_container(Ratio::from_id("185"));
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", ExportFormat::H264_AAC, false, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", ExportFormat::H264_AAC, false, false, false, 23);
        encoder.go();
 }
 
@@ -306,7 +306,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test5)
        Rs->audio->set_mapping (map);
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", ExportFormat::H264_AAC, true, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", ExportFormat::H264_AAC, true, false, false, 23);
        encoder.go ();
 
        check_ffmpeg ("build/test/ffmpeg_encoder_h264_test5.mp4", "test/data/ffmpeg_encoder_h264_test5.mp4", 1);
@@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test6)
        }
 
        auto job = make_shared<TranscodeJob>(film2, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film2, job, "build/test/ffmpeg_encoder_h264_test6_vf.mp4", ExportFormat::H264_AAC, true, false, false, 23);
+       FFmpegFilmEncoder encoder(film2, job, "build/test/ffmpeg_encoder_h264_test6_vf.mp4", ExportFormat::H264_AAC, true, false, false, 23);
        encoder.go ();
 }
 
@@ -346,7 +346,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_3d_dcp_to_h264)
        auto film2 = new_test_film2 ("ffmpeg_encoder_3d_dcp_to_h264_export", {dcp});
 
        auto job = make_shared<TranscodeJob>(film2, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film2, job, "build/test/ffmpeg_encoder_3d_dcp_to_h264.mp4", ExportFormat::H264_AAC, true, false, false, 23);
+       FFmpegFilmEncoder encoder(film2, job, "build/test/ffmpeg_encoder_3d_dcp_to_h264.mp4", ExportFormat::H264_AAC, true, false, false, 23);
        encoder.go ();
 }
 
@@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test7)
        auto film2 = new_test_film2 ("ffmpeg_encoder_h264_test7_export", {dcp});
 
        auto job = make_shared<TranscodeJob> (film2, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film2, job, "build/test/ffmpeg_encoder_h264_test7.mp4", ExportFormat::H264_AAC, true, false, false, 23);
+       FFmpegFilmEncoder encoder(film2, job, "build/test/ffmpeg_encoder_h264_test7.mp4", ExportFormat::H264_AAC, true, false, false, 23);
        encoder.go ();
 }
 
@@ -380,7 +380,7 @@ BOOST_AUTO_TEST_CASE(ffmpeg_encoder_2d_content_in_3d_project)
        film->set_three_d(true);
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_2d_content_in_3d_project.mp4", ExportFormat::H264_AAC, true, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_2d_content_in_3d_project.mp4", ExportFormat::H264_AAC, true, false, false, 23);
        encoder.go();
 }
 
@@ -394,7 +394,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test8)
        film->set_audio_channels (2);
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test8.mp4", ExportFormat::H264_AAC, true, false, false, 23);
+       FFmpegFilmEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test8.mp4", ExportFormat::H264_AAC, true, false, false, 23);
        encoder.go();
 }
 
@@ -415,7 +415,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test9)
 
        film->write_metadata ();
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test9.mov", ExportFormat::H264_AAC, false, false, false, 23);
+       FFmpegFilmEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test9.mov", ExportFormat::H264_AAC, false, false, false, 23);
        encoder.go ();
 }
 
@@ -430,7 +430,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_from_dcp_with_crop)
        film->write_metadata ();
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_from_dcp_with_crop.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
+       FFmpegFilmEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_from_dcp_with_crop.mov", ExportFormat::PRORES_HQ, false, false, false, 23);
        encoder.go ();
 }
 
@@ -445,7 +445,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_from_dcp_with_crop)
        film->write_metadata ();
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_from_dcp_with_crop.mov", ExportFormat::H264_AAC, false, false, false, 23);
+       FFmpegFilmEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_from_dcp_with_crop.mov", ExportFormat::H264_AAC, false, false, false, 23);
        encoder.go ();
 }
 
@@ -461,7 +461,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_with_reels)
        content2->video->set_length (240);
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_with_reels.mov", ExportFormat::H264_AAC, false, true, false, 23);
+       FFmpegFilmEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_with_reels.mov", ExportFormat::H264_AAC, false, true, false, 23);
        encoder.go ();
 
        auto check = [](boost::filesystem::path path) {
@@ -485,7 +485,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_regression_1)
        auto film = new_test_film2 ("ffmpeg_encoder_prores_regression_1", { content });
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_regression_1.mov", ExportFormat::PRORES_HQ, false, true, false, 23);
+       FFmpegFilmEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_regression_1.mov", ExportFormat::PRORES_HQ, false, true, false, 23);
        encoder.go ();
 
        cl.add("build/test/ffmpeg_encoder_prores_regression_1.mov");
@@ -505,7 +505,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_encoder_prores_regression_2)
        auto film = new_test_film2 ("ffmpeg_encoder_prores_regression_2", { content });
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_regression_2.mov", ExportFormat::PRORES_HQ, false, true, false, 23);
+       FFmpegFilmEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_regression_2.mov", ExportFormat::PRORES_HQ, false, true, false, 23);
        encoder.go ();
 
        dcpomatic_log->set_types(logs);
@@ -524,7 +524,7 @@ BOOST_AUTO_TEST_CASE(ffmpeg_encoder_missing_frame_at_end)
        boost::filesystem::path log("build/test/ffmpeg_encoder_missing_frame_at_end.log");
 
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       FFmpegEncoder encoder(film, job, output, ExportFormat::PRORES_HQ, false, true, false, 23);
+       FFmpegFilmEncoder encoder(film, job, output, ExportFormat::PRORES_HQ, false, true, false, 23);
        encoder.go();
 
        run_ffprobe(output, log, false, "-show_frames -show_format -show_streams -select_streams v:0");
index ff2e7b0dc7de22aa93298c3a6d4ff10a257973f9..5f66df20abc9811662e8fd8f87abf92a8085c4a9 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "lib/config.h"
 #include "lib/content_factory.h"
-#include "lib/dcp_encoder.h"
+#include "lib/dcp_film_encoder.h"
 #include "lib/dcp_transcode_job.h"
 #include "lib/encode_server_description.h"
 #include "lib/film.h"
@@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(frames_not_lost_when_threads_disappear)
        auto film = new_test_film2("frames_not_lost", content);
        film->write_metadata();
        auto job = make_dcp(film, TranscodeJob::ChangedBehaviour::IGNORE);
-       auto& encoder = dynamic_pointer_cast<DCPEncoder>(job->_encoder)->_j2k_encoder;
+       auto& encoder = dynamic_pointer_cast<DCPFilmEncoder>(job->_encoder)->_j2k_encoder;
 
        while (JobManager::instance()->work_to_do()) {
                encoder.remake_threads(rand() % 8, 0, {});
index cad7d7d263e0517ba7e1fe15fa5e87aed5877ab8..50514041b33e6fa8a90710f7bd7aebfacbbc4ec5 100644 (file)
@@ -22,7 +22,6 @@
 #include "lib/content.h"
 #include "lib/content_factory.h"
 #include "lib/dcp_content_type.h"
-#include "lib/dcp_encoder.h"
 #include "lib/dcpomatic_log.h"
 #include "lib/film.h"
 #include "lib/job_manager.h"
index c8e939861f877abb10ea2f9b3a0679fb45e22067..bb2c1b7fac456f937be3825edc0bc4619bff66a7 100644 (file)
@@ -36,7 +36,7 @@
 #include "lib/image.h"
 #include "lib/image_content.h"
 #include "lib/image_decoder.h"
-#include "lib/ffmpeg_encoder.h"
+#include "lib/ffmpeg_film_encoder.h"
 #include "lib/job_manager.h"
 #include "lib/player.h"
 #include "lib/player_video.h"
@@ -459,7 +459,7 @@ V_movie_range (shared_ptr<Film> film)
 {
        auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
        job->set_encoder (
-               make_shared<FFmpegEncoder>(film, job, film->file("export.mov"), ExportFormat::PRORES_HQ, true, false, false, 23)
+               make_shared<FFmpegFilmEncoder>(film, job, film->file("export.mov"), ExportFormat::PRORES_HQ, true, false, false, 23)
                );
        JobManager::instance()->add (job);
        BOOST_REQUIRE (!wait_for_jobs());
index 86b60818f18f31fbf3361b8e215877bc104dd869..2d4da570f9ee7f7dd711651a5a5cbb0cf27cf73a 100644 (file)
@@ -23,7 +23,7 @@
 #include "lib/content.h"
 #include "lib/content_factory.h"
 #include "lib/cross.h"
-#include "lib/dcp_encoder.h"
+#include "lib/dcp_film_encoder.h"
 #include "lib/film.h"
 #include "lib/job.h"
 #include "lib/video_content.h"
@@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(writer_progress_test)
                last_sub_name = job->sub_name();
        });
 
-       DCPEncoder encoder(film, job);
+       DCPFilmEncoder encoder(film, job);
        encoder.go();
 }