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 set_state (FINISHED_OK);
94 struct timeval finish;
95 gettimeofday (&finish, 0);
98 if (finish.tv_sec != start.tv_sec) {
99 fps = _encoder->frames_done() / (finish.tv_sec - start.tv_sec);
102 LOG_GENERAL (N_("Transcode job completed successfully: %1 fps"), fps);
104 if (dynamic_pointer_cast<DCPEncoder>(_encoder)) {
105 Analytics::instance()->successful_dcp_encode();
108 /* XXX: this shouldn't be here */
109 if (_film->upload_after_make_dcp() && dynamic_pointer_cast<DCPEncoder>(_encoder)) {
110 shared_ptr<Job> job (new UploadJob (_film));
111 JobManager::instance()->add (job);
123 TranscodeJob::status () const
126 return Job::status ();
131 if (finished() || _encoder->finishing()) {
132 strncpy (buffer, Job::status().c_str(), 255);
136 buffer, sizeof(buffer), "%s; %" PRId64 "/%" PRId64 " frames",
137 Job::status().c_str(),
138 _encoder->frames_done(),
139 _film->length().frames_round (_film->video_frame_rate ())
142 optional<float> const fps = _encoder->current_rate ();
145 /// TRANSLATORS: fps here is an abbreviation for frames per second
146 snprintf (fps_buffer, sizeof(fps_buffer), _("; %.1f fps"), *fps);
147 strncat (buffer, fps_buffer, strlen(buffer) - 1);
154 /** @return Approximate remaining time in seconds */
156 TranscodeJob::remaining_time () const
158 /* _encoder might be destroyed by the job-runner thread */
159 shared_ptr<Encoder> e = _encoder;
161 if (!e || e->finishing()) {
162 /* We aren't doing any actual encoding so just use the job's guess */
163 return Job::remaining_time ();
166 /* We're encoding so guess based on the current encoding rate */
168 optional<float> fps = e->current_rate ();
174 /* Compute approximate proposed length here, as it's only here that we need it */
175 return (_film->length().frames_round(_film->video_frame_rate()) - e->frames_done()) / *fps;