<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><font size="2">I'm developing a library in which you can push in
        a stream of bytes to a decoder for a specific codec (right now
        I'm testing with OGG), and it will send back partial audio
        packets as it becomes available, plus a final stream of decoded
        audio once the user indicates the stream is finished. This data
        could come in at any time with any size, and I keep a buffer of
        the unprocessed data until it's consumed. </font><font size="2"><font
          size="2">I want to be able to support partial frames/streaming
          as well, so I need to have the data processing in the
          background before the finish method is called. </font>The
        library is written in Java and is interfaced with in Lua, but it
        uses a native wrapper to FFmpeg in C
        (<a class="moz-txt-link-freetext" href="https://github.com/Manevolent/ffmpeg4j">https://github.com/Manevolent/ffmpeg4j</a>). For example, here's an
        example of how a user could pipe data from a file and then wait
        for the result:</font></p>
    <pre><font size="2">local file = io.open("audio.ogg", "rb")
local bus = peripheral.wrap("back") -- gets the decoder object
repeat
    local data = <a class="moz-txt-link-freetext" href="file:read(16384)">file:read(16384)</a>
    if data == nil then break end
    bus.input(1, data) -- send 16384 bytes to the decoder in slot 1 and process it in the background
until #data < 16384
<a class="moz-txt-link-freetext" href="file:close()">file:close()</a>
bus.finish(1) -- tell the decoder that the data is finished
local event, side, slot, ok, data = coroutine.yield("asicraft.result") -- wait for processing to finish & get the result
-- do things with data
</font></pre>
    <p><font size="2">I'm currently using the Java library's wrapper
        around an `InputStream` to send the data. I have my own
        `InputStream` which holds the buffered input, and the library
        will call its `read` method through an implementation of
        libavformat `AVIOContext`'s `read_packet` function. If the
        buffer runs out, the read method returns -1, and I used some
        mixins/reflection on the Java library to make it return
        `AVERROR(EAGAIN)` to libavformat. This worked for the first
        packet sent to the stream, but despite always sending `EAGAIN` I
        was still getting EOFs simply from returning less data than the
        demuxer expected. To solve this, I forced the `eof_reached` flag
        to be reset to 0 each time data is added to the stream, but
        because a partial amount of data was read during the last
        decoding period, it ends up skipping that frame.</font></p>
    <p><font size="2">I've considered putting the audio processing on a
        separate thread, and having the `read_packet` function wait for
        more input before returning (which luckily Java makes pretty
        easy). But this would mean that I would need a new thread for
        every single input process, which theoretically could be opened
        and then left running forever, and I want to avoid ending up
        with thread exhaustion (this needs to be able to run on public
        servers where users can trigger the decoder at any time). I also
        tried throwing an exception to attempt to unwind the reader back
        across `av_frame_read`, but this failed spectacularly as I
        expected.</font></p>
    <p><font size="2">What's the most optimal way to decode/demux a data
        stream in chunks that may arrive at any time, without losing any
        frames in the process? And, more specifically for my current
        method, is there any way to figure out where in the data stream
        the last frame was read by the demuxer? If I can know that, I
        can just rewind the data stream to that point and continue the
        decoder.</font></p>
    <p><font size="2">If anyone wants to look at my current code, it's
        available at
<a class="moz-txt-link-freetext" href="https://github.com/MCJack123/ASICraft/tree/ffmpeg-decode/common/src/main/java/cc/craftospc/ASICraft/algorithms/OGGDecodeAlgorithm.java">https://github.com/MCJack123/ASICraft/tree/ffmpeg-decode/common/src/main/java/cc/craftospc/ASICraft/algorithms/OGGDecodeAlgorithm.java</a>.
        I don't expect anyone to want to poke through it, but it's there
        if someone does. There's also some related code in
        `util/FFmpegInputFixed.java` and
        `mixin/FFmpegSourceStreamInject.java` for patching a few things
        - mainly, switching it to use `EAGAIN` instead of EOF.</font></p>
    <p><font size="2">I would appreciate any help in getting this
        working, as it drives a major part of my project, and I don't
        want to have to drop it or limit the features because I can't
        get libav to cooperate with my input scheme.</font></p>
  </body>
</html>