diff options
author | Max Kellermann <max@musicpd.org> | 2020-07-01 21:15:59 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-07-01 21:21:06 +0200 |
commit | 7befab7e830f830ffbda43959d136c57a392a608 (patch) | |
tree | 7f3f580e9629b9c67239b4bab2bed87551a14767 /src/decoder | |
parent | 4244e61214db8d421a09be353b2374f21fc33f2d (diff) |
decoder/opus: keep track of the granulepos
Will be needed for End Trimming (RFC7845 4.4,
https://github.com/MusicPlayerDaemon/MPD/issues/867).
Diffstat (limited to 'src/decoder')
-rw-r--r-- | src/decoder/plugins/OpusDecoderPlugin.cxx | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index 34e8a9d7e..ed4ec3d01 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -98,6 +98,13 @@ class MPDOpusDecoder final : public OggDecoder { size_t frame_size; + /** + * The granulepos of the next sample to be submitted to + * DecoderClient::SubmitData(). Negative if unkown. + * Initialized by OnOggBeginning(). + */ + ogg_int64_t granulepos; + public: explicit MPDOpusDecoder(DecoderReader &reader) :OggDecoder(reader) {} @@ -114,6 +121,13 @@ public: bool Seek(uint64_t where_frame); private: + void AddGranulepos(ogg_int64_t n) noexcept { + assert(n >= 0); + + if (granulepos >= 0) + granulepos += n; + } + void HandleTags(const ogg_packet &packet); void HandleAudio(const ogg_packet &packet); @@ -154,6 +168,7 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet) !audio_valid_channel_count(channels)) throw std::runtime_error("Malformed BOS packet"); + granulepos = 0; skip = pre_skip; assert(opus_decoder == nullptr); @@ -261,12 +276,14 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet) /* apply the "skip" value */ if (skip >= (unsigned)nframes) { skip -= nframes; + AddGranulepos(nframes); return; } const opus_int16 *data = output_buffer; data += skip * previous_channels; nframes -= skip; + AddGranulepos(skip); skip = 0; /* submit decoded samples to the DecoderClient */ @@ -277,9 +294,12 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet) if (cmd != DecoderCommand::NONE) throw cmd; - if (packet.granulepos > 0) - client.SubmitTimestamp(FloatDuration(packet.granulepos - pre_skip) + if (packet.granulepos > 0) { + granulepos = packet.granulepos; + client.SubmitTimestamp(FloatDuration(granulepos - pre_skip) / opus_sample_rate); + } else + AddGranulepos(nframes); } bool @@ -291,6 +311,11 @@ MPDOpusDecoder::Seek(uint64_t where_frame) const ogg_int64_t where_granulepos(where_frame); + /* we don't know the exact granulepos after seeking, so let's + set it to -1 - it will be set after the next packet which + declares its granulepos */ + granulepos = -1; + try { SeekGranulePos(where_granulepos); |