diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/decoder/OggFind.cxx | 38 | ||||
-rw-r--r-- | src/decoder/OggFind.hxx | 40 | ||||
-rw-r--r-- | src/decoder/OpusDecoderPlugin.cxx | 22 |
4 files changed, 101 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 351978440..469aa129f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -531,6 +531,7 @@ if HAVE_OPUS libdecoder_plugins_a_SOURCES += \ src/decoder/OggUtil.cxx \ src/decoder/OggUtil.hxx \ + src/decoder/OggFind.cxx src/decoder/OggFind.hxx \ src/decoder/OpusReader.hxx \ src/decoder/OpusHead.hxx \ src/decoder/OpusHead.cxx \ diff --git a/src/decoder/OggFind.cxx b/src/decoder/OggFind.cxx new file mode 100644 index 000000000..4f4fd1e96 --- /dev/null +++ b/src/decoder/OggFind.cxx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "OggFind.hxx" +#include "OggUtil.hxx" + +bool +OggFindEOS(ogg_sync_state &oy, ogg_stream_state &os, ogg_packet &packet, + decoder *decoder, input_stream *is) +{ + while (true) { + int r = ogg_stream_packetout(&os, &packet); + if (r == 0) { + if (!OggExpectPageIn(oy, os, decoder, is)) + return false; + + continue; + } else if (r > 0 && packet.e_o_s) + return true; + } +} diff --git a/src/decoder/OggFind.hxx b/src/decoder/OggFind.hxx new file mode 100644 index 000000000..6a55f9b34 --- /dev/null +++ b/src/decoder/OggFind.hxx @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OGG_FIND_HXX +#define MPD_OGG_FIND_HXX + +#include "check.h" + +#include <ogg/ogg.h> + +struct decoder; +struct input_stream; + +/** + * Skip all pages/packets until an end-of-stream (EOS) packet for the + * specified stream is found. + * + * @return true if the EOS packet was found + */ +bool +OggFindEOS(ogg_sync_state &oy, ogg_stream_state &os, ogg_packet &packet, + decoder *decoder, input_stream *is); + +#endif diff --git a/src/decoder/OpusDecoderPlugin.cxx b/src/decoder/OpusDecoderPlugin.cxx index c4d6c2d12..9c2f86d05 100644 --- a/src/decoder/OpusDecoderPlugin.cxx +++ b/src/decoder/OpusDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "OpusHead.hxx" #include "OpusTags.hxx" #include "OggUtil.hxx" +#include "OggFind.hxx" #include "decoder_api.h" #include "OggCodec.hxx" #include "audio_check.h" @@ -291,6 +292,23 @@ mpd_opus_stream_decode(struct decoder *decoder, } static bool +SeekFindEOS(ogg_sync_state &oy, ogg_stream_state &os, ogg_packet &packet, + decoder *decoder, input_stream *is) +{ + if (is->size > 0 && is->size - is->offset < 65536) + return OggFindEOS(oy, os, packet, decoder, is); + + if (!input_stream_cheap_seeking(is)) + return false; + + ogg_sync_reset(&oy); + + return input_stream_lock_seek(is, -65536, SEEK_END, nullptr) && + OggExpectPageSeekIn(oy, os, decoder, is) && + OggFindEOS(oy, os, packet, decoder, is); +} + +static bool mpd_opus_scan_stream(struct input_stream *is, const struct tag_handler *handler, void *handler_ctx) { @@ -351,6 +369,10 @@ mpd_opus_scan_stream(struct input_stream *is, } } + if (packet.e_o_s || SeekFindEOS(oy, os, packet, nullptr, is)) + tag_handler_invoke_duration(handler, handler_ctx, + packet.granulepos / opus_sample_rate); + ogg_stream_clear(&os); ogg_sync_clear(&oy); |