using std::cout;
using std::shared_ptr;
-/** @param gui true if we are running this job from the GUI, false if it's the CLI */
-CheckContentChangeJob::CheckContentChangeJob (shared_ptr<const Film> film, shared_ptr<Job> following, bool gui)
+CheckContentChangeJob::CheckContentChangeJob (shared_ptr<const Film> film)
: Job (film)
- , _following (following)
- , _gui (gui)
{
}
std::copy_if (content.begin(), content.end(), std::back_inserter(changed), [](shared_ptr<Content> c) { return c->changed(); });
if (!changed.empty()) {
- if (_gui) {
- for (auto i: changed) {
- JobManager::instance()->add(shared_ptr<Job>(new ExamineContentJob(_film, i)));
- }
- string m = _("Some files have been changed since they were added to the project.\n\nThese files will now be re-examined, so you may need to check their settings.");
- if (_following) {
- /* I'm assuming that _following is a make DCP job */
- m += " ";
- m += _("Choose 'Make DCP' again when you have done this.");
- }
- set_message (m);
- } else {
- set_progress (1);
- set_state (FINISHED_ERROR);
- set_error (
- _("Some files have been changed since they were added to the project. Open the project in DCP-o-matic, check the settings, then save it before trying again."),
- ""
- );
- return;
+ for (auto i: changed) {
+ JobManager::instance()->add(make_shared<ExamineContentJob>(_film, i));
}
- } else if (_following) {
- JobManager::instance()->add (_following);
+ set_message (_("Some files have been changed since they were added to the project.\n\nThese files will now be re-examined, so you may need to check their settings."));
}
- /* Only set this job as finished once we have added the following job, otherwise I think
- it's possible that the tests will sporadically fail if they check for all jobs being
- complete in the gap between this one finishing and _following being added.
- */
-
set_progress (1);
set_state (FINISHED_OK);
}
class CheckContentChangeJob : public Job
{
public:
- CheckContentChangeJob (std::shared_ptr<const Film>, std::shared_ptr<Job> following = std::shared_ptr<Job>(), bool gui = true);
+ CheckContentChangeJob (std::shared_ptr<const Film>);
~CheckContentChangeJob ();
std::string name () const;
std::string json_name () const;
void run ();
-
-private:
- std::shared_ptr<Job> _following;
- bool _gui;
};
}
-/** Add suitable Jobs to the JobManager to create a DCP for this Film.
- * @param gui true if this is being called from a GUI tool.
- * @param check true to check the content in the project for changes before making the DCP.
- */
+/** Add suitable Jobs to the JobManager to create a DCP for this Film */
void
-Film::make_dcp (bool gui, bool check)
+Film::make_dcp (TranscodeJob::ChangedBehaviour behaviour)
{
if (dcp_name().find ("/") != string::npos) {
throw BadSettingError (_("name"), _("Cannot contain slashes"));
}
LOG_GENERAL ("J2K bandwidth %1", j2k_bandwidth());
- auto tj = make_shared<TranscodeJob>(shared_from_this());
+ auto tj = make_shared<TranscodeJob>(shared_from_this(), behaviour);
tj->set_encoder (make_shared<DCPEncoder>(shared_from_this(), tj));
- if (check) {
- auto cc = make_shared<CheckContentChangeJob>(shared_from_this(), tj, gui);
- JobManager::instance()->add (cc);
- } else {
- JobManager::instance()->add (tj);
- }
+ JobManager::instance()->add (tj);
}
/** Start a job to send our DCP to the configured TMS */
#include "dcp_text_track.h"
#include "frame_rate_change.h"
#include "signaller.h"
+#include "transcode_job.h"
#include "types.h"
#include "util.h"
#include <dcp/encrypted_kdm.h>
boost::filesystem::path subtitle_analysis_path (std::shared_ptr<const Content>) const;
void send_dcp_to_tms ();
- void make_dcp (bool gui = false, bool check = true);
+ void make_dcp (TranscodeJob::ChangedBehaviour behaviour);
/** @return Logger.
* It is safe to call this from any thread.
#include "analytics.h"
#include "compose.hpp"
+#include "content.h"
#include "config.h"
#include "dcp_encoder.h"
#include "dcpomatic_log.h"
#include "encoder.h"
+#include "examine_content_job.h"
#include "film.h"
#include "job_manager.h"
#include "log.h"
/** @param film Film to use */
-TranscodeJob::TranscodeJob (shared_ptr<const Film> film)
+TranscodeJob::TranscodeJob (shared_ptr<const Film> film, ChangedBehaviour changed)
: Job (film)
+ , _changed (changed)
{
}
TranscodeJob::run ()
{
try {
+ auto content = _film->content();
+ std::vector<shared_ptr<Content>> changed;
+ std::copy_if (content.begin(), content.end(), std::back_inserter(changed), [](shared_ptr<Content> c) { return c->changed(); });
+
+ if (!changed.empty()) {
+ switch (_changed) {
+ case ChangedBehaviour::EXAMINE_THEN_STOP:
+ for (auto i: changed) {
+ JobManager::instance()->add(make_shared<ExamineContentJob>(_film, i));
+ }
+ set_progress (1);
+ set_message (_("Some files have been changed since they were added to the project.\n\nThese files will now be re-examined, so you may need to check their settings before trying again."));
+ set_error (_("Files have changed since they were added to the project."), _("Check their new settings, then try again."));
+ set_state (FINISHED_ERROR);
+ return;
+ case ChangedBehaviour::STOP:
+ set_progress (1);
+ set_error (_("Files have changed since they were added to the project."), _("Open the project in DCP-o-matic, check the settings, then save it before trying again."));
+ set_state (FINISHED_ERROR);
+ return;
+ default:
+ LOG_GENERAL_NC (_("Some files have been changed since they were added to the project."));
+ break;
+ }
+ }
+
struct timeval start;
gettimeofday (&start, 0);
LOG_GENERAL_NC (N_("Transcode job starting"));
return Job::status ();
}
-
- char buffer[256];
if (finished() || _encoder->finishing()) {
- strncpy (buffer, Job::status().c_str(), 255);
- buffer[255] = '\0';
- } else {
- snprintf (
- buffer, sizeof(buffer), "%s; %" PRId64 "/%" PRId64 " frames",
- Job::status().c_str(),
- _encoder->frames_done(),
- _film->length().frames_round (_film->video_frame_rate ())
- );
-
- optional<float> const fps = _encoder->current_rate ();
- if (fps) {
- char fps_buffer[64];
- /// TRANSLATORS: fps here is an abbreviation for frames per second
- snprintf (fps_buffer, sizeof(fps_buffer), _("; %.1f fps"), *fps);
- strncat (buffer, fps_buffer, strlen(buffer) - 1);
- }
+ return Job::status();
+ }
+
+ auto status = String::compose(_("%1; %2/%3 frames"), Job::status(), _encoder->frames_done(), _film->length().frames_round(_film->video_frame_rate()));
+ if (auto const fps = _encoder->current_rate()) {
+ /// TRANSLATORS: fps here is an abbreviation for frames per second
+ status += String::compose(_("; %1 fps"), dcp::locale_convert<string>(*fps, 1));
}
- return buffer;
+ return status;
}
*/
+#ifndef DCPOMATIC_TRANSCODE_JOB_H
+#define DCPOMATIC_TRANSCODE_JOB_H
+
+
/** @file src/transcode_job.h
* @brief A job which transcodes from one format to another.
*/
#include "job.h"
+/* Defined by Windows */
+#undef IGNORE
+
+
class Encoder;
class TranscodeJob : public Job
{
public:
- explicit TranscodeJob (std::shared_ptr<const Film> film);
+ enum class ChangedBehaviour {
+ EXAMINE_THEN_STOP,
+ STOP,
+ IGNORE
+ };
+
+ explicit TranscodeJob (std::shared_ptr<const Film> film, ChangedBehaviour changed);
~TranscodeJob ();
std::string name () const override;
int remaining_time () const override;
std::shared_ptr<Encoder> _encoder;
+ ChangedBehaviour _changed;
};
+
+
+#endif
+
a long time, and crashes/power failures are moderately likely.
*/
_film->write_metadata ();
- _film->make_dcp (true);
+ _film->make_dcp (TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
} catch (BadSettingError& e) {
error_dialog (this, wxString::Format (_("Bad setting for %s."), std_to_wx(e.setting()).data()), std_to_wx(e.what()));
} catch (std::exception& e) {
}
}
- auto job = make_shared<TranscodeJob>(_film);
+ auto job = make_shared<TranscodeJob>(_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
job->set_encoder (
make_shared<FFmpegEncoder> (
_film, job, d->path(), d->format(), d->mixdown_to_stereo(), d->split_reels(), d->split_streams(), d->x264_crf())
{
auto d = new ExportSubtitlesDialog (this, _film->reels().size(), _film->interop());
if (d->ShowModal() == wxID_OK) {
- auto job = make_shared<TranscodeJob>(_film);
+ auto job = make_shared<TranscodeJob>(_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
job->set_encoder (
make_shared<SubtitleEncoder>(_film, job, d->path(), _film->isdcf_name(true), d->split_reels(), d->include_font())
);
}
}
- film->make_dcp ();
+ film->make_dcp (TranscodeJob::ChangedBehaviour::STOP);
} catch (std::exception& e) {
auto p = std_to_wx (path.string ());
auto b = p.ToUTF8 ();
try {
film = make_shared<Film>(i);
film->read_metadata ();
- film->make_dcp ();
+ film->make_dcp (TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
} catch (exception& e) {
error_dialog (
0,
cout << "\nMaking DCP for " << film->name() << "\n";
}
- film->make_dcp (false, check);
+ film->make_dcp (check ? TranscodeJob::ChangedBehaviour::STOP : TranscodeJob::ChangedBehaviour::IGNORE);
bool const error = show_jobs_on_console (progress);
if (keep_going) {
name = String::compose("%1_test%2", name, number);
auto c = make_shared<FFmpegContent>(content);
- shared_ptr<Film> film = new_test_film2 (name, {c}, &cl);
+ auto film = new_test_film2 (name, {c}, &cl);
film->set_name (name);
film->set_audio_channels (6);
film->write_metadata ();
- auto job = make_shared<TranscodeJob>(film);
+ 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);
c->video->set_length (240);
film->write_metadata ();
- auto job = make_shared<TranscodeJob> (film);
+ auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", ExportFormat::PRORES, false, false, false, 23);
encoder.go ();
}
s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
film->write_metadata();
- auto job = make_shared<TranscodeJob> (film);
+ auto job = make_shared<TranscodeJob> (film, TranscodeJob::ChangedBehaviour::IGNORE);
FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", ExportFormat::PRORES, false, false, false, 23);
encoder.go ();
}
s->only_text()->set_effect (dcp::Effect::SHADOW);
s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
- auto job = make_shared<TranscodeJob> (film);
+ auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", ExportFormat::PRORES, false, false, false, 23);
encoder.go ();
}
s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
film->write_metadata();
- auto job = make_shared<TranscodeJob> (film);
+ 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);
encoder.go ();
}
s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
film->write_metadata();
- auto job = make_shared<TranscodeJob> (film);
+ 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);
encoder.go ();
}
film->set_container(Ratio::from_id("185"));
- auto job = make_shared<TranscodeJob>(film);
+ 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);
encoder.go();
}
map.set (0, 5, 1);
Rs->audio->set_mapping (map);
- auto job = make_shared<TranscodeJob> (film);
+ 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);
encoder.go ();
i->set_use (true);
}
- auto job = make_shared<TranscodeJob> (film2);
+ 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);
encoder.go ();
}
auto dcp = make_shared<DCPContent>(TestPaths::private_data() / "xm");
auto film2 = new_test_film2 ("ffmpeg_encoder_3d_dcp_to_h264_export", {dcp});
- auto job = make_shared<TranscodeJob> (film2);
+ 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);
encoder.go ();
}
auto dcp = make_shared<DCPContent>(film->dir(film->dcp_name()));
auto film2 = new_test_film2 ("ffmpeg_encoder_h264_test7_export", {dcp});
- auto job = make_shared<TranscodeJob> (film2);
+ 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);
encoder.go ();
}
/** Stereo project with mixdown-to-stereo set */
BOOST_AUTO_TEST_CASE (ffmpeg_encoder_h264_test8)
{
- shared_ptr<Film> film = new_test_film2("ffmpeg_encoder_h264_test4");
- film->examine_and_add_content(shared_ptr<DCPContent>(new DCPContent("test/data/scope_dcp")));
+ auto film = new_test_film2("ffmpeg_encoder_h264_test4");
+ film->examine_and_add_content(make_shared<DCPContent>("test/data/scope_dcp"));
BOOST_REQUIRE(!wait_for_jobs());
film->set_audio_channels (2);
- shared_ptr<Job> job(new TranscodeJob(film));
+ 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);
encoder.go();
}
{
shared_ptr<Film> film = new_test_film ("ffmpeg_encoder_prores_test9");
film->set_name ("ffmpeg_encoder_prores_test9");
- shared_ptr<ImageContent> c (new ImageContent(TestPaths::private_data() / "bbc405.png"));
+ auto c = make_shared<ImageContent>(TestPaths::private_data() / "bbc405.png");
film->set_container (Ratio::from_id ("185"));
film->set_audio_channels (12);
c->video->set_length (240);
film->write_metadata ();
- shared_ptr<Job> job (new TranscodeJob (film));
+ 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);
encoder.go ();
}
dcp->video->set_right_crop (32);
film->write_metadata ();
- auto job = make_shared<TranscodeJob>(film);
+ 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, false, false, false, 23);
encoder.go ();
}
dcp->video->set_right_crop (32);
film->write_metadata ();
- auto job = make_shared<TranscodeJob>(film);
+ 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);
encoder.go ();
}
content1->video->set_length (240);
content2->video->set_length (240);
- auto job = make_shared<TranscodeJob>(film);
+ 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);
encoder.go ();
auto content = content_factory(TestPaths::private_data() / "arrietty_JP-EN.mkv").front();
auto film = new_test_film2 ("ffmpeg_encoder_prores_regression_1", { content });
- auto job = make_shared<TranscodeJob>(film);
+ auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_regression_1.mov", ExportFormat::PRORES, false, true, false, 23);
encoder.go ();
}
auto content = content_factory(TestPaths::private_data() / "tge_clip.mkv").front();
auto film = new_test_film2 ("ffmpeg_encoder_prores_regression_2", { content });
- auto job = make_shared<TranscodeJob>(film);
+ auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_regression_2.mov", ExportFormat::PRORES, false, true, false, 23);
encoder.go ();
film->examine_and_add_content (content);
BOOST_REQUIRE (!wait_for_jobs());
- film->make_dcp ();
+ film->make_dcp (TranscodeJob::ChangedBehaviour::IGNORE);
dcpomatic_sleep_seconds (10);
BOOST_CHECK (film->reels().front() == dcpomatic::DCPTimePeriod(dcpomatic::DCPTime(), dcpomatic::DCPTime::from_frames(263, 24)));
film->write_metadata ();
- film->make_dcp ();
+ film->make_dcp (TranscodeJob::ChangedBehaviour::IGNORE);
BOOST_REQUIRE (!wait_for_jobs());
vector<boost::filesystem::path> dirs = { film->dir(film->dcp_name(false)) };
make_and_verify_dcp (shared_ptr<Film> film, vector<dcp::VerificationNote::Code> ignore)
{
film->write_metadata ();
- film->make_dcp ();
+ film->make_dcp (TranscodeJob::ChangedBehaviour::IGNORE);
BOOST_REQUIRE (!wait_for_jobs());
auto notes = dcp::verify ({film->dir(film->dcp_name())}, &stage, &progress, TestPaths::xsd());
bool ok = true;
c->video->set_length (24);
film->set_three_d (true);
- film->make_dcp ();
+ film->make_dcp (TranscodeJob::ChangedBehaviour::IGNORE);
film->write_metadata ();
auto jm = JobManager::instance ();
pair<int, int>
V_movie_range (shared_ptr<Film> film)
{
- auto job = make_shared<TranscodeJob>(film);
+ auto job = make_shared<TranscodeJob>(film, TranscodeJob::ChangedBehaviour::IGNORE);
job->set_encoder (
make_shared<FFmpegEncoder>(film, job, film->file("export.mov"), ExportFormat::PRORES, true, false, false, 23)
);