From d5d7d3dbb20deed107f83d58c33bd220e1d47218 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 2 Jun 2014 14:59:10 +0100 Subject: Expand the over-allocation of image buffers to 32 bytes to attempt to avoid bad reads by swscale. --- src/lib/image.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/image.cc b/src/lib/image.cc index 1fa55e242..e8622eba4 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -490,8 +490,13 @@ Image::allocate () OS X crashes on this illegal read, though other operating systems don't seem to mind. The nasty + 1 in this malloc makes sure there is always a byte for that instruction to read safely. + + Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3 + over-reads by more then _avx. I can't follow the code to work out how much, + so I'll just over-allocate by 32 bytes and have done with it. Empirical + testing suggests that it works. */ - _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 1); + _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 32); } } -- cgit v1.2.3 From c5b3d91fab31fde4c21e1cc5bb5adb1d6d26fcca Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 3 Jun 2014 14:30:42 +0100 Subject: Include audio mapping in the digest used to distinguish different audio analyses so that the analyses are re-computed when the mapping changes. Reported-by: Matthias Damm --- ChangeLog | 2 ++ src/lib/audio_content.cc | 2 +- src/lib/audio_mapping.cc | 18 +++++++++++++ src/lib/audio_mapping.h | 2 ++ src/lib/colour_conversion.cc | 20 +++++++------- src/lib/dcp_video_frame.cc | 16 ----------- src/lib/image.cc | 17 +++--------- src/lib/md5_digester.cc | 63 ++++++++++++++++++++++++++++++++++++++++++++ src/lib/md5_digester.h | 43 ++++++++++++++++++++++++++++++ src/lib/playlist.cc | 5 +++- src/lib/util.cc | 34 +++--------------------- src/lib/util.h | 1 - src/lib/writer.cc | 8 +++--- src/lib/wscript | 1 + 14 files changed, 156 insertions(+), 76 deletions(-) create mode 100644 src/lib/md5_digester.cc create mode 100644 src/lib/md5_digester.h (limited to 'src/lib') diff --git a/ChangeLog b/ChangeLog index 059dc5cc8..07c985c47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2014-06-03 Carl Hetherington + * Re-calculate audio plots when the mapping is changed. + * Version 1.69.19 released. 2014-06-02 Carl Hetherington diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc index 1896c4d5c..dbca6652c 100644 --- a/src/lib/audio_content.cc +++ b/src/lib/audio_content.cc @@ -139,7 +139,7 @@ AudioContent::audio_analysis_path () const } boost::filesystem::path p = film->audio_analysis_dir (); - p /= digest (); + p /= digest() + "_" + audio_mapping().digest(); return p; } diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc index b1810c973..e35c1ae94 100644 --- a/src/lib/audio_mapping.cc +++ b/src/lib/audio_mapping.cc @@ -22,6 +22,7 @@ #include #include "audio_mapping.h" #include "util.h" +#include "md5_digester.h" using std::list; using std::cout; @@ -126,3 +127,20 @@ AudioMapping::as_xml (xmlpp::Node* node) const } } } + +/** @return a string which is unique for a given AudioMapping configuration, for + * differentiation between different AudioMappings. + */ +string +AudioMapping::digest () const +{ + MD5Digester digester; + digester.add (_content_channels); + for (int i = 0; i < _content_channels; ++i) { + for (int j = 0; j < MAX_DCP_AUDIO_CHANNELS; ++j) { + digester.add (_gain[i][j]); + } + } + + return digester.get (); +} diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h index 26087bfff..b0b75ac06 100644 --- a/src/lib/audio_mapping.h +++ b/src/lib/audio_mapping.h @@ -56,6 +56,8 @@ public: int content_channels () const { return _content_channels; } + + std::string digest () const; private: void setup (int); diff --git a/src/lib/colour_conversion.cc b/src/lib/colour_conversion.cc index 5f17f9184..f8675900e 100644 --- a/src/lib/colour_conversion.cc +++ b/src/lib/colour_conversion.cc @@ -24,6 +24,7 @@ #include "config.h" #include "colour_conversion.h" #include "util.h" +#include "md5_digester.h" #include "i18n.h" @@ -121,21 +122,18 @@ ColourConversion::preset () const string ColourConversion::identifier () const { - double numbers[12]; - - int n = 0; - numbers[n++] = input_gamma; - numbers[n++] = input_gamma_linearised; + MD5Digester digester; + + digester.add (input_gamma); + digester.add (input_gamma_linearised); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { - numbers[n++] = matrix (i, j); + digester.add (matrix (i, j)); } } - numbers[n++] = output_gamma; - - assert (n == 12); - - return md5_digest (numbers, 12 * sizeof (double)); + digester.add (output_gamma); + + return digester.get (); } PresetColourConversion::PresetColourConversion () diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 6cf987648..09b909696 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -134,21 +133,6 @@ DCPVideoFrame::encode_locally () matrix ); - { - MD5_CTX md5_context; - MD5_Init (&md5_context); - MD5_Update (&md5_context, xyz->data(0), 1998 * 1080 * 4); - MD5_Update (&md5_context, xyz->data(1), 1998 * 1080 * 4); - MD5_Update (&md5_context, xyz->data(2), 1998 * 1080 * 4); - unsigned char digest[MD5_DIGEST_LENGTH]; - MD5_Final (digest, &md5_context); - - stringstream s; - for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { - s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]); - } - } - /* Set the max image and component sizes based on frame_rate */ int max_cs_len = ((float) _j2k_bandwidth) / 8 / _frames_per_second; if (_frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT) { diff --git a/src/lib/image.cc b/src/lib/image.cc index e8622eba4..8a8fb1c7b 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -22,7 +22,6 @@ */ #include -#include extern "C" { #include #include @@ -31,6 +30,7 @@ extern "C" { #include "image.h" #include "exceptions.h" #include "scaler.h" +#include "md5_digester.h" #include "i18n.h" @@ -629,21 +629,12 @@ Image::aligned () const string Image::digest () const { - MD5_CTX md5_context; - MD5_Init (&md5_context); + MD5Digester digester; for (int i = 0; i < components(); ++i) { - MD5_Update (&md5_context, data()[i], line_size()[i]); - } - - unsigned char digest[MD5_DIGEST_LENGTH]; - MD5_Final (digest, &md5_context); - - stringstream s; - for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { - s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]); + digester.add (data()[i], line_size()[i]); } - return s.str (); + return digester.get (); } diff --git a/src/lib/md5_digester.cc b/src/lib/md5_digester.cc new file mode 100644 index 000000000..1244209bd --- /dev/null +++ b/src/lib/md5_digester.cc @@ -0,0 +1,63 @@ +/* + Copyright (C) 2014 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 +#include "md5_digester.h" + +using std::string; +using std::stringstream; +using std::hex; +using std::setfill; +using std::setw; + +MD5Digester::MD5Digester () +{ + MD5_Init (&_context); +} + +MD5Digester::~MD5Digester () +{ + get (); +} + +void +MD5Digester::add (void const * data, size_t size) +{ + MD5_Update (&_context, data, size); +} + +string +MD5Digester::get () const +{ + if (!_digest) { + unsigned char digest[MD5_DIGEST_LENGTH]; + MD5_Final (digest, &_context); + + stringstream s; + for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { + s << hex << setfill('0') << setw(2) << ((int) digest[i]); + } + + _digest = s.str (); + } + + return _digest.get (); +} diff --git a/src/lib/md5_digester.h b/src/lib/md5_digester.h new file mode 100644 index 000000000..d5b6a9c4c --- /dev/null +++ b/src/lib/md5_digester.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2014 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 +#include + +class MD5Digester : public boost::noncopyable +{ +public: + MD5Digester (); + ~MD5Digester (); + + void add (void const * data, size_t size); + + template + void add (T data) { + add (&data, sizeof (T)); + } + + std::string get () const; + +private: + mutable MD5_CTX _context; + mutable boost::optional _digest; +}; diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index eb9a49d30..1f00d4d67 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -30,6 +30,7 @@ #include "job.h" #include "config.h" #include "util.h" +#include "md5_digester.h" #include "i18n.h" @@ -113,7 +114,9 @@ Playlist::video_identifier () const } } - return md5_digest (t.c_str(), t.length()); + MD5Digester digester; + digester.add (t.c_str(), t.length()); + return digester.get (); } /** @param node node */ diff --git a/src/lib/util.cc b/src/lib/util.cc index a5111b7dc..e81165365 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -44,7 +44,6 @@ #endif #include #include -#include #include #include #include @@ -70,6 +69,7 @@ extern "C" { #include "job.h" #include "cross.h" #include "video_content.h" +#include "md5_digester.h" #ifdef DCPOMATIC_WINDOWS #include "stack.hpp" #endif @@ -424,23 +424,6 @@ split_at_spaces_considering_quotes (string s) return out; } -string -md5_digest (void const * data, int size) -{ - MD5_CTX md5_context; - MD5_Init (&md5_context); - MD5_Update (&md5_context, data, size); - unsigned char digest[MD5_DIGEST_LENGTH]; - MD5_Final (digest, &md5_context); - - stringstream s; - for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { - s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]); - } - - return s.str (); -} - /** @param job Optional job for which to report progress */ string md5_digest (vector files, shared_ptr job) @@ -448,8 +431,7 @@ md5_digest (vector files, shared_ptr job) boost::uintmax_t const buffer_size = 64 * 1024; char buffer[buffer_size]; - MD5_CTX md5_context; - MD5_Init (&md5_context); + MD5Digester digester; vector sizes; for (size_t i = 0; i < files.size(); ++i) { @@ -468,7 +450,7 @@ md5_digest (vector files, shared_ptr job) while (remaining > 0) { int const t = min (remaining, buffer_size); fread (buffer, 1, t, f); - MD5_Update (&md5_context, buffer, t); + digester.add (buffer, t); remaining -= t; if (job) { @@ -479,15 +461,7 @@ md5_digest (vector files, shared_ptr job) fclose (f); } - unsigned char digest[MD5_DIGEST_LENGTH]; - MD5_Final (digest, &md5_context); - - stringstream s; - for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { - s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]); - } - - return s.str (); + return digester.get (); } static bool diff --git a/src/lib/util.h b/src/lib/util.h index 5ca9f74c8..5d93456df 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -62,7 +62,6 @@ extern void dcpomatic_setup (); extern void dcpomatic_setup_gettext_i18n (std::string); extern std::vector split_at_spaces_considering_quotes (std::string); extern std::string md5_digest (std::vector, boost::shared_ptr); -extern std::string md5_digest (void const *, int); extern void ensure_ui_thread (); extern std::string audio_channel_name (int); extern bool valid_image_file (boost::filesystem::path); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index b175843ed..2ed55a276 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -37,6 +37,7 @@ #include "config.h" #include "job.h" #include "cross.h" +#include "md5_digester.h" #include "i18n.h" @@ -524,9 +525,10 @@ Writer::check_existing_picture_mxf_frame (FILE* mxf, int f, Eyes eyes) LOG_GENERAL ("Existing frame %1 is incomplete", f); return false; } - - string const existing_hash = md5_digest (data.data(), data.size()); - if (existing_hash != info.hash) { + + MD5Digester digester; + digester.add (data.data(), data.size()); + if (digester.get() != info.hash) { LOG_GENERAL ("Existing frame %1 failed hash check", f); return false; } diff --git a/src/lib/wscript b/src/lib/wscript index 72e149879..f932a142d 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -41,6 +41,7 @@ sources = """ kdm.cc json_server.cc log.cc + md5_digester.cc piece.cc player.cc player_video_frame.cc -- cgit v1.2.3 From 974c5553244616ba92caf70a67d42725c6224b97 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 3 Jun 2014 14:48:38 +0100 Subject: Tweak backtrace file for Windows. --- src/lib/util.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/util.cc b/src/lib/util.cc index e81165365..bbe6f77e1 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -266,8 +266,9 @@ LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *) { dbg::stack s; FILE* f = fopen_boost (backtrace_file, "w"); + fprintf (f, "Exception thrown:"); for (dbg::stack::const_iterator i = s.begin(); i != s.end(); ++i) { - fprintf (f, "%p %s %d %s", i->instruction, i->function.c_str(), i->line, i->module.c_str()); + fprintf (f, "%p %s %d %s\n", i->instruction, i->function.c_str(), i->line, i->module.c_str()); } fclose (f); return EXCEPTION_CONTINUE_SEARCH; -- cgit v1.2.3 From 82926443230084739cb673a83b2ab1f9d733a07b Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 3 Jun 2014 22:58:46 +0100 Subject: All audio content should resample if the output frame rate and content frame rates differ; make Sndfile sources use the video-frame-rate-based calculation for output frame rate (like FFmpeg sources do). Also, fix small problems when flushing Resamplers used to get fed back to Resamplers again. --- ChangeLog | 3 + src/lib/audio_content.cc | 26 +++++++++ src/lib/audio_content.h | 3 +- src/lib/content.h | 2 + src/lib/ffmpeg_content.cc | 24 -------- src/lib/ffmpeg_content.h | 1 - src/lib/player.cc | 39 +++++++------ src/lib/player.h | 2 +- src/lib/sndfile_content.cc | 9 --- src/lib/sndfile_content.h | 2 - test/audio_with_specified_video_frame_rate_test.cc | 65 ++++++++++++++++++++++ test/wscript | 1 + 12 files changed, 121 insertions(+), 56 deletions(-) create mode 100644 test/audio_with_specified_video_frame_rate_test.cc (limited to 'src/lib') diff --git a/ChangeLog b/ChangeLog index 4d066e657..a0e776b0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2014-06-03 Carl Hetherington + * Fix bad resampling of separate sound file sources that + have specified video frame rates. + * Version 1.69.20 released. 2014-06-03 Carl Hetherington diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc index dbca6652c..79912f1ae 100644 --- a/src/lib/audio_content.cc +++ b/src/lib/audio_content.cc @@ -29,6 +29,7 @@ #include "i18n.h" using std::string; +using std::cout; using std::vector; using boost::shared_ptr; using boost::dynamic_pointer_cast; @@ -148,3 +149,28 @@ AudioContent::technical_summary () const { return String::compose ("audio: channels %1, length %2, raw rate %3, out rate %4", audio_channels(), audio_length(), content_audio_frame_rate(), output_audio_frame_rate()); } + +int +AudioContent::output_audio_frame_rate () const +{ + shared_ptr film = _film.lock (); + assert (film); + + /* Resample to a DCI-approved sample rate */ + double t = dcp_audio_frame_rate (content_audio_frame_rate ()); + + FrameRateConversion frc (video_frame_rate(), film->video_frame_rate()); + + /* Compensate if the DCP is being run at a different frame rate + to the source; that is, if the video is run such that it will + look different in the DCP compared to the source (slower or faster). + skip/repeat doesn't come into effect here. + */ + + if (frc.change_speed) { + t *= video_frame_rate() * frc.factor() / film->video_frame_rate(); + } + + return rint (t); +} + diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h index d30db02d7..2a1216d86 100644 --- a/src/lib/audio_content.h +++ b/src/lib/audio_content.h @@ -54,11 +54,12 @@ public: virtual int audio_channels () const = 0; virtual AudioContent::Frame audio_length () const = 0; virtual int content_audio_frame_rate () const = 0; - virtual int output_audio_frame_rate () const = 0; virtual AudioMapping audio_mapping () const = 0; virtual void set_audio_mapping (AudioMapping) = 0; virtual boost::filesystem::path audio_analysis_path () const; + int output_audio_frame_rate () const; + boost::signals2::connection analyse_audio (boost::function); void set_audio_gain (float); diff --git a/src/lib/content.h b/src/lib/content.h index 596a0a905..3cea93cfc 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -65,6 +65,8 @@ public: virtual void as_xml (xmlpp::Node *) const; virtual Time full_length () const = 0; virtual std::string identifier () const; + /** @return the video frame rate that this content has or was prepared to be used with */ + virtual float video_frame_rate () const = 0; boost::shared_ptr clone () const; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 41a3724a2..4ea6dbc6a 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -309,30 +309,6 @@ FFmpegContent::content_audio_frame_rate () const return _audio_stream->frame_rate; } -int -FFmpegContent::output_audio_frame_rate () const -{ - shared_ptr film = _film.lock (); - assert (film); - - /* Resample to a DCI-approved sample rate */ - double t = dcp_audio_frame_rate (content_audio_frame_rate ()); - - FrameRateConversion frc (video_frame_rate(), film->video_frame_rate()); - - /* Compensate if the DCP is being run at a different frame rate - to the source; that is, if the video is run such that it will - look different in the DCP compared to the source (slower or faster). - skip/repeat doesn't come into effect here. - */ - - if (frc.change_speed) { - t *= video_frame_rate() * frc.factor() / film->video_frame_rate(); - } - - return rint (t); -} - bool operator== (FFmpegStream const & a, FFmpegStream const & b) { diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 6ab95d2fe..c15e5c10e 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -147,7 +147,6 @@ public: int audio_channels () const; AudioContent::Frame audio_length () const; int content_audio_frame_rate () const; - int output_audio_frame_rate () const; AudioMapping audio_mapping () const; void set_audio_mapping (AudioMapping); boost::filesystem::path audio_analysis_path () const; diff --git a/src/lib/player.cc b/src/lib/player.cc index b112760ef..68df8ea70 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -149,7 +149,7 @@ Player::pass () if (re) { shared_ptr b = re->flush (); if (b->frames ()) { - process_audio (earliest, b, ac->audio_length ()); + process_audio (earliest, b, ac->audio_length (), true); } } } @@ -269,8 +269,9 @@ Player::process_video (weak_ptr weak_piece, shared_ptr } } +/** @param already_resampled true if this data has already been through the chain up to the resampler */ void -Player::process_audio (weak_ptr weak_piece, shared_ptr audio, AudioContent::Frame frame) +Player::process_audio (weak_ptr weak_piece, shared_ptr audio, AudioContent::Frame frame, bool already_resampled) { shared_ptr piece = weak_piece.lock (); if (!piece) { @@ -280,19 +281,21 @@ Player::process_audio (weak_ptr weak_piece, shared_ptr content = dynamic_pointer_cast (piece->content); assert (content); - /* Gain */ - if (content->audio_gain() != 0) { - shared_ptr gain (new AudioBuffers (audio)); - gain->apply_gain (content->audio_gain ()); - audio = gain; - } - - /* Resample */ - if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) { - shared_ptr r = resampler (content, true); - pair, AudioContent::Frame> ro = r->run (audio, frame); - audio = ro.first; - frame = ro.second; + if (!already_resampled) { + /* Gain */ + if (content->audio_gain() != 0) { + shared_ptr gain (new AudioBuffers (audio)); + gain->apply_gain (content->audio_gain ()); + audio = gain; + } + + /* Resample */ + if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) { + shared_ptr r = resampler (content, true); + pair, AudioContent::Frame> ro = r->run (audio, frame); + audio = ro.first; + frame = ro.second; + } } Time const relative_time = _film->audio_frames_to_time (frame); @@ -427,7 +430,7 @@ Player::setup_pieces () shared_ptr fd (new FFmpegDecoder (_film, fc, _video, _audio)); fd->Video.connect (bind (&Player::process_video, this, weak_ptr (piece), _1, _2, _3, _4, _5, 0)); - fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr (piece), _1, _2)); + fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr (piece), _1, _2, false)); fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr (piece), _1, _2, _3, _4)); fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true); @@ -457,7 +460,7 @@ Player::setup_pieces () shared_ptr sc = dynamic_pointer_cast (*i); if (sc) { shared_ptr sd (new SndfileDecoder (_film, sc)); - sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr (piece), _1, _2)); + sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr (piece), _1, _2, false)); piece->decoder = sd; } @@ -555,7 +558,7 @@ Player::resampler (shared_ptr c, bool create) LOG_GENERAL ( "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels() ); - + shared_ptr r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels())); _resamplers[c] = r; return r; diff --git a/src/lib/player.h b/src/lib/player.h index bf6260c0a..6e70ad707 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -87,7 +87,7 @@ private: friend class Piece; void process_video (boost::weak_ptr, boost::shared_ptr, Eyes, Part, bool, VideoContent::Frame, Time); - void process_audio (boost::weak_ptr, boost::shared_ptr, AudioContent::Frame); + void process_audio (boost::weak_ptr, boost::shared_ptr, AudioContent::Frame, bool); void process_subtitle (boost::weak_ptr, boost::shared_ptr, dcpomatic::Rect, Time, Time); void setup_pieces (); void playlist_changed (); diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index fcdf88778..6f18ebbb4 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -159,15 +159,6 @@ SndfileContent::full_length () const return film->audio_frames_to_time (len); } -int -SndfileContent::output_audio_frame_rate () const -{ - shared_ptr film = _film.lock (); - assert (film); - - return film->audio_frame_rate (); -} - void SndfileContent::set_audio_mapping (AudioMapping m) { diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h index a79fb99b6..dcfdfd8d7 100644 --- a/src/lib/sndfile_content.h +++ b/src/lib/sndfile_content.h @@ -68,8 +68,6 @@ public: return _audio_frame_rate; } - int output_audio_frame_rate () const; - AudioMapping audio_mapping () const { boost::mutex::scoped_lock lm (_mutex); return _audio_mapping; diff --git a/test/audio_with_specified_video_frame_rate_test.cc b/test/audio_with_specified_video_frame_rate_test.cc new file mode 100644 index 000000000..986033205 --- /dev/null +++ b/test/audio_with_specified_video_frame_rate_test.cc @@ -0,0 +1,65 @@ +/* + Copyright (C) 2014 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 "lib/film.h" +#include "lib/dcp_content_type.h" +#include "lib/ratio.h" +#include "lib/sndfile_content.h" +#include "lib/audio_buffers.h" +#include "lib/player.h" +#include "test.h" + +using std::cout; +using boost::shared_ptr; + +static +void +process_audio (shared_ptr buffers, int* samples) +{ + cout << "weeeeeeeeee " << buffers->frames() << "\n"; + *samples += buffers->frames (); +} + +/** Test the situation where a piece of SndfileContent has its video + * frame rate specified (i.e. the rate that it was prepared for), + * and hence might need resampling. + */ +BOOST_AUTO_TEST_CASE (audio_with_specified_video_frame_rate_test) +{ + /* Make a film using staircase.wav with the DCP at 30fps and the audio specified + as being prepared for 29.97. + */ + + shared_ptr film = new_test_film ("audio_with_specified_video_frame_rate_test"); + film->set_dcp_content_type (DCPContentType::from_dci_name ("FTR")); + film->set_container (Ratio::from_id ("185")); + film->set_name ("audio_with_specified_video_frame_rate_test"); + + shared_ptr content (new SndfileContent (film, "test/data/sine_440.wav")); + content->set_video_frame_rate (29.97); + film->examine_and_add_content (content); + + wait_for_jobs (); + + film->set_video_frame_rate (30); + + BOOST_CHECK_EQUAL (content->content_audio_frame_rate(), 48000); + BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952); +} diff --git a/test/wscript b/test/wscript index 676f47104..6f1490a15 100644 --- a/test/wscript +++ b/test/wscript @@ -20,6 +20,7 @@ def build(bld): audio_delay_test.cc audio_mapping_test.cc audio_merger_test.cc + audio_with_specified_video_frame_rate_test.cc black_fill_test.cc client_server_test.cc colour_conversion_test.cc -- cgit v1.2.3