+AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content)
+ : _audio_content (content)
+ , _decoded_audio (shared_ptr<AudioBuffers> (new AudioBuffers (content->audio_channels(), 0)), 0)
+{
+ if (content->output_audio_frame_rate() != content->content_audio_frame_rate() && content->audio_channels ()) {
+ _resampler.reset (new Resampler (content->content_audio_frame_rate(), content->output_audio_frame_rate(), content->audio_channels ()));
+ }
+}
+
+shared_ptr<ContentAudio>
+AudioDecoder::get_audio (AudioFrame frame, AudioFrame length, bool accurate)
+{
+ shared_ptr<ContentAudio> dec;
+
+ AudioFrame const end = frame + length - 1;
+
+ if (frame < _decoded_audio.frame || end > (_decoded_audio.frame + length * 4)) {
+ /* Either we have no decoded data, or what we do have is a long way from what we want: seek */
+ seek (ContentTime::from_frames (frame, _audio_content->content_audio_frame_rate()), accurate);
+ }
+
+ /* Now enough pass() calls will either:
+ * (a) give us what we want, or
+ * (b) hit the end of the decoder.
+ *
+ * If we are being accurate, we want the right frames,
+ * otherwise any frames will do.
+ */
+ if (accurate) {
+ while (!pass() && _decoded_audio.audio->frames() < length) {}
+ } else {
+ while (!pass() && (_decoded_audio.frame > frame || (_decoded_audio.frame + _decoded_audio.audio->frames()) < end)) {}
+ }
+
+ /* Clean up decoded */
+
+ AudioFrame const decoded_offset = frame - _decoded_audio.frame;
+ AudioFrame const amount_left = _decoded_audio.audio->frames() - decoded_offset;
+ _decoded_audio.audio->move (decoded_offset, 0, amount_left);
+ _decoded_audio.audio->set_frames (amount_left);
+
+ shared_ptr<AudioBuffers> out (new AudioBuffers (_decoded_audio.audio->channels(), length));
+ out->copy_from (_decoded_audio.audio.get(), length, frame - _decoded_audio.frame, 0);
+
+ return shared_ptr<ContentAudio> (new ContentAudio (out, frame));
+}
+
+/** Called by subclasses when audio data is ready.
+ *
+ * Audio timestamping is made hard by many factors, but perhaps the most entertaining is resampling.
+ * We have to assume that we are feeding continuous data into the resampler, and so we get continuous
+ * data out. Hence we do the timestamping here, post-resampler, just by counting samples.
+ *
+ * The time is passed in here so that after a seek we can set up our _audio_position. The
+ * time is ignored once this has been done.
+ */
+void
+AudioDecoder::audio (shared_ptr<const AudioBuffers> data, ContentTime time)