2 Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 /** @file src/transcode_job.cc
22 * @brief A job which transcodes from one format to another.
25 #include "transcode_job.h"
26 #include "dcp_encoder.h"
27 #include "upload_job.h"
28 #include "job_manager.h"
32 #include "dcpomatic_log.h"
33 #include "compose.hpp"
34 #include "analytics.h"
42 using std::setprecision;
44 using boost::shared_ptr;
45 using boost::optional;
46 using boost::dynamic_pointer_cast;
48 /** @param film Film to use */
49 TranscodeJob::TranscodeJob (shared_ptr<const Film> film)
55 TranscodeJob::~TranscodeJob ()
57 /* We have to stop the job thread here as we're about to start tearing down
58 the Encoder, which is bad news if the job thread is still feeding it data.
64 TranscodeJob::name () const
66 return String::compose (_("Transcoding %1"), _film->name());
70 TranscodeJob::json_name () const
72 return N_("transcode");
76 TranscodeJob::set_encoder (shared_ptr<Encoder> e)
86 gettimeofday (&start, 0);
87 LOG_GENERAL_NC (N_("Transcode job starting"));
89 DCPOMATIC_ASSERT (_encoder);
92 struct timeval finish;
93 gettimeofday (&finish, 0);
96 if (finish.tv_sec != start.tv_sec) {
97 fps = _encoder->frames_done() / (finish.tv_sec - start.tv_sec);
100 LOG_GENERAL (N_("Transcode job completed successfully: %1 fps"), fps);
102 if (dynamic_pointer_cast<DCPEncoder>(_encoder)) {
103 Analytics::instance()->successful_dcp_encode();
106 /* XXX: this shouldn't be here */
107 if (_film->upload_after_make_dcp() && dynamic_pointer_cast<DCPEncoder>(_encoder)) {
108 shared_ptr<Job> job (new UploadJob (_film));
109 JobManager::instance()->add (job);
115 set_state (FINISHED_OK);
124 TranscodeJob::status () const
127 return Job::status ();
132 if (finished() || _encoder->finishing()) {
133 strncpy (buffer, Job::status().c_str(), 255);
137 buffer, sizeof(buffer), "%s; %" PRId64 "/%" PRId64 " frames",
138 Job::status().c_str(),
139 _encoder->frames_done(),
140 _film->length().frames_round (_film->video_frame_rate ())
143 optional<float> const fps = _encoder->current_rate ();
146 /// TRANSLATORS: fps here is an abbreviation for frames per second
147 snprintf (fps_buffer, sizeof(fps_buffer), _("; %.1f fps"), *fps);
148 strncat (buffer, fps_buffer, strlen(buffer) - 1);
155 /** @return Approximate remaining time in seconds */
157 TranscodeJob::remaining_time () const
159 /* _encoder might be destroyed by the job-runner thread */
160 shared_ptr<Encoder> e = _encoder;
162 if (!e || e->finishing()) {
163 /* We aren't doing any actual encoding so just use the job's guess */
164 return Job::remaining_time ();
167 /* We're encoding so guess based on the current encoding rate */
169 optional<float> fps = e->current_rate ();
175 /* Compute approximate proposed length here, as it's only here that we need it */
176 return (_film->length().frames_round(_film->video_frame_rate()) - e->frames_done()) / *fps;