diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/audio_buffers.cc | 12 | ||||
| -rw-r--r-- | src/lib/audio_buffers.h | 1 | ||||
| -rw-r--r-- | src/lib/audio_decoder.cc | 31 | ||||
| -rw-r--r-- | src/lib/audio_decoder.h | 2 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 2 | ||||
| -rw-r--r-- | src/lib/film.cc | 10 | ||||
| -rw-r--r-- | src/lib/film.h | 2 | ||||
| -rw-r--r-- | src/lib/player.cc | 38 | ||||
| -rw-r--r-- | src/lib/player.h | 1 | ||||
| -rw-r--r-- | src/lib/resampler.cc | 49 | ||||
| -rw-r--r-- | src/lib/resampler.h | 20 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.cc | 5 |
12 files changed, 136 insertions, 37 deletions
diff --git a/src/lib/audio_buffers.cc b/src/lib/audio_buffers.cc index 403babaf7..6d4eb8514 100644 --- a/src/lib/audio_buffers.cc +++ b/src/lib/audio_buffers.cc @@ -144,6 +144,18 @@ AudioBuffers::make_silent (int c) } } +void +AudioBuffers::make_silent (int from, int frames) +{ + assert ((from + frames) <= _allocated_frames); + + for (int c = 0; c < _channels; ++c) { + for (int i = from; i < (from + frames); ++i) { + _data[c][i] = 0; + } + } +} + /** Copy data from another AudioBuffers to this one. All channels are copied. * @param from AudioBuffers to copy from; must have the same number of channels as this. * @param frames_to_copy Number of frames to copy. diff --git a/src/lib/audio_buffers.h b/src/lib/audio_buffers.h index 47b8145a1..b450b83ec 100644 --- a/src/lib/audio_buffers.h +++ b/src/lib/audio_buffers.h @@ -50,6 +50,7 @@ public: void make_silent (); void make_silent (int c); + void make_silent (int from, int frames); void copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset); void move (int from, int to, int frames); diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index dc49a1846..3b97cc16f 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -31,41 +31,12 @@ using std::cout; using boost::optional; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr<const Film> f) +AudioDecoder::AudioDecoder (shared_ptr<const Film> f, shared_ptr<const AudioContent> c) : Decoder (f) , _audio_position (0) { -} - -#if 0 -void -AudioDecoder::process_end () -{ - if (_swr_context) { - - shared_ptr<const Film> film = _film.lock (); - assert (film); - - shared_ptr<AudioBuffers> out (new AudioBuffers (film->audio_mapping().dcp_channels(), 256)); - - while (1) { - int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0); - - if (frames < 0) { - throw EncodeError (_("could not run sample-rate converter")); - } - - if (frames == 0) { - break; - } - - out->set_frames (frames); - _writer->write (out); - } - } } -#endif void AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame frame) diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index ddfb296c9..d3f12ab84 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -35,7 +35,7 @@ class AudioBuffers; class AudioDecoder : public virtual Decoder { public: - AudioDecoder (boost::shared_ptr<const Film>); + AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const AudioContent>); /** Emitted when some audio data is ready */ boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame)> Audio; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index fddb70294..b2eb1dbde 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -59,7 +59,7 @@ using libdcp::Size; FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegContent> c, bool video, bool audio) : Decoder (f) , VideoDecoder (f) - , AudioDecoder (f) + , AudioDecoder (f, c) , SubtitleDecoder (f) , FFmpeg (c) , _subtitle_codec_context (0) diff --git a/src/lib/film.cc b/src/lib/film.cc index dad9d6808..16b34110c 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -626,6 +626,16 @@ Film::set_dcp_video_frame_rate (int f) } void +Film::set_dcp_audio_channels (int c) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _dcp_audio_channels = c; + } + signal_changed (DCP_AUDIO_CHANNELS); +} + +void Film::signal_changed (Property p) { { diff --git a/src/lib/film.h b/src/lib/film.h index 08fdc587b..2bf1a0e90 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -139,6 +139,7 @@ public: J2K_BANDWIDTH, DCI_METADATA, DCP_VIDEO_FRAME_RATE, + DCP_AUDIO_CHANNELS }; @@ -221,6 +222,7 @@ public: void set_j2k_bandwidth (int); void set_dci_metadata (DCIMetadata); void set_dcp_video_frame_rate (int); + void set_dcp_audio_channels (int); void set_dci_date_today (); /** Emitted when some property has of the Film has changed */ diff --git a/src/lib/player.cc b/src/lib/player.cc index 58ba57bdc..7ab72d9a1 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -260,8 +260,10 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content); assert (content); + /* Resample */ if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) { - audio = resampler(content)->run (audio); + shared_ptr<Resampler> r = resampler (content); + audio = r->run (audio); } /* Remap channels */ @@ -274,15 +276,40 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers audio = dcp_mapped; + Time time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate()) + (content->audio_delay() * TIME_HZ / 1000); + + /* We must cut off anything that comes before the start of all time */ + if (time < 0) { + int const frames = - time * _film->dcp_audio_frame_rate() / TIME_HZ; + if (frames >= audio->frames ()) { + return; + } + + shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames)); + trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0); + + audio = trimmed; + time = 0; + } + /* The time of this audio may indicate that some of our buffered audio is not going to be added to any more, so it can be emitted. */ - Time const time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate()); - if (time > _audio_position) { /* We can emit some audio from our buffers */ OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position); + if (N > _audio_buffers.frames()) { + /* We need some extra silence before whatever is in the buffers */ + _audio_buffers.ensure_size (N); + _audio_buffers.move (0, N - _audio_buffers.frames(), _audio_buffers.frames ()); + _audio_buffers.make_silent (0, _audio_buffers.frames()); + _audio_buffers.set_frames (N); + } + + if (N > _audio_buffers.frames()) { + cout << "N=" << N << ", ab=" << _audio_buffers.frames() << "\n"; + } assert (N <= _audio_buffers.frames()); shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N)); emit->copy_from (&_audio_buffers, N, 0, 0); @@ -521,6 +548,11 @@ Player::update_subtitle () return; } + if (!_in_subtitle.image) { + _out_subtitle.image.reset (); + return; + } + shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content); assert (sc); diff --git a/src/lib/player.h b/src/lib/player.h index 5a4ee97be..b3eadd7c0 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -110,6 +110,7 @@ private: libdcp::Size _video_container_size; boost::shared_ptr<Image> _black_frame; std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers; + boost::shared_ptr<Resampler> _last_resampler; struct { boost::weak_ptr<Piece> piece; diff --git a/src/lib/resampler.cc b/src/lib/resampler.cc index 1235b9038..565fb69c2 100644 --- a/src/lib/resampler.cc +++ b/src/lib/resampler.cc @@ -1,3 +1,22 @@ +/* + Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + extern "C" { #include "libavutil/channel_layout.h" } @@ -7,6 +26,7 @@ extern "C" { #include "i18n.h" +using std::cout; using boost::shared_ptr; Resampler::Resampler (int in, int out, int channels) @@ -59,3 +79,32 @@ Resampler::run (shared_ptr<const AudioBuffers> in) resampled->set_frames (resampled_frames); return resampled; } + +/* XXX: no-one calls this */ +shared_ptr<const AudioBuffers> +Resampler::flush () +{ + shared_ptr<AudioBuffers> out (new AudioBuffers (_channels, 0)); + int out_offset = 0; + int64_t const pass_size = 256; + shared_ptr<AudioBuffers> pass (new AudioBuffers (_channels, 256)); + + while (1) { + int const frames = swr_convert (_swr_context, (uint8_t **) pass->data(), pass_size, 0, 0); + + if (frames < 0) { + throw EncodeError (_("could not run sample-rate converter")); + } + + if (frames == 0) { + break; + } + + out->ensure_size (out_offset + frames); + out->copy_from (pass.get(), frames, 0, out_offset); + out_offset += frames; + out->set_frames (out_offset); + } + + return out; +} diff --git a/src/lib/resampler.h b/src/lib/resampler.h index cda718934..7c85773c0 100644 --- a/src/lib/resampler.h +++ b/src/lib/resampler.h @@ -1,3 +1,22 @@ +/* + Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #include <boost/shared_ptr.hpp> extern "C" { #include <libswresample/swresample.h> @@ -12,6 +31,7 @@ public: ~Resampler (); boost::shared_ptr<const AudioBuffers> run (boost::shared_ptr<const AudioBuffers>); + boost::shared_ptr<const AudioBuffers> flush (); private: SwrContext* _swr_context; diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 80a6afd2b..8374abbe9 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -35,10 +35,11 @@ using boost::shared_ptr; SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c) : Decoder (f) - , AudioDecoder (f) + , AudioDecoder (f, c) , _sndfile_content (c) , _deinterleave_buffer (0) { + _info.format = 0; _sndfile = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &_info); if (!_sndfile) { throw DecodeError (_("could not open audio file for reading")); @@ -89,7 +90,7 @@ SndfileDecoder::pass () } data->set_frames (this_time); - audio (data, double(_done) / audio_frame_rate()); + audio (data, _done); _done += this_time; _remaining -= this_time; } |
