From f26af8112b03b5233eb5239defd11a7428b705ad Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 9 Sep 2015 09:50:48 +0100 Subject: [PATCH] Use SRC_LINEAR for speed when analysing audio (#685). --- ChangeLog | 5 +++++ src/lib/analyse_audio_job.cc | 1 + src/lib/audio_decoder.cc | 3 ++- src/lib/audio_decoder.h | 7 ++++++- src/lib/audio_decoder_stream.cc | 2 +- src/lib/dcp_decoder.cc | 4 ++-- src/lib/dcp_decoder.h | 2 +- src/lib/ffmpeg_decoder.cc | 4 ++-- src/lib/ffmpeg_decoder.h | 2 +- src/lib/player.cc | 14 +++++++++++--- src/lib/player.h | 3 +++ src/lib/resampler.cc | 9 +++++++-- src/lib/resampler.h | 4 ++-- src/lib/sndfile_decoder.cc | 4 ++-- src/lib/sndfile_decoder.h | 2 +- test/audio_decoder_test.cc | 2 +- test/dcp_subtitle_test.cc | 2 +- test/ffmpeg_decoder_seek_test.cc | 2 +- test/ffmpeg_decoder_sequential_test.cc | 2 +- test/ffmpeg_pts_offset_test.cc | 10 +++++----- test/resampler_test.cc | 2 +- test/seek_zero_test.cc | 2 +- 22 files changed, 58 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 676cc7bfb..31c35e392 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-09 c.hetherington + + * Use SRC_LINEAR when resampling for + audio analysis to speed things up (#685). + 2015-09-08 c.hetherington * Missing libsamplerate dylib for OS X. diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc index b45af646d..c863c6c68 100644 --- a/src/lib/analyse_audio_job.cc +++ b/src/lib/analyse_audio_job.cc @@ -72,6 +72,7 @@ AnalyseAudioJob::run () { shared_ptr 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); diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index 268a9d296..2944357ba 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -30,9 +30,10 @@ using std::cout; using std::map; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr content) +AudioDecoder::AudioDecoder (shared_ptr content, bool fast) : _audio_content (content) , _ignore_audio (false) + , _fast (fast) { BOOST_FOREACH (AudioStreamPtr i, content->audio_streams ()) { _streams[i] = shared_ptr (new AudioDecoderStream (_audio_content, i, this)); diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index d5e7c6f55..716b37969 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -39,7 +39,7 @@ class AudioDecoderStream; class AudioDecoder : public virtual Decoder, public boost::enable_shared_from_this { public: - AudioDecoder (boost::shared_ptr); + AudioDecoder (boost::shared_ptr, bool fast); boost::shared_ptr audio_content () const { return _audio_content; @@ -55,6 +55,10 @@ public: void set_ignore_audio (); + bool fast () const { + return _fast; + } + protected: void audio (AudioStreamPtr stream, boost::shared_ptr, ContentTime); void flush (); @@ -65,6 +69,7 @@ private: /** An AudioDecoderStream object to manage each stream in _audio_content */ std::map > _streams; bool _ignore_audio; + bool _fast; }; #endif diff --git a/src/lib/audio_decoder_stream.cc b/src/lib/audio_decoder_stream.cc index 267c542cd..97db8a93f 100644 --- a/src/lib/audio_decoder_stream.cc +++ b/src/lib/audio_decoder_stream.cc @@ -45,7 +45,7 @@ AudioDecoderStream::AudioDecoderStream (shared_ptr content, , _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 (); diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc index ec1f02d3d..2bdf6a8e9 100644 --- a/src/lib/dcp_decoder.cc +++ b/src/lib/dcp_decoder.cc @@ -41,9 +41,9 @@ using std::cout; using boost::shared_ptr; using boost::dynamic_pointer_cast; -DCPDecoder::DCPDecoder (shared_ptr c) +DCPDecoder::DCPDecoder (shared_ptr c, bool fast) : VideoDecoder (c) - , AudioDecoder (c) + , AudioDecoder (c, fast) , SubtitleDecoder (c) , _dcp_content (c) { diff --git a/src/lib/dcp_decoder.h b/src/lib/dcp_decoder.h index f23b5b82d..15220810d 100644 --- a/src/lib/dcp_decoder.h +++ b/src/lib/dcp_decoder.h @@ -35,7 +35,7 @@ struct dcp_subtitle_within_dcp_test; class DCPDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder { public: - DCPDecoder (boost::shared_ptr); + DCPDecoder (boost::shared_ptr, bool fast); private: friend struct dcp_subtitle_within_dcp_test; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index eab85c04e..ae44ff522 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -61,9 +61,9 @@ using std::max; using boost::shared_ptr; using dcp::Size; -FFmpegDecoder::FFmpegDecoder (shared_ptr c, shared_ptr log) +FFmpegDecoder::FFmpegDecoder (shared_ptr c, shared_ptr log, bool fast) : VideoDecoder (c) - , AudioDecoder (c) + , AudioDecoder (c, fast) , SubtitleDecoder (c) , FFmpeg (c) , _log (log) diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 28d8e4baa..5475be612 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -44,7 +44,7 @@ struct ffmpeg_pts_offset_test; class FFmpegDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder, public FFmpeg { public: - FFmpegDecoder (boost::shared_ptr, boost::shared_ptr); + FFmpegDecoder (boost::shared_ptr, boost::shared_ptr, bool fast); private: friend struct ::ffmpeg_pts_offset_test; diff --git a/src/lib/player.cc b/src/lib/player.cc index 5e1fbcc63..302ab161c 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -76,6 +76,7 @@ Player::Player (shared_ptr film, shared_ptr playlist , _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)); @@ -127,13 +128,13 @@ Player::setup_pieces () /* FFmpeg */ shared_ptr fc = dynamic_pointer_cast (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 dc = dynamic_pointer_cast (i); if (dc) { - decoder.reset (new DCPDecoder (dc)); + decoder.reset (new DCPDecoder (dc, _fast)); frc = FrameRateChange (dc->video_frame_rate(), _film->video_frame_rate()); } @@ -158,7 +159,7 @@ Player::setup_pieces () /* SndfileContent */ shared_ptr sc = dynamic_pointer_cast (i); if (sc) { - decoder.reset (new SndfileDecoder (sc)); + decoder.reset (new SndfileDecoder (sc, _fast)); frc = best_overlap_frc; } @@ -674,3 +675,10 @@ Player::set_always_burn_subtitles (bool burn) { _always_burn_subtitles = burn; } + +void +Player::set_fast () +{ + _fast = true; + _have_valid_pieces = false; +} diff --git a/src/lib/player.h b/src/lib/player.h index 0a2117470..842c2283c 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -52,6 +52,7 @@ public: 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 @@ -124,6 +125,8 @@ private: of content settings */ bool _always_burn_subtitles; + /** true if we should try to be fast rather than high quality */ + bool _fast; boost::shared_ptr _audio_processor; diff --git a/src/lib/resampler.cc b/src/lib/resampler.cc index b12b549bf..ba57deb63 100644 --- a/src/lib/resampler.cc +++ b/src/lib/resampler.cc @@ -31,13 +31,18 @@ using std::pair; 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)); } diff --git a/src/lib/resampler.h b/src/lib/resampler.h index 5a69d0983..f51c3cdb5 100644 --- a/src/lib/resampler.h +++ b/src/lib/resampler.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington + Copyright (C) 2013-2015 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 @@ -27,7 +27,7 @@ class AudioBuffers; class Resampler : public boost::noncopyable { public: - Resampler (int, int, int); + Resampler (int, int, int, bool fast); ~Resampler (); boost::shared_ptr run (boost::shared_ptr); diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index b2d35f302..49633dd1f 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -32,9 +32,9 @@ using std::min; using std::cout; using boost::shared_ptr; -SndfileDecoder::SndfileDecoder (shared_ptr c) +SndfileDecoder::SndfileDecoder (shared_ptr c, bool fast) : Sndfile (c) - , AudioDecoder (c) + , AudioDecoder (c, fast) , _done (0) , _remaining (_info.frames) , _deinterleave_buffer (0) diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index c8d1f1f59..da9016ee0 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -25,7 +25,7 @@ class SndfileContent; class SndfileDecoder : public Sndfile, public AudioDecoder { public: - SndfileDecoder (boost::shared_ptr c); + SndfileDecoder (boost::shared_ptr c, bool fast); ~SndfileDecoder (); private: diff --git a/test/audio_decoder_test.cc b/test/audio_decoder_test.cc index 00d555d86..e63e1a5b0 100644 --- a/test/audio_decoder_test.cc +++ b/test/audio_decoder_test.cc @@ -59,7 +59,7 @@ class TestAudioDecoder : public AudioDecoder { public: TestAudioDecoder (shared_ptr content) - : AudioDecoder (content) + : AudioDecoder (content, false) , _test_audio_content (content) , _position (0) {} diff --git a/test/dcp_subtitle_test.cc b/test/dcp_subtitle_test.cc index 9007ad611..1defe9d01 100644 --- a/test/dcp_subtitle_test.cc +++ b/test/dcp_subtitle_test.cc @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE (dcp_subtitle_within_dcp_test) film->examine_and_add_content (content); wait_for_jobs (); - shared_ptr decoder (new DCPDecoder (content)); + shared_ptr decoder (new DCPDecoder (content, false)); list ctp = decoder->text_subtitles_during ( ContentTimePeriod ( diff --git a/test/ffmpeg_decoder_seek_test.cc b/test/ffmpeg_decoder_seek_test.cc index 39536f1ab..2a9b4da71 100644 --- a/test/ffmpeg_decoder_seek_test.cc +++ b/test/ffmpeg_decoder_seek_test.cc @@ -63,7 +63,7 @@ test (boost::filesystem::path file, vector frames) film->examine_and_add_content (content); wait_for_jobs (); shared_ptr log (new NullLog); - shared_ptr decoder (new FFmpegDecoder (content, log)); + shared_ptr decoder (new FFmpegDecoder (content, log, false)); for (vector::const_iterator i = frames.begin(); i != frames.end(); ++i) { check (decoder, *i); diff --git a/test/ffmpeg_decoder_sequential_test.cc b/test/ffmpeg_decoder_sequential_test.cc index ce799bb24..22ab61624 100644 --- a/test/ffmpeg_decoder_sequential_test.cc +++ b/test/ffmpeg_decoder_sequential_test.cc @@ -50,7 +50,7 @@ test (boost::filesystem::path file, float fps, int gaps) film->examine_and_add_content (content); wait_for_jobs (); shared_ptr log (new NullLog); - shared_ptr decoder (new FFmpegDecoder (content, log)); + shared_ptr decoder (new FFmpegDecoder (content, log, false)); BOOST_CHECK_CLOSE (decoder->video_content()->video_frame_rate(), fps, 0.01); diff --git a/test/ffmpeg_pts_offset_test.cc b/test/ffmpeg_pts_offset_test.cc index 0ded56431..65ed6436d 100644 --- a/test/ffmpeg_pts_offset_test.cc +++ b/test/ffmpeg_pts_offset_test.cc @@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test) /* 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 ()); } @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test) /* 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)); } @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test) /* 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 ()); } @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test) 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); } @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test) 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); } } diff --git a/test/resampler_test.cc b/test/resampler_test.cc index d633f75c1..f536d6547 100644 --- a/test/resampler_test.cc +++ b/test/resampler_test.cc @@ -33,7 +33,7 @@ using boost::shared_ptr; 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; diff --git a/test/seek_zero_test.cc b/test/seek_zero_test.cc index 5f870ba41..ab2b48198 100644 --- a/test/seek_zero_test.cc +++ b/test/seek_zero_test.cc @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE (seek_zero_test) 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 a = decoder.get_video (first_frame, true); BOOST_CHECK (a.size() == 1); BOOST_CHECK_EQUAL (a.front().frame, first_frame); -- 2.30.2