How can I read OPUS packets one by one from ogg/opus file

℡╲_俬逩灬. 提交于 2021-01-28 22:04:57

问题


I need to read OPUS packets one by one from ogg/opus file and send them further in OPUS format so without decoding. I'm looking at opusfile lib but API and examples are rather complicated and more focused on decoding the file and getting resulted PCM. Is there a way to achieve what I want with this lib and how? If not what other options do I have?


回答1:


libogg could be used to parse the Ogg Opus file's "pages", and then the opus "packets" could then be extracted from those pages. Mind that packets may span across pages, but I have personally not come across that when testing files created by opusenc. You could also parse the pages manually (see Splitting an Ogg Opus File stream)

I recommend reading the basics of the Opus File Spec (RFC 7845) to understand the file structure first. https://opus-codec.org/docs/




回答2:


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.




回答3:


I guess I am slightly late. I had very similar use case, I wanted to extract opus packets from ogg opus file. I found this answer

https://stackoverflow.com/a/26285277/10110652

Following code will help you to get opus packets (without been decoded to pcm) in 'nextPacket' byteArray inside while loop

File audioFile = null; 
    try {
        audioFile = new File("xyz.ogg"); //input ogg opus file
        oggFile = new FileStream(new RandomAccessFile(audioFile, "r"));

        for (LogicalOggStream stream : (Collection<LogicalOggStream>) oggFile.getLogicalStreams()) {
            byte[] nextPacket = stream.getNextOggPacket();
            while (nextPacket != null) {
                    //nextPacket here contains opus packet
                    //do what ever you want to do with this packet
                 
                nextPacket = stream.getNextOggPacket();
            }
        }

    } catch (EndOfOggStreamException e) {
        System.out.println("End of File");
        //file usually get over by raising this exception while execution getNextOggPacket()
    }

Same program can be used to extract vorbis encoded packets in ogg container, means ogg vorbis file.

Happy coding!!!



来源:https://stackoverflow.com/questions/64479365/how-can-i-read-opus-packets-one-by-one-from-ogg-opus-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!