summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2018-12-31 03:04:31 -0600
committerWilliam Wilgus <me.theuser@yahoo.com>2019-01-04 06:56:52 +0100
commit100f4338deea5239423a0b8974784939d520385c (patch)
tree95d63e56710b031fca6a8f26500cc2cacd964378 /lib
parent976831e6674db98cc7992db1479afff9d2877c81 (diff)
downloadrockbox-100f4338deea5239423a0b8974784939d520385c.tar.gz
rockbox-100f4338deea5239423a0b8974784939d520385c.zip
Fix Opus FS#13133 - Files with embedded artwork 45.8KiB+ skip near beginning
ogg_sync_reset() causes issues on the partial page boundary due to the next page (already in buffer) being discarded instead seek next page boundary past complete page Change-Id: Ic05f188f489b015693d663f131e09cd92ad37ff7
Diffstat (limited to 'lib')
-rw-r--r--lib/rbcodec/codecs/opus.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/lib/rbcodec/codecs/opus.c b/lib/rbcodec/codecs/opus.c
index 1ce7f19dfd..6574d6c052 100644
--- a/lib/rbcodec/codecs/opus.c
+++ b/lib/rbcodec/codecs/opus.c
@@ -57,6 +57,27 @@ static int get_more_data(ogg_sync_state *oy)
return bytes;
}
+
+/* seek to ogg page after given file position */
+static int seek_ogg_page(int64_t filepos)
+{
+ const char synccode[] = "OggS\0"; /* Note: there are two nulls here */
+ char buf[sizeof(synccode)];
+ ci->seek_buffer(filepos);
+ while (ci->read_filebuf(buf, 1) == 1) {
+ if (buf[0] == synccode[0]) {
+ if (ci->read_filebuf(&buf[1], sizeof(buf) - 1) != sizeof(buf) - 1)
+ break;
+ if (memcmp(buf, synccode, sizeof(buf)) == 0) {
+ ci->seek_buffer(ci->curpos - sizeof(buf));
+ LOGF("next page %ld", ci->curpos);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
/* The read/seek functions track absolute position within the stream */
static int64_t get_next_page(ogg_sync_state *oy, ogg_page *og,
int64_t boundary)
@@ -408,8 +429,12 @@ enum codec_status codec_run(void)
/* Do this to avoid allocating space for huge comment packets
(embedded Album Art) */
- if(os.packetno == 1 && ogg_stream_packetpeek(&os, &op) != 1){
- ogg_sync_reset(&oy);
+ if (os.packetno == 1 && ogg_stream_packetpeek(&os, NULL) == 0){
+ LOGF("sync reset");
+ /* seek buffer directly to the first audio packet */
+ seek_ogg_page(ci->curpos - oy.returned);
+ ogg_sync_reset(&oy);
+ break;
}
while ((ogg_stream_packetout(&os, &op) == 1) && !op.e_o_s) {