summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-10-23 22:39:19 +0200
committerCarl Hetherington <cth@carlh.net>2025-10-23 22:39:21 +0200
commitbda1a2c382229a5f1a893c015d23524807e022df (patch)
tree42a6599d223850642a903b3e8f3161628f6de163
parentc91f1e6aed0eebe98363ff9d5ba5bf87c6acb48e (diff)
Allow writing DCPs without any other metadata / working files.
-rw-r--r--src/lib/dcp_film_encoder.cc4
-rw-r--r--src/lib/dcp_film_encoder.h2
-rw-r--r--src/lib/dcp_transcode_job.cc7
-rw-r--r--src/lib/dcp_transcode_job.h6
-rw-r--r--src/lib/reel_writer.cc25
-rw-r--r--src/lib/reel_writer.h2
-rw-r--r--src/lib/writer.cc12
-rw-r--r--src/lib/writer.h11
-rw-r--r--test/reel_writer_test.cc4
9 files changed, 47 insertions, 26 deletions
diff --git a/src/lib/dcp_film_encoder.cc b/src/lib/dcp_film_encoder.cc
index 631010071..63540c360 100644
--- a/src/lib/dcp_film_encoder.cc
+++ b/src/lib/dcp_film_encoder.cc
@@ -64,9 +64,9 @@ using namespace dcpomatic;
* @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)
+DCPFilmEncoder::DCPFilmEncoder(shared_ptr<const Film> film, weak_ptr<Job> job, bool dcp_only)
: FilmEncoder(film, job)
- , _writer(film, job, film->dir(film->dcp_name()))
+ , _writer(film, job, film->dir(film->dcp_name()), false, dcp_only)
, _finishing (false)
, _non_burnt_subtitles (false)
{
diff --git a/src/lib/dcp_film_encoder.h b/src/lib/dcp_film_encoder.h
index 3c697a115..b51dfb5e7 100644
--- a/src/lib/dcp_film_encoder.h
+++ b/src/lib/dcp_film_encoder.h
@@ -42,7 +42,7 @@ struct frames_not_lost_when_threads_disappear;
class DCPFilmEncoder : public FilmEncoder
{
public:
- DCPFilmEncoder(std::shared_ptr<const Film> film, std::weak_ptr<Job> job);
+ DCPFilmEncoder(std::shared_ptr<const Film> film, std::weak_ptr<Job> job, bool dcp_only = false);
~DCPFilmEncoder();
void go () override;
diff --git a/src/lib/dcp_transcode_job.cc b/src/lib/dcp_transcode_job.cc
index dd7b7d624..f1b527b64 100644
--- a/src/lib/dcp_transcode_job.cc
+++ b/src/lib/dcp_transcode_job.cc
@@ -36,8 +36,9 @@ using std::shared_ptr;
using std::vector;
-DCPTranscodeJob::DCPTranscodeJob (shared_ptr<const Film> film, ChangedBehaviour changed)
+DCPTranscodeJob::DCPTranscodeJob (shared_ptr<const Film> film, ChangedBehaviour changed, bool dcp_only)
: TranscodeJob (film, changed)
+ , _dcp_only(dcp_only)
{
}
@@ -74,6 +75,8 @@ DCPTranscodeJob::post_transcode ()
cpl->add (decrypt_kdm_with_helpful_error(kdm));
}
- write_dcp_digest_file (_film->file(cpl->annotation_text().get_value_or(cpl->id()) + ".dcpdig"), cpl, _film->key().hex());
+ if (!_dcp_only) {
+ write_dcp_digest_file(_film->file(cpl->annotation_text().get_value_or(cpl->id()) + ".dcpdig"), cpl, _film->key().hex());
+ }
}
diff --git a/src/lib/dcp_transcode_job.h b/src/lib/dcp_transcode_job.h
index 4699884ed..2bfc52355 100644
--- a/src/lib/dcp_transcode_job.h
+++ b/src/lib/dcp_transcode_job.h
@@ -25,8 +25,10 @@
class DCPTranscodeJob : public TranscodeJob
{
public:
- DCPTranscodeJob (std::shared_ptr<const Film> film, ChangedBehaviour changed);
+ DCPTranscodeJob(std::shared_ptr<const Film> film, ChangedBehaviour changed, bool dcp_only = false);
private:
- void post_transcode () override;
+ void post_transcode() override;
+
+ bool _dcp_only;
};
diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc
index 01a798676..8750653d8 100644
--- a/src/lib/reel_writer.cc
+++ b/src/lib/reel_writer.cc
@@ -103,7 +103,7 @@ mxf_metadata()
* subtitle / closed caption files.
*/
ReelWriter::ReelWriter(
- weak_ptr<const Film> weak_film, DCPTimePeriod period, shared_ptr<Job> job, int reel_index, int reel_count, bool text_only, boost::filesystem::path output_dir
+ weak_ptr<const Film> weak_film, DCPTimePeriod period, shared_ptr<Job> job, int reel_index, int reel_count, bool text_only, bool dcp_only, boost::filesystem::path output_dir
)
: WeakConstFilm(weak_film)
, _output_dir(std::move(output_dir))
@@ -113,10 +113,11 @@ ReelWriter::ReelWriter(
, _content_summary(film()->content_summary(period))
, _job(job)
, _text_only(text_only)
+ , _dcp_only(dcp_only)
, _info_file(film()->info_file(period), dcp::filesystem::exists(film()->info_file(period)) ? "r+b" : "wb")
, _font_metrics(film()->frame_size().height)
{
- if (!_info_file) {
+ if (!_info_file && !_dcp_only) {
auto const info_file_path = film()->info_file(period);
throw OpenFileError(info_file_path, _info_file.open_error(), dcp::filesystem::exists(info_file_path) ? OpenFileError::READ_WRITE : OpenFileError::WRITE);
}
@@ -174,7 +175,9 @@ ReelWriter::ReelWriter(
dcp::filesystem::rename(*existing_asset_filename, new_asset_filename);
}
remembered_assets.push_back(RememberedAsset(new_asset_filename.filename(), period, film()->video_identifier()));
- film()->write_remembered_assets(remembered_assets);
+ if (!_dcp_only) {
+ film()->write_remembered_assets(remembered_assets);
+ }
picture_asset->set_file(new_asset_filename);
dcp::Behaviour const behaviour = _first_nonexistent_frame > 0 ? dcp::Behaviour::OVERWRITE_EXISTING : dcp::Behaviour::MAKE_NEW;
@@ -193,7 +196,9 @@ ReelWriter::ReelWriter(
dcp::filesystem::copy(*existing_asset_filename, new_asset_filename);
remembered_assets.push_back(RememberedAsset(new_asset_filename, period, film()->video_identifier()));
}
- film()->write_remembered_assets(remembered_assets);
+ if (!_dcp_only) {
+ film()->write_remembered_assets(remembered_assets);
+ }
if (film()->video_encoding() == VideoEncoding::JPEG2000) {
if (film()->three_d()) {
@@ -299,8 +304,10 @@ ReelWriter::write(shared_ptr<const Data> encoded, Frame frame, Eyes eyes)
return;
}
- auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(encoded->data(), encoded->size()));
- fin.write(_info_file, frame, eyes);
+ if (!_dcp_only) {
+ auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(encoded->data(), encoded->size()));
+ fin.write(_info_file, frame, eyes);
+ }
_last_written[eyes] = encoded;
}
@@ -348,8 +355,10 @@ ReelWriter::repeat_write(Frame frame, Eyes eyes)
return;
}
- auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(_last_written[eyes]->data(), _last_written[eyes]->size()));
- fin.write(_info_file, frame, eyes);
+ if (!_dcp_only) {
+ auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(_last_written[eyes]->data(), _last_written[eyes]->size()));
+ fin.write(_info_file, frame, eyes);
+ }
}
diff --git a/src/lib/reel_writer.h b/src/lib/reel_writer.h
index 367b62349..d7d09c9f4 100644
--- a/src/lib/reel_writer.h
+++ b/src/lib/reel_writer.h
@@ -71,6 +71,7 @@ public:
int reel_index,
int reel_count,
bool text_only,
+ bool dcp_only,
boost::filesystem::path output_dir
);
@@ -135,6 +136,7 @@ private:
boost::optional<std::string> _content_summary;
std::weak_ptr<Job> _job;
bool _text_only;
+ bool _dcp_only;
dcp::ArrayData _default_font;
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 7121c594b..e0b780fe2 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -74,10 +74,7 @@ using dcp::ArrayData;
using namespace dcpomatic;
-/** @param weak_job Job to report progress to, or 0.
- * @param text_only true to enable only the text (subtitle/ccap) parts of the writer.
- */
-Writer::Writer(weak_ptr<const Film> weak_film, weak_ptr<Job> weak_job, boost::filesystem::path output_dir, bool text_only)
+Writer::Writer(weak_ptr<const Film> weak_film, weak_ptr<Job> weak_job, boost::filesystem::path output_dir, bool text_only, bool dcp_only)
: WeakConstFilm(weak_film)
, _job(weak_job)
, _output_dir(output_dir)
@@ -85,13 +82,14 @@ Writer::Writer(weak_ptr<const Film> weak_film, weak_ptr<Job> weak_job, boost::fi
, _maximum_frames_in_memory(8)
, _maximum_queue_size(8)
, _text_only(text_only)
+ , _dcp_only(dcp_only)
{
auto job = _job.lock();
int reel_index = 0;
auto const reels = film()->reels();
for (auto p: reels) {
- _reels.emplace_back(weak_film, p, job, reel_index++, reels.size(), text_only, _output_dir);
+ _reels.emplace_back(weak_film, p, job, reel_index++, reels.size(), text_only, dcp_only, _output_dir);
}
_last_written.resize(reels.size());
@@ -713,7 +711,9 @@ Writer::finish()
N_("Wrote {} FULL, {} FAKE, {} REPEAT, {} pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk
);
- dcpomatic::write_cover_sheet(film(), _output_dir, film()->file("COVER_SHEET.txt"));
+ if (!_dcp_only) {
+ dcpomatic::write_cover_sheet(film(), _output_dir, film()->file("COVER_SHEET.txt"));
+ }
}
diff --git a/src/lib/writer.h b/src/lib/writer.h
index eca2c2a9a..d8cda4f7f 100644
--- a/src/lib/writer.h
+++ b/src/lib/writer.h
@@ -91,11 +91,11 @@ bool operator==(QueueItem const & a, QueueItem const & b);
/** @class Writer
- * @brief Class to manage writing JPEG2000 and audio data to assets on disk.
+ * @brief Class to manage writing a DCP to disk.
*
* This class creates sound and picture assets, then takes Data
* or AudioBuffers objects (containing image or sound data respectively)
- * and writes them to the assets.
+ * and writes them to the assets. It also writes the DCP's XML metadata.
*
* write() for Data (picture) can be called out of order, and the Writer
* will sort it out. write() for AudioBuffers must be called in order.
@@ -104,7 +104,11 @@ bool operator==(QueueItem const & a, QueueItem const & b);
class Writer : public ExceptionStore, public WeakConstFilm
{
public:
- Writer(std::weak_ptr<const Film>, std::weak_ptr<Job>, boost::filesystem::path output_dir, bool text_only = false);
+ /** @param weak_job Job to report progress to, or 0.
+ * @param text_only true to enable only the text (subtitle/ccap) parts of the writer.
+ * @param dcp_only true to write only the DCP, and no extra files (cover sheet, assets.xml etc.)
+ */
+ Writer(std::weak_ptr<const Film>, std::weak_ptr<Job>, boost::filesystem::path output_dir, bool text_only = false, bool dcp_only = false);
~Writer();
Writer(Writer const &) = delete;
@@ -207,6 +211,7 @@ private:
int _pushed_to_disk = 0;
bool _text_only;
+ bool _dcp_only;
boost::mutex _digest_progresses_mutex;
std::map<int, std::pair<int64_t, int64_t>> _digest_progresses;
diff --git a/test/reel_writer_test.cc b/test/reel_writer_test.cc
index cb5ad349e..841aa1c72 100644
--- a/test/reel_writer_test.cc
+++ b/test/reel_writer_test.cc
@@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE (write_frame_info_test)
J2KFrameInfo info4(55512494, 123599157123, "ABCDEFGyabc12356ffsfdsf4563395ZZ");
{
- ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, "foo");
+ ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, false, "foo");
info1.write(writer._info_file, 0, Eyes::LEFT);
info2.write(writer._info_file, 5, Eyes::RIGHT);
info3.write(writer._info_file, 10, Eyes::LEFT);
@@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE (write_frame_info_test)
BOOST_CHECK(equal(info3, file1, 10, Eyes::LEFT));
{
- ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, "foo");
+ ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, false, "foo");
/* Overwrite one */
info4.write(writer._info_file, 5, Eyes::RIGHT);