+2015-09-09 c.hetherington <cth@carlh.net>
+
+ * Use SRC_LINEAR when resampling for
+ audio analysis to speed things up (#685).
+
2015-09-08 c.hetherington <cth@carlh.net>
* Missing libsamplerate dylib for OS X.
{
shared_ptr<Player> player (new Player (_film, _playlist));
player->set_ignore_video ();
+ player->set_fast ();
int64_t const len = _playlist->length().frames_round (_film->audio_frame_rate());
_samples_per_point = max (int64_t (1), len / _num_points);
using std::map;
using boost::shared_ptr;
-AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content)
+AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content, bool fast)
: _audio_content (content)
, _ignore_audio (false)
+ , _fast (fast)
{
BOOST_FOREACH (AudioStreamPtr i, content->audio_streams ()) {
_streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (_audio_content, i, this));
class AudioDecoder : public virtual Decoder, public boost::enable_shared_from_this<AudioDecoder>
{
public:
- AudioDecoder (boost::shared_ptr<const AudioContent>);
+ AudioDecoder (boost::shared_ptr<const AudioContent>, bool fast);
boost::shared_ptr<const AudioContent> audio_content () const {
return _audio_content;
void set_ignore_audio ();
+ bool fast () const {
+ return _fast;
+ }
+
protected:
void audio (AudioStreamPtr stream, boost::shared_ptr<const AudioBuffers>, ContentTime);
void flush ();
/** An AudioDecoderStream object to manage each stream in _audio_content */
std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > _streams;
bool _ignore_audio;
+ bool _fast;
};
#endif
, _decoder (decoder)
{
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 ()));
+ _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_audio_frame_rate(), _stream->channels (), decoder->fast ()));
}
reset_decoded ();
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
-DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c)
+DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, bool fast)
: VideoDecoder (c)
- , AudioDecoder (c)
+ , AudioDecoder (c, fast)
, SubtitleDecoder (c)
, _dcp_content (c)
{
class DCPDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder
{
public:
- DCPDecoder (boost::shared_ptr<const DCPContent>);
+ DCPDecoder (boost::shared_ptr<const DCPContent>, bool fast);
private:
friend struct dcp_subtitle_within_dcp_test;
using boost::shared_ptr;
using dcp::Size;
-FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log, bool fast)
: VideoDecoder (c)
- , AudioDecoder (c)
+ , AudioDecoder (c, fast)
, SubtitleDecoder (c)
, FFmpeg (c)
, _log (log)
class FFmpegDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder, public FFmpeg
{
public:
- FFmpegDecoder (boost::shared_ptr<const FFmpegContent>, boost::shared_ptr<Log>);
+ FFmpegDecoder (boost::shared_ptr<const FFmpegContent>, boost::shared_ptr<Log>, bool fast);
private:
friend struct ::ffmpeg_pts_offset_test;
, _ignore_video (false)
, _ignore_audio (false)
, _always_burn_subtitles (false)
+ , _fast (false)
{
_film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
_playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
/* FFmpeg */
shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i);
if (fc) {
- decoder.reset (new FFmpegDecoder (fc, _film->log()));
+ decoder.reset (new FFmpegDecoder (fc, _film->log(), _fast));
frc = FrameRateChange (fc->video_frame_rate(), _film->video_frame_rate());
}
shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
if (dc) {
- decoder.reset (new DCPDecoder (dc));
+ decoder.reset (new DCPDecoder (dc, _fast));
frc = FrameRateChange (dc->video_frame_rate(), _film->video_frame_rate());
}
/* SndfileContent */
shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (i);
if (sc) {
- decoder.reset (new SndfileDecoder (sc));
+ decoder.reset (new SndfileDecoder (sc, _fast));
frc = best_overlap_frc;
}
{
_always_burn_subtitles = burn;
}
+
+void
+Player::set_fast ()
+{
+ _fast = true;
+ _have_valid_pieces = false;
+}
void set_ignore_audio ();
void set_enable_subtitles (bool enable);
void set_always_burn_subtitles (bool burn);
+ void set_fast ();
/** Emitted when something has changed such that if we went back and emitted
* the last frame again it would look different. This is not emitted after
of content settings
*/
bool _always_burn_subtitles;
+ /** true if we should try to be fast rather than high quality */
+ bool _fast;
boost::shared_ptr<AudioProcessor> _audio_processor;
using std::make_pair;
using boost::shared_ptr;
-Resampler::Resampler (int in, int out, int channels)
+/** @param in Input sampling rate (Hz)
+ * @param out Output sampling rate (Hz)
+ * @param channels Number of channels.
+ * @param fast true to be fast rather than good.
+ */
+Resampler::Resampler (int in, int out, int channels, bool fast)
: _in_rate (in)
, _out_rate (out)
, _channels (channels)
{
int error;
- _src = src_new (SRC_SINC_BEST_QUALITY, _channels, &error);
+ _src = src_new (fast ? SRC_LINEAR : SRC_SINC_BEST_QUALITY, _channels, &error);
if (!_src) {
throw StringError (String::compose (N_("could not create sample-rate converter (%1)"), error));
}
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2015 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
class Resampler : public boost::noncopyable
{
public:
- Resampler (int, int, int);
+ Resampler (int, int, int, bool fast);
~Resampler ();
boost::shared_ptr<const AudioBuffers> run (boost::shared_ptr<const AudioBuffers>);
using std::cout;
using boost::shared_ptr;
-SndfileDecoder::SndfileDecoder (shared_ptr<const SndfileContent> c)
+SndfileDecoder::SndfileDecoder (shared_ptr<const SndfileContent> c, bool fast)
: Sndfile (c)
- , AudioDecoder (c)
+ , AudioDecoder (c, fast)
, _done (0)
, _remaining (_info.frames)
, _deinterleave_buffer (0)
class SndfileDecoder : public Sndfile, public AudioDecoder
{
public:
- SndfileDecoder (boost::shared_ptr<const SndfileContent> c);
+ SndfileDecoder (boost::shared_ptr<const SndfileContent> c, bool fast);
~SndfileDecoder ();
private:
{
public:
TestAudioDecoder (shared_ptr<TestAudioContent> content)
- : AudioDecoder (content)
+ : AudioDecoder (content, false)
, _test_audio_content (content)
, _position (0)
{}
film->examine_and_add_content (content);
wait_for_jobs ();
- shared_ptr<DCPDecoder> decoder (new DCPDecoder (content));
+ shared_ptr<DCPDecoder> decoder (new DCPDecoder (content, false));
list<ContentTimePeriod> ctp = decoder->text_subtitles_during (
ContentTimePeriod (
film->examine_and_add_content (content);
wait_for_jobs ();
shared_ptr<Log> log (new NullLog);
- shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log));
+ shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
for (vector<int>::const_iterator i = frames.begin(); i != frames.end(); ++i) {
check (decoder, *i);
film->examine_and_add_content (content);
wait_for_jobs ();
shared_ptr<Log> log (new NullLog);
- shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log));
+ shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
BOOST_CHECK_CLOSE (decoder->video_content()->video_frame_rate(), fps, 0.01);
/* Sound == video so no offset required */
content->_first_video = ContentTime ();
content->_audio_streams.front()->first_audio = ContentTime ();
- FFmpegDecoder decoder (content, film->log());
+ FFmpegDecoder decoder (content, film->log(), false);
BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime ());
}
/* Common offset should be removed */
content->_first_video = ContentTime::from_seconds (600);
content->_audio_streams.front()->first_audio = ContentTime::from_seconds (600);
- FFmpegDecoder decoder (content, film->log());
+ FFmpegDecoder decoder (content, film->log(), false);
BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime::from_seconds (-600));
}
/* Video is on a frame boundary */
content->_first_video = ContentTime::from_frames (1, 24);
content->_audio_streams.front()->first_audio = ContentTime ();
- FFmpegDecoder decoder (content, film->log());
+ FFmpegDecoder decoder (content, film->log(), false);
BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime ());
}
double const frame = 1.0 / 24.0;
content->_first_video = ContentTime::from_seconds (frame + 0.0215);
content->_audio_streams.front()->first_audio = ContentTime ();
- FFmpegDecoder decoder (content, film->log());
+ FFmpegDecoder decoder (content, film->log(), false);
BOOST_CHECK_CLOSE (decoder._pts_offset.seconds(), (frame - 0.0215), 0.00001);
}
double const frame = 1.0 / 24.0;
content->_first_video = ContentTime::from_seconds (frame + 0.0215 + 4.1);
content->_audio_streams.front()->first_audio = ContentTime::from_seconds (4.1);
- FFmpegDecoder decoder (content, film->log());
+ FFmpegDecoder decoder (content, film->log(), false);
BOOST_CHECK_CLOSE (decoder._pts_offset.seconds(), (frame - 0.0215) - 4.1, 0.1);
}
}
static void
resampler_test_one (int from, int to)
{
- Resampler resamp (from, to, 1);
+ Resampler resamp (from, to, 1, false);
/* 3 hours */
int64_t const N = int64_t (from) * 60 * 60 * 3;
Frame const first_frame = video_delay.round_up (content->video_frame_rate ()).frames_round (content->video_frame_rate ());
- FFmpegDecoder decoder (content, film->log());
+ FFmpegDecoder decoder (content, film->log(), false);
list<ContentVideo> a = decoder.get_video (first_frame, true);
BOOST_CHECK (a.size() == 1);
BOOST_CHECK_EQUAL (a.front().frame, first_frame);