diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-07-25 22:04:20 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-07-25 22:04:20 +0100 |
| commit | 78e5a331074a456097a162d47501daf1df1ab1a3 (patch) | |
| tree | 17dbc6cd0e3e6a4878277959d7cd86129fb516b4 /src/lib | |
| parent | 991244a0d4be149e8733a8dd70bfd745cab72583 (diff) | |
Hopefully much cleaner handling of PTS changes under resample.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/audio_decoder.cc | 28 | ||||
| -rw-r--r-- | src/lib/audio_decoder.h | 7 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/player.cc | 40 | ||||
| -rw-r--r-- | src/lib/player.h | 3 | ||||
| -rw-r--r-- | src/lib/resampler.cc | 10 | ||||
| -rw-r--r-- | src/lib/resampler.h | 4 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.cc | 2 |
8 files changed, 60 insertions, 38 deletions
diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index 846cdf595..1f5868583 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -32,36 +32,16 @@ using std::cout; using boost::optional; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr<const Film> film, shared_ptr<const AudioContent> content) +AudioDecoder::AudioDecoder (shared_ptr<const Film> film) : Decoder (film) , _audio_position (0) { - if (content->content_audio_frame_rate() != content->output_audio_frame_rate() && content->audio_channels ()) { - _resampler.reset ( - new Resampler ( - content->content_audio_frame_rate(), - content->output_audio_frame_rate(), - content->audio_channels() - ) - ); - } -} - -void -AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame) -{ - if (_resampler) { - data = _resampler->run (data); - } - Audio (data, _audio_position); - _audio_position += data->frames (); } void -AudioDecoder::flush () +AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame frame) { - if (_resampler) { - _resampler->flush (); - } + Audio (data, frame); + _audio_position = frame + data->frames (); } diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index e2d28d707..2ad53da8b 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -29,7 +29,6 @@ #include "audio_content.h" class AudioBuffers; -class Resampler; /** @class AudioDecoder. * @brief Parent class for audio decoders. @@ -37,19 +36,15 @@ class Resampler; class AudioDecoder : public virtual Decoder { public: - AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const AudioContent>); + AudioDecoder (boost::shared_ptr<const Film>); /** Emitted when some audio data is ready */ boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame)> Audio; protected: - void flush (); - void audio (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame); - /** Frame index of next emission (post resampling) */ AudioContent::Frame _audio_position; - boost::shared_ptr<Resampler> _resampler; }; #endif diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index e2e5b9d64..58745598a 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -60,7 +60,7 @@ using libdcp::Size; FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegContent> c, bool video, bool audio) : Decoder (f) , VideoDecoder (f, c) - , AudioDecoder (f, c) + , AudioDecoder (f) , SubtitleDecoder (f) , FFmpeg (c) , _subtitle_codec_context (0) @@ -140,8 +140,6 @@ FFmpegDecoder::flush () decode_audio_packet (); } - AudioDecoder::flush (); - /* Stop us being asked for any more data */ _video_position = _ffmpeg_content->video_length (); _audio_position = _ffmpeg_content->audio_length (); diff --git a/src/lib/player.cc b/src/lib/player.cc index 1ab164d86..620efbd0d 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -31,6 +31,7 @@ #include "job.h" #include "image.h" #include "ratio.h" +#include "resampler.h" #include "log.h" #include "scaler.h" @@ -190,6 +191,19 @@ Player::pass () cout << "Pass " << *earliest << "\n"; #endif earliest->decoder->pass (); + + if (earliest->decoder->done()) { + shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content); + assert (ac); + shared_ptr<Resampler> re = resampler (ac, false); + if (re) { + shared_ptr<const AudioBuffers> b = re->flush (); + if (b->frames ()) { + process_audio (earliest, b, ac->audio_length ()); + } + } + } + } break; } @@ -264,6 +278,14 @@ 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()) { + shared_ptr<Resampler> r = resampler (content, true); + pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame); + audio = ro.first; + frame = ro.second; + } + /* Remap channels */ shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames())); dcp_mapped->make_silent (); @@ -314,6 +336,7 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N)); emit->copy_from (&_audio_buffers, N, 0, 0); Audio (emit, _audio_position); + _audio_position = piece->audio_position = _audio_position + _film->audio_frames_to_time (N); /* And remove it from our buffers */ @@ -497,6 +520,23 @@ Player::set_video_container_size (libdcp::Size s) _black_frame->make_black (); } +shared_ptr<Resampler> +Player::resampler (shared_ptr<AudioContent> c, bool create) +{ + map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c); + if (i != _resamplers.end ()) { + return i->second; + } + + if (!create) { + return shared_ptr<Resampler> (); + } + + shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels())); + _resamplers[c] = r; + return r; +} + void Player::emit_black () { diff --git a/src/lib/player.h b/src/lib/player.h index 5b1b6936b..cd480dd1a 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -35,6 +35,7 @@ class Playlist; class AudioContent; class Piece; class Image; +class Resampler; /** @class Player * @brief A class which can `play' a Playlist; emitting its audio and video. @@ -89,6 +90,7 @@ private: void flush (); void emit_black (); void emit_silence (OutputAudioFrame); + boost::shared_ptr<Resampler> resampler (boost::shared_ptr<AudioContent>, bool); void film_changed (Film::Property); void update_subtitle (); @@ -111,6 +113,7 @@ private: libdcp::Size _video_container_size; boost::shared_ptr<Image> _black_frame; + std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers; struct { boost::weak_ptr<Piece> piece; diff --git a/src/lib/resampler.cc b/src/lib/resampler.cc index cc5072442..7bc933fd0 100644 --- a/src/lib/resampler.cc +++ b/src/lib/resampler.cc @@ -27,6 +27,8 @@ extern "C" { #include "i18n.h" using std::cout; +using std::pair; +using std::make_pair; using boost::shared_ptr; Resampler::Resampler (int in, int out, int channels) @@ -61,9 +63,11 @@ Resampler::~Resampler () swr_free (&_swr_context); } -shared_ptr<const AudioBuffers> -Resampler::run (shared_ptr<const AudioBuffers> in) +pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> +Resampler::run (shared_ptr<const AudioBuffers> in, AudioContent::Frame frame) { + AudioContent::Frame const resamp_time = swr_next_pts (_swr_context, frame * _out_rate) / _in_rate; + /* Compute the resampled frames count and add 32 for luck */ int const max_resampled_frames = ceil ((double) in->frames() * _out_rate / _in_rate) + 32; shared_ptr<AudioBuffers> resampled (new AudioBuffers (_channels, max_resampled_frames)); @@ -77,7 +81,7 @@ Resampler::run (shared_ptr<const AudioBuffers> in) } resampled->set_frames (resampled_frames); - return resampled; + return make_pair (resampled, resamp_time); } shared_ptr<const AudioBuffers> diff --git a/src/lib/resampler.h b/src/lib/resampler.h index 6e282838a..69ec83ba9 100644 --- a/src/lib/resampler.h +++ b/src/lib/resampler.h @@ -22,6 +22,8 @@ extern "C" { #include <libswresample/swresample.h> } +#include "types.h" +#include "audio_content.h" class AudioBuffers; @@ -31,7 +33,7 @@ public: Resampler (int, int, int); ~Resampler (); - boost::shared_ptr<const AudioBuffers> run (boost::shared_ptr<const AudioBuffers>); + std::pair<boost::shared_ptr<const AudioBuffers>, AudioContent::Frame> run (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame); boost::shared_ptr<const AudioBuffers> flush (); private: diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 09ccf4fbc..1fc1ecaf2 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -35,7 +35,7 @@ using boost::shared_ptr; SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c) : Decoder (f) - , AudioDecoder (f, c) + , AudioDecoder (f) , _sndfile_content (c) , _deinterleave_buffer (0) { |
