summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_buffers.cc12
-rw-r--r--src/lib/audio_buffers.h1
-rw-r--r--src/lib/audio_decoder.cc31
-rw-r--r--src/lib/audio_decoder.h2
-rw-r--r--src/lib/ffmpeg_decoder.cc2
-rw-r--r--src/lib/film.cc10
-rw-r--r--src/lib/film.h2
-rw-r--r--src/lib/player.cc38
-rw-r--r--src/lib/player.h1
-rw-r--r--src/lib/resampler.cc49
-rw-r--r--src/lib/resampler.h20
-rw-r--r--src/lib/sndfile_decoder.cc5
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;
}