You can use libogg to get access to the Opus packets. It's not all that much simpler than opusfile unfortunately. In C-ish pseudocode, the general flow is:
readPage(ogg_sync_state* syncState, ogg_page* page, file) {
while ((ogg_sync_pageout(syncState, page) != 1) && file is good) {
buffer = ogg_sync_buffer(syncState, yourMaxReadSize);
bytesActuallyRead = read(file, buffer, yourMaxReadSize);
ogg_sync_wrote(syncState, bytesActuallyReadFromFile); //tell the syncState how many bytes were actually read
} //now we have a page, or the file is done
}
read() {
ogg_sync_state oggSyncState;
ogg_stream_state oggStreamState;
ogg_page oggPage;
ogg_packet oggPacket;
open file;
while (file is good) {
readPage(&oggSyncState, &oggPage);
if (ogg_page_bos(&oggPage)) {
sn = ogg_page_serialno(&oggPage); //you can remember this serial number and check it on every page for robustness
ogg_stream_init(&oggStreamState, sn);
}
ogg_stream_pagein(&oggStreamState, &oggPage);
while (ogg_stream_packetout(&oggStreamState, &oggPacket) != 0) {
//check if it's a header packet, skip if so.
//See https://tools.ietf.org/html/rfc7845.html#section-5 to see how to identify a header packet
//Else it must be data
do something with the buffer oggPacket.packet with size oggPacket.bytes
}
readPage(&oggSyncState, &oggPage, file);
ogg_stream_pagein(&oggStreamState, &oggPage_);
}
}
readPage pulls a bunch of bytes (yourMaxReadSize) from the file into the oggSyncState structure, and then extracts pages one by one. In read, packets are extracted from the pages one by one.