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::dynamic_pointer_cast;
47 /** @param film Film to use */
48 TranscodeJob::TranscodeJob (shared_ptr<const Film> film)
54 TranscodeJob::~TranscodeJob ()
56 /* We have to stop the job thread here as we're about to start tearing down
57 the Encoder, which is bad news if the job thread is still feeding it data.
63 TranscodeJob::name () const
65 return String::compose (_("Transcoding %1"), _film->name());
69 TranscodeJob::json_name () const
71 return N_("transcode");
75 TranscodeJob::set_encoder (shared_ptr<Encoder> e)
85 gettimeofday (&start, 0);
86 LOG_GENERAL_NC (N_("Transcode job starting"));
88 DCPOMATIC_ASSERT (_encoder);
91 set_state (FINISHED_OK);
93 struct timeval finish;
94 gettimeofday (&finish, 0);
97 if (finish.tv_sec != start.tv_sec) {
98 fps = _encoder->frames_done() / (finish.tv_sec - start.tv_sec);
101 LOG_GENERAL (N_("Transcode job completed successfully: %1 fps"), fps);
103 if (dynamic_pointer_cast<DCPEncoder>(_encoder)) {
104 Analytics::instance()->successful_dcp_encode();
107 /* XXX: this shouldn't be here */
108 if (_film->upload_after_make_dcp() && dynamic_pointer_cast<DCPEncoder>(_encoder)) {
109 shared_ptr<Job> job (new UploadJob (_film));
110 JobManager::instance()->add (job);
122 TranscodeJob::status () const
125 return Job::status ();
130 if (finished() || _encoder->finishing()) {
131 strncpy (buffer, Job::status().c_str(), 255);
135 buffer, sizeof(buffer), "%s; %" PRId64 "/%" PRId64 " frames",
136 Job::status().c_str(),
137 _encoder->frames_done(),
138 _film->length().frames_round (_film->video_frame_rate ())
141 float const fps = _encoder->current_rate ();
144 /// TRANSLATORS: fps here is an abbreviation for frames per second
145 snprintf (fps_buffer, sizeof(fps_buffer), _("; %.1f fps"), fps);
146 strncat (buffer, fps_buffer, strlen(buffer) - 1);
153 /** @return Approximate remaining time in seconds */
155 TranscodeJob::remaining_time () const
157 /* _encoder might be destroyed by the job-runner thread */
158 shared_ptr<Encoder> e = _encoder;
160 if (!e || e->finishing()) {
161 /* We aren't doing any actual encoding so just use the job's guess */
162 return Job::remaining_time ();
165 /* We're encoding so guess based on the current encoding rate */
167 float fps = e->current_rate ();
173 /* Compute approximate proposed length here, as it's only here that we need it */
174 return (_film->length().frames_round (_film->video_frame_rate ()) - e->frames_done()) / fps;