X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Faudio_decoder_stream.cc;h=150e7c2429f0f329e33ee3819dc6bbbff726fa16;hb=02cc8c7680381c123a31c23a43f6b34a04c2115a;hp=97db8a93f9ca61d392429144ff6196ba345b4084;hpb=f26af8112b03b5233eb5239defd11a7428b705ad;p=dcpomatic.git diff --git a/src/lib/audio_decoder_stream.cc b/src/lib/audio_decoder_stream.cc index 97db8a93f..150e7c242 100644 --- a/src/lib/audio_decoder_stream.cc +++ b/src/lib/audio_decoder_stream.cc @@ -1,19 +1,20 @@ /* - Copyright (C) 2012-2015 Carl Hetherington + Copyright (C) 2012-2016 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of DCP-o-matic. + + DCP-o-matic 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, + DCP-o-matic 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. + along with DCP-o-matic. If not, see . */ @@ -39,13 +40,18 @@ using std::max; using boost::optional; using boost::shared_ptr; -AudioDecoderStream::AudioDecoderStream (shared_ptr content, AudioStreamPtr stream, AudioDecoder* decoder) +AudioDecoderStream::AudioDecoderStream (shared_ptr content, AudioStreamPtr stream, Decoder* decoder, shared_ptr log) : _content (content) , _stream (stream) , _decoder (decoder) + , _log (log) + /* We effectively start having done a seek to zero; this allows silence-padding of the first + data that comes out of our decoder. + */ + , _seek_reference (ContentTime ()) { - if (content->resampled_audio_frame_rate() != _stream->frame_rate() && _stream->channels() > 0) { - _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_audio_frame_rate(), _stream->channels (), decoder->fast ())); + if (content->resampled_frame_rate() != _stream->frame_rate() && _stream->channels() > 0) { + _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_frame_rate(), _stream->channels ())); } reset_decoded (); @@ -62,13 +68,19 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate) { shared_ptr dec; - _content->film()->log()->log (String::compose ("-> ADS has request for %1 %2", frame, length), Log::TYPE_DEBUG_DECODE); + _log->log (String::compose ("-> ADS has request for %1 %2", frame, length), LogEntry::TYPE_DEBUG_DECODE); Frame const end = frame + length - 1; - if (frame < _decoded.frame || end > (_decoded.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, _content->resampled_audio_frame_rate()), accurate); + /* If we are less than (about) 5 seconds behind the data that we want we'll + run through it rather than seeking. + */ + Frame const slack = 5 * 48000; + + if (frame < _decoded.frame || end > (_decoded.frame + _decoded.audio->frames() + slack)) { + /* Either we have no decoded data, all our data is after the time that we + want, or what we do have is a long way from what we want: seek */ + _decoder->seek (ContentTime::from_frames (frame, _content->resampled_frame_rate()), accurate); } /* Offset of the data that we want from the start of _decoded.audio @@ -87,15 +99,20 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate) /* Keep stuffing data into _decoded until we have enough data, or the subclass does not want to give us any more */ while ( (_decoded.frame > frame || (_decoded.frame + _decoded.audio->frames()) < end) && - !_decoder->pass () + !_decoder->pass (Decoder::PASS_REASON_AUDIO, accurate) ) {} decoded_offset = frame - _decoded.frame; + + _log->log ( + String::compose ("Accurate ADS::get has offset %1 from request %2 and available %3", decoded_offset, frame, _decoded.frame), + LogEntry::TYPE_DEBUG_DECODE + ); } else { while ( _decoded.audio->frames() < length && - !_decoder->pass () + !_decoder->pass (Decoder::PASS_REASON_AUDIO, accurate) ) {} @@ -136,13 +153,13 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate) void AudioDecoderStream::audio (shared_ptr data, ContentTime time) { - _content->film()->log()->log (String::compose ("ADS receives %1 %2", time, data->frames ()), Log::TYPE_DEBUG_DECODE); + _log->log (String::compose ("ADS receives %1 %2", time, data->frames ()), LogEntry::TYPE_DEBUG_DECODE); if (_resampler) { data = _resampler->run (data); } - Frame const frame_rate = _content->resampled_audio_frame_rate (); + Frame const frame_rate = _content->resampled_frame_rate (); if (_seek_reference) { /* We've had an accurate seek and now we're seeing some data */ @@ -155,20 +172,6 @@ AudioDecoderStream::audio (shared_ptr data, ContentTime time padded->copy_from (data.get(), data->frames(), 0, delta_frames); data = padded; time -= delta; - } else if (delta_frames < 0) { - /* This data comes before the seek time. Throw some data away */ - Frame const to_discard = min (-delta_frames, static_cast (data->frames())); - Frame const to_keep = data->frames() - to_discard; - if (to_keep == 0) { - /* We have to throw all this data away, so keep _seek_reference and - try again next time some data arrives. - */ - return; - } - shared_ptr trimmed (new AudioBuffers (data->channels(), to_keep)); - trimmed->copy_from (data.get(), to_keep, to_discard, 0); - data = trimmed; - time += ContentTime::from_frames (to_discard, frame_rate); } _seek_reference = optional (); } @@ -211,7 +214,7 @@ AudioDecoderStream::add (shared_ptr data) _position = _position.get() + data->frames (); /* Limit the amount of data we keep in case nobody is asking for it */ - int const max_frames = _content->resampled_audio_frame_rate () * 10; + int const max_frames = _content->resampled_frame_rate () * 10; if (_decoded.audio->frames() > max_frames) { int const to_remove = _decoded.audio->frames() - max_frames; _decoded.frame += to_remove; @@ -242,3 +245,11 @@ AudioDecoderStream::seek (ContentTime t, bool accurate) _seek_reference = t; } } + +void +AudioDecoderStream::set_fast () +{ + if (_resampler) { + _resampler->set_fast (); + } +}