diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-01-03 23:18:47 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-01-03 23:18:47 +0000 |
| commit | d7b23d44dec9d6357619e8e009e564e475215470 (patch) | |
| tree | 0ac5251fbbe5c55da24499eb5c7b4194f90365bf /src | |
| parent | f0e95aa5b7ada81a1c40f06facab2e94e45ab26c (diff) | |
Various attempted fixes to audio sync.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/audio_decoder.cc | 29 | ||||
| -rw-r--r-- | src/lib/audio_decoder.h | 5 | ||||
| -rw-r--r-- | src/lib/decoder.cc | 9 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 20 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.h | 1 | ||||
| -rw-r--r-- | src/lib/player.cc | 13 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.cc | 5 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.h | 5 |
8 files changed, 45 insertions, 42 deletions
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<const Film> film, shared_ptr<const AudioContent> 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<const Film> film, shared_ptr<const AudioC /** Audio timestamping is made hard by many factors, but the final nail in the coffin is resampling. * We have to assume that we are feeding continuous data into the resampler, and so we get continuous * data out. Hence we do the timestamping here, post-resampler, just by counting samples. + * + * The time is passed in here so that after a seek we can set up our _audio_position. The + * time is ignored once this has been done. */ void -AudioDecoder::audio (shared_ptr<const AudioBuffers> data) +AudioDecoder::audio (shared_ptr<const AudioBuffers> data, ContentTime time) { if (_resampler) { data = _resampler->run (data); } - _pending.push_back (shared_ptr<DecodedAudio> (new DecodedAudio (data, _audio_position))); - _audio_position += data->frames (); + if (!_audio_position) { + shared_ptr<const Film> 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<DecodedAudio> (new DecodedAudio (data, _audio_position.get ()))); + _audio_position = _audio_position.get() + data->frames (); } void @@ -68,17 +77,13 @@ AudioDecoder::flush () shared_ptr<const AudioBuffers> b = _resampler->flush (); if (b) { - _pending.push_back (shared_ptr<DecodedAudio> (new DecodedAudio (b, _audio_position))); - _audio_position += b->frames (); + _pending.push_back (shared_ptr<DecodedAudio> (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<const Film> 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<const AudioBuffers>); + void audio (boost::shared_ptr<const AudioBuffers>, ContentTime); void flush (); boost::shared_ptr<const AudioContent> _audio_content; boost::shared_ptr<Resampler> _resampler; - AudioFrame _audio_position; + boost::optional<AudioFrame> _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<const Film> f) } +struct DecodedSorter +{ + bool operator() (shared_ptr<Decoded> a, shared_ptr<Decoded> b) + { + return a->dcp_time < b->dcp_time; + } +}; + shared_ptr<Decoded> Decoder::peek () { @@ -51,6 +59,7 @@ Decoder::peek () return shared_ptr<Decoded> (); } + _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<const Film> f, shared_ptr<const Sndfi throw DecodeError (_("could not open audio file for reading")); } + _done = 0; _remaining = _info.frames; } @@ -93,7 +94,8 @@ SndfileDecoder::pass () } data->set_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<const SndfileContent> _sndfile_content; SNDFILE* _sndfile; SF_INFO _info; + AudioFrame _done; AudioFrame _remaining; float* _deinterleave_buffer; }; |
