Supporters update.
[dcpomatic.git] / src / lib / ffmpeg_encoder.cc
1 /*
2     Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21
22 #include "butler.h"
23 #include "cross.h"
24 #include "ffmpeg_encoder.h"
25 #include "film.h"
26 #include "image.h"
27 #include "job.h"
28 #include "log.h"
29 #include "player.h"
30 #include "player_video.h"
31 #include "compose.hpp"
32 #include <iostream>
33
34 #include "i18n.h"
35
36
37 using std::cout;
38 using std::list;
39 using std::make_shared;
40 using std::shared_ptr;
41 using std::string;
42 using std::weak_ptr;
43 using boost::bind;
44 using boost::optional;
45 using namespace dcpomatic;
46 #if BOOST_VERSION >= 106100
47 using namespace boost::placeholders;
48 #endif
49
50
51 FFmpegEncoder::FFmpegEncoder (
52         shared_ptr<const Film> film,
53         weak_ptr<Job> job,
54         boost::filesystem::path output,
55         ExportFormat format,
56         bool mixdown_to_stereo,
57         bool split_reels,
58         bool audio_stream_per_channel,
59         int x264_crf
60         )
61         : Encoder (film, job)
62         , _output_audio_channels(mixdown_to_stereo ? 2 : (_film->audio_channels() > 8 ? 16 : _film->audio_channels()))
63         , _history (200)
64         , _output (output)
65         , _format (format)
66         , _split_reels (split_reels)
67         , _audio_stream_per_channel (audio_stream_per_channel)
68         , _x264_crf (x264_crf)
69         , _butler(
70                 _film,
71                 _player,
72                 mixdown_to_stereo ? stereo_map() : many_channel_map(),
73                 _output_audio_channels,
74                 boost::bind(&PlayerVideo::force, FFmpegFileEncoder::pixel_format(format)),
75                 VideoRange::VIDEO,
76                 Image::Alignment::PADDED,
77                 false,
78                 false,
79                 Butler::Audio::ENABLED
80                 )
81 {
82         _player.set_always_burn_open_subtitles();
83         _player.set_play_referenced();
84 }
85
86
87 AudioMapping
88 FFmpegEncoder::stereo_map() const
89 {
90         auto map = AudioMapping(_film->audio_channels(), 2);
91         float const overall_gain = 2 / (4 + sqrt(2));
92         float const minus_3dB = 1 / sqrt(2);
93         switch (_film->audio_channels()) {
94         case 2:
95                 map.set(dcp::Channel::LEFT, 0, 1);
96                 map.set(dcp::Channel::RIGHT, 1, 1);
97                 break;
98         case 4:
99                 map.set(dcp::Channel::LEFT,   0, overall_gain);
100                 map.set(dcp::Channel::RIGHT,  1, overall_gain);
101                 map.set(dcp::Channel::CENTRE, 0, overall_gain * minus_3dB);
102                 map.set(dcp::Channel::CENTRE, 1, overall_gain * minus_3dB);
103                 map.set(dcp::Channel::LS,     0, overall_gain);
104                 break;
105         case 6:
106                 map.set(dcp::Channel::LEFT,   0, overall_gain);
107                 map.set(dcp::Channel::RIGHT,  1, overall_gain);
108                 map.set(dcp::Channel::CENTRE, 0, overall_gain * minus_3dB);
109                 map.set(dcp::Channel::CENTRE, 1, overall_gain * minus_3dB);
110                 map.set(dcp::Channel::LS,     0, overall_gain);
111                 map.set(dcp::Channel::RS,     1, overall_gain);
112                 break;
113         }
114         /* XXX: maybe we should do something better for >6 channel DCPs */
115         return map;
116 }
117
118
119 AudioMapping
120 FFmpegEncoder::many_channel_map() const
121 {
122         auto map = AudioMapping(_film->audio_channels(), _output_audio_channels);
123         for (int i = 0; i < _film->audio_channels(); ++i) {
124                 map.set(i, i, 1);
125         }
126         return map;
127 }
128
129
130 void
131 FFmpegEncoder::go ()
132 {
133         {
134                 auto job = _job.lock ();
135                 DCPOMATIC_ASSERT (job);
136                 job->sub (_("Encoding"));
137         }
138
139         Waker waker;
140
141         list<FileEncoderSet> file_encoders;
142
143         int const files = _split_reels ? _film->reels().size() : 1;
144         for (int i = 0; i < files; ++i) {
145
146                 boost::filesystem::path filename = _output;
147                 auto extension = dcp::filesystem::extension(filename);
148                 filename = dcp::filesystem::change_extension(filename, "");
149
150                 if (files > 1) {
151                         /// TRANSLATORS: _reel%1 here is to be added to an export filename to indicate
152                         /// which reel it is.  Preserve the %1; it will be replaced with the reel number.
153                         filename = filename.string() + String::compose(_("_reel%1"), i + 1);
154                 }
155
156                 file_encoders.push_back (
157                         FileEncoderSet (
158                                 _film->frame_size(),
159                                 _film->video_frame_rate(),
160                                 _film->audio_frame_rate(),
161                                 _output_audio_channels,
162                                 _format,
163                                 _audio_stream_per_channel,
164                                 _x264_crf,
165                                 _film->three_d(),
166                                 filename,
167                                 extension
168                                 )
169                         );
170         }
171
172         auto reel_periods = _film->reels ();
173         auto reel = reel_periods.begin ();
174         auto encoder = file_encoders.begin ();
175
176         auto const video_frame = DCPTime::from_frames (1, _film->video_frame_rate ());
177         int const audio_frames = video_frame.frames_round(_film->audio_frame_rate());
178         std::vector<float> interleaved(_output_audio_channels * audio_frames);
179         auto deinterleaved = make_shared<AudioBuffers>(_output_audio_channels, audio_frames);
180         int const gets_per_frame = _film->three_d() ? 2 : 1;
181         for (DCPTime time; time < _film->length(); time += video_frame) {
182
183                 if (file_encoders.size() > 1 && !reel->contains(time)) {
184                         /* Next reel and file */
185                         ++reel;
186                         ++encoder;
187                         DCPOMATIC_ASSERT (reel != reel_periods.end());
188                         DCPOMATIC_ASSERT (encoder != file_encoders.end());
189                 }
190
191                 for (int j = 0; j < gets_per_frame; ++j) {
192                         Butler::Error e;
193                         auto video = _butler.get_video(Butler::Behaviour::BLOCKING, &e);
194                         _butler.rethrow();
195                         if (video.first) {
196                                 auto fe = encoder->get(video.first->eyes());
197                                 if (fe) {
198                                         fe->video(video.first, video.second - reel->from);
199                                 }
200                         } else {
201                                 if (e.code != Butler::Error::Code::FINISHED) {
202                                         throw DecodeError(String::compose("Error during decoding: %1", e.summary()));
203                                 }
204                         }
205                 }
206
207                 _history.event ();
208
209                 {
210                         boost::mutex::scoped_lock lm (_mutex);
211                         _last_time = time;
212                 }
213
214                 auto job = _job.lock ();
215                 if (job) {
216                         job->set_progress(float(time.get()) / _film->length().get());
217                 }
218
219                 waker.nudge ();
220
221                 _butler.get_audio(Butler::Behaviour::BLOCKING, interleaved.data(), audio_frames);
222                 /* XXX: inefficient; butler interleaves and we deinterleave again */
223                 float* p = interleaved.data();
224                 for (int j = 0; j < audio_frames; ++j) {
225                         for (int k = 0; k < _output_audio_channels; ++k) {
226                                 deinterleaved->data(k)[j] = *p++;
227                         }
228                 }
229                 encoder->audio (deinterleaved);
230         }
231
232         for (auto i: file_encoders) {
233                 i.flush ();
234         }
235 }
236
237 optional<float>
238 FFmpegEncoder::current_rate () const
239 {
240         return _history.rate ();
241 }
242
243 Frame
244 FFmpegEncoder::frames_done () const
245 {
246         boost::mutex::scoped_lock lm (_mutex);
247         return _last_time.frames_round (_film->video_frame_rate ());
248 }
249
250 FFmpegEncoder::FileEncoderSet::FileEncoderSet (
251         dcp::Size video_frame_size,
252         int video_frame_rate,
253         int audio_frame_rate,
254         int channels,
255         ExportFormat format,
256         bool audio_stream_per_channel,
257         int x264_crf,
258         bool three_d,
259         boost::filesystem::path output,
260         string extension
261         )
262 {
263         if (three_d) {
264                 _encoders[Eyes::LEFT] = make_shared<FFmpegFileEncoder>(
265                         video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
266                         // TRANSLATORS: L here is an abbreviation for "left", to indicate the left-eye part of a 3D export
267                         audio_stream_per_channel, x264_crf, String::compose("%1_%2%3", output.string(), _("L"), extension)
268                         );
269                 _encoders[Eyes::RIGHT] = make_shared<FFmpegFileEncoder>(
270                         video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
271                         // TRANSLATORS: R here is an abbreviation for "right", to indicate the right-eye part of a 3D export
272                         audio_stream_per_channel, x264_crf, String::compose("%1_%2%3", output.string(), _("R"), extension)
273                         );
274         } else {
275                 _encoders[Eyes::BOTH] = make_shared<FFmpegFileEncoder>(
276                         video_frame_size, video_frame_rate, audio_frame_rate, channels, format,
277                         audio_stream_per_channel, x264_crf, String::compose("%1%2", output.string(), extension)
278                         );
279         }
280 }
281
282 shared_ptr<FFmpegFileEncoder>
283 FFmpegEncoder::FileEncoderSet::get (Eyes eyes) const
284 {
285         if (_encoders.size() == 1) {
286                 /* We are doing a 2D export... */
287                 if (eyes == Eyes::LEFT) {
288                         /* ...but we got some 3D data; put the left eye into the output... */
289                         eyes = Eyes::BOTH;
290                 } else if (eyes == Eyes::RIGHT) {
291                         /* ...and ignore the right eye.*/
292                         return {};
293                 }
294         }
295
296         auto i = _encoders.find (eyes);
297         DCPOMATIC_ASSERT (i != _encoders.end());
298         return i->second;
299 }
300
301 void
302 FFmpegEncoder::FileEncoderSet::flush ()
303 {
304         for (auto& i: _encoders) {
305                 i.second->flush ();
306         }
307 }
308
309 void
310 FFmpegEncoder::FileEncoderSet::audio (shared_ptr<AudioBuffers> a)
311 {
312         for (auto& i: _encoders) {
313                 i.second->audio (a);
314         }
315 }