X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fexternal_audio_decoder.cc;h=36605141886aed7ec596bb024b0425bfedc23f94;hb=dea922bbc1fa2b643140a6b5275e58a1fb0225c9;hp=99dd1ded0062ad3c77a136f0452d383077f4c97c;hpb=4fbd1901fdabc829cfa7e7d4d0c1272bba87033c;p=dcpomatic.git diff --git a/src/lib/external_audio_decoder.cc b/src/lib/external_audio_decoder.cc index 99dd1ded0..366051418 100644 --- a/src/lib/external_audio_decoder.cc +++ b/src/lib/external_audio_decoder.cc @@ -1,3 +1,23 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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 #include #include "external_audio_decoder.h" #include "film.h" @@ -5,18 +25,23 @@ using std::vector; using std::string; +using std::stringstream; using std::min; +using std::cout; using boost::shared_ptr; +using boost::optional; -ExternalAudioDecoder::ExternalAudioDecoder (shared_ptr f, shared_ptr o, Job* j) +ExternalAudioDecoder::ExternalAudioDecoder (shared_ptr f, DecodeOptions o, Job* j) : Decoder (f, o, j) , AudioDecoder (f, o, j) { - + sf_count_t frames; + vector sf = open_files (frames); + close_files (sf); } -bool -ExternalAudioDecoder::pass () +vector +ExternalAudioDecoder::open_files (sf_count_t & frames) { vector const files = _film->external_audio (); @@ -28,19 +53,19 @@ ExternalAudioDecoder::pass () } if (N == 0) { - return true; + return vector (); } bool first = true; - sf_count_t frames = 0; + frames = 0; vector sndfiles; - for (vector::const_iterator i = files.begin(); i != files.end(); ++i) { - if (i->empty ()) { + for (size_t i = 0; i < (size_t) N; ++i) { + if (files[i].empty ()) { sndfiles.push_back (0); } else { SF_INFO info; - SNDFILE* s = sf_open (i->c_str(), SFM_READ, &info); + SNDFILE* s = sf_open (files[i].c_str(), SFM_READ, &info); if (!s) { throw DecodeError ("could not open external audio file for reading"); } @@ -52,8 +77,12 @@ ExternalAudioDecoder::pass () sndfiles.push_back (s); if (first) { - /* XXX: nasty magic value */ - AudioStream st ("DVDOMATIC-EXTERNAL", -1, info.samplerate, av_get_default_channel_layout (info.channels)); + shared_ptr st ( + new ExternalAudioStream ( + info.samplerate, av_get_default_channel_layout (N) + ) + ); + _audio_streams.push_back (st); _audio_stream = st; frames = info.frames; @@ -66,9 +95,24 @@ ExternalAudioDecoder::pass () } } - sf_count_t const block = 65536; + return sndfiles; +} - shared_ptr audio (new AudioBuffers (_audio_stream.get().channels(), block)); +bool +ExternalAudioDecoder::pass () +{ + sf_count_t frames; + vector sndfiles = open_files (frames); + if (sndfiles.empty()) { + return true; + } + + /* Do things in half second blocks as I think there may be limits + to what FFmpeg (and in particular the resampler) can cope with. + */ + sf_count_t const block = _audio_stream->sample_rate() / 2; + + shared_ptr audio (new AudioBuffers (_audio_stream->channels(), block)); while (frames > 0) { sf_count_t const this_time = min (block, frames); for (size_t i = 0; i < sndfiles.size(); ++i) { @@ -79,9 +123,64 @@ ExternalAudioDecoder::pass () } } + audio->set_frames (this_time); Audio (audio); frames -= this_time; } - + + close_files (sndfiles); + return true; } + +void +ExternalAudioDecoder::close_files (vector const & sndfiles) +{ + for (size_t i = 0; i < sndfiles.size(); ++i) { + sf_close (sndfiles[i]); + } +} + +shared_ptr +ExternalAudioStream::create () +{ + return shared_ptr (new ExternalAudioStream); +} + +shared_ptr +ExternalAudioStream::create (string t, optional v) +{ + if (!v) { + /* version < 1; no type in the string, and there's only FFmpeg streams anyway */ + return shared_ptr (); + } + + stringstream s (t); + string type; + s >> type; + if (type != "external") { + return shared_ptr (); + } + + return shared_ptr (new ExternalAudioStream (t, v)); +} + +ExternalAudioStream::ExternalAudioStream (string t, optional v) +{ + assert (v); + + stringstream s (t); + string type; + s >> type >> _sample_rate >> _channel_layout; +} + +ExternalAudioStream::ExternalAudioStream () +{ + +} + +string +ExternalAudioStream::to_string () const +{ + return String::compose ("external %1 %2", _sample_rate, _channel_layout); +}