From d7b23d44dec9d6357619e8e009e564e475215470 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 3 Jan 2014 23:18:47 +0000 Subject: Various attempted fixes to audio sync. --- src/lib/audio_decoder.cc | 29 +++++++++++++++++------------ src/lib/audio_decoder.h | 5 ++--- src/lib/decoder.cc | 9 +++++++++ src/lib/ffmpeg_decoder.cc | 20 ++++++++------------ src/lib/ffmpeg_decoder.h | 1 - src/lib/player.cc | 13 ++++--------- src/lib/sndfile_decoder.cc | 5 ++++- src/lib/sndfile_decoder.h | 5 +---- 8 files changed, 45 insertions(+), 42 deletions(-) (limited to 'src/lib') diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index adabd5d99..8d3b0e128 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -37,7 +37,6 @@ using boost::shared_ptr; AudioDecoder::AudioDecoder (shared_ptr film, shared_ptr content) : Decoder (film) , _audio_content (content) - , _audio_position (0) { if (content->output_audio_frame_rate() != content->content_audio_frame_rate() && content->audio_channels ()) { _resampler.reset (new Resampler (content->content_audio_frame_rate(), content->output_audio_frame_rate(), content->audio_channels ())); @@ -47,16 +46,26 @@ AudioDecoder::AudioDecoder (shared_ptr film, shared_ptr data) +AudioDecoder::audio (shared_ptr data, ContentTime time) { if (_resampler) { data = _resampler->run (data); } - _pending.push_back (shared_ptr (new DecodedAudio (data, _audio_position))); - _audio_position += data->frames (); + if (!_audio_position) { + shared_ptr film = _film.lock (); + assert (film); + FrameRateChange frc = film->active_frame_rate_change (_audio_content->position ()); + _audio_position = (double (time) / frc.speed_up) * film->audio_frame_rate() / TIME_HZ; + } + + _pending.push_back (shared_ptr (new DecodedAudio (data, _audio_position.get ()))); + _audio_position = _audio_position.get() + data->frames (); } void @@ -68,17 +77,13 @@ AudioDecoder::flush () shared_ptr b = _resampler->flush (); if (b) { - _pending.push_back (shared_ptr (new DecodedAudio (b, _audio_position))); - _audio_position += b->frames (); + _pending.push_back (shared_ptr (new DecodedAudio (b, _audio_position.get ()))); + _audio_position = _audio_position.get() + b->frames (); } } void -AudioDecoder::seek (ContentTime t, bool) +AudioDecoder::seek (ContentTime, bool) { - shared_ptr film = _film.lock (); - assert (film); - - FrameRateChange frc = film->active_frame_rate_change (_audio_content->position ()); - _audio_position = ((t + first_audio()) / frc.speed_up) * film->audio_frame_rate() / TIME_HZ; + _audio_position.reset (); } diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 12f8505f6..bb3aafccd 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -48,13 +48,12 @@ public: protected: - virtual ContentTime first_audio () const = 0; - void audio (boost::shared_ptr); + void audio (boost::shared_ptr, ContentTime); void flush (); boost::shared_ptr _audio_content; boost::shared_ptr _resampler; - AudioFrame _audio_position; + boost::optional _audio_position; }; #endif diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 30244b40b..53a0c31e1 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -40,6 +40,14 @@ Decoder::Decoder (shared_ptr f) } +struct DecodedSorter +{ + bool operator() (shared_ptr a, shared_ptr b) + { + return a->dcp_time < b->dcp_time; + } +}; + shared_ptr Decoder::peek () { @@ -51,6 +59,7 @@ Decoder::peek () return shared_ptr (); } + _pending.sort (DecodedSorter ()); return _pending.front (); } diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 25fe655be..dae0ddbe8 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -445,11 +445,17 @@ FFmpegDecoder::decode_audio_packet () } if (frame_finished) { + ContentTime const ct = ( + av_frame_get_best_effort_timestamp (_frame) * + av_q2d (_ffmpeg_content->audio_stream()->stream (_format_context)->time_base) + + _pts_offset + ) * TIME_HZ; + int const data_size = av_samples_get_buffer_size ( 0, audio_codec_context()->channels, _frame->nb_samples, audio_sample_format (), 1 ); - - audio (deinterleave_audio (_frame->data, data_size)); + + audio (deinterleave_audio (_frame->data, data_size), ct); } copy_packet.data += decode_result; @@ -603,13 +609,3 @@ FFmpegDecoder::decode_subtitle_packet () avsubtitle_free (&sub); } - -ContentTime -FFmpegDecoder::first_audio () const -{ - if (!_ffmpeg_content->audio_stream ()) { - return 0; - } - - return _ffmpeg_content->audio_stream()->first_audio.get_value_or(0) + _pts_offset; -} diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 680e39c39..ee725b20c 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -58,7 +58,6 @@ private: bool pass (); void flush (); - ContentTime first_audio () const; void setup_subtitle (); diff --git a/src/lib/player.cc b/src/lib/player.cc index eb7b177ec..3db2fe6c9 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -172,11 +172,6 @@ Player::pass () /* Will be set to false if we shouldn't consume the peeked DecodedThing */ bool consume = true; - /* This is the margin either side of _{video,audio}_position that we will accept - as a starting point for a frame consecutive to the previous. - */ - DCPTime const margin = TIME_HZ / (2 * _film->video_frame_rate ()); - if (dv && _video) { if (_just_did_inaccurate_seek) { @@ -185,7 +180,7 @@ Player::pass () emit_video (earliest_piece, dv); step_video_position (dv); - } else if (dv->dcp_time - _video_position > margin) { + } else if (dv->dcp_time > _video_position) { /* Too far ahead */ @@ -208,7 +203,7 @@ Player::pass () consume = false; - } else if (abs (dv->dcp_time - _video_position) < margin) { + } else if (dv->dcp_time == _video_position) { /* We're ok */ emit_video (earliest_piece, dv); step_video_position (dv); @@ -222,12 +217,12 @@ Player::pass () } else if (da && _audio) { - if (da->dcp_time - _audio_position > margin) { + if (da->dcp_time > _audio_position) { /* Too far ahead */ emit_silence (da->dcp_time - _audio_position); consume = false; _statistics.audio.silence += (da->dcp_time - _audio_position); - } else if (abs (da->dcp_time - _audio_position) < margin) { + } else if (da->dcp_time == _audio_position) { /* We're ok */ emit_audio (earliest_piece, da); _statistics.audio.good += da->data->frames(); diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 1c651e614..d6537843e 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -45,6 +45,7 @@ SndfileDecoder::SndfileDecoder (shared_ptr f, shared_ptrset_frames (this_time); - audio (data); + audio (data, _done * TIME_HZ / audio_frame_rate ()); + _done += this_time; _remaining -= this_time; return _remaining == 0; @@ -123,5 +125,6 @@ SndfileDecoder::seek (ContentTime t, bool accurate) Decoder::seek (t, accurate); AudioDecoder::seek (t, accurate); + _done = t * audio_frame_rate() / TIME_HZ; _remaining = _info.frames - _done; } diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index 4ecea0846..46d9c5e5c 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -36,15 +36,12 @@ public: int audio_frame_rate () const; private: - ContentTime first_audio () const { - return 0; - } - bool pass (); boost::shared_ptr _sndfile_content; SNDFILE* _sndfile; SF_INFO _info; + AudioFrame _done; AudioFrame _remaining; float* _deinterleave_buffer; }; -- cgit v1.2.3