2 Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /** @file src/j2k_wav_encoder.cc
21 * @brief An encoder which writes JPEG2000 and WAV files.
28 #include <boost/thread.hpp>
29 #include <boost/filesystem.hpp>
30 #include <boost/lexical_cast.hpp>
33 #include "j2k_wav_encoder.h"
35 #include "film_state.h"
37 #include "exceptions.h"
38 #include "dcp_video_frame.h"
45 using namespace boost;
47 J2KWAVEncoder::J2KWAVEncoder (shared_ptr<const FilmState> s, shared_ptr<const Options> o, Log* l)
49 #ifdef HAVE_SWRESAMPLE
52 , _deinterleave_buffer_size (8192)
53 , _deinterleave_buffer (0)
54 , _process_end (false)
56 /* Create sound output files with .tmp suffixes; we will rename
57 them if and when we complete.
59 for (int i = 0; i < _fs->audio_channels; ++i) {
61 sf_info.samplerate = dcp_audio_sample_rate (_fs->audio_sample_rate);
62 /* We write mono files */
64 sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
65 SNDFILE* f = sf_open (_opt->multichannel_audio_out_path (i, true).c_str (), SFM_WRITE, &sf_info);
67 throw CreateFileError (_opt->multichannel_audio_out_path (i, true));
69 _sound_files.push_back (f);
72 /* Create buffer for deinterleaving audio */
73 _deinterleave_buffer = new uint8_t[_deinterleave_buffer_size];
76 J2KWAVEncoder::~J2KWAVEncoder ()
78 terminate_worker_threads ();
79 delete[] _deinterleave_buffer;
84 J2KWAVEncoder::terminate_worker_threads ()
86 boost::mutex::scoped_lock lock (_worker_mutex);
88 _worker_condition.notify_all ();
91 for (list<boost::thread *>::iterator i = _worker_threads.begin(); i != _worker_threads.end(); ++i) {
98 J2KWAVEncoder::close_sound_files ()
100 for (vector<SNDFILE*>::iterator i = _sound_files.begin(); i != _sound_files.end(); ++i) {
104 _sound_files.clear ();
108 J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame)
110 boost::mutex::scoped_lock lock (_worker_mutex);
112 /* Wait until the queue has gone down a bit */
113 while (_queue.size() >= _worker_threads.size() * 2 && !_process_end) {
114 TIMING ("decoder sleeps with queue of %1", _queue.size());
115 _worker_condition.wait (lock);
116 TIMING ("decoder wakes with queue of %1", _queue.size());
123 /* Only do the processing if we don't already have a file for this frame */
124 if (!boost::filesystem::exists (_opt->frame_out_path (frame, false))) {
125 pair<string, string> const s = Filter::ffmpeg_strings (_fs->filters);
126 TIMING ("adding to queue of %1", _queue.size ());
127 _queue.push_back (boost::shared_ptr<DCPVideoFrame> (
129 yuv, _opt->out_size, _opt->padding, _fs->scaler, frame, _fs->frames_per_second, s.second,
130 Config::instance()->colour_lut_index (), Config::instance()->j2k_bandwidth (),
135 _worker_condition.notify_all ();
142 J2KWAVEncoder::encoder_thread (ServerDescription* server)
144 /* Number of seconds that we currently wait between attempts
145 to connect to the server; not relevant for localhost
148 int remote_backoff = 0;
152 TIMING ("encoder thread %1 sleeps", pthread_self ());
153 boost::mutex::scoped_lock lock (_worker_mutex);
154 while (_queue.empty () && !_process_end) {
155 _worker_condition.wait (lock);
162 TIMING ("encoder thread %1 wakes with queue of %2", pthread_self(), _queue.size());
163 boost::shared_ptr<DCPVideoFrame> vf = _queue.front ();
164 _log->log (String::compose ("Encoder thread %1 pops frame %2 from queue", pthread_self(), vf->frame()));
169 shared_ptr<EncodedData> encoded;
173 encoded = vf->encode_remotely (server);
175 if (remote_backoff > 0) {
176 _log->log (String::compose ("%1 was lost, but now she is found; removing backoff", server->host_name ()));
179 /* This job succeeded, so remove any backoff */
182 } catch (std::exception& e) {
183 if (remote_backoff < 60) {
185 remote_backoff += 10;
189 "Remote encode of %1 on %2 failed (%3); thread sleeping for %4s",
190 vf->frame(), server->host_name(), e.what(), remote_backoff)
196 TIMING ("encoder thread %1 begins local encode of %2", pthread_self(), vf->frame());
197 encoded = vf->encode_locally ();
198 TIMING ("encoder thread %1 finishes local encode of %2", pthread_self(), vf->frame());
199 } catch (std::exception& e) {
200 _log->log (String::compose ("Local encode failed (%1)", e.what ()));
205 encoded->write (_opt, vf->frame ());
206 frame_done (vf->frame ());
209 _queue.push_front (vf);
213 if (remote_backoff > 0) {
214 dvdomatic_sleep (remote_backoff);
218 _worker_condition.notify_all ();
223 J2KWAVEncoder::process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format)
225 if (_fs->audio_sample_rate != _fs->target_sample_rate ()) {
226 #ifdef HAVE_SWRESAMPLE
229 s << "Will resample audio from " << _fs->audio_sample_rate << " to " << _fs->target_sample_rate();
230 _log->log (s.str ());
232 _swr_context = swr_alloc_set_opts (
234 audio_channel_layout,
236 _fs->target_sample_rate(),
237 audio_channel_layout,
239 _fs->audio_sample_rate,
243 swr_init (_swr_context);
245 throw EncodeError ("Cannot resample audio as libswresample is not present");
248 #ifdef HAVE_SWRESAMPLE
253 for (int i = 0; i < Config::instance()->num_local_encoding_threads (); ++i) {
254 _worker_threads.push_back (new boost::thread (boost::bind (&J2KWAVEncoder::encoder_thread, this, (ServerDescription *) 0)));
257 vector<ServerDescription*> servers = Config::instance()->servers ();
259 for (vector<ServerDescription*>::iterator i = servers.begin(); i != servers.end(); ++i) {
260 for (int j = 0; j < (*i)->threads (); ++j) {
261 _worker_threads.push_back (new boost::thread (boost::bind (&J2KWAVEncoder::encoder_thread, this, *i)));
267 J2KWAVEncoder::process_end ()
269 boost::mutex::scoped_lock lock (_worker_mutex);
271 _log->log ("Clearing queue of " + lexical_cast<string> (_queue.size ()));
273 /* Keep waking workers until the queue is empty */
274 while (!_queue.empty ()) {
275 _log->log ("Waking with " + lexical_cast<string> (_queue.size ()));
276 _worker_condition.notify_all ();
277 _worker_condition.wait (lock);
282 terminate_worker_threads ();
284 _log->log ("Mopping up " + lexical_cast<string> (_queue.size()));
286 /* The following sequence of events can occur in the above code:
287 1. a remote worker takes the last image off the queue
288 2. the loop above terminates
289 3. the remote worker fails to encode the image and puts it back on the queue
290 4. the remote worker is then terminated by terminate_worker_threads
292 So just mop up anything left in the queue here.
295 for (list<shared_ptr<DCPVideoFrame> >::iterator i = _queue.begin(); i != _queue.end(); ++i) {
296 _log->log (String::compose ("Encode left-over frame %1", (*i)->frame ()));
298 shared_ptr<EncodedData> e = (*i)->encode_locally ();
299 e->write (_opt, (*i)->frame ());
300 frame_done ((*i)->frame ());
301 } catch (std::exception& e) {
302 _log->log (String::compose ("Local encode failed (%1)", e.what ()));
310 uint8_t buffer[256 * _fs->bytes_per_sample() * _fs->audio_channels];
316 int const frames = swr_convert (_swr_context, out, 256, 0, 0);
319 throw EncodeError ("could not run sample-rate converter");
326 write_audio (buffer, frames * _fs->bytes_per_sample() * _fs->audio_channels);
329 swr_free (&_swr_context);
333 close_sound_files ();
335 /* Rename .wav.tmp files to .wav */
336 for (int i = 0; i < _fs->audio_channels; ++i) {
337 if (boost::filesystem::exists (_opt->multichannel_audio_out_path (i, false))) {
338 boost::filesystem::remove (_opt->multichannel_audio_out_path (i, false));
340 boost::filesystem::rename (_opt->multichannel_audio_out_path (i, true), _opt->multichannel_audio_out_path (i, false));
345 J2KWAVEncoder::process_audio (uint8_t* data, int size)
347 /* This is a buffer we might use if we are sample-rate converting;
348 it will need freeing if so.
350 uint8_t* out_buffer = 0;
352 /* Maybe sample-rate convert */
356 uint8_t const * in[2] = {
361 /* Here's samples per channel */
362 int const samples = size / _fs->bytes_per_sample();
364 /* And here's frames (where 1 frame is a collection of samples, 1 for each channel,
365 so for 5.1 a frame would be 6 samples)
367 int const frames = samples / _fs->audio_channels;
369 /* Compute the resampled frame count and add 32 for luck */
370 int const out_buffer_size_frames = ceil (frames * _fs->target_sample_rate() / _fs->audio_sample_rate) + 32;
371 int const out_buffer_size_bytes = out_buffer_size_frames * _fs->audio_channels * _fs->bytes_per_sample();
372 out_buffer = new uint8_t[out_buffer_size_bytes];
380 int out_frames = swr_convert (_swr_context, out, out_buffer_size_frames, in, frames);
381 if (out_frames < 0) {
382 throw EncodeError ("could not run sample-rate converter");
385 /* And point our variables at the resampled audio */
387 size = out_frames * _fs->audio_channels * _fs->bytes_per_sample();
391 write_audio (data, size);
393 /* Delete the sample-rate conversion buffer, if it exists */
398 J2KWAVEncoder::write_audio (uint8_t* data, int size)
400 /* XXX: we are assuming that the _deinterleave_buffer_size is a multiple
401 of the sample size and that size is a multiple of _fs->audio_channels * sample_size.
404 assert ((size % (_fs->audio_channels * _fs->bytes_per_sample())) == 0);
405 assert ((_deinterleave_buffer_size % _fs->bytes_per_sample()) == 0);
407 /* XXX: this code is very tricksy and it must be possible to make it simpler ... */
409 /* Number of bytes left to read this time */
410 int remaining = size;
411 /* Our position in the output buffers, in bytes */
413 while (remaining > 0) {
414 /* How many bytes of the deinterleaved data to do this time */
415 int this_time = min (remaining / _fs->audio_channels, _deinterleave_buffer_size);
416 for (int i = 0; i < _fs->audio_channels; ++i) {
417 for (int j = 0; j < this_time; j += _fs->bytes_per_sample()) {
418 for (int k = 0; k < _fs->bytes_per_sample(); ++k) {
419 int const to = j + k;
420 int const from = position + (i * _fs->bytes_per_sample()) + (j * _fs->audio_channels) + k;
421 _deinterleave_buffer[to] = data[from];
425 switch (_fs->audio_sample_format) {
426 case AV_SAMPLE_FMT_S16:
427 sf_write_short (_sound_files[i], (const short *) _deinterleave_buffer, this_time / _fs->bytes_per_sample());
430 throw EncodeError ("unknown audio sample format");
434 position += this_time;
435 remaining -= this_time * _fs->audio_channels;